pax_global_header00006660000000000000000000000064134372467350014530gustar00rootroot0000000000000052 comment=3420e23febf0eb38c1b05af3c157d614d8476557 CGNS-3.4.0/000077500000000000000000000000001343724673500122665ustar00rootroot00000000000000CGNS-3.4.0/.gitattributes000066400000000000000000000000161343724673500151560ustar00rootroot00000000000000*.docx binary CGNS-3.4.0/.gitignore000066400000000000000000000010301343724673500142500ustar00rootroot00000000000000# Compiled source # ################### # Object files *.o *.ko *.obj *.elf # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex # Debug files *.dSYM/ *.su # Fortran files *.mod *.MOD # Editor generated files *~ *# **/*~ **/*.bak **/*.sw[abcdefghijklmnop] #CGNS test files *.cgns #cmake CMakeCache.txt CMakeFiles CMakeScripts Makefile cmake_install.cmake install_manifest.txt CTestTestfile.cmake CGNS-3.4.0/.travis.yml000066400000000000000000000016121343724673500143770ustar00rootroot00000000000000osx_image: xcode8.1 language: C sudo: required #dist: trusty # whitelist branches: only: - develop notifications: email: false before_install: - | if [ "$(uname)" = "Linux" ]; then sudo apt-get update -qq; sudo apt-get install -qq gfortran; fi - test $(uname) = "Darwin" && brew update || true - test $(uname) = "Darwin" && brew tap homebrew/versions || true - test $(uname) = "Darwin" && brew install gcc@6 || true - test $(uname) = "Darwin" && brew link --overwrite gcc@6 || true matrix: include: - os: linux compiler: gcc-4.9 install: export CC="gcc" export FC="gfortran" export F77="gfortran" - os: osx compiler: gcc install: export CC="gcc" export FC="gfortran-6" export F77="gfortran-6" before_script: - ./bin/install-hdf.sh - ./bin/config-cgns.sh script: - ./bin/build-cgns.sh CGNS-3.4.0/CMakeLists.txt000066400000000000000000000337261343724673500150410ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) if (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) cmake_policy(SET CMP0015 OLD) endif (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) endif(COMMAND cmake_policy) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "one of: Release, Debug, RelWithDebInfo or MinSizeRel") if (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release;Debug;RelWithDebInfo;MinSizeRel") endif (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) project("cgns" C) set(CGNS_VERSION "3.4") # Allow for building a package set(CPACK_PACKAGE_VERSION "${CGNS_VERSION}-develop") set(CPACK_PACKAGE_INSTALL_DIRECTORY "cgns-${CGNS_VERSION}") set(CPACK_GENERATOR "STGZ;TGZ;ZIP") set(CPACK_SOURCE_GENERATOR "STGZ;TGZ;ZIP") include(CPack) CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") # if this is cygwin, turn off win32 flag if (CYGWIN) set(WIN32 "NO") endif (CYGWIN) ############## # build mode # ############## # get some type sizes include(CheckTypeSize) CHECK_TYPE_SIZE(long SIZE_OF_LONG) CHECK_TYPE_SIZE(off_t SIZE_OF_OFF_T) if ("${SIZE_OF_OFF_T}" LESS 8) option(CGNS_ENABLE_LFS "Enable or disable large file support" "OFF") endif ("${SIZE_OF_OFF_T}" LESS 8) if ("${CMAKE_SIZEOF_VOID_P}" GREATER 4) option(CGNS_ENABLE_64BIT "Enable or disable 64-bit code building" "OFF") else ("${CMAKE_SIZEOF_VOID_P}" GREATER 4) set(CGNS_ENABLE_64BIT "OFF") endif ("${CMAKE_SIZEOF_VOID_P}" GREATER 4) option(CGNS_ENABLE_LEGACY "Enable or disable building legacy code (3.0 compatible)" "OFF") option(CGNS_ENABLE_SCOPING "Enable or disable scoping of enumeration values" "OFF") option(CGNS_ENABLE_BASE_SCOPE "Enable or disable base scoped families or connectivities" "OFF") option(CGNS_ENABLE_MEM_DEBUG "Enable or disable memory debugging" "OFF") if (CGNS_ENABLE_LEGACY) set(CGNS_ENABLE_64BIT "OFF") mark_as_advanced(FORCE CGNS_ENABLE_64BIT) else (CGNS_ENABLE_LEGACY) mark_as_advanced(CLEAR CGNS_ENABLE_64BIT) endif (CGNS_ENABLE_LEGACY) if (CGNS_ENABLE_64BIT) set(CGNS_ENABLE_LEGACY "OFF") mark_as_advanced(FORCE CGNS_ENABLE_LEGACY) else (CGNS_ENABLE_64BIT) mark_as_advanced(CLEAR CGNS_ENABLE_LEGACY) endif (CGNS_ENABLE_64BIT) if (CGNS_ENABLE_LFS) include(CheckSymbolExists) if (WIN32) # Windows does not have an _open64 function set(HAVE_OPEN64 0) check_symbol_exists(_lseeki64 "io.h" HAVE_LSEEK64) else (WIN32) check_symbol_exists(open64 "sys/types.h;sys/stat.h;unistd.h" HAVE_OPEN64) check_symbol_exists(lseek64 "sys/types.h;unistd.h" HAVE_LSEEK64) endif (WIN32) if (HAVE_OPEN64) add_definitions(-DHAVE_OPEN64) endif (HAVE_OPEN64) if (HAVE_LSEEK64) add_definitions(-DHAVE_LSEEK64) endif (HAVE_LSEEK64) else (CGNS_ENABLE_LFS) remove_definitions(-DHAVE_OPEN64 -DHAVE_LSEEK64) endif (CGNS_ENABLE_LFS) option(CGNS_ENABLE_TESTS "Enable test programs" "OFF") if (CGNS_ENABLE_TESTS) enable_testing() endif (CGNS_ENABLE_TESTS) ########### # Fortran # ########### # Allow fortran support to be toggled option(CGNS_ENABLE_FORTRAN "Enable or disable the use of Fortran" "OFF") if (NOT DEFINED FORTRAN_NAMING) set(FORTRAN_NAMING "UNKNOWN") endif (NOT DEFINED FORTRAN_NAMING) # If we are using fortran, enable it and configure the C-Fortran interface # It would be nice to automatically detect this setting if(CGNS_ENABLE_FORTRAN) enable_language("Fortran" OPTIONAL) #----------------------------------------------------------------------------- # Detect name mangling convention used between Fortran and C #----------------------------------------------------------------------------- set(F2CLIST "LOWERCASE" "LOWERCASE_" "LOWERCASE__" "UPPERCASE" "UPPERCASE_" "UPPERCASE__") set(FORTRAN_NAMING_HELP "Configures how to link the Fortran components into the C library. Options are: LOWERCASE LOWERCASE_ LOWERCASE__ UPPERCASE UPPERRCASE_ UPPERRCASE__ LOWERCASE_ is known to work with gfortran. If this setting does not work with your compiler, try the others until one does. ") include(FortranCInterface) set(FortranCInterface_GLOBAL_SYMBOLS mysub mysub_ mysub__ MYSUB MYSUB_ MYSUB__) FortranCInterface_HEADER(${CMAKE_BINARY_DIR}/FCMangle.h MACRO_NAMESPACE "CGNS_FC_" SYMBOL_NAMESPACE "CGNS_FC_") file (STRINGS ${CMAKE_BINARY_DIR}/FCMangle.h CONTENTS REGEX "CGNS_FC_GLOBAL\\(.*,.*\\) +(.*)") string (REGEX MATCH "CGNS_FC_GLOBAL\\(.*,.*\\) +(.*)" RESULT ${CONTENTS}) set (CGNS_FC_FUNC "${CMAKE_MATCH_1}") file(REMOVE ${CMAKE_BINARY_DIR}/FCMangle.h) if(CGNS_FC_FUNC MATCHES "^NAME(.*)") set (FORTRAN_NAMING "UPPERCASE") elseif(CGNS_FC_FUNC MATCHES "^name(.*)") set (FORTRAN_NAMING "LOWERCASE") endif() if(CGNS_FC_FUNC MATCHES "(.*)__$") set (FORTRAN_NAMING "${FORTRAN_NAMING}__") elseif(CGNS_FC_FUNC MATCHES "(.*)_$") set (FORTRAN_NAMING "${FORTRAN_NAMING}_") endif() message(STATUS "Fortran name mangling convention: ${FORTRAN_NAMING}") # check that FORTRAN_NAMING is valid if (FORTRAN_NAMING STREQUAL "UNKNOWN") if (WIN32) set(FORTRAN_NAMING "UPPERCASE" CACHE STRING ${FORTRAN_NAMING_HELP}) else (WIN32) set(FORTRAN_NAMING "LOWERCASE_" CACHE STRING ${FORTRAN_NAMING_HELP}) endif (WIN32) if (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) set_property(CACHE FORTRAN_NAMING PROPERTY STRINGS ${F2CLIST}) endif (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 7) else (FORTRAN_NAMING STREQUAL "UNKNOWN") list(FIND F2CLIST "${FORTRAN_NAMING}" ListIndex) if (ListIndex LESS 0) message(SEND_ERROR "invalid FORTRAN_NAMING value. Must be empty or one of: LOWERCASE LOWERCASE_ LOWERCASE__ UPPERCASE UPPERRCASE_ UPPERRCASE__") endif (ListIndex LESS 0) endif (FORTRAN_NAMING STREQUAL "UNKNOWN") endif (CGNS_ENABLE_FORTRAN) # this forces cmake to set up the required Fortran variables if (CGNS_ENABLE_FORTRAN AND HAS_FORTRAN) enable_language("Fortran") endif (CGNS_ENABLE_FORTRAN AND HAS_FORTRAN) ######## # HDF5 # ######## option(CGNS_ENABLE_HDF5 "Enable or disable HDF5 interface" "OFF") if (CGNS_ENABLE_HDF5) if (CGNS_BUILD_SHARED) set (FIND_HDF_COMPONENTS C shared) else (CGNS_BUILD_SHARED) set (FIND_HDF_COMPONENTS C static) endif (CGNS_BUILD_SHARED) message (STATUS "HDF5 find comps: ${FIND_HDF_COMPONENTS}") #set (SEARCH_PACKAGE_NAME ${HDF5_PACKAGE_NAME}) set (SEARCH_PACKAGE_NAME "hdf5") find_package (HDF5 NAMES ${SEARCH_PACKAGE_NAME} COMPONENTS ${FIND_HDF_COMPONENTS}) message (STATUS "HDF5 C libs:${HDF5_FOUND} static:${HDF5_static_C_FOUND} and shared:${HDF5_shared_C_FOUND}") if (HDF5_FOUND) add_executable (h5dump IMPORTED) if (NOT HDF5_static_C_FOUND AND NOT HDF5_shared_C_FOUND) set (FIND_HDF_COMPONENTS C) find_package (HDF5 NAMES ${SEARCH_PACKAGE_NAME} COMPONENTS ${FIND_HDF_COMPONENTS}) message (STATUS "HDF5 libs:${HDF5_FOUND} C:${HDF5_C_FOUND}") set (LINK_LIBS ${LINK_LIBS} ${HDF5_LIBRARIES}) if (HDF5_BUILD_SHARED_LIBS) add_definitions (-DH5_BUILT_AS_DYNAMIC_LIB) else (HDF5_BUILD_SHARED_LIBS) add_definitions (-DH5_BUILT_AS_STATIC_LIB) endif (HDF5_BUILD_SHARED_LIBS) if (BUILD_SHARED_LIBS AND WIN32) set_property (TARGET h5dump PROPERTY IMPORTED_LOCATION "${HDF5_TOOLS_DIR}/h5dumpdll") else (BUILD_SHARED_LIBS AND WIN32) set_property (TARGET h5dump PROPERTY IMPORTED_LOCATION "${HDF5_TOOLS_DIR}/h5dump") endif (BUILD_SHARED_LIBS AND WIN32) else (NOT HDF5_static_C_FOUND AND NOT HDF5_shared_C_FOUND) if (BUILD_SHARED_LIBS AND HDF5_shared_C_FOUND) set (LINK_LIBS ${LINK_LIBS} ${HDF5_C_SHARED_LIBRARY}) else (HDF5_static_C_FOUND) set (LINK_LIBS ${LINK_LIBS} ${HDF5_C_STATIC_LIBRARY}) endif (BUILD_SHARED_LIBS AND HDF5_shared_C_FOUND) set_property (TARGET h5dump PROPERTY IMPORTED_LOCATION "${HDF5_TOOLS_DIR}/h5dump") endif (NOT HDF5_static_C_FOUND AND NOT HDF5_shared_C_FOUND) set (HDF5_DUMP_EXECUTABLE $) set (HDF5_HAVE_H5PUBCONF_H 1) set (HDF5_HAVE_HDF5 1) set (HDF5_HDF5_HEADER "h5pubconf.h") set (HDF5_INCLUDE_DIR_GEN ${HDF5_INCLUDE_DIR}) message (STATUS "HDF5-${HDF5_VERSION_STRING} found: INC=${HDF5_INCLUDE_DIR} TOOLS=${HDF5_TOOLS_DIR}") else (HDF5_FOUND) find_package (HDF5) # Legacy find #Legacy find_package does not set HDF5_TOOLS_DIR, so we set it here set(HDF5_TOOLS_DIR ${HDF5_LIBRARY_DIRS}/../bin) #Legacy find_package does not set HDF5_BUILD_SHARED_LIBS, so we set it here if (CGNS_BUILD_SHARED AND EXISTS "${HDF5_LIBRARY_DIRS}/libhdf5${CMAKE_SHARED_LIBRARY_SUFFIX}") set (HDF5_BUILD_SHARED_LIBS 1) add_definitions (-DH5_BUILT_AS_DYNAMIC_LIB) else () set (HDF5_BUILD_SHARED_LIBS 0) add_definitions (-DH5_BUILT_AS_STATIC_LIB) endif () set (LINK_LIBS ${LINK_LIBS} ${HDF5_LIBRARIES}) add_executable (h5dump IMPORTED) set_property (TARGET h5dump PROPERTY IMPORTED_LOCATION "${HDF5_TOOLS_DIR}/h5dump") set (HDF5_DUMP_EXECUTABLE $) endif (HDF5_FOUND) set (HDF5_PACKAGE_NAME ${SEARCH_PACKAGE_NAME}) if (HDF5_FOUND) set (HDF5_HAVE_H5PUBCONF_H 1) set (HDF5_HAVE_HDF5 1) set (HDF5_HDF5_HEADER "h5pubconf.h") set (HDF5_INCLUDE_DIR_GEN ${HDF5_INCLUDE_DIR}) message (STATUS "HDF5-${HDF5_VERSION_STRING} found: INC=${HDF5_INCLUDE_DIR} TOOLS=${HDF5_TOOLS_DIR} HDF5_BUILD_SHARED_LIBS=${HDF5_BUILD_SHARED_LIBS}") INCLUDE_DIRECTORIES (${HDF5_INCLUDE_DIR}) set (HDF5_LIBRARY ${LINK_LIBS}) message (STATUS "HDF5 link libs: ${LINK_LIBS}") else (HDF5_FOUND) message (FATAL_ERROR " HDF5 was specified but was not found") endif (HDF5_FOUND) set(HDF5_NEED_ZLIB "OFF" CACHE BOOL "Does the HDF5 library require linking to zlib?") if(HDF5_NEED_ZLIB) find_library(ZLIB_LIBRARY z) mark_as_advanced(CLEAR ZLIB_LIBRARY) else (HDF5_NEED_ZLIB) mark_as_advanced(FORCE ZLIB_LIBRARY) endif(HDF5_NEED_ZLIB) set(HDF5_NEED_SZIP "OFF" CACHE BOOL "Does the HDF5 library require linking to zlib?") if (HDF5_NEED_SZIP) find_library(SZIP_LIBRARY szip) mark_as_advanced(CLEAR SZIP_LIBRARY) else (HDF5_NEED_SZIP) mark_as_advanced(FORCE SZIP_LIBRARY) endif (HDF5_NEED_SZIP) # Check if HDF5 version is 1.8 or greater if (HDF5_VERSION VERSION_LESS "1.8.0") message (FATAL_ERROR "HDF5 version must be greater than 1.8.0") endif (HDF5_VERSION VERSION_LESS "1.8.0") set(HDF5_NEED_MPI "OFF" CACHE BOOL "Does the HDF5 library require linking to mpi? (Only true if using parallel HDF5)") set(MPI_INC) set(MPI_LIBS) if (HDF5_NEED_MPI) if (NOT MPI_FOUND) include(FindMPI) endif (NOT MPI_FOUND) # MPI variable names changed with cmake 2.8.5 if (DEFINED MPI_C_COMPILER) mark_as_advanced(CLEAR MPI_C_COMPILER MPI_C_INCLUDE_PATH MPI_C_LIBRARIES) mark_as_advanced(FORCE MPI_LIBRARY MPI_EXTRA_LIBRARY) set(MPI_INC ${MPI_C_INCLUDE_PATH}) set(MPI_LIBS ${MPI_C_LIBRARIES}) else (DEFINED MPI_C_COMPILER) mark_as_advanced(CLEAR MPI_COMPILER MPI_INCLUDE_PATH MPI_LIBRARY MPI_EXTRA_LIBRARY) set(MPI_INC ${MPI_INCLUDE_PATH}) if (MPI_EXTRA_LIBRARY) set(MPI_LIBS ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY}) else (MPI_EXTRA_LIBRARY) set(MPI_LIBS ${MPI_LIBRARY}) endif (MPI_EXTRA_LIBRARY) endif (DEFINED MPI_C_COMPILER) mark_as_advanced(CLEAR MPIEXEC) else (HDF5_NEED_MPI) mark_as_advanced(FORCE MPI_C_COMPILER MPI_C_INCLUDE_PATH MPI_C_LIBRARIES) mark_as_advanced(FORCE MPI_COMPILER MPI_INCLUDE_PATH MPI_LIBRARY MPI_EXTRA_LIBRARY MPIEXEC) endif (HDF5_NEED_MPI) mark_as_advanced(CLEAR HDF5_NEED_ZLIB HDF5_NEED_SZIP HDF5_NEED_MPI) else (CGNS_ENABLE_HDF5) mark_as_advanced(FORCE HDF5_NEED_ZLIB HDF5_NEED_SZIP HDF5_NEED_MPI) mark_as_advanced(FORCE ZLIB_LIBRARY SZIP_LIBRARY) mark_as_advanced(FORCE MPI_C_COMPILER MPI_C_INCLUDE_PATH MPI_C_LIBRARIES) mark_as_advanced(FORCE MPI_COMPILER MPI_INCLUDE_PATH MPI_LIBRARY MPI_EXTRA_LIBRARY MPIEXEC) endif (CGNS_ENABLE_HDF5) ################# # parallel cgns # ################# if (CGNS_ENABLE_HDF5 AND HDF5_NEED_MPI) set(CGNS_ENABLE_PARALLEL "OFF" CACHE BOOL "Enable or disable parallel interface ?") mark_as_advanced(CLEAR CGNS_ENABLE_PARALLEL) # Check that HDF5 has parallel support if (NOT (HDF5_IS_PARALLEL OR HDF5_ENABLE_PARALLEL)) message(FATAL_ERROR "HDF5 has been found, but is missing parallel support.") endif() else (CGNS_ENABLE_HDF5 AND HDF5_NEED_MPI) set(CGNS_ENABLE_PARALLEL "OFF") mark_as_advanced(FORCE CGNS_ENABLE_PARALLEL) endif (CGNS_ENABLE_HDF5 AND HDF5_NEED_MPI) #################### # RPATH Management # #################### # use, i.e. don't skip the full RPATH for the build tree set(CMAKE_SKIP_BUILD_RPATH FALSE) # when building, don't use the install RPATH already # (but later on when installing) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # the RPATH to be used when installing set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_MACOSX_RPATH TRUE) ENDIF() #----------------------------------------------------------------------------- # Dashboard and Testing Settings #----------------------------------------------------------------------------- option (CGNS_BUILD_TESTING "Build CGNS Testing" OFF) if (CGNS_BUILD_TESTING) set (DART_TESTING_TIMEOUT 1200 CACHE INTEGER "Timeout in seconds for each test (default 1200=20minutes)" ) enable_testing () include (CTest) include (${PROJECT_SOURCE_DIR}/CTestConfig.cmake) endif (CGNS_BUILD_TESTING) ######## # CGNS # ######## # Include the src directory add_subdirectory(src) CGNS-3.4.0/CTestConfig.cmake000066400000000000000000000027251343724673500154460ustar00rootroot00000000000000## This file should be placed in the root directory of your project. ## Then modify the CMakeLists.txt file in the root directory of your ## project to incorporate the testing dashboard. ## # The following are required to uses Dart and the Cdash dashboard ## ENABLE_TESTING() ## INCLUDE(CTest) set (CTEST_PROJECT_NAME "CGNS") set (CTEST_NIGHTLY_START_TIME "20:00:00 CST") set (CTEST_DROP_METHOD "http") if (CDASH_LOCAL) set (CTEST_DROP_SITE "10.10.10.82") set (CTEST_DROP_LOCATION "/submit.php?project=CGNS") else (CDASH_LOCAL) set (CTEST_DROP_SITE "10.10.10.82") set (CTEST_DROP_LOCATION "/submit.php?project=CGNS") endif (CDASH_LOCAL) set (CTEST_DROP_SITE_CDASH TRUE) set (UPDATE_TYPE git) set (VALGRIND_COMMAND "/usr/bin/valgrind") set (VALGRIND_COMMAND_OPTIONS "-v --tool=memcheck --leak-check=full --track-fds=yes --num-callers=50 --show-reachable=yes --track-origins=yes --malloc-fill=0xff --free-fill=0xfe") set (CTEST_MEMORYCHECK_COMMAND "/usr/bin/valgrind") set (CTEST_MEMORYCHECK_COMMAND_OPTIONS "-v --tool=memcheck --leak-check=full --track-fds=yes --num-callers=50 --show-reachable=yes --track-origins=yes --malloc-fill=0xff --free-fill=0xfe") set (CTEST_TEST_TIMEOUT 1200 CACHE STRING "Maximum time allowed before CTest will kill the test.") set (DART_TESTING_TIMEOUT 1200 CACHE STRING "Maximum time allowed before CTest will kill the test." FORCE) set (CTEST_SUBMIT_RETRY_DELAY 20 CACHE STRING "How long to wait between timed-out CTest submissions.") CGNS-3.4.0/README.md000066400000000000000000000110471343724673500135500ustar00rootroot00000000000000# CGNS [![Build Status](https://travis-ci.org/CGNS/CGNS.svg?branch=develop)](https://travis-ci.org/CGNS/CGNS) [![Build Status: Windows](https://ci.appveyor.com/api/projects/status/jux83kxj0r234oy6?svg=true)](https://ci.appveyor.com/project/brtnfld/cgns) Coverity Scan Build Status ## About The CFD General Notation System (CGNS) provides a standard for recording and recovering computer data associated with the numerical solution of fluid dynamics equations. ## Bugs/Feature and issue tracking https://cgnsorg.atlassian.net ## Installation ### Installation Instructions using cmake 1. Install HDF5 on your system a. HDF5 can use the standard GNU autotools, so './configure', 'make', 'sudo make install' should install HDF5 without problems on most systems. 2. Unpack the tar ball containing the source code into some directory. 3. Create a new director in which to build the library. 4. Use cmake to initialize the build tree. user@hostname:build_path$ cmake /path/to/cgns/sources/ 5. Use ccmake to edit the control variables as needed. user@hostname:build_path$ ccmake . (a)The path to the HDF5 library should be specified with CMAKE_PREFIX_PATH=$HDF_DIR for linking with a specific HDF5 version. - If HDF5 is built with parallel-IO support via MPI, the 'HDF5_NEEDS_MPI' flag must be set to true. - If HDF5 is built with zlib and szip support, these need to be flagged with 'HDF5_NEEDS_ZLIB' and 'HDF5_NEEDS_SZIP' as well as the paths for those libraries. (b)Fortran can be enabled by toggling the 'CGNS_ENABLE_FORTRAN' variable. - A view of the attempt to autodetect the correct interface between Fortran and C is show, setting the value of 'FORTRAN_NAMING'. - For gfortran and pgf90 the value of 'FORTRAN_NAMING' shoud be 'LOWERCASE_'. (c) The build system must be reconfigured after variable changes by pressing 'c'. Variables who's value has changed are maked with a '*' in the interface. (d) After configuration, the Makefiles must be generated by pressing 'g'. 6. Use make to build the library. user@hostname:build_path$ make (a) A colorized review of the build process should follow. 7. Installation of the library is accomplished with the 'install' target of the makefile. user@hostname:build_path$ make install (a) You must have permissions to alter the directory where cgns will be installed. ### Installation Instructions using make 1. Install HDF5 on your system (a) HDF5 can use the standard GNU autotools, so './configure', 'make', 'sudo make install' should install HDF5 without problems on most systems. 2. Typically the standard ./configure, make, make install will suffice. 3. Sample scripts for building parrallel CGNS can be found in src/SampleScripts. ## Usage ## License The distribution and use of the CGNS software is covered by the following license: ----------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ---------------------------------------------------------------------- This license is borrowed from the zlib/libpng License: http://www.opensource.org/licenses/zlib-license.php and supercedes the GNU Lesser General Public License (LGPL) which previously governed the use and distribution of the software. For details on the policy governing the distribution of the CGNS standard and software see: http://www.grc.nasa.gov/www/cgns/charter/principles.html ## Development CGNS uses the branching/release model as summarized at: http://nvie.com/posts/a-successful-git-branching-model/ ![image](https://github.com/CGNS/cgns.github.io/blob/master/git-model.png)CGNS-3.4.0/appveyor.yml000066400000000000000000000073741343724673500146710ustar00rootroot00000000000000# Notes: # - Minimal appveyor.yml file is an empty file. All sections are optional. # - Indent each level of configuration with 2 spaces. Do not use tabs! # - All section names are case-sensitive. # - Section names should be unique on each level. #---------------------------------# # general configuration # #---------------------------------# # version format version: 3.3.{build} # branches to build branches: # whitelist only: - develop # blacklist # except: # - gh-pages # Do not build on tags (GitHub only) skip_tags: true #---------------------------------# # environment configuration # #---------------------------------# environment: global: 1_8: &1_8 1.8.21 1_10: &1_10 1.10.4 HDF5_1_8_VER: *1_8 HDF5_1_10_VER: *1_10 matrix: - build_opt: -D CGNS_BUILD_SHARED:BOOL=OFF -D CGNS_USE_SHARED:BOOL=OFF -D CGNS_ENABLE_64BIT:BOOL=OFF HDF5_VER: *1_8 HDF_DIR: "/Program Files/HDF_Group/HDF5/%HDF5_VER%/cmake" - build_opt: -D CGNS_BUILD_SHARED:BOOL=OFF -D CGNS_USE_SHARED:BOOL=OFF -D CGNS_ENABLE_64BIT:BOOL=ON HDF5_VER: *1_10 HDF_DIR: "/Program Files/HDF_Group/HDF5/%HDF5_VER%/cmake" # Operating system (build VM template) os: Visual Studio 2015 # scripts that are called at very beginning, before repo cloning init: - git config --global core.autocrlf input # clone directory clone_folder: c:\projects\CGNS # scripts that run after cloning repository install: # by default, all script lines are interpreted as batch #- echo This is batch # to run script as a PowerShell command prepend it with ps: #- ps: Write-Host 'This is PowerShell' # batch commands start from cmd: #- cmd: echo This is batch again #- cmd: set MY_VAR=12345 # install hdf5 - set PATH=C:\Program Files\Git\mingw64\bin;%PATH% - mkdir 1.8 - cd 1.8 - set HDF5_1_8_VER=%HDF5_1_8_VER% - curl -O https://gamma.hdfgroup.org/ftp/pub/outgoing/QATEST/hdf518/relbinaries/windows/hdf5-%HDF5_1_8_VER%-Std-win10_64-vs14.zip - ps: Expand-Archive hdf5-$($env:HDF5_1_8_VER)-Std-win10_64-vs14.zip -DestinationPath . - cd hdf - msiexec /i HDF5-%HDF5_1_8_VER%-win64.msi /quiet /qn /norestart /log install.log - type install.log - cd ..\.. - mkdir 1.10 - cd 1.10 - set HDF5_1_10=%HDF5_1_10_VER% - curl -O https://gamma.hdfgroup.org/ftp/pub/outgoing/QATEST/hdf5110/relbinaries/windows/hdf5-%HDF5_1_10_VER%-Std-win10_64-vs14.zip - ps: Expand-Archive hdf5-$($env:HDF5_1_10_VER)-Std-win10_64-vs14.zip -DestinationPath . - cd hdf - msiexec /i HDF5-%HDF5_1_10_VER%-win64.msi /quiet /qn /norestart /log install.log - type install.log - cd ..\.. #---------------------------------# # build configuration # #---------------------------------# # build platform, i.e. x86, x64, Any CPU. This setting is optional. platform: Any CPU # to add several platforms to build matrix: #platform: # - x86 # - Any CPU # build Configuration, i.e. Debug, Release, etc. configuration: - Release # scripts to run before build before_build: - echo Running cmake... - mkdir c:\projects\CGNS_BUILD - cd c:\projects\CGNS_BUILD - cmake --version - SET HDF5_DIR=/Program Files/HDF_Group/HDF5/%HDF5_VER%/cmake - cmake -G "Visual Studio 14 Win64" ^ %build_opt% ^ -D CMAKE_C_FLAGS:STRING="" ^ -D CMAKE_BUILD_TYPE:STRING=Release ^ -D HDF5_NEED_ZLIB:BOOL=ON ^ -D CMAKE_STATIC_LINKER_FLAGS:STRING="" ^ -D CGNS_ENABLE_HDF5:BOOL=ON ^ -D CGNS_ENABLE_TESTS:BOOL=ON ^ -D CGNS_ENABLE_LFS:BOOL=OFF ^ -D CGNS_BUILD_CGNSTOOLS:BOOL=OFF ^ -D CGNS_ENABLE_SCOPING:BOOL=OFF ^ -D CGNS_ENABLE_FORTRAN:BOOL=OFF ^ -D CGNS_ENABLE_PARALLEL:BOOL=OFF ^ -D CMAKE_INSTALL_PREFIX:PATH="." c:\projects\CGNS build_script: - cmd: cmake --build . --config "%configuration%" test_script: - cmd: ctest . CGNS-3.4.0/bin/000077500000000000000000000000001343724673500130365ustar00rootroot00000000000000CGNS-3.4.0/bin/build-cgns.sh000077500000000000000000000003401343724673500154210ustar00rootroot00000000000000#!/bin/sh # # Builds and tests CGNS for travis CI. # cd src make make install cd tests make make test cd ../examples/fortran make make test cd ../../Test_UserGuideCode/Fortran_code make make test cd ../C_code make make test CGNS-3.4.0/bin/config-cgns.sh000077500000000000000000000006171343724673500155760ustar00rootroot00000000000000#!/bin/sh # # Configure CGNS for travis CI. # set -e cd src if [ $TRAVIS_OS_NAME = "linux" ]; then export FLIBS="-Wl,--no-as-needed -ldl -lz" export LIBS="-Wl,--no-as-needed -ldl -lz" fi ./configure \ --prefix=$PWD/cgns_build \ --with-hdf5=$HOME/hdf5 \ --with-fortran \ --enable-lfs \ --enable-64bit \ --disable-shared \ --enable-debug \ --with-zlib \ --disable-cgnstools \ --enable-64bit CGNS-3.4.0/bin/install-hdf.sh000077500000000000000000000007501343724673500156040ustar00rootroot00000000000000#!/bin/sh # Set odd/even days of the week day=$(( $(date +%d) % 2 )) if [ $day -eq 0 ]; then #even day tests, HDF5 1.8 branch HDF5_VER="hdf5_1_8" else #odd day tests, HDF5 develop branch HDF5_VER="develop" fi git clone https://bitbucket.hdfgroup.org/scm/hdffv/hdf5.git --branch $HDF5_VER --single-branch $HDF5_VER cd $HDF5_VER if [ ! -f configure ]; then ./autogen.sh fi ./configure --disable-fortran --disable-hl --prefix=$HOME/hdf5 && make > result.txt 2>&1 && make install CGNS-3.4.0/cmake_uninstall.cmake.in000066400000000000000000000016531343724673500170530ustar00rootroot00000000000000IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file)CGNS-3.4.0/license.txt000066400000000000000000000026461343724673500144610ustar00rootroot00000000000000The distribution and use of the CGNS software is covered by the following license: ----------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ----------------------------------------------------------------------- This license is borrowed from the zlib/libpng License: http://www.opensource.org/licenses/zlib-license.php and supercedes the GNU Lesser General Public License (LGPL) which previously governed the use and distribution of the software. For details on the policy governing the distribution of the CGNS standard and software see: http://www.grc.nasa.gov/www/cgns/charter/principles.html CGNS-3.4.0/release_docs/000077500000000000000000000000001343724673500147165ustar00rootroot00000000000000CGNS-3.4.0/release_docs/CGNS_TestingSpecs.docx000066400000000000000000004260631343724673500210350ustar00rootroot00000000000000PK!+G[Content_Types].xml (MO@&f]`pP<*v ݏ,_i P}gf;CE4ʚH)3N9ga2QX)[^3\:S6 =prZ`b:ɭ"Уs'm& q(=X!/ Y]2\SW#™v5YB'OҪzvzA4>M|n}3+N湒PK7D']$lr'AjF +?T$͗1.;"i7<0z7-Fz(F_6nW9*c4o({JuLs7u"mͳr-g@PK!'  _rels/.rels (N0 HCn ]n0$J<ޞJQMbΟjwb)%rDbt;H uQjmH"eR&R\l|162,dHS67 }?G[hQjib&lQclu:tifc5=z ϒvLΐF$3<)4/͡cTZ LֲPK!y |word/_rels/document.xml.rels (n0HC{Mf{z]Գmٓy{&Yvɪl(ڋ+3x&7I6v6gY` XJm}[}<{˒–8 9 _b}LȊ9;Σ1u,(${!ע~X\062g2:On)%|pm|,회PnzcӺTUpPI(1r ]SHA{!Xavv%Hsŕ( rWov՜H5 "lbN6ߙث f-GЫ7VrE0nR 9k*1fBx3'(PS sLCrc;6L.OD*+idQ Z8D'1ݐ[e>xՉ1&@=숌IL t.̋VrH<OPK!eP$ aDword/document.xml][sH~߈']{k#j*}BT.}ڿ7dD"$%w%w'3Xfy&Wg;LQ:ǫ_ƙA24 ^{$L ^SQL//.S8 whyP!i6 $Mt9| oA~Vn{$U/&h\L(߱أt&߇4E.lz=EtQ5߮fYrY>s 6ed'vt=$ݻ:&S4m۷=.pcSIY^M>f3}:1fMbFF7JbW}UO{ގ4s$=OwaY:֣F&Z %=5͡`AV=L.o4 cP\@D]tO/w*i73UEU# j~/IZ\I8Kʎ.՗!b%sW![_}8<#aW/4n{؉$+{Su;'hk/wJ q-)QyF, <]Yfjd.O7&R#J^tgJtd(ڡC,tN<*%T#ļ_=4(*dScAs'+"UI)[2M5vz1*fT#.m][UtU7Q;h!\7ڞ= E :zd$W=$zJAR%?Y IX`J &N2~倠DGI m: zn_.K2]PX@1%Z(*LwA`ɻ$,6zNOdUsmaɷ,Q2Gn]+"5OWӶ뱢y|i4e^ KiTw<ʇgEo e;$ze> F@ia-<$_(#gUW-ҶWTKv,v5,oY-ӨA[1 OlDY(5KA.W@yA^%*ѠQ8B< ?Q_|?q4G̈dEMP-M%j>xH.* Pқ :A:$sDH-NP~DK1UlYmj䛼F㈊Mj}@De~D|J\p{q%UuoȂa/N`7ګ $`i 56'_UZ}&WAr5X Dwi]5;P:xWߪE=՞BH`:-ZN,VfJ.(L1%$$ W!1O =N75x\m=ohnN67W_ {Y|lSVdBp), dhCq~J#]#6%aa#$)YSB~X $^)9*E(''2t%!g+JAīYd.5BAsQRiXPϿ)|Lb!4% CQKEEGAm2J8zL*rۀuXt=DJp5uEW04D9:vTd], Rմ-z"蝈MtlZu][U泇ʣE:lofdt]RMZ8o ipRK܂u" QZN(2 ́hZcK!ʒU{]Jk`Lχ`1= {Y TJXT#T}ҥ m2ЖA1lJʮQƒ`fCMk=õ%5琢M`? h T-k 4]%ÞDa%.Kڵ%JWa.58afzæPmG݁@-2r0i0,(X!kcuM!iPfrX2މ:@3rzEğSU:n.Ng$1f J ZɥGlܘHIHY%ضm/xlxI"f.M2 `yy\]fw7li9x(^s":`Il=>}WkIp~¾{Kpud(逘k҇oC4UbKT8#-~.Lֲr:,X{_Jfh̞vUiQLZJAyOtTa ]4@Gwr?'i > x3?+kh%ċ06@Է9|{]wٟ8"@!%&lIx,WKg1 DIQdbD#b'\?k< H͹ zSw tHTaݥoa۴N4207M.Z})SGtn;@yiR}$ڻe*C︁>T4l1 WM(5:}'P[o4dO<GZ3x4nUyʕ=$M?}Ohc0=Z[Nؓ!jt}zuZPD2ʢ᫊;؅ݛMb ]IĄ W:SKCp=0<@UaY@G9yR` DMk8CYtP++Q1dŠ躒+ EBg벆pOPV`+_גpY'yUY(ۢn^=҃,|C")jO9Y?v<ǑEz e46"mU )&k#r>)N8| F/cNF.u8T(Y(dTC5=(MA8C}+Cۄr?YLlG٣xC@@Zu]CyH,T|8jƶBq=eHtl8D}  zD)z8ja;8C;n)D|BtuP 5N;E:dO^}smUBIP]X^6Ns1"߷/ZgHʯTMR(OYemְV­ 궤w8'jvuxg?'~OJ U:,ڷO@Gũ'1TH|ǔ79[<U2 U7aʕNiB [_I z G P ~d!ɖF@rPOj'Q'r8YZi?1pPrt1>ζ)>]}q\B+KxK\d{_4i EFO"JvVV4uZ~}JK.@(z±(HP=#"z0[Y/23X>QB OSmMm.{L8~ `Q^|\d6awF񷸺On5 z[0SUD\\s![wl廞wn]֔r/=&yqe,M K 8׍+evy{zr|5Pd3T1ڼScLd$"Я+(mT+;; [D*W/e')1aN,{ QxnFaRPޡ7 (Ԇ4 >Y2v)3aƮ§nBx\7IA}%uC=kjQǫJ8)XgʞFl4ګ $ДIZ]I&gg;k0CTqU*WAUZC*!`= r;l(L]IutDsxkI ,dr. SmP=xMIQ,i s֔XtJ~M GuF.Dő4I.] (#iRfo"1T-E8}sTsZYdPXLk2}ϲ15DI;FY m(xLsZstN"uhsˁģl.G6@\i%[L/j+Yln @ Q.Qaz[X1Ž+D&f=[1 -*l.8L'&qz- ˴6 3AiV_eU-PrH#qV[IxkgI^ܶ࿡T1#ӨkرM/?U6uŜ+[Bc;[_~~//8:{.O>bd_TS'9I2na8zLɞ{(q;xձ EiCϗmkG[؜sb~']v[@YZQt/8@+ⰶ.d(bf((sj.&>q5Bv:]-s \mQKσVWP%:.Lo@u9CN9㽂Fz׶ 6v v.]8K8v+lֹ!%]I:&$USUA_M*^&dkaѸ֑XXGО_Yu4,>`6D3ҵ'ڮd)"CJKn!hCJR3 .NOQeBN14*umgDS/8=.Z*]Z !F5D,cZzkC{2q%WlSz#l!-7s-8r5c6q-,#nab/33ʏ5, V1=1_[DA7 ؕ:pҬ)+` wg`"5G,o+ z59ᄒyGY~ji4\bVhS7`5橣.|Z.LJ݋hw]7e>6k6@(o7@[l<݉6x^puVy.rItE ][M%]7_f}G˼1EF6O߶+zn2|܅Jڔ xw_VD ['cQ1䪰!bG1! baNQfC-t2JL|f%[9LqVПFg~'}xPiB$IO1Êk9IcLHY<;*v7'aE\h>=^,*8q;^*4?Wq{nԉogAߤ>8f2*<")QHxK |]Zz)ӁMSm@\&>!7;wP3[EBU`1OC5VD Xa?p S4[NS28;Y[꫙,T1|n;+/ʕj\\,E:! t4.T̡ e1 }; [z^pl@ok0e g@GGHPXNT,مde|*YdT\Y䀰+(T7$ow2缂#G֛ʥ?q NK-/M,WgxFV/FQⷶO&ecx\QLW@H!+{[|{!KAi `cm2iU|Y+ ި [[vxrNE3pmR =Y04,!&0+WC܃@oOS2'Sٮ05$ɤ]pm3Ft GɄ-!y"ӉV . `עv,O.%вKasSƭvMz`3{9+e@eՔLy7W_XtlPK !9Y<docProps/thumbnail.jpegJFIFHHtExifMM*>F(iNHH8Photoshop 3.08BIM8BIM%ُ B~ICC_PROFILEappl mntrRGB XYZ   acspAPPLappl-appl descodscmxlcprt8wtptrXYZ0gXYZDbXYZXrTRClchad|,bTRClgTRCldescGeneric RGB ProfileGeneric RGB Profilemluc skSK(xhrHR(caES$ptBR&ukUA*frFU(Vaeobecn RGB profilGeneri ki RGB profilPerfil RGB genricPerfil RGB Genrico030;L=89 ?@>D09; RGBProfil gnrique RVBu( RGB r_icϏProfilo RGB genericoGenerisk RGB-profil| RGB \ |Obecn RGB profil RGB Allgemeines RGB-Profilltalnos RGB profilfn RGB cϏeNN, RGB 000000Profil RGB generic  RGBPerfil RGB genricoAlgemeen RGB-profielB#D%L RGB 1H'DGenel RGB ProfiliYleinen RGB-profiiliUniwersalny profil RGB1I89 ?@>D8;L RGBEDA *91JA RGB 'D9'EGeneric RGB ProfileGenerel RGB-beskrivelsetextCopyright 2007 Apple Inc., all rights reserved.XYZ RXYZ tM=XYZ Zus4XYZ (6curvsf32 B&l }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzCC2 ?( ( ( ( ( ( ( ( ( ( ( ( (( ( ( ( ( ( ( ( ( ( ( ( (( ( ( ( ( ( ( ( ( ( ( ( (( ( ( (xí+x=?ၪXodb_ER]]F)l#l)-Vs:2U:Os?i/gy9΢Թok;g~^~Neݹ~.[sZKUP@ wH8Y݂"YݘUP f$$f#xnnTdY! fXeH$FVF*AfMiVii{iӺzk_RRӡ濲Sӥ;]=SPiͽXڵnaJ2qrQZRO.WM윹]1]]F뙦Ҿ+]K_M.kH€ ( ( m~#`W?KS:gu-UgkZx]ߓ}iE#5ΝJ|<#Ry愬dgg&3%r\R2vvjf ( ( ( ( (ۻ,~Ɵ2X?:4]:ĺVt|N_0k¿֞8l/? [zY 3jKT<-=Bᧃ<#xKGǝ P! # D5vj[cX:(1žԎ/ G Ru_1*u%.Vkbp0Rx\. ,N98=yՅJkIT)8)'(4G_~W_mwu?ઉo7ĸ/!oQ㟆??Nzίk^A,|AeVXt&7'6s6|]:Uy.5eR375*SpكUUC8UƝN#jJPPpӛJ'7O|\_~&О5čgF?j@׾:|i?Z|W"hTqìnG֯_hZ%QRRx>ʕl`񴹥ˊ7;Q7hǞezeLKk|}BJ!ù~K᢮xS6-Ki[ )f,>aVibq00VTT0ս{J7a QQM8O5ĸq5౵Ѣw,E?lhԭgj4,*+ƷU/D޺o/N 7¯ |~~>a&/¹|ρ<'>;ͮ!ʞ!]8MŏٗƳ=^ğΛk|<%]_}O (u FSMZ^Y6 elz n")MSNtiռ+V**ZFpq䏲*%:(FUiT61(ZT7QދI[X߳7R|1ç|o [>'zWZ.g?z {Rv)BI/h]ݎR GS6Nx\qkt`qĹ.M,;j.0EF*"jnoʬmJi_ڥx؛ž&~_VE-fڑ>;x{C|>~x?Oҧ״85[{-Sz]B%QSx,,#¹}N.&Uprd&j+ʜԕf6pm=*<<8bWSRQpzJ-Y#ɼ-ou~fχ? xh|~i4|>!^JĚ<w<+we? j[Ɵ~ .^rO\]?B&j.aJ ]5j¥* ū8ʜ4S:kЛʥө0^QYJT3IJ2WwRZ3k׉!N/㗈eSqO <-O:Wsx14%zem BVoPӛd/3 Nsvr,qXUTVYU t)FPWRs劍K5,SxeQlDc+T9#S,')U'fcݷ{bxK֭OYGy3Atn<7D|) "R_;> oTՓHӡ[L,qp_XiU |TqcSqu7FthgO`RSa(i==N+FRe~X!g~~-|gkMnn<Z 3I$>+A$ִG} S=Znx^ ̓˰1b*)QU V)TnZYGY*[ O _ !CeMFpOW^E:x{YM7Zl_G`r ʹZ3l'v5}ź/rrrn.RiqYN:Ν9`OpT%Q]%̓%yY^Ǵ|=|}2|]/_?|bԼWM#S־k|?ý_ī[/|~wmbx+8$<.0[1(VbS xJ1 [ʯ6ZU[*|ޖic_ NV;w:e'BU;TQ?$ܚw C? gڳ߳W >-ZW>=‘ï%/4 _蚯Bu)=]ήƳu~Wա*O}^wUMNj3P:SW#rby&԰ZIGUZT+9I96\b }Fl?i3 /5/w~7>|2樿 5]:>Ӽ}qjV3O|9izeڒhу&L*5c3g"U)֯M}bU8Jq*fRJs`*5JIq߲sßNs\t>|JGį>~xg?csOnDŽ ~ w~U M,>utʶ  _+T{|5O}nVjT+Gޅݣ3:ץƏ1WZ%:u/KE ^J?e+ğ~-$u_ C4ޝ#o;Ky/[|C~Қt ߄5hv^-uO Lau<.x\N"Lw" `*5}_'jJ!VׅHnU6pgXFiV(>ڥNx)A;JQS? iC|S$k_ > ~?o}kG{/^kt;Z?NgǶ^qYN闞)o/gp GbZO TgjtdQu9 S~94x|WSJ>b*R>1Tr>^YJQZrd|ri?4QH|0k:ψt}CWp|+FylGN𯎯ekh`tetUY{Ī"*҄a8֡5^5J1M%Q>^ƞ3F.eN$#*0WT7$w5~~>=|QҾx55߇%b&ӼV/, }nڣYj!kYue0XyWJl pUi}^pmժRir*7.2\겧9 μ9h)49o8:Y%o{?m/~ߎg߄ <߲X| ExxJOOWOh< z-ž [ +t8N#,֞Y•WYP2R֊qUjKRaa,mZ?g(Uҭ94*sz+%/aO?c_ oTW40m)Uf5^5<|_Z _EiṮ`O/+.lpsW*F%%Kں0b%ԭNs0h΢iJ=ھZЍVqTsU%ESgRIԌ9c~S?ۓǷ?h!A_H*P}%N^ϕBQwyf5^e, a[uJlDjǙ fQRM99E>8'|~^ߴw^=Ҽ#KNվxGR|7ýK[۟w k~ n-LfMd \U/YT E9IeJJ*qa|0ٮ' 5#4:STWRt`/KiF7RwBSW4_<^?h/8|=Ozo; _ BOJn)ovk FU@7,V9X؈e(WJxҍzO 5I{YIP䨪Sj7ʚg|qaxD³R\$"' (nduzτ'+|_Ŀ? aO~ #|Z[V?O - wO_oC%⫿>Em2UX*źt*SsC BpO{jpi葝\TS },jխN3NM36ճl?? WßZoÏ ~>)4O>'?&x_ľյo VZMOx:w5 x?Pnq#? #<#IxcH=|/.+QYkt)}[/үRP1$JQӡ<kƛ!&hDuɣIwYhWl=/,z~" 3Yz8Xխr.1h%9sϓM))F\xP Nuq??iYmܹ)J>qnN>JL[mďQ{>־?#޹þ㟃.kut;_񖍯@%-CGHC{׆ 0[8(U2hFTWCuc(UN TeVZ9gVtp6(­Je rE*k﯊>( (( (xWM/~2-WZ.$/:wehD6׫GBnUjSV|)NI]4Z5$gV:Qzua*s,՚oTVh_?5'~* ?< ? 1mwxbD4A㯉vAgs6uϧisxYKFgaqJZy6 ľjuRQN *Rr_R/'3q~" f8Z*B-G0YSu*G7vҌa%D_ |W'kGQiO:SPeдAO1t^ eE|O0Vq=&jT9#ZFgqtԞ*GDS̫<o ^j*B)+[ٺ Q]XVkדUҥ(H:~u;8,wJ?%|`~?<]?Z2|'h{㿇|qxs{G|!x L5-MYoGuhkbky+|MeZo~iW^nXx⮍[WjMs}RI ur_^4+XjVacBx|v>kӬRtp1 )Uy>NG6̩eN6\ka8Ν%VWnM/idm/ry|%> 0^ox=3Nռ/^gKk']ΗwZ;j2C{ ŬJ]br|TiSLI7' ^xʢZu\$-+mˣ:(:q*֫6NN0j|ѺG{{= /G/|!>?~=~<9xŚ&xQs W70oԢ՘Ȗ׃8v /F&sZ8Vzx:Rs׺ŧb2b1u':59xӅ9|* 7!b{{ DM|ʝ;`{_n*g:ӪӅVQWjz٧ͭ< Ɩ}xSi^'UZċC1 ٯե,N&S ZӫRPI{(e%i\',\,=/cFQNt%OZ-vSӿ ma_~w|4IV 5ozwt꺦P>wk0:4M'GGW;:S「9ڱr*ь||ϝqx[9r+ʞr7Zğ)2+~Ϛ_C¿iu3M6xKO=Y>xk~յ jZֺ^kz<8|.˰eժ˪֩^ZqR5)Ғ&T,yJ e^Z8hž2Jn S*2Pqq_&bXr{  O4F vqSSE%;2_4tE[8/;w?8|Go) z ύwS_j_4=º.C{G4ɠ[n^_|!ҼC71_~4[M;W^w]xOĺXj]ZA8<-L? G%Ӽ#HЦ%3NE4NIsYCaᡋ`t*U:qrwZU%{WJ6*L5JեZT(b(OX9ISQ,Ҍck>{O¹.>xWǟGŏ߳?OWލi:oIgV mbzhqCwi>!Jj jSaΔukuaZQ#,;7ӛiG棔K:N(9N4JJU}MA'k$>2~0|M~;Gߋ>!O~ʿ? />? ;2iا"}[Xִ~4W⵷е~<}|Aɪ[zs"o*[Giw%{.G(*xJ0eK6ӯkѤӇ#\jziS/[:%)* d*u')s-Tl8A2DO?lY)O|CށvFþ= *K?A}.ְ羅1.kdҺʵ9%ЦҕTѭx=*:n!r^Me#V2IjHYou?i}9ӏ5ɺ'״~&?_?uO/K|;K_m'}+4}[W2h 1 3 >xz8GZB&QmpR5*+VY*)7E3\Ǘ|rq++ź77?g x7K.?~QFhmV=T:[yJ,Wˇ?j׶xs*}^.v0ePh޴,gh쾫sѽ9}__|uEk_Uߋ k[o%[=:M*:_n_ocwӤ|G4COBPQFRM-9|ͯy?SzO$灩pIYFu=:{'kj^}+> пZM{GGunJFttrF-m]vT,N%)?1(mG޶nYD2eU΋}t=t|7[h_$ݟOZg1lk_o_ |G/w xohk+<,K/ej0ӄiWITSSiJgi E˗}fxu)RƺrN4hNt9kJ#r-Z^8s x?h?bq!_ KIj:>to `+sB4/iK?xC^(׉GִyVkkKi-[B+a0Ӝsu!V.aө 5etzx/Ӡ^xzZBaASeӍֶR_ K·ҿC7KC ?|:x;д:VksGhZz^#vkkK\(g8l..\>UB_,N%ʵ 97QVrQJqcAASv4V+cĺ4bԧX(ЊPtn%&96E_OO|E|Usg~+|wN1w< <74{ú|xdnjme|k-uasXzبaqr[_gNJ_Z6VQro78V*UCZa8R)%8'*>i{кiEF{C ɞ,|}]n7Ad/jvoo ۏ:[o1cb`]%fg51*RN 1RnQ斷W|B)<& qIN-|[[UYrW% ŏ.kO[WQOSis|D<xR||CJ\lMoy4)EzX쮎/}gCFH¬5W(*5,[Vz0׮{ oVm:ZrY]Z\6GxP@P( (5|e<=?Z.,+ROkPh W:_X$J]JocFq9V>xkR)PRWz‹ʫ:j\MS|GͭG5YʆaILueu%7{8kis'oX?V[_}c?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<oX?Q.e?_4ᦧ<:7:_x*^ke=ͽ&[o|w⤹@Dm݌j#kUi8 yfPTd(G98{I+EǓNa |E7FpRJ3|oRVZWvP@( ( ( ( ( ( ( ( ( ( ( ( (( ( ( ( ( ( ( ( ( ( ( ( (( (k֫~Lg$x//MCh;үE?j~m?`!n<^FWn/yϗ%P@P@P@P@P@P@P@P@P@P( ( ۟~>+Í{⟇ jm𷅴V6U5MZ.QGlt;[ k:/aCrowWNAC2a7!'K/ʞ7 dxs}֣`p e',?ZxV**XNa7\*EvIJM)wjega ?o4\<o k8tm?@> ^񯃧Sq.Kof}1'WpغGȰ8 \%U0?P͸fX:fyNx>ʔFqfT\%PYNѩΛk9JI~->1OO>u~6iayx;SK?'5H~<xgW|we9ɸ{_%R0=hk:OuѩIFtNݣh5W4Y/~!Y~s4|/0Ø5|}dZ]߆KXO-wֺȻf,/GzyqOp9n:aG'503D89)'g>01øXw)'JR*)wpN-sIJqp3LҼNS!]V]ӥw1xoŚ}%\xK5_w-͕ ~6e\_kX|%LF V ⡒S2|..|-Ys"e,*tn'r<41^e_#ռ%_ yj~$Ѽaψu%}WS\¹|_YK,q/\4oW8 9Rt8s|%x4zSv>xN5=RE5WT6->Oïxgxcgi5xsJ*~g||~Aĕ̯LF^`_B<SEq} fu8dY Gg(CG KשQxjN՗HR<UM+_?d_k_Lj<%'?uxt+]_IO!Oخ7|9kq|Mf񅕾~%=o <CMs繕,'fc[1eN/ x\&9axeYq Q8 y baW ׂ­QUUgU*2% JQj|ѕ'7xW)P@P@P@P@P@P@P( ( /s)䚆wԵ}ZP%uqup4H@$K'0Y.GoeF[B8l-4`xx6G Z4ҋjJ*ni𓓜e);R}[9`ؗG2&w|b?GbK%IW&/ǮOee=ߝ{?h+'ֹ9R7'7*=)?P%_eq K+W!e? |&Yw 6:P+pÃb}"|xIx*R2\]V]}a'gvmC/}? M%s%[$ <*[\C źIZ*! ѫg_T?-?x}G@?TC7+W ¿&#;"[ hਈ?`ةFU,_>QػIs3uwff4'dž_%wŹvQ-#QI$J'0_ CD_`د_7? LGwDķ8Q`إՕe_ ? e`H*pr 5-J>0x&x9M5iBiinP-b5l+ʣ:_1;p_ CD?b5l+ʚ?bYCOGg KJj4TbΜkŽ"(QPR)))iK .jTiӓN.Piu?=ƾ( ( ( ( ( ( (?( (KuO~l-k$񅶧.i;gy;/m)go ź'Z}7,:?S5ׇ>,k~'׌,c4{?]"&Ė Pn#^:ߍ|0,-k]YfŶ}sx +'߆~v|>/;4_ont]TkoZx+H񖁨ͥ]CZԽ"Юn'v-Ƒoi?5SMCoGeѬ/A|3->+6՟Nӯ>3_x㿎|_/⹇^!ռ1W𕝏]GŚM!o5>CڍVhտ۴4k}sN( ( ( ( ( ( ( ( ( (( (u߂Q8~"oN U$:^i|zkGaRx]CH5ƑGkf %=x }xX/U凊j̷~-|y˪-Ԛu ;ᯏ>)߳$~*񭇈W:I5 Ox&;/ڇ"|7}W׾?_KSw^"8/8Ⲯ-1::\=[$|e٢oN9]?cr֦eRpJSJa2-V0RΖK*0Wm7 M^_j-?߳YEh?g+ԮWƁx_Ym_tgu+-G_FCZJ6rLapf.>/\|,σ{  Ga8S<q m"BpӜ.Ҩ_cڏ*4i;I|g>9~h*xCwXuoO|Oߍ)o|-/^;NGƳMĺ-ׅn|[𣯅g)qż5gxFef?d8qٶ,b4! iU!Jse\Mg%/oFғ~ 5{?O쵩iz&c=ntZz6|rlST:FhCixK'~.qx#,nW^u^ _ڼY>Y(f L'qX|Uwj/-Sk7.Rak7MO~ٿįx+ 񶫩x=.ĭ .A+ JYbk`3|P,VxLoC:x5Yœ*7:Nh8yB)'.^h_?|#k;OC7jcxnF>> xM6/ZS׀|Cǫa_zK3d:kd\5fX 34\AV+*eZqY^xז'T!)Ԕ,nYQRRr^MA'(Qf~1x2_ :xD|M{ixj+_zv>4N,V[/(O*Y8nYd489XC үCᔹ=t=E.d-ݚ#6M/>1OG |Ix]& WgQO Ÿ C}' jIکsNJL;og\-c)& 1xU盬+ͧ.+0ԿIJN\Ɯ*{OgR3XnNn_IMno snR:QU/G;x24w<9o7u)5B4/4uռ&N>)GYW*#]֢q9S9? O=ys ƜU 32OA.oh]OAu=7Ē?vǤϯK-IAq?dFos~]ha<׆r#O' m4]&a#VZk~(x:G>+αx_DWfTY5̸9y3<[øIG W!,`JXMpkf؍Kꑍ:גO9sMݩՕK)䠢Kc(Ց"kEWL?/PuixSƚ;~SR}G7^8h=߳x)4E&N{m#^EO#E(3Dڷ_s[?4,o 6Pg'3(pxO 7˸!؞JkĜ1TBrU*F;4O2rMaZܼŮDFnUVBI|KY(^o XfngQԮouJmR-v-SW?&nG^&V<3̲>|V*5Jxl-R $2Rrl&+- C \1BsU_vmܛw۩y/~.mOލ.J?'QhEi]+Hoxz1VUm.Wto!V}MkO|9{SEx?[8NeYb8\Gę2ͳ8+N\c!.iSՇf4*՝ iebU<Z觍WRTOih\i'vhi?wm O'nmƹYg'|/>s=e:gt<9? .,:.38ƺҧf= /nfT|b)|+&kOiK?m7uᧂ^gnleJέ.].wWu^5?힩I/ęiK~+sj|_&{=*7gŧ~ 7v'q_z:z9G̣x8p<0pXja'\KԒi;3[F۶[ךqobώjxcO|wB_|E|H>#^Yu|[\[G<}+Dm/x8OgC6/q?yWYlu>˲ :\6[q[;q{giW2*vZvխ8~ſƚw7=:PmkD~;'y-[,j6 QRw7Ȱ;p; ̸oW!$,F_VϪդjyF9וFkrx+U#SZj?:;j>NCᮋx:fXizM)籅mլ?jzϋu0jڎw7=;UsN#γ,8eC08Ldi&5_ a06\.,apTaOB8GԥF#>^h'㦚:Mos( ( ( ( ( ( ( ( (5 ?KM&s:i6+ZZƅ:-MԵYXzji{uj_ ivmOT,/ ~$t'>xo^R5S5m:wiڅZZ·tS,Z۠'T ajm_{~)l5"4_^mᴓJK=Ac{p _\Ӵ%Qk]SW;?zNMYvwcfdR[v)huנ ( ( ( ( ( ( ( ( (?( (ϋ?E|Y&9~.|?j^;cyß} u=nIbmúquH>~kIԭ|M4_||bM%|<񾿨xo˝K#WӼ1NĴdj-+埀t-6ѿ-t]|Oހ߳E߆Lj(VUP/HK[ϠO?,~w:TpsҴϲ-;x;!>#1;Du[_> x7Ct}At w&WcLu e%]'_M ş޿kk8X<8Oym]kOxZBxSRd4mqrng?K_k7QjEֳ}aj&ڎWZ_ҝ_cWȟ8՝(2RMkv.3<[tOx_^\xVigm>±xg|#5V|:׎g{?_<#(_!ź]x{xH~=\ЛCkמ?յmN>,S]vT}3_^{E 3Jlj-Gx_#/f xg__IL:Է~$\O|J״T)Ŵ9Z)]!v_oRz WBށou2>` qQe~Y4җ/vm^Kk!76qO K 1[P\Io >k 6*Hr*J*ʜNUBNjTIS*FYB J44K뽽72j ( ( ( ( ( (?( ( :L_I>隧WZ'il45x?WVY^6$Z%Uw~6k4tπ>__ZF|czf׼_Cck_^xo]׉̰e*׋qX8(Odx^!VYQXv 1^1Ux:I+r̔]\!IGF|#r|mNn>$ O&S>40[[>>-Ik|O#|&V{[B/ ^h_>xS<>}XxaҮ4?^E~{ lq\[xn YOgcg\EW;oCxsY^K[p|q8|>,8FU> :UVxJP#㈧&qMTN$~;VZu9ռ/ִ /xƺý&ţ|/ZǞƞ54jMkXO`| US2!62L<Qb?pefĵ5'StWxEJSt8)EJU)N)(,j?ߋB|kuBxcS~ 5dkMWw_xh9qXlm<?|4on85|I<N٧njnH{+X5FS_Yĺhaj2iJQOKּYmT_Ƭb2;O/t]/o(ӵE$+4_Mÿ|s.ƟxJ!n4?uKƘl/ *xeeapa%_Ë>ϩ:2ͱ90ż&cEINNsoҔjF1PtV*+<1PѵRkk:Y_k:GjMoZzޣ|%]"|[5_ 6xCہ.,q&[fX,Tpvqa}/S,x0o9, ˘f9N5ƽI4(MTqOZmIΜ%/iU-r>8vx2qkYԔ꜕5+sV:pTe.k˿Qj_~i.Q.⏌O}?kxJi>oMO /5KM@ˬ|E {[=#QKߛOxY/.,s^'L 8J|cR2qcPK,su84*\QsOTfiGעتrj3AqCE_x/_>?|Q[yGÿfXռkoub];RM?[ς+at<$p>,+W|Dʳ.6Y!C?s.iWx㋰^+ BR/<=<]\x]g_?ˣccW򥎡_f}!W+yo{I5.xk㗊.~!kO۷^iZ߄'7to͖]Jo{fe4ky<0g2ʜ9WʳVrLpn/es<3cKt:j:o#)ZSRPu(0q$?VƦ*9YVβ vr} >S 8rV|2PEG8M)GόRW?}3[R⯋<?~=ơS7>>Կ7x[O}C&U}g/./m|a䒥j˃|CKp>xF;)/9E,/)V[geTPuN>J5`PkNҍ(^^Iԏ7%& 0Rk| -ZEc |C_!4-Th?kO ޭ޹x\)h ֛uw53O xg~pigX26C|MZG/p_6SR3T37(dY }5*y/*IZ:QS*nM2h]?t(W^0/6L]N׿tM3G ZO;UHmmxeSC3;?XL`>ueܫ/򎿭J؛fT"NS2TN.;Qr4iԿk_|Q/|!H1S[?G5b߳!Z/+i/Ҵ{[i.G+'h?|e9/L:*`Y6=bka8k׆N\pUq,Uxgxrd^PX/P΢FϢN EϚRۄc( |@.ZiW/6:G5O kxB|/cc+  iw=gŖZ׋%|GMsAѿ<7d[=~1 ,n78O/U2/>vھ~|QZk fm{Lu-"<5[$󽟈twO_>xoPC|4}G7|5X'_KVvk Y8h5;/{⏈:(|! E]zޟώcluKxkqxoKмeX\5Z^hQ_hC,{G~x3ESO/~ ⃪GVsIx G{UWT?Zhi Z`/?i)M KC;ҴOv+CZhY 厗o?ۛIu ?|zt :!>,_>(ψ:_|_-폊5/Oǂ4"QU{-m~_о:FOƵ.7LִuYtl%=|Hu 4NH> x CE WzZ/W`?hh ( ( ( ( ( ( (?( ( (/{77E]֣jZWx8]:XRkk+ att^ih?g>#Ǻτ.3ᛯ|<׬5-O5? h<s6wΑ6miuqk2+{pw#Yl'|ux;o-j_?ei2l^_ Vo~%y\6m_67~!GڎgDžt^wE]<7ĿRփG"_xľ1[0y|.>#+x;g~.xCÑz$^0 s\fI iug'@:տ>sᅧox//t#>*j h|7x+ᾛi?77.k-gI.]u _O>}E@P@P@P@P@P@P@P@( ( ( 5G {LQ~k7MWYMu-{LmP_@!5MY4.l4WW5 GB5X;8jڗڀ;:( ( ( ( ( ( ( ( ( ( (?Mø4 tK} V4߃O Zz/]i G~xtCIDf6_j]/:[y^YcO_ϺnG=mO x٧xgEHtmcM` KfڦZUt ះOxǖ(׼;.u\|,B _ $6v A?f3&xXTl {xU~ xWƾ91 'KAYx7ߌ|QأͦzmOdx 94JM_ž7˵n? xƗ?g xFh_zrc>,-nSͻ 9l.7o(W|j .+|Lb_W@ iFi+?x ߈Wf4-7X_BtP|i&M'O:Ɵz}?ZU3g1G*t<5:36| hؼ"2S:+ [MVʾ__r}b#ROܜZٻ8 -͞🌂[j\SwTkڭ:LdžE%a /^дm6KO~%0ΝL%.J;¤`8:ti7J2kAP_fXgkb(;EG-{KqCDx ÓC mᮬt2t!Xxm-WSSgeX{H5#aYf*fitN󧷑+ͼ $bWF2y>*tr%0`"W5#tTo\ sS,&n/iޓO%4cyYza40[Zë}sl|PI+jk!:\Kxo,E֡c _4x Y/Z| >$h0 x5D<(!8uӮU5M/L=?qY`1|/q7d9}+Νn !9UL$Y߷19֨0qX#yiQ ugR8~MӒoUrKIAÏ+A't3?|?3~!izGO=MQ n[/o KbP:<ԦѼa^$!:xׄeu3 eV} p[bxgc%C_(Sba"`ᾹO7㱙^希ERѪΕ:Q9IEF8UI7GiɸIv'}KG >*`Y>֮ Wğ |1RHWXk^oOmy~;C.:YW6\:y7VpxmǑþ`3;cڵ՗cpMZ9ZmSʜ`ȭgh|WU[2r&M <=JSg>$k~?x1Z7W~3I2.5S<=cxJ+ i1Ѣyn& |7 1Ld*Χ[ pG Q㰸L& ,b|<1aWrфJqN (J+ZVmJioNJpI׾|t /^ dO 宛o/M-隮b-6|?M+]ωtM]ѯ>+Os x|GgcR9 /<GTacs,^?퇯 M5V\煉,vf 2G›P@P@P@P@P@P@( ( _zCO~txw?MZ wY6GPoaa.\6pf/G^Xo?oWG~ /<^}f=3B_uYt}8ާ_Z\h}xEO #9gۄrԣGᡖljxYT:hVXyS_mKJuiB¬*[ڪ:>gJx_~enY|]؇g|?xcSᧆ-cmwDSƿ?fBYln5 >}-nNxZ;@u{+\AĞ!cl&*0_< ,5:~/b)`l׉x,b*4YĨfpx,E)qTnJqi{L4p}U9' t׽GxgXdzt~$]x69e$ZBH4 G' A׬|)lN?f/xsosj5rdX]' x<13xj<^qFq m0˱L\pOڬ5>i_MVփ#ip~9٢MǏ_ ?1[i>"xo?~%k^ -eh^> uEU>X{xn,< Q9wu,8C܍*|70ܶ$Xψ.Uͳ(,5*q%i 8غ\z2W?{Jo/IScIMr.n_~._ '1u/ im =񿍾/|4tƺ,u\ +ŖnOA5K]0/ٿ-OeC p gپ*ah3S`k,9W0q e TxJ!ef\өiе_5_i;O߷KS_O_يFyko:zUԘM[9'̼_1+/<;Vg⸚xORgxn|Exdo;.8ʱX: +}[UWeQT­!=FL|*$|ue ?'//;i>2Ӵ]V;"xcTSM+<+Y5U.09{GgF/&8W" g1-ͨ?lob08l#ڧ+`Ve&uc8()Bq*dUH8ϝ(rF FG}o3O4CIi}jZ=j+q /uѦDHWO;\u) WNIOGմϾS/d67-:p>!xS58a..n^15,ObO/px9Ƽ%,&"w¶J_=_JvMF1qk>$~_V <~&e/3M:>1|s'ǽv }S]kki~*}kk> Ҿp^g8>3\':gx\<>/<\U渼;sbp5)e2g TN:~ʥjKRzu,Oݏ-dx&k_>|=߈?t |~,;ՠ#w>(|Ohq~,}_,ψƉ ƻX붺MF0Ř?y+s*~|cC\5O_ ]9a,\ke?ҡ0OUeՆ5Ej|iR\ғMSm6+?>$McM.l4 /G4X[?$!LJ"-%/VNMž:9随uu0>2xeK1~$fYg^"YG0)Č^eL%Of Rr첶?p[8\bIa8PVçKRN8hg)F.u%rr򿉾74o|Y|[{߈^W7V~ пh'_Rxº2gb^cie?zo"V[of!ÿَ/c|182wc20> GK-,Vt'9}[T#cYJU:(')A7%I3ɵ]G"t|a2&{/i(>4/5kšuD^ a?j> j'Vu:^0:P$FY|YӜ0gp7(ŷps9V`Hӝ9jRիYI5U)^F.1qo<ᛏ]>*xwOW  7Iu??t P 6[x<'l'5-W\񿋧[8*߆G3̟f#:6Uw DԴV(/[?t-Z-RKEnլx;r[_KY(潴kƎø ( ( ( ( ( (( ( (>>|gwg]K?<}Ҽ'~$O  xUЮ[:g-sxP/imn4itm€J,AN z/? ׭ |Ce t[ygO{綼ͭe\|ZּqڕkLdL񏏼Em[$k=W 4+ŷ;o[֓G_A'4} bg ៊~'='qYk]]׼7~ lVZxS@[@Iok|& ' Zx;KcN_g-no>Fl'lw/TMߏV ZV˝ŚU߇#j;[]ohN|HG𷆾#7,_1k-.-5=?n=?WK?^־x;^DV񄍤k=QP_5-|g7p=S Uz.5]Px{ŶRi'跋oh$hl|9Biu/ iBfkho_g3.'5o??>Cg&+OihrϪiO7F/t[@ >wG>=ǎ4{+ķrx~x^,W|av%Zdž \1_M/4%~*[uJog/ |G'T>$ozO7xEԼ?SÝ7Zx _kMO^|{H: QҾ"\oK,ny}gjG 5[M:_:] 2ږK  /wR'|wkxZ?'ĿD-𿏴?~e2sƋy]x7_Z ܺݖq}g-Ms Wwdxv=G,R\Q $m.e,r!xmmmaTifyeaZIe#Egv Pnf(--IdY!fXH䍙YX% YI{N^`t/Kl(NOuPt{IIգmP@u}%uETӆ_+a6ex_#9xm\m,>(|y-ዿGeMwF4Ox:~ ]cSeֿ$`_ ~(x?Wxk>+|cWˍ*u:|tM[Y6^|xguLNh1>"A.Z'ƶ@'dx㏋;{?_ ѷvPK?MΫ F\Mukp}|Zx~>>*zgaI,Z?7o~#H>K}&/-t ?fm)l_O|'Ag#įxMޗ7#mg/橭xSz/|'@] g,|$hX9x?@5{W_Wkw~xT'OÏuZڟ:yj>~ޣBM֝;EvN?~-g|I(W'CVN]rO3CGK፤v$k) |mѴ?x ķZ}r/׶>Dž ,Q^XOSu_&hM#@k?|s[{O !>/)x| ;;ٲu⸼>~t/o]+/ׄ_OF}Vߏu/·xP/+I|W?-}I4z 3Um4f߄?gE4_i ]Ŭjz_I%|IWZjZt1u i:lF@9oKsW㮡x*\ClWvef6#6'🀾~ #bqO@>[?y4׊>6YZniw |@|OZmS;VV(>-Z@=jkt/O;E> ޡF|`Ï߳Ko')>!zDoKQg%5j~Zׇ~^5WSIWu N ( (( ( (>U~>Ii=5y 'xBljYxWY_zj űNJׇ|D,M8o{4ax-3K׼7Z[?G?Mi-J?|MBխu.R ?C7य़~|lYkvZxx?v_\чtItWö 6>"е+]Y[-nP m>֧񷃭5R>5O x_k2i~ ȿh|ZMwVtHy_O[v='\gi>l5 zNj"?w +jx4btL =u/?'~-Ԭ|0O5\xO-i^'F5bkýRM'VcYe瀿 u_:?9~? ֏Ci5ՏJ_~6zf [/lB@:ٷ_Cx[|Ovso%z3k00hw.;~]3G,}KU kS6^$_+nLu^7ͺM^0Ӿ~3oOߴ\6:{"I񿆬SD`|m}|V]Lچ|<6;5msQ'ï9tcFR_-|BSHVEΰ/H=rƺ|?c+.um~[tAumS~{sxW9w‘M {^ k|k֗IVOR$GCXEw'T1Gt4i^"sFtjVZ?^_/|)xh5~~/Ÿ|mi d|L_{j7^Э-hݞrZݷj> s]|>$6ӵ4~%([؛9|9x瀥k.4]^_)Ckno+g}KEtqW >xi{OiW<;mUANj|4xF-gՎ/ZKْo k>$m÷cBK, ˟$j~巏-xDpP@P@P@P@( ( (?3~ U53Y?? |/>x3Asxh~:g4֥vm/-| 1tkz틨|U#ouCş!|_톑o{W־ӵo|LW׾Tv:?P pmhT2~ ^xsK_Vπ*_h-Lw:0Iៀ.k~exV'3cۉx2d5Բͧ\W^1HE/zi{R7~5Yf%U<?^35`ɨG/-P6Yx'Zi< u1ҴU~*5;Ι8k~+\wgPA~iߍ~ x|<񿇿ekP}5}rM^7-c&{kq.@SOo3{uAg/^-3htOiyFׄR>#iGs]GwQP~ ~2ړ4?/ |tI2Ix_xSƞS4 8xg+_i-{þ/~(xwCqCoPj>x[4^M[kxD[ZnEkx#%_ t5p|HmxEx š ]U[-P~~߷狭<+߉| *w~x /f4kLuo&VMZz>~xF9x^WAK]_r3?j^%Z> R?/*ŝ>MIkz ( ( ( ( (( ( dJx߆5Ik⥮-?^!<+I :?tC&of>6'X?l ~#5k mVdV^9Ŀ_ (Ic{x=;BnYZG̺PEa<xq&OV-.,\>gW8 ^3q8 5,F *tXw9rc1ӧ8F3rJ7fIKo+k)`uoCF9~ Sׄ߈~k3ѵÞ3u+<q&ֵ s^65k 3$+ʱ{ bSK(e_dXadT2+gʐeۇG32Rw5jRcQϑCޔU.ZFxv ?:ߴf߂ou[׵ D/ho^Vbz/M ⵎce omw=lyw٧|{lV˰>`ĵbqɃ<ФnbcxpWԖj(Ip> xW^i|Ǐj%Q4o4:^1$sZ jZvat/5{tMKߣG|^]*˼H<U lF ) 5vpyY' 0XT23Q'^U)IAҲmTq+T%&U%M[XRgZF|Ai^&ﵨ4<=]\-,->h9BdTkTxJ:uS~Uj0u*SfW)YU[S, ^ rY4A$9%gͫM.i}gǰz^k{]c~%[O x/ſLJ}J\|='SOey? 6״}s$q7Z*UY,6ଟR8j &iW,."%Ùcf3iV9_O8zʫ_ܩy$ go hk᥇ŸJ x#O/~3u?M躌62Co x[Ul]&]O[擥ˉgI}3f !ว%>8K)^)p/ Z/o9Y Vqp`(U'Bά_SNOE%f{Ï۷~&j,[w8xCK?|;itEuv:OP=ֽ-ز4k=C>9 p|I~_&Ù Yr39#/ɿ3jSGEK1ZٸMԛOÒ)IE4S_sws@>|IJצ<^,M$w O6G_+gxIq>S_yESq θS* G[OS)MU 8|.t je+N0mR|eSm'~~yZ4E9KGf<x_umW_m w?x]]¾%G]>> .5 Կ ,x&&5E 1yV{W0l[+9uL߈MYg[ܻ4㦪t~f҆+C搜e)RhΪ.nJxz q4Tt^ui)gQ{_?]_⇆ux >/-|/TOٗT4&])<9KYi> DZ_{V~חz8-SL l6}YM<*kfNq+08el+iէ>gW U,)ThcS̝n\!/g(:a "<2|nYCW*K7w |]exg?_ ie&Zjnfoto xU6tw/ ;5C~'є[^Zk|79-|kgo|?NC^9~6 /ix>p;9WK;̳n3ѯF]2{kVZN\ЄeJ!JQkjFhٵi9J>9}w kacm /?%cύ>('c\­sƷik Ex÷P^^]!3&w"w"#W$Ë=V|7}esCI|~2Yf2R RQ,]e^ӜBn)UiC|).Y[V[9FoW|cEO4V0P~ͺ-|SkgxEסgN.& tYOу wϳ<ͱ>kʹ%|qқM񇀮)::6YJCwI.1 [ÖuY{h}sXLg}lxX^1ęG <`UK`֣e<ҫXz-FrӦrʧ4~Y%N.kY&zO(-|I?xzuv[kZ𾣣i|9x RޣZkĖe6hEn57g|AŲ|9LG†aج70LƦ5`kaw]uqta1/cӥRU"ۜ%(EW5sc_ǤP@P@P@P@P@( ( Kπ5?z뚯o|=-~k.WDO ^$z^~~ÏK-2[t'Ht-9}uφ(G›|HxkOoz|z\< cJ;l,K :{=*B|9: - X¿eT%.hFjUbRh~'}w*|&_aB'>hLW ?a~&t*GԬ?eG/ß%{{ TVjٗWV_rѫ~+8XG#:O0b]F!F28FklU}#<ÿ/vۉ埴S^%V D'|+//c/υki[Ş>:O6k-ii OfHzyx^WbrlNc^ì{5d{PR+ 崫a"a-?Uϗ^MSu|No\#ֳ|woK6stFOit??oW~Ҿ,럱|/3ßxJ\Z獼Eit?/ZkczQ9cK Ka)(i,PѓEBH=_vNDޭWŸ;Vßk|].Ih3_WK6ZčM5/ `/u B6./_OMnQGŸ 2>+|mgƹq+KMcq.+fÇc*c2ҝ|Lط9/ƊNhS NZT!N*p!4PJ?u%mv_i+{@i:3M[')V^.f޷xÿ tOf? xOO?|%}GuE4K{?<Dž؜L֎u[3ip9`2w?f4%lM,0YW1jUJ`\d^%IE61N\XW4c;%&N02>ğ?/૿#ᬚZgغ6=7|74sK(oj~YˬxMPH*x͕VVw*ז*JUZqSRxU1S7"OK St_)`XB<׽$z׷7=ů_CCGYX~ZΫ*/<%|CҎ~:T=_m|CSxz_4 ;~$t^3eSSSwpXjx(e<R/vC.qOB\m'T\S h5k4-x|iZX~3u]Sʗ^0tkσ"x~?+'f?x?ߊ<#3smHO/9]lN# /eybxjx<噔i**uQ5])fj+bks,2IqR,0Qw&8E*Oh >(?:ECyּ9W| ?CT᫏ ;7&IW{oFNgA5ձ׵o]􂥘3b<ge̟px<Ɯ]s,7}C45 %bUUj`eUcK HX J+VQFビcߛբ%ʓ\RiS(~ wJxQo['ԯcH|1k?dk-~^~Kodo .q< ha K;NK0/Ge̪aiG,8J. 7, NXKqj'˃^S%+`ӛ~3O2c'O9ѵ~e[\Mc8-%24_i34Kϲ?f??>.|M<<*_Ri^x43ĺ']uRMQڗ FiSPLjEa ?_Ɲ? *G׍~#/[jWPJn> M{]p^:#0B=&B|~6w5 ߅'R?|k—-տ𦳢K/Ԛm:cL\ρ?<>|Qף-sGu?|}? _ؾ%摨i:F =:Yҭ4;][EoW #c'?7Y7þgm_Þ"_lAXtjV< VЬ֝mxjen8 |oO\x;Ѣ7"| x[ǟ .|%s}wAo{zL'*ӠXKu?oE"=W?o]s৊KźmK {MsRo46V:k7Vuuo>;񝷅֩㿏,M_?IxKķ#Ēx_RּUľ&ڞ=cx/Ig_qM#ZzO2w+X:h5w=]>ixǚxH}ùemoiAFh~COaX wxoOA Os[ _C|ះoƖW_ .Kȃ¶KqxrI^tQY^]@-QoN4xsQHmktvǶ=߅QxTl"\?tn/@;xlٶk_72o_m>&[xoxJė7boͧI-dpVM|@o>}h<+}{[H</>yE4? _{ Cc3@+Y= NO@>c  ?_/ŷz x_GֿxīxV]aY<%oZY/<7j6n=\5mZ?d+I]osI쵶IZqw/,.>7&ޥE2ӵ+ğ84{k~<5N43^! T4??G]]xYӧм'`*[NmN/~$<o-x?rk_+#P,4,6i7 x;}gseG=ۀzn˺ߍ<7Oj5^ xKA? YC]|9iV7g5+eΠ]P@P@P@( ( (>CigR0ִKO?Ҽ?ĺMSⷈ|e{D`a/ڦgkĶ6Z:Cx?AEq5iC{Eu> _O񅯌B|ceŴEx,,Q]Oqm$-΋@?>%|#Ҽ{W|M.h_~+|_Mg:toiWQMm-|/oo\~MǴIAt |Ak'_ gO @%Cuj[XtcAWrj߀h_^ Ҿ0+Ү[╟h{xk xG>'_k^]!OxF;~uyMp/ 3S |@oM_ #?|Sl|1|_Ɵ|){{h%N _ x}@, IWwvZdAK"F~)M/x$|aּYC_n64V񍾧hn|'%kc,v4|[xoǽ_᷈~+w~?zM2vxOų]diz5CxZlm+|r?ᮿ?h_ /G|7o|L'ڃ] ,֙|;DltO>ςi}{VF+f+ğ9|J|?N|s6V> ķ1M^ym@#4KK|Ti3~.;c|qmQ񦛦à|s+/:f#Ky(^3/⯇~&|QA|,мisH1mwwso:v- iKѾ'+>5oFHTG{ wh~?/ υ0ijƯ|a|eߎzf|BMOumcZtaw4MkK%Ɨ{ iaٳ:}gZ̞?~~ |BG׏.!|H/ՠdj?]EC/n$#h~g{M&Դ>*q}No߀ i'Z<1f|"wͦ㠭i]ׇT4۠C/F}ڽέ |4֢׏4K{žO|=^ӴoXZk߈< JľֵkSGmo9u'쥪ZkvW֤Ķ|?[O?Sjw-{oĺ {[y5M[Zsv妕y ?t_>.\_/[4i SxDŽ|IqYjz~_WkuŨkG|`&]:PϷq|-­ ^*Yxg?:wm59;jOşk߈oY`ŏ<*񵿈/x4xz=*)4OT5iXxS)⟇_Mx Uo}2AՑ>ORC1|,S}#NvTki6Z=ckԴ?%\_i^$k闚nhFޏx]^yvS/Cu }]W~*^i7_5ᑢimxzΝZfi4cÖ^x!{_ػ¿'4Kf~M>2^=Kxjxe|iiUFYԒp9?4M&w)mه'|?Oɧ/:<1+_״Ԇif_'?DŽ}ωO3:#{OfCXVHԾR|d ;C]_|4u?hO[POյh|Dh_=[]#i Oeq}\ZwiwiԟS>a߉'tJ_hگ#~9 }Ŀ|t>~I?rh= [Mпh v^Zv۟䓀\Oͼ? h~-xυoODAj:4*oi.мMeM6kmOZQ5~>,?i|x?ys_G-Nju xIH5ؼ ~ǸTljF+Rp(' _~/״ c@S|E JG4m6w,Z}|M/#hr ( ( ( ( (?( ( (?9 _~>|C?4_[xºά;Ծ~/URƕ}-7>W1C?<}Zi~<[|! gI?_v/u/?.| ф֑mS{3EI6;h¯O Ԟ!>OEO +K_x\%>M>PwĿ x*NFxw?ke=r 0NҼa뿵¿3 oǺzf⏂"j>Uޝ\Yjˡkg%h.x@gZg/xw<-/S5u=F-FhzܚDžK=C~-@o-/oK=_@x㷋>$x||wAkUӭޛɴWs^蚔忊3[]iҹ> Ykk?x`-/& &/S|;|'?kzW- _Gɼ[X|oѴ'kGo|Ij'> Qݤw!j:O\x'Qѵ,Sĺ[Ύe_5WE|~3޳qEm?t?cÞi~-f|T?eվ67QxfxᇌayJ}v{U{iO؏? ?zT~ΛZ.K?_ZKKm L_G/06q[ ^]Ʒt cB׵/||K_G@]coj9a/~\JC"_Mz/zmW[xSվqk/~ÿ Ic_G/]xWUƭ.mAjMZxuCNt%v7V1iז'?/ğ~$k67گGޥy$^%:njf߃| [_uu7q&_ /iĚ|!yk񗊾6U|'< w:浢xP/c:ΥciZxu%ޱk xjw FiuvKo_^㿆|˯7| ⏀ |T_/sk/?ͥ׉}_:ό<CSmǪkچvzƗ/tko-w Sm ?h^'5j/~H/~'j^  S>8? :4 Oᗅu .F@K74{__ƍC^(KIYxǞ3$~[/GY>׭"^Kx^PѬ%>?g>%|<_?i_ TMojj~,3x[soG״ n>MXM|;q>o3|/4?lj;p$i1VyXУ51`ҡ,/b:ê*RY}QV.XqD-xSU0֩RU#X|M:&uxƛR'RC)wū-g>w}F@٫t]_US^՝)I͎uZU\tJ<6.lF+)[&J?Rg/NN^VJ0w:.?-TP:T1ٽZ3O˰*3+j9i/C?X6φ??eP~?&'<s߈^*ݟtZxr/^Zi+TxL^ʴc>RTVE,= i%Z22h9GUS}7͖Xz|B|`6SFiӍiU߶g=S^8Oa/TSlnWյ?iмE[_|>m~_&/-'h񯅼}xk8kE[/|;{?6^=d^=|CJĚkz/<w>o,Wdէ/x\#CCaa[5+[ ލ)T%8ƒV~Dix^,6q$MvNk[ŚqxO_hLshvzkW+^Juk[.4ߤKZjx*…< /aFOiR4Ue:yJ+:tl2RZp eO )UgZ>ҤBSQ>ZQgRpq_U|';c~C!i~$r|gЯ}/>nj5_ x?7?ltMgpg-sk ?m$3hp*aW :8\muU WC hƭ)M;֭VJ^^(t4% \='*հ麳R(N1^9GӺu1Q̿|N__ |f ΕO _^2~xa~?Z:@WKWX"7~toZ4p/:5<=62qO+ֆ`9uT!F)ҙ%UQ -,چ5)5UTTƸԦpNx5nuEFR]?ૺƱtkog__u>xB7j|U~xľ-L};:ͫ|)`u[*Q4]Oī[jPx;Cy~%J'%F>&] T B(ߘ=I*0Yd|T2RX.5(43ԩWj)FN*JP<E7o]sl<)om^!^ǧv;ԾIϋ|[kֺm퇈,#{ԭ|ۄg`K)c*eهQrth+V50*دaVeJXYBqq%bXVK)ԂA*rwA[Fj2EFPr~a|Le  |qt^ g<jt^!=炠mbƵ.֟䵁]3Vڟ`|0 |(b*B5UR*v:R*4)S͏pձ8IbaOSԥV$eхjeIC{,3EZ\ΤkN_SxƏf_F-›ڧxQ|I_|IMF5Ih4&wFdlwօ_AkG"C*b] fgb3:)TpjRRTUO⹵ 5u7[ mO|yh/ŏ5_O{Z.>-o j /agi;VZVr\re/V S-Ϋ;3jU˨C`yqtҔc)b 9`ZeԾxY^*Q:RQ'1I|tF-yXxsǟ|Nx,%e̿<kS_/|YΫ⿴]_ǗvtO}~ ɲ| 0Upv7*8x~&8ⱙՔp8jtxxX:'I-^cch< BJ|^^y}ViNTp'^e:2#$? a|5~0xG¿^3Ţ :^1m:?k,<=xO׌-kZͥߡW/xѥBXW社N"j4c)Jp8gY᥋G ,Uj|=5Jz\% QrۊQSwX7]+ǿ_ xূj|@ݷ ߲>xZ]WzƟ6>]S[B{FnuU0+s <-gJkc*/TCJ58NRmG_0+`Ne*" etATBҴeNJQt|-I4=RW5fƙc[%^ ;{Gu.'t\-*[#o{iKˎ `i֫Gj9py.xS*MҝX!iQQtS8^ X/Ν:^#ӕG4$F+hϘ.>( ( ( ( (/?߁TO|xnxw ^|^=tGS^5[O5ijK Fͻ6qzj-<'ާ/Ŀ*/xzMcXԬ<4;}> Jid4.lu.!%V]}> E;`x;uxoIXooß>8ic<}G_x@֡x!G?A_ t}#%ߎOxw&x?^+KM_6Z:X^wIxf'Ԕa𾷫xohNZ_i̞&GkhI|+4n|Oc ZhEO3 / [YkOxd27|Uxaeg4:'u=tb%[:^yx_4gͦ;,jj4]G^6IM|F{_>]M/ ]__#WγKyas/ߊu__ڠ<+f&uB~`X(Q=Oa3 J+]C R5JN6|S廑{Zؘ:ܫFj>_}T\t3?fm6_٣{woGW]GW֝ sNjkK6]oJtYm ^wGkAa{lEZXxօuEMg³Τ#6%pe^_y*t'k9ʚ~'#Ԭ^ |-Z/ZŧKQxSfh:ݟ];)_I^g{k6K3CJYc*xB*2j!J4cr^1ӷ5(sr+)`0xy9PM:RF?n7̒m33G7 4|_v:mk7Q>j_-chz͕rOJ/:E:5pՅ RNQVa95J.rj׼zFS:PZQ u%m*SIm?+q'I?<~O]E|X?4mkvL5WG{"R-tݽ7y8]hі5~[*SqyJܣ ]8Y6TK.r~Ÿ#җ//.唗+M|}v߳yx׌/iU+k~/ih闞EjBЦ+;#JxKpMbjҍ,D1tMs&:ҷ%XBQI˫r: YՓ ΔMΌNnwMG _? -m;:,t?;:"ƈV"2/2kC-G,L&XɺRԌkfb9ʎ)WRa~c,;qFy5VhJy(M(TR?k/G?cWe߉ <9Fx~'u[KS/u=^_>]K&VIR5 /2wQxpjT,5ҪzT\aj#MB;*2xHyק)(=ɶ九Ꮕ? >5-h *\| @xKC@xI<)ϋ /C5YoeoV7l;B8jT00ZxJuBӽIyΫ\(a\ 8jueuR:u*Uzү*3Fr")9G zt V?QH^>Z. g//G_V >6·1_¿1>&E[O>'IֵgK! W~ļ@:F2~eFK_ܒ挾$G;r]IUq+9ZR"ZNv;sƟ炾0xÏ>7x-j<)#E{a\\|;jj׺K 6{]aqWQG}*+be­X*4~{aK(sPFMTPbI#ʗW?E|~S~*O&k^k^FƷχ "sbTbsm|=jZ5qgNUkN[jm8ŮfҔTK.P pxjUiӧRaB^wiٴ{_;Z麗>'v/~>2}?|_!6_hO4O5bTֵM2Um2'x/o5 6?_B\Mia`Tb)H+*Wºh:%|aa];kxưZw!^4kX(f4֬㏯EʟM<yW3jal. _Njt}%KKAOiռM11~/z_[cxšOů :W #׋4 cj#IҢ9cxQ~^Em/aGU=6E< ׳I'N6TzkK(QӍ jХy 2rvemx?|hv{~6.sCĺ6i-5=oWKmbķb19eجF ѭZu!E(EAJ䇹䇻G@կC FjSJo8~i{ۚ^'sO;{Oßoxk >xU~<1g|SxY,u} 0,.-ԴK-gjԮjWCRUU')Rj15Nn\Ri5{ O pS{(rFWRc҅Gi8+ O}i2σBit/:7-?X%~3A|aia}ZL.E<'9>)Zϣ;/gi?tˉtm#Ukkmb;L9?,N*jӣ)'Ҝneu̓Ix+Txz8j\эhFj2̛Nͭ E[oٙl4_Z^OZt?WG>x:Mdizwiv1?AŪ*E֩=׆yi:1ʵ,MLe*ui*j"G8֨RS8&ca Ҏu(:j'B3)C9/D&mn|5%߇?w j 4TebNoU*TK.ʕNTMRI5$w[yh0?!|Hݢ|A Ŀş>(OÖO6 Cj:7%Yhus$7V^k ^?lGaҩV*YtפN51 |4M"8LWңZYV`SܼԩMF+FWj/?P^AѴKm"VԮ~ xfM>^5kI i{x_:w?&Hm<3!Y|wC7u|M5{ Zm`e9Aig.ៅ;gNu߈ MoHk\a/׊gҵ R[ x VKPO߶gŸl.4zޑŚW_x^Dž-/:¿,ccoyHvoKe麽7~_7MEO|S7c~ ^xBRԴ|u-Ηyaj:}tkn_Z kFKPg?/ua[݇>$x_Y4h|U]:fohfMmJRM+2 شgJ֭&_ĿP>1iֽ*@VuΓ5X3 xw<-h3|w,F^鷗_``5Hci_e'Uoqh^>~"xzFÃ~)+oi~'5?h7:=[6>k)OPk^KPxMFSxß4VM Re~"|y}X>a\x_}@lο(g晤xUݾJV[?hkֵ"L7Px]k-@ijng]<%񦗨EiS~$]JRӼ#icxwZ|+=J {m2Z|x_a{Twi~16ox[G_6Gg \t|jM4MkE%9oux{W+OfWWL!R֖(oQ8 z7ںmx+TVƉ _ſ_j+_ivV%ϏS%-Kb:Ι CRoOcÛ/_WOi}Zt? j?t7r+I/-;ߴwĹ-d}^oϮk__xJ9χ_º^ _ŝRº׎ xWsiޥ uaxSOK_~%@uOVΧx$ 3=uo߈zO ~9[{/믊OPݠ^Sŋ;״[e3jh-~Π|>~%k  I|Q x3\mml ~u x"5[ 6%i>5kԺZ<-ϋ)_k>z>5m4OOq|>_ᯋ>%O)lk/EG▝W(uM|&o_ѭ-So<=_xW_>qG~|e>#3ҾM\O[ƁYoWG½GֶZέUvK)6xup[))j;>>[ zu=+º?Z#P In 0xkFVՏ5}H_?_'~xgo[B7|e.?hf+ĺ'{xg? jKNdo6mkB >0|3oߋßxOmrN6~ ?i}':-{-vDjeZrInn.'g˨P{cx–_94/ KO<)iWw~LJ|1ŪHԼi ݜ@Z 7ǚ|eFנxƞ!Kdt FFmH<=jZ,: Gŗ]] 5Em> ErmgP{_zf_XF{|(OWia[>%Ѵdι{s8??a?_'_YW c֚oO\x⟅h˿0:^׈~>#09k/k]i^#wo .<߁ մY#կ_MψuMibPokZ$x3[ď|eU|vF/im4'ھ xVxXOĺ%o ׏u+_^]",ZNJuS\6 ( (( (?qG|)!~ͦ_/Omnj;|5}[|9Omi)KI--4ۧCşK+־7i7co7!q[?qV$ҬG[jovwk;6 G@.<;q{_k:@S~񾁦|Q}x7$I|[[cYP: )Ku;kt ?XBzj:@cw@~{[|5{m]x+_$ֹ?_tM[Jψ=x Gs5Ip2h iQXj`ƿd4˛mSß>oO3Iu;~-k*OFAnnmƯvUC o? >>>yimsa? |DgP:݇t_xf{|?-OPvYx#~kj'o~.uZ]!!MsQgۻg$> Ut7T|YsT5 K$lcҾ 6߆}i4(1_n I.5OgモBNqg}bTSԮ>~|is'G,|1AoQܾ0xr x_ƫKg>/'< Ɣ oq iIcwƞ&ZS_ "Poײ\%lM<0~&62m-/ÏHs{ٻN?GZj 7~*?Qm\Ѵ^W $6N.oe{MRѤ_ -]|P;ͣ]<5q;тX@4/Kmh< f_OoEO~k{:__KG+#Ծ ^w > xqu!nĀ]1 }x5'➑}_ (~/xr+n{-GKZ{-O_޹ k? >ǎ~⎹=݇涰g\Xx>ӬPV5X%.mA?'o_|!Ęy~"վ|u_[:^RLW?| g7u%?+¿-|;?_ 躯 Fd{ \N佴|*.޷Η5/~ǿ{h֚',ϊSFcZ`7d:woT~Z_5٧?>5jq/? h5Z~i>RKwo?˨Nj^O<]/h(אjֺiu OYm#:0|cGuVxUF~$"K\ZYG?~ om2_|#o`h6>#4~-x&Jylog7n.-usYclӼ]g7^jiEΕm?zG@v\V|L-!_OB~6ƁOuOiA{;o^.5v-'SVZkQmy.{ gLjz];ZŸ,ޱx~#x 3?>*xzu/ ? IWA"Oehug^Y@-N/|I#? ]x)hpCcŽ3dzi_YM?|,<[ x^L7nu[*_'LJ[oc> \i]VxgH|?$_>kᏉ[~!i7˨H~3jQKz?eo?h<Zi<+OWYyӮxMGWh=ݽc _j:ޏ OB _'WO? _:x7W/SDῌz_/'GZRV]Y1<᫟:F~(~b_u]o|kC3>&M5f4.'ß_1[}OL/MOĒxʹ&/g¿mhſ `^|U7cŶϏ63\O/,~Y(nw_/</ 73h,o/^#_tUV?|YUg|CMPH_P'?N+j:O5KP:tKumwPM7QlZ'MNPφ>>k_ox/]Լ'uO)tcIo?׾0r^5JH+NOk"ZؙZ9QeXC$tu=]rt > ( (( (wo;~$~~!5|vSƞ6'Q}W1|B 13oc_^F^"?*gg:Sxg_敩 :XxSoaៈ~xuOw^z<_zΛxvu^4γA ۬<,WƑՍm1t.𖫧P_?c?|"ڗ| #|y&~n/x' |Nu{ sGӬ5jz'tAsX|_m'B |)DĿZ>v0|% sUBA]?F55Ϗ.׎$:g]MqGjM/<;ZX|oΡ~~5-Ǿ5ixœujwGOڮ,G kI &Ke|cByxWſe?? k_|U Vſj]j{c?٫[M~KHxxbO8ӿ7/k|e Ŀ~<?mSF33Nj|)|6`? .=[` ˿ƳEYAmkյ6uOcP期 /SCͽ!>-߆cXi~$L8C 3kkrZ|pݷ5 _!kOz~!x:]xѭ4 Me -iu?v:įt^$[xHŭWƭ[O4<ᇋ>iZkpjx-6SԀ8 05}oOxźďKo>#MOx.SZh?|+jZ0xf[MOLmop K54mt FO >/'=-#l64t҆s*T>&;=Lit/}^e4 c xW+j//7@W:Ϗ<=qk&TZ<_훧jt߇#</6n<-CA΅o CXxº߈+GPV4}@?cKִe"k;(!|T|vHơx>Y\~úF6u_t|1g/~gS5Zi8ӼgqSg;H|=<4~EMyu O>@6SfKKگ~ig[|vMGþ4 Ě׍d|1Z]a?Z!A~k,?o[x~I?n%/~/?h5{L<Lj"`G/K`L>#|M|oN}_|]-[:~^tEީ\ϣJw ?e.#MOBυu?[A7 SGh{j:&P%D-|SbƏ_}6; @G uIu &M(zr>Ծ1"f%5?oX07k 6[6->%ӼU <16Fx]@%Yf+}7pHY[7|'7ISzu5O}~>/+wY}Eo¿^*mû;/d>h|6)C᛿7>?Xx{~!so:Dt(~7uxC6~"->1xV?~&xYѵ'[]RxҮbcl5NOl|e i:/_"ׄ.n>KŚ7OE[cm\z_3' "Ac]W[3~'Լ)q]B~yx^z׋47Z^e-/@9y?f(`G-_O ^&>#'<0i|x0xkt+=7ė`C} [I OvAg|okRCӠjKKKx]CI\IHg_4=?Ŷ6~<7|r>6>#Hmo |_Oڵ/ >#AKI }[MN_]5П|}y.K1jh-难]gV߇ xCPސ~?k/>6xiS-o}:9$8𕆱{Ԯ]7Dlh4G.鶠0xWQ_?5RsG SOQmcLσ᧎]7ᥴ>γk?ZT`|1jF[߀{F<D <-u{l>(|:|[`>$xEvGY>^|o]sG_ ;A/xǮx^/- :v/Ǯh.t}g0ϢKkg/7K?|P⏍ 4Ovd*ֺO#14}_}᧏>%jn"ΛmO/i~+o,A-0Yӭ^cÞ$S.<)7-yb (?( ( ( SӵMWvz'bvX_?|#9-?xU|si'nѵORhcGwx&_O 'G3nk<9jiөSªٯ䙦-QaJ>& -jXWTbTī F %).YF\ރgKVx |]n._hRo~>mÍkKIo? ?]+ͪCY~%~zq^edn .qP𲧒ٚp\^U?`1|=Zy;#|^oďS;g~L†i`*/8R)<ҽLj.zm9r56%iU8ώx5m&15xzH~&kG> C|w^\h?M׭~*þ&6Vڧ=KKXȿ%x{_|*xwjpiYlj\{yibr, ™u^,* [ ƘLeWxi&7乖_F<9\6?)!xs0̱eWd!C6% N?F)sbF&a.{X9YrƥQOGx?,xF;>"w'Ŀt4?áP#~ω 6LW]ujM[<21̳ > jpc~4A0"~b8~a'rkPr1X3˱X\ʾlMJQzsJ%VH\ܗgΜ9oG?jPx.?%La{e_ hh8??ă0f |-rj9%>|5Q'ʕ<5(U.XsF$NE ]uk|W{  o<Z%ԟi)2tV m!ռVKᦅ{_|58u |o:W/9= 4<3b0L8^?1:YZ -,&Nef&{0#Ĺ>^y3>3VN1B8M{걄i(VK޼”' jӏG<-Hض NCQCNZ)⮣2Ӯ<76 x <'.Q 5(5㰸.$J|%$9CiVRaಏ$_V bpES^{V\?\>[ϗٹ{yZ:ŏsoK&_[~54_i?e5 >Ʒk_i^-cIV]üyYlx~~ d96IxaWc3Sgx>Wɥ}sO>P>7:<ҭN\8TSKt}~(䌼W-d+g#J^/iO_o:%_x o㟆Zټ76Wy9V|'d,7gg`]1kpVXl5*?S<>͕UeŹqVQsln2.yi)gRN+SSW-a^6qM>x8>&$k-N#GԾ#imY/>#xLr|X|v!,/4i'o5g-oK8S2nߏ|?qY?oK sgg߅Ar!lJ<LGK?*izU*41UI**UhAtpqUuu-+oEcޫ@|TAj_=XY|~l>^?ğ76_xOPMx $Ac[\:G]=߄8[<+X7xlN#Ïq<[C3 8[$㾽68q ,C$1XbΣV:~-}g .՚*)8{'Ks~IEd_Wj-Vl,|7Mw[Ү~.~ƾ).=~x*FMGC+m/ĖjZ^jW|xGe >fnE\Q>K6}S>!̸_4b֞fШTFXuIR^X|$#)AV= BrK>oR3|B~8 Q1x'9|ux?m3W ai|9> xMMtmBMp< < yxY+eX|/y䕱|QS:ϱ9.™ai#RcRScç9Nt_Jn8EA5b(ڻF>O|uu3$-|BC?iY^ 5έc?ٝ^]*>/B?zlt|:wxx%9]Xxύد0]WRqm,#+Z9v1rLLIѠȑ#*nXSR%좱1ҋjx^f.i)x_|iu+if액k/|;~.xw>uOo X i_vC_b7Voտi8C<ukOWn3ox_k ~sipyx7Ta16β~a׆0~O,q6^q3:9Lf[N K դ6)(`c)?9byNT(J)5Ν>~UK~<4L־_0[ȺN ~?W+n|6'Ɓ/5*)u}N%,.t8¿K>NW<^ZVON7/|C9r.'g,1YO-l{RRcjFO ΊIΓc*Q"rVrD+t}JJ?|%jV~+|F>;jT'kg}'Jq{Cϫ跳?a5ଇW-p'(px<Zw 9o<҄0CŹ.]&1g[Ra&KKRj֠V^P|ԨttRq~Z+jGĺ]xs x'\Ə|74+Q񯉒)/?Ҏy4 W< XF ڞy|Ocϸc/}{00.E: ̣-N<'X*2ƕ0ŹE4Y&M6oqnۭ}?TibZZ12kʳ!0\&)GcYv.4TN* 5Й#RߖqRI]z}g·=hA|/@ AhYJ⇉m4D㦞>-ikژS @Og%Gf$$$IyP.)%Iqn~]U6b:~χ9l(?l<Q$\ ;J%+[>9׽{뮷\/Pzr_QSgN:Ļ?}S @O3D>&Kna?ir_QQG8uvL'aM?V9g_W0%; @*K~_7wv]?^j&o3DE?q%70 4X:~όśObrYx >ΒCĸIqn~^Icp 4X:ϱ+c)*q8)KB%\Yvmi|?-#< '` s kҲR츷?K]^_=\/aM?V'3DE?q%70 4X9~_A G(gN:Ļ?&+~|8_$G'(ZD]eozK$U6b9~_A G(gN:Ļ?&+g/?5|L_g޿?>l? ?I'GI$y$dzi/l? r_QSgN:Ļ?&+g/?5|L_gT6a =3"q8O;N}>Il,/Lt: -?O Hm-`D#*f'qf"/Wbjԯ+Mԭ_^Vj%*jԔRrrr%I$IhJ$I/a@P@P@P( ( ( ( ( ( ( ( ( ( ( ( (( ( ( ( (?;6|p~ǿ ~ 迳β/.3lnYVRr>Zғ>;J5aN(Q9at6/QV%%+F|c~(_]|ADO>x~woo ZGSY'vx_-|9xMNrkb3JIG .YUѯ^h8o]RJ z4NUW/SgGUu )R IӍ*Ns'E*'%MŸ4yh 'WxkN?W74ǫ >~<Αok~2pGWU*V.U:QQFkU|-$g EO$Լ/5Miֱ/~)|%mn~<g½F> <.H}׉DѵPB揦UKCՈ<ҞBwG-[hQ*Kԧ gJUT^~ʬpRQ K<Ɲ4EF\hZ*YOVOV/S Zx/_OW?|w[-ytSk&𞙢O/U?qX\.^/10Sb0&8*طQIwIӥ^uc qu)(<.)Voغru}+Ɲ^"^ITiƛ_S=SÖ?{|0kW-aGem[|5D_qmx KȵQv.k\n ZY})UU `< :1Sa҅\E9F/RV)o[N8ۧR*4VDƄiT -JVv ·OιC|FElZ'u]vBnm5}t9ZjhwV/zxLEЗb!K)jʵ:S!Ʌ?<#RFcEB )AY‚+(%9}#~:?\=?ll5<7{keO_eg\ZMͦE8݀t7ͩ['=Ƌu5Aihu=J!|d~"b(t jW@] <1xUkĞ.}ƝY:/#ho$xGFte-4?~#uɴgOi~mjZݾzW@`858LM,]ZT ӡVxiC/*:5)ǚsSN*RpVSQFt!O۬G5ZP+Fx*Bn2JUI8ϝE)&{D?eZh  [xh1,?-5!H4+Ѝ[Lt-MN x>UxWU0nԜQKHNRJNNNN[NSJT)b*۴RcѩF1R~So?‹{V.S{iSɦue2lY5X%Ѵo$=sgnb)a3FTK4*>ʪTQQqQSJґO+˥: b"^^ڞ uvτ|0<ǂ'Q5 ]Z>Ij"Ag[j e$w7TF_`nTnhIh6pSi3lN qt)b)))VIm('$\ѳ9Ma1 w|'>!x_ߌoxkM+H4#RӡRZh?%DZ63޶ gVUbNZg9RjNU_5Ԫ;J9C-׆& ӫ 48B0qW?ݫ;{?dcU^y;?<5-gžt-ľ#iiak^\n{edHo-宐xfقץNjZեI%JyFK_oXreʲцX #Ns ^ QrRI9~m͢:͟]Sþ+/:h~$NQ=S7vXsxz@Uu\#HWӝ*9k 3e*SR0tO*uU?5*e Е:<<:X%F2ʡZi^$T9p\O,?FVviyiom-uVx_|=o ]j2:'K-NS%4agggg06vv"UU ]|ehSLEIUʥ-m9Iwm^St)asR\J$IvI%dJ3( ( ( ( (?( ()6Z[j~&е{>kC㎻}chK[d"Ԁ[AhZuuMKǷ6fzx韰hjox[žNx/SE?>-xKm-6_r{wƕިmG,m>/<~ߊ]C[D"LF%xU~&|0oR$kAY[߱P(-@;/x\>Y^|!o\ڨ|g&I؂k'j؂7P?Wψ> t=w%?QM'?f:|=4_xZZj!x<5㟈_ <2OBt/\M׬ڗEDxok?F|| KOMS~'ÿ?$ݺ]k6ό57ּ?_i _h?i/iO߁ǁ|Uĺ.Cag-+h[x_|Yh߇P~'ᎿjƸԾoƫm\K'lx67gYoN>%.gwOq hxE߈gOYz5j@k߲O?\FSGx_o|9G5 |QO~Ɩ>qz:QM?Ho5.uk_41kZ__a:|_ZW1{#4/j'ˤ[>||)4^.ѯ7??hwo9Pj/~)П~ 2 FgM*þ#\eVݼTP@P@P@P@P@P@P@P@( ("gzo 7GW[xj_G1NjV7jp&txwCžψ?ˠh> 񅮑gBPE5]i/&[t9᳒iWŸۋ[X|D_ߌs|>>[)oJѫ3T4 _xKo@y->9ǿj2o|56]Oį|Bν?f}xQ⑦j^^ok79`r ( ( ( ( ( ( ( ( ( (( (#}L3+Pt/&g-ZG+֍Wp,|av7֭tinO6H\&9x c3$=|!yOOEok_xv\k4KJM{xnH ?!G|)>"AmXI-* Ήσ;x<_X|*+|HG]ˏw'L\k/_G/zo7tX<5 6Y|,ϑUťقp$< C!=+^+Zzg\[7w6!OPY^éZ\ows #WF4O xK߁|O0KFӼO{h^ 3V:>& l[k~ ԇ)|IھzwO?i ~W_ <#iu~՟~.Έ߳:/hr%W~;?a,VVxKSOִmN.[I4Y?^5JM UiP@P@P@P@P@P@P@P@P@P@( (KǞ>?/Ŀxg|-񧌵7~։be櫮kͦX['2^\s(` ]֍ŏ>|5Ӿ!C[6^='nizO^*'-_M7Ğ.|]敮hZޛ\[KrP B|/h֑xÞҴ @tK ]+F4]&+ +H4Ӵ6 + 8!+{x4E'~_ |e??h 6t/Z%_'_>|+ }KSk/"&q6{^{JY؀/ 5^$ֆl|IƏiZ>}P%xo5s߇7|;hu]vH guh]@~x3UX_ $|U5{o h:햟h,+5Krit[ ;/,;CPxlbyngx᷶7yt(9 ;PW9}+VԴJk6V:Ύ&\cq:{`Vj vl;oj:֭iv_\7:彔jz֣ktS\r_Z#F9n)@24xG׈|7xC5 /m7SԴ|M`گflI4{&i+h٥Hܨ'ǟk^|McM[KÞKV[Efh+@5-OXӯ+i. ~j77wm|}[5?Zg!UIo]oZ-# >{kVR]ϥ%-+|]Jq b~ߋts yehzfwxvi(k) c&)zgiƓ6Vjoj3׭jA=Ɨ--Fib $Rhh@:mz~]:{mi}C2^Kc&hA0 Wesz=jڞ}oY.mwQljty#MG@Zśӵm6OiP׼Y 6%^α[iɬxTYi]w:ƦmMӢfERP@P@P@P@P@P@( (uleq/΄M~j4{Ub:|?1OWj~$߆ |3ƣy}|5fψ.M[}/AЬtKWާvWzq6M$r8&Sl?4k_I5dž@W~ jԼY"2Oݎ*+oς4ĺemW^|kGptW -G^>iqx俇>! VVƊIDؗhV3𶓣x/of=Αwa|oEXKB-7owJi6Ee$2Qew~ ,| S/7wjpZJ<}Oڏt'|o'5Iux]>< P{Y_¯ C 2o|oo"?<h׼X2yc]5o/KC[8'w :/eiu]{xRSY÷|EjMN|;mp嬚,1i֏x8g?'|iߍkͨ7ǂF_q/k+X~>,"{m_Mӯ!y@861xfK_W>%6|~"FW[׎ /O?'󬇏/>/FEum2 ǿ߃9ON >_m{EO93ቶԴ^r\ƞ)g ME4_¦O}}xKI)ό~? _F.to=O~#K[idߌ<1krPEo!zXXt? | |'?Ɲfe~%xsxž61q+9-_G[ ܬev^!4ωVwAt%i><ψ|YM}RŚǭxE4jx,u(/HJ_& Mcյy.<OBPǃ>u~6Լ;@k'Ë_|Xռ#I?l|U?2CCzռ5x,#ω$/-oW=+o?O;ߊ+> >7,^  a5WHwu^w:5>]oեݕֱtc_]V{/VkY~u]ZZxYӄǮj^''Wj<#|gῆ>+7> ?/i xoVxS(Uxge/.li&/FKJAAh k>~}v/G/im$ xLA7K־ ?~KHkX_Z &x6$嶗/iG-Ywy,5?/8&{Ҽymŀ%kV|/Mv?xV>"]x~Xtv:嗁nl_ڮLGEu yφ?c(ރ?߅4OB<oU/>'3=Xw=_ĩ=[Ox~SOEQn=noً [i?jK=XCxǚL7$x&};Y]]$i$+ھ}'XtόQ^6ORf_/TZ> ƫZK(uZ2ky$#Қoݮ6_ 7~Oᯋ~&x!.=? $xBOxGiGЭ[?X>+Q_-;菤p,oφVQkG>&h.x;RZh nv&n |gG]>"˧xj>?h>-xG K]WÞƩǿk5þ?tk4/T'Pֵ? >(-Gb/x3O4?x[U~xW_Wq/-|ex<7xy,t/ZXx@4+P>)] ]K~῍m,~;+)[㏇<=aCLifAo~~7 cxiZ3yyoh_(oln4φǁtM;-GW/rj%hwST~+A3x/ò|l)>^x{_:'I8G)=u+?xx#k+<$toySbQDu(_6s>Kt?i_[-ûOV5·WSm<5&O|m߇tk%|Lt_ L~5 ק#Xu-?iveƱE,^u6jz%? ~Wn{ | f:&=߂tw! }0OQ:,Ӭxo{B.uqO wN?j(.^ϋ4=Ʋ zMkz隗W2y/-okXi̠u7 sxtI}CC/QTSi\4MF[x>!型o]UNJ5 _?@Xை~k?gQo|_tό {.m[?=c ψQZg'ҵm=Ɵ_x?t;A➕z¿>,|=GOO Ӿ$i$K/![|* Ϫ*|nx|3#D3?6>/2!79#_sw?^'u__x.>P<şf[}+^ ?h O?>"xiG}WXӵ-_L|/w] ×'X/]~h׾8>g/|DydO|Y'LO]7zIIvjˀЦ.C{.u~΂*ͤ!CE('LL{褍1!TgY7"iu]('!*`0D}'' I٘,]>gQuXdS10Jg,%[V-j(R!f|0="B%+r L1rx}5Rq e^pNv2xBԃ{W5(M͋~GxYdOXJxA3ɇ4\{(G<(b -O,@ | gO+Ʃv^y#9gOqwAƮ 8RKX? ioONT br \1$hbI1x4=IWJqZZ]O(C`J!|k (\-  fǰi:h rsݗ+N. EU6nt9`gՏrHb>imt0Տzd>Wl&Gpxo~sPK!Gqword/styles.xml=r8J.;-]OR͎3ϔDۜHI HBhF򐈗n@ͺAkj62\ǻ_n8+on?n|k?nfy|J' -F/!?/{~ 7^,uxiM&@ ? M&m<) 0Z=Gҏcћ5meC71وSPv Y7O0kBv *\NoNb33Ix JHJlhMrd|sƯOAxs'q )'y/o}+:>?5ť{w# =|iS63i#>o>!7DbDAk&V>So 2mBXWK(;~/.Ix`@`?v!.7Ef.{T0wupڭWD:bbX1UGdCJ"ml i T$W4/ VFT}&|oЅ}Y{K)\8joa[/h\E~\#zJ0hpPO1GpK=_UۤAD#f-؜ACoʈD$z7Q=@TxgmF GlR}H6DֶY;^3J@9`X7,o.xF2Cx#c1Doz7QumFRFಶ ¦<DF GllC?F`fPx#Xs'cPEe͠ .aa@m>z7Q=@TxgmF 6lmCeemM7yd@dm:[^<:tUaG$,B~D:|ꐊ/'[4`BXVHN4>{ Rc$ AOm"L~.g)~%.$5FI 4B²ŚIϧ-v% 3@{ ?_=$|?B@DUP0IY#6 ?9-H3+kDKi؄,Kn0pux2Vnv9/YT-[{ھ% pF"Ƥ×4KS1LywObScH 1$dzWRSI+r@ډWGu^wיf̫T(&B@z ݭZ'=ݜ" pdA˘$p1w,QxR&k- X)\>vHJFOEf~!0䖇n`L@bniG7;IBj& y0pYFN}yTI6XsuL=|2k*c3ׅyשx꜈l]$W!n{E\e%v["͢­A Ԃ8ţ:J]k D6\$&6#7SC&ۥLZpszIzk@馎Y, <'-P+ ? ޱ6|E ջ<.9UTHYM{<zґ,19.A6B_Ued 8`  T *o!8b.,s9X\t> _b|QWwuҸO*u??L]V])K0`]u5.#j\Ej^"][܅ufκqlNw.[vJqWwS]m;Rf%l|ҼDeKl1B:w~M.kYw%fSw_"]{]: T1b} )Pr-5و`4/w.#j_S܅vmqי9c]f:Yrܵo9@qWa DOF`5oRru;,`+fVT Uv /˳wɫ43gԔkt8J%H)EX\oIO%"SyiZcB{-Z.FdQ+bĚlP Qs1E_Wx.H@EX?i[KBq+qFAt&bo\\YnCvԻ(1HGB}B 9},'6 V{3YPl (P`gڋ팔qˇSȜ.!Kt;qtKuzn˃WUCte21lT ײ|gK5ʕ^eWi3J/zH;ܓw+ԐK pWS3$)9>wqup廫*!|qwwF (ԺRap2Ω,){2w2NN#s\/]m&ҝxQ}Lz(%4%R;4\.(Ws;r:QVx9Cڭ-!D_\:W]9gЇKv|wU;|F T -G ;][r -9@PJ(# qdHYUWizn_`|nPw6w|]B["G@-UCõ,Rr;W#;r[[C=zWW pWX32 prﮪ|H ;ȝTygQug¸;' *^|gG%wFʪ2j.5ǩ~9Ax4O9w|]B["G@-UCõ,Rr;WP֖Mve 7V0ù0ܕ*)!^\up廫*!䭇|qwwF )ufyI|Ξ\#5&wf m.9Ւ#e/\W3RidNgҫݠ`ܚ>R>1qNd)H q2w/:| v'olV ~Q ^br-_j]zN.{$50IMIju:eE sÿppz﮹p]iɄ3T}Q(2%@3uQZHOBkߋ(퀤wM@L~>ق?4k&$ieFJ2mbxhc}^PT68V ]^qigr0'VbHaB͓/ Z .7d@\X CCG"K؉ƻ!-0 A 3KJXFc FA8nfqB"ЎGzɴh$ޣ +Olz`6 2|^8M'Ž,S/XdӚT\f_U&t-'l*~"RYKܴX˯kGsD[:'iO 641Skao@=F2SM`?Q yO +Z[re-fNPET6ܼ0-Pł4.=p"Bv}ub-JZ-epUdg.˟"d.[3s-= nnR-^]Xl1k%]X#/Ep.*#-W~D;HoVhM[m[hn^ tǻ3>q@s+tLo5z>(o.cX1UJ/M3X'ҕr+v%>JILso1xIdJBړ$r?zUU.HtsnԖD ڿrI*9O"GiVD %&OEtTO3W3ۺ(oygOe=)`"*T Χ|VZ|uBw}p1>O>՛tǃHDͧ2/ЉPS1T] v::7j˧&IkZ\`T%x>nO5ᱡ|>p˧Jp=tȧ9}>O!*#.B@u%SlV8?U| >|Sٰ-DTW~鋷OeS{*=ʌAΧCpSל1q-r<7j˧Ywd;2gtS,'}Z&@Ub-\1p8˪6 4Bl:Zr*qnm;NVd+=ȁ|ϻ& z28d u1rNrY|3.FhHQR 9ޡK!6 6IYO6xF>o}k%!*#.7A@u^μxi˧މLU[4SQ`mX1 wBHpgЙ&CuKZUS8!nџB\a+%3S|*#r_ՖOo&4? i: .RDqDX&~D.N wMH=!R+~nm؀"OMoAOdY76^MvPdVkN۞,.w1+|)d݌D|JJ>~]#~zɿ*`fI fw"aW'o@%;&_ ߳wYh Y<^Eṫfz-ٌ1?#$L(vQf EYvLv\Lvٗ91LF|3h"o~Mvn3r/Kv,KKRV8T7` ލKx?qяw?D[d{~ݏ۽/[T;]#js(؍,/lFo@}0J}l˦͓Βp_0p?ݪBzI 'Ol J/Lvb8@1PLGjIB= 9MP# PճSlóۭ_a=.aD@_6-$f?O)~?pĭ^<`*qІ;'qeoN5v=)ߜI(X i^-W1rm魿?kKE8̌7ryYy?οnܵ'?~a}{+.>cX}gG/v9C+ :: Ȳe97̦{+. vrXS]NR,Ͼ^ ǿz[Qvj .-A@Sw\62RIgjιeewGd)2Q1Q  0Q`oع+/E=I?uk:Zya3DŽ6T4ՍC,64P䊫Ae<]m8ڄ&?8(XӀυ0' !J]ا7Z?9G--l=l9d/!sFJ 4DS%{@3p_UJB42܂98$f,**q)pwa?O?w.)箨"|c?- &-z uw.iLuh,QЦ`>H 5X127ZbgG-XcAeŚ)9׵5r,pճmZikչ R mc+ͣby oѰ4G&; s|y@ D\"|cH;G \fYz1;eZ[f47 F{P, *Mk|\M.(kSm&e7d$@Q3ƛM@Ԍ& oH3\ֶAԬ& GlR}(k mvf=?mxX3h X3\$pISGՌ& jx5c 1Doی9MemMo"k e7>bcJ7j75ƛŚ;9*T.kpIMm3f7aFof7Q3ƛ6#ixpYiSƛRj 1ބ5c o37m65k ̓D5Dֶ]P4L"#9ͻCj"LghQ#)k2q;4"{: >c` H;o(.=Mqƙ|@&YΠA+k-@1342I\u[E* \L]EY6As?XQvP]_ً8yw3c7hЊa_@1a@WKc=@?(mǁ41Qi+=p즶Nys .Z9|ns3esBnvD#z `$ص+:~-!9ӛ3 v& [(¬I%E..)~^]g}WZ\qC2XRÿ́Etq_.Ppt?1@FU9Pa+6hY?$^oW~$Z4r[Ȣv^2kDJiؤ,HeKa0xwxrVogrQ2YT-[wҽc##ņ͸Dqf'`3cڏKh<@lcR])KN%/0\d,V(.BJEVuu DEO7cQNVX{2:2'0Yp.R%oH}jW%4z"dէ `.ʭ݊ B baYRBj&d`= 3?%2M%ٵ;S:Jn(F| ȶLV̂ Tm"ź\wE\r(7nwT^RWQHMw4zhHX6.8!kX6 :`T L0*o8b.v>-]:*B`e1ZY+T],>|64܎F@u]xyQ`Xv&ڢfVrdVGPis01<ԂE-1T#,=N ;)ײlD{\m)Ff 5T5g3~D)zŎT^6X)U2-,Tg3g$Gg&gWB'g%g:(Y)BIW|Ue76(Z:JZF[V*ZpF=.e(adւiwxřQVeh GQԻ^)8 5׹R8κEgd AiVpժٓD h= E 5kÖdv˞cfQ>i 4n:ɺd@J;#\^hg ^>Ct \\ӝđ-ߥGBgN[/V`+$4wd;#\Q|G?t"JQVx9}ڭ-EPC.+ ]N͐2|gd AW#+]T o=Ԭ[s3R@E)ѳJÖqNb)H3Õq2w/prNw[|,wc*} .!V*ߑZpF+QRnm(]|gr_iw5wF@۝:E)P7|g3*lwMY7|d@J;p\W3R٣;#eU_%_Kws7^#i_#ݗ =jei+߹Rnm(]^a|W|gd ܽ+]T)5|awƑ;é΢|qawN6T3=s;\Hg*Ue5\k>-_cKv|wQ;Po8lHw6廫fG>\~GsNڽ\[I\7|gsK)Fʞ|gȜʻݠ`ԙtŎ>(0úgvp) TU =j.;FkY3ew|;Tr[[#=z׫Wg\:s"-WY32["+]T o=Ԭ[s3R@En6^O:]b6 3-)jRg.s+)d82_:|go[oVV\lN wt&aI))댁ZD=]ː縟h#{wGoKn Z2л,Um,gT*LI6%\i4w]6uRKߋ퐤wmD ? kw$-ډg4S2SDQ#%bO1B紊Tt(+Bd^yi |i+R\vh*k1V9U!wðd oz فik}W1H1ϸwc,#K1lP$039!H.Qoih=\5{lc[iԝO[F/Wryb>f.Odo9SYzHOdL:28)sNewmB,k\_]%YD|H/}usofMe[e,YV\f_ut-lѭ*n!V[lq ,z1"܀Odu v;‡:'ˁiO >49Skq7ᏱVaSއY2Xe-wb6[D{dí+*Z KU,9OS-e%lQҺlG.[70Kgg"-^FXnmڢ[[ e}>+XxY/.[l\_]fe.[,=PAt٢ۉHu˝q]Pd7k&bSr4 I σ3;Fqr+:&ޜk3{0{S9qǼ8 /4ubOd;X 90)&Y̡;r_M2trVr?Rǘҏ_d%Mr?N@_(O lˀqP3OqNZD$"IFeʩՀʜdqO˚do{ ~]~2HP,{Iiёɬut3޵2,lI{s}eɑ߻.Z>=7 ;<_1fQJB ]DBm%}C iܨJ~&qE_v!y/,3@)?,vU׵5*X>H% d..v?ҭԥetz~;0\\0bǙuYz$EϮo@2ddϐA&tfF4??Ba21?j"f@B ] .椣ҹei ?@H}$_u7aiܦ~Ұ?BK[9F_BH{ݛ!.x~@|tĴ ]Ea9yO:H:t. pΐ ]ŬxE-njVRjU%AEQDXy.XP6a8,mtv=K:g϶to%edutWч\y 49S.;uJVęilC_zJbTJ0yz4ĩ,oR/2[U)V.l ,5zEu$QWY39*NqG]C.ƅ--2fM+)P] y%]vcaȦa6\P% gߏ48JpLّPWd]a5s{zBj x%6όzϋ6ۿIэ{vf \h-m) (H'wKE ȯ1]}\J C|6f-)^<(WNǥLms!,.ʤk3Iӿi )@sv߮|/iN@c`H1.ǎqm9RG.`pH*\0-]9My5K'W1n#DP$27l *pI$997K"Gd_$R'IZD %M|?5*vM#.\뢸q}>P\c]VոTOq>5fj1AWOtWOܧɧǽѠ<Qzvqs4l!TlTn |)|OS3)/0s|j4u' ʚP]>eOOSO|JS>"zU֧`O|f:-])W_]>E]E\>ztG"+QͧrUu6OƐͧvCpS9ל3qmr<7˧&io4V\_Z`T%x2Ӈ?7xt.-V{@9jOd}M1h܃Vhj, .A,x V7tRjjZ=C1q7n8_EJ!>-kci7.GܜSuk9kt5+ZE@t9g5VUtV| !&8U3_V`J˧\B9F e 1T`ODdԭ|jt3O)p4P)q*Lp.<#ηq0k#}oE/VfxE.Ov;}g _7bѝt%PpZkJ3rmp>ygVBS:u^&=H~bO,Ie?ȯ_gYf^ (?s@=0 Zƾ$k8!$Xzi' 3K%ހ5hę%"bc޷8Z9_3g@>$'PvC8 EYvil{~!sfGJa>sFM2Տ)ЫΌ\K_3hxvT*u-NFBڛ`ٍKDxo8HxP"y+_zvKUAB5b&0ΏȊȏ |]?C6gG/n()5 /Hj%/% fr݌<+>Mb|  $t{@hB n{ 96 S?PK!<,docProps/app.xml (AO0+ܩR!@S# qR-{X8eohčf_ )>0D캬UYNiۭ˗,bV ,<1daS7E Ɩ& HԆN-gBPɰo>oM9_|mshpF$sP. &i"yjYtX *U l,aӋ d"^] pR$˟ .6OBj\l >tY-ՊL@u P![{ya,ސ ^7%"U*Q6%}y.ysbF/;1֌uCQ$^F(TKDg"Ivyȇ|O@FOq{񾦼h*h ǡU-hĠ+L ךl=L̕#GHO*i z*/`:SA梺4 aHݽڟ9G%{vg}$;f#e6Su96|o_C߁$XE)+ rAf]j8(L9oK.ڜQ5Tɱ$;9^EbMN !Ke|9+ I.nk12'f1` S JPHk`.3 32)63\2v}oS#x uPRʯ53|4>"dhg녗Z.v)K>fÂ)=/UiL_kf @bՅҠt? Q4]/m21GƂt#ter·R$6*]K%i4"vw.k& H*qR-[Tw*O~"WDP8YOiUW73*P͜NiTt^9]F<}*NSۤ6UҥBZ( NW7s1OjӍBj8tZ«c]/Xnۜ1-N\4b&տf&ʏnWLLG֝uFvUv/.rV) u*u]gTkRٹ;{ן4] }IO9#ͩ|*.̞Sa剩95 ߜ)fsoNՄWs&8UNs~(\oN7~ҋTЫ~ՇK xd%摕!M5!F۔n/PK-!+G[Content_Types].xmlPK-!'  _rels/.relsPK-!y |word/_rels/document.xml.relsPK-!eP$ aD. word/document.xmlPK-!!Z!*word/theme/theme1.xmlPK- !9Y<1docProps/thumbnail.jpegPK-!yxgzword/settings.xmlPK-!-| word/fontTable.xmlPK-!Gqword/styles.xmlPK-!=Vӱ\word/stylesWithEffects.xmlPK-!<,docProps/app.xmlPK-!]y,docProps/core.xmlPK-!ʳCs!word/webSettings.xmlPK-!NRKN5"word/numbering.xmlPK(CGNS-3.4.0/release_docs/CGNS_TestingSpecs.pdf000066400000000000000000002676511343724673500206570ustar00rootroot00000000000000%PDF-1.3 % 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream x\ےܶ}WpȪ:\SF;K{b~Z$U6i?^v~/9s vsIN92>-ɹt0"$IO aR.jBz!Hk 4iWLqFYۡhדM%GwHF(}HhRqdS W"t1ng WVb  Nx *ReMGl>+;S qvePTMsƸɈgEc53mVBwVy@BmuW NqKuQXVА^ HHV~Cq8n1tB{Tw{xW XĐM:WOHL#8=!W>>9'H"N+Ae2βCc&Eʎ1ٶp$q hnL){sÇ (ZVV,$u?Z A Kvy!!Ud)̛@J1U?}4x^#62BIUg)2b>pO4t9p 7-+!GTi=i4; +_MLiQ"#׽ov/7H4S%ay# tu>}cÊ-I Զ EE-C |3ΤҬӁ69?.M[a{ }jnpE]Tk&B$%YF:+l <;[R_#BN&;v+\ԗۗcVuvP~" fn$=d]W51Eљ΍7b{TosDp6Zt/JH…r\i9낡6TDf^!܃.;`H[@ylv~u|"tAy 8jֆHd㠔jØtjYZ}/ )j,=g+'dMx>2>u'㗠INAA7;O7%ʲMe2ay/np=QCWF[_T!4EMMfLťInZԜ T_?Z!}oO[h{֘S L+k>s*2 pIk0UDKk2`}ÖVmDyjዕ'sedqPˣ@Y= U5b]Xs'ЙS/gF`GKJGOlq>c+cA.DelhLciHkb5LĞBQUtK% [\{1+ِԬ'bRɆ9-YTh A9p\ \QJ呧b(X]Kh:$6#QP~?2bzv ' Tؔ;/1ۭ#o bKI -yщ]5rՇT(rM"G&)@3<7i:=쿑Y|B2,4;t™Erc^^SdB}=<啋֋j6`X>ѢƦQ5+D;Ȼ;yx-D, aM@_5H$Ξӡ4/\&/kF|TEEG.₺sΫ3ZP(G8pޅH@߲m1`sX EGS`;?Ol'EsBvږ.uG VQ?HMY+]73l.}ϻ}ftߺkXoPjRZt/#ž4Fao >-?z#X!6 ZY^`3_U&_ &ӢugD7f| c>xQk,!kVx!%fc Os|,B5*$Mx@nS*>M9֨ Mo^Hi[*xu ,7hyqPﹲwFmCJxF dii[~9?H pvXzc{_/ۀ$~CS[UUQ* rke-HHk.Ǚ#wZPCPM ,~PS*L8IBt#-JM Zk\6~ȞV)QO7$S]ov7 @&աL: {п);j%j0 .ܫrxL !5/@"w=R:8^GK|"iwxkm%Dw4 !q#:׀j܃zҀL\][z4} (};9<[r22 x 8*iySw|Yc[[:=sc6-wƦ"MECsyľ<ƆQP2i}Xu~ endstream endobj 5 0 obj 4722 endobj 2 0 obj << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792] >> endobj 6 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT7 14 0 R /TT6 13 0 R /TT4 11 0 R /TT12 19 0 R /TT2 9 0 R /TT11 18 0 R /TT9 16 0 R >> >> endobj 20 0 obj << /Length 21 0 R /N 3 /Alternate /DeviceRGB /Filter /FlateDecode >> stream xwTSϽ7" %z ;HQIP&vDF)VdTG"cE b PQDE݌k 5ޚYg}׺PtX4X\XffGD=HƳ.d,P&s"7C$ E6<~&S2)212 "įl+ɘ&Y4Pޚ%ᣌ\%g|eTI(L0_&l2E9r9hxgIbטifSb1+MxL 0oE%YmhYh~S=zU&ϞAYl/$ZUm@O ޜl^ ' lsk.+7oʿ9V;?#I3eE妧KD d9i,UQ h A1vjpԁzN6p\W p G@ K0ށiABZyCAP8C@&*CP=#t] 4}a ٰ;GDxJ>,_“@FXDBX$!k"EHqaYbVabJ0՘cVL6f3bձX'?v 6-V``[a;p~\2n5׌ &x*sb|! ߏƿ' Zk! $l$T4QOt"y\b)AI&NI$R$)TIj"]&=&!:dGrY@^O$ _%?P(&OJEBN9J@y@yCR nXZOD}J}/G3ɭk{%Oחw_.'_!JQ@SVF=IEbbbb5Q%O@%!BӥyҸM:e0G7ӓ e%e[(R0`3R46i^)*n*|"fLUo՝mO0j&jajj.ϧwϝ_4갺zj=U45nɚ4ǴhZ ZZ^0Tf%9->ݫ=cXgN].[7A\SwBOK/X/_Q>QG[ `Aaac#*Z;8cq>[&IIMST`ϴ kh&45ǢYYF֠9<|y+ =X_,,S-,Y)YXmĚk]c}džjcΦ浭-v};]N"&1=xtv(}'{'IߝY) Σ -rqr.d._xpUەZM׍vm=+KGǔ ^WWbj>:>>>v}/avO8 FV> 2 u/_$\BCv< 5 ]s.,4&yUx~xw-bEDCĻHGKwFGEGME{EEKX,YFZ ={$vrK .3\rϮ_Yq*©L_wד+]eD]cIIIOAu_䩔)3ѩiB%a+]3='/40CiU@ёL(sYfLH$%Y jgGeQn~5f5wugv5k֮\۹Nw]m mHFˍenQQ`hBBQ-[lllfjۗ"^bO%ܒY}WwvwXbY^Ю]WVa[q`id2JjGէ{׿m>PkAma꺿g_DHGGu;776ƱqoC{P38!9 ҝˁ^r۽Ug9];}}_~imp㭎}]/}.{^=}^?z8hc' O*?f`ϳgC/Oϩ+FFGGόzˌㅿ)ѫ~wgbk?Jި9mdwi獵ޫ?cǑOO?w| x&mf endstream endobj 21 0 obj 2612 endobj 7 0 obj [ /ICCBased 20 0 R ] endobj 23 0 obj << /Length 24 0 R /Filter /FlateDecode >> stream x}$q~IfwUm5 Bweǎ ǀg{/"rphHLDEFFD-}ߟ:o^79Q? ^ꯇsφ}'o۷t;]p=<ӗaF7}~Կ{.H|y?Aw/Fo&<]n+қJ#Sz'L洇NEvO3'!^TS` = nxv#[ȡ0KݝA z82b.eyucY; 686 6&3]gTųp=$iveA> JidsߡU;B+;H2vux"c0l̒*Jï5}h3~bdOoN1v?y~MhWCGJ x.MA   w),h?空0РÂꮷ )Z5#B8Q09L|pp?ӄE75?AgbB~B0/0˄Ѽ&tC)3aD n(ЬucPn ưauCw=͈DA-"ARY~c\c"f4tρZڍmr ?h9`Yn'^Grv$Pj rrr!&aݏ%xox'ܔ784&5^*cJc+Ƣs-fZhmNl[hۖjHz*(*i9f.9^G+mnG1kܨ_"7ptbE' JsTИdg"NmqHŠmfYbjISO |-U@!GgiH zs]f}̉Z>;Im]mVD9z]! EP>^Xڢ#biщImz,Eun si}&T6 J_`ֈY%jkjed SUnQmp0TՆ Vql\m6`w+M7ؓO=ʞ3dKwX]C9tdX  ~n$*A ]4IUZDeJ(͕=,=ʍPʨ1B3KT6&mRYˆc/xm@# W:_˓gFKFX1zk2d~4X姝  " S̭Ci1̀ۙr KQ@vퟰB;0)U ёq!G28ZFE`̛e\% $PǍx N^X֍w'_5#) j4nWiA+ϘĘf$e@ j B3(,N$MkI4М Gѹ 96r;Yp.,HbN]+SJ)umr/ RyyPiLkibhhU Dv o ovR^19 $S! rtLx'y+@f9% )$((SP6 BbNi$ >O1e'ݾ#j]APF4'UVn{}~iN13ar(LpTnmi!G2(p.O9b9VIOn$!S>|La<\+A5'e)4_ziN)c1N:iLX@M ;kV B sAO!FL]1Ep鯙SrXDAaX4'q~@rxEN|"iBd.cP&CԽ8=M^f9jCN~+P:`^H-!JP7F)v"0(X+H,bbB*e(;Y^ytPO byQo 61 M'(vy8bisyٸA+wG#yH7f sk۴;v-pT1G-0!})r? [ q5-v}8^O0qNx-wѣC/1[cHV?+[o 8Wӭ?\qoәnq+H| u2vSߟ-c0|aA{Xvdds-s;01i!.=zA+]"άF'+ nvtM,r[\'<~c腟zy Uy/o-έЃE[1C9CG/3Tǐ>wk6:׸o  yppc腛yymk7}X];TDoœ=F+泸;C~թn2di%Cⴅ8~(yӡp/v"8H#r<+Sǭ_c5*p &C~<04oX%"plas/dۺ,T}.qǭ<& ώ&CN֒!G/ /fUR ^_nΒc\"U?[7NBvg4 Ka_m2[ɗkQ,Ӣ l'-ފ( &t 3C5Rh^V߲ XШ5A01- q8 4& ;_H\pQiؚ: N4(1Ma*o94<,V i.ݐA|i(Ţ*eF3VF= Ua^0! c:Q((Dݬ57.E޽ SlWIYU2"[1^XCʞju'_2m5T+e+aBcSfc_a' (hX v D/<ޑxzAZ!!T!7ar`)h!pK!A$n3MFݤ#)KT9 cgOOOn>[0W--B2@)>FĴ1 ;t|;}5S!C4v !结 SM9LR41S1ATvny; DNC{4[DBg gg'_$CBGN;st:G- oKXFgxۇ y(p2dգƮ%.5Xy|žW :5v?g sJkӿ֎d{XEG;HVm=ZCn{E]3 =UZ:TVb2 #{Si2.p@ R&eB11"sIC@$v86 &%N!@AQ P((o$ldXؕz;[B9h'IQ$I)7;q,<T cr }N!,) (Mr9۔B!HU18Mv1$9(CDA,^Q$bMXYe= i|kpŲv9@ڤecc|i?}tѾE4Z>EJOcRCuA n^|sLWޕ揥UˤEX,{^zY5؛"GRN&ڞ* Gab%{Y'[Z VcL:cMM -7f:[m wgQrIH9s-{aUy3簶ŢEt}45q}9:A~ak+[\e`»Xį,-xFQȚ>U8Jmg,1 yyR˓*/1'0{>.CnDy&T7sмyȼuYǪ(>EœDz֞w*&'';IE;`<]0 <͊ylV럕gl+/k3g!0C`_& G-}]1GN##$.h:XM fUb ste*rLח=vuE*ƚ #{6"ɗ>im0!>aKk[ٮ'wخ",4ڍ?4:7Di o>zp}نfjw9IlWHeh]5:%%oWGlO#u$LQ| |S?{ŗ&ێ^)Uu:خX V[](>=įN~ ,q4e'r:+̎*3h]k:hV| Y`늰:-|m7epj+e+*p2&U^狭Eu 9 uU!Wy%ۦHqh\wք9% X6N]9({'ke'+̸9nu5+״{y|"q$0(0ìB`_M|+Y@9%ɓ[aX~+yU+䧆R$Yp#挈OؗN|h_tRzH(hUO"l]R3W{Fb90>0۔Eb#rȕ1i!ikfG BQ)E,k+Mv#ɂ$F}lx4.3T FCN( IR (;y2}y|Fd*hKgdvidK![WAWOy8E>~1MI3 cW>/&ir8*Em 2Z+vwu٥[$E'ծYFHaRG+J)k4~ :a3Y{vbb|LXiT{ aC[$l6#l]a̿c늆DDOFk7S\ҹR~]aj QW|q NWAO%c|o[Ӡam3rkrӦ՘샦U[M|B'Q7\;tLOUZ3-+e;z3?T~뽕GhIMݛG|iІL{:` 6 ykHE~ $Qۧj[[J5J6 , e˝Ք! JK:'V㫩N֒;O ,+%5+f}#x|ZZn~HIM(78{SOm(dž[ijy+b<20R\-V}SII OJa`p8/7ĿC F[imuv/:y/RFbqC}P3$ުOw{V,WXnP6Vl_2*+'qkVZ[o>/(,M8}n%γ}@}G-rdHS/^&W3?~//ѳVZP5_dQ,j!U ɚDZY.+d}d)6NZrˆ=U{7zF1lQoQĒP e`&%(a[ 1>V`9f=)xPW +qXR`YIر@Ae`3 ҉"Hm3w cC`q`l܍kH9Ϣi y(oS  FLӻT$ah-VrJؖK*_qp|V ՜A1vޢoxw*`պvjY]8ho@cm)ekZvZrC3UN /a6jio2RfdL&St?1a w\GهX@AхFKSjƮc钱 Ɏv"Ό|;QzjҕjƮԘTKw-?m)gdSΙ]7=qjg~ֺE@i%8ȨߵEo.LS 7>n]]lMpkX~զA@vqaU-TkhX[*`Ew 4*O > i9zj>&ݥ^Ϥx|Nbs؇V0'nt^wT Uw%B'牍:/V&qYqEvq*ϩ(Z7&hrz0šs[Ƶp#X"O_zpǼ.2,_|ǧ,#I/iU/ԟ"^O_^>Ϝ"OM<  _dՏ=n>W!=je<'ɐ5*C/;V5ZJ 4mh_nux/4Y"R>Dyozee#[iP %zahVٲ Z-F!GeD5ѾlĢkebN*R,(ɦo3ٴB)J)'(Hh_*1ɕrѼ66a΄PqȇagO>sUѿ 04al4P64q4I#3*#ix$#Yq\ޓjhh7|?},gSm;L+ hI>A4j;fV%*)虫 &dYIsŅYX(vǺu8^q!7Ͷ '%K˜ x ))Jj}Ϲ\諚Q¬y 30]q~](|rw\խ$rBQ n9B֘@~)eU b~Ǿ𘶵fo ~l(3%mĿyoɓJR90Zc?[`P|1ˇ67[i.dyL_w t1_b=|~ncڪߍg0uAQ6LR lR`q3F I_@A ]d_F:sw_н?5i|{tx~۷(qS;AhȦC@7{Bs8b8ߴ=akskp`|"8_{H(F߿`; ??|oto?9O7AN~T>Z;ǜ7ƚŚ3AfCBrڿ?nt?_ש]~ weE]<{}vd^| U.p0xKl6TK'zl 4c_MWd/ ;ݯE#-q_hYMܤ0̱(~Op֬ls+Ufen$%q,(Sv6KXLvGfA 3M߼jd꠲ AWQ`Um9=!{kt_ d"Ceڟ\? HZDٜ3˜wJQG WViǦY2* A ))| ERUSՈ)wT i^=H u`=G5<ˊ^٘h8bﰧ_H5*nG:(*\T,::b3x;WUqAERhRP.aыT1-k=t;GdH®;2x.G,k;%)=V#K_zD7۪fa-L]|}SV| =*];(b1 Ics= !۵L}ɝ1C}%D!`1'Z@L;ިqb8[DbȅՃA~Ws?$*H|n }u v2 +3RIYI"bXJ:!!w$dX[WXfHyBs0&a'\XT&D$BqEV a h)`]0z^ #êX1 ]. ̂Jg M7N\;(aD'Wc`Ky RKtCD@v]' tזĆkx,2]fQ..'.fAeuLDd)09!.`v&屾1&2)K"vS M24_I!!U&_ 9QX.'q7ғT=Pٗ:ERHa&Eo(s&GW^xXTJ#1gD-N:lP$Ih9A=]b4ǵk2n>>hဳ=c[&5 Gg&j$Dlcm4iMMld L~oHS8}̦:#+7GdTk$iKU*hY)ZSvB'OXtrOs,FpɳCFǟƴ߹"R8CœH;ÆP-hE5ik[f/a;]e-ūŃ\mb.'μ,eX28YB^)b4gnةveAمXfl/ro aߌM;אJZP^((-,>Prog;Z̆`J ٤;H͚lcJQVaSB9m뤼\E}E(xr0P;yF iυ)GY6DbkRa R.9p(9*.8ohl|;Ʒm5k @1PM7wAua%5&(<$P&ɐ& O@SdYL@^|GG=douϷ~<~Y}()C$0>'3F$I $7J@|$`&7I.A$xSt}#i52I.98i'W-ܶs3tYΟ5ùAodqtmj';LդGQYkj|O>_Kx8DGBw<0-&n>-f{v?é܋w9 ܝ=_dWnYݜ!uk&CLy33si2م*Λm&Uw].*8GEP"å.c6di᭥ w85mXLMK;5-QkUbDZ yqiRMC)'JKd*e)};IZ4[ H+ I+ &JR%UR.ǥ[",4 ĬҨ(-ky/$%jArWU)H&ip0-F'iqX"Sc\´L/i'i j`99&/$% M DDvr(jr12cxJֲ_͎f$c xՅع f035ii3')4yrJT>,r&Rz`z ^paHKb ;o#⠒>kx9QpneCRҌyZ GypĤyt>d~=@5B%K uͧ^ ^XpqĀLpai6/J)ʒ 4;kjGs B|(R?bG?~+_T3W ?: &/^ҹ\Pr;.KqtDҚѯFtNO$NaT>'ɛ!_ 쵉T Q) /àk(K_~xF e#vuZ l7f=Nvpk`%>`8nU|ȳv'FNt%vk/zJa掏ph~FoR7W@/V>a<75|GFP|5\LW#jȭ(^]b3хhVҮ[}rB1k2ޏ0/\0莩}9Õx [@8 ublF+kB',h8p!%;ٕ/ۺo>%:0M[INW8,ϤB k>Uxow0&Wa9@@;B/r[@xgO#1u`{t7!UzXsT6M#2S7lxc܀= {{[YaRv]E4{@+W"e@qr61vA&܅6YRərkdiIn"pEv endstream endobj 24 0 obj 13351 endobj 22 0 obj << /Type /Page /Parent 3 0 R /Resources 25 0 R /Contents 23 0 R /MediaBox [0 0 612 792] >> endobj 25 0 obj << /ProcSet [ /PDF /Text ] /ColorSpace << /Cs1 7 0 R >> /Font << /TT12 19 0 R /TT6 13 0 R /TT14 27 0 R /TT9 16 0 R /TT7 14 0 R >> >> endobj 3 0 obj << /Type /Pages /MediaBox [0 0 612 792] /Count 2 /Kids [ 2 0 R 22 0 R ] >> endobj 28 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 13 0 obj << /Type /Font /Subtype /TrueType /BaseFont /PNUUNS+Cambria /FontDescriptor 29 0 R /ToUnicode 30 0 R /FirstChar 33 /LastChar 96 /Widths [ 220 621 488 556 531 430 278 338 414 504 264 552 490 494 552 547 205 441 832 563 611 681 496 611 488 524 558 271 504 382 554 382 266 332 653 555 593 537 483 205 303 324 537 774 554 687 662 554 554 921 648 221 264 623 554 568 815 571 554 554 371 575 554 500 ] >> endobj 30 0 obj << /Length 31 0 R /Filter /FlateDecode >> stream x]n0E .E`Z" )x\,sNfq\p8w(q-MffC;252wmwec5f 9wCwre9Β<]Tzujyooqi϶[צrKuLnaKw-~>oƏbyk9[+*J$xLG$$WH ZH@t#ArmT!i5/*%7Hԓd|پ D׊vHz. &(X$*JUx,mTURx-od# KI d-WRx-n~E*pīQU0+UxD5ɀWAeM=kts%`Np&1n оs,p3&Y fD1'(I ,Xe1R59TWsdoĜ@j|T0Wtsc5K "c!S j-1h1A(2A`RAAPg W*D\nEtCz8Өx[ endstream endobj 31 0 obj 649 endobj 29 0 obj << /Type /FontDescriptor /FontName /PNUUNS+Cambria /Flags 4 /FontBBox [-1475 -2463 2867 3117] /ItalicAngle 0 /Ascent 950 /Descent -222 /CapHeight 667 /StemV 0 /XHeight 467 /AvgWidth 615 /MaxWidth 2919 /FontFile2 32 0 R >> endobj 32 0 obj << /Length 33 0 R /Length1 24396 /Filter /FlateDecode >> stream xy`[7:sVKjmɲ$۲->eǎIv6;VVHb & a B IJoC0J(R x|s$9 {~}9s̙ggi՛"< XGOܼё6l!DuV'VBVm].KHšKkryrT$i97"JVL/Tr-?ڱf`֚EH^O{nܲd#6])DW࢑r舟`y\K/gKi"v6 B۽u,?]w?~K%zH|Я`K??{J'WZ)Up!U2U"UT|iIp.U8U(U[~^nNp6Ux;Ux-U]jTTLRp(U-Uؗ* S]ͩ¼T/UMzRT+U*t SRT!*ST8UP TA*~.y1TLωb/bzVL*o51=#/b91}VLGi1b>*[t1ELtބTvv1&tvi6AI# E< - ,?* $bQ+ B!B!B!B!B!1u9Zu9Zu9Z9"o>D4XxH\7:c$eui7=ۀ816%NtdVAk-ҷ^Ʈ%ǩCv\!YĶ\4d-ƹY[o-Yuכ]o{w(ouHVEr5;ܸ)Ôl%+,Ya_|x}mfs+ 8DnC>5s=!HG(I³#>H?pz"EHoKrskeb{Bs֝;j~]KXܓP[OlcJY7Qs;BΞ߁d#±YmFoJdY |-7W؅kJnf)[- gp3Yȧqӹ.RM i2 ^76~\?Ӹx*t=-Aޏ#_A 00 "՚9=u=uTkm4V8nq9RUʡFsM'o&䌍k_2/ƒR&\S"E(!j#@5q:ՍYO kɼ2W$sG2/GΞ &@0p:0Ҹהd"}+ґ+8%&2G@| FsT` ̱9 0(p߅'`F6zEl@&P$LgN)tv2Hӷl2~$^~Z )ӠlTr"L4Gu-5?z]\[TTs%HKMK^/%)VxS|yC*.+>X7fL-yuXNu='Y ȅׇ@vPvj^qtǰ;w0[n Ki0aj2Y+M ܤ e&e$ x.|u\\<^MW[y.MKqjT'uUxc04Z&WyT B-㣹늨ZXI$oDWi'I^~r3?_yD$UQPt<3ݤ$ k/ >=wgo^*වg/nvvnz=n@`*0P @1@ Š?G?~=8a{wgCK/DOG>}6:}:cGFFDGD;7E;ۣۢ3]ѶhST&cp`t6b2>1bB$2W#d|>>RO'|IgpD7~.<$X]6m,g0!OĚݟgwy@~Nn$?N1y g/H"J h'95}& ^OGO-&$?BAёd"ݟ݉\MNM)诞wHW>oŷl GI Fr@|}18YBP 2<({(SՎ7ك6b}"AW%?-=. ;K{N<.POAg@-Ar;udF{ ?mJ+?Ib`]W6B8AnV>!_E߼:H܍x ل|9`SpnpPD5IyZɵh=E~Fh)/+}kjt#1$> x'ďHDxT/͏_oɯȻ5{";ş?Kd3'$r7{,̐IJ^hP],&WiJz/Xw3lӝdD[]py}=gvN65(4ׅ'TWUVʂiIqܜ,{j12NIWҔ L*(֘ee99bi;1b;]zG[lb9Nޘ&b[w-1)XK}~/e68;nʀ#u7ĚapjjTjg/ҙ=e/-e|iÜFGtնHd'wbĚ?`Y֡$F1yc |{oAKt%_E}teFqUZyIx 5*V;NT,pQ|6+cž~\ w [%4KT|gL'XbdxS:ߧ{buݱ>Ta09Z;Fp#uEK~W=v,{vX:O=;?b]`##C3z.dm ֒bH oCg-+l=*2G3 -^ `oJ#'v03dēd=KDTA^-+# ؃~2O,w xwY3fGFZ= mXc G1-f[( DzU#bB!`@L%-u9FXrw,çs>{%3{Z"L:ђk;gCkZfݙꘑ>,N(0<&ۋ$0?2r Zr\#u-Q)k/"n8ccUcjrV۝6"~;s~ӹ^ dw2Sl=f*N -Q1 0ٙIJ;JQx E'N'ӧ==kYl?A|gwFSwLٝԝ]D.ma{46 )@1α&(qv|1O|sDr|1isϨ=a,)ڴ!T+($C5z [qsB-#I-4e'T)1x. \P]{ zanezӰ.XL0^{s;C,8Zchz~f{ hbO8=A+EAoۻceDoI'Q vʕ'juv/X!VQ;L6 e⽔xZ1'l8dZĝnmmkYq=@wy /z^ϓ8Ab-vM5q A l'BĻBDWK4B%uT;uD a>[az\`z4&t\߻|vՓ?N9:ZSX}oHXr8NAG]PbLsnǩqX3Θ=:bR̠ՓcClLL>SLt&1%zP&{@VLAK,1`#r8jc2ObR{w*;ޅ')!k|#t`YF1f fu* ,Ĺ ⟕U^!/^J6u1F乌@jgc. 5}u3"EWq;nx^KfUrZthOumeJb &>H7+b`8߬MGF@^hYY%) >P^"([_$2{dd\# [$Qd+woZv3$PKAݗd+%Y'y4IO%w #+*2'N$WCfqN"H1i̒\h@ NfB \E% blĂr=LضnCy5L?&8}֐:wn\$!60Y vP#M!%$@I9"ĂAZ8$8 OJRCH.)#b#e,&Ď#N+ړ:RK2?Hhn6I5 ngzyQ.AH[Yl\!/XѩxI0-+1vէh?hJ5* F.XLM/ s*A),ٖek-YˬOزmg2 { Y r!MbR JKU咊JR Fj- L yL@-5~|tgtg!ݙ2_hEy=WUW{\yN p \hxbrUPSπ-ȷ)÷4giIn^fwQո:ffܘSj-׵8Y5?Or륒/1d%]&DJgT٬yg/H3ss5BH ZtfzH52Ԑg%7XXg &EI(dA7Xjn(U^\&3e-&'hSEC4ʂV/5gW҇VwyœOӬOVu%~tRU![J8EJd6UU"uv@v _?[ȦG"W jՑow:"`ȷC?[dkXJ|$Ӫ;#T E ` 0ԗr gq LnJ. qRΕ'PY%.=kk}QzŃ;=y{yL_>6hip҃s?ڼǝgwmWipc_700YkK གྷt:-CkXdXk W B҅Lp%X4f`1xIɸ4j< yi3goBkODZĪ{bP=ZwB "U!L#rC~,1 Z,nYw|cp6wQ;(4wY-s\[Kl~bR֧Fpsv /ܯ2q9NN?/\ty1zIE9o)-0C~)‚L޹jNm<hmwf}?ϝ,[ _ؒPXq*JgF^Jv=I8ѡTirs-VSEA@_H+K湎DuWZr$RKya`9t Ywx*ʬȨ$LF̱}Z_|WSdlbse|Uu6!b#2vBM Y2'EY:;?ma!>{Z_49 1NC z],iCF5JS(f^Kz~(W(+Y9G"9EG"E ^k4.Fbe+I+b`k =ߤGQSC\Xr<GeA;qdGqzzhG6(sRK;>^RzKڐD?iwc>Kqҩ&[E01pLe 7X?TXd0}kQqIbW.!-΢4[Wr;2;Zs<Zg&r}& R\q$"7##TsqcR;†w"}:7LDSrj^l s~Ae3[G">MyXp`ec\i9DRЙcXqq[ji&wx޼+#6:0=Q*c*RaRMPl[#t7 G";mr+qCv+K"z#)CIh[gЊNӺw| .3_IyP4 k!xteeG"Yr4K,BQi*CŗІ0 DfKAEdz]ΐ53ӥ ]J-mcr)tc.;W]Gw- C]/} ce^ 3`,>kRjo H<wCdTgfH۷Wv;z⿯;O?N=^T[T8oaCog{41ϲZ,/de%4VWyy\Qu(N3,hV6+[p%?L)1:m;\[qJgk,ZhQ]ikNtYnY?gCk$"NAA_2Is$3G"I3\Ǎ]UU ݑPý(N-̼&E+`Qt-qVyKyD\!TfOi|”}S7[]8{ B`pW5\͈rO[F+M-P+m8:-[`Z[ n< ÂdD%1I7>aJ4՚ϗdHx~hdiXOPqN @\BXA0 &`,9PkG s8p_pK!liNldݒb=#jm囷nݼ77MݿzҺqY8jЭӛ6=23giMKµko\h.+ybo`yraͭ WWXA 6Aү8lDkc"\6bm;krMghaY}~6鄫JN`F' ~fJ8$rIR TUe k\jgcyxN|$]ׇ%P xSa4f0xB;42ATFh\ę4hE)Xaei =pҩ+'guZa1at,<q>h#0_7$6a_@l:`ALn{EQNTNNsA %cDCyr%7rp`Pdq%ǫVT\zG19 2:X0%&RLw<ku#F& PN]Oߏŀ,8 T/4;nI}dNW.~(Y~=*,|}S~I R דeBmAJ9 _/=qT3~3uuIYZ+U|AAX~/]G_j2?HlU ~0ku8J{j!R-)Qj T*/[XRT* QT]UTR5RTRʗ>(Ha cFI gd61WtS/ޤxݽ61#C3LUT ׫hX++!u@+"d޷`=B) s$i ''>ѡ(wAP\0T 5Tph7gzsizSP0-͋$S&]zC˷TϜycpMSs =-_QdkZ*hAzd.RRB.ݕ]tsh$dQMFt'+-6+RFc.64$C ɕʽ0IG,Ёpbv`DHZ NYrS[k n>q6L l~5]|.mor~Gn$ S+r _.3>vMi+3!aNrqX!rĠ38 2@jCSfZ\Gs4: t4htHwgڐZ`:7Jv3 3LDwLX );eMU -5isC<ŝ3ؑwjxHSu]sw= p<% c:hDg e~ϐ+Wrш(hڰ!#w1V2vVI& k uK'wUy$ u1Ke*? VVh׬+k.Ӛ lÒ ~?>mPqftYrp.pnFsSNLve氝!`3K̼lX iݔ2씋tPM5b-z@2 t22]3wW&燄:_U߰dl??6Ru`MWɊ#ˮSk]/nյ٫ni>6L.}U#  G# 6'>-qǨ4ڨ`s9Ά9ua+.'uSge3~ &Lh΅ʘ'Ra$!܏0oU7i$cJYeݦUPcO;Hse(F!%ջ'& a8J;ei$yansכ+*yŁJ̭WJv&)5iu:SݸNu:E}rg0f ̊Ϋfwmp!68#T6|kkVT_H׆%l"ޒ`gA}]VkPd$G#6SzkuC]V$K}^q0=\_AE3 & VG#0Hƣ b‰2$DzK^0]j)9 "%>+Q)4T:H%]R(B2=4}h+´… Fj*m5tʒ0~ =a6)n"6~6w'(J!k( .PJ TtaJHER$5)S#1:`FT":QDk5ζgtc@u@snS0ўW)h.+.l3Ӫf6:>Os/θvY|ZQuɓsL,yu":8~KM8dd3fi(8,aY+e (a%>ز8aAM G#b6rX/.C7uz:5S 5$ +v)`}@+3C!>tcpi0Qhn &g/XBB{ZbIBPF/Q#4TDH_TqE 1bb]'\r ėX[Q]srǣOZ7+gt9s^kV1}mueICG']o7:^xvMk/JJ8_zIT1۬X;[M,9j(t .WHlF2m]:BQ襆ᜤdiEd8y3?#ęEiM̎@>T-\R_oOnCt7wV,j Ŀ?[nyl!Zi,H̆ә]ɦmsKl*7oVsnuZc)]~T)Ug|@0KsTVTF Un8//Nx,,:V'c, J,ZbIx#ؼjxQeBlAcMŠ~sxjU"Oגk*~c}JGAykzpKVGciWty\@t +bӍgAW{[r! {j Qz1.:mvq鸿MfH_xZrp.(f cςïA*} ˗B{H\ .yZ h^$~E@6jAz&6b&-l)@}Uy/"yKcLx8ō̼|:3ykfi gEU+/./6MfQ{nɑ*ar<~U 䱽x]% ?@]f)bҔ"G)^e՛WK\'w(L ,љM"vNExT.7cQhNf1Q4`} `Ȥ,p6aD`*:)oSҫZ|N5'Nڄͼ ꍽg9T&gWѷ })]Ǵ{N\Avb4]PqJa/#~_X$AzL ֍Z89yrw#VGu1yT?"c&.6|36yB?x]:⟟C~;yg \:wR-crd HlL<ΐᕈXWo?Pk5xbG8D7< Wg07<@(NQZvӶxɅ }~dt>Vtr<Ѩ߸? 􂹽uRZzsiiI[DZ{}|&ΓlASNOʬ;z44Wk'c^>³V!apBW`8?ax{Wz?N& 4(B%AMNԑːMzvD3`ܔCbCܻkKeŖ?kr\zC+0޹U$\͢3^_9S)(>އlT>'FEsTҝ&SbT;U2ٺΥx=AI_jD{ǮZ@]S=G-O6nOr3Ю2ByN7a4fRS#M=U(-ith%Ģtlaz/ LOӝ ;Dz.*d׫dTZ;mRqR}^}++p7vRK1,BlAif>|-QJMZ( RlT.s5lJu6gӥ7ΰX>f9q]`FljX`*lM|>;uCX|n ;n;~޸uk?{T2uzJ?VPSۊ Mքwntٖnv!v{KN"lzuTm|qc}׭Xʁ9ŵaر]Om^ps֛;TԱ^sEȜ[]D)DȢyg?;UɥiYRL+d^i{xKéHv+V{8#'%,+̍n Qᬠ%'`) ࢜^o3Ֆ95S#k+]2IZ|xrp#z_ÉjtLa=O)UK3u,b+xYmZu6쇲ZKXF=Nl̯y/gD'su?hC]W[^y],M6tcqOnWS~RV}X1vȡR>]>ﺶZ{xfH$TLrp8(\Pfb7}-^o:VQ-[UXw~2Zj(=\M3ca)&4K [~ kSZ۟\5˪l)ۇU9Kgnk2}ʒ;jztbGK_βϟqUkI˧4nٷ-| 4^: {7=FrR.ЧPSBLJ\)Ky9(9=ʄ+s(z~~3ڞ==gБ>2x3kfV/zn[ endstream endobj 33 0 obj 16250 endobj 9 0 obj << /Type /Font /Subtype /TrueType /BaseFont /GMYRRS+Calibri /FontDescriptor 34 0 R /ToUnicode 35 0 R /FirstChar 33 /LastChar 54 /Widths [ 533 631 646 459 226 391 527 305 335 715 479 349 498 525 452 229 525 799 525 229 525 423 ] >> endobj 35 0 obj << /Length 36 0 R /Filter /FlateDecode >> stream x]N0E /a&}P)! ؓ:.1${7m'd2]|pNL+>dMJ{ЌYN| `*3&%8ųC+׺>fvvqجr)f?yÍȘ}_ ^c$6a/Yem]=<ԙ/tIh;Ĭ*5f6,,M[ᶻ/fuv^֔(@K8d^U]vjT\\jAyQ"хL:aփJƥ"iNEIT%͕W"TaփJSA36} 2ON1_~q@ endstream endobj 36 0 obj 373 endobj 34 0 obj << /Type /FontDescriptor /FontName /GMYRRS+Calibri /Flags 4 /FontBBox [-503 -307 1240 964] /ItalicAngle 0 /Ascent 952 /Descent -269 /CapHeight 632 /StemV 0 /XHeight 464 /AvgWidth 521 /MaxWidth 1328 /FontFile2 37 0 R >> endobj 37 0 obj << /Length 38 0 R /Length1 20284 /Filter /FlateDecode >> stream x|y\Tξ0; 0 8l00 *w}lf5iv դifim&mڬMDysŴ3e^F׮$zH$YJ"[av"B V.\ -\q P.E&|"8-S-[s菤`.|.le`ZYz0.t: kE$Z@e"1/-{DTutϷ/Yʾ!8y-%^éӗkP? S Է!?:u@\S$QV򌊻kB#..vrq!;6.r\lb#X:.X.Vq\,bK%\,b X \sE/=\b\b⢓Y\"E\ࢍV.ZE3Ӹh⢑.깘E\pQE\࢜)\q1R.J(梈B.&qQE>y\L"." ?" i\r…d.p".pqE,N.b V.,\0qŅ z.t\hpBŅ "$"1.pqS\|w\|?+.Nr7._p9q)p1/\|şr}.].\q6oq&op[.^7\ū\\xsK.8Y.OsOrsGr8E.B\fW/Yf֟}GF3{e?,g z3 XWœ/35ȲW<_2zqF`9e31z=I|ct(yY2zaFht8=4(aF1z2?U_r/{X݌bt'30Uv+F7h?70k]Үe\jUd,ftK]Ⱓm(f+Xk' Î a6a{Qh++hS1,Y 3ZhZFkXիYUVel9˹RF0Zh1+Bve XAF,g?>Fzg45]\FsXgu2.w& Q;ӰtNw,4Qc؎zFS.l߆ڰPMؾTUuJFFV )* [`MfTyT¨8l (l-AXZ%!U6Q,Q԰F)ՙLbyX-nF\xF.Fqbn bhFFvF6FVV (Գ:20R3RJS#L}n3~iӀGS}߷?ow}$7K_#3؟ZK"G?{=;o4.uaLsx7F5U ߯/AKi\~θ}ec4a j5 kGQ 0F~!&-[www܁2/p}+-7Q~3nנըon*]JB]+t/Rݻb.ؽ3#xm[V֦րU|pSpcp}pċ@Ypb>vHzH88$ CHC!ɰ6: YݺzjVd;vh+زh[\\ypEpe% . .({{󋻃v98;U3;m77l 6kxoKfzq%%T\'] $)'fbXaEثb%Upfd֙b^cb@LFv6G{%m[tsmۡ'mmՙvn@,XNZ$W͢$Lc&1`BvS;JocQR jbQ6m(EЋZ;Lz^ V[b@_Q]gIˏ$iwݨ@E JaT;7jȌuNH4NmCKC$8{N \5"!{Slf_gJh %w$t5v@ #Ѥ?o<[/f-lMh~l7 ^r5\A/q`vVɀ \ۀ`3 l!`-XVˁeR` X,@0ts9l f3 36h4 hz`*P5@5PT(ed("@0rl  H|@ ^ H<Hx`lfDF4PJ@Q9w  d@O8~~N 8 8|||| ||  gOww?~  x * 2k%EW//ggcScQ`8< <a`{{;wۀ[[π}u5^*J`pp90 \\ \\ \D*wv; v`l6 z`0UJ`X,.EB`0 @ y@70N`0@;0hZ4 hz`*P5@5/_/˯9!g%!J5d~.&{ȵi#nr g Jg6*tSc' *yeSxyc_kgFUVQ?cq%&Rz3׀VFf9d.&= bD,#ek9B/5\d%YAVdJ5!?Fl&[zٳ)dl#33? o$0fhMV KyD{.DFH"ѓ#dTOiciCgk9J#cR-RUr]!\33ylQ3s;CR/ K×,P&#'8Ԇ^\Xӌ fgW=RHx6L!kk}IIZ. >m>Wr]!) MS"ڞEЎ>OV&zVM )R Ii=}({kBĒtM D7ڑA#0ur+Cvo6$vq{\ykC鏔 Ԣ,H0z.o[Q?Hu(.zjtJZp5J .o`%9>/t\ mInS5N%uނS7oU!3iVy:)TW )(Z]J_%Xp!kR"箉}4^PvfW) #i,"%hhw6de$kB")h/:=!zCN94r6{A#<Ij}fJUY' <36F*$ t*bk&kJo]c  W,*46 {;ЗD?JL=U#^ҶpiΣfB3'§` 3̹]u3@gKע.:H4BH𖓐-ǣ\!V*ꯠ WQ[gkp\'watS=ccI/Nt%aJfw~FJЎ^z$NgfCYBZԠԀur:Q}\L1HTzF֐.JZ\CjらÂK[6HC:o bIT й"6KJu!m6*/lT_uB/[D2!=(m\(#$5k%xZM(݀^Qj$ XYy=Wǝ_rux&lqV{M^̖OnLISY9c_*6(=H79hӌF;hS:hsTi|=>gD ,G ,G ,GINGIӨw8@(p %9 :[.i #9) t,^otwg n Ta%)9mdFbRj Ơ65Unol3oX, A+ܤꬥs&3;q`mN1ϖ`ӤeM~jŖck)6E1[N^wPo7#.|`bBL&{$B2#2#t6"dMLeg97ωyfs"Kb&3t&"6-6 ֘ ! nYAr^]2Wq6 J&NbOI٘ g& 5[ s+5궩kڲ޻xK%Sz&4jWvݹfZb`P uu *lL+hJ&ẖ؄8o-3xLVEF]{U flD#㲑xytb?r">:$,/QQ0D Q:c;eT'b 'f m3ݡt#zE8Fm޿ۦy1:وvTǖ5uTjfSF,X~{Rdfߠ֩;,clj5EOolKvFٜV;)=CvuS^-` .7zvɂUBZ ݗJ /VBrXr"d?r猊ΖT/QdʰWq(Y9 ++_f-_a10"fʋ9Jii"f%NSbVz^[vv3c](Q02iJmKP4g6[բkgm bPM$݈~Q?z<SXQPy/Qْ2zIIØ)V(",1F10 w(*c 5P缛'je,^`ݑj5y`PȤq gs3K_P{:X-0АcPU(3WVܳlՁ%d-m\?eny2._Rӆَ8:*j X|覵G/YsSmuN\@@8L'<\t !\ t˛  NH{-`5c#I՝(v"3\OyhxWtW8IC^=_b%*ċJJHpx^Jtzlf3{5zR IiD)z3Omx~G=DJO-΢w `sqt)M{$rő owWME re&E &:vUCqWM9ijʬu !zKդtO_̿zݘtk[r*'LMYp4փ`.`b=H@ozI'rDto NO{OO;N^=B0IF_8!6ފ 8M+r3CZ5-got.t柄@!@=tm'!{BUȰiF! i40A2D!A,$# t#J :;ypg"Hv3c.GLy%)vT¦F/NE#JlQH펄0@AHzt̓WܵdkEʗ4,IrU,i_RMU74+)qgoI3Io"6p㑊 !_aG X%ԖWy`qi~OpRBΣisK dؘpؑ7n>1r(ͼ@ʸgwimY}ór xqT]U'|]S3|-T|%If'g8~x2[F37j)ރh+' iHrd,TTНDCe%lZ.yƌ!148O^zg=<T7~:/$*QhbRJ <% ƤBDVسܴUX3IN}Y mc'WJTҴ&[ey6f!V15dƸ 2]a\tq.#Eg1|YS&A  &8 U6t[Z-=C?as qvl~$Dӟc͈O&QLmn }Ou L$ q a^(U ON{Etǔd!%YH"IHI<#xIX$$QI@e RO #)!Iנg KoS-n+QN骨$1`l1E͂(g^Vcg^Q(cØM8~qIZA}( rGYVq]ět UQў4vJѮ%cc)hBsFPD95[HK,2>XgW*pVOjߋ֊aۢ𖨵%96tS=Z5dWk!=բXxqu-Q}ѿ{K]3f{.[ܾ endstream endobj 38 0 obj 10601 endobj 18 0 obj << /Type /Font /Subtype /TrueType /BaseFont /YZSCZP+Cambria-Italic /FontDescriptor 39 0 R /ToUnicode 40 0 R /FirstChar 33 /LastChar 40 /Widths [ 433 522 535 382 345 457 199 530 ] >> endobj 40 0 obj << /Length 41 0 R /Filter /FlateDecode >> stream x]=n0 wc:g)xH[l6Ԓ ˃o_JIS>>>sXxNa0VB@kj<+(ܮsĩ!@A96joAc0v׹͕v'84k_ m7qRs4%Hi}0tvD&8r gշ@?;R$Ώ;DU;B!&ֹHH"ܚyO$rOy7Pxe/OV3?;VZ endstream endobj 41 0 obj 270 endobj 39 0 obj << /Type /FontDescriptor /FontName /YZSCZP+Cambria-Italic /Flags 68 /FontBBox [-1105 -279 1222 1047] /ItalicAngle -6 /Ascent 950 /Descent -222 /CapHeight 667 /StemV 0 /XHeight 467 /AvgWidth 542 /MaxWidth 1224 /FontFile2 42 0 R >> endobj 42 0 obj << /Length 43 0 R /Length1 7804 /Filter /FlateDecode >> stream xY tWy>վǬF+˚VJ^Ic,Y~H\v%%ٵ$[~%IEfmLBB1ګ#s $ -ڜ&(ήGSZX͝{}}Ό<2 gs簔>vy]Ӯ)Sى< װ^3 &,€+.X7L;챫`aO;XgN_5eK[zwW0.+HYeV[=`{݅wzĽw;?|.۵o;wmr%NN/=?^8e~ OTX'%9*}j"8~-Ԅ^()T_/N>\?sb:Kv†ʠ|U0qr έzLrmNQvy7\.6*,+8cDy^vS׏c3~lf$I6F[;HLHV('f2Q8ӌ jYmnlq#nk64b$&=1DmB8t.BXb$zt#X$lKX7ۍV{bu_3PVnk[HWɶj^Qi*]pXEh:g5P[i9 n:s5?O?jX/NHʋ}F[;ubXo&6c8U bXu*&*bbsǜ1{3"Ä:uӈ?KCY!F.NVhj2xڟ`ZQD.OfPyi niC$yZ9D4d :|Kgr}+H1BGp7uCb6;0MX?ꗻ7Z30Jr7P~; E?:/kcRteO0>aqgA_u w,]a驥&CZz2r+:Oi`؊v,,KK]_@5<Z =҅V`5 r K Ex s2?7f9}6$tѿ|8p|.u1UR9 G,ҳpQ,>x$<' _Ь9(֢5Mh{{ŗF@ h4!n_C_XJ:"à .Rn̿wKX/5=ySۇ6o׻'^vuv֭im475CJU5j* UVRv8VlMF^sBG}Tr-g0 Q+b@vHpE ~H́ڞV- fQJR]/ycv}qEa? DC^Ga қȄ@C)ZLhܰȋ-Brœ4LJ;:KbF F0%w()Ľt99\JрrC)GD Ec2LYr|wY0WdA1,戵h Κ\;ǁs&YCՓl %%%xQ-6'5ĩ1i7UNJsܩyvd<KQ>>e#E`LI ƌ'%L7w9]oOLMf@9 ,xfԡb^|OD>JԍA'Շ\Rpnf4oЌJtz ejZ=Yt0Ya[ك=uXIVOi[C{{Sr,L`>xk@*c.dKN2x*2Ƅ\OZÚ pF5HXT$i18o.EPP*`މ\0V<Q/KR=rO&둥\&_!KZsI /iϩ42Sdf!6=n^28L#MeWh"^\9~s9g{+f'QaE*mOaL 톱DȢO8<,8H ;Ӄ<-yP 1$ v&^th7{&779deWW]=1%/rL[ȳVCz#3fNTP>ZciIp`$ӋS$,K$F*yێGLo2퉩P/c w/bSf;6s! M1Mm켣i7\OI0rIh)!-22{~L GGC{+և>ȩZ\Z;ZqZz|8U7NZ\}l+7WP\ĆoQ>-󱻢Fݬ4ٲ{<9@[ݠޙq߲CYLN ΩĶE?N=.NU,uQP5.ǸT$F@?ўLxQ֤:J#0/<OX㐧T .1TH=e l=[ɝs3Xi{k]UD!Wus+#=k:;zUe;~z'jnqzҿGo_oOJ\Jӣ*xJee:^wF-jU!مcΎ%//><_V'|{%%K$LH8`jq4i*YE״y `x܏9wX|z=qW<}vcDӋ?8QqMercTsKौ&~~AU2c:yT5Uy%mj@sٕ2—t|9Uw3X+X9RA6cH]0 z] aC[Wo~8zt_6vvhnD*{gv׫FS>}k$HN>70~i eZQ[,L(WKj$[SQR8,U e(= Fo< :#o<֕-{ CD"aa>0cU‚02[kCDD1*e'ϼF y9EeGǒն3:]cU5(<{D?9s>v~S07w*"~  V4Eko ~gvp[ES7S+Ѕi"ph %kCR>2DYZ]F/,~a1z%'bEgS pɭɵz;'mUq-uܻ[Y|Ri)rYD\^Ɯ\j7R qixoFLXio@F]=N&5k½]WM{x|2=)TAnyrGꣽ-'*u][snvdP;~\^M)Zeh۶U?$x^ RN"SRbr;=`2dwipf3 _6k*x|ϩu0[8l{Eq1Qmw751,件~"ƀ1y!;_?zjdϔ3upmEtx_ԶF&cvumccN.>Ɂ GUnσ /5:M.ij3mW#/Fz-bX:m%ݿl}c[ endstream endobj 43 0 obj 4964 endobj 16 0 obj << /Type /Font /Subtype /TrueType /BaseFont /XEIRGF+Calibri-Bold /FontDescriptor 44 0 R /ToUnicode 45 0 R /FirstChar 33 /LastChar 62 /Widths [ 529 637 659 473 226 495 503 399 347 246 537 474 537 418 316 494 538 537 474 537 631 630 459 355 537 813 246 473 606 537 ] >> endobj 45 0 obj << /Length 46 0 R /Filter /FlateDecode >> stream x]͊0~ -14ؒ("oޤS>]#/CS~˓? c 9^k4bU0A\4o%iLƔi,f>dk1d~uxblѶ&nҝ)홮'~hxe|]:Ţm"_WZ{X*Y|v;a^FdmZ,*[A"0 v7 knAdf-[=܁^=@u "zy~SEQUD iD HX F<ÑFDu'WpNNDU%CX3Y=wd* YEY5Y=/.Տל*g81ŏY TKի endstream endobj 46 0 obj 421 endobj 44 0 obj << /Type /FontDescriptor /FontName /XEIRGF+Calibri-Bold /Flags 4 /FontBBox [-519 -306 1240 971] /ItalicAngle 0 /Ascent 952 /Descent -269 /CapHeight 632 /StemV 0 /XHeight 469 /AvgWidth 536 /MaxWidth 1328 /FontFile2 47 0 R >> endobj 47 0 obj << /Length 48 0 R /Length1 19240 /Filter /FlateDecode >> stream xy`T}o>,dd&GHBB$U@dQ*ERŪZT& T*Zj][lmJ]jE}g&m!g>sϽF7 *p`]z"~WưBd)+ׯZ/ QWݲِ{b&NVCi 0k1/\;8Hs ѿn>-+gЊD:&ݍWl a$) /_7@pQ7ѓLjp#D=@g t'*>% >̎? ?PN~k(S)>kJ$p*8y̙s9b|_">1ψœc0}{w cN4w-XF*DeeFx:fy C"^A 2◈_ ^B3ċ#Co, ӈ#"B< qcyq( "xq0b?b"AQXz1BGx[ cG?#N">D 1>=Ļw!fcf9wz q"fu_#D3C1s5īW_!^~GVs,3ċ#r?ŪE iߏcZhQ,Il#'#CFB{A~}{@ { wCu+- 7r# ׃\r-w@Qvd'U ܗ)rqq_W7~qS&(FĆY 02y {9(lNزD; 1ъhA4#D=`‰@#;†cZf6xq/A99_A> ȧ | ȟA߃ ;߂{ y@~ ,O@y GA<=~a @ncύ!.DP-++e~Db)b уF8 At!B  D6ad!)B$]I  b_%q_s( ȥm> ٸ=rɞ푋E.ڳ-6s[6^`۞mo]ظ5rִrK="MT}~pkO>{Gኙ ۇ #TǢ=*mơȆ=CP7!zbrC}o\rX!A?T8$ 5F ^<{AŃp M7E~$у&cr7r$=p(bMpUdU{G"`odɞȢ= #=ِ`W$+,i Ώ̇`KdޞHs1Ҵ1H"| VℿΓN/c}>D ~}tb/:Iu^=[on g 1ittu{u|nCݤNWGjо۴KZ^ea^/hE :K# iFӦwi MVvCMTVSAmP9%$|Tp Jxp)dJi^3 Z)틢򨯓}  ˣ$pQ(WRnNW4c!/ݹfD3:wfDÅ.&dImO`Ɇ 66 d8 "(|0|+Yr@"3m^: u@ff ,hֶ?7.]No nځ%]p2'GЛa8bI~N9J~L&ϐg2#ϓc"wR~LEG{B#^Byt /v}k7פ}> y.>Q? czsbb>9{W$7fv_u41- d8S;,9i K{ h}''c"}|H>O?|1όjg3W99=%~R1r'NDz*CsZ UP%US R"򯤨R _K9]tB'i̗jvy3:zh&=fJqCfQ_Y,i* kaysi!!.%J)p3 Pd-i'ZrJ<+ fQaŋtG:to8nNlzVe`A~ߗtY zFTeR Q_msG}QX~uCTÙynV)@Ε_)`Na*'ջHUAtaG7\cux- <(᮷sGi>p|:RY,'J\*]?JsxH6G;OGuEesr.(\?2rU\O˽wG~(4׏\o]4wVPh>BZL݀F>=){>VOO|O Kd8(O^ham2.enư,sĈ D>r$bɔ}^l/wjkt2wA>J|eWx A :ʬ- A>x5L ѐw}4[چW[,Ѵ9Q7( CY01.oGAR{n@nHNrbE;J/ؐ:ZߖN/3B^iQiN`mʺU SƯ$7%#)ޖvsoB#7_YZ&JoC׭w7'/}g06-vvWA_~c+u*i-]0ԎzsaAeݗwu8fAZA7DX,dY,jZ1@v1U"F؀q (sO Nqa0׻gH_\ ] 4J$ya.SGQװx6J9i \7q=~ONvu{9z<0$,*H}͐o.>>A"0l聱4EP"Qh0sB7ЁbnMװ(i΀n:~vPH7 F h1ALjh2 sĬ)Q_!ґH$xJ*P!kU*?y(=ڑGU"4U& v v@Yj:dw3La*V$ C])>8rj;Of fq |5"(PX=2P_))B-D~6"!WaYEڤ*HT OH ?&s%-"4[$r]Nlsg\d$Uw )"Mp3t%:,vPAk(=X&OIL'o#YWѨ̚ ̐hܪyr .gpm4d ΓBfMK0xH5#ޟY>DC( 4TtiLXSa#ME@QcHmE0++7TZM2(X2mRfFߥKn^;c97,?ij}Xo3*MV).~~KȪ:ZRgSfetftE2ǝ4eߺ{|tO/F\ kAp} JP2AUǹb,Kނ,QY8FjXNܦSԜ֋3Vqi0뮡ca=j|v]8B KiIqK.8 DډvqN5}[Q;5YJR&/N5iZtjG_O^'Yal2ӥŹ3'ΊɓB fJt#JA Čkje嘡2\yZg!Xfc u&unj2^4MqrTd\{9gX8DfyveyNInKs ǟJy^ ڔ-`-Z_M-6q׼EJ*+C!4{";ٞps=TWKjt\3.Gȡnz8+V;wcD40gCLJ)MJ [^ZX?':M.xF*lX\PouUٕi/ *OǒWϯ) ΊlZiZמcW{&_IF7հʽ\&G V}V,5TqPO]a::~ 7s%52mz˝-Jb0l8*03*k@d_%ǢĨf8l*1|W4SXJܢ$;̈s[jK%>C8 ߖ3232y]+SK23%0/ Z5YUO[3Ng^f-[%N^ؒqo^qq 7{4G+•0Aq>`.4 Gq)s6@q:Jg. r ;ϚY[o:ې=f`^^ePɔ Kg/Yg֔]Z\ΝYkZ8CKVY^M^Zzf2Ncnůf{*2Ϙ8r仰\O`ν1ѯJO!6ۂe0ilA?R*&֤wY%aOtƁa95z: PP`+JJZT0n}ӕkS3 } uf]]c9_ ˜EuiM_hWRz1Хmlp9 e9 8_&IFq?ڜeũ+flk?v48n%ٰ2^~"ry5αoZrgONklR&>U6PV47`Jͭ+35м,jݬwI[/k,Zΰ.ߘ9򟒰?%ܼvISc2QpCf_V Va  Is v F5w{[[  {ӂf0;$vus2ܬ3{g.o*))<'IXvӾ3ϿW~/ZZ87d`~eL(O.Nk>m6߹}ΖY!6MͤlHYOZ0}es%хP螧od+oGaApBӦFq0ii3c5GԊY L#ۮ-iƻᬬ zQ QY:r Q'%'<4TB1(KepfˆEu]/H5..Eh osqSͼ6Nj>M&Ng2UW5k»Z{YE 6\l.kz{S+kD?}Y L󛟾wU󵜤р^plq;ϖ|kXԂS^oSf'lxP ٪f,ggk2ט%Wt6ufl;p0ɱVA!4g5#xXO xǙEYt1_4+$9{GӢmI㳛K3MLW9Stt>8RRO1sOC} l&|ڗa-0qzڙOl g&C&[+2sVjVpkDIfT4͛YDB/{]ڂNcTCJBl* A[ Eױ/7[VM5ڰ 2pdaNs:J`:ya349 jꆂyIG\ YpŦYeg>/sϰE$̄gA$S } [+X\|UCfYVp9*.wE|]{yw}ؐҒݳ=OPz ahW[U@ujHh>K}gdJw8aN8hVM*y)\28oe+%fTS*3{# h'Sgi0xNV⏖gS5{EwCY{r~yr;% 6E7V*&MΚ2N:|ysE<% msp );KIYTIv/ɞ=ʝ \v-;C!wN>D6=qYtM,N:_'˚Yi6UYPc;4;V9谘9)]t)CJ^;lS)(@_gr7]Lr \Ĉn 79ԏ;2%L5R'"]t[Ƿd#sǏ' xB6wȻl.8uX'd$Hor\`SHE]ƓwWNzvn/QGSG xcwAiG /j,4%)j* D2K|Z;ZgKvt  ) eKafحWuUs:T5mN֞cwyyTNgrYirդ{\ytO6jZ2Jf밗143sMAr-M>oc&aƢ8S _# "q=-HLJ@LInY8w**OoFcFxɣS@?IfiƧ36\I懌6/N|w5MMr\nmmaӰ*p?![*M*)<I-:sDdG-y0u`w q>&4OU|˂Z=Ãא';3;> endobj 50 0 obj << /Length 51 0 R /Filter /FlateDecode >> stream x]j >E[!eBC>IVhT&搷hz9?g&7#>m>nճIB2> endobj 52 0 obj << /Length 53 0 R /Length1 13616 /Filter /FlateDecode >> stream x՛w@SgƟC 1#T J  (pڭvi[:Gإv[v/׫E뜛۪o9IRD0:RF._hv\}fRuB=oiS^BJVP[^յK0oAywjK_}0 uYT6дS!a"€LX1lFWޱfU @AGY wo:}sSy;"hSv~ݩA 4; FK kYְfiaYŲere,KY,fYe|Zy,sY԰Tfbd`)g)c񲔲b)a2f2RR2%%e dI,YrY&dgbqddcqee hQ,#YRYF g2%!,YY$$$\2eE,,q,Yd~,,vK_>,V,XYzDDD` g cYYL,A,,,,~,,>,F"Eb9'iS,bwX~egX~d{XN| ,_|,| ,'X|!,ﳼ.;,o&,rUWXˋ,/<˳,ϰ<'YEE PSj|jIB>D֟)NQ߿QF:_G{j}Gq[k*~E%ӐϨ)>'(SGR)ޣxC)R{Nǩxu*FqUWhQŋ/PFBd-t5< 1AF1V ҥyM1J ^G#)RհhP܈jXb HQQFQôioHhz=B"E-v1@ZlEqjK)dZKiE_CчJћj5UK jANh!f`iAT 𣑾4҇F D!]e63 ۟j; ~Ag~D=D[ F+%|2YHS @8#!w;m\[!7o^7^௚leڋZ 5ϱ=c=m=em;Ob :qXBۣGl7>ETi2LͶ6J۽p7 vLI;w16N\vX&u#ֺ6pl`XoKdUASlWͶmvEnzcm1նVJqVV]+ۚ]flmm^^#/hkky2RbגŮ *zע&OSDSc&Il7Idi7]zϫoW}F+ ^ :7 XQod-t-pյ-pͯu֤vUvUV**\e.ojkVLWIL׌"Wq[˓vMi.W[ 55-5%uk2Rs]r]R]9mٮY.'N^1ZG"R`zGX!1mpDL yG=s,eG#sT۞L!s%gFJH)a?#ZZ RhhW!vbt j ]0EyY&J3M1,)ip0Jv ǂ0hG#Eڲ:$'J:- bjWHޑ_mT.IWz%CF_D7\%*-&]%= % M %+ihLпђnwC#maܬeh_#?q]u°A XVf,R,@h `! |P 恹``62`(3 P t0 @!(SA>Sd0 L``<N 2@: 1`4FT0 P.C` $` . 2b@_+ zhDHzp, 3&A~½P΀N'8 N?7+ ~?;p| _ 9 | >8|>6x 1*x/[+yvߚsf,Gmb;A[;gFyj{U'kt wF۳m8׷[ ڮjv;lַSC)µ-4.vھWk_rh#J>${Džst]xX`¡W ZU+jCZC[i*x-z^\V $QaPCyp+,N{vyVx[K=ڋKDR[R$yP X|ɕINiZ=~Z_NW( ӁRSxʹ7; ݱ/YOzbJ`~M(WZʽq^+3܃/!9J V^#9qmp-h(-œ=F;"ݢly.;=P5\D{bcA@zŊ& oetq|Dy^]7T*_diL %pķAXlvzkC*v'~o,G|i`{*{"m_ cטH1ILŏ 3>6}"33G"aLJ*B2>޽6r:iqaZ燝/'w~x2|dI)r2X Ӊ1G]?<%咱aC~!6tƔKI-YdgX)MK;4k4&RP7fP?`Dzy~DFńDEƄwr'ߐ>N_k=#_G^͙ca  9>}"#iIbWûwO gOIΫ)d]x endstream endobj 53 0 obj 5932 endobj 14 0 obj << /Type /Font /Subtype /TrueType /BaseFont /BBRAOR+ArialMT /FontDescriptor 54 0 R /Encoding /MacRomanEncoding /FirstChar 32 /LastChar 32 /Widths [ 278 ] >> endobj 54 0 obj << /Type /FontDescriptor /FontName /BBRAOR+ArialMT /Flags 32 /FontBBox [-665 -325 2000 1006] /ItalicAngle 0 /Ascent 905 /Descent -212 /CapHeight 716 /StemV 95 /Leading 33 /XHeight 519 /StemH 84 /AvgWidth 441 /MaxWidth 2000 /FontFile2 55 0 R >> endobj 55 0 obj << /Length 56 0 R /Length1 6780 /Filter /FlateDecode >> stream xY xTյ^{3$@ Ih`2yLFBdB &@TR>V9 (j+pj}hگ}j} X޳ZkYg}&K/md oˢN2rZ-Qc,"s5~ݼ7^X ۚ[cuPl EK[v9Rm^Լ<>>Iz]6iT@Ύ%Frdu.n3?Qҟv,b0t.ja4HV8}A^@Q ]IQ#nJmGI5W.GJsvldMF5T_A56v7b#I{Q\r; FIOWyr7*\=CKSK vBsD>6U@ f"PiU`'p0tsivTDDy'Gݨy9gK>2VxBiGd~ 6titBw8ð-M-*9* `6sS*ۘX h%0U!a(N6mbglj(#rz5-R~S(*o[(78&ewEUC)_Aֱf˨%Uǐ?^_fwc$[u|c=!~bxS*,4OuwTBse`Tõ>au5 ;"ubnbP:ܳ_}ۅ>:*W;&Ƽ6{` XɎgEYȲLRj)8-K%2ĚnYYVlUJ!Q#zCόf ; (qfKz^?k}-T?Wվኲ4iTXG-zV,~flsZ2jG.Ukr/1fSPVƲʬu?C2XQdym3yT z^^ ˾`g}s^Q5H JÏT91`,Hv ~%_B~ ¤_wp_mpdete.O|2Bt9>Zэ|.vc36\J.Ϲ7F>>)'s^ V@K |m@P۰=K U4p綴Kܦ\mZV.7$nj5mro\4mLc?7֘i?349$O*Ir29Vkw19>m@ =<)u3lF;Vie%yZZKd^WWI)iujܔܙ튛lPɳdiRͯujRy+b#u?{ŧykٺ^+QUNX 0KJEb('HG!9JDKH;g.sAc%Z~}#V8 ah߇|It.a]u24ew `ҸŒ87\<@w,ZfG@QV܄cHq'|zs,Z^CTK 6 ԀbNxa>@G{}OiJaTEӨ6D'[.먓tYߪ^WJjA9f.h;`[&/F ^ZL;lo1'݀9(4>Am1b+D zyHeN;h&qI nE36K6l*˰=*?DLHKBǘ=;LɦRt~(>˾+QV:yk72}rX ʮ#yO,&+FJH<)O(ߙOpGt7KϲTe] !sSyLyҌU_Mh=A_t6Mgbl[~ö#WF~-?#eҥjݴIZ/oȇ՘>[('3$6EeN6݌mb]1cاx%}ɾxr3G\|1Nw{Qc_) +&֊;P(9QEGKML;MLO35'[~w+?CSm=4o|MQ~oCY2b YrD6=l)vQzSݘ|,SQmzƶ= $*B1ImbQlxE'N(8a[(9R>ccSe?̉EQ8TXY[f[XZ[C4 xb'jOf>Z'̫9*pd*[>ܴ\tVq#/+^.z6QC!MTi*z^nNf+s2EpF3 #^ fQwDNG4d3JONq=%gGu# 8FV-t@VN9^Gg!<ՍgÙ0 l|EK騒H?bGSbrBjW^cH+@9m(U૰4aOۋ{*1,dȋ!v܅}BA3~vWiGiiî_j^oY#]G[Z}zE-鿙:)MuN/a]xEDy w´ʛ4*ߐaNsq` #L}4 ޭ׉NM,45[<{ 뽙xDG ^Dk)ޚUʊK'O?lѥ.)S8aNՑg:dpz-uPJrRbb6)3*ꂪj5yrh>OT.Tٮ <'ޘ'ibqsڑZe!ouT!O1; 9Ӊ/VXPiuþ`mqNJqմ%Qwb$HZeV0C ݜ)Xi.4E7ܪM:"մj$OJÅja4sf1Q㌣/1jAOrɯf<V˼飬g[sEؗ5_ZUNC >Жuz#T4H!t#Pi( N"g3kHUe.0 #?d6xo^8 endstream endobj 56 0 obj 4538 endobj 19 0 obj << /Type /Font /Subtype /TrueType /BaseFont /OTDYWK+Symbol /FontDescriptor 57 0 R /Encoding /MacRomanEncoding /FirstChar 165 /LastChar 165 /Widths [ 460 ] >> endobj 57 0 obj << /Type /FontDescriptor /FontName /OTDYWK+Symbol /Flags 32 /FontBBox [-167 -299 1094 827] /ItalicAngle 0 /Ascent 701 /Descent -299 /CapHeight 623 /StemV 103 /XHeight 467 /StemH 38 /AvgWidth 572 /MaxWidth 1042 /FontFile2 58 0 R >> endobj 58 0 obj << /Length 59 0 R /Length1 3704 /Filter /FlateDecode >> stream xkxF\uM5k,I.pKBDBRX4b)H #4yh TzZi)ZCwOyo33gdqmRʹF/]O)S^2wzi([!mbHjVT.YӢzUOӶT]̏[Y&af Uv`d[S[UQSZ9_!0rKË z<^c}zxȚ^=;sfOYT!+͒sFOOzV]9t+C&v騲 KH +D֔ CtL^"M^$?!/"?&I~D~H'A#.5Zq-W4>.y#xmdJh{KdޤF:aJP~?!#1axDy+?dgiْo &Hgjی"_VB3{6Q.dc| 7miާ' ze1}\51f-%rMGri٘wq}dAfp#nbaIgd(VQ%438%43l,i5OzyL\Idaor>6՟0l“bdO*YMȱr*YMbɳDޏQlLՌZg̕=j'&A$zNFzS";Y;x DƻzM棧ݬԼĜ`]uz H;KV}j΁ڦ67kNu PjS%'R;KhPHWNve6d7]k(Ac,u]=aH 'u([.7ǭ,Oܕy9OdʝJ?'$ia ,C9њ] (REZUWc+B/%d Cq5Gl1 t]@((gF1Ҙ_1T c+X$WJ^(ăU,#t3H Ed#HKS J.ǭE{h"@o+ B@$"QiW+W,!YsԜ6X}qDb13pf |1ފk IC+2*Z$ICf 3 uF${KHʭyc/,]gX4;7>vo0GylBᓇ{C{ Qc:Nwnt_x3ȌТWc6%)DFܖ7[/wu-;[LѹCvj:_+rd}CUΫZ)# endstream endobj 59 0 obj 2061 endobj 27 0 obj << /Type /Font /Subtype /TrueType /BaseFont /EGGCDD+Cambria-Bold /FontDescriptor 60 0 R /ToUnicode 61 0 R /FirstChar 33 /LastChar 57 /Widths [ 220 551 314 604 597 525 505 652 597 308 531 618 592 592 639 459 365 592 592 592 592 961 597 569 798 ] >> endobj 61 0 obj << /Length 62 0 R /Filter /FlateDecode >> stream x]n0> endobj 63 0 obj << /Length 64 0 R /Length1 12624 /Filter /FlateDecode >> stream x: `SNrNNIOҞ4I۴MP4--BBAR WQJ xu:/V2+Ήm^_Sy/s~IRqӛ;^lڸyҡFՃk# [6r6!D]|5ټBy+V_',90|BOh u>|B!/ONgeߑe_2~I'e!eO2#2> 2NxxGdK7Fo6xdIpxzP+l%v p@p X`x@)7t8=^t / [КVtZw 6m=+VZв!lhckw9s6=O+ɧ?)P!۩i6j] H +f٣˶7wH(r(ouwBV7Nn* a&VJ+Bw3wж⢛w^.j-S즈]_kؙj;*ŝm-@X4q陉Й>O՟UN!cET,KSa/2X^ZO+z)=CtnCW\ޫzP;FttB5[Mooi6a.-&{ .U: P4݈}DQaVOc`*˛K%|sa3j7[M͚fnFs"dF{nThW uK9Q1uF$c,m cMwsHN% yTܸӛjI6ouK='DC~7%Û6_X3,}.i_9 bg+!>bäհT.UHPb rad a\R+{qPhTCER['!-=s%ETۼQ P|x `h @!JKM}z'[S^JLEԳgRSOFSҩ}=ݩԮMS;S;RSR=9TgRR6QsR? )j!of'iRLp7η˾mM|qs6:z$7N4Ch?h\e/r܂JEp5(  '{nG/}^ 4@k?Fo~)Z;ي/ _؈'NG‰\+I[͉"!!1K\%~ct0s %} 7YaI.g9PrI M -K<ue^mߖ4;݀$,YGCa >UY@Sno6\UB{j%p4i>7G8O^4XўN&-juP#-G J4J!g!m'J'!!ĀoPcfl t6BLNayNiTE+%q@Bъc,Z SBj`Q\`Q͓ħ!O& 1zqyjhY N 1ӴsN{%sH2@ww8:Zɓl:_X#m@\|]`UQcm+%ov.]Rb{r0GiBFy{cH|d",_&`'e;m,|#1:xRy@I 94$ {h!# X4+$6$)ǹϚXbh ~E6Vvrvvķ9,hJZ&U)x]BP \ f@(||1;^ȌI?˵yD=rofK|2&Gco&cA q,k/ʊ*;Ao<j5@_͋M'Y `.B\̷쓪 ~A-pZư p2./d%R W&͐2|5mVh,:*{FE|܅c&7ϋ?Ja-M@]A\ d&<ɠn =J1rB.pP˲ A8elel(?%$ΉߐJ'ȑ@lI2)F/ieQI'DIy+)o͖3\%DAA91PtRGN&RN '$ƿ &%&A 3dDL5ԓB.I#hr#@giu@P ʱ3!%BdJ"xSh@v(H[Zٝ0~I =`!K8dh5ahp."@-7(Y^] E+! ZISCҺ*UBs{s `nV2U]d-œ?%^Z RAdw @lgK'EdR\/&%*+ ͋DpODH_Z T_ZjiR&d}%*@˔Je =3!TzQT58s(hE5)N.?~(oz?"?EfNABm+D0,K>zĠfxJh8i γDAِgr"TB/] }SW'>YTWƕ瘇TEԥߨ?ьh^&uNݣ 伬@OڣJQFSPhG#&wU?;bjmmecaT)-T} ]7% )P7uj cv]fU8K4.qk:[< >`WYnz|o_^t#Bw*o,2W,0kx s9}X=5qvXUi닋o*J5ApJOc*t"\Dq4hS> W8dF3j4tYQlA/ךaUH{8N,>mNX IOk t03Z2}ᙎSjl&Gv/UE+g(5F+~ME%apE78#``K#6UѪY5?c 7E-[(B.r'?5՜A/+ H-n< QkJʝg:"~>QCe_T,m>)龮.:uVӋb[  ܂(~t6P&h(ۃ1d1smgl@+'WN@6'T6Ă/-',_RU J)f[!k\LO.Sܽ #e ,*gj]OJ$@L,hsuv2 rU= v|,r9h/.9Xg!5~64>[kv >(쌐t'/;yQhʎ l.˳G-kK 3'g3/9y`JLbߔE4.}dȫe[?E?7uJ­OZy;c9 GbǶhc5>0#1htCECqh$)AٽEw"!‹4mZ/_D|}ºz:@XMxw[6<ʭ3TtΙկuu=s: ?%`[ ׍`nu!'H İ<Mfc%b%a+ K֑B"Yvs9>@ikDD7b^#_ K u Yy?'?(fcpzJ<?V Jk[-Wh]Յ`݌[X23FL8ujcVxM3W̪TĢ=PDo&8BVzHD GsD r.EhTp}^s :Bܱ3 6r0w|̑]g[<$Y7#dY8`W='vN7RS/M]~k/>YwsW-DnSҪ#"ُZrDtA!*/% t&'1ao]@l @AN _u 9pʋD@zSIBqdlYMv[6%c YZg z~ُ>V % ,XT7}4j,v%}͌rΦA:wo.-oc#Z`!p1^&# ۩06&V= C,m2Uw3L ' C @|7ͅR gY Gc؄Uv@ 'Y_k(PAgkhA,gi@gOo:nY^\qwaclzYS]Ե~H5O L}fl_8K)~<9鬰jTV iuȚ G=]8`BI&2H7na +%̎Ђ?tŜSiV,wYN$xxZ1sTz;7\b8 i:f|v 72=w(,sx*յ.7ezwA|!L#OpMW3p_9uJyיo¿ȡ"4*.~nFJСbcWkl8:Vӥd&jjދ nكXֿf@GY+ŸtUVѢp' &O8y$)枬%w)1f_9O #v>."\X#P7ҟ@C}@O* d S[J+HO|xKf5&[|{f-[2b;p>Ork:-Nh*FKL@ig.=9 d>و w!V8bYXYĹQڝ v6]~zj*ܘ< k^ kvš@neväRʢ}&SYPer9(8JTA,tAaγ$߰,D$$|!j~M\qZE~y~u፫74,훳wx=p8sO4tUkmǚmޅo~;w@@A%0ǃNXâ@ۄV@ 20Z&.hͭש6]XvV"HK NY)Ԁ0Yi@P8ֺTgi' fM Ru\Kڷ۞ǽ:xhÏ/_3wIhulUۖlzbE%QuuB'7YnY9m{>fҨe#XU*s˞w=4isRq qhiNPR_ZVMҾ{qoփ WW] 6P-F-N^O^dimgYaҚ%bV.qS}dR#ju)?-_In!^̅f ƟcMX5(\N/?o>+9U;-1A, ~½v=;j6T,f{7|ݕm9暽bhufYْ̋r"kaO`7\l[j5`/a.+֍q~0Rk0rܹIϚe+e| pàQ1 8_[Jq1\OeNWj[~W9_3?._SX[sVL]6uo|ǎ/5uhj8@> ghBmkn\9P]:U !g endstream endobj 64 0 obj 8016 endobj 65 0 obj (Microsoft Word - CGNS_TestingSpecs.docx) endobj 66 0 obj (Mac OS X 10.10.5 Quartz PDFContext) endobj 67 0 obj (Word) endobj 68 0 obj (D:20160224165508Z00'00') endobj 69 0 obj () endobj 70 0 obj [ ] endobj 1 0 obj << /Title 65 0 R /Producer 66 0 R /Creator 67 0 R /CreationDate 68 0 R /ModDate 68 0 R /Keywords 69 0 R /AAPL:Keywords 70 0 R >> endobj xref 0 71 0000000000 65535 f 0000092399 00000 n 0000004838 00000 n 0000021590 00000 n 0000000022 00000 n 0000004818 00000 n 0000004942 00000 n 0000007849 00000 n 0000000000 00000 n 0000039491 00000 n 0000000000 00000 n 0000068634 00000 n 0000000000 00000 n 0000021730 00000 n 0000075405 00000 n 0000000000 00000 n 0000057040 00000 n 0000000000 00000 n 0000051155 00000 n 0000080487 00000 n 0000005113 00000 n 0000007828 00000 n 0000021334 00000 n 0000007885 00000 n 0000021312 00000 n 0000021441 00000 n 0000000000 00000 n 0000083080 00000 n 0000021680 00000 n 0000022890 00000 n 0000022145 00000 n 0000022870 00000 n 0000023128 00000 n 0000039469 00000 n 0000040206 00000 n 0000039737 00000 n 0000040186 00000 n 0000040441 00000 n 0000051133 00000 n 0000051719 00000 n 0000051353 00000 n 0000051699 00000 n 0000051965 00000 n 0000057019 00000 n 0000057841 00000 n 0000057324 00000 n 0000057821 00000 n 0000058081 00000 n 0000068612 00000 n 0000069126 00000 n 0000068797 00000 n 0000069106 00000 n 0000069361 00000 n 0000075384 00000 n 0000075578 00000 n 0000075838 00000 n 0000080466 00000 n 0000080661 00000 n 0000080908 00000 n 0000083059 00000 n 0000083814 00000 n 0000083344 00000 n 0000083794 00000 n 0000084056 00000 n 0000092163 00000 n 0000092184 00000 n 0000092242 00000 n 0000092295 00000 n 0000092318 00000 n 0000092360 00000 n 0000092379 00000 n trailer << /Size 71 /Root 28 0 R /Info 1 0 R /ID [ <400eea66c103acec83e6d159c3fb5c2c> <400eea66c103acec83e6d159c3fb5c2c> ] >> startxref 92543 %%EOF CGNS-3.4.0/release_docs/INSTALL_Cygwin.txt000066400000000000000000000160741343724673500201150ustar00rootroot00000000000000************************************************************************ CGNS Build and Install Instructions for Cygwin ************************************************************************ This document is a instruction on how to build, test and install CGNS with HDF5 support on Cygwin. Preconditions: -------------- 1. Installed Cygwin 1.7.25 or higher To install the Cygwin net release, go to http://www.cygwin.com and click on "setup-x86.exe" (32-bit installation) or "setup-x86_64.exe" (64-bit installation) at https://cygwin.com/install.html. This will download a GUI installer called setup-x86.exe or setup-x86_64,exe which can be run to download a complete Cygwin installation via the internet. Then follow the instructions on each screen to install Cygwin. Cygwin uses packages to manage installing various software. Users can choose to install or uninstall certain packages by running setup.exe. http://www.cygwin.com/packages/ provides detailed information about Cygwin packages. Most required dependencies can be satisfied by installing all packages in the "Devel" category. 2. Compilers, Libraries and Utilities Installed 2.1 Compilers Supported The following compilers are supported by CGNS/HDF5 and included in the Cygwin package system: gcc (4.7.3 and 4.9.2), which includes: gcc4-core : C compiler gcc4-g++ : C++ compiler gcc4-fortran : fortran compiler 2.1.1 Using Compilers Not Supported By default the current configuration uses vendor compilers; to use another compiler run the following commands before running configure: setenv CC "foo -flags" setenv FC "fffoo -flags" For example, if users want to use pgf90 as fortran compiler, then setenv FC pgf90 See the configure help page (configure --help) for a list of environment variables that have an affect on building the library. 2.2 HDF5 External Library Dependencies 2.2.1 Zlib zlib-1.2.5 or later is supported and tested on Cygwin. 2.2.2 Szip The HDF5 library has a predefined compression filter that uses the extended-Rice lossless compression algorithm for chunked datatsets. For more information about Szip compression and license terms see http://hdfgroup.org/HDF5/doc_resource/SZIP/index.html. The latest supported public release of SZIP is available from ftp://ftp.hdfgroup.org/lib-external/szip/2.1. 2.3 Additional Utilities The following standard utilities are also required to build and test HDF5: bison : yacc implementation flex : flex utility make : make utility Build, Test and Install HDF5 on Cygwin -------------------------------------- 1. Get HDF5 source code package Users can download HDF5 source code package from HDF website (http://hdfgroup.org). 2. Unpacking the distribution The HDF5 source code is distributed in a variety of formats which can be unpacked with the following commands, each of which creates an `hdf5-1.8.x' directory. 2.1 Non-compressed tar archive (*.tar) $ tar xf hdf5-1.8.x.tar 2.2 Gzip'd tar archive (*.tar.gz) $ gunzip < hdf5-1.8.x.tar.gz | tar xf - 2.3 Bzip'd tar archive (*.tar.bz2) $ bunzip2 < hdf5-1.8.x.tar.bz2 | tar xf - 3. Setup Environment In Cygwin, most compilers and setting are automatically detected during the configure script. However, if you are building Fortran we recommend that you explicitly set the "FC" variable in your environment to use the gfortran compiler. For example, issue the command: $ export FC=gfortran 4. Configuring To build HDF5 for use with CGNS it is recommended to disable Fortran and the high level library. $ ./configure --disable-fortran --disable-hl To configure HDF5 C without Zlib, To disable zlib, using $ ./configure --without-zlib Two ways to configure HDF5 C with specified Zlib Using $ ./configure --with-zlib=INCDIR,LIBDIR For example, if the zlib library is installed in /cygdrive/c/usr, which is the parent directory of directories "include" and "lib", $ ./configure --with-zlib=/cygdrive/c/usr/include,/cygdrive/c/usr/lib Through the CPPFLAGS and LDFLAGS Variables For example, if zlib was installed in the directory /cygdrive/c/usr then using the following command to configure HDF5 with zib $ CPPFLAGS=-I/cygdrive/c/usr/include \ $ LDFLAGS=-L/cygdrive/c/usr/lib \ $ ./configure To specify the installation directories, using $ ./configure --prefix="path for installation" By default, HDF5 library, header files, examples, and support programs will be installed in /usr/local/lib, /usr/local/include, /usr/local/doc/hdf5/examples, and /usr/local/bin. To use a path other than /usr/local specify the path with the `--prefix=PATH' switch as in the above command. 5. Make and Make Check After configuration is done successfully, run the following series of commands to build, test and install HDF5 $ make > "output file name" $ make check > "output file name" Before run "make install", check output file for "make check", there should be no failures at all. 6. Make Install $ make install > "output file name" 7. Check installed HDF5 library After step 6, go to your installation directory, there should be three subdirectories: "bin" "include" and "lib". 8. Known Problems dt_arith tests may fail due to the use of fork. This is a known issue with cygwin on Windows. "make check" fails when building shared lib files is enabled. The default on Cygwin has been changed to disable shared. It can be enabled with the --enable-shared configure option but is likely to fail "make check" with GCC compilers. Build, Test and Install HDF5 on Cygwin -------------------------------------- 1. Download the current stable release from: https://github.com/CGNS/CGNS/releases 2. You may need to specify the compilers in the environment: $ export CC="gcc" $ export FC="gfortran" 3. Specify the configure options, below is an example configure line: $ ./configure \ --prefix= \ --with-fortran \ --with-hdf5= \ --enable-lfs \ --disable-shared \ --enable-debug \ --disable-cgnstools \ --with-zlib= \ --enable-64bit 4. Build the CGNS library using $ make $ make install $ make test ----------------------------------------------------------------------- Submit bug reports at: https://cgnsorg.atlassian.net/secure/Dashboard.jspaCGNS-3.4.0/release_docs/Release.txt000066400000000000000000000204531343724673500170430ustar00rootroot00000000000000# CGNS version 3.4.0 This document describes the difference between CGNS 3.3.1 and CGNS 3.4.0, and contains information on known problems in CGNS 3.4.0. Links to the CGNS 3.4.0 source code can be found at: http://cgns.org/download.html User documentation for the current release can be found at: http://cgns.org/CGNS_docs_current/midlevel/index.html For more information, see the CGNS home page: http://cgns.org # CONTENTS New Features Bug Fixes since CGNS 3.3.1 Known Problems Supported platforms # New Features ## Configuration: Enforce the HDF5 version >= 1.8 is used in building HDF5. (CGNS-150). Autotools: CGNS will find and link the compression libraries, szip and zlib, required by HDF5. This occurs automatically if neither --with-zlib or --with-szip are not specified (CGNS-156). ## Library: Changed default CGNS to 1.8 HDF5 file format. -- only for HDF5 versions > 1.10.2. CPEX 40 Rind Plane Indexing (CGNS-87) CPEX 41 NGON modification proposal (CGNS-121) ## Parallel Library: None ## Fortran Library: Added support for NAG Fortran compilers (CGNS-107) ## Tools: None # Bug Fixes since CGNS 3.3.1 Release # Configuration: * Order include directives to get correct includes, cmake (PR 109) * make clean does not remove executables in Test_UserGuideCode (CGNS-99) * Windows builds: CGNS_ENABLE_LFS is ignored (CGNS-117) * Sun's make implemenation fails to compile fortran (CGNS-28) * Some systems need to explicitly link to libdl (CGNS-128) * CGNS fails in fortran test with PGI 17 compiler (CGNS-127) * CGNS fails to find the lib64 HDF5 library (CGNS-123) * CGNS fails to compile on Windows with Fortran enabled (CGNS-148) * Can't compile using MSVC & IVF on windows (MSVS 14) (CGNS-146) * Fix szip linking (PR 97) * RPATH handling for MacOSX (Darwin) (PR 88) * fix tests failing when compiled for 64bit (PR 85) * remove variable length array to be able to build pcgnslib.c with VC (CGNS-147) * Build parallel CGNS on Windows (PR 69) * Cmake fixups (PR 58) * If check needs to link, then need library path (PR 52) * Specify STATIC when adding cgns_static lib (PR 46) * _stat32i64 is msvc-specific (PR 45) # Library: * Eliminate potential integer overflow / undefined behavior (PR 106) * Partial write of unstructured MIXED element sets fails with CGNS > 3.3.1 (CGNS-151) * If processor has no data, set end = start = 0 (CGNS-133) * Large files fail on 64-bit windows (CGNS-83) * mesh_dim may be exceed the limit of 32-bit integer (CGNS-131) * RUNPARALLEL is defined but never used. (CGNS-96) * typo in cgnscheck print_units cg_TemperatureUnitsName index (CGNS-126) * cgp_mpi_comm return value unclear (CGNS-111) * Changed ADFH_Read_Data and ADFH_Write_Data to honor the cgp_pio_mode (PR 98) * Support for std C on linux (PR 96) * Null check fix (PR 94) * Eliminate dead / unreachable code (PR 93) * Fix parallel write (PR 86) * Add missing argument to cgi_error call (PR 84) * Fix BC type string constant FamilySpecified_s (PR 83) * Remove double condition test (PR 82) * remove some gcc warnings (PR 78) * remove variable length array to be able to build pcgnslib.c with VC (PR 76) * Fix bad if test (PR 70) * Eliminate memory leaks in cgi_read_ziter (PR 68) * Improve error messages, fix error check (fixed) (PR 66) * Drop obsolete matherr hack (PR 55) # Fortran: * Add missing dll export symbols from Fortran module. (PR 59) # Tools: * Update cgnsutil.c (PR 89) * patch cgnscheck (PR 72) * Fix cgnsview linking to HDF5 libs. (PR 56) ## Known Problems When building with PGI and gcc compilers it might be necessary to set the environment variables: FLIBS="-Wl,--no-as-needed -ldl" LIBS="-Wl,--no-as-needed -ldl" Misc. issues can be found at: https://cgnsorg.atlassian.net Supported Platforms ====================== The following platforms are supported and have been tested for this release. They are built with the configure process unless specified otherwise. Linux 2.6.32-573.22.1.el6 GNU C (gcc), Fortran (gfortran), C++ (g++) #1 SMP x86_64 GNU/Linux compilers: Version 4.4.7 20120313 Versions 4.9.3, 5.2.0, 6.2.0 PGI C, Fortran, C++ for 64-bit target on x86-64; Version 16.10-0 Intel(R) C (icc), C++ (icpc), Fortran (icc) compilers: Version 17.0.0.098 Build 20160721 MPICH 3.1.4 compiled with GCC 4.9.3 OpenMPI 2.0.1 compiled with GCC 4.9.3 Linux 2.6.32-573.18.1.el6 gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) #1 SMP ppc64 GNU/Linux g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) GNU Fortran (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) IBM XL C/C++ V13.1 IBM XL Fortran V15.1 Linux 3.10.0-327.10.1.el7 GNU C (gcc), Fortran (gfortran), C++ (g++) #1 SMP x86_64 GNU/Linux compilers: Version 4.8.5 20150623 (Red Hat 4.8.5-4) Versions 4.9.3, 5.3.0, 6.2.0 Intel(R) C (icc), C++ (icpc), Fortran (icc) compilers: Version 17.0.4.196 Build 20170411 MPICH 3.1.4 compiled with GCC 4.9.3 SunOS 5.11 32- and 64-bit Sun C 5.12 SunOS_sparc Sun Fortran 95 8.6 SunOS_sparc Sun C++ 5.12 SunOS_sparc Windows 10 x64 Visual Studio 2015 w/ Intel Fortran 16 (cmake) Mac OS X Mt. Lion 10.8.5 Apple LLVM version 5.1 (clang-503.0.40) 64-bit gfortran GNU Fortran (GCC) 4.8.2 Intel icc/icpc/ifort version 15.0.3 Mac OS X Mavericks 10.9.5 Apple LLVM version 6.0 (clang-600.0.57) 64-bit gfortran GNU Fortran (GCC) 4.9.2 Intel icc/icpc/ifort version 15.0.3 Mac OS X Yosemite 10.10.5 Apple LLVM version 6.1 (clang-602.0.53) 64-bit gfortran GNU Fortran (GCC) 4.9.2 Intel icc/icpc/ifort version 15.0.3 Mac OS X El Capitan 10.11.4 Apple LLVM version 7.3.0 (clang-703.0.29) 64-bit gfortran GNU Fortran (GCC) 5.2.0 Intel icc/icpc/ifort version 16.0.2 Tested Configuration Features Summary ===================================== In the table below y = tested n = not tested in this release x = not working in this release dna = does not apply Platform | C | Fortran | Fortran | parallel | | parallel -------------------------------------|-----------|---------|---------- SunOS 5.11 32-bit | n | y | n SunOS 5.11 64-bit | n | y | n Windows 7 | n | n | n Windows 7 x64 | n | n | n Windows 7 Cygwin | n | n | n Windows 8.1 | n | n | n Windows 8.1 x64 | n | n | n Windows 10 | n | n | n Windows 10 x64 | n | n | n Mac OS X Yosemeti 10.10.5 64-bit | n | y | n Mac OS X El Capitan 10.11.6 64-bit | n | y | n MacOS High Sierra 10.13.6 64-bit | n | y | n AIX 6.1 32- and 64-bit | n | y | n CentOS 7.1 Linux 3.10.0 x86_64 PGI | n | y | n CentOS 7.1 Linux 3.10.0 x86_64 GNU | y | y | y CentOS 7.1 Linux 3.10.0 x86_64 Intel | n | y | n Linux 2.6.32-431.11.2.el6.ppc64 | n | y | n CGNS-3.4.0/release_docs/changelog000066400000000000000000000056421343724673500165770ustar00rootroot00000000000000== 3.2.1 == - fixed problem with IS_FIXED_SIZE macro for cubic elements - added check for open file to routines that don't take a file number (suggestion from Marc Poinet) - added HTMLHelp interface to cmake scripts - added AdditionalFamilyName to UserDefinedData - fixed compiler complaint about comparison between int and enum - added routines to set MPI communicator for parallel I/O - updated CMake scripts to work within other scripts (remove conflicts) - updates to some cgnstools utility conversion routines - fixes and updates to tests and cgnscheck - updates to support CG_FILE_ADF2 (2.5 compatibility) - fix for point set subregions == 3.2 === - full integration of parallel I/O using HDF5 with MPI - implemented CPEX 0033 and 0034 - compression (rewriting) of file to remove unused space is no longer automatically done, since may interfere with parallel I/O. Added cgnscompress program to tools to do this afterwards. - removed cgnsversion program from tools since support was getting out of hand (N squared problem with versions). - added routines to convert to and from AFLR3, FAST, and TetGen - implemented cubic elements (CPEX 0036) - CGNStools documentation no longer included with source. The NASA Glenn website (or local copy) is now used instead. == 3.1.4-2 == - fixes to cmake scripts for Fortran - added check for open file to routines that don't take a file number (suggestion from Marc Poinet) - CGNStools documentation no longer included with source. The NASA Glenn website (or local copy) is now used instead. - save window size for cgnsview - fix to computing path lists in CMake script == 3.1.4 == - added some const definitions to library - moved unlink of filename when using CG_MODE_WRITE on open to cgio - fixed goto for FamilyBCDataset for UserData, .etc - added cg_get_cgio_f and cg_root_id_f Fortran routines - fixed cmake and configure scripts to allow MPI with HDF5 and fixed bugs in those scripts - updated CGNSplot to handle all element types and 1-d and 2-d cases - fixes to cgnscheck - cleaned up some compiler warnings - added cgnsBuild.defs Makefile include to installation - removed unneeded tools directory from cgnstools - cgnstools no longer built automatically - need to set configure flag - allow CellCenter for BCs - added cg_precision and cg_precision_f functions to get integer size used to create the file (32 or 64) == 3.0.8 == - Fix flag - Test for v3.0 release == 3.0.7 == - Internal updates == 3.0.6 == - Internal updates == 3.0.5 == - Added install.txt and install.lyx - Added readme.txt and readme.lyx - Re-integrated the automake build system into the src directory so that the old build system can be used by invoking ./configure make, make install in the src directory. - Added license.txt == 3.0.4 == - Fixed a compilation problem with gcc-4.1 == 3.0.3 - Internal debugging release == 3.0.2 == - Fixed BUILD_HDF5 flag in CMakeLists.txt - Fixed file prop list scope problem in ADFH.c CGNS-3.4.0/release_docs/changes_3.3.lyx000066400000000000000000001030011343724673500174420ustar00rootroot00000000000000#LyX 2.1 created this file. For more info see http://www.lyx.org/ \lyxformat 474 \begin_document \begin_header \textclass extarticle \begin_preamble \usepackage{minted} \definecolor{bg}{rgb}{0.95,0.95,0.95} \end_preamble \use_default_options true \maintain_unincluded_children false \language english \language_package default \inputencoding auto \fontencoding global \font_roman default \font_sans default \font_typewriter default \font_math auto \font_default_family rmdefault \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \default_output_format default \output_sync 0 \bibtex_command default \index_command default \paperfontsize 11 \spacing single \use_hyperref true \pdf_bookmarks true \pdf_bookmarksnumbered false \pdf_bookmarksopen false \pdf_bookmarksopenlevel 1 \pdf_breaklinks false \pdf_pdfborder false \pdf_colorlinks false \pdf_backref false \pdf_pdfusetitle true \papersize default \use_geometry true \use_package amsmath 1 \use_package amssymb 1 \use_package cancel 1 \use_package esint 1 \use_package mathdots 0 \use_package mathtools 1 \use_package mhchem 1 \use_package stackrel 1 \use_package stmaryrd 1 \use_package undertilde 1 \cite_engine basic \cite_engine_type default \biblio_style plain \use_bibtopic false \use_indices false \paperorientation portrait \suppress_date false \justification true \use_refstyle 0 \index Index \shortcut idx \color #008000 \end_index \leftmargin 1cm \topmargin 2cm \rightmargin 12mm \bottommargin 2cm \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \paragraph_indentation default \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict false \end_header \begin_body \begin_layout Title Parallel and Large-scale Simulation Enhancements to CGNS \end_layout \begin_layout Author M. Scot Breitenfeld, The HDF Group, brtnfld@hdfgroup.org \end_layout \begin_layout Section Overview of changes introduced in the HDF5_Parallel branch \end_layout \begin_layout Standard Many of the changes discussed in the following sections address the currently (as of version 3.2.1) underperforming parallel capabilities of the CGNS library. For example, the CGNS function cgp_open, which opens a CGNS file for processing , has substantially increasing execution time as the number of processes is increased, Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:Time-for-completion" \end_inset (trunk). The current improvement for cgp_open is substantial at 100-1000 times faster (branch) than the previous implementation (trunk). In fact, for runs with the largest number of processes (>1024) the batch job had a time limit of 5 minutes and not all the processes had completed cgp_open before this limit was reached. Obviously, the previous implementation of cgp_open is a lot worse than reported in the figure. \end_layout \begin_layout Standard \begin_inset Float figure placement h wide false sideways false status open \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/cgp_open.png scale 30 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Time-for-completion" \end_inset Time for completion of cgp_open in write mode for the original implementation (trunk) and the current implementation (branch), the error bars correspond to the minimum and maximum time over all the processes that had completed before the batch job time limit was reached. \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard Section \begin_inset CommandInset ref LatexCommand ref reference "sub:General-behavior-changes" \end_inset lists changes to CGNS that could effect the end user and introduces new functions and specifications. Fortran programmers should take notice of Section \begin_inset CommandInset ref LatexCommand ref reference "sub:New-Fortran-changes" \end_inset which highlights changes introduced for better interoperability with the C CGNS library. Section \begin_inset CommandInset ref LatexCommand ref reference "sec:Parallel-installation-instructio" \end_inset gives example installation guides for GPFS and Lustre hardware. Items listed in blue affect compatibility of older codes when using CGNS v3.2.2. Known problems are highlighted in red. The branch can be checked out from sourceforge at, \end_layout \begin_layout Standard \begin_inset space \space{} \end_inset \end_layout \begin_layout Standard \align center http://svn.code.sf.net/p/cgns/code/cgns/branches/HDF5_Parallel \end_layout \begin_layout Section \begin_inset CommandInset label LatexCommand label name "sub:General-behavior-changes" \end_inset General behavior changes and new recommendations for parallel performance \end_layout \begin_layout Itemize The flush functions should not be used. Writing and reading immediately avoids IO contention occurring when flush is being used. \end_layout \begin_layout Itemize The parallel routines are meant for parallel file systems (GPFS or Lustre). \end_layout \begin_layout Itemize \color blue The default parallel input/output mode was changed from CGP_INDEPENDENT to CGP_COLLECTIVE. \end_layout \begin_layout Itemize \color blue A new function was added for passing MPI info to the CGNS library. \end_layout \begin_layout Standard \align center \series bold C \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_mpi_info(MPI_Info info) \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \align center \series bold Fortran \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_mpi_info_f(comm_info, ierr) \end_layout \begin_layout Plain Layout INTEGER :: comm_info \end_layout \begin_layout Plain Layout INTEGER :: ierr \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Itemize Functions for parallel reading and writing multi-component datasets using a single call was introduced. The new APIs use new capabilities are tentatively to be introduced in version 1.10.0 of the HDF5 library. The new APIs pack multiple datasets into a single buffer and the underlying MPI IO completes the IO request using just one call. The availability of the new functions in the HDF5 library is checked at compile time. The current limitation (due to MPI) is that the size of the sum of the datasets must be less than 2GB. Example usage can be found in benchmark_hdf5.c and benchmark_hdf5_f90.F90 in ptests. \end_layout \begin_layout Standard \align center \series bold C \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_coord_multi_read_data(int fn, int B, int Z, int *C, \end_layout \begin_layout Plain Layout const cgsize_t *rmin, const cgsize_t *rmax, \end_layout \begin_layout Plain Layout void *coordsX, void *coordsY, void *coordsZ); \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_coord_multi_write_data(int fn, int B, int Z, int *C, \end_layout \begin_layout Plain Layout const cgsize_t *rmin, const cgsize_t *rmax, \end_layout \begin_layout Plain Layout const void *coordsX, const void *coordsY, const void *coordsZ); \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_field_multi_read_data(int fn, int B, int Z, int S, int *F, \end_layout \begin_layout Plain Layout const cgsize_t *rmin, const cgsize_t *rmax, \end_layout \begin_layout Plain Layout int nsets, ...); \end_layout \begin_layout Plain Layout /* ... nsets of variable arguments, *solution_array, corresponding to the order given by F */ \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_field_multi_write_data(int fn, int B, int Z, int S, int *F, \end_layout \begin_layout Plain Layout const cgsize_t *rmin, const cgsize_t *rmax, \end_layout \begin_layout Plain Layout int nsets, ...); \end_layout \begin_layout Plain Layout /* ... nsets of variable arguments, *solution_array, corresponding to the order given by F */ \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_array_multi_write_data(int fn, int *A, const cgsize_t *rmin, const cgsize_t *rmax, \end_layout \begin_layout Plain Layout int nsets, ...); \end_layout \begin_layout Plain Layout /* ... nsets of variable arguments, *field_array, corresponding to the order given by F */ \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{c} \end_layout \begin_layout Plain Layout int cgp_array_multi_read_data(int fn, int *A, const cgsize_t *rmin,const cgsize_t *rmax, \end_layout \begin_layout Plain Layout int nsets, ...); \end_layout \begin_layout Plain Layout /* ... nsets of variable arguments, *field_array, corresponding to the order given by F */ \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \align center \series bold Fortran \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_coord_multi_read_data_f(fn, B, Z, C, rmin, rmax, coordsX, coordsY, coordsZ, ier) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout REAL :: coordsX, coordsY, coordsZ \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_coord_multi_write_data_f(fn, B, Z, C, rmin, rmax, coordsX, coordsY, coordsZ, ier) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout REAL :: coordsX, coordsY, coordsZ \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_field_multi_write_data_f(fn, B, Z, S, F, rmin, rmax, ier, nsets, ...) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout INTEGER :: nsets \end_layout \begin_layout Plain Layout ... REAL, DIMENSION(*) :: field_array ! entered nsets times \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_field_multi_read_data_f(fn, B, Z, S, F, rmin, rmax, ier, nsets, ...) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout INTEGER :: nsets \end_layout \begin_layout Plain Layout ... REAL, DIMENSION(*) :: field_array ! entered nsets times \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_array_multi_write_data_f(fn, B, Z, S, F, rmin, rmax, ier, nsets, ...) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout INTEGER :: nsets \end_layout \begin_layout Plain Layout ... REAL, DIMENSION(*) :: data_array ! entered nsets times \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout CALL cgp_array_multi_read_data_f(fn, B, Z, S, F, rmin, rmax, ier, nsets, ...) \end_layout \begin_layout Plain Layout INTEGER :: fn \end_layout \begin_layout Plain Layout INTEGER :: B \end_layout \begin_layout Plain Layout INTEGER :: Z \end_layout \begin_layout Plain Layout INTEGER :: C \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmin \end_layout \begin_layout Plain Layout INTEGER(CG_SIZE_T) :: rmax \end_layout \begin_layout Plain Layout INTEGER :: ier \end_layout \begin_layout Plain Layout INTEGER :: nsets \end_layout \begin_layout Plain Layout ... REAL, DIMENSION(*) :: data_array ! entered nsets times \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Subsection New C changes \end_layout \begin_layout Itemize A new parallel example benchmark program, benchmark_hdf5.c, was added to directory ptests. \end_layout \begin_layout Itemize The cgp_*_read/write_dataset APIs now excepts non-allocated arrays, or NULL, as valid parameters for the datasets. Additionally, the dimensional arrays \shape italic , rmin \shape default and \shape italic rmax \shape default , can also be NULL. If the data array is NULL and the dimensional arrays are not NULL, then the validity of the dimensional arrays, \shape italic rmin \shape default and \shape italic rmax \shape default , is not check. For collective parallel IO, this is used as a mechanism to indicated that processes with NULL API parameters will not write any data to the file. \end_layout \begin_layout Subsubsection Internal library changes \end_layout \begin_layout Enumerate Fixed issue with autotools putting a blank \begin_inset Quotes eld \end_inset -l \begin_inset Quotes erd \end_inset in \begin_inset Quotes eld \end_inset MPILIBS = \begin_inset Quotes erd \end_inset when compiling library using using mpi. \end_layout \begin_layout Enumerate Replaced the hid_t to double (and vice-versa) utilities \shape italic to_HDF_ID \shape default and \shape italic to_ADF_ID \shape default from a type cast to a function which uses memcpy for the conversion. This is need to for the upcomming release of HDF5 1.10 where hid_t was changed from a 32 bit integer to a 64 bit integer. \end_layout \begin_layout Subsection \begin_inset CommandInset label LatexCommand label name "sub:New-Fortran-changes" \end_inset New Fortran changes \end_layout \begin_layout Standard All users are \series bold \color black strongly \series default \color inherit encouraged to use a Fortran 2003 standard compliant compiler. Using a Fortran 2003 compiler guarantees interoperability with the C APIs via the ISO_C_BINDING module. Many changes were added to the CGNS library in order to take full advantage of the interoperability offered by the ISO_C_BINDING module. \end_layout \begin_layout Enumerate Configure was changed to check if the Fortran compiler is Fortran 2003 compliant. If it is then the features of ISO_C_BINDING will be used. \end_layout \begin_layout Enumerate The predefined CGNS constant parameters data types were changed from INTEGER to ENUM, BIND(C) for better C interoperability. The users should use the predefined constants whenever possible and not the numerical value represented by the constants. \color blue A variable expecting an enum value returned from a Fortran API should be declared, INTEGER(cgenum_t). \end_layout \begin_layout Enumerate \shape italic \color blue INCLUDE \begin_inset Quotes eld \end_inset cgslib_h \begin_inset Quotes erd \end_inset \shape default was changed in favor of using a module, USE CGNS. \end_layout \begin_deeper \begin_layout Enumerate This allows defining a KIND type for integers instead of the current way of using the preprocessor dependent \shape italic cgsize_t \shape default . \end_layout \end_deeper \begin_layout Enumerate \begin_inset CommandInset label LatexCommand label name "enu:int64" \end_inset The user should be sure to declare the arguments declared \shape italic int \shape default in the C APIs as INTEGER in Fortran. The ONLY Fortran arguments declared as type \shape italic cgsize_t \shape default should be the arguments which are also declared \shape italic cgsize_t \shape default in the C APIs. This is very important when building with option \shape italic --enable-64bit \shape default . The test programs were updated in order to conform to this convention. \end_layout \begin_layout Enumerate Assuming the rules in step \begin_inset CommandInset ref LatexCommand ref reference "enu:int64" \end_inset were followed, users should not need to use parameter CG_BUILD_64BIT since Fortran's \shape italic cgsize_t \shape default is now guaranteed to match C's \shape italic cgsize_t \shape default . \end_layout \begin_layout Enumerate \color red Fortran programs defining CGNS data types with a default INTEGER size of 8 bytes also then need to compile the CGNS library with the default INTEGER size of 8 bytes \color inherit . This is independent of whether or not \shape italic --enable-64bit \shape default is being used. For clarification, using \shape italic --enable-64bit \shape default allows for data types (i.e. those declared as \shape italic cgsize_t \shape default ) to be able to store values which are too large to be stored as 4 byte integers (i.e. numbers greater than 2,147,483,647). It is not necessary, or advisable (since it waste memory), to have CGNS INTEGER types (types declared \shape italic int \shape default in C) to be 8 bytes; the variables declared as \shape italic cgsize_t \shape default will automatically handle data types that can not be stored as 4 byte integers when \shape italic --enable-64bit \shape default is being used. If the CGNS library was not compiled with a default INTEGER of 8 bytes, but the calling program was, then all integers passed to CGNS with C type \shape italic int \shape default should be declared INTEGER(C_INT). \end_layout \begin_deeper \begin_layout Enumerate CGNS developer's note: A new C data type, cgint_f, was introduced to be interpretable with the C type \shape italic int \shape default . In order to allow for default 8 byte integers in Fortran: \end_layout \begin_deeper \begin_layout Enumerate The C API wrappers in cg_ftoc.c were changed from \shape italic cgsize_t \shape default to \shape italic cgint_f \shape default everywhere the C argument is declared as an \shape italic int \shape default in C. \end_layout \begin_layout Enumerate Configure detects what size the default integer is in Fortran and finds the corresponding size in C in order to set the correct size of \shape italic cgint_f \shape default . \end_layout \end_deeper \end_deeper \begin_layout Enumerate Two new benchmarking programs were introduced in directory ptests: \end_layout \begin_deeper \begin_layout Enumerate benchmarking_hdf5_f90.F90 uses the conventional Fortran wrappers. \end_layout \begin_layout Enumerate benchmarking_hdf5_f03.F90 calls the C APIs directly, no Fortran wrappers are used. \end_layout \end_deeper \begin_layout Enumerate A new Fortran API was added for determining the CGNS data type of a variable which is interoperable with the C data type. \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout Function cg_get_type(var) \end_layout \begin_layout Plain Layout type, INTENT(IN) :: var \end_layout \begin_layout Plain Layout INTEGER(KIND(enumvar)) :: cg_get_type \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Standard An example of using the new function to automatically specify the CGNS type corresponding to the Fortran data type is, \end_layout \begin_layout Standard \begin_inset ERT status open \begin_layout Plain Layout \backslash begin{minted}[bgcolor=bg]{fortran} \end_layout \begin_layout Plain Layout INTEGER, DIMENSION(1:10) :: Array_i \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout CALL cgp_array_write_f("ArrayI",cg_get_type(Array_i(1)),1,INT(nijk(1),cgsize_ t),Ai, err) \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout \backslash end{minted} \end_layout \end_inset \end_layout \begin_layout Subsection Unfinished Fortran Features \end_layout \begin_layout Enumerate Default double precision for reals in Fortran leads to a mismatch in the C APIs, which expect a float. \end_layout \begin_layout Section \begin_inset CommandInset label LatexCommand label name "sec:Parallel-installation-instructio" \end_inset Parallel installation instructions \end_layout \begin_layout Standard Two parallel files systems were investigated: GPFS (mira, Argonne National Laboratory) and Lustre (Pleiades NASA). The following descriptions were for those systems, but the overall procedure should be similar on different machines of the same type. Example build scripts for these systems can be found in src/SampleScripts of the CGNS source code. They include scripts for building zlib, hdf5 (assuming the user does not already have them installed system wide) and a script for building CGNS. All the scripts use autotools; \color red cmake remains untested \color inherit . The next few examples assume all the needed packages are in ${HOME}/packages and all the build scripts are placed in ${HOME}/packages. This information can also be found in the README.txt in the scripts directory. \end_layout \begin_layout Subsection Building on IBM Blue Gene (GPFS) \end_layout \begin_layout Enumerate Building zlib from source: Download and extract the zlib source: http://www.zlib.n et/ \end_layout \begin_deeper \begin_layout Enumerate cd into the top level zlib source directory. \end_layout \begin_layout Enumerate modify and run the script: ../build_zlib \end_layout \end_deeper \begin_layout Enumerate Building hdf5 from source \end_layout \begin_deeper \begin_layout Enumerate From the top level of the hdf5 library, change the ${HOME}/packages to where zlib was installed in STEP 1. \end_layout \begin_layout Enumerate ../build_hdf5 --without-pthread --disable-shared --enable-parallel --enable-produc tion \backslash --enable-fortran --enable-fortran2003 \backslash --disable-stream-vfd --disable-direct-vfd \backslash --with-zlib=${HOME}/packages/zlib-1.2.8/lib --prefix=${HOME}/packages/phdf5-trunk \end_layout \begin_layout Standard where prefix is set for where the hdf5 library will get installed. There should be no need to modify the script. \end_layout \end_deeper \begin_layout Enumerate Building cgns from source: \end_layout \begin_deeper \begin_layout Enumerate cd into the cgns/src directory \end_layout \begin_layout Enumerate modify and run: /build_cgns \end_layout \begin_layout Enumerate make \end_layout \begin_layout Enumerate To make the tests: cd ptests; make;make test \end_layout \end_deeper \begin_layout Enumerate Important parameters for good performance on GPFS: \end_layout \begin_deeper \begin_layout Enumerate The environment variable BGLOCKLESSMPIO_F_TYPE=0x47504653 should be set. For example, this can be set in a batch job using qsub --env BGLOCKLESSMPIO_F_T YPE=0x47504653 \end_layout \end_deeper \begin_layout Subsection Building on SGI (Lustre) \end_layout \begin_layout Enumerate Building zlib from source: Download and extract the zlib source: http://www.zlib.n et/ \end_layout \begin_deeper \begin_layout Enumerate cd into the top level zlib source directory. \end_layout \begin_layout Enumerate modify and run the script: ../build_zlib \end_layout \end_deeper \begin_layout Enumerate Building hdf5 from source: \end_layout \begin_deeper \begin_layout Enumerate From the top level of the hdf5 library, change the ${HOME}/packages to where zlib was installed in STEP 1. \end_layout \begin_layout Enumerate ../build_hdf5 \end_layout \end_deeper \begin_layout Enumerate Building cgns from source: \end_layout \begin_deeper \begin_layout Enumerate cd into the cgns/src directory \end_layout \begin_layout Enumerate modify and run: /build_cgns \end_layout \begin_layout Enumerate make \end_layout \begin_layout Enumerate To make the tests: cd ptests; make;make test \end_layout \end_deeper \begin_layout Enumerate Important parameters for good performance: \end_layout \begin_deeper \begin_layout Enumerate The Lustre parameters have not been fully tested. \end_layout \begin_layout Enumerate On Pleiades, lfs setstripe -c 64 -s 0 /nobackupp8/, has shown good performance. \end_layout \end_deeper \begin_layout Subsection Parallel performance results \end_layout \begin_layout Standard The following results are for the \shape italic benchmark_hdf5* \shape default programs found in the \shape italic ptests \shape default directory. The benchmark simulates writing and then reading a ~33.5 million 6-node pentahedra elements mesh with ~201 million nodes. The benchmark results from \shape italic benchmark_hdf5.c \shape default show improvement in cgp_open for up to 32,768 processes, Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:Results-for-benchmark_hdf5.c" \end_inset over the previous implementation. A comparison of the maximum IO bandwidth speeds for reading and writing CGNS data compared to the practical maximum IO bandwidth on cetus (ANL) shows the extremely fast writing of the element connectivity table, Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:IO-bandwidth-speeds" \end_inset . A comparison of \shape italic benchmark_hdf5_f90.F90 \shape default and \shape italic benchmark_hdf5_f03.F90 \shape default also shows negligible performance differences when using the Fortran 90 wrapper routines ( \shape italic benchmark_hdf5_f90.F90) \shape default and when calling the C CGNS APIs directly ( \shape italic benchmark_hdf5_f03.F90) \shape default , Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:Results-for-benchmark_hdf5_f03.F" \end_inset . Additionally, negligible difference in performance and scaling exists when calling CGNS from Fortran and C, Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:Comparision-of-Fortran" \end_inset . \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status collapsed \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/C_gpfs.png lyxscale 50 scale 30 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Results-for-benchmark_hdf5.c" \end_inset Results for benchmark_hdf5.c on GPFS (cetus, ANL). \end_layout \end_inset \end_layout \begin_layout Plain Layout \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/Bandwidth_cgns.png lyxscale 50 scale 35 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:IO-bandwidth-speeds" \end_inset IO bandwidth speeds for benchmark_hdf5.c on GPFS (cetus, ANL) compared to the practical maximum IO bandwidth speeds (shaded area). \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/C_gpfs.png lyxscale 50 scale 30 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Results-for-benchmark_hdf5_f03.F" \end_inset Results for \shape italic benchmark_hdf5_f03.F90 \shape default (shown in color) and \shape italic benchmark_hdf5_f90.F90 \shape default (shown in grey) on GPFS (cetus, ANL). \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/f03_C_gpfs.png lyxscale 50 scale 30 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Comparision-of-Fortran" \end_inset Comparison of Fortran ( \shape italic benchmark_hdf5_f03.F90, \shape default solid lines) and C ( \shape italic benchmark_hdf5 \shape default .c, dashed lines) on GPFS (cetus, ANL). \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Standard The benchmark results from \shape italic benchmark_hdf5.c \shape default on the Lustre file system (Pleiades, NASA) is presented in Fig. \begin_inset CommandInset ref LatexCommand ref reference "fig:Comparision-of-Fortran-1" \end_inset . The system defaults for the Lustre file system were used along with a strip count of 64 and a strip size of 4 MB. Overall the Lustre file system appears to be faster at reading a writing, but the GPFS scaled better for the benchmark. \end_layout \begin_layout Standard \begin_inset Float figure wide false sideways false status open \begin_layout Plain Layout \align center \begin_inset Graphics filename figs/Lustre.png lyxscale 50 scale 30 \end_inset \end_layout \begin_layout Plain Layout \begin_inset Caption Standard \begin_layout Plain Layout \begin_inset CommandInset label LatexCommand label name "fig:Comparision-of-Fortran-1" \end_inset Results for \shape italic benchmark_hdf5.c \shape default on Lustre file system (Pleiades, NASA). \end_layout \end_inset \end_layout \end_inset \end_layout \begin_layout Section* Acknowledgments \end_layout \begin_layout Standard This work was funded by NASA through the CGNS project, contract #NNL14AB41T. Additionally, the computational studies done on cetus and mira at Argonne National Laboratory used allocation time through the ExaHDF5 project, DOE contract #DE-AC02-05CH11231. Computational studies on the Lustre file system was done on Pleiades through NASA's High-End Computer Capabilities Project. \end_layout \end_body \end_document CGNS-3.4.0/release_docs/changes_3.3.pdf000066400000000000000000032435731343724673500174250ustar00rootroot00000000000000%PDF-1.5 % 50 0 obj << /Length 1828 /Filter /FlateDecode >> stream xڅWYs6~#5K}tiz5 EBZ*@^dŝG& ,H}FnSeDyZ:VIt`<uzLgd>[׹]HG—U4%H#UebjVǣgRG#htQDnT`<n2AYآ^}-Оur[# .ې|X0oĠXuqCmأ~<9C7+D4H|T ×*t Nhzdc "J&?#_` σCz<'mHgΑWbb- Ky]:LVj dZa,>8 9X2T#^W6RycFn QKstpt> stream xxTU҉ EZ5" (H[H,@hTAE`W" * X 4E Im&o83dғ9s}w'_ ޼yƍ0aBFիwڵzO?ngW6m 9rWxxxi1cԯ_?>>^=MLLlذipR/_,ӦM6Κ5J*%yJ}פO?6~Ҹz<>\O>m<{4K%yJԩL&mcLL4jժd8O 4Lm<ƚ5kl)jժnXT=<SСCʕ+Fy*~~~%yJ]bڵK۸o>i\~}pRO>- .6Yjժ%ŕpȡEKرc4iW^vTWR?վ)")b,lݻWTyn!<w.vvAR`g᡽S~Sk׮ A@@ÇDrKFts9YI縨oڽG.\h޸qc+Wڽ|ͷ~A6lؐQ4 ƍw"ϟtҥ~d e 0%b,b,GVB\ 6nܨmLOOn& t!)))%%ɓ/bڵ×O>)611155U?s5j(TXS"eT+VDGGLe}Q s9rH $Ξ=['N(+i[HLL̪Urdͳ;㮻Rpmd2V244Tի>999^^^Hb 9r֮^T+0Hۊ/Q/_bo>>]vڏ[f/~'v{ŋ۵K۹s)==]]r[؄UfCXXf6l [:V.SVRVL*)))uu<2/`^sq9_RzvmUTs'Ntbإg}V~ΗJ7bP.XTɮ] 2L 4Pjk׮=oJcv7 GnڴdR*醍@+A?eՏ,eYLˀK.=M4QF}gΜ5jd4OOOϞ=bŊGFFΞ=YfCb2۶mׯ_Z$J 0>ӾgرYmkO,[LrGNN믿# ;v"MGyT]{Ф3l)SKvأI;L2EKz.\p|utv1e>|خE 6,""CzfϞ=2]` e(u._NeO?@W:TZnRluN<ʕ+ $nwrlȸWVf֭Y(yl\uֵlr߾}2`5x`ڂZȬY<( >}j)`[)S>\_?kZd+S[?رc2EUhuիyNVGL&vuQTɯ1I_hJW%B•Ej{Ų/,ڡN;m٬YGjO̔};Cu+dNRJ)v֭)Uuz ?kx]wiϔVGk'RvKʯۯK.Ӗ-[b'O2[)~ٖڒnHU?Sd1-UΝk7 jZZZN?Z]Qdx)))je$g3c u4P=oץjkY~Wy. LsoLogyv2<~饗\+ [sRMN'#kvq=_=zkqKR\Oݱ)Heգޚ+´g7(lJU10&&FۨHt~g+_UrqnXu9{Ց2|])֭>|}d1W &WUgҥ%b眝;wb';uՙj6m?~;*UtMCU,NJU ~1[ 0g%ڟ:u)Օ_/'ʷ@vZ^ZU"u(qԩHqח#hըQn8T9jZ!;NgY,TYq׮]ِMaw sN<)y%Rs7S``o֢E Űvq*=zHͥR333oV8x֞޽n7YE6]^qJ5LҿcǎICWCJ֤I EHz)NJ}wѺu* ~mKw!O_y,-6m*zdI7@rkw裏j[Μ9sPVZC qq`gx]_Ç[-Zm<}dM~VϞ=ձ3\@/;vlq2”_kg϶=}ꩧN-ZSSi/I"?cƌ+W:a-Iӧk׮LRX;u&Mmڴ[W,99[[)n;9rDO88)ҲpBq)Օ_/I*U.dI7:rb,ejL(wј -kOm}%8WnOah].A՞tRSNYUIׯ_[jUjմ+SۥæM_СC5kWeI@#==rKPPc5L0"+ߴcƌQjOTSM$k%QFȽqpƍ ?Jv\UI% 755.9ۺu?\yǎj?R|M~Us9^ߋ6'Kբm-[H>)U{1O<|ϗY{e)Օ_/XoT f YLŴ wΜ9>CJJ,v5>]uD'OJZf͍7dxi']:>+\ulq$++Yf+8c߿?>>^_xQڵÆ N*G)d2IpJEVSOjӅC&MfÇKd@|rmzΝ7@J,_D_V9vXNN$'NX~}.]qR d{O?$KSJyDDā,X Z̀TdSέjwi[K+d=eՊY3j*YulCuX;$jV om-}uDM}l2rRR믿.A{&jMկ_?u'#yWppŋΝSD%*׋KQ-NK*Xz۷K.H兄m۶Qql3P Ov:{lH^uسgOΝW.{「'|"#Z70`vD] lճgO?ާ2< xiv :aoo7ѣҥK?u ED 6hc, tСz:*ϒey:Ӽ|M4;%]_[ޝ_{N'Nݛƕe{Ua˖-6,p a;DFF޾b rڵk'{q3gjJ5v+"{{}cǎ/gyFVM6]9RobisxHm۶[kV)o7,?wrӧG9ԩS}||N_nI)/{=qKRj`0SVRVLŴ| nݺMj֬{䂏?![lr˵%R+y,b,šs?iRRK{+:T RK$֫D7Zɫ*[gP?C#NݻSRRӃxɓ'9sJ v˖eYN8vبQ= =zt~ H7@ܘ˗wԩvuڵY&)[:<@' @?eՏ,eYLH y)Sے֪UsӦM۾}9s9r$OgϞ-'N3&&fժUj9ǎ?q]wURE@M&m%f_zt]<''GVK2p@iX,#G}K?GFFV/Z˗/K۷oZ]SGŭYFTmvRJmU%/Aj;HW/HTT)tC)")T$kn̙v-[hG//<ݱcG~nZюK%bԩUTp O-M6u_؎4Ѩm)v4iR^l]_~e?P'sn{#觬")TR-[Vz(mk<<>~ذam._,t̙)))?ӭ*VzM7rsN<ʕ+ $nw6lȠWVf֭Yո瞳up֭[ײe}%''K}qPWJזJJ\oEU?Sd1-G_. _uֵJhTO:qmQQQA绾2-k׮ȸW4~ֱcdl{,$j!\zU6o񑷘L&vuQü曝/y-RiBdy[[(prYmu/QXVVE%rT;Iwym=5kqQGDD,YSOiT׷:ڭ[B?.}~Wخ]Rg̘!ִ[)~ڒRIzfܹvuE6)))q~qH3fPGofx]e_Wa~o )O+?dPojgl'^zɕDкu<.Քd;H(a}nR{yyĔcJUKs)R:uG4miϞohQؔr8VRRig)tVts}^uy"}WppluÇ߾}{~!Y̕9~ɷUUYti9gΝXu{N:vubM6Ǐwq߿J*7tS~-9~=q<== ?hJeRiR\)"iRNo4ϛE8|%>%%eڴi5j԰;MեvwpGH{qjtsYEr컩ZԮ]j/׵![FrN<)y%Rs7ɿ[-:NR%xTܣGowRjff歷*bsrrQݻwTf5kȦ2N&IwرP^&Jz!y[Gy%Ekreq~odR[|Yg 譎)"iɢnrkw裏j[Μ9sؾVZC qqhgx]_Ç[-Zm<}dM~VϞ=2`xcǎ-*i]Kr|O^r6͞=r~8h9NMm$ Θ1cʕ?B89n( 0}tWuڵҔ)S kg7ΤIBڣ;M6v+_%''{{{K}r m#GH'j\ZrI7.۷<}G֙t8l޼Y!en4vڟ~%8HnOaaN.A՞tRSNYUׯ_[j ε+S}vi&Ǘbcc;tPFUْ-[fkIOO߿-?33h)U]q̘1ꀚ4oY%*Zs=5rD7n<`QJ*H@jmݺ.c~AW_o&/pEthHJJjѶÖ-[G}iذ݄}:eZ;HJm1LZxW*R C,: O˜9s}*i˕*ڵku}Yu®:Rɓ'%HnYƍ YK,.Dl:}Ypa~լYΉ}K"x//^nݺvڽ[v% M:U9R xx))PժUzBmIIlV:00P/_\^esM<(&8Q~r;&D'N_K.8~xV姟~٨$GDD8p` HE@v:uzvL֭+V~Hzj[fg_~n0`mO YAAA>>>z=4S"H$dU%xxx8^jC2 kܠGK.uԩSs/\Ys/// 6lLGGmsРA4(֜?$hCjޠ}ӦMo-7|s&Mŋ]n[Vﯽ'MʊI*e˖|"##e_bv9R}ٵfvV&׷vڭ[^z$}3%e_t]B9~Z)D d1ESd1-UmֻwVZxUML߿0/ϊH<ӧG9ԩS}||N.ptpT #[6ʒ6mY{ԏ?i._,@z@eOOϓ'Oa\\YR)-醔 Nܹ?d~E n Rz!D1?JPu%KjcVW_-3]ctRӻwouǏ'OMs즓- ZǑcǎ5ʀѣG7{,n: )~d)+bZIHHX|yNj׮]nݮ]Κ5n6vokR*u4v,t)#0-GǸ9Ϩz&Pʅ`OY#KY1ESLŔ솩GO5q%uh駬")bJv4oǵp9uT@vô\E{8P.#@E{גyex/-KHnFNxxԐaz-,:}q|RuLw]D_\K%PJM@@~ʪYʊ)bli=j7X*clǎg[YI@jOJԤ|AxΜe>Ld1-ettE0:gŴ|Na;壏unca,b)7d=AkDqaR*u\ U?Sd1R6G%V.-~|u&N* ' }:D=0<m3 siw~yLKJ%RG$ IF4·$~p˫b2GOǓŭ ˖}h5-#Sݸ8I:7ooܸ>&LhԨQz]V>t=zropvEȻH+zq녋%~VRj3yQW_QVMѿ~O7ȳիW6m9+<<}`0gҏ,eYL1EIVdGwܩ&-~N:I8i㦸gZOqNnJU#=?q L&w.2rٌm1cԯ_?>>+1aÆCAAAٯ#KY1ESL-တfMrGE[.\Ԝ$|G' w;$'CP7SةH%HK}Z7 UʕR/_,ӦM6Κ5J*4U:I8%CYmI7f-p uRj(;ZRk&~/իWއ:Hٳa-Z/^#H' 9lVcHeIARYؙ,nI1>\O>m<{4K.bz/}mFD>;t$n="cMO<hu\S6#Y R&"VؔکS'i7pilժ}W")Ȗi_}el]xփD fl1JM $ 츅[WHNJ)AҞcTk֬zPpRHMuS?DW#|HY/LN>clmz/U#*$tmڥZSjժUǻSipu(.J'#|Rûv=zN|y91Zd_yO Ww:#9) RjZl6kAΑ`;} W;udS.Dzf%sWYDF}$'GJmѢ'%%aKLFPGSd1ESL͓'MzanG/5wL~g.ݒ6nRO_T<%%#9)mRСCʕ+Fy*~~~6 ~+RVLSd4I#o"c{*.Eoڴ#^`y\Cٻ#KY1ESL-2V% kΖpyw?U%Itu)UTD;T uoYRlM_~ӳqh}#]ռxFEaD^*Fg){ڞ=ƶo.R*)#Kjj]}dܞ/kʲf=Ϫ8x*nXAq̓taj(W$6n YeU#'N7 ˖[7Ee9/0:V.PSd1ESLޭ%;d=e-))֬іUN[JNjηUrHNXTtSd1ESLbxzKO' 1tPc29Ts)z(ust8g:M&F-kM|yu[kVm;mFvp{K"mηW}$'u( u[ᗙlNxx²ֳ67zy=37Z[f<.ˍ9.νJX" U?Sd1YIZΞC0/cٜK¼Ye+yN۶,3vӖLtԱ駬")ȺB[O=m"F%jͪ7nbl.arsқZ,/]Z,z++JvM f4iF.}R*۶gNH3̩g6NNӱGHDUwfդej3VZ?(+#+X23# N?W4cbR\5sפ,ii4ʕ{B"ue%u,)~d)+b) Ifg3¯G|~Ϫ][jFFE6dj~(J"9v>2D'F\6`1ReՈ;{}X?,iڗ;ԍubxʒJYI7@\'v,Ad_Yd%FyYO_kV-̝J&4VJnL֙y䄇3¯LK=Qymr5dg-\d]^ooŇa,bd%SD_IRʚi_fqe`yZRw#-%)4_5}nJX" U?Sd1H׿gb_ye-٩۶E}ʪ#GSƦ9aaQXgv#IJPXr"#;X'M*],I"fe}ѳYu"OUXӬS"zasBSV PG"<0w'YKZZۛ#z=>8.åjw#:汉dJX觬"):qf-m焅1w?YKjjM;jz?Sa{a-ZJϕ=q(+\@U?Sd1Y{ NkX֒lͪ>YYǟ:{Le+täTPѰj<Kf&#|5%ئJfdԒ;eu:Vm SV PG"gu"hLKJDufVm;Bfj6EmηḳG)+#@q[:ͤ'P6hLXښU[_$'2Pٗ.E[(5JXpb,lcaͽڔl Vz0/okVnmͪQѮf:G{OYI7@&]YLSwɉz`u(;|9j^c/2'$81Mݶز==hgR>qxDtF*.\6#Y kVmAjھ}b'?}M&]g}|UbީӾYz5޸u;+SV P2`0觬") =o4i$FGѣ& Җ"c vM= e%u,{SVRVLSdΝ 6zyg]Y>=(jx;/)#@a/#e1gFtn[+H%Eg[FdFȺ.vR: n=&}> 5x@J%u,SVRVLS=&,[nM~-)tvMulXF/싗#"/Si Eb;T'M"b,#>iR^, Ȓn:Sd1ESLC֜ѣSmc,ȒRc`0觬"):Mxi5ba,ȒR#@9u|dYL%PG#2ގa)#|d1EtC+;!!!)~d)+bdӾZ]#)TX OY#KY1ESL#kIIuuҤ?a,ȒR#@9ZFѣ͌Y u(GزUXYb,Ȓn#@bo4iFb,: \()")T6}nI]#)60"b,VFYKjj]}dY ux$ Ȓn:ؑ}-تMXG2GSdI7T7`0觬")-S27>"K!AAA)~d)+b˦g4C'YL%ݐRKFFdhy #|d1EtCJ(_^ !rsr#)R*@9zغuҤ_0GSdI7Tw% @?eՏ,eYL1uK؀iIfa,ȒnHK['MYL%ݐRKffdI|>"K!/ɛްN4hHnv6#|d1EtCJuob,Vpٜc;Ng#|d1EtCJu{ ~ʪYʊ)bNtY )|8xPv>9Y )dgG_IYL%ݐRubGb,lޖQt,YYY )U')~d)+bDE}:X'M"^Kґq萨~kk7w c&O! i 9qn#@1pXƶsˆ3bZ2_?K7?z˱T5IJAS ݀ȅB")bZdS{:iX223bʯ& 譎L)")Jޱ$gŔ_MP/z:iҤ'3b Pd?تMkd1 賎A?eՏ,eYL1fsía tcPP~ʪYʊ)bZeS>HBDt tsllx.ҾIAS u%&=68,@K打I[ggH7:觬")IbD3bʯ& PG(_R?:iwZRR3b PûNŗd1 PG(_P`# )n:*b,lٳa-Z/^" )H7@A?eՏ,eYL1KqIV8,j"u%/&eIN&T425Ox_m-ҁ 6"z8mq9qoqR**lpWӐU?Sd1Ŵ& N47b!T@쎥͛}hcj"m(SVRVLӊ,};; 0eP&Ha)q(+n:@7»v7'$g##Ԉ^wY'M PV u.YL2M\zCQcrf 0ey¤")bZ6ٿfl*Eˬ_Og؇)+e%u%},ݵuҤK3@YtJuTG:iRnx PV ut`OY#KY1ESL c}W6qWiOy 0e OY#KY1ESL+ _5F&6dk!mÚLY)+#>Y O}M7.P%eҍN޼yƍ0aBFիw5D² HzO?ngW6m 9rWxx8uǒu}Q~h:nqq(+Rucƌ_~||_Ć SGG Sd1ESLIs> 򹀑RVR*R/_,ӦM6Κ5J*f YLֻnu挮LKY)+)\O/BW^M:}ZS>@o|N @JSåƳgJDD0'%E Cyu8'PV )SNn2111تU+h`>Yʊ)bZX,1OM|԰,TaJYI$6h@333Tk֬I >Yʊ)bZ$Ȯt̾zU||[)+)J)VZU-QJub0/f- SC)+RZV-i7Ƭ,ilРu޽VyO@JSj-=))߸DiPtM}e/cR*q)\IC+Wh4QG;Gb, />;&gtmT(b iߵkq߾}Ҹ~zE#훝aZ[(+Rzii_pq͚5UV -ٗ/w|[dOP1¦TaرM4^ګW/O Œ5hc>Tv ":J{*:7mtĈW^[`.#1c- ugtm@U?Sd1Ŵ$]] 3:RV PG?+EˌdOt* 9;uz+2ǔ PXGzIf3|LI@Xpb,jIxq#mNH`޾tS6dgggӦM֭[ <<<<==;v8qď>(99@_pWSf YLS۶غm֙3 1ᷕgJ 64iO#uŊ (m.\4m/C>`>Rwqǘ1c6nO?J蚞n29e˖~z>>>'OvTbIJg))MA)q}~L-[Ȼ.^H>[J OY#KY1ESL Eۛed1UJYI7رcz"W_=z4To)@d֬Ew{cs(+#/9QQ=zʰ駟FIA?eՏ,eYL1͏ԏ?lel>|[tS^{A.]lv]9s:O!SVm$[}% SM9ҭ[aÆ}iii͛7ھ[T "z`d7LH7KۥQֶcǎTM)5$$D?eՏ,eYL1uȨǟT=f%;)VLu%[&k[Z52Sj``~ʪYʊ)bjG҆H -h$aʷSVt3iҤg}ֱ= @ֶ]vdR=T'aͽZGŋk֬9a„#G$%%EEEܹSS*]Rܕn=,ORt"}x衇rrr)-deE#a*f\)Bqsm[nS=ܳyfBtRSd1ES76MXIR}6'$0ۊne9G+L)"nLbu۬3gnmTϲTNKv>R>)Ç TV-tΝƍ;~8"I7)TtsĉիTKjj>[Z7|< U?Sd1չi쌙=`IO'aʷSd+`9rmʕgIjGb,z6My]IO>^%aʷS}V8SN .8ΞȤ P GÚHn Sf͚)))*-ժUjT7.N /$a 9o߾}v떓KK)ғczMd7L"/e˖~[ZZŋy;C3I觬"MVBSD^h S"[ͺuVx %K:On@aZ3%a %;vlĉ͚5zM7s֭ԋ Pɾޱ$7"a 4X,*EJp,QCI\ [F8T u,& Sd1EJmxdZnmʒn%u ,W^͗-[]~QNJ`OY#KY1ES{%cY/0ۊ)(L>}С i@@v+W悎S*@%%)c6Ҿ)Ttsw^rE=e =<<_zVZQ5R*ɐ7o~x_W(}P`NL'a .TV-%%%ƤIw}/^իS5=ԐU?Sd+KKO3R]"{ SdI7|K#33Stҥ޽{IRSVRVLKkY}p,dk t]d7L)1,[vj5Ν;Zn]]);?VbmU6Q)u qX,.X؆$j  j"A!5I#1! :ٗI2puN{ɓgd&oν.A[ii5:sau5hiO?LYI uT%\z@R’JMkW+VwQVDRº~ZTq#)aIJ!6RٓԽMkjع䥣^ޚw#)K$%kMaa~^=7޸ ?sTk rl5hW_O$IO>,// ,ac{mcS78 Kss3=q7M^^ĉ=YYYzbwf1ӽ{_~֬Ygy-ܒOi:N;eNXJRºı}BQ~U^^?OM 9HI v#6l2r3r饗[쬳Q! ))I;eNXJRº}ڒk?|얽{ik4stNI#_n$}U466&&&w4iO3"7:UɅbڏ[sǡԶ6'iqX*`7@vʪuj}۳d9/nKUMg^wB%GSVEuZXG;իZ[iFۚ0Le.M[Aj/j_dX* MjH.e uuƩtǤzeRPW/4WkvgϾ{=ZJZ-H;eNXJR:[o3:~~)b|v Y-X**aIJX-O~Çw|mUUUrZHU;a)+I l4nyC̥pu^?vyUWy66#AqbZSI s=k;~}8-@7[W3L'zÍ$m'Gicu3~qn-==kkkko+-W^y%UR`h|=:z-{33 y v%nmee%\2Rqw}w̘1vf09x+)ijE$,Kkkԛ;wpM':dҟʧ+dTnk׎1 dT.= )aIJA׬= gGԛj!ouu[mdrFM[/ץn?/Rz-lKe7<,ͥ^oH}k%DWoϺQ Qc/oٯ9~ KRb7}#И:z߸'j;q3_q4u6ڼ;Uq:՛nqPWb0sܭ^DuR'G4n:N;eNXJR: 7Y5sŤ}U{q/?0C,KeW%,I YX`Q:tNeK$ KYIJab0^{u Ԛ[]Ӻzwz lQ5w*(pQnTޗHJXkv+c}~ʮJX O:@1@o ,K%66v ھ}NIIq9afORH;eNXJR1ڒIW~b I T:t())iѢE*~*v~,_KR"22R;eNXJReE4%hnňiDDo(nV.5//ΫbT'暚IWZR?zq_u:];9IMM-..VSPP Zj744y,JbXROW nX* 6b]ixј-vT x$@jVa0HTWW+r*NȩXj\\4vzҬڍbQkR􀤄%)a$1$O"n I ;ؔDDD􌏏lhhp!6m[jfORiHJXϘ WtT\ʊi0,K$% QRRNN9mlltEv UVaX* D`H}qfX@,K~~֭[lrhѢVM^^ޥ^_5:@ s P.^XӁR] Nj',e%)aڕ"n I gfHhRRRB``j^^dRp*/+dNY~tQ/?:zeE4%~&&&.Y&"jy&Lؼym-WR``}~u t ---YYY"~~~69]lYrrȩbQ T$JKǍPg+VRVčl| .u*r;V"ne&IUԩvʊOTI맟 @vRDǥN}||DNYV+7‚IKK蛶N9dS# ,-P\y@ Z~֣iƉ::(!)aI>a5q#,655FGGm7v\ZEGp]*PGHJXj6l'XRlaـ6##cڵ+VP>KXtSa۷o/,, PGT*~337‚E]: M޽ցԫ5X*aTTTgϞ7|3&&6 OOπ*pQԌ 8t:U;a)+I #@j}:ʊ XarssSRRヂ9XjTTƍ/^,w_xu*( ʊuzSV턥$%lt@"neVSXR\\uָZ#?#ڔ'KY0Ta@__+7‚c2u:觯o;- OII-5]*јqTn: ߏSFXp7ĈOOO{'uwwƄܚz NR1su otFXp mٯ#]R1VVצ&z 긹i KYIJخhu Z@N#eRU 8ʅYYY]wmadn#*Kb Ng n'l6;Tڵ_t599Yn.,n#ցke K%,hhaiK”jb)@? č0444o*ZRe#., V:#)aI@ܡ,--q#,ƜlgTӉ677SVb7@푷GU;a)+I ց (+FX6`)(( fHHtx_XNK,Yg/,Can@Sj U;`455fر#::Zպ:Ҥ$R__vZȅu.1::q#,8BFFڵkWX!)f͚e˖)3Ҡ^zw+**, } P>STTj',e%)a1u p U#eRU]Qԅ㓐k׮/8DFFj KYIJӘw#И"ne={H4OOOix@S| JX#CJʷFX蔪*N joVR9]z;bccR  PG fs]w[R_}@ 455eee%%%ٟʻtRi)~q_#8YRob2ah4%''GEEyxx/!!ANz P$%,IUlցד(+FXnf9???555..fr[ZБL!,vPv5)Ӹ$Ukئ䷭KXvABS1SLݣz;* a /Lnny@;N$DDD(644Kuai1[qE*FX]Limm-PGBi KYI&Sٴb MJY7ªo6LNxn&Abo%bѵHJJNYTafH~7mmq#:6`bf^^^ RGF,&S٭YRFo nuuzr K ug[X*aSjjjL]j\jZ__O/`7\Xz-ց; č.Dsss -Yd.5n::'nnn)vRVj6l7w*)+ʮ)]Mmb PG:zց čNMh"zzz*fo4(# h|=:z]\٨T&A `$#NI čhIKKj賱KMCBBI;aI,k`.HY7 )-ʏsssKMmsI!,vqȐ U;a)+I\zցԔʊ 1-|"l_sݾQMMM"֭oVIl ]G|qu~Ҙ:z8tKUu+V 3/_ofggϲ`7@4ާ7ԡXjߒwU]vaDGG`7@IQQvʪ ۰qjZVe~饗<==mN,(.AYIJXc?NYT;a-CYRwX*e u:]TTMNOWZLd0(+I u 3̚X* ,%///!!6r(_hMZCCCmsv@GC5׊4zK2%%eٲe6t!촴K#hx 5333..6go@@@rrrII uJ􀤄%44ցԴ4ʊRg4!!!77d2qCX4n$%,I]4l}z@PV,Ԉۙ+VHOOeㆰ PGցS7Tf9+++>>KS__ߤB:}YRCW`8'OܺukPP"qqqbLut*t:vʪkn RV,HOCCCSSSـ KYNHRRvʪ[ցGX*en< ¼/ PGU'/j%sy溺+iHGa)!!!,x PG^aE\ Kv)`7vcs;cڒIWYR߰TnSOOO<榝j',e%ZF~Ktʕ+{)0a)+vl4暚IWʏZ?G/FH`NɀƂPGvKYcH}|]BqR;"-tKaSn#8++'Nc ehjj \ݮG"< O脰$I KRԺ@')b dTRŋK׮]+`ocǎmٲ~Z߿ $%,vNC j',e%,լO:QV@~vB;>jBY}?䶴H;0aIJXKaԺs<Ѩĕ+Wzzz bo}.Nj/ټysJJ޽{>뵶ׯ_o@??-[;vm NbR?qZ[[ӓbbbxvQNG?TpcsvPPБ#GRSSqqqV4M S䉅555*~U<ੈlf{VǢ"U;a)+Id+W=MY^%Gb[ jߦ&OoZhQW*b+ft:^/kW :ۙ/qCXPj',e%j,\/?䥣(a4u:֭[cbblSLLLG`v%-|"E5G!5r[i/y#/f򷒓Ove{'de%K]nS>nHJX#؎{j%s=WWXR2}^W FDDt5T*җY\\J$nPU^x^; AAAy^%KKKPv'X;Զq-dtdTTJ4xSm*fYo='''---;;^<7)`7@GT9KqX6K a[~?'񌈈h7ۡRJWhN՟((( ==$$믿(kjѢEU6`7@.= :tFѴ9pdy~ŷ , aN.!ϡRռ/L&^lw:CT7?~<88X~j*mϊA6 l%)a4n$RGU?Z1!@sdoXXXgҵkve˗/_lի{ c(n::NNYV;ITe}(c3g5uivEb)..JIIx{DDDBB< 77wh*}G Q nݺX*8$%%i X]+}SnwnjjMrիWŋo޼9&&飋-[fffyޗ* aIJX#JRln;~#]㫯ՆGT>Lٴ'/moMRW95tŊ0>>>bWBm'?~d2 F1;;;---''CAn$mee-|ҸU{^:e7R %[WW4;mH:ͦ¢a㦚nVL+NKn:М3KmqhŬ_d5'9h=|Srn,6]~SU =/ zŸoLҴ#{!} |~l6Zs7TyyW̜U2N#L"UWk448gRmf;f upEzȗh`u7ۢVcs\K3WV0jlޝjx]ʆ }I4&"牊qWMv~flᅧ/ M쮻?+&(vyUu/2.J, ',  Zh=ɹ*<"ͼFU^ukbŚ%ƅJ?tSEumK.L8,i I----jWE Zʠ0k6˟n+)1;f=g-ȰsgӶm'ǯ][UR:VսuZw5+рoW-{au? 3WU +fhѢvf9faIJX؎HU;a],b^1l ]XS\TTXd:n76nyD꾰6yQ*g^oG.zr KK~k$gвgO[q6TԕDXn:8!bje"b/- 7 8ij͝*i^^^JJ)vI0v )u'3fEТY^g׆fWT#QS$: 1/5FUVs?A6ڛOG3ʪqɣx@M"|U-ɚz|oz1^cǍI[<K`Rx$0Hwc+JirrrLLL;3 s-3J7’$%,vԱLkh\SӴ}{Bkzq7%-(( }㮻%| ff7a>nHJXڡXjSC{,zF>wMߞ[Y:wZwףmz+**C5f uM1:c>w'^qeB<wHҌk׮XB` ܸqG}TRRžPGSVwPЋ/b),,LIIiwiHH͛,Y"w=\`0_`7@A:VR ?**:'bIZYYmf+-Үn܂R9~thAg, ;kCڟ{-pB/I CVVVRRRXXLݣ:]ՑR*M;eUwXz4Vd Y9GOk3ӒIW9 jٝ[sKu٬j^ez7a>nHJXQG}'_p+,,t)6m?_LA (lm'O~{BkN?`X^cv̋%z K:WeJjcǎ]r%3f(**:~ٳGbyӧO)#hRs /OݨZ 7wBoukl7ZDwRnN7ͪTr,̙s|{RWwE͟?r`)KZZ>ۦۛi'7eCX,:=wҥ Tr,lK!}gqQ,$J0ʁ}ٝwO^NKv媖~dinXjqqq- X6߄!)aIJX,U5AtmyiRajgsR[ض6 6V>ǒS]Y~I ن^ܺ97%%'b|ㆤ%)aT0sL҃7:tHGX*h KKKNWBÏxZK/UrV99_C}ј%KF܆^,KuijvUVVJqTЄ67+fZ>c1'/--f9~UFAAAhhB'҂!;KR]#GJ7]iR]QFIqҤIX*VW6Fo='ǯolgRz￟|rww}B~W_}Ud޽{eee N+-kKKˁna+Vضm_|J gHר`/]nR+RUh+)iھjN?.|i3L]RkkksssSRRIE<==ɦh͛S|_x5k("_Txy*???};((H"O'%%IOO_+=aq`3=~1iKfzU =6n$3u KC _Saɒ%b[bz"_ݎ/ufggo۶-''gKQfO=̊6qPfmË^Yt)3fJKE } -OOOa&qCY KRj_Gy䗿7p#~X* "1Sk^f6dy,Uc;v{)K.o۷OUJ^)|W{ٵk7o,&l21y׮]/oٲwMKKW<ɕ߯Ln,l.C^N_r̊9*2Dfm&2+nȬC,x'NpKuE0l޼y_<|kiӦv,DƸSG9lVk4/sY, 72I 7V.35!.777555111""I111؆O3ʒ QT׮][IIJXnPka6gكVTT(ץ +VΒ%,`GX$%,I hPkRѢa&EkLRBB3KNץl6ٟwg'.^Xdst ߙ5{͚5wVNUǼ\d8a$Eg6"fs/lNLw'O_.^S6hѢ[feeux݇&Ϙ]w~ujoYnKY}u^޹Sxyܷv=9Z|,\F;hGZ>n_DKmg=s(?P5n9I|ImU&2oIN\?U+w6z]^6Zl~#=ڨFu:]^^^qqq6JcT1igNXJR%)aTa/5RGLtˎx[wG]{ڳɺAAAlTv/q7)&A؈Ξ$%,I KRbڴTmcr[}*^Vq*חWLbD!(?[-6Z֓uGdqM137?dQѰQRUlGX2WH|?(;\9W\uWȍ+&5Ѣ Wz|{6<8#GCz𨇇bIII)))65LlWX*RKo_|}5rSwqk_&32Kg=G`T%ߕ|ˍ7fAAA7nLNN{V.1W%)I KR’TaTWԊ :w=ץ֖;v,//?߳gOzzΝ;o'$$ŭ^:"""88wao;WYЄu&\!Ƨ^sjnKR’%)aIX[@k6kjj sss333E6SRRnݚ#s7&S~~+/ߕ.A^^/,KuaK3߸ݏ͕:z1--n4NS7o ^^^(7l)/zg=ug]y'ϮAZ_/Tl/(zaŋ=<}m֫( 4RFss3 =rĉy_|OM&ګ(p&6:^O G8zMϟ>]n>_CCJccco馟'?GsV}Scbb瞹s{499;8.ӧ޽[ %sב-"ȦhXŷ['nڴi:b@<'.oM+,,ߣy$1]u#ae۸9看.HsuI:8r\ч-VGN[ K>jNبgqZ[ZZ:y1cƤ_}ȑ~vvFMټzj| -))qaaaR7|SHDᅫ̵{޽{=lĈ;wtבsnǎKf̘QTTtٳg=]zmhG^#I{Ll;oW]HE{III$??$wu#I~#}b}D̨R :묧~CtRW_}+M¾i0Vށ}UVٷ{WԺ:^2zh7ŋ@m Å#)_w|3g΅^(G]9J͟?ц~vԑNv=}YQQQ$:3i$ ooMΑøvꏨa$88xڴi"D;vSϝ;w˖-*.y'l7 x9~4͏=g鼽[%OSU*]`G{<.GR Hݝpsϗ 7zyyq{mhG^#IIT;oW/ґf͒|W.o3쿽69G+zۍ?Rɓ'X?Z#oڴ驧RwqG-ђKiToɏ"##TSĔP<*_KoW/ؑ":নN:PpHnJumf;Hcttt +t$#)gE:g?5 ˓9s8ۮjs$0xqEQ GX0_+cJ_̛/-.O?OuY~ͪ .`ԨQFQ5UAz5״DT%sHvpS1bĤI|Ʉ:W{L1Puwu̙~ACIцkv:ԑNv" {gvAK%\ ooMΑøOWwFTB"˦h&[oU_\y;#(IwgYF޻?L0aϞ=7ׯ_/I~nG$__p"1򗿴l?_u$@ 7Wv8nܸ^Es=+t0i)aE:VbhwmWw9t9n5Ty׮]Shd<3,XnJ/;Yg%ﮡ.><`;я~koud:;-ѝ\XX}+blE[[[4{T{tW`RGR t$};\$oMΑø GQSGX0{_}>cgS}qM/VbʡԆ o*>}CH}ʔ)y)E[[^_IKOOWHT:*k=n~'%%ENS lݝjs1b8Ѭќm Ixayy8իW˧Rcccjj}''nN10?q丢n5 ?9r'TKɓ'v5f̘^xv͚57>li?p}9s1 u6446,)n=L/"h0n r16WeOlh4Q^ќm{Lxay|t]tW]uUhh?`^uu7\Iq+F QcNr_~|hO=+:t'?rرc\sݥ7OۖݻwKl.yEp*{,:_G^pWEt=W4o޽tU"r(FIt"1gd o3PekM 3lZFj4nl @,"W?\>wv%|>=89_y8/>qռ#qɤ *73[fkNJy~jN9Lq0ۮRA oϛU~{V]]F:::f͚NwXh$ eyOIm,YG_,\5nxKY),ϊ|bxN5oFȚU߄kP?Ӭ3ڋ oJuVyڵkɓ'm7+VH`ww#""<:eک^~mNٿJՙDZ풅Q]Yjt-**xYY6XQQ!;vL}V`ûx vҮiUW)S޽{篽CmL0a\9TTCt[x]tI{.&׳(8}u 7gI\~juuu\`G\YY)YXߎׯcSe՟DOYŮ]>>_}GhѢL0zu`ʼJ98fsJJJjj^~%… ØlPRmF2.x/^DrGykP<3ڋ X!&|e Ɖ'|R=űc}}}^zI&Y<++W322jkk=(HXQQy! ^~2ZgItm$1oksZ<%ׯ,\2+7|\ٞ={%//O6/_djC fFp;PLYcnn3f̘ݻw||Or#uucg,U갬b F@ѿX|رcgcZkd2[.**JrOJJzw<+Ǘ_~Y/88nS.{;e~X+H%%%r2H K,9|KNd< ̻{;wN.n*nζxc 6CL fnױi={vBB²ed=ZH}֯?ɍd:,ɋTJq5554Pټyɓm׬Yk.!Ltɒ%G꯬,)oϟ_t4? A-l/ٜqFɴo߾3fh466+=믿{Om]3 T*~ղ.QESSVotMM{{u{zz$sqRI=fyhznUti:u*UVVV`znUjttUjGG9Pݹs|N*Mc`o*/_._/^XJ߯u_-**f+"_/_]Ǐ5jԜ9s\b]9s&;;;22Rwww[O>9sfppphhy󪪪]5556mZoÆ ##C'>(55U~(|A{ԣGJ1n(dXV\%C &H=}\:9,8_vvvN2E6l2XLIHMD|G͹sJ655ZJ"W&D6333޾}q***ۥٽ+U?*O9K/t!/,,ݻWz(y}w2u3Fg͚%={wH7˥M^^ޥKZ[[>i/uI^xAեa*UH{ XYDZZZHCCQ"ϟW"Ν͘%x޽[<~j?CHd_K-.ͶmۦFF-ARfŋ?c |醌UXXj?XHT?-:9,J~WR;VZG"՜lgϞ=>}bŊ $88 >Uk޼y7n(AgqRF{G63ҍ~Z6{AWWWBBœ9s ˭*[mr*UIpڴi߄:_JiwgJ$$$D3flJf`uDD4rJunʦd6\jgiRYYip3V\R:va.yiԑ#GJ&mP\ߐUFoAh FԩSJ֬Y}`<,J9xaR4ĉyĈ[oitvv:t޺RJhL*H7:h+#"zzz 3//OK R>zWUUUPPP@@0V_~D֯_l&%%frrr__g]pueFF4۰a6xI \rȪT#HII{GۦlٲeEm)JKK_os3([VT6ݖR[񈜜0~fҥ󖖖͛7KO?[W8p@Om Fy ٩4谷J5ҍ7|S .I$$$d߾}%44Uի7juv9sXpԕsK~aSOYV=,T)[;Ui-~ZXJԩSJJ=rxxD L&Ν;OB=-g_}UuzZ]VZy睿Kwwi> nH͸cٶmۤfNlvCEYd-b|XtHAi&!6w9sXpE2`ޙ3gj#/ [JJJfI@;saG;O<Ą oF)TZZsX|AjjjYTFfۺukllĉ_{5{EjiӦ?X.g } endstream endobj 61 0 obj << /Length 2026 /Filter /FlateDecode >> stream xv6=_GfE=Yy'kgn;>D,%ʷ8m"Ač(%ua9Ɂc/]aq^ P (-z}>Qgc2++'=Y\HiP+T*)\l0hcb3 [Lep[U"Q߇-];,vb󀹁g1 "!,iDƱt"di=)iJq&mJY ̊ Z&h .%ds}e}M; `0FRGd' `Uj`P].;)>2`">䄾1h_s㽀,7ʶ Feer% 4,@Oojyݨ|-umT mnPځ_nU8۝͐l͊NhE <9!BH$H0RM 0ʜPOF!-7rp.p[˼$tJ7tUߚ&2Mjɺ(٠3J:O^#4;dxaުscCbbZ1!`]ppcI@$IrmjߋaYgql5>a76d89 CyU ˢ"m mhLiyh'Q>FXh;dr üjq/reF]99Nt?+h39Tn,LN5VMM^+0S.0N@.#UwIDo~u^:RlPӨ9b93yMA+ݶmiFXxZIOӄeF]Ϊ@lj!88T a7>wشi>"=4 c,Gk3ms@߹fFf ϱiVU(:DA[)R`N%7DF ZBq jUآ-ÁCHL(Q˞2 s@#V31,t{E/pMܤ@S /1`ljDm\m%A`Y#M%\--SxH t@} HRĐ?Drյ6_]qt+q`ځbd-N^1-sMV^,E[:Tݓ0hLrY9o,1w`c:DoSj>Uo:1sZs">Go 5 Q{K~z o,tS`lkQؽOo4[9FU%`=~4d)dzMv9 f8 )fI. gSYq fa ~~ؔK|u_Z|C_7= m{hB+ͧ>ԣ!W8'`#%.`q(, D޽qOW{=Y㧻nV3Ʌ1@1o$]/pjق}o' u.9Ù.\ W#YU\ࡪ¹geA1[B+5V/qz]jsB?6۽E-cN凜<ݖ:-}<Ց:TGQGbϽeN}:Jn?:rѧ/-nt:ROarĊgzr T&X),!an%>> stream xY[o0}ϯ`*eNy(*B*t }vA*ė$ǟc;DP!H/B$(#3r<&0> Gmfi9^j o _ endstream endobj 74 0 obj << /Length 2875 /Filter /FlateDecode >> stream xZKsܸWLn-MkreəD7|ש)ČX$ǒӍn%ږ7sM Hbp9cԻńis~{?g.2XoK!i 龌@D WvFZ-G5# yyŹ.0qbwq]@ ]xq-~NO..k{wC+6I]'\־7JMfm|Wܞ6jdP8Ny+<*m8\bsZ5n+Wؠu:ٻYG?ii[>]( K-_U1N_oA6/dɑk%r\,Uc #=YPbd5˫9WafWlD̬f!Z:l<߬߈ E9!pe(UVr`mB5cOsAx@=aAe h>xYHx qzu+TI³nr7 ݉@{8|׏Nh}Y%uHdW{8͹Y<\"HOD?ծNgEYl)Cz$Ho+"eyR@e[մUMTiPITq}u]A yqWՏPp/k<[e@ݧꀞsʪ\&+4i9ތ*xBGҪjp9ao%m *wٚ-?d,6ho% dYU eYt5x 6(T9-Q}^C̍XvDdVޅ)Ynq$s?vp4)Y}Sё-iizK1^l,EȸXz t0Bs< L:LРѧ`Z08yrY1@ Ov 15'PmL6`;%Jo/ m6熿ÈT-ȎB9vp>MCP94Vg)h?$Ep~:-n=\%LI)hSimS 50Ybش<$$- 3 T({.{4sam@j3kBu!C` S q/+,!P@`(%,,{c~Skk|^&h3~T8uߛ7͑A'?|hs8m^xg}R~"GsV{I@47//hߺ bZ|߱z0tAONp"NINVmmZUffϟ# 6s a6,T\.yY}K% H٪b0qGMι֕^fgR>mc›V˩!LC be 'us`U?|deMNu.i #Pm8֢!tHGPi!y lѓ=*vE1sƅLԼAB]\ lDS\cCs[뫷kVgGL`+聖P +h&s4ܥחW俺{ MM>-M t*ɨ#]] 3Xm&<5i֧To{z%!KkI*rk5t+ψo|-+c/K ȇ͂.$0ϕ?,oiytۖ*itMg O1~8z4ҒT6paSJ _RbrÀ=(ew(qWmF!ЈHt=\F*jϰ|9 Q' <Og>FWmpӥ@5 Ȣ#@*d.X)RKR5M,$ ;%>dV3 U}#gwXV \2"pKI‹&I MSh;J wuNTFynm0b4b8\@CʣCY> `!7gX:XZlZt7{AooNmZ2Ǽ^/|_ҥZn[}[ o;QW.&'ۮ~œ}tႬ(&V3PE9P=|ۋk\,)`b@;=FK#;5 }MkPp2\k$>8ޱC1tj%~Fȑ).ra[l 7:|8[&|:BKu㱢 ^q>M gPxRڑEr4ٿyf endstream endobj 87 0 obj << /Length 3344 /Filter /FlateDecode >> stream xڵrܶ_L 8O,jmŵH5ܒ\JsɥDj%p;[mV o7~=72u^E* "7UQ?6Zt<97G'a8FLͲoכ"cZYnANq#L+f_ܮ^o +ӭޚ޴={{^_WsMpu_eL4toum^Nn')t/3vvT>P$qg3Ȉ .>ǩ=[>"ԍX= ]? yR|8 VfōhLxwt@{­6 'H~.?Ɉ5z$$Bݕ-jh`qyu#wxݬrPpU]wŋ"yݕBZEBO)V޴>SsLCϝܕgi8TNʓ([29|uZ,i<¨p~pVly5nIЍ#+B?{2 1D8G78x1Ie3} C+d +ݖ(R˦F0.)J '|qz\ښ,97t*S^k,4H)>[=]37JHb~dd<sy-;M+/GJ'Hnd)<ؒ6(`<yb+7$B%ަQ~knMk4:-X)dP̎؏c8Ju>jVuZE! i$ CU$t석FK@Qwf۴`#Ɖ_mʼn; KwcUqۊA5:[ #Z]Cx4&p01r3ys aƬj,u~ y3vNbq&Y킙so*C:Kde7Ua Q93.05=tu!| ]I2 ݡˊX@"Gaҡl/._OSrW1ѓl:30wNUow&ɶ -8U$1yHoْ[.-1ӭ,RbcC'J>f{H ?qgء֊;&+8 U[m^_?tBwa͛GΫg4QRm.S^&Fݻem wz:0v:0ߜ"o\Kk >!8צi &^i!,t|*  E @9?R({Y4F`tBqlIDŀX}sGհ#b]=^;L*%<ܖ?$<"3c/U+M,MJ5U{30̳\2N?IF|8B-x5IR)sCW 鱧=9n)(|4G'pc= J!o(sJBY(r]_ntoWG' |-[ tn6pIkFV`5Y\Jk빍p;*]BYЫ a߱pپtwmy4{}o!\*#HMdxX B0L&&ZN|KUt*HIE3fp]*:6SپbWwde[oaMVuǻD H⌵د1KT`S{tOFD (,|QTLE+SQb}cMLՍqz]x?\n|k3> stream xWo6_C@ XC$DʾTwUB͵^3WIk'x<ߌ}knف; dE̚, Y1 ՚Xd:.,̊jAuW3Q `GZJ,ꓱ?v \hl>o*P/fzT9n2aʚgjW-eS d.:kIR6G\."޶4!Q+KFFhP]Eؖ2nR;(WYkE* ]|ftDhmOF)/ m Ei[4}E7Ձq0FjИ;f jg,F|azbrp$弚Cɟ^ ˭E6ne.Z<17D G΢$/K ^ON@Uj,-Wi1 5VUEB"md ]xnVlEe o!Í3Oe \_8եyV ` (|6@(fj5ʢ{7ːqêХ*^f+9tp]w]FTP=Fp5~QM) ȕ`oۅ ki5VtXaBb-PVG6u eQ@b jLYx1Y tB}mƽ ѱ"(Rm(҃|H(Ϋn_y>.^6~׃xD XMoM;ۍˣR}R&gkP|eNvh`p8fP,Ou. khޜ/Lp)^0n!h=H`"#bZ*Ejzz*tW`-+ںZ;&z(4?}<:9|uοGFxj Y)!|5XΫ]`t狦q}R^/VbM *"r. 5N}ߺL3`Y[ӴL5F'׭:8^urf`+0{=9=gx~>߆oɿ|8$ .F49vfU˭ׂ@~/kOޔ|GR<!/gגҾh6-n {ׇ_c}$[U>y7#k B/ kY8RcIȈ,59  endstream endobj 142 0 obj << /Length 1842 /Filter /FlateDecode >> stream xڝXKs8Wjm<ܛIwV&!;%8 RFlm n@22x{%Ͼ eĄ(IXA^*4nIyfYLW[c峃_?\UId\@Ey"t&xzsbi%/v84@D-]ϫ΄ݕ |my[noo?1WҎ'>?~^ݚջ S0IDό=Flu"yC迿\R+HgӦ}m&]ZԻ˖i|h^0pA6Uuo˱-2#B@BG RFA* %^ꖈH—$@LG9xqvl83Aq-*ϒQw`!a[7Mys謼{%3[[ؖș;[;lyT['$y%{+%d8;v`Oi1 u(0XJ )JfS AL$3엺;xبX6%#C+H3Qv,OE毓A m@C+?#@acV8s*2 ! w\c#VV|lcgd䌢hxz7HoE7XoZqu+X9 76_dd 7 \*xi|'y>(BJi3t<˾'AUB3tl``p Bz R{vDUc{e&=j2܃'-b;b?IbJBк)cPe K2*ԑyc@z4d ;)yV0<9%kܘ?%zG*!ÓzE"ajoеa>ë 79Vf<O:U_ܞZܱxP.)qnjv ),y?h;a8=U˵XXdɋMUu.SDJ Y ^S-dxW`hDǏ,xj,N.%<4P[N\e S̀녡M)x4nc6iBITc@r8Bvɔm!nM^G!dʊ*bʪ?倍nX^PծbRu;#.R/a qV#ػݘ߹K-eBÄ׽/܋̣e>cz}Ό&gbݛgxIܬM"~xstZꥌqMFؕ׈M5ݤs^x*E>%蓒]?]8ښҾO  u?_:՛fj?~\n'@9X)CP endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 814 /Length 1762 /Filter /FlateDecode >> stream xڵY[O9~_%TP"[TRw..$(w8$}xs?>H(Q HD'HQ+AV$,! MlxI,(ul &,X L4 0X`*x mEhDx]TPt8@B,mea0hh+ ^[Ax0O^x.GRE9N:@XgE*% CtAG P9;D`R #ltF$ vP2J3a)$D:m(DUX'#;Cp E |hCyqhHy"(y"4q 88LC܃c0Cs [$!q8G9"ܽAB#CHU;;>ב߉Wb: %oTNL '030?y_NUY:ϘNΟ~Y[]vH=U2*U~l Zg̟f~Ӡ]a5Ǹ Ƙ\Y˶ +GLK׃nf7[96w'-09G aQVOՏY@'ZM/u[G$sYͫcJ|`zTןwϮ p:ALFE3Asy~cx}! ƠDw{;瘻x&~>iUK9MUΧÿzw4lsitZcu]L1\~9$:>ފn$׳qP[/EҢK$5lIFf3hַWv":hf\G#rA.Iרz$. m+p 6i AotYVc)o'.0Ҁ]}:h'PŭD2J5Gͭ+c3m?C}]/u0:.8n__ShUԩdOJvϪ*B ! w-oafEXu/7o>J]b Ҩnla`]P^|J %Pq@yj,ItawEPd*BR҇"M-$f T R[fl ݌n$KD4?r%$ nuP;62tN|A==nnBe\T $A-j _"ڐT~M`J!Jrk;u\u-k!̥ n^,T m)bC^sRBO*2Na(2rR2l ikTŅ"2Zd5[Q:W/q4fM֧2G^a*䋣,B] p ,P'*"s)ĒAU^TѱpoBM?}[U}皪~?7iƄ@=0,}2+ endstream endobj 134 0 obj << /Type /XObject /Subtype /Image /Width 1597 /Height 896 /BitsPerComponent 8 /ColorSpace /DeviceRGB /SMask 147 0 R /Length 129307 /Filter /FlateDecode >> stream x XUe䬌D1deNHkrss~߉6!+eg}{rgϞw `R*++K_{5`ppMvvv˶X*[[N?s_~)+Vh6Keɓ'xjja0--MŪmTb7DpРA-0blգG5 Etqqi6Ke+;;;ohh0 EԩS˶X*[x}}aN{Ѳm#V'LPTT$""АOq㔸\UZZuVj޼yEBuu3lmm$%%UTTTVV;wnѢE;wnyih6=q+I@닍U2taV۷{^[[;aggotmFFdN{ 58ͦjt")))^zɓ'6Yd믿~;˛?#K 9Ҷ,[HJN&$ #l/.Y(>vX 5{yy7p{oNNNNy&Nض֙HJ&$ #lч~0X\\ܣG2da>>;w~'53/_>l0''#F$%%i6Ç*_^^;tqqׯٳ y)4h?ğ$(wq@;/e˔H@@@BBBXX/^Xm|m_ddd||>* ^z&33JUJ^ ??p>… ׿Im,(V8{XetٰǏٳ6&Mq, $$D,~fJ͛'6YhX{ey~PF'cEN׷oߚ~Z77KJJd$))0^UUelekkkINNۿ,uSN]^me"odիb_~J1cާ)Ҟ={E-qbdA@#ڛnݺIiNN[7e|رc-Mhzqad̙2Rv*TTT\ZZZWWwիW:t˖-nǍw9qF{gdtFX:Z/// =7olikkk)R.ARG,UTTdgg{/\씊E???^FEEEMZ֩d'x*V< 08m4̙3Lbe6h4j'N(&J|Ν">z?\}ӧ8QFO-?S[x73yjņΜ93lذȌ K۪>|[yyܹsiӦfTƌ#v%RQWWdJf?/]\mmS?ytQ;GvrQ`!#@;Dqh(w0h6o!7[ntRUQǏ'&jiiihszԩS &744?">n8%.WnݺU7o^aaaG{n+5\U:իSNU&]v5b,W%uV>,>`CCѪ}y5bTffzK_#~h.]mJJaW^"~IM,YA}||ZjZrfV-"hU8K/$K,1;VCCC^^^>ܞ={Zj:}Z0E߫$qڏ?l,..ѣ20߹slРAZ-E߫$qN׽{w1Žxܱcǜ9s<==:u222,X6yd_t؉r„ 'ō?Ul>e-Msssf[Z9bzz%KK$gڵ⍋˓O>YXXXUU%V 8CQQݦ:T$*&&C߿z""" ' `p/xwٲeJ$ !!!,,L/^ccc6ܹDFF>"nZ/2[AZz5MffS"$$уZ?78qDee+"y7n̚5KDDN688eee5{l뽝7o,ZH˓&MO;8^ |N۷oMM?`x`mm[AA%%%Ғd2[5$''߿_dggf~~~N˭0m]~]F222d<mQQ܉rիWb~gϞ"hbYY>(w@忏W]]]nĴ6''G,9rdʔ)rU曱cZ!כE #3g4[wruuU3-7 VTT[VjhF1t:p; 1 >iy3V*ԲU0Ec&c!!!E*Ӳa_rPzDwȑ .4delh=zK+PFg/ٖj،ZpF)RNDعshЭ[Fm}ŵ[08YB _۷ JJy[_gcccxۮ]de˖9::Z!Q2}F>7=5GlF٪vk"77Rj+;GPSSӥK]=7I\\\n&k/˗/˸a&<<\Doߞ5k,\pWYmܸJW}]رcUUU2V[[[PPpȑ2==]ك#ʠ褌ٳgZ쿩ZMXZ6**J,.Z?< hCӦM3Ϝ9sʔ)Vf9l\N8QaΝ;=<>ه۳gOK͖;tJ 4H=uTd$0@9p>Æ=z!C ;wnޱdfl%ȇ_Iy!IN׽{w1xܱcǜ9s<==:u222,X6yd_t؉r„ _'ō?Ul>e-ͺvk1퀚cnÆ srr1bDRRRN8!zyyH{{~͞=fѭrGt\/.[L$$$ŋll;wx__G}TM6f+9W0`@bbFsvvn9]UTTFvcn("V8{8)[rqҤIbQ$@Kxx٪i* }>{L.t}ֺW$JJJd9%))0^UUelekkkINNۿuejeӕHK]mUWW':881cޒ)KMfV<}+s' Muuuݺu؜xȑ)SUWoƎki,כE #3g4[}ruumtmt[oe.52dƌb111QTWWH٪Hի͝gOVXЂy,m~`'Opڵoyf;wrxiilvllթS'H߾}En_vzJͱ6OA/,,Ts*"ҘQFɞZSg|=Op8/>>^Lb}||{OO\?t9sX}0bggg@x~埚cm kjjzFYF S"ׯ_3gN=Ν{y5S%׏>zS RV~>#5b/}"Ҳ}ڮ]?~|ĈJ\w}b~<<X}Jy *۶m3lju7lXFurrM=fFKOOO>W\Q=[Yr~&ʨ}_|QcGpBøpAAAV&VѣG z otԫ&;vhꡭ7^y%"0%%IS%-{UU?>#ݳ#+V0툋0_}LHϞ=mllt:ٵklWRRl2GGGK7$JZVnh ;XF"oo~Dy$7ZtlZAEƍ'B;;;ƢKr0fOV_曽>k (wqnGMMM.]vjXq777jRIffa2nX ۷gee͚5K.\h~7n 6ȖX?|LܻW[[%"AAA͓mlmm-HtL6KNNgϞ]~?,=\YY&>>>"\QQ*%zrKSU+TmK ӦM3Ϝ9sʔ)VfFZvĉ~~~YYYJ|Ν">z?&uʱnRRRꫯvUt̙3Æ PC{{>}dC^Dd(w0@ N߿N0HDD!??駟q)qt֭bռy =؃>b{{{[[ۜv7n,[LΝ;DJ{1cؼZ'rX:+C|hUJJJ߾}YtItxѢE?FLWm߾*++ 8-NvELSSRR z'Omdɒ_vӲg裏YF]6]`O+VUmUhү58-^%Kǎ+⡡Fq//fnϞ=-;+NMM:tx#=WKIt kO:ՆYZ# #8 ?aG">dx~~~Νw2Yiϟ?ҥ/SOu $A>*$$ MFGtݻŋ;̙it`llԩS5|p^`77ɓ'ҥKN&L0=Ýō?Ul>e-Gtwwvx_^^.65mifՑ#FpqqׯٳoN4< I_IIIfOVڜ8qB{b)n;8{LuٲeJ$ !!!,,L/^ccc6ܹ,DFF>"nZ1[Yz5Mff&Nht"n&MA)+++(( ro.\EdƌUUUQ;[[[F.Aaa|N\K;TPvN'cEN׷oߚ~Z77KJJd$))0^UUelekkkINNۿi>ceɓb~>R'-njcxdyyW./a5j<󌚿 iPWW':88٬ (wq@;WWW׭[71YG2e\տofر&B}}ٸQ02s_jۥ=z4 5Jl_7qfNNNI9vgΜ=z̝;ͪcߢ+YF SӬʒigW{KvlL;'jxkv߂G}wڮ]?~|ĈJ\w}b<$DW}Jyj *۶m3ljt833sbsU?#vN }r劕f"ϊDCGegg':'FYUVKbrGܭ^|E1_9r… Y/[9::FF-/2.44Jo,X`x=Ǐ>FjRWSRR7lllz)X@^y&4*oV^m%^~Wv 05!H`p0_}LtT ٳNS"vJJJ-[hě[nV |xdddyyܹsi&Xczc>9h|}}mllé~mG٪2HjjY>*-I~qMrs\9-^i3~w.9NNıO[$n9Ƅ˨v/> ٵsާW+vӋ[7׆gbV>~œfKRj^ {W޼PPP}׿Q.eUJ1JJO}ՖQqQ,]z&'3ׅY>:8IѝGWbB,}wnw'^|[7l)ZlRG-ZeOtPgggr 0agXۈA>AAAIr6TSL;˨&֯$nɻB~ gTN~zƫW0`@bbFsvvV J&M/+++(( { UVUTT={׷ѲU=DnSLA)|g.\՞Mj|Aadd8)G}TYEd$88"E|4{lMq7odѢEb˗QƱt5Y2j݊'ՖibnկH`vjd…EEflgg~%-1c 2DY+_C`6ⱄ~V_m^'Yjh'E*7|S=ztm9squus'''eqƌ"D߭ϐv*TTT<)SW\1 oA.?5m\QY4b&PF6it\,”Ʊjhϻx 5JjC3ʺx^G6;U&>X 5mٷo_}Č5ʨP#'^XXhf9R4HOOWyFwhoTyDPRRTE"(7ԩSouvvm=1Vw>K/CrGQWQ_ŬzZ֯:R٩666QKt/Z̙ӣGs?hbJLk>g$o*qaPgoovdۇ_PWWNjԔUݳS jpp<JVķmfX}Tn3ڹXζ#gΜ qg$tIàF1|6,i42Фqjkkd+$$4f]|6s懾mTz KAPxM/*5OR$?ஜMP5E0 0>zhJ044__bir;vSӦMm>9o|?ydx RSSE6,i42ؤqyΝ;Enݺ58MQ"؂6ozG rǻUiO?ɶ.<Ֆpwj0bdgv%啔,[̙3|Eo[fXo~<\yzF~aÆݻtmyyxx\ܳg|D>:utymnZ([< QTQj47o]'&.FMpN~;eO"?@pdKAPx+/+0_XJt\eeeׯ+W}EK.~RXpmܸQGD+**CCC-i.\y>5/// 7o܏ފw1cÇŶuuu/^\zСClbX8nܸsٳŰjڤɾeffn,._,#JH^%Z4@!<<\Doߞ5k,5"D{V%-Z&.*e+Ӛ`lEtaկ4EtyTeF0`Jܹqџ|}}Y^^>w\''oڴI)))yWww̙aÆj_O>}η5*,,짟~2m駟O߿m 3cagajډ'Jq1cƈ]EDDյm߱! @#Ԕ_|puDX^ZJ⁘k*M+p78QWR̾/.ב"]r(ؑmn|A_ŬzZ֯:(w0;Uetajʁ*:D׈?q 6ԴB.]=r&,8---""ÃF #&%?pb'ۂW+WkW4m^]2jH hW#""d'++K߸q#11qԩ"2bx`XtϥKf9]zUvXFv7)w0{կVGMܵsj+Kd.ly"B@hyfΜ)AAAw|ZU^dRffzK_#zEta <*l >qkR1wQ@NwMg"Vhv&l'|||h$q='vs"kT2|?\65VWWC[unv՞={@[' #5?!^0[ZLYvKFn﷟>2\9cڍE\Zak:CUf*[ 488ޔukZMAvj_8ؓy.9.#Еk) J+rk:㕏@_fiǻM2%%%EYU]]9b{{~͞=[n^WW|aÆ999IIIYF[Zvzz%KKӭ]V' Ī:;;(**R۴Cr̈́ L Q(""bРA"E?xPP-rӺLmʟ+4EyR.KM9p.9ٖx fߗQ_^ŧ ?yׯ. bWbbb(GÉ>\9-:#$:׵ZEtpƫ֯_`x HLLh4~~~ΧNk'M$v_VVVPP" (V8{픭NQmqr7xĉX|gDonܸ1k,yN688"'5{l뽝7o,ZH2|PPSՖouؕs崬w)Ů2,vŬ|Sb'J݋eK)ve}P]:]m37-NF.\hzYlgg~%-1c 2DY+%Cvz뭷thFcz3꛱[^/zkb144Դe߾}ŪFYZZ3j(|xaa짡k׮Y/[&^ՌZt0:;;ѣGQTU;'~!q?O;8QCC}uuEYi~QsggH;t.9~zGy+ڽv~G~S-z+u kޟ'ˇ'=UıON[3eeɜ+ʻPY\}2V(NZsGSM֜x>lccckk+kx񢕽]~}Μ9=z;wv kjjt@e?շTm;[{{{ y^tPjV%S(wqir/Y2J9\rNDxۍ {E> u~[7lZ\ʧ֯xub{7|}>F$_*cITR앧y)؍%?n\MVxsJKK`CCo۶ͰVy;wrr;jZͦZv*jkkdq,$$ѳ>cɒW^"ؼf_^+JJ~ܨrղ@#X/Tk+ KK~)BΕٗOʒ:q쓣?:`†VȢ4kGk<[7YԺj1u>><;15j4`@@a|"`hh|/0%%va*i^rP+ݾ٬ZpfODعshЭ[F*x`y~dLHs@cΎ ݻ6ӧOիM>mڴaVֲߴv䣴J JK~**,~s̴C؉8qHOղv/0YW¶nXfV_'вZ,=666F%]vyyy%%%˖-stt۽{wѳgO/UӆqЮr݊?ȫNeTYi>LPj F0`Jܹqџ|}})surrY aor >oT;Z*f39yd˘o[*mGэ_^ߕ|ʕ+rssշQفFX7KEQ⁘QWohme i{y:-m8o^;q+ĪvLJ(;F[3ߧOGWyyyM` FwX$n$-poNv>ߌfwCN7h ԩSgж@QUUwoQ|wwzի%%%!!!bmGv/Ok̉ctJL'"8tж@݉Hïğ*;VVV&+]|D?$~Z^^޴i~_;00P,6 SޅO?+W=w.9^OZ.T#׬Yc>..n񮮮nnnSLIIIQVUWWGFF1޾_~gh4-_|ذaNNNeRRRB,fddn{zzݶ` 8qBR &&Ђ@ڭ+?UY}Ffڡ7H }Y N[~KTTTCիW0 11Qdff9;;+7鎏/+++(( { UVUTT={׷yE!ܿqww7ݕ4Wkj),,4|\\PV@#{FCfڡ7 W6ϭசYpaQ/MNNۿ1c D<("ӧOW"M UUUFF;|Ӥ4t=qaJ0f+=>3Жixɶٹ9H 5YeBoG5`Ù3g-Zٹ8c ILLT"ͻꭷ2Шm҂=4RTT$Kedήуm՚kJ߸dA&rGh+z}ݹ不ū];\"-pf mee>(CCCM[Wjt111F2g}QB׮]^R;CC)))bرcUJSNMpkҜ:wv'3t ?P0ІjkNd'WĪ~{q?гY Çmlllmmvvvŋsѣܹsϟ?osXSSc*Z׬Y#ֆ̕ܡ}2jegDבiOͺ¤eJ_`UUIܲ߯|西K(&-AgF`yJKK`CCo۶ͰVy;wrr;ۨp~ԨQvvv"E*s%#ʳoeIy7Dy~\#>yͲ{);(`@򢄽K'|牵&%VpY F8pG-^^^z^ KRRR,\aǎ;w&p5f%ƒ6-(2ah3bX3XʖbU+)Jnzw{o[B>y>{rOgZVCKKKrjʕBK%%%Ej"pB0c0wlB; (綷!Ӊ&GL ?]YAX@.(--P ";u,,,ܿRdd$uh۶-9KP|k?:QnZ RO6-gNf^k߈>!DBI0544]ƊЭ[7r!˭U5$wp w#ԏW=vڏ[ vr+h̰XcǎQ"//yv͚5ޱcs g رCdW'O /$u֕ե޼] R]]X^|Iݼy3GQQzǏS}$=0U)ˤRKjHBG*F"""x<^qqqTT 7|C , f^Rkv"+VxǁW̎֩.Ke?㗷k[ ЎhΌ踑W%hXbccglv>}vgg+))]|arrN۶mjjjZ\\q6m݄UVuҥ}zzzC !Ή׳V7]J%^ 5lժѣ/%V_ƫ>1T)Ju:Q4>V@hGh䤥d:, #47JYAYh[Mmf ,46 wyRR궷$ #.//AXh<@@;@s ?n  mkA |Zٳ+**>B={fiiZΝ;}typ֭wﮥs΄ r *ZzZ ١.<^ H~~޽{ ΝK,#F [^ڭZRTTLKKk&ܿ?h.[TTqĉ1c(((_39r%+#a=N1:K #,Pl1} Unٲ%Fࠨ8|p"@܁v$-C*^$}F@CZ;ثWOU)|VVVz<ON#L9x 9_<555|¯5@O{OTr[@Z;t!OU8p y1rHr4.۷o_rѣGgg ZCЎ^6G~╻ى gU㚑AT $[666䪙3giůl"cn,*]x>vPUU'WywUjffFVVV^^^ZZZ۷ԩٳcbbMMMGѮ]VZ}k׮e:p!CڴiCtPrɶmHUg̘!.̭UTTQXZ+/'44UWW1&MbGvFeeihу-LN0 azZW.{رvڙ  >|O>l6;))IOOm۶ nSN%YݼyblٲڵŋСC%%%QQQ:::V$g]]]ᡡ!p:tٚH)~ٓX.]ZVV&,OQQuedx\;>2e V,L-&d SU;v{FDDh֭[BKjj*ӣcƌ0`,%pBK@@OBKF[-ZQxF./f/,,ْeZs;;;ba^1k,#\٪*2bքfXvOE1+!Ӊ&GO ?]Q kUq]~=yVYY)i``Io^Jmڴ.]X,=碢/0F"޸q2ڥ׼ꫯ"`qƌaqݻXjiѢE|Y<;>k@hGh]macam}`rj ;_~XSEEbΒ"kkk)1{t-ܚ* SN$y)[Tsɓ'eڴi0==Ucbbٱc^rزe˺?Fv2;y3]` a)Vf500PAAAQQlѢ|^zaÆ/bƍO<ɼu䰢BJjBCCCJ,]vbVFWkyʊݹs5!Zk?ThM8Ίlv$3=oT:ulat@n>[,g ^Huݺuһw"Q (**=ӹ͛uBBaRRR$fަMr*$%%G|x?L.߻wo%^k)8gG#qCKQFhтT@0ªS%"qZ>~v8\-[mgVe-@IKy| *^.K{z!d{tAvfhV+믉Q__iWSS#Fuuu8ccyt[29899I8۶mcGb*,WU'٪֚S8N׮]gΜY :ʕ+TrTKD>Q2QVφ-@NIwTBJ\UTp(@󤴴"+V(((HLY__?33pJJJԡm۶,CxB'č?^8nJ${AAR߿?"qeZk.̌v,f$z$Tnݺ \n=/F[ w|Z܊nGLѬhz!,رcT߰c]f wܹsق;vYɓK455eݺu%%%t9C[+++Չ˗$͛7|%V2--$.\`%;b:*:: b4ۤ$sMZk g}֫W/jT$%FDDx⨨(o,X@2kMvE,+VS?4X ~<$Q7q W^mו=-N=$ӄ/_K++L@诊+=r9ɄdK2'EH^hRR RR%R7o-Ji`eepBМ܁vΌc*WN\n$0[vď v* z;-@Mtڕ9!;Ў>\nų{գstXW$d)v.;s\A.dzHL+4؅^$@"a0,c䧿JHKy$q.ޱmyceל?ԱYhU"cddԾ}]|>4s wSRW";3GIwc"uuݗ7;ooDي#||ji˶R܁v>wZ^sCC@cԩS7&[{A/1339fiXVZSWW}z#Rzq-[֔gHHȪUؾ_ ~[nݽ{w--;w&$$Hd wNq1]C JEh>xG}Wg;iҤ}*4:99mذaذa"Ν[SYL_ƳRP&cĄXlʕ+?.^:9LJJ?]{8xG",ZOnʪ4ݢ%"2Ң.s\QEL@Ν;ڵ۲eKNNNQQw}Gzkw:$''gk׮p8;w&-ZPTT[aJJ ڳg9ٳWT]v\t7i$!tÇߟf'%%mV8TfnݺL!zԄ\~E__;wyj!3;\.رc$뺿0UII y.[vСe˖iii̳޽{wD*!q֭w+{#@@;6*** 2%'={^ύjWݾϷTr}w䉡6#m/6 wPYh?58ȞǫBX@c#33>[hru[ԩ?Kvv6=ܻw/9\|9SAIIиrJbټy앹{.RhaX={$[n^VDDD-RSS=ˣ r_#tѣ!UQQ!ݿpJ՜z"رCXwVbquZOXm61>|X(dزeKrObHZj%UUU/;ЎHYYׅiiᑏo^}}/qYѹyL]pJs)uh4юՄè9]W=gs'K9 h$ 0@d8tV`rr2=,++#mڴ.Ξt!1KeCR:63'xȑ7ի:u7n(?H^Rӯ_?Xzm^'يf:6L4d\*119;!gETuhvl_A41 [5%I;6Ԓ0իKlw߳q㎳?o`;G[Y'5;6f3]O魸2ʱ 4/9vyOZuu?L>r_"3yjIQVn~=ՏLe1c~c\~XY[&9\nEp>= c3C=>>9t(+P͝;vSVVs]MAEEE]e+:LdmO:+P|1U5emGy&VSS6lXFFitGFFX@EEEB^'ATN:3f\reIٙ)Za+++rvΝ xf 3򗼆r@Bߩ9BᅲPIIBC{8p;j g[=>a:l{O ʹSh;Ew9]5=X wDԲ<Js,W~=G/ZJ 7;.nsή|OKǎI͛R|tҩSwr8իWmVDrR 2ݺu#NI/K (**C{{JKٰUeeeΝI<1b۷o,.#Ru눥wTտNҀaҥbnnsRa."%%%(͜9SzfjѢE||,&F" x4*MDڑ&:;{߬;=h1UC4N kWݱk=At;iz.Z߻M?{.7ޡ9'\N zPXsz.@70HmZo^# VsX,@I~|؏&ڇL'\3/++FLb„ o6ydwɒ%LK\\\Ϟ=vھ})S*\z'{ef̘A.ٶm+|e1N̥͛d+²e媪1Bo7FFFuґl_M_y0WUU1 ݺu[f􂈏QdpI%9rG{;W"u@=عep4iFX \5_c/^Wmu׽}GO;$ydg%=u)JyARfL\q`qxhkr|ȡ$Ћ{Eܙ\zg·i3"n+5?ҳG-r9uK=k{ rF/ʲr9rKUUypas] 퓇y#@XΎ>eggX,bС˗>yyyfffҗ٘(eZ8t+<;wlɓ'N}333 ߯ĬLV^^^4{ܸq}||j >@#^$e^^S}.]pšΒk?4Ι3ǜpJ3 曧|„ ݻw?T/e֣Gmm튊Z+I˒ihhn{`UU!^5J([McO*$(>U*tǭn"֒O._ooӸoJq XkhgUۏ܂pIpf"q>.uH5Me<: ҰS׻~3 s{HnO=}M|#qtyn>xy]tsX*1@0|6l:u,ռyX,ɡkΌЈl׮ɓ'Z֎;Dn ENCƍuVkNj۱cΝ;3Q{N]K±chL9<'9;w|5_D /!ӟ4mMgTeee=zcNNNPPЖ-[ZnM'##cŊe˖eee D677޽)gBcN59$F?ScV8""{"AoqGx{p`m+ [FI_T2*#'[|H|ui͢n/#{&q{2p s& Iw_vU-G{ 7?q,I1\E܊_'J6.[/qUw8kƘ>|qBC.cx6_w!3[#H„gQ\V ޙdXh[MS xC 0<2D :AAAteĈׯg ,Ν;ÇoӦ qppp_}.^پmm[nIj-yJJJjjjcq-vQ/^xѢEvٳgKy!66VxfӇY7qZDBBBd-󔮮Çe )bժU׮A^LZj_*/#tJJDv>}ʜ&vҩCy.?~FFdB:,0Tʪgu|`z,^ӥn׏3EWq{$dC6I.9ʲr<5)--q߻OeW2W7U vc3SUU gװG++FMYYmoK  3JIALbرf``pH 55Pw\\Dv|̲jZDd+#o]Vzu#]o9~C' R+nċv'GQ";!?iS=?Փ~=G_97d=Yc`bn䓲Gk/L9j93xbV.b>>,kÆ СCNFn:7h=ɏV&:ActN֨mn.~)ZJ";!^ZNm!<{[v/GUHbq7)$^諔"?$|YO:gm;BYϯ؝?F 8z`Sy*jA 8tܱ:vWVi#I">";!VUq n!UHB%Cݿ8$;@gHw:"IF"IeN]fڦک]0V0H%>H/$0$D<7tTtxw{xwOn Z1!.k~J\|<@#]s͜?Kfz b̗gsC5C<]НG^Z`h0Xb9V;hϐt}7\W$sH \UM\ |x[ tY$#PQ=~ufS]M$xs[NᓽOb'vYm0QeDYϮh/_ F,t|r J7n\-[ibHHȪUؾ_ D![޽Ν;TYb,/!z]r48.4K/sΑQ(-s+^d+e: W){n'`lfO~L"3x<~3=?CG[y(ŞzKmVRCT2ROU\CO7x`}z&,fz|fffTk.gϞ<,Yu6lxsYł|\nQQQDDĉ'ƌ`hh( caa Ę/Wp-"ӧSM6UTT)T)i0 /^;w.I;S\5cn%T9'5Kv7UT \Yuzܢb$GT{!+Éh*($CDRqPk e. gw4+0LS|QTᶝt8e&`Scʔ):'UU***ԓ\"khhtѣGWc=sB6]EEÇX,]x Ñ%ϟS;)wȑƍ%׆ +D떔Gvl$wUypas] Vscc|W>wV~& &ܹsGDWTT9sg͚E܈3Ěz\.o߾Qe+ıRӧOi!hy2qdrZubĤIY&)g }kj9/؄B,MB f:ga}~^*b{vV9N׮]$5d@ "l߾:99IŅgfRzte-[T޲1bHU===gϞC;ڱ.ծ2Nߐ5bl_w @~I{ mK֕I3ٳg˗/WVVn۶ȑ#Ef͚թS>lr³{4hPnnUTTH>SN%֣2۷СիWge/KKKC={옘f&v8p dzd:D9rΝvmٲ%''#ݻw ?쳵kr8Ν;-Z(**R֭[ӧ~CCÔgrسgOFuk.RK.&MDϕÇߟf'%%mV8/TfnݺL!uV ;tвe˴4Yb޽;UD/Bdq!nݺuc(KKV'j~#~zΝ{m!Ў[~ôܔU]UN~]՜5 :g"l7-Z$\~t:u$ĒMK/_TS? pʕIJyf+s]rbzInݒ-Z/!===zG3!/ŋ/wgu۶mTc=|P FZlIχ\.qkժD)=䪪*ru"IGbtYg:s_S Qb;ڱQ-/(7e _{IOvY5 5) nTVU",@NeamoJp=wo3'ݭ0lذaӦMZ:uD|*EKtt49ӧS?B$^ٳgKRRR?g̘!{YŇה !dMrss?..Nb]vC"׽{wFhM6Iӓ^LBTkL>3.y@ d!;&qwK 1‰ImHCaⰿ / =Sjr(bL0`%qdzXVVF۴i#fI8<<)ˢH=w2E2߸%k֬!;v[gҤI5/Mm23&&;vl&nLOO"Ybx/Ў@V'):yM)kGO"gLū V# @L?p`1+1iХ@5w\~zŜpWSEEE]e+:)- >L,tӧOw2\JMM%Ewԉn;cƌ+WԔ,9;;3uZieeEܹ[65 [A(zyqvufȄ{?x$6 r 8zpSy* ӱcGݺy.]tݻgm۶O0`֭Ȍ7I\uJzY@QQ3}JKK!d+ҥK{f(RR̙3?k֬-ZRO>?j(⟐P}JBT'lJ;O끳s[=r@;6y"]: pSVuzzWY 5A_4~ktؕ_2 &M &ɓF__%K0-qqq={ڵkL^qUߟ앙1cd۶mRbcEV,555r\x޼yR2pAbJAA[nk֬133?QTT )###iiiIN\yd+O8tX|% r@;6exS9y|~v+GEEcv6╎5RN!b?;;bK._gu^^E6#)** ʒ]k׮y;wlٲ'Od/ݝgff߿_IIYH9sFu̩$z4f'Lн{wqM^=z֮3z|r ZAx 52ެ鋆ujK.-\Pbgγ{\n"@9[]sXnk^R_@L@羝3x; mk@GX`";mذ3uToooYdy楥X۷CSSӺgݺuB 芊 OOvڝX Gvfi녤gEv_ۣ a_ [Ssйco5UBEeSH_-*^:u=>-EW܌A+_f% &M hСg!C:uJānGPPP >]t1b㝨Ý;wަMP555W}-,e9;;hbTm̧}**[Q媢)䎼ds Ryt6b~Yy>B;tVeav 7$X#+KA~fرcۡC9EKKK?NY]t|BC@;|^)uAzvfg:A*lEғ(JNl%qp;R*,(?1 Sfq*z&UUAuI7oP['55_~́UUUUƦ]v>[ӓ <]4tC=H鶷啋;\.gOOJILLي\)䗲¢+?Z= [c jj%;;AU3kh/m{Qa6b҄>|8鏕؟>}:{lfMJMIXu~.320uAFvf\JrH;aWܻy9fQtt N.!}'n$VѾh90\MYUYOjxN]xq+gD4|:g׺ 1i; "##9Nyyyjj!]ߛG$ >,rx@=;= q;\âH*QgW2,J$6%W.s_G2!Y I^R)++*8Gm5k[/[vrSVZ}n. 'U߆vV}Ueܿ<<9EiL'͑sASb޽{ذa:tԩӈ#֭['t'sε>YzjhhL0 ǧ0+>5 S~}(THKtWR|`Zjxn3VQNes]r4reF\{vu+|>tC;t'f*[5zaZد;z;6E~7׶Ny#h?|:gvH)DnC׼u[>{F ]sDW/^z׹".wvvv];ᚚtCPR_j>;e-cc|R;ф|!hG <={):Vs\ a@祊cw)|i;Cd@%#-thAkt [,g4{v===C]+nu8/M~NdJU'Ϲ;<#3=Tbtz'k A@;9u Is鰫Ӫ:a޷j_^u> TʻFsG`m13 b㟰|tY,V߾}![ p8o4NeOO'? f#V ~ũߘK:||+P#N K{언LXOߖl߾}^<;i$}MMMGѮ]VZ}k׮eu*Wz&&& 6LhIHHسgϠA\#G Rӧ斕S_u۶mM&>bKKKoNfϞMQAӄ˭L vgacgytpЎRVXt_]]4Ɖ4 :A|Ac実DIoKrڵ]v.]p8qqqT?0uTby&ٲe 9$Y^n٫W/oʯ\Κ5k!!!+V CCCfVӧ?NJJk۶G>MWOظ^";'bt rFMYUYY/ds= 4B=t([uSkr߽{ZX,VϞ=֭[3fb3x`˭k=DR˫W%++Z233a޽WEDDhтykGOO TV vCl n^Zn3 Ў**no2MYku-VUU!,Hy<&î4g8qJ1 4"KHr8cd)Go={6948c f-Z6mXn])񬈅fX\.9lݺb``Io4 v@ Jaag-g_=az>v «$R6A )OI5Ϊ_r֝k h$N2sSwL=a5Gxx>̓VVbcY>F.w׮]ɩN3-[J̡zԨQJS72V|>VrX8Ό@6y1-lYMbZ[̼rqGpvXSu7eU'QZ*FTNi'VA@@}|Vm&JYOɏc3'L':]k㛟J~^.>~XN]23b@EEMYu&B\nų{3_s"g C=\ 6N8@hvM]nݺSaaaL#m_2s`N{SaÄ l%ɡ=ӧF_D暴J^WJLGBUeǐv{ k,@e>-qo8怜KԌ9i 11›SVʊ%]vNKychvM]3fS۶mccccq>:::#F8JMM3"͛WkkZ&Rg1<dz,&ԿlA[Zm͵aWvǸZp\y3Hnъ{AVmo˓VsYr=)-- #a']Ɗ9OpΝ-[|ҭ[7J۶mɅP|7uS@ wwwj$߿RddvՍG[VMb:;:vS?YaΣ[]cZp3;F׼""™|3%b ,ޓb[[[*XZZ~Zgݺu䬆FtttEEgvN<ٵkqppHNN^bhjj $55ؘ.v]Z.=?N %:$@D-E-cmEn q ۣUC8"-Nw vy;M<>pyAfVνܔU{7TV gs Kū5Ϯ==Sn!m 4Yz"Htx񢦦fjoݺ%PZZGe"WGGm۶C555-..޸qc6mokk+RST,ggQSS|jWMN#_GOeTV􈑜J;4 vujׅ=(nf(DTVq Cūk SJKX?;wi*IT7=LҝKSVSױ]s<:«znh^@@;fEs1ojWe;ວ碥ˌfuSi4cޢ%~K2 #%|P3N[/dL\ 2gSl U:;Rcg3rGiGY.@`_[ƕ0vyFӒEK C>/999S#CfzLiK`qد"BF5'r͑bˎ-{"tq(*F 37j"@v|nZwfX7eU_ѴS{?-Yfq@/}yYYYg9ى? ˖Ǟ%ů D.m*+.*&)*K&"+n]H}VQJd wA3؂CqTrs}Osd쨐<>CP3*þZUC>W8neC/_thi6IUU3#ļ6P6)bwpUHFRxqC8@tVHPt|W1+W8K q^FEh:܁v@v};U ߽`%=q#hkKָu8έV-뷭WO - 478Q1 _]gm;^~LT+ ^%N'e!@Z_|部p:ᶝ|˝]q͘JC]PËc4,Hz@W)T"JC{vfS:mٮ w#yKגjy'L'ZMlMV_eh)Z֑S/0}[-+^Jj*I&O\|%+Vf{vCA^T?ל8 J@GJbc|\rp渾ufzDŽ|f磻A};o]V:4 č8 J~2]O1V܊gwZ@@;`jYWεzMZ։kj_mP_m퇳ukQZźGTQ6  a 4&hIxyMr󞛐De9_|!:z&G[<>YdNI& ##r??{$@Z഑]\. }ClL_ }1D_o!Dmi.EEɏxLL ~pzFT[]XAI zzٍ/ ekxEۢ{@^b=M;#3̼3sYI9\{iU\.Ƹ$}3š  P{ً"7Iܤӟ2EQŭ%[nQKKV4}I쬥:TqCM%vk/L9˸z+k !*(%+Y}(fw_ӗ߄}D 7JעΎ:@P(`v4>l>g󡛠#Џ<fk{Kr#Y0ez!K便C. M 9*巳C\pyNS+~#+\2ǥl3;53~-mr3$vu"fn=w\)9IJ.iJ)vf,[OyuZXz|:z 뇋mGҵޅG@ ,d)/IM4*쾎ڪ͇@(#t~`t y|Fm?joVzsY[eϢ\VzzF}CχH Wdra+"WZ+ž8\n['ZF˼[ќ-[]Bj?b~9~wыTWrPVIU$vo,[U{D\7sߌ*bҼf(jy]EXsEXwL~XYM T{+zFR ͇@|%П6MrYǴ6(fnCkD@ 3=D?u< z>zwU<rwc݂HݨAkv-FV>WO?9#pz{{Muv~Ţ_/txRul.C Xb_p Fo;Qyiʐy';#Mmvq&40)>'ӷ8. Hw@?"d[tC!8rO0jsLlF2o8\Vk{^e5uϗ`_uU}a׏QyVo>q՘MwZt!#mU^>FWc}!ATZ[X /?=&1ejb@ &aB<ЏO-Znh;g|vU߰;xgN/ =;i0e`ѥhj8~M 4<B 3j%&X(?7*NkCsSU;{k,y|Rs;}yՉNpVAam%B$xڊW?:mW @w}[^n'B S\n Z|>"#7+ >&粫Agoq&|+#_Bkn*a2{ rr7PMZ)72m6ri{~CNeF .txF@v.ِi@xDTctst'}{F=z\БT~Eu[7}^5À0繝'=Z:%[e&?ؽ5)9xfA';u:9Ppmg|]7Ծc4)-͝n`{=Cw}'>^xf}cSLl*B3 /aVgAttvB46oz,Vt&?ؚ)IWY`ؑW278 TBNU1 Qi+5naE GtA(=sPo$Ai)9(,<9go [AX.[$te!8o`p8 2<} oAݺ_mh2ϗxxBxϾ#,XGZsCq/T$gtV>`~O[= M tx90E A-Z5D asOIί/N ? FGzuroǙ[h߮r맋4X2[B6&~.qK5\WVlvy&U}0 `^ i,_V/^-βytխIԖgȄjo"6tp`ʜZ'UCL7w꘡Mu6 m%fan)H[=HA n1eVgҦ:$mUIeҩ!KΌlCf~Nbsد&Xb6%ťIbXkc`JGKSkmMl;h+pBcs-n~1E:iZi~6]& tzUuMvnndt4egh|9=+㖮7^v ROT.~`w.jºoEp9ֶ]A1mQ_B ^Yvf7606akS6ڮޞvT``ğlh%Ɠ؉Rfmv !8b67$H[ɮI& I;!R.1ɕ e`٭-Dm_Mb76ԎƗUv=:Ur݂FHM6k1P-?Qm8<ڎY&wKHt܈ebru2T /(iO4p دg+ҸnsOԵv*K$~. m%mkKqwabXr=dK[I7QJG_B;|jY@n&꓉^jJ]6^-5Yj~Nmoo/)-ueXs|^'wfUY]xhts,fkk(/I#778\:/GpIwji] ϓyMcE57Ve'RDQҼR]c#CLB |yyn_- VvN'47dH5xIu-SU,aQ֮nJO V둕k[a+$PVL޷1Z1nRJ1n⟞Y5r§}7K^I?C;tMY읹$ dmF)6^4@'&yA(l57P2g93Lk)'Ân&D=qk7HBNjli.m+*-/z&;G۠ zy8u?`dMOtzL!}[[}ww:2(CY '`wo;=,鼕΋f⹦~Q]=OX\[bONNm`4H[ɮGFMr4!@hQqkS}rʟ /Kg[7!Qbaa;! XBAVN3dxx'=eŷ+̿y,]/w{ a& #$*C~v7ƒt u+R "8FXac:8iؚ)X?*ksDw9z@ЃF :$t`ACEc8hHg'zNqwOh<3$vcK6扷m|8|JQx"Tb7@x4D'B]xOEFɷ|L2X8VI?7}TUW_zMsҝ<Fo,~#l?]Nނ c࿖`M 4'd^s$j%ڇ'Sr+Z瓃_<35GԺYٯ\Dʿ hB=Ly6ZaG[f]"b7R$tIfJy|[w$v㎕&= z8f55>`ԩЏc%0 ,%GmAW^;[\˒UMmuu׿_9s`AϿÀA(CL-(:iCTR69o~KZ;ֵcO1x VZu ACPSS3cƌ-[o۶mЏcVA+{p,ɣBJncHi%sV}G/H=k|N`mv&G:00gU60c>a5NB#F뎢X4o:y-=,)%ccM: t p_}]:ٳq,9o5]H=s|v=0X6lھ[w[Z_Z;x kb #EQ 3xd?KIZG˹P1r*Ï5x2hǏO0q16zbL~򌫥<<ֳ10og؃lhd~jn_.ǒW5:C RiP8PXꟐip@Vdkss8Gy[+z^sŘ AK(&xD~2E1%VBy, 8\^~y{XE[eKTİ(J\o1ٻu"P';^fy񍝝hg}([Bg+{䱡4af3P}>R!ۖV#jw([،UkEu(&mTɘ*u]{ot9~VjASpy+:f⩪~Q9q`"g;^fivΣЏhIeN{:< 87! Dxgit+}%&f?}FYMȶnm ^DK3phbف׌/\PUѥh j9T[;tLEy*%mVNq^4mr٢9C鎗!=qD]w1#ꫯB?ʨԺ6d~IDCaL,yu9RbAe53?",Z%Sr!`t 0C54ASo;/]%%eUR)B䟐9鎗![o\.8m4Gq {)3LK!&c&uӜ(-=CemkݤyU5u@jxQaeU{ ׳S)ivhpK/,TcdUpit5 2C=dg͚>Rsmꫯe݃VXvRr{ b'.5zO-e5u55?]2X}Q> F]C 8ږ̢JrJsp SfnX-!a#~,Px ōBqt ޸q#^UU%6B?PS ?] r|>?,6; {HwPmGDDoE---16ybîj}G|uژ3FasQ9{Ж؜ś*B(OF $$L_B6kYkH 8Z{Xm໎I f=gwe5uu^/+%U5K* z`tޮ[Zwxw~W!dT?]КZPꟐiu͑yQ)%mTWݢKgIW6E]Fgx LfLL BWX,ɤtss3nZSSCΟ?~lmm~ceptb<>isEӭmTUVS?y,+s+g- Ϗ|pc Sܑ sZz~wcKa1>>;^N81AUUu~={ЏЏr=uO~uPBM+!ټ~UQYuQ*6g+ uj/=0㳠Z;Slv0p x}Ϭ5]{ot R5SAݍx ]usm 8^Les!&<탆чĤߎUVS߽WmDZ9 7 TkCv0 tX `8>g+?5Vi06sCK_2;;P_RgxF?v ֱ+|i?1U)9v"1b aGSl2 >jYƴ-(™WGNѵFs',W:=rb!q8⣭|"P|%zNxG0F*>jE!S;t>0 MDg9!t=qHw@? ڂALNTcYҁ}x|hDc⬅4ВˀWx.R҃nLQ̘Xq≅QRHdq106();Ł'jޡc|ɜWOЏ`l"Qk") )T@1`8a ^WyaZ;xNt:&U6֬mu3W;tL9\CH+.ms1.q!Ƭ>F@6js$1`hlޟ)PA9z┲ʞֶvQ vcɫ5Ju(xf8gEQ tR6'Imz@ >$·n`Rة@qa即ptb<>'NP}6^3f}|WVS?xX3,,68',yrVXAFa9QQjU+[w#7!D8kNyʐ~c_?uO~uPBM+m|[j]Ǥ[<~SS16gPniqIW+j t9}csXO-(5p Pdevꘝ2u3 L!F.KVC r,St#il 8^Les!&<^R#}o6RDss<-3QWohtEϿÀЁg?>u~ީB.H(+ւw0+5GR|=<%ىiCpyz4+i'OЏ@ޣ~_@1' P$P3E _=~$,0]{+Ɯ^ DկY]h+dC|l`rL!@[K# v>, bHr3߱OP`{>A!-,yuIgggcsXvl\<3Fa)/SUdnU EL>e&Y!FXyl5}/<6p`d:)oƓ*Џ|>?,&9%Wкu(1: Fa~'} Yk)=l.g <+3.*K^%?[S#~4))_>`s9TKXJ1 yWdm-OЏ@.q~_@q=e]`e|ڑcsbsy}L|>ê/gu@M90RB07{eb{ kc!&aVQx:f9~Zr;! r!Xa}SV]Qx R:%vk(<{.7/ܚO`Z׫l\lx Fz ÛSr[yU:OCIDUUSݪ N1ҏ@Xdu!qjC0 ̵!o?mQRX!k`ĕjr)e5ue~ ;NϺp]b?n`6$gT} -S5/DnVjŰC>lkf~K9 %ZSOr J ZHڡc  ѥdoo 7477#d6jMX"KnCNNL )yC Cߢ}Оh*3V l6Y̐}' [ۥo*(jN|$5X}Y_B;$?)AGyy i+D [=,~qzjA)˃<2 ˱ٵB0G0n 7UP$;irϯ&z> IPIZtC>%4<⚞ 7ыU}/[AX+50NϠ<(VԴ3Ϊ#Gٸ\1Y.}|: ohYmIl#3~7d|$[hy( fк@(JAo?7+ lta=v,EP5ɔ [rsCjW׶OT^>q z^/QVSo]zl5_ mM۸8|#SrrJStYYZe[<Ũm_cPAv&K7O_"ւ/0~=aSl¬m ZG8@uDDvkY7Mo7k3|KvD!0(8&6.O %q vt5+Z,+~x:VNi%sV}GN!LYy?N\qeA^XdfaɫV \1!Yh{XR]kޭkm"OKpVcŊVSQCCVDN%^ja 128h+CFF[}pW/P&]$䗹+u[İ_?{ֶv7KgjId0DlGϺv{oNyʌ)i$H[BjWlk:/݀CW硬#!N{ig0,-#]y2L]Jh ,s,HOJJLJOp:1%}l;[&onxH"5WL:9˼FdRvUۦwgY>tl!5t3*sj  e6jWYa^A/i=W_h;@ӇU7cab J?Ph6r jj)i^dHw@?0 9CO3|iCh"CJJKssE9^\wln|myZ&k5+U_.ݲ+w+hIQjώs >gMC$bl.WN4$J)J*R/1s@ckml$ edS/z=&fA@? 94k/Y,Egqd=2WI 677WONIwucwm+g^8rC;כ(rǬzK~唊ʟ?_^w`1LϯUjw,7sYfDON[3>JhIz stѥƦ{X#GQ] ӡ:c@qzU6rɹc3qڵwy租~mQWW'HpV?x|jy'f0I7"쬩S22}L_vS?qX5c5 ߱mON I F~8g'M(ּA~f-eƒWOݺ"zbtԷ nIG)ns¿vAЌrHwSߊ6FDDۧN3PV wio3*38 Ք>qVXyH[0B.QSߜ^왪{3ru| g~l`/z%]W%ڎ~| 94wb]-̘LF&J \}Xh]FBRrKU/MG 28;;3P&1TvFU6.;qrYcHĪgiHcɃiɃ,*3K&,۲Sܐ/@_OѸt֜%edl6B lߑ߰ߡm*V)ijl<’ecwZ*i`1x7\1mDG;w\8e Vz};zBF@JȏLXuL[SJ}R:{1Z2بk1Զ8=]txn ֱ , miv>B!Y "c0G 1oL#VjIc^7 ǐ8+=˚dH2ps1DX^҆~6ڞj1j\VlAj*,^q4C_طn ݒuYW~&%@Lƶx)6jrB[6;`jhR6Ql`ʞc0ݡ%ȑ#h̙L#nV9Ե%:1yi۽;M7{bj m y{,!9fjŅXX2\\`.ƒW)sR}-𯬢ʋlTe 6ZK2~})2,`lҤIjjjYYYmmmaaak׮괛'{9|AS/Fjvϯ6γ!O7}7Z¶{k)t'$jmJ][p0nbE˕ },ҧQK!8>Dzؗk 1`93.nMNf D[ rѽḊ@?vAKo73W!ܬV7޺ł0fQNXj?!3&j;_Kіz2A(넉+z d%p̙/_wVX >[!&CN9.@2 ߦ&!PE=H0$nmkg]~j%jE~wi%鯬-t` B#6rV я,@btڐE @VDG/ۋHwGKh Qq-\B&"*'!kam^SzID˨E. ,^%7d5BFK?`53UL٨ }@v?$9j%[zdU|[h"z[ztBYn[ocǎ<8dcM[ѓT]XkE)э[PL3'NB|ӀErolC^7 -1$~k>lkDL/AZ?8v5/QK^g.Wլ#G yP sptwB_[m/ s:{vZb +; + B;g鮋^\2x ;߿oz7޽ #@mت|AYz\M w“*kTAr$6>pHP}<|ɫֶv==]EYZ>7ojp=?PXF w[l;˂b +׀ s=xǤtǶm֯__]]-qlh?r2я{[hd$CI7F0 }scbhy@aT}~p lI΀m_̚\ cPeCk)CԂVa`|*Go Ɋ1xwJKK mYhr2я&Q[W.=!/_(Q&މ`CRVSGM O]_^d3se?K9QZ4^ŜVa`;c~'$ܑtǤImy7|~ȷV7P U=OM2&.+>(9AYM]e^k[췬"`+Oj^|FI̾)/ʶ|@r{*/*-hk1Xyܑtʕ+ccc%竨-_5o2яfQ"ZCP&Ϟ88jq Kr}|hPVS?l +@Вy8k! ]k JB K^M[$sg-ܱ՞nF?D 4۠Һf:1 Oѱ1̲2WWEaExu0Z 1/Gk[1 RVS׾[^Q![fK[KТXw,-}Z!b# xIA|ڇOgq 2idFa"[=6'NTg #`#6|a%ֻ &EdqgLg9:rT&a|,YgBǫ.+I@lm.{KX2G?8\ `8]=P}͜9sĉ… }||4~s\2dMi (x^ MXa:vcĮG J-&[Uoh?oW_ҧCGW΁s-"gilձ9TY\ $ :fHwajGw`m\n6m^6yKi)Nv6qlxq6'81\MW0ӋMEPYӑhtftgsw28tSK XQ|J &q3U(2NxW,t[۸%lr^z{, ,QOL1m{,X]ͫl󧺥Rz &S\G*?C@ |> 2=(@L/d zR>T6Ŕ-w>-_ٍC0 kض=C;JO/De-*T+ F臺rqa;s=w1|s?ϯ6S|$ ~f$Ch,^}P WJ`}7 Ȉ_W88C5)@߳SW4fVsx5szИݒWq:@qβRtV%cdK@dkJWjmKi釰as4 eH {1A㩧0ľcZZZ%駟sL,#|=k_)i1XQ̃1e%ChLq)4fp;#R۰~JT.&+㭝[2z ,$A1ҰuJ@XD lRt/ q2FU怪UϠ0"(w[:::ccch$$$ 覮O?sL,#Inz>ul냘+ĥ1[^U]]&?mOW:xD}-~_^;#HgsKeNWQ/rY`pR *`ƕQ&19 )^'S!,`CAOL<'gyjZ/^'XGp|J_ #NPHF8XvpکQ3-=̹ |50l|EzMWwvT%Aӳ|"wV?v`#bS *`uR!<5Jc@dDOk>p' Y:zPsB&1)*rPTT|饗~턄=ֲLҧ hDRM,cRGT1}Q'CǸKWs;Ԯ2+Wo}r_^/xכ6[U葷5zųXQ|jg7ՀdʙbJ)G@ FS2gOУ *)c}D*u;wS5] P,7 !+Kj4pM_| ٓي eR9Efl Yv)GOwx_ޡ9؀X@I `u#ɂmu t8siY䄴9+m ը Rm;pXp kYeb_˨k<lvxiٳSc |ih.1 X\ }oGpUBw?*,z8V3f1[Ӿ8ANxۨюziK߿/eƨ4RBI],X]ͫlf IX?V6[E wCFÙ&"`%@7!-oՏ)MCc`9|$zx9-=ca7tz+9>S(|ZT.μژU,ߠ]?g(–DW$/?LB~y y6&i 1#vXRq 0GEe Q;tӲ/S! BQdu[wr厖_|sA x 4rP'f*ۘD{(P5hJ16bM$5u0Dȸs,S6y_XT yXsۂ6?.$*@ѡȖsP %U, =oW5w@XėBYSVgM7+ }F'iJXu Nܑ /\p 222h{9&R`Eʓs~O{*̥ņR :~Sva873ᤥg`N-f39:^iEeDaVr<{r^ l%L}7 i&wɻ J(3`GF-Zْb:]nxS Kؘ`?DRU#1)YJvuJlLlT͐ QUU>3G,((gN:;;333O~gpvqXi;vym1i=`9ǘcx#^rˈndGOo -n8*`*BbOx{jѢ_ߞ")[`ք.Cے*z_TD8MWo(cĤ9! +vuHݏ:ZTC4PtsfgӦMvvvl6N-=v<ëQ \P̣w $Ԥ*'jljRU-n H?}W̷7 [ FU5W%yn|Q"zޢ8jU69bCnQ}C#DDII_IU}^2TVv%Do  c2I@dѸ"=Q;&'Nؼy?O?Oyydo@``3 "A| 2P<+i{1@L 6tY NoȾ/Dz#,Dnʉ/0(GzUK[p|Ulۗ;QMY/JdyKuj{GDXVeҚvX:C$%dRƨqgppH[-jT JVy.fY+8lLF'9Os ^4ˮ+`(KZorYZQqR>e#rX zJ~oVFsQQYW?~-z>⊖4G 34zۻBu;x.-# EbS *X{a괁^ "/]TZVTVU)(^|LL fsM]QVXr`兮^ frLH$+gꞪʪkA7*)_q;+ ;# N?&|P5rFDG'ɛYZ,TS^PZ\RDiy}c}\}$$U-X8)3ءw)5rq#5UUהTx5bjP`<RШq,kSʼnX^k9gmkٰ E%ѴÂC@I] e]? aа˴6/zjZX^z$U,Q/G}zߋ!p!  nEiK'e% 1U{mdV3(J8@QY_"U[p>=PE=p JJVu16ok$GC":ȖsPgeK43] &{3OɞE+*V=!}:" Ck"?} s8@b V3c4 %`_GIY?CCC<+o,z橈mS<يI-qRЈ-sq-tğNhib-Ξs&Y9_x:j:z^^))]]]A[π-)5k4;j7uBX4oƩU2sJMMp8%uwD|a@H=\5 [q){"<9w1-h/d\0(ByE<] S{RO\WG*ʓ<d=.Y9u$A]f8W?Yħ7Bpĝ.Cے*VhcX|!5iet__E.)}8rBۇN[N`k,QWٰV#?0z[Ǖ6rgϞg}s"8fd+`&=eH{ޔkxEg”OnWG8' D 49%{=MJEeUphnG=򖠆V=} ieVN.f$P*E#)Դw |u z-A 0=X)Cl}El"oř do{>XlS\Hue% k L6RB&n =gZ9k:D*eï䬣o磜 ===:;=|䊺/t@׎ѱ1qLu]r,ue>,*/8#;.-ʀDv>cl7QcK1j[$He[_uSSchp8 `$7uouW_y't2W\PFF?f$?8lRB.2K6{絠7S6@+8"lܛ_fkWʢGZ{Fob(.-/)jҽ+Q;{H X黇QiWWglWE{dp(ՉԾN "|){g_\E`E)b懦CxK kp1ټT(3pn•?ڙXdl(h>w-m-[QZ\>!S<.)hz[Obђm۶y. V Zr8>%g5  tlۜgb`1)i4Q$Ynf &XS6-I$;;VD*eVN3ZAvȁ:¢-I_KwijXXY/,* W6}09SW9< =`Vȶ7Dz\VvX|wpRE4'fja906DbZadsM͈%^Pl;!ze(h7&iuA>N"?'RL[[ZSOy. V`M-}zYczN+` 4L`1eCzzzL-HDYMc>_9Jv:a?O9,ikglhѣ(d[#NF߾U{:==D, H$e7g̳t= QU]s[,% Qfv[ \d>LBrpygԬN9bi!hZ·#mC52irPBp@]e%H |nAϓu!߇k0 [,6 Uvj_ )iC@}%@LzΙ/,W9kWM`rd/#[1A!n8J2f/v nxQâ;8>:MC[KN!HZt9 znVeXYauM ovd+4$>~}-]~qscsfי.s_W&+T4&i=W:|GDm(bUxL`1i.9%w*j[{J#*Uo7uE暟NAΙ7|366Dmmm۰I\; `p 1G(|1Id&L2#5g\+JG&(X&oZiL /q"VWi7*XVRZM24IMKkjnb27)8DE=74.*)=g+=B5!:Cww6 GNHEDA.+;yI"p)d[j/Ι\# /mpuo\T[U^<860Κ\ҩn^.Yz1nͻ VVVO<AUUUpV1j|RmtdR!,"`9ٍOL1i+<225zVQר^GDd+&zZt K+9v_'=ۦo_%^` ?Y9ٚ:7T ՁױԵzޖTNRs $$Q z1cF=gxuvNJ n@庲Jm]=?K*S~:(F9ԍ+HinlR&8UG[Ak~ l(,,:~~~7'n0Y_ yGWwV|(C1)-*u^bAѓ=}aímmn(gdy7TTpO=c'457,3F^0wja ;ǰM_My=򖠆V 399icOD'zd0ivű1+[;:OLW*/E}ᯉ,(uYY|ÉDi<}rMC6u)$#C`28@X^:F^f W  >+~x͔25Aa_(vpNbic/d9fD{N+z2:{Lpѐ):NHKK8:D>00@PsKϖsH V{WQ3ZawJT*5Ooo$Sg=rGeUչK [t]/; 7\+Fo%r Qޅ^kPbGҬ0ѩKrwmO!J1#^}{ 2˜u򝮮.CpởmJ4.4wr;v/0fcrl gv /#6l5[\sRϦߒD c5-6gdϘ|& rSRwvD"!nM[ rprZ=wuwL!`y&3>/k\R"z}GoUK# .\VSpB}cڠrp?r=)]𣻇(6:<}pzA<:--ZXNndjrb27xOe+ZB})?Em$/??+;5JHr-'k[3 sCczMQ̭,-aJx hW e+;ifbmic#2SSО?cO@`m]-+-+ ͏Y\Rk)3xO81&0;^X -!5MmaL8n163{5nٲO9{= BLl> 7Hc`l:]]] [! *C 7ZBgoJ[Q*cxb)$շ~K `M'Ym[jݏijV\\,mmTx1( ReWD+J;8Җxs\䭷{.0QJ݄J UsA[VXZ&]F=mFq5V<~iGT1`(핀 >vIo酘 jpÀ1)E3cfinbUM-yu@Nnк LPǏX[?[X} .DA٘O ye*o/|;-GuК%5Z]K?hpb}њKntZq0G^ill\`%`Mv,=sJ)n̬;11Qs++I&^eҫ"J3++'OoaAn|@j%%IYEE4`,OVaa eQз^9|*z‘CG>v\JTN Wbqox -]ٱ-[Q)i.j{neUL:s=uUqXSHezk% [2#xc@J^ `ɖK&T3g\Ga`w/R<Ke`ln E-baPFӲ*\3N_z$H8}UHߪڗW<l }g2ʁИ.{+6=&EzYe怠DS` Mxw"YXbO+zkgٿ1:S<;ݺ޽^A=qIlZlv󡢲=Ozu{7}}|4 =M`ttvyS'&Vs?'''yF7wD)$5֟l:&+ab_ֱ}M2DII]ֵu)$Nvv`!lLvc5A| 689K1V4&&6y~ LttB665W;b/06pWSjՖǪ4IĞݒ)4 ʬjBٔ>yw,#{O3!?/n2JatқQTk`=WShR4`2J-qsU@bt Z^R;L>v7uGRBeZ-M{+V^œN[N>XVpݼ#-lE1۴uDڊ8}S=!hq{fo O< ({||ףظ8\xCEKVvpٲv]Ye/*S.]Q,-+iV4L8 W&Y;D!Ŭ)$ıcfLk,..}fF ,k~%6)ëC첫 XSJLN^mhh(+; RtIIXR2h )pDG_x(I8?AEzW4N^_߇<ɷw?zbFEkX{lr_NH]#}`#:Fof~]}mݗL׷'}w-G.BZ^E* ]blUT-%[WR4-e>V/S&g sڻ_ |b;JX{,sH0ZRˣg9aSoԝVoQV-V]6=;Ʀ &AuXpG?:۾[HrYS/_$В_FP2҉7)ueCp81qrFcS\/UTRitrqׇl0&X2MLsɤtl P~Q>f3$lL٪Kvd Wi]+A.`6zFGތiꣻYM==7XZّBq/rS6H?u9S1%#$&3q ̉[̵1/$%-1/qI &ԉfnX:i3iOeL40& צgתi٤h ok څT Zl5~ IeZac7:yr[{JCF&fXa0pEޙs3@ZDb^GVo%>lYQLJ$ؒh,^,?h P әoz%-wYf.i~ 넴L_Ŋӗzn[vs[vWe61Gi-VGYVȟuۣ轼zPe}n=X&\$k{=05϶N4,٭_ڭSioS/f!AxSXT+e?Ak[M-WDZLe+6][&̿9;aCT܁zSϗhV<̙3ghoo}d+Qfv){"TO~7  1bj?H.M-O9j͋X g7wE%el{ŸejaEL!*pԲ 8qRНKl(K"&ĭS x[ iؓ#n{"{Bv+&v܂W*(_>yE VWg˚VAOܪq/1%n ݼs)[hx^▰V'o շD->=:D,Xڭ Ä4i_Җ/E<m5t(V3J|{'OK|"UC[V,/ ,+/ WWDLsK+z>&% Wc,mp?ޱjXh2,tz*i.}c"n绚*E^^t, d+aWŒ P֝RDe뤔8Fմv tP`iː2_j__8wv򦮏ڭfʦ՘׷M=N6ek7;#Nb+9%2gUI,fJ,1+2YXW4ʔz5ɪ=~5ig!=Cc2p5DUUt ўG1Ͷk`l;j}IFZM>)X9RGUZZ&5fQ(FJX\I)5m!ʑp8EEEπl7m#fZgi44~ OouMD,S ˈ(ruMADy- ?6XBR*M9ltO%AQ;iQm?'M%sӨ\V8-;+,(jc)%;a Wʸye|ӒwS]?,NtmڶdۏʋgfI˞EKeubWUCgu'64eqZf OF_99icOD!BbTbeQ_ض QP(]](i(,'e zvѱq}wܹk.%d+@D-BD>Is>|Kj,h&"lja)+^ KQIYV$I)ve϶ON^j/j~z>I&&{qPYֲ e! /+#_xZHMes%?ˣ 5WV -c2$&zV]OBZ}C]+3i~h+6̓ Qwxz{K%$r@6|"]тB}}PsuwsrvvtE`k###<͙״t!߉A19-'ǓdΞ])lP ,7N+*n0J/w (mm`0B>wW4=AP*F?9I9ɧT eexzhWN%bYѽ#h(m㑱18Vg;L3᩹C#=gc4ܢ?_Ϥ.rb6^S['$=!-Ao阧m0L&Sض=$,NL eOL(,*:wICut㯣TRUWr|i'Vo%>~]=yEp8΋(cL29KTvwQ\RZZFzRJrRrr||ֶ6[ZkijGP LW([P_( -Mk5h9jzsLA~ ey3rhIjz(M6 ̌@XwJԊZeAAc}?Ƕ#&( #,)&6dzvIE%e<1)<2ұ)o?>؁G^RY!&e,6{Fu)%x1[BZҡ3{,^nYe6ֹlFG'5.忾YtqOєTUY0"*-Gb{zKWK^,X&df$qT]ܴ("8Wgnm)|zki HCBZMXARXN .c-;" xI㿎gdVQYY[W[[WǛaaaN߹]| {Z+ZFꆩ/I_mc/,Dc|3i$,˘zdJJȔ5ӫNIӘm~ *iY,qL]Ro~en}2+%_,Rzc^~gOsWbG3. dT5*ɴm'? L88:;;5 _ w+dٍ,vYlFX2976S[QY1S#,3aJ_rylin( oMxJfkhiffaӖ L6Jy(["8GgB-fj"rn;Х!.d`0o(7ctwy˫0B1V3&'!D+iASL@EC[^qZաH˞bdjI))ŭmkqcjcnݺ-)xGtht:0M-,)##}:sE.؇mۗw+߯1ɀS465+ihcGc7q8ںZ\P]SR31kj}owXS[[ltM@q(-|j#S/߼e.o_>VWEy:M=e\fY-F\\ܩ(]V /)@nn.\F FfW<+s̳$'4 Aa0׶)ǔCe]qY̙`q)n!hP&#wngN_~CЈ@ O/(lljB2Y.\sjBĞV(%\9|MHOfQ&{9ZU 55OoBXHr4ږ>#6>e$:Ʀf37E) FG9^y:Jeލ_ծ)<\W>rkAwr CB+CKJKkjq} kp["EfsM]Ţe7|xJELLN]+R%`PGy6Av5#` Vm۱UXCx} 4yVGOBǤN{Z8&&%q i9D-4C5]h h;"Scj>uKz^e{l! =|TKWoIC\yO{yw-J* ~ 1a VXqvsr"OABoXܥ]Bb,vbJ{YVLvlnS/aam"װn)梫l*ϝ_"D]b~/k텀 mn1mOLN<|B*19y㲾ꚚYwb<}|l4u/^36qr.k񅧷O9:ꚞn%sFYM@ (kHɜAK]DYoA%3K #-?a`HE dE3%m mb9+ؘ>[F?[ZVEvvs7TQהv֎II_gmgHΩAZì9DnڴUu`""AcGrWPRjO((/eKL&!n܌V̓6Dד=QFr%t33ZNj(." hTj ꔧ- 3'l<9Cn d1/l/im;oju,]axx[uXPw7>Dtt50D5l2[;MS ot fH vF捻z-vgۭoF93q{&aHojӳ+|ˆ Z++*xR19:e|||yg`ll4;''95NLf 50<(AWþ~K~aṋBO3sZAzWSf˟(~娡AXBMڿ0>΀/byT˞J[kniwp::@ ˨{[QTgF/ kp:ɂL6'y;OLƶ\׊Qu d[-2LPcS5ss𲭌]WT2Z+K^7٭ (k н>hz^ƛ{_դWo)DFX%҃y8KOmnm j-gv 먔mVQPu~R5&I11 7NvhstiwSgSiYpi2Um7וzy||M ,]m#;B,~Rc0SsgS̾dIE}`juXu%*I$.hohd+,ʺ@urq306x;49wj1fױϜp%||L`'l W#'j[ںֶ6EW_:TEIdP[FQ?F+vהiZL\$fǥ~|bjW\{ciktV`1AgSժO Tɤ3&4 kNt;8ງIu&{"bc}7"V&XB҆q0v"Qn&MXS+7::J3sD 9fyk_ϻ]‡~ &jD,ër?oN+l+ #Z01 4Y>ʞXP\ Xvq, KS6T@2Z*`pK6ɕ}h=k({갹7DS.OcӫhZ.x!vWwwSs38;'75-=v1wqw@+W}}"Kx;Yso|BPEXMtlh DA-%-IʺWX#5K۫pdkZR~}VT 27K9طʼnV%~kcikh\~ xUeZ~5iU=߻vP3B7 lfiD uBHj1&U#'N;jw!,nIeO&s~&[rQwP]VpTKPk#Wz=BպRQͧuIa7>} gگ9 EEp36;xaCGNyx BE0QXTӼ8*tO^Lw-+f`[rkcp7SxdK=YITm-zAʠϞ:,`URۂ2N3rDf+jʦNЊS\>ddOQ«,7?y҃325G/:6^ֿp 1'﾿xۯ/~Tht&)\K.kرY*\2.Yp,pɢHKpɨ.YyKVd=Gdjy_RRSW9܆`maU(jqzսY e꾜 z>mU-wb24(_ft1nD^EoJLyL{oqnGQOU'vϩۯکMwiԺU>t||of<ѻȉn^Bتr)i0}Ta*n'V\XyE=㙀$O-UM*uC[U*]뷋ɌO+@G.׈?r(Gǯo2yz.7j%SXֽ~TgԺ뚛2l޾֧'r8rƫ]?riYٶp\xgmMeW:Q҉Q>w\{'gU-7?a,>Og#Go}b\Wucm -EY dž,6W$HY~aG4tk\^피2_ԗN~#BN\rCfޏfX9jfsg{2ɋp+uSg"beHL>y cEz +Cق׍Mנ>b>&=SϾYrfyoVBRԬg#D4pbޖJ?abUm ئUqƗ=KƘx3KkBX;$&QZf/%MYCASگm]mڠtZUm^yrzSGo%FԄϼSG7uP?.irWOo! 갊WDNn2ppr9ةwpD8/[;z3â̜r_ 3nؖSnpS+P4 J^i 5]瀖؏h)R q'~%+7_]"w ~RqrE3ِ^L+,L %;D$Z|M~>訅cb7n7lyu=BѦ35_(l1g=F 2њR\iƛ6ڡ5h=-whfa[zjHҖO};?S&j_o;T]~Tj݄=:5z?HHT&ʤIwʌMoWpSR,u2"h[˹ÿ́kƊʐǮm1S{藙9+Rmޥ5qFAkU$I;~qɹd{ŬʦޖnVkxl|B`Y$v9T2_VidE'Ra=-C'AN.:ŧg)'5Ƕmd*9Ĥ O.Fstq}0{dN1GW7FCJ;wN9G~D˶/-3G&U)u۴INiUգ `Xl7CK[x M"M)qHܼQ ۻQlfD\qoE=bGVPZV k{ U;>nz=jh9ݧ}ziG7O+HOoAkRs7nwa+f%UnLmk~TOۉZΛ_wnWXlBsCЯxkJ wL-W2`L[u Gל20^Vr&>=膚1*n;On5>an1e^17d`a eť_r kt*t ܮz I0Tz"9\􇝬nV]{OIm ꆶ^Ĥ3ⳋIthd6<"8/ E1Q Kn{-}=c@G:6tI+ 3:rt@ yYasdr9& ]eS/:UŔrj5K˂6)2ھJ)Tu@);VXQ}slK+떥DibC1S_z4/> 53VS6T7u1'^%縵yteg:L ֲ}T'MyO>xzaW߼C4w/㧾R`8rlUj? ,-wero|~NnzC*"KMwH}uRP7 CC:mOAVO/ɞ4mG.bgWyG^p S57dV7r's%ymu&"bGlnm0%UiX$suDž@1 _:ǭ6c;b?n_hwhh7a(2"o,}CYECiup%ޱ 7 T9T c;hgdp:x$:e \3Klfu /G4L.ȉԪs EǏZY ޥ|Pf'XȞ f|߭70j,&3{ZUf,Fx&땃_^Pۚ=_Rmͧ Ի5ښO_Twy]V^5koV(Y}Kc~g{c6AX{2}L(Z/J[(6܏Ꝝc-w|t&/&}|Ej.9XTv{<Ԣ݄&, i* O8jɃ~D+ѯjۺE^:4D8&$%)^'ɔa`ѫUhPfbtőɹwҽ).uXVGc)ۀ>ܗ/5I[s֓i UCG^SC׶0;38BҌ-C\a*sSϼ>98$&lL}O2f$n 鵏^~йe2(GMS"+(nUYV_2l?̪jbTzVIb,m5V9| |~m'6ow>̳s"TrgEO s'6 --44<k^Uc%Q͇9Q\bZi Z.Sahgx:Β+rZsrx1VƼ^՘W('u'ap!}>Cƃ:HږN0;!j%'~g]/G.M&f-?v! p0r9/&sp mLSݗD'nPlt'^+&3XM2L2v?Q.NyhŠ;o%)nƝ͂?⎐g_'`ƦǦ- Qg'RX#رŋI<kT"k. O8i㯖V_kD<6Tfɣe遘<%66R 7)aqe*0|,Q2l+Z`|&.ږJde]9A=ū.Vûo]#I^N>E{_1ʴ%(Y ( a8}fY a%E}5y#JzPE=7?YQ8LBO2{ k /`6$ѮzT w $%1;YC Zwti -ufɌDZUL/P|2LYбK^k9\̡Bg/BEx oDC E.;_ڍdNK L6cMGNPzӓ?閨T7~tQ5WaVD%LRDZK{@­r=|3i| `y'.E=H2 y7aQg$BI3-ŕ0lUi@YrUJg`\˄Tu2Fj|ڌP䅰T:l闙;ݻlRn2%<⃽|rm'>fV)l6{7=-'V #K*:Ht [+O#mΒ){b/7i]KsF-ѶB'}h[ņfjװ@ ceߧ&[?FXX q5i^c+opcJ 5d6آ5۴A:sxx*u’K1DO}Y;@/wR[ãj}mIO\*湷S> [ƈܰ'OMe2>UCCkVj0cXSmsw?%]sVd2#e6_:)- My‡oGW E82Zv{GL[;\ՠٛF;WZC 5G}gqG. EcnGXc0?'#3)L(v}/6 oش=FfؽU~m1 ŒJ _﫳Jlʭ\b%R=k?vn%B}~##ܒ/c瑀$<欵SZ_Ev;2FƌzJcO|속{8|f/O}ŎqDK]YT"A9 D|p3_}Ff6mmL]?QU"vɌ+__8<kd3 Sh ̈́ϠJ;R#o e:s充Y⫻yy}o~WHx+vf.CC;E.t_&jO®QJ}[e`l:00YW­|uMl+`CfeYja|$95Yq&z*T.u`jߩfsARx[gSso{>sAVT|.( Wz87'rL4Z'Jz[ !X_iNĽoL 垸DDLJw$ny?nӎ追vdY~A{Ж.}\A{GQ:6t8#FUK5/g)ݪS*nՕGuuwk07g.k 08*K֠Z7_"ɧD"̞DiA4,J5$?IWfмSZ]dIec ZƛL(i:gM00^|4 3k߰ ^j6?$ʑZCZ0OkuyüSfOs$Ŀn?Z)7ߩ/h/y'2,]xt$MVRb'%/`^֎~t.䋮8`_<V^r~'<_~'٭7vR5ڭRD^vV d07V3"R q'% +;Qtx>3 4Qpټ 4@=>=gCnsV7ޱ$ 44y/Gy{On݌ώg?s%6U~a7c`af-q̌Q=r~z_V|GQ?bۇ7џk}هP[$5VhP/zu%-ɹF~QM oϓ?$]N)] DCM̗^1KYRІeՓY}ӪcJdU)u!zDMSev66*7ށ9W< 6XXK|u7=owI[gDz/zxʃzz?o.bZTLHHN1GkB7WX,"G"4߶)dmrTCDϫ;4TL-!jF}f H[>1e^CP8LXyˏ8Khѩd^e&D{Y>`][olVmv~&e,Ltf?]YԻ?k&g^ZHЭ~꠭{Nyzv+l+4, «kh4TZ]lJ8d--}r , GPm͗mH~3cW٘yXPMD`D1TMe-ko׹TϞ#:hgTv.=͢\;4VLXơ)E[MH{TwBc. %>b[.JztY^5&+Zl:j2r9=!PȤd}[e#ŕ624G B}Ea-siZ*נDsקbv;ۜ^5hvCCO 8:),Ξ\~5^$%O*l::p7$, OUm߿<,~Ym1 L B_6n'V@LoIzm(Mg4\CMQev]zA}oBs\ݱFT* @0?j|%KTl7ʝVahGX:ΒUOj-#i#Zތ.y҇WO5( 7T Q$ )mUx,sih+%ѱqNov+MNAϽ7S,WfHFM[&v͚ck` -qx\`M$VmuƟLgw[ժ:he}+6!FJbpܺUվG0&n&˔*_ 2ʮj6b`uIu&8ӗ1-WiՖ2 kֶh\V> |O$c9GV^Ӻj{ ݎZ̽0g䎚ڦNgt2\NkL~1gIѪF`[i,Cr%WyWv11J5 =r\I*^lU:`#1GV.ɔs)䘥:m%ߟW6b,? 5,-JJ^\HElmmpRĊ'mMwѩۖ1~ǸT%n&ZFM[}m @* @Oȵmݏ vvdɲjzT˹(u=$6oqBRy+j,mLmtf\$&Iq9덹Uƛ#U)ut,"؞`whpX&8<>)~vj»>ɹ1e8-AGvP30 8K?o7Wl`[.46(GE[E,(E4H?a3\v9e /8`c:;8,9C/=0kxz/TLuWEʠc ͎5Y:U}P;:P h:}Wq?ƖWf`[+ryǩ_gϥ0L%F_m VYlq7K^dG,4~'{n`whpX*d2y/ st \m*:YH٫YCG$h8K/Iw{V``[[RcP=PD*Op+QEW\'#=T|~[e6DH.{zie?hs5G,#K0 ⳋ'3P;hDS5;:4m5>3JVH*;_$CS&ėNl}i,t٠vZR(:E3!zDe29AK«fo|s,0;RUݡy`1tycY`J>cB e`F)7 )r2 l+@Q$mj~Vr1faW+gzk l=+,d@NGR.E[^1-! @QM3}w i # zԶXazrKXyˏ8K‰x m˜Hr}(Jk-]9?#bpvhڒF39AtOTL!WVGXGEcݡy`^DbJ>s(Vxť20/aGBC"c a( {32 A=[ۜ:T[WmCԮa34 Z?!]72 +ϖ!%zk XZRG44 OA2n疢mx< G'$vV_gq'@X%=?Ģw9K+m̗V3e-Wm:WumP=ӬMIθ݉M- Ym^!Y^,[=z͒^w*No7V>41pCM4@ʦe>fD PbinIBCݧ+Gv`[ڴ=,]cqַKڒ+y>e2P*.eQ&B᳑tech^TzؒvQ׷n'gvS05&3(p:ؗYjM~+s,kw/ !4qj&$ҵl6 iq#wORrK7?R2ƼuY1Vb_:)Lɦx6%X:"([7We&3G<*:kyjTa=Mn[!nد5^Aۉ WS>IT\|}HZ nb%>?]KhI%} [e#ŕ62w1zGt yO`wh+p{l<29fX%eGy ,T7&~fUվ#GTQ`M/ޮh\CH*,54K-kؽ\қkϪ?VSԯG/M݊y z FvVg#鯑ߎ)ݝX]f~Z̮ad:$k8gl`~7J|ֱ͒_w*m2)$z*$ X( ;8RB7 +Ye5b "/&aݏnd<Pi34N$%R_:g %j".4T}q`Ժ}~r2mo2sz^م솗om%}T]*CLXN.FȄZ2 ^'D 8ɀ)oEÖsN!4C;b,e\9hBԵ2x?aED)2bsPmgU)W, Ze1jpb`Hweב/Sv'+J.Hݣ^sӤ֝ ꏕ2T2Sɀ6oXMp5@OL\#s8<>)~3ZD&粆@Xbk;nw:xQ`[DCknPL@XmowV} 4w'^5IC-`eHz;8ni$%i<ۍ"@$e`ujcڑwo H+ 1Ď%lHh#${#c.1icbPe2њA.( xz;8ސd#(̭Bo Mrc kH@xnb/l#ɀD f)Yy֎J2O2Dg#VYFMIx,I44 HC; >X13z$أ Az[ޟ\zkIiIkb]ûޘ[e6DHJweG2f sV7M}p)mZkx,$v3Q<&cktTÒ> j= *>W7Ks~7'>yE30 hdHhrʦ7̰)m-ܮbݑ< @"gF[ADg`ƙ vve5#{p̩1>\̂P,>f鋆B}`[i `[91xD`n_\zK-X4R~N7gbz5f8+a^l-Z^WOP*r{`dI4&MJk 4QNdrq+?̰:m]<ʝe@in'<`L "?nSTW^70z>1v¶\60U8|fRH #H#}&e`[i`[&54!0$R)(44^Stnv}@ew,ŕsֺ&Q&;d` { e%P[Ht.!a w!(mH"I/b^U =I-ݐ ?Qh3(Ru;v}@G&Uԅ6NW9''GlaN:WF//g(8"Bg@vXߐ2(Ip8KPF 4a729Wz*/z[F+AXHe wѨGS>+s$ŕfsL'^kzhN/$hjEJ{y02GVc՗fxPF 8 }.~#̰FVYX(*ŠΗSJer9v}@C,#U,(VW6߼?ٖ% jIf[ZV6dYe5|n.J]{(7+[js sb)x`;>ϒ0ols6;{֔D2bh/7Kxs,8%jJ4*O>T4̃BV:8nD[i:`[# F~Q[cjP!3w%.$&jkP35Zga=HlY =bUJD(hG'ދg(+=vք.cb:p8)4`_;`AS$Z(~Ɖۮz@gmq/9bn͛)V6I:7+lKx>f^}T1h1`[i `[=0~38Q)jrg<1# l+@gapټ ~[eAxHIdfl\\t僒WF-/m1p +|@]yNXtv}@ ʫR"&/8`ûT|.cx=Knbs5Ev; V]JN~DAU}pa,!X@e;iuWDi֡qǬ|Ul큯Xb0 -?9W?;*}Hh+~Vo'^kɤu.V93j]pk ̐٥ V `;33x>4` >v]<ƝX6`G3ۨ)̟,DVRG4hV sA" DWսT{P蒀ԁ3K[3胰!9h%Dm}3N2PB|`o3 Ҟ|~{3! +MS>`w {bn Xx|4b _iMPab9\Z@(b,H>bM{ʡj%5fie6=h>|NYS kxqVdQ/ـO^w'[b}|q1Uy; @ ʢY=p+OzAcJ#|jz) Xf? VHI*\Z VT r2&Ya g_YƑ2-]L2 15\ڶд܎u]alG+cś%[悹U曝Џ=} ђp!a"y* F*wq~vn]j͓>T>)VYXh4xmVn )~-U:h ʚ=̬GDjU_5q!HTe l߇}T3̃{;CܿGKSպꭋ"rzF9dV/ԓ$-YgKV u>E­B8߆VZpZAX%a,]ufOLZTz X FH_+2Q7&u &Lo#^3{s_wئJxzwe+QEJ᭘!D^{{$ϲUZ^[Qېy^yoQ7xŗ; [T.%9Tl8a؏h=#u}p8G T*+mq!PtM<1jmxBA$>hcO)zҚҞdH-A"YSU/:`[)V6Hnz&Z=5xb/~Od򇾰F?|qy)*[kޥh`[OM>ZdpmS asqʯH \BgC~^%Dk '}h{(q-P}MF5OX(@s0W٨ÿ)s&G$K?^`F{Bhԍ( 8u *'*G|PYt<p +L*J #o +] X$Z/KYj~S5 Qfx]JNXdO,mn!3=,O.^{q.x} UzFԦ<tAϘڷ%.f^=KA"gk$ŕfVo'^kɤrhUnr>Knh坵z6%m{3?02 tf}ٓsI5ޥVZVgU'm#s;YC sL-cj:}/V@XWm r~7'4ιܩTs6#[s~|iTݏSZ5fVbnˎo7䚙 Xc;2Ζ!OkK J+X:"n|Q_q҅ukr{F'Djݪ\jװZޭ<`Yаo2.甈xmI{f6/oF5}cHOMYū.[e Si% ΪmPZnRO.HZ:nf[j-nƕevG:N,Wkӻ+tSM>.cJ+ zrŴ~q,}1J@1-`z;!}y͙Чؚ6 ;!|T }?'i2 RLfT,Ip{XTCIp0;$JE$.5,}>`[i`[ZLK+$v>HYhMJ>chtfCG7&G}SS~ _,}fG.Lo#^3}s_wئiMx\BsQ%9Jjz nV}GIti950- 4ߏb5I4p4<>+ox"'?Vm #VIhZlYfE*0"b l+l+@kNPWo*ݪ6!InRx]F}[lIДYYn}dRyx9̰y=ŕ65,`0s >`[i`[_(J/bE5tܪ~qu=2fW`_r $lFpJfk?Hzgg,ŕ[-J*DUOl~@e³V=㙈q4 E"0lt=1ꀉ')E$>+4+Ƀʚv|wdfi/$KHh-sfr MvBkPkUԅ6a.|N}> P"<\GC ,2YIm')sۆ'dL?͎ V_9(&~zŠHDp iT|rg&{fz|~%> ʃVqVF[`[i4`[\~'$v6st \ҋ|`=ߦ6 Z^I-Ek@"4,*:xҪ2hghԏ \BHZ OǾ2Ò7J XHKnJJ1d 84[30C*K%֫^(Dp ir1' R\B #|MNOlnavpJ457AgELM x/$V#ô4[304kVݼ~gvAcn UV&Օ+MIigkQ\9p >H49SV$m5m"qVYEp^)ꐙ')C& @{fu ;3 AeMVA5$BI{YWN=BlS-ӀxdF"dW` .@$ZyJ{ٟzŠ=Z[a&A-l+`5ҒEsyJDh,cK~wbj:@"V V #IM 5y^ժ~-BDo/rxmz<+@$Zy( aOZ'+Gz]72PSF[a?ph(`[+\.l$%ܪ} Ye5<XO2<޷iy \B+X iQ3TRlᮑE?ќLKn1Vp,y=?l mҖV$iޝEuhV65kzkkMD[5o$mr ⊢BY1 ! Ѱ 1ɰ 83xq89<9;j;_:.޺_P\CfJS=#.]8%U˃m_܏.ZK'xe44BC>D$cČ۞_U^>zROx,'w+(-'h>*yZ5tFiхDmE]Jdj]V|~juxC/TTBC>D$s5M.1Wt VOl8(o8V@ ݧ:Dg~VY _D8ѬE{z[b/TBm~jaoC./UfX/]RXH Y(m8_*X=z31'SR Vv++kUQ ۏzÑ)Y׵Z Ͷ'JM#Y~Nb)]R_Rݶ9!wrIȇ|WV,9/8`N=}bPB$En{{(>w4ЗdT'Ff%W*f{Hu}Tr]7)jדx-<0e~J,NӶKThv1y{uPRVhm-37?ū M$vY)Q눍nj, UԤD8Fne:w w=%^PYX.F"!"[V7_qw>y V?CJ([Sָ͎y6@iyop ͚PxF9cH]HݨΊ9g:⑷/MO-K?DD>CDMNu5wPokF' V@ F&E#8흹ȩn3)=Y'g?zH:ծ'HI]RH:t/뗪Vw w=YWY.F"b"Rk/oZςe&ˇ"PB{ÈZs5F8=YMnlwhTkSm8B^ ijjh[%Ul\gC.޺J.F""kR\y%HؐzCJ([@eM홋Ww|WWUXcT{h9%pp4ۭj죒k,%Dd]$,!:uѶp=S_.F"R#*kPRj+U Mݒe+Elx|փǬv_:o|򪚖o\WL|$Ch'U7G%?WJ{PFlv)ݲt{G5ƺL񮖗T-mmtIUIN)|Q^e킐?[,<3mBVA2iߥ櫢S}`MT5kʝ'R54}T8yu/k_l[yy]#uY)RxM A;M۾]Re^ ˊii`c"! (r^`ZRu5Wv{>hRSܚ٪_˪TQ jY3]Vm}Tr]j%߲Y%Vm]Rl:钪K!)bB 򱴈 fF]-Q z.V@JS}¢WETun>b/^/jd͚[)->I%.+L/^4F ]|O%Uq ~ ݺFTbIy& XfD9oy{r5^ot>TԵ5gl=xLkIEAG#Tznavgs/kwє]NpS{z:q/P%UbDD>CD"쪮N*-fUe+El˲ iN6왱hT5snNTp4<y/mZ:`ΐ̛Dd &Gu6g~u~woQ,UbDD>CDwILxav~w+|([)e+3~w-XEg`Z܏~S~4sk4̩u MQ|E w~bCttmLm,J<Dsb^`=koyV |([)e+9sj9r盾T/&(w ݽ l}E& 3US}K!)ᮧt}u-T_wIԒRunv+|6bDD>CD}_ECJ(["cTo (&$KG{SV 5 Y9q !VS,m~q|g<Ң3+ *BbDD>CDw.&w?[>DPRV=IS]~ͩJW='TW3:j~oKrkRՖхň|ȇL+4onݔRŦTM>UwkRS[ͩ>oT̩gdfG{'CD&QפvIG*?&ˇ"P5u ҜꋷETŜ{K멖!eۥyїL 9!ՊR5iBbDD>Q|JGl tRdPRVRYS{]#`Nu^kis85V_壽b7=k->J_Q fw'gtQRj BCDC>D55=p{1[Tf; e+Šle;|Ƕ^PPZ~<>ycsyFTp/s>_2J_d'?d\RtLHE"""!κV^ ]՚>U{G;|^(>ֈ=9箸=zJFp/?m$U Mncm}TeFOHek0!U}U=]]@>#. {w3JV{xԵCJ([HJ s{{G67wLT5oTpoYy-zzxƺKYz`o|Φ XܻRхȇȇ|gs >_5/0b~lU֯/L\f-u<:O +MҲt{G0xѨQ6sj <ʄT)Ϋ>yMH9#CNu5wPBm/9YZ|([)s I͎8@]>۰JMG6yIyݭղvwy/6ǣ{MHtۄv J{"NADC>rILxq߯A~uJ·"(lؤY\s"Ș{/6w%옷j˻7rv;ŲOXtRz OW[-yk{sA\m%h53_3jxdWMDD>䣼j.1WtNFCJ̺lUSאr؋}W9ks;+\?;sjJ&rJvE+4YzZttׂm͗ꢲ9 U,9/t=,8gDD>5+ݨZ+a\VkYPRM~Iybjq[گM\deSME(õZܟ:lH?Ŕk'] I9m#l5+`yp8߄̖3J|?+{qR03w}<<#sFΩC>=ѷ/1Xh>'VZ6<%WN:~ԌEv.޺_3Ա؋.曪6"]٪|A@LXWj7' ^\ck+U6O^Zۨ朑sj"r2yoXtnJ|(~]~kF_+.DJlURQUUTg)6?-Vm/ ˤڔxx&[54%U]e{9LٲlVSK]@%^/%[[nZ?VFwfTG%)@*^= 953rNMD {ä?+OO޿ |zI%]NNjvMp5u]/+7K]#Col6)ɡlQkJ>]ys휨AOΞ*Mܽ{3 9g䜚ȇ|ȧ v~VC[7H,Bp@Wc;S52ۤM|:w+[ω"2nNBwC,wv\ɇȇ|dH*[O_m59al[eIswÏyc=vQ}1:S}_s;3sҪh/5p95k\̦CR!pLVKz@XxhwNyU[focO$\N/)g)lעgW޹FtSJ='jhwuI[ĥDD> \Y~۷Y@|\ e+=᫫Jv4S}.MuS䍲 J?&> mB粸O1DQ f܂=3q CDC>2qZ}n}|pIߚU+]]m5khǙ[Y,ۻ]YlENi^4dku3qrݨƣR ŗE5C!"!KIL,uxgA_:)[҅([dfdŎ㯽pTsg(YHV+T;6Wq0!";S酙fzY5[H' Z}1|?DD>civ " pP|YXG1W& j+Knc؅([?V5򼊌 u:nږ'-+;ϡGOI:v囵;'lω;}ݡ= CDC>=/fA䎱[x&f7+]S]ȟQ]Y|dZWT6<|^-~/hd'KFX w=Mr^R( {? "]/[3]-yZ-Al 0#Gxɡ7-\6rY9'/YY:zm}TeC!"!W]͝;T^=/0Dd.DJ([[4jMINiJdH g2'H/L/*W˟f~VNjǩs"!"!nUۨv!`ޛUDd.DJ(['f^lcHHnU MDd.DJ([`Zd9Q*]b<| SR^) yZ  QRVtFկPyX6+_ne*ZCujdggt]bVK>""y7J{e+El@jO,&Vl|t7\&tF31_KC[!3J'e+Elڊcnk} *T:3v(|?DD>+JkAiXSK̕F".DJ([EFlv)'=o'+knZI8UZs>9<O*Zr¶# .q>\j״|ccY$TׯPepD(F*g}yn񩵝rBD>DD>Y9oyk'>V@Dօ([)e+]muxM~WJ|.Htx~j6o$T*?p}_)!ZL, R^/#^BN >NZJq(ۭk?UN[g"(lɄ UEՄ75ٯJSw;9!"""PuCK̕g\Q;W,e+El0iљ+`R6]Cec7u}˾nhʍ7IwywNƹŧ5ɇCDC>[Q @;_iD}naČ&5ɨ QRVҨ57R2d7s>In}yb;KZC^QC>""1ƥy|_S=#TWs5Z-ɮ QRVhkʊ9ӴKTKF٬w|%Z' ~_ߤLxqi=Vjݷok^`tB^ ɷ QRV^ToPTGو jto,L/^6nۉIwYԵYt"7,g?DD>Om%Hxߢ YeUD$.DJ([I'O,{OukT45Vj0nka&5+poJ=b']5O[PX`>E5wxlil1%JE}#GlpSOL$^@J cPZ::U}u^TZ̦CY-_SXZ>ʫ8/@E+!g\ V@ @O:&T&&Ru#u*pNd& z) "2n5Z"(;7=uzGxpṵ QRVzX~ZI ecȼ^/t4]Vw4v~O_9VYXE\_Τ([?v5dEfR(-V{jzpB͸N2A>%{!qn|c3.{͚Z䰫65Ne37TTT߼HetO٦Cw~%V V]mPk? "1|JkzbAi|}Trau}lt7g<۟`w}_,t)K=KE# s9o>ֿhR֯nwM'k* * /l֓W\~E!"QF>e B?Vc<34]ltu:-:3Ԯ^tƎţ~4U1C#oteɏ_Vwt],`yIK!)Y9%9Z]1„*msjHY]"P`*픪mX|)$EwXazv⟖?ެV{VT^O=- /;UZ6vÔ-xx-8 ~†FڨuU?NΉǨ|ک_5*~E!"1|rtXꛛD.DJ([M (U(L/ZřkS OMqZpp)[n-V 'UTj-,:qשj+|ڗ]fXzD+yS$ƨtH7@o~܅([)e+_ZW.iT3^IN .JhSb۞VkvSH.Dy3hvC [\^Q @X=$ƨ&"R~lC*U8FnaPr᮲Rj xIh_fs;sKhIwIh-rQR"S]OyXRDp'J_iQj2y?DD>'L9 b(:{PPRVڢRQ[Z$]zJ@ք\u-:!hсPFlt"_5jcT5<iYzW""~'ݘopou!V@ >)UCݤџ^ltccLp]盐*C}u1?1T;~E-%5ԩ%Rԯ?DD>2̧I⶯fςUDd]"PTaLtQ6OSSVׄ.ݖ뮶.mNeFTϧejկ?DD>ʧ^xiHSdȢe >c ={vvv1oqww;wСC)[G(UyB-݄+ڙ~:~C D\L]6vY:z5ש~E ߌi~wCD#|UXbHc ێx&f4(tNCԲ _v-''71bD^^^4iҧ~.PVШnrw&-<|`bIN)AurVnYF\vBň-.Co׷ \V]ͱ .i5Z8W@>UQctp Xr>ZyoykxeUb "e+S>}#o߾Tur=YARUuJUr$mͳZ-e8u4_֒l I8WL>Rj\W""se0<$/zeu QO'":Y" "M>}%"RAAAb}olXƺsUp_\Ub}JdjU1sUbb [f>-W7~CDK ˯C^uҗm>왘Qפ х ҧQ$c*ӦM&%%鯼|X)÷S,*eU?O |I+q*ȧ;HetW[=xTVb+)BjAg#]3fHeqqXOwvVTeQ Ӌ&fR8'՘ܢCGl կFoQ<\PF>t!1kRJ|{Yԫ>~<3BƣaZ644_<1A P*JU?~w6ߡ7Wc||Bc~*b6>N}ךkQ¡ uׯTkŗbeiVWէD_.!(|ttN῎[9y)W""Snh NϣxO*]EPt΢aZ j4biVkT5ʆRpO>ƐWO:vW"";Ѡքg- 0-/{~[~9a;?VtaZÇVVV꯬+GeLsPƘ(UZ֯rWC"r>*yg[ݾuOŧfV$AVt.aZ4##CR={1A uᮧ%PKFوuk*)UCճL[?9JKn7k8`7J4?\ se0$(}(w~[JDz&+]\\iVy<@)] vKz2ɧ_=ȧm8|c*?9Cn;L+))ID_tppׯ_NN1Uhj"KˤNZR"S^ElR#˾p8"~OOW?dXQB>t!YeUnoyPЅLF{wx ƍgqzJW迾X*JrJuo '閬Lݒr~KGv_IgK)MW1m|s5NпJH~աG/ u:թ]g/͊XRd_ٕ{u_EY%WU_3nl?t7Q6AwQܒ\tXbh%s->uGu}zF\=";hGe+L/^6ʙۉϻ56V֔]-I~5Hro1ҽoAB,Vy-8;lmVI.;.iQ6RM⛋!~qJաmQR Oi( *.Uf͢ppO>&'կozWn2yo}.|*;QM QceTF֖UTJ2I8%]<w-ZXeׂVxpwf˞3LƮaŏ5K,C.~GVKKrJoXt5 *3ē@>Nd{2yoTmЭ/ %NIwB-9NEKktzΏ]Ha>*yP{pP0CڱW7TW\pe"W7Jstx43#`f鎹3w~<Ⱥ0޷^RHʷ3b*j4jmoDs5ZAUC]]g\>yZ艹Qɢ5Z]HI([5ݬDO[VTvXrfs Pm w ;,@Պn'DHe+#$ؠ$'gg|}bVX+y=05]roRN s'cJkCDwO+\EZ/e\56ټw[v_esbվy f33/yfxGiyq*J;qw[V.$^ ^&^aw҅z+[Nx@ofvO=C׺_H57HW[,ec3a.<P!EP+'s8!"y.1WTS=#o-|ǹ?-~rvrA !Z?tz ze+V#VֿhM?'7BRҢ3sUWW39'D|Jkŧ.9?3.ݔDcf^~31#FIm.di]HPqns=dU]5?Dt([.mN+6{3.A.}z@;_3CD==Is ='D2ϧI?-~kd5;]ȴ6-T׾w;TIe Y>-+L/Ȕџ}^`8`Kqz~wНӠ/K(Z?9].DmlE;"3'}hoNj1\X.IvJCD=rNǼǙI{7,cD-T3]o[hd !zk9{Ei Bη?{[ena;?7#қcN=ub"2#8!");ܷg֮Ⱥ{s=4 y%շ YeQ|.UY]Cim_UQZ%-7Ko%6(<#OZ]O_r[|\JZowD?-'zFH˫܂4?O?Ͼ&W_sRLn.b"" tYY]CLn{B°7Ⱥk s#t(F|_:ڧf.t2+_* ݐBb&C* 8+ >qquIEJE!/R* #L* eK {?if׀"~a'vcb"" ܹFE~'S^-P)ZcH.k_;CtHq ]Lw1?Bi ۆX^3Z܁tnV(Uƹᗻ.8z^BiD.FD;@;"&jMJaحGD29x֭uӃ|oIE?>:+H($]yRQhυt5ZGnHERQH,w' (&$(ňrhGpBD>DYƘ|]zQisXte=Kpw"+_[tֈ>#8g$,C"nͤ P9#ȇ|zVN&>rU[(wЎ|@DC>!#8g$drDD>A;sF@(wЎ|@DC>!#8g$drDD>A;sF@(wЎ|@DC>!#8g$drDD>A;sF@(wЎ|@DC>!#8g$drDD>A;sF@(wЎ|@DC>!#DV8C-sFQx AqNMDC>0 ;hG($SHΩ|r0j~{G✚ȇ|`(w( 95PPj95@I(wЎ "!DD>A;Sȇ| C;hGsjdrpN "" QΩADC>!#95|2Dv8@(wЎ "!DD>A;Sȇ| C;hGsjdrXY$ZZ& nX HIzvN[E&C>-;hGr_m5?a#W[zZEف|r@>EvVQv AA;@(;wQUȇ|л(wЎ ҢX& jȓ[EY|(wЎ , ZE&CvVN&>rU(ːeݍr2FvteAwA;LKӣ|%ӣ(wЎ.lV&<Bvtej$JBgQ]@ n;hG@PFvte+Q]@ n;hG@P`YN\-YO|_)^CPPƐ.j+(wЎc\m5?a#W[݄r C;hGA;@(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!# QdrbB}CJ@I(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!# Qdr C;hGA;@(wЎ2Dv!>c ={vvvI"^>wܡCҎ;:%++kذakrrr|#F[&M駟v)ӧOGʤ/+** 2w\SrD\VVV+?䓾}fff-DD>CD!"!""!"Og9;;W&y e+9||ȇȇ|YӦMq%%%鯼|X)$olE?'"!""|:k̘1""bO?mPȇȇ||ȇ@>5x`WCCJX-DD>CD!"!""!"OgOĥjW/-DD>CD!"!""!"Og 0@ĥhW6666[([ω|ȇCDC>DD>CD >|ReEEX9j(ȇ||@>DD>CDC>D^{MĕR|)VΞ=$olE?'"!""|:kժU"Gꯌ+]\\L;)[( (#%%% 1[ht;OU5nܸ[([ odee~| &M4qNER[[.'uuu Ξ={C;wR_'L0iҤNE͛UTTr>wܡCFBBB&Nx>׿Ȥ-קOrЩstt/~C}Ç裏Nǘc#NL?믿V|8 0hРI&=zA%cv;G*cvV+6ϏM0B%c6$L1;xͻczwTl1tjVc"W^ "^*`f5f74&J&9$6б ;%Aѩ9]|RۑFK=|$Rddd߾}H:7o;vO>R***ė_}xƜFG#K,˳dV\tRO/]Dg. K:ܡ:0 Y ^֯_#GXȠdy7S5lذ_ڵk999o# Cg0ʘ2&]R[jLD?x}OKK~7f}d|vY Jw~Hl̡cv(9 J&9*Ͽ*[͝;9 Vȸ{쒒M6I=ńc@3f:>gT!W*cN;]VщΝ@:dmm믿Y Lc:RG*w0Twj<8'/Wt6 sܮ1f0(ӬF,ekk[$ΗG%>1qNaL>5(uC&/ATGwee1c:Vr_N0Aֈ@SO?O^^^t$} iL$b+>ƜF9sc9|jZMuufPZ߰A4(u2rg/O*}M̋1on*--M_'WwHg0ʘ2&c]R[fLDoxMjjkm&Vo:۬mc^RW\+_yƜ' H͛ǠԅaiR[iLQHeriqXkgv|t3ePRO_$Vw! 3.c1f}PjgӌG_P )))bw\lSy J&<$nбSvP2QY:5u_,7|cP'41hӑ | Vsω'sZ*%%% >|xcc%#K/dlYJo1_|i_baw\lSy J:$ne;(_洎y),,A($MMMjTT%7T @׋!q?Μ9C8mu[Nbbحlp JF ̖rF.x Z|A''';<(fء^ Λʧ~Si(`j]FᶛtQGddwֿǥ6k[;1נdCvL^ɏkjj}Q:VСC",Ԗ1J?:*۷/=#",YLu'ReJofBFV]livvΝ{l!RonJtAR|:Fed>lJn1__-O dR˜|kPCI^Rw?y3fBԜQ2#okF(?քԒK:tP)qRsN2D4iRbb8vh^xAhYjuQQQ``?/6`P2oXdfa,apgIKKo)JeiRonf;T~zė)i(cj]cݠd̦QII3<ӷo_;;;q>'ܲe˱cy)דL[]{/]rb_|aQUUU]Llo[%c%JFnf[F*#wqƉ~gR7a7S%=IJlll+&2FV[|v4#͛7?!CgK,Q_ iR|kP2!q['ok*++5u̥J3τ۽{7/_~衇>ˬ^zI|#zG+hi)8p@mAɘaɃ1VS;KppZdfء.HsA540Rc䶛du HW9r|ǥ6kv |kP2!qC7A$GŁ5ûV}7l@}}TONN֭Crl)>NeRRR[͘ݭ'Ɋ +G}R>qD%ceSHٝJl-sP2|Su3ePV=2""Btqq12 si1rqP2r:Յt͋/(^gKmV#V1Aɴ-;L\;?* < QsZGJ7e'ܼySQ #JomyF#UZ*b8_.VۖRTT+dR7 va=Ruag ۾yf 6TL;tb0C~rrr$ s.i3(ܴFjgϞ-2|s?XlSy J=$nyصJҝTiӦu-jN6܉'^~e|ܹӧO':R.\r`裏*mu^{mĈ5ׯ۷S,-3gA }UF#Uv &L8QJ3(&f١y'xBnqՅ4b2fɧmW̠jQ^^8>hKݸfph?3L{Hбk; ;?*7o^YӺ^'Z'<<\+,ܥKꥒmyjtΟ?}o999G>|رcss G=mڴW=z^dcy饗 """"jjjnܸ!2j;ߡ0J1c<ǽ"I޽4u/*@EĩS(1cԍ[cuJ#MYCYLessq%_2n2)t2ś4m\z} ~ 'cǎ&)ʦd)Χ=^<WUUiFΟPk$;*G@h֬YQQCJӼӧ!!!^8ΥKFGGˢo߾/g}&IpppxxxnݔlJύ&)i?t0Mrs왙p3r111'O}&'+A?ӬwzJfVTK{}t{ؔ;>={N6M6{%V퇡yU6%Ou>u r78'''))u鉎;k$d7lVn/X ::l6nٲEcɒN<c&)))Ǿ ߟ2e$l۷o?XC}ZtڵC LxQFF2;wTVV1..N"i rˊ+&\|YzwJ7²/Sr89eee3JHHm8`2ڵk۫ԵnIc+[?^ϔѣ|w8`2;QPP7ͤbbb.[Kbp@l޼Y~-++bfV%ಕ`dd$@zI&=-4"W^]nov %,,lȑ>N:1#qulٲJ7n\^^ڕ~ؚ˗K¨Q4~4h eZv;Ň~eCIpȐ!NL{ YYfEGG~п,;wX,OIIQgedXRݻ47n7OhxE”ȢEN8Q^^>oÇKZVVq8ڵ -[?s  ZrLC֪UVjΞ={$!""BDEEISSBFa*ݻ7(((**ݻ~-[Fʼ"n[!!!ܹS"W3f057nUVIݻw?3g|s&gK,ɓ'Մ={1BtE鵵JfedX|2֭`~ϕ2^zqnݒjU۷fEE)4nZҪ+WOMM{… rw hOp|JZVVn1zQ[[;qDefbb9\.륹zz `WEoNuu=#=4ij}뭷233nw^_;q… ;wҶm۩S^|wJ;v޽lWq1yРAO$$$xfQoZC!jjj6mԵkWY=z| ]~Y,N:eddjth] endstream endobj 147 0 obj << /Type /XObject /Subtype /Image /Width 1597 /Height 896 /BitsPerComponent 8 /ColorSpace /DeviceGray /Length 2798 /Filter /FlateDecode >> stream x1 /*$;

|1Yaʕ%B*11?0(RV^{޴H/ɣFH`V8C4BHtʇ' jg P5.ХU{CĈgi.BFG4RAzoC\ 3{)kN{iٞa*cȪ )bΊntpyS} dև䳫z^f:eyp՟g$ͷK"*gb뼗ҹ2^Dh ' Q2Sׅ>IPPN0=4T*ݫ%^s+Z0x]qEY kG$wF;x #v;x#SKb@V buڴ9<)3_#KT`1f^Dqm<|f]#Ҋ a*DGS$|1=6H֤ M >ۇMGyB多O6ğ лjd vYyC-yjZG 2 U=7R("Hk2^9֨#`B-{q e `”  B &yޏq&A.o .?+LLLncTOވXsd`oz?̈́*~0Ge˕\Ԥ~Ⱥ*%w5ɻDxQbjITI..ӭ:!$\Q?q%Ł0YUHOm?F͡Y,FnJو{ӆnT"[O~gKU0L OfU`L෣yqAཟK͞&:̝y RSчzvU~wzrKa47?>j#(5~>L*ފt?CCNGdʙU\-o;,1TtU5FqHQ[Vm/ۋ!4g̘F*\g@H KP T$v":[wEn*^S>cOTǎ0=q]cXH%5 JGɜ(0I*CÜ7}TJ{t4-WSصqTY#^'"2;z뽮wfS:,7; P̀h߬CNEXW{>u[&K%g =r^*\l{cBbd1ptXRF2rt}Y@搋6msO֩bzj\ToutTv&`sD"f pQHا/Z7nЙYd UM4HQ G_Ȝ)Ko|K>ߠE)L >7c?uʛ Vת؇̚d<,]рʠ4m5^;< D|?Yĉ:7' +MgE/_NO/\U.j~۵e BsSj}9cYțM*і;#Y,PT6+!zœgU+_YE77p A?Z(ڠ*O2{ &DnυJ88W[x ('¾USc);`/|zj}HdC"H> B`Hu$_䥷6z z57GV Kt1>y82H&o&ys]Tq=W!81s@iB!R}c@;ʟ!C`wd 'ʼ>l+r3V&y>DWj- Oi:K48HP裎qc0W~^/:ւsΪFMZ[9RGqh/K endstream endobj 193 0 obj << /Length1 721 /Length2 11635 /Length3 0 /Length 12238 /Filter /FlateDecode >> stream xmwcpݶul{;cIرmvl۶;Fvrs31f1ǜZvΪ, ,̼@qe9.Vn 3#3VٔajT1YY("v s g 1?A Ts[\]]\\]-Lf kSZB^ (ajkhh Tt1eAƦN4@3;G _!`j PNLUX\A^(&¤*45J-uv65vWw@Zֆk7oh2vlarHWC_)Z(ggbh T1d/B¶cw$r75Q9D5L=9SͿMw&v{69雨< WKCGI+=!m/gr03k=?Էov^ ,\@6n ;khj{"#. Lm-+)2P[b_A Xߨ!Moibkt8>ECo 'YoRsݏPcyk@E ̜?%,Qmh[q+w4zTHtUh3!FO;ayAH}0 PAz:1Y`jMv[pso0W, W`[sŐrw y 28v#G,rvyg"d>c[4M6չR^*YJe6C:A藟XhSx@LM.nqM) 31ͯP<b%e]6:NN>X*HI |ѳOJKk)5L&?;FЇ><}6K5l&kTZJ98b^].bܮ pnL |2zZFB"|)2ڀ/ NV3u#ɣC ?D+|R 9@kd'Ly љS&trpxair4Yrc*h.`rʼn!?}hBuB>VHK86Y@z[BEBlY5.5Va8p\`D 5#:('ɝcj ?YQg;A`*(OڢM(??&~zl!~^̗A_vG  '?@c 'bO oQhTH%+_{оkչ2cm^7I561/͞ЩKU$%] I8LwF?$>8Bә ֭ꜷq*TAH{jɵ.UoO퇃لK?).6\#MUCfߘlJEo@Acc:v3Y~k0ub t\jކ9>1w:e`fʊ0c.O?^z_EbMv&2{X-A#* ӅB\$__VO4T@Ŏl K k78%x<OPa;χ,ҡ/rZKCʖ114i/𣏕#'?6,8Iɶ8"_@wZZЕ,hml6_Ȼh5^ӍT6u_g5 Ũ{3M1hz>DQ<Y*R % }֞jaPhU,>WQ*.}ōprP?78JfUO@I Y|~[#x!`UMJ^a{j2R_%JͫwC|Ǥ){)u0h1a{?=PDg[LRW"=o,`nϓ!e/״8OǴsRVoIo,skG|~iI; =$tl҅OeT숹Est<(oST!)yr <|vTtǽO6ƽ]x3ӏ{E36eM|(6ܒ1i2m†d_"<(ijkPZ~EKFWF!f.||0Q ԏUؔ:ߓ w(c݂r \x_wz`_4'ksw=ziԫPT$`Dn֦w Rj0Ԙc%FcU1)J BS`pF(ڑc@ 4222n'[-ϛ+Hxi@QS2{ZwX?UKG?E5oq `V׍f o؀,(9~|X19s mCC4wO$6I&dQl6 M0]s(7 ]Ã{P/"Rh/ GBaǾnm3*SUbۀGSr;}%իɄYL1/<$&yd0If¿mzZW!MC, I~lƋKg|1(YkqK>MTP4IH@7N `EgvRZb^/gK;\B Ϧh{K1rQT7hBk*BН?xP[گE }>m0٦Ҫ0_DV|bD-8[ E9C8%ݜN¬XLZhC)=KyqpLCW#e= [.78H,}@:\mvz#ޚR"JjV(1" `{ PtOG-4?=`@( W!?8VܝCMy֢ȶݬhr:*Ӿ&mI8k3*9" %WhJbG-FKo\huר/g S$mX" ?yi ц/CtI=FI` u`o;pD:Ĩ6&L"MiܐLcg#"NY =e 0%|nNnY&iM!5w ~s'h;9Z-N^E/곚+sXX,ft`r [d6*P F|:Qacկ t&jZ2$pԢQ\wEbn+

B K۬5ga __v-0<p;+-K6T(䔵ٓ jo{1ԁ; 1QcBv%JN$:1@zבew0Bࡐ$Y@.l͝%-ךpW)tZnBRG^8oaϳBz=NcJ)h0!IXʗ+z3Ts[:9.EVC.[4±9 %N/T垸UqW[rה׹}A9E,S"+OBTӴU!Rʹ៟c5hͅ|KӭZ6SLFx_^ 8Qt'3.F'_n #Y&`KOG%tƒע39_Dqֵ}p zn%s# tڴ>O瑋6.klFr(Wc}]FOk!%

a`2_חB̰OˢotLTB|d<$4-{,n3#G\@)zl>2jU3jlsrK?3<HkO ڎC?#2V.YZדhăBAK ni*xFGGnZMSStàR~&Ѭ0Z&6-!4XؕbѰ_юNBU{~q`[dUM;vI ^Iڏ;X?ǖfy!)[P J+Ŀx@)уr}["G +>NlbPBf l:, .>C_xCBzw( ۖl0B,}sYdݺo@@X-Tbf+Z ~办G #vI7kWpBp߿wpO*)uK6׌md[k ;hxgjIe(7KZ K"˃k$MY|Hؘy8N[NDqF4J!$Ee<*JT> upy~љsb/=lu cOӫ+PSjHySG}P$t/X0mafԓHheTt6Rko<;9.aiv<(c,*cw]FDfNn1q+aL"%d-Kza`8":7xwN؇}_FZk%НN/>O8ti['pىvXKȦKG+^\1_>A#TuA2y9 ~19활Hp'ќDٖj7yHGn |jط!,X5Iw:/[`/~O%WHJZ{r,%J$ڜ$XYijk"t#GD瑖&'>|< nQw.b=[Qa9+s)6c TYJFkl7Oru#)޺O⿺TpƌJ ~i{@ N6i[& !Kڊ]gײJ: \<5~;:Ӂmww-^F|oy]̚}ɍ|g6X{!|{ՐwǺRMGY$Ii'Uޖl@0̔ ;I#LցkN%d"5d+'?^:81ж|OTB~ZOSPڤ:p $@ˊ0[S jYYyhCbGi2ot:^2N.n׋sz7X(M@I(dP+zqGe?&t7n_"<$-,R97jGdJ.87OD(T;LO:cgۥ8#9{dR ǖ#l _\ .9a 4__/fsdq԰v^86a& mƯrVKX<_Ayfʋ}7XAe5>k@s}6rG7niaW,>l }+uӬ7 U(;pDF[BAŃ`'r]b$myzU3R,^ԩ}yi"wĻC,]X⎅e/„ar<̴ݠK[Ռƪ+3GZǙn& ^_h|:G919ֶ<2 XZߞa3+zous_~PjxWvt>`H;O[Dn/=YQQO*7/HQڸ[} ޲5vrDVͺkGb ,5Zwp%委7L:ƋǕ\v0+%18'ʛ{%hL+J{àLK,w1poڎ}@W&غj-n2>tu8E;=A*xeF]Ǜ_g;ϩlg(YPըYG;xduE=jrjNs#‡]}cGF}F|L1.:.)^OfDz8g6r'(s9y;to(L̒)&αkRb!, iȒfxr:Ë<,m@4zHQB̴\r&ɹA% } `v3_w>Ll }0t3IEnES~_ل{uOgeiu3bA>U[;m  {h8KF&=4wTZ΁oV}+f WkSeZz ~?3~Wbh2|xb@:qF+_(fSVmvH>:8^n2ϊ#lFA߳s7st0}E)+zUuћ, ґb Hh@W 6mi̊A\]<) k%iaC/C;<ۖ }_`KݠPvb-U WIҟPWmyzH%e\y HϽl v*Jn00ؑMAn$)tnCƃw xr?#VhR(lr Eyt y"25|>dLfOЬ79cm=B`lDO@<<ZhxV2@ L(@ uyWf^\T઎`v郯 춘Py8ʌs7jfU{"Ia=p@=mEm md  | +ZY'!]֣;>%,JQP^Al?$Qki31e$|M?F4 JE'<|*`ܧxZׯ}f$Y+ݺ# =Sd:1={z 9ؠ,t7km "EժJtr>a1WqMĮ*or눽>)Γ#jTA!t !޼/JUD\jM{tVP8.513H~1)WKEhk=D>uoaSr&LRb&^e8ss; Jmn [X4_lI o)={6QWl"<ʒ-D},S&fa&y,fC)|qm#0k !㹣)  vR¾Cߴ' 4:ZX]i7io/8kXdQP#0y=5X}13_8gb`p)>utm' A.YCO4;#dO{ ,3])9GQd"c)$e޾nr̗M 3mFxXiJd8or*ֺj#E0w>Ng@`g>WԆ&=>;SP>v ٧n<Dab &zT#0dq"kވ djS|Xw/pnZ걺 J||K% Xf-@Gj#Q yӸН9mp mا 7 Tj3}"e/쨮Yl)gNQfx93z!9|BiqiAT?OGlZR0PfS'%h uY_Uhnlv}\pO6d?aWd6nhJh7.Q|e:t {u"?MR{Si L>(S^$D[8G~Q6s>${4XjE6m>g[eCG-Kgni:&B*Te%(hL<8a" ?/ SdU\/L(@ wă:?)&/,.g!s$c:Z832ו'-YJ7nq0% ]OIf*F9 U#uA?3`.F:(uSȁ`dinxV\ݽfq۟*%{R4a ÓK̊k eB(l=} QQUCKS^B}reb*Y ֙CAdrWg&{3 VA ՂJ8 R`~[8md2YJGqZ rCzD/o6Uv#`vUSRxѺ ۶,BauV)&4ۿI,%a+ک)@w[n ]<ޮ endstream endobj 195 0 obj << /Length1 726 /Length2 31284 /Length3 0 /Length 31823 /Filter /FlateDecode >> stream xlySn͒ml۶mWmmsm۶mrݿϹ}zw3!G.2"q{;UO=#7#!#=/22' P`Jp db&dfddEF(bdinBHiB !++??TB PDAQKJ^RB^P`p2!Tt54!49mۙZ'gs8CޖPNLUH\A^PLAUΔPVv.&.U-,XuEą`nit3'dwSr!?RA)Em\]Nr';B)*o ٙ#+=#SEK73G5ߛQ埾xs)_2hHg 373'TqGQ#'V4 2vǗ3rq a!a-A {xqұ032b_lM\v.RR4_+&IPQ gjhj,B o^A`oɰ , +µ٨$Ea(nQOm{ pzVN)Ӻoy<( O%__&|dݟ^}QSNyY/vD$W[mLPgMl5xue]@6EtNl/ڄ Ȝ7ԴyrJ.qx=oQOuO`|3[ٍo57?~oVhZ1B~Cl)֠|/9HҎ&4'[4bW/2x;7ZLpq3EĖb%R$tHOTo}o?x^MsN!y[%_H;Gj.Ioz'u͸7ת:i@d樌uc-AarGCX ?2^.wMiy"/xXNz[gP@/"Oie@ 2c/[LB4м_Zq4}C *gd܉:qX:"a"=B.:_ưق%6=pAkSi:~c6LX6"&Z^w(my)g "6ΦʫR鴁Y&vӗ*u6σMYii3{&lɺ=*;vI`6P:c^w>Ifhz2=HVrAMMQwWâ$s2Vx,)w>7z+Lc|;];%3h6q)OYfT}bh|uq8=JE_1;ax:e(p\8T5Zޭ@q%_ ږM^M^ H,eK`9Z1 4hR̯ȗ[gꌫ{?4B1Ei/4VQf9Ig&~IrQyAv~S ξ״T|-BB !w̎ޢZHj{8j-Vg-UG_9=3 1hï2.fi?_LIma\g#5L(/#8hq* (B(.t~.fk$aZaUpۿVDY*yez~+'4^ΚhL_< W˦lwkZ:d/b~˅äz aǠa9 :Q l'>~6BbOL-&rT\rշb)8 wARtߔGW7U[6+ h3'N2|͌5XkKc+h& 0XX1mz/V_u5é"r? $\1ܮ6ɼq:C8K//kh7 :2۰q5 C (3Ei 4biIJR1]h`bYg"0\;#%˲|nx ]¸'C^\vW%iO%\">|j >n̵VLW,W3} ~L8UĔ,9] E*a]~Ν(17t6J7t;,;d"=[{RpK$_A%Cnh@nq̌'PcΥ+li 2-˕v޶Yo[nOR$!Mɞ??ځd*S iYWYI=1Ԭ d5`.5Yq&OvUY_u0 xt/u!J΁%>1) 7?hn@BaI/>}R ƷK[=C.RbSVPZWK@}g!T+AMdԱTy]~3D$u| ۍJ?wy =Fl`ٛ^ L^ȝ9 ޘUs%|rzzi+<18䏇>}N ʋ]_;klxњ^9EK*=2? 6ӌm|L0rq5FNYgnܹLg*:CYڪ1\o%_ H+OR5QB~mT=8S/ b)'jLbbbgU8 t4<6լ];VK.ed t3].l40!s6 W;~r%}:pBhR>LBS=M⟶F8(LS ƣ[Ԋ[Zp]mlz0I"n3'ծ_-AA.j:mեSrAV*,9dVT[7>s1W]2^)D3P Hi4Nb'\"إ h ?ZF%+}o*Д/7ұ`/q=LTAТiM7x%OHX#Z:fomu=O ͂ >BX"X yU X1PZ\_wla5ۑulT&ĕQ>uv)pfZmE,`0de~8HC>2pK03GV:KLFױTĨ3Pyqڎh>n=`x. J̯FڕĽc&M*w,"` C0E*1m#, 6S*x.&~4ًf-?]FeOڃZydrg[nb+VuXx^9U(eJc@ uaڻAN?eqK^RG e]%XcF&>Ҍ>B;%"eRFmT V^n!5 |{P kB0Jcg:V>[O b"S9hWׯn["gv~Y/a?AFB3?*RKd"ֈ$9 }"`P&E߀hT8t/M uZ5LruSeRCc4[B!~ uiƕ?=v1%MXô^`Z3+eNVN"<-A~DOCs_.a+ji Hgb-sTd64A1܋)_PXs=+E!V^ՁN 8LeJ=UUgUe=y(jn>8 $募Y+mЁҩ4Xlo?L.¤խEQ}4QU_PZ)zrȐ͓/B>$׈7~ āI  F$i!(%#q? ɤ7w~TbTEAwҚ{`ٷ@'|;]R]E *G };:-#Af}Ճ_p 0+_ߑ 68䢠27lq. eo1x"A a"l=uNxZbuq8[VzO[wy6Uˡhie~_> Q=@FrL!MvZ:mp2)XU"ti7;7OExLj@|+q;({n$ٌ ?w0I{*„6Le'@%"J/Є]=e>-Xxb;Q3aYG6yPeO=4-m_晌>%iKvm~i"αC) c ]#р2g7y| ^b6B=խᝠ<1-tBuV#4|1/Boo4<A_~j>f }5"NޕG*Pr|T*B.X97zH[SaqBѲ u RY=OD \a7 @KF'n|9\;/fcWfHƖݟw8_U6F!ؠp<d)N0x5PE1YѓtU% rTK\$$jUPob?|4-( Y̙dnBd{%45{ ;ԛOv]/Yke/\ gb}TBptB#pobg*ut$ 5m*컵.т_F|Ch`V2 ÿ!o*9qT}2R~p(?6+OMtV}\<ꠏz]AEQL5 /E=&cURQQ.3Յ훎!{|E 2}(nJ85Yx㰡ll;eBV~+q܁F֝ ZN %̐ ӂK _v{?N0yCa!F݁Ww;3+CC\r0r0eA%<ap4zf> tY ~4 jt&d憰;AAJ)g1ctxdtL5fU葄${X,,"u KO9C(T({.:,coib[ՎKe\ {eFnفҍczjlf$5 )!uã1Ԗ5ЕՅE3:20nd'rH VOVxlJUi󊤀tM?8*64 .;CALX$JYv@s#[VfL(kKֳ9&F`xeX47mwOYhJ9P\#$6 CLFP*'f,RcU`j Ia9?5 xsetLHh` ulzo<>Q@nk.J|;s'PZb̭kѵ{Unfa#:zeL;#N\SE?sJR(XYdI.H*:Rt&@.PJKCxTQ,j%3t.S ΂ 7/2Jsgn6|qppD"\ "lq*HɵrkF8 n/;&Y)0b7!ȗ I](6Sܘ-Hnހ7Pȯ& sseP?ʻ_-]G4f;C*M0& n'x3?\PpA(쏱Pi$#:t9T` cu=.ym*e.݇s=zAd5GN-d+#UܜuQ" ?͘pb~>maRQ $NV'woCh*CVuѦ !(#zۣ5ł#`rVNpgȽv)0j"}k6rHhw P8ufZm͖+'/ʇkޟ-!K3>mH$6b'= ֛hՁɞ ?Yrk0tcnv i\[Hi]MS2hMu&|aڒgv5{'.Hۅܖ ba|*>kZrL;&Ŵ(qE-@y o8ޡͰ;1OGަ/ˌ}C$6q{YP s[X~-5\&`үg 5|~nx+:`z %Q "vD>6$ou$m:|[f!"-l -&i1̳49,5B7ɜNIiƸSp$@UBLC,t3] 8v/,̨#7J)!+9>2o4ABU g?!1m;_~d $?rȲE@F GܮG.lƇRHԥMPO zO9w”t:}4v:+aG't(20 j4 g4<Xِ]psh[jkn6kռ % )h.F,>Di 2}$Q .Qy͘æؔ8eb]wULtЬ[{4 >|'?= 'R D*#\{HpݟOpMlt2kPt%j:{`סCƒbAlf|6=Ǡ0Lz;=WCIN~4F;؉A0϶`hen Jր_P̳Ԟh'O }z[gp2|ɀsD5 ѕ_!epi$/Nu1 CpY8#^ܦ69s7+#AD4)a,P7'ؗ6Ѐl3!Oge$a #i.ke}>%<s!3wչJB1c5iq ';EE':VP|Zp/sLxW~_Nbڼpo-y,px?  ir:nG-*;}(Ue54{/K!Q@u j@I3i9wa-~YK๲;|_67̩ ֋B.}QE-PL!^eZM?I~sUYPQ'ʈzF:w_K\v]Rht6a>E_/EUV6fEC#%LYNpjSۅ-p}0Y=k| Q9 YK;_DPHOBݨj?}|], > ْM0SJjWowCFȩ`jBJ=ryUj<àз.BZ+DX 1dḴްm4Ї}`_P^~G,YTKQ/Lk+U $$Q(Y&vp徙wzȞkeJSS/"?N~9!w`澧,+\hϽ*`W4R1'>͔yle 0tx &$7FIۍow)*T%JғtI#ȯljjғ_=z Y䖫Tj&UX/n]NO4KēC@Ld\B'έtQ= O+.53?"2sEoV`vuWI(.RƸjaJ<׽kGU*t^˳,/'3*h}SuU"#!ne-ǚLj8}IRq: Gf2E*W :iWSpV=c#xhPcx{.X"$̈%2E(^,NB69TW3z _\iTw8eͯXͱ[SyBA`dV_di0[0Bn:嫿"3 A"DPeӽZ1.yp}gxJ }|f1̣AY/:^' Jp_ |,yne5ӹ7g8`:e;k[pm}H Kޞgcj! ݡ\S?5\<>&ke2c 44ndhJR)]^ $B$tGOVoRp8kKB.g ŠX1}N㝀|՝TQݘ;;dMg&{q quc$c/hqmE,;Tf!d@_H*Nx np̌E3.]q/# ٓUL۝͓$[vG_d PJ|Is}`nW{iN jML FP00[GHt-DOJbpf`FNp' <ܾs}_OΘt)Jѣ9٨=vMmobvm2oK]2Mx,w#<:\SMy|-ϼGf=ƮJ#NX ]2eiȰ[z^ݭl61Bg~jë!RbJ Ma߿VN㠤*e[ĊfA|@,ș"VA)cQ_7-ժ@9o37l>R ,fq$|#*S==NjO?(e'~Aw(VŸ;wWЪ9{ }'%e&7+?&m9W˦_3"N5 L".`ʜYsU8yڇ!3}D%Nv`E g1lu*؜i /9wm.I1"QOJNdT3Lºt~3ANgAVIyqPLK= ۃ.MĎe5<ƛ:`Fͪqmޖ:] #FŻoӬ\sp#x@LMmD6ɬ@{30DGZzd@&Ȫ`ʪHJXLAAru8:7Wzce1:TYnH ϙP6 3ldƔ7Z"QveTܯ.`qWbH!^ g-;gxQo49R-Lٗljɍ5:w 8+Z1ƞ0q*C\J2Nɓ[e Mo;TEX`J<͸&_fP#/ #9[P0jŭl"ΡM~T DMQ:0譕}8\d3uK UnHOu1~UY#KDr-{<wm|ŀ{lKQ{ՁyvFޮrN{t)?OU+;bD#L۹ ZFnXalg͈(MhU'CsbFu], ~ڼaգn;GXqwrcJ5դK%._qJԆ{ ^x!q"%) ߥO]w⭇+a-ԒUC,K~= =:%w9DN D ЧT$j*Z_%; yh&J9\7h;>{SI.UaF&%&~n?g/4 ϛ9tз`c oi~yŷV]cJR 4$Y4%Qɣ)RFƚFe5jR9|pz5itr$ '$c?p6vD+vaN+Ed3ZVYxr1|Z&FDxX:sF7߷NCG_k禔ӎnudi!p^\ճ+ 'YcuWIz)x xo_wuaI/jwtZ5Qfӭ7QUyhr-bd>;6@2FXA>obSC `9?{}r ր~"ƃnb];a[.Yл~22XK(n J8Q#]ZZؗۍppʬ@FŶ8|G&"*`fQx*Īs6ɧ!M^ʃ |,Gep˨OB5wh^++DҨ@W4c)6D]-)Q2N hR6'oNgyܳ"kt֤T(p zۏ 8-bFZ4A\ƦR8Qtf!8Dp D}3Ű mq'GCUٽm 4zLVlM"c{MrTC@[B ;Hϗ[SER|=`M[.nf5  <8}J0m`as1QFOIO{()hi}gks> m"U14~臯RB,gNk-jswJ2B;Q1ZiyibaLo>PnjPI{2h7s:NԼ|<^F |Gq%sMK ܀r늈 5x@wwÿkSM~ٳaQdX4ȸ Sk< 3b;^!eRJ%aFy]Ɲ0ٴGkM&HWo^v g5rlqTDp,oaH9}(jC+س&:;:׸EaeqGjr~:RzF7}yabb7ݥ-EZkV7s.̋tD,rtWftն]Oj}(u,۽tT?(; &I k xc֪n6,pG.Yj3s-2eOJF Md@^@Z}݉SR,:ͷsx֍IS̫R]!7ڜ 'uMCx}7WFq(^7ed0L`dg6{Qv1I}ХɯH%e̿}fp߲Q.|n" B#ojJAtB!4DZ: "z'  cd{˧~ IiqŃ:3aQܰ\RD BՈF<)QԳ2]69^QՈ1'_ /H.?isˡ/E ?='mg}x ]FŅVzJHU!jc%B3(8f5&5r gвj@imsX@`۶m۶m۶mm۶m6wQu|!ʲC& ,:C=R3hK2uѷ]Eù&˾30ΓozJRT4"5xќPY3MO!I3&@toK"^5BR"qu8Pȏ`1Cqef#CyBG`Gsp+P^̆m•"jURy$2* |-ÝyRXFK[b`ys56K4g9Xz߾⸔: _*Q{TK̅ҭSٞ {vȻIv>嶓e衒9~ eaڶ:X!FF=ŷW~!OE6jV;VUn4/!ҏ" \=ެF4$X}*CE4{N>(HGz:çË*^Z2~C& D|?٦Ae hb~~ tՈhY#!i^@N^#gRŌ4Fd z (R@ѵݽ L->*7+z>W??:'§E* p vT ٶsMvYP22YZ87-.IsnjR(G#KnY0.n-oan3 [lKo']!8Γi=Ί&ܪP}vuן h&lZ)zH ƄeKi6=0KR"eh(nX@ $g:t};%yQw̗ VP4 =^sJvx>J1b'~,QqENQJIL}݁2 Q{_w>>Рtz"1ͤp3+_A..74ܗ4D3eדtڦJ"yTcKbաL{Ŗv~ Trҟn|6m$eu& lV@^{^d <fuZpҴ稭 y-&u&+@qut";?0 ;v~aLUVdb$xDm9zUV8dok5Ngݔup;ϢY rj"geuCtRAjRy v"/#Sϸl/ 'K%%k()X*k#n!$QߴAs]"KRo6j4SC\bB4SFCX+zsFYjSBhӿ{+84+|u{eےځ@[e|C @fdK-X ]wS҇ 0 U75P,VF2[m2_۱C)P^ȴ/j S^{"j%08;R>=OC.(^ FS$ַilO]}]Ϗ:CcnOF,v\~q^7[Try8z{?K_PK&1[i"06ܷb{sͳO@)usYJ;CK&J!U |Ϻn87n/W#P(m9/C=b EzF4'Ԟe F&st زrjSEqB m8Luf<@+==svs25ưrq])PPr˰$=Id.FBJ&zyp`:#f _֩x@p>Ŷ<|/>0oIh5PY% b"ԫDgt&{hx::Jn1u#;ٜ 7r-ۃF: @4> '2J2[=kux7חWmt1oB]siƯ'aVTL ky9x)rD xIbC,0iYG&-'x)+6 E%]pC]% !`([f49uv/Ͳ(O̦+D؄Ķ27+ *qEQ mOj0EpS0)ށ ~́JgJs Xh$!H]O7e{Q"N9 3V.1~-]h*RHq(D9R0C{:֤fK$3~J :z9s XH>kip /Q-hQI&##//TI_?nihy@ݺThZpҩ2Ml~%]h ӯzыjv. `SkWiw6AybmZAZy) Wz!Q"qiqQ?t-*ܩc4pHurp%j{S][B$6UzJ! Kb-8[h+jNu0 >^Zga~Le]Z]9N9+q%9LmL:yR 7nܴ397Kʡ}UvQ}LbG(\#fUv$ +N?OjuA'@$ؕ/dK9 !J{ NQ}(j 2ى$ļC}OɁp'ҰkfP%M=^7L7EOX N^Y;XLш&${B8_q[e'N0gDf lzʗj +34''C}9k4z`O1Hwb:'#{: 6lLsK_{$ #LBO PurxfZ@&_,pJ>#QěcO-vEy("HqԌM& /C$9 }3~1cap,Tf%-.BdK'aomI &UTݍeXR;:L=y@%mA/T [qO 3Wܐodx-Gp>氷xʣ%AߵVsJ["P$]Y>6$GT4o>bR//~fMJA*J╪wW6pHz6`W^; zՀan5ic)IgܫgvDM|̓Y lbyA+e:VnsS8%.3Rd Kٟè+cPBGC %;0 ArUZvmx}j<׬1xW`懻Ů)NA5Y(/Pc-B۶beT. $P\8?"'}&_<ٶ:)#BW *~*QB$SR 'M46B8kt]YH$ow>h&L#߈K!ZΛ(v{;; dhQ Qx֨y3*]vrgF_ӦG*BѲᅪziS&LtsS.74 +Mk([X+Vghp[ј+&9,0cȒ:E[~z"@BW>`9q?~?ւrfz(PBciPx~iuAÚOQ&d*(;q43K#,v}{~to/S=d&:mF1A7Ys'%r'C ;VC*K@vuRs7xT׵rsp:UcMΩ;3ayC>1u\*"9א({#paI^^ ѠI`4F][CR@?^T^RVt dnb E;f&qXVY)g` ,oe8.`r3. 68aF ,Iɍ3 8H;YY*3 ̶朒 'X/ڃ"Jceo!{ S/SNe͘C5VTN8 P<* @:6}rQ%?;I]0]j=OdM9ГIs%hJۨQ$Kz)0q#5;kz1ϡV^/|ٮ;"ΟE~F(@aᖖ汚D$dJcIܞKMûȗkJO#wqb$w?bl-#KOA>>OG3x  /[v%.JlJ֚/Zbiuv{mO['O' 5heIR*@XgUecx ejd;=35sCm:GZ6؄؄8wYSr.2txpCoDOxoUR1bU^Q(owEX,Vز7-duA(g sTH`h&( v1s=Hfҟ E[I[phӣ! 뇦Ϸ5^I Hl独1 nN~,:8y&1\RrKw`A)/Dh=&ߕ'5q*tfZL9D[4?Fr#eь %0zwX*z<SX 'Ms y4U R4 tf,$Fn2ߵlEhx4S ^b^ֲxDU1HPp#7aJyLЋ}$:f{ɖճBHbY00č  >:Is`(:DI# T<.s{^M,y_*6A.sgnpnEyVn&4s: i5^Ez/ {^~$EkCц >$Tp:/@z bGN_4tGNŌw5n"zqe6I̊%)ywtTCE"4aL)k*2Ե5\,’-e&-u-ʭfe(-T:Sz}Vg.`|;0SjxwS؊mOǃ,yO$=NlTmM%̴D.la6QZ}s;?Qȯv/A $pNb.ϸ/}z˒53 kV}?n#w^&u\X\#@4tWVݽiR+ۘnOd;<1BkSrz6xY=TcwlQaGVVN])w$rBg@&/EVIM*b_Կݴ[vMT\'ZnSnXxAlӇT6 ?0fuom-}v:Ҁu_٤VQ^@hD>'r MU vgnsE)n',r=ETfo^u{G<mvI /}g{ VÝθ8Y}m!N P _ `NQ*kmK?M4Iϭmto9fd:L4r23s&o=5-ԨAݚ"W7Cۙ5톸s|cNչb1mh}TH>݉eU8*2=JûhW;>>X|j5(~g5ܦPK-߮>sYJb[cEZo.㳫U^TML,G}^ uT"G2ßV)]Ϻoafg2"eWmcu*E P]RS掻WIf}T9Au7E_0׭ VIGJtc0)W(;(ޮex<*7p؍/Od+Z:Yg [&Unn/ڛYj zʥgd: >yRx/6U} ö"=39]:Ͷ$@(vLf*bXjY& zp/4l§>>[+3v2W'iY @%&og=7`4Se\<ܔY`.0rH x|+,It~beLY^I8V-NaYׅ":vpDICyS{`T,6PGPloMQTS{5>5aϸ2)Daws(rhjeBU](.fE$X1m御Bo)n#Jaef<`v<%ct[#.%fu7 dLU;+i 'g2F m(mP#2NV=wN- 8(Ϥ%A?FN?|v$%5L}Ap?׻*A Y8M&>ת:= <њ3{[D=KP#޳J,q@7ξgP-c * 8˴fgt>R6<&*)4JYh [8OX /QN&yrvdIFbiN{(JY:}X'-YtaBBvфwyW?Jh&~̚!mEL]o6Iޫ^W;/kr&s}3N>(e[: {#C%Sqc M`Eo:Ft?uξ< -C˺ QVIjGf:y!эJBXz= ~ԗ=c!-m3vxm#ЈmU4r_0{%PiɅ&dT] آџ!LvrǰJ2D%DZ PvBBJv EPZ~=JH]lis*FߤBeG]}>hJX&{Lt^j t)a=r1ZNmAyce9`:R@xEL{HWlS¦$ZjnXQрúRbZFD Yy g{ ň a]K)+ahm՟4wX (Y<`܇JfT pVW~ ].`#O@S-[ձ:A+E1;&l,(7V)rm5]Ѹx*/m{MrkD ݞ ɉ477Xi<@%t&,tl̎*xYNn x*远&$U^ࣦ|׀4 rU$h\|U "D{hu"wTbV֖7KB3;'_5{6V\P},]Ķ+ 2K&dy?ZPK,T(O~~PM.{X,&) yqѼ ޅ\7:o;`/ׯENu7Wq4=fk+G*=u^> '+zn e#O6HxK 03bzlF y-_\luHxbSQ?A7$5}zޑ{nIba 쉶i~PPnHApKf[&ɅE Xs"h.4MpZl6gva1\ѽh!ׄ*aʐ_sO}5z$ȨU vi[6/rɽEbh"29c=nji-hmW&{Ho՗]76ӴGE 1?+ A; 8qfTS+G7>:Hց-tU5]>7֌o Vu8Z`\PI%)#.Ʈa(+x =@ƪjIt2LУUZ4Pܡ.f *"doC9)>^pJ5xB܎rQ!֪iQ>f ^XdSG;Kuߦ,@j%IyQ⮿~Ŭ#G+kWgp m.x># q ^n)o6_jTOI5Wߓ ǺVdj7CL^j`tPf 3tyDc\VFڅHtS<]zDe8rWT᪇[{$lʇw!ÑV4AOCa la,l-#?-M1nަI mGr-fCrG,xv ͳ;\Sh-sXlBM:L@zGy (i&WKzb=vLM^.jѮą`Na_3*$L(HoJ\ek NBi4[V_0]0+$3wݧ[+ky喑T_c큿!q/Jj<$zhxe[7Ms!Ranr(Tx5W9 BF&p5<o2ʕx9RUS/ő!fl r-q1Z 3 D0sO'jG b|EF=$֏F"հ֋" c&#Hb]Qu(4ZS2G ƏlT Q&@_+$'J͙cG Z vGJ3\:@\2[ʭ fqQ5[bPU`|Y}EyY;ߙ3ʆYoP|S By/%̝d:OVҧz-PZocKA!^*,>H'{P;[Ep[GL/~ H6^ԲQ}_Ũj &{ڹ;1֎fG|G@(D&C/!WQ^t&h۠ۊO;њ "Q)vJA婬<@T#q;IIאU87wH4E`/zYl_RAEٴai?we:n6 yXaufy&MFwr-i*`ҟvи~}1_rdߪI]ՆB'T y n]ε5X^"ԑv;nrtV>FеVNQoe76 K vQLY&F <%.Ζ\vrG_0ex 3l%`N /wrdOeN-,J#P\gakJ<dR6y#3n!5D9 zc%.pR#xw.-jU;j81 v%s4f 5?\,P lqV[pq[Yɝm3)bJ|^# m6zDWYӭ6b9`a:ÿ`a^VběѰiO*^GXmn"0]H)ӹ 59+8o0[tic)3#G&ՔJeƇS_~zˡp0kjOrCb" 1@ǠƟFy+ (0Yl7{6'ӲQ< "yi27`VYp~>_ͨTʂ40xg7>]H́dD쉐lu$}rv#(V:>ŒRm3 pNv„єܟe) C aETQn NϠD+Ei2P,N=5C /3<%N#1Ç'ɓnT_ eɽ?K endstream endobj 197 0 obj << /Length1 725 /Length2 33859 /Length3 0 /Length 34413 /Filter /FlateDecode >> stream xlcp߲>NĶmv6'mĶLg/UkuuWɈ\T=LtLqUU&F.6#= ,N T&f3##,@@iBo#@ nocfibusstsvwr p,mE-)y @ht2(Xd-Mv@*? _ 03'{[*@LAU`dg 縝3?@eG p_% `ji0[27);3{̦u|8v7(Em\]N9{S_ܻ;YcooDHC?1d,n4Uto'W?ǁpϫxύ4E$i373çV4O+ t9#'K#J_%%,lM cag018Y}\W''˿I'.& hlo*%OhfnPf teFr ^'6ИorG7Qxr*(\o組ܯvMoC5:ȟ7 r Pً2Ujq[O|n/~3.3zĈaGmse\d7'6W5P+, 61"\;9c +p0`/0 ;9 ;mkN`yy$d3gH@\θGpuvfOdlbJZa?W5k c[EP@H8<~LemhzbW%5j$j@M" [qt}uL @-](Z3Ze3Q>V@,㞃8öq`6mZ kEY`g- i2R'7B+h0W,j<Տu&!(6oUP )թ{Л.X.pRQ* ٴ& `q$^zA[mgo4#L>ӳB€C!mY*THPM`+DOaaڃF)0TRf۲sssFsvpt<,ڋs )DyU1"rp`GgGOD]H`"PPxOBZ;[wkX-xҫSQ8"؝D9XۃT{{5\/5]FX=bEҀB<y0 J(&Y_Kմf|$N6"7nŶc@A7NȬTwT튣C l1'1{yI,WT.\jNoD.;gswV^h{mSAa_/<3}q_ҩ0?ݧ5 W40<@@`cC׫L˪ O ,DZ6(kt<>KdG'#( 4w8X"zhW?xx ?~`H3>3J&qrO5Gs=8ѷ.5ޣL.IW%[ٌE3f-' YYLYu1Ͷ D2uNv6FX:S:cP4Qѩ^pwfn 47F@􅐌9`O.AJ-G ۷*Mz d#Y_w`cCڃI.{2K9/:AZoN3/0<<6|T\8'{/Z_48A3*KN1=bFLr?p7䷿YƦBY:3UpwT͗7 . 9@G/$2N/;( w=lRw`GJ,zhSz` {NNOEAԯw}L\͸AF7*e?]J{;Qa'uO[DO:aMyfp;?1gߜ(1Ff*GlNJIdxw+ ?e6u<=*vl͗fM-9v ؟ jВ&/]O,$Q_&bK)p5k z{0 6On \ޭe8wJV>_'ˇ/]5 I?Z *Փu62ݽma]kF fKfxv@3 ?"q0!YM/eO'$hcvݦ"كjK aWQR ^=l3` :ф'GHtl ez3t#ۦhss<^⍴B0R+c&͛w]X $ʇ.6ԌQxiD5yl+ic<4WL!=U{^M^VbӋPFV9;NZR*ЎsݰVOI:ٸc,A_l|]}=lٻGWZ+3Dz6xXz͉9!wMrXO:ڣW2ZSƃ}TmHmg'0)ԯalE^,wC@DB!7oONf@nŇf!8y/ύ1֏ZJw1R0tP ߳9R.x(&ar+IAsZǨJfWY@yEWCV> A?틎TH rn Rfn\6^װaEMcЉ_/18w &&1Q3_E>,H~7mx o7 L$f2*i˚T5Oxꗹ*#Ԕ)q~-d3E\sT/Ur@.) # Լs^H=hgyO+T{, (IzSyN| sWލΰe*x^#kxDnu>z+gtu.0_ٻ<cccD|(K(*~¢ʳlzhsO{c e.xYR|Q 2C@3uغ+0c*N0k:f#)bU<"45%\[&ryaХIfyO<&VtʌR֭A9O*/y*c?Ҋ/=[~;hN r2ӣ *RsyZVXt0ucTڧ-lVI(ϲƕiw/+?`;̧ґvu@bNotU:%߮9>|"dSvPţl-:}d m1H^\۟OM{EYUSJi4t8 H-7Z'j}s wr9j{AA|([.lfd7[OUU"=Дe8!5t(8t`#"_A`p k؉5Kk xew\R%Keh.L5>t&dcXOӕρd!I|G`{~ ~a 9D,~}hPQ5B#g>j 5=:.@nSAP?q7+(Ηø |M8ɬ)|uwZ_{lcJt@Ku5EV0 )v%f,mi7Sᝒל_+L&vx-fph4~ӾnrQT8s\Y?`b)=Mz{F b2zK.~YK9]c^\Ұ.(j`mop?:'[M%vѷ&*r_H,g,qt5 !|ZgZШjDg>K` P;k/Cf\Epr .I$ u5Ht i,\{15!ɶ&P+eO0i}KÙh&VWsbl4PiSc$yxɀY*v͡}N5' }qj j_j/#]uhE!#j{>݄DIrȞq`G6U/-X^kQoȣ;?fa^ka [&$01v.@f5#?JNVJ֪b{_*,<(mQ ohzDC{Cg8d4+hk`KBNF|iܦzo׭1ja%?Ma(Rm-o[2WdFcmKNChL_Wl&tTOZ1WPnevIFQ1K==bZDklr*籏&4A<hYcEY U+:DK y|g44&>!nfi:E|xյym91ZЦօDG<'mBZp1NJA4V7ljs6ҙL)[1go+`1u1W=7F=|i-C65U{&FX¸e| 6C01vXP17[\նnQ>(RrKdf*s ({n W:SC^$܂ζ {Zn>FCax@qMt6X KnRSM㰭 n:1vAQUu0̬,䒗!slɶ|YhVbI򗚻yIj* m󪯟6e-h$##޳R.8FO]UfLJcBòhpÝjjS8e)LHvSsu-9՗nO9 $PQixX0Q;9Uf0)t~K(jzOZLs ,`9ol#K0Q% cl1nꂯaX(p{Ị F{ ȋ'`QZ*4f/dH1+2jn:e%Fl ^lH6S~\#,̈]Zp->oMe'ӢcQ+\cx}Ut꺍OR@\vwIPRN\^Eʸ6ŭFv f$~%lP̬L)®1S7e{IzJRzN|Y#ԅSK8~:y>m귨Kw^Pb/Y =g xKPl`UxrY0T5菝lx O(QڑKle>3ދ11_hx ̢:i}[;L.m:y#к)w>no?xOl*ΚF!Ep^CٌH#NлI>=tm$QJ}oATK,/5ILtwy7/%ibL47P}䐜Q"{No5/noepq<'hQXQS(o'ݔe]+_|/?-> [6(ujz'J ;ėն SS=$*Us~:尗30K5!Xg*YWG0 Ð8_Ae. 1i!I#wh9CKP ¤l"l)ǡ Ouxj;b_MpAd?S~0(k5.ݪ|92<޴ ˙*Pi7)g% -~Q*o p?$$':mk>ߜU >* wcAd_V*Gm9Z:X"řW@~sg{[J3˽@ .8WF̩陸 Yc*rz436NMPm91btcPm43.\ұuJ>ַ-_3O0?d ѧnW4P(8ZU'JD Cee *ő5nẽ A._,97rjXה"8 Vt'j[)1S0.U P5y|Kt0s,dzFI(!.,Uy姝DM=(L0[II!ޖB{2y pPey]Gkė#d7-# 1!rm 0FEGH5Ȉy9|嘲}v P ۋ\a !H11?uGTJ6#WkFiu $\UU\l UU9d}^i;'{_7]ID,9Wt poJgh֒;_0p]Koumrx.+D9{V 5j؈FMɩ N>̥u[nFJ*>65ʿN|#h!OP֘Dj wa23g&EV @м9:%6ϛ>Ň<e>/@%Kwp`j] -HP(Q/$--t-mj63MZ1]{&Ӊ  ٟ(^C{|o'R*v_gsA5OZz4Eb7Ub:Dl0YOtDz8z6SMcטHtD;_-M;pTWJɣtKht-R#h IFyAd $A$ѫ׆`nsi>zZKuÙ9A=rA ONX _9!c@٧.=:N ^5%Ty{EX+a|"*,*sU>h1ażiES E.3d;lJ]g6{?oMj>F}Њ薎B 6 |5rӨӧ F+nc0uBRU`Jd S;~- R:Ox)ћY%?1zʧ`!Ѝùz}E"m'|2$SfBMG` @H^|aѾZ\1_8lg^5NEJVV @UPgp>=3l[?Ql”.wR݁qc*Ua.'?~PFҢ, އtCJI\N!Wf zyAVxÕǴ~wLZHwI7+ݛd|3 /֐OFDy?n:Љsz۠D#!g1ealAjŅF!9Ljm/f@WJ۽0\T"z/cO<bY^0bp S\Of_ %\W4 /zyb!ϘD,(8"_]񇊻?k=XEm!mSߘѷDYNћO^f ot/(;GcM]SEun/ݔz6wzd['aKaFޔWDZZ:< s]$%YKlK^?l{i)z&[rm Jr K9dKoW)e0ڶqLGhk2vjaN%dxid֕-o iT(n_~g~͘~(H/d(s:ppIri_۬eD75@+|:K?aJM?ݦGCG} (iW#TR5^O9xe;0F^ ʓ(*7Pfy"dɏ+0H\وf42\ ?:CJd|B2`T^Pu /)baA΂;)ήgn_[P<+&.ǓC4op;Yum'.y#gy ՘-\&q%R U7T`BJ5*Ѐ .-3$0x-FSDxY_-EĭRm $P Uh,!?s*#*1HMK +_ʮ]jRu,bwN7|Nڧ)`k(.%Ӟb>Q_{9A)Z@ נ DDl5'b?#t%]N(PjUSi^@>AP 7Fwl?_H͑ePD7͚cq{~Eݢ>"SBYe!ւk۪ U`ڝ_[5>;}!ǤvZZG׏LmN!anbr䉙|^P\manI6!g$Q8dGz](أfR`;`/XZ.p2iLkvר JnQȷ>=_6?.5LN3 '>y}/m67.._9 ]ﲻgUIߐ; -gF]Cn yl`WNpF\uڛQs.!=iA_Y7\JILo̱uDʳ/v>N!uz8Đ{A*{MFkC-:dܤ*\&/ = 3=m(6 7^pOW~&LrCԕ gu!\a( zt i«X)JJm:;OOWI'd_HE8#ZM]1]ꜟ'*-\B4:꺇q9,ՁG/udeZߛL ^$E7.Z| !U6E `M" I |oJnHX'rK1&&szf pIf^؍'$K.gN.zxؓb`, )SGwkMnS .a@;J _6diQ&GhPpul;teeⲼ{]}z J#F \5HWOY\!k6Ǐ E)dyz[ε,7Ǣstm%?JvEzu6k=8Ix_4ȢT3R4|:j7]ϊaxj9&UuE[nG)%&6JYKAϤKzrZXre%()|B%Fq헛eW1i'{t1۶s]Ѭs AzCExY)iLsuK՚!NQ=񤇤O)QV1&_ B B)Ot^P_dYV&׻L1C6:ўWy6sE`:hj,EP l; $Ťgzh՝X[1K%lKB y*<B3ٮL:Ev'0$& N~.(P3p5jrjf7mCY|d_׮f]FH7WݳL&߭QxL(ݥT}y6L"qw& N{Ç%;o@R3EH"_{<fl Ds]Lҟ~ YcM'wHX6GJ/*u-Ҥkև8T:s,gbv!Upn< 3JBx`]30Ͽ&8z8Gm4H;}]dhZw!.)ƦYWԤt-;VPfBhMkc0ǟ5wQoUU=W㖾)A:FƷׅ'oc>InQ>ey-1r /0RG<2-]EF*+-R,#[px ļL~q:{FT[غ8vǙRk@;>8 G {闬8_aMʷ X­ĆG`+[E pjM,YĽ8ti72kHezMP+58"*qwZKw^g3:߹q޻DmE}(ftUϡD KxF_5.}($. {54#2 '.ݚa%%c3* "d!-ٰ,ڷ2RGu oms#r]]ۢ=$%־j|ᘋ% [4MB9W l\cI9?.sSҊ=5OZeY:A6arT!J)6@V@S 9*!-EէFuGmJЯnH9:+[\ɊZ)N /@[S+#ZA~j)~}v|$.l9lb)8^:GqZ OH{Ala@Z'|[ )q .LgL )i(y(N0AoMۗzW,ق;Pb89yd6nՕ(a$U0k{DziҾ",^f,@$b小 t^Q-+OӬQ6X&.p ˚`#rcZ̨||0zGkz9AKVr%JTVW"`+)ܭ*oVB) ]7C^zHy ڬ[`fA`4 >~BUX ;otJsZӜ-)X6Bz q: \Cp#+b7}/H>4ZtxLv1ȏfo:tK{PIŪ{R\YAܻ. C?N0ܛ ^vWp/aBu\dIs&ڬ#Xp3ke`~T|`4E\[ͧX;4tzڜeN>z׉oH;FTipO.0鎼TJMёyb,rZ܋X<Ƞ^Osz>d_; <"25?`XR zzZD+xhf \;~FUO+$8T1q:nLdZJUKK8^{ ;ۚ&RW3$Cx5!c%pbt<fwVWa[܍^-\p(!@)1i8(9!|io'boS=~?x;Q ߅FKтmaV{ tؼ3{kqXD_](_XO"b{R)(tgE# C:k0]qXvpSkHGpUjT? */}_nSd(>h%͇dKyeRa`ogyݯ9%sPAMipAhPm_6)D569{aW^K\e!Jڂgc]gZJT'W oWt2".Ų6\-ӈm\:$vmWQ;~Vk*݌kR!=P2Z {Nwqv?P$ٍ)EDiJX4 *`O8~ Ij2  )Ts-G@*NhoV C&CA-׎@8M=qHwgO YҎ ׮ 6t卬QGHP>g>bz4hx ;7#Tɕe\buL;` /:BE=Fy~9aW͎<(c2|γa9Ā ؖ5ZmeK.Mr ӄ$0(ڛA1MpMp.}':TIgA`wi<Σ#JTž?SCW NhzS)4A&P{uT4 N̜fc^3eSSyQ5UH ^5'/-V~6ByX+ũٵ}Miт[5r[;Ȏ ~Exx12:ϣ{#1#_ƬI pM k/TMv0B=l$S3洨@/[U DCL2Bm:gbפbi֗ڭX>N. !. '}cb9TJ&y #ܻY&(QK>l4:-:<@REw.xݻV cVUJo]C`[QeY(thDZ Wy.ʇreE烏P^KL }Raĥ%J>Q![~n|Py( >_f][PNR\\ 8c j[ b^3DL1v#*'unkxUBĤuj>sE| .)&t +Ȱ qD*9YR Nby3Û2 `%_gK/6% S5)N>hg4"}P;d2.P4ŹkR^u0"Ţ];ъs ^;Xɯıɴ?E>W9WP~μt y߻]5 ~ż[u<ȜsۀRPz XَH >FM> žGds QK.a >/5K*u[eP!@eρv2 0\g>"n)徧f~v6J/\)Ţ׮Fc |oF #&Ը}wn75Ҥ.Ri?o!'6ꟓ438 U*O~bAbT%K4v z5w;th~M6v\{#JTž?SC=ƚށ`#gkQn}ތA۸a :U<=}xQ<oLš=9"ڨhB+`_iC4m8lK 5Cؼ!+|ãT7t9tL\ R!WZҍNC-sAcDMJ"x&/͗Fz7|3N;(##+.6dM:-rX!vCiؚ٩WMIˀaeNw'H%ꅣ%7@L-3F}.)t:aYL(Yqide?!HŰÛX@;hu:p>N)L{?!aHcgvi6$ JR!Z2b"MsȧDҎyɵ&ηÏM6d+AUF"R܋s@|U|GA/wԏ6v2thHSJ֛)X6KMV%~UJ |b}_:M2 {d5faw` um 82l:f\`#!{f G=*k eFAmi d}<aY爐*jƴ+</M!2l& Bnn6+sMALDF5 (oN#TsY3sr5;xc!L>=d?',h;fOGT8s)k8ۍZ[خ2nX3 B/CRNVDx&rzY@Esp5gP{1zDr)F["+U'B}4_x4)9-$'Io:Đ.-+hڪUFۻ΂4jW EB/b+!}pTmTD.e?WNw/;oj6K`B V8#+\%1ayBL=̾ϖH1srFb,e't\oѐPX9;Gm|bIS>%W-PT֨6(kb @TM{\wZc.R*˥6nOX>sU?x0 &Wͷ4N웑%g|}׵ O*ؑ``ln Ry~k + D͇iYOAoiͲ%ll)ʕ+Lj%`p߹=Ϥ8kL}[0TbyB'lNI3:ig U+OOW/!wn.ilDە/NO8epT%N `hYTeB@64;{͞x)‘LWZ.X3xy )/۟Nyѧ19>+kb.yjmK'E,N!e\Y[Mns+6&QHBv4גun}5*TD0 ֕x4%st]T9zuVK-H T1X"ʱ|L q0T RzJ::P%TFj VϞ_ CߎN+kyE)͟*ԧ|TEurddƊ |OWI+ !I"C7_=Is4+,W1xVP*_U<:M6q )z%Ej}#؝VZdK@Pyǂ85NUX3S҇ǭˡ l6j=;,[!ɩ$E5v^p#0xݨD7$)ĢgD~3 g 'Y z'ג- .5A˘}tV4>=*y̔*l7SjZȅ3 _B]֟> +CsKO1TIh6ӣ!pbED iPq5 ɫ*D-;9R%>V}.ah"Uwsyr2@ͅ:BZi\o&.تԠ)>7CKAW.X3EW+fd6dt`ݬjh~$|YffIU/ߏCAk[.=Zs/XH<О# 1 .gh#yD6vdI7UB?˟/uy(e~̾5zk/8ECGʏ0W%;N8.JBg螥C'rÄ#FQqa ĺ g'b3~^l>UC3i[ⲱfE+`Chj* я }!dB |[ 小gʩ1/<[<+*.]D{Q;5Beaހi9#փj [%*)BT.:;GKNAHo=-$v|u{gEO[r}7OzA@6#h14u9Jm"BsHMƟc#g2woxm'̷; 4۽|5W;0LɄAt@k{J={xK:T칎9r|PFu j.{MË;%D 웧7nd|\wmk^,I2?YqC撿t>GФaf]l 0ڳi+k_V(&ΨU[i&IѶlospjf tՊy\`R$^7ڭNהүJ`tpxȲ?G*{܇@JRݙ)Ma8? mIJ_fRR4+čDGB:15DH (h }>4 vDQs|ҭX;6!Kd:6G҉o,K(l,.5^kxoAl@O4AF/ 0@(3nF|ac—׼x7Ob/;'NrH%¥r SOU=e۬zBӌ_1튆f8lL ;Y%2]D24S:Nջb8S_7 .Щ?ct@і%K+0%KwN?l[.t{luq~-teR0 z{^@0Ld/!?,3Ti[@,PUMfA`rtiط^ׁ~jy;p̹Edq\3ߜj9d^oм*ƻFir?̻;+Ž[!\ ͤ#yz2`!(v7 ۽iqp@Z1`;hU$`+s0 _?SYD}W# n" 6ﴠyk'UyN[PfprA{.̛#t]65+ki>G&SV4 VH ݟ{L0vӂ/I|g(\oa=_Ǵ!h&E*FRg_] Ժ &vY\Z$|=Ao3j l4~L6!;]8VG(`& )8LOcgXP&Hᖼ>CIfVŚbMaN[fo `z {dafuiR/Ⱥi" -o ◬1r|gw[s۸7_Ri|kG ג r_km3sо=[Y)nCN58x4;|\MsIt.ЎFWG.[5 ֖6rk0tn&~6tCn7t@a\xO Վ:Zbn[xK/ |SLt&T^!:wSԣ4FUN=kōK7|9θ}٦`tHpBB=*;**Ä yb[ߊ@mT7:it}n~E.wICe^EB=H控r[lWp!q,!v_"z ܁|͌Ea 5 L%\2dsW%pLOD,E*dy8: +YU"r.d#xeA wʊ0W,q:P-tшBm8Z䊣-SVP""#7=8prVn@xgZiK BY #_;W?sW#f8J:HkPo<2,;v픹=?:dse+ /G\pvI'Z"a|L]wm0,:(9zy~vVfLwX'! :4AQmfZ\u-tx_e68յu'7^MWWd_IDiIë\P0$j3>c-S_4ŨKҾmuXew4Nsv2܁.L}IK]i‹MoYzG*ti;$͒ N,)~Q݋@d'$M1я" v3BcITSYS On4RjzaڀBtLc_P^Lsiar*J/Zv7';mY"zڠpjj`)KY . .dLkJl\&ⷻ ռ/QFP_4Pd}r9OwPl:8`B/_`D g0o^f~;r ,THR wr[D%!cy) ; _&Ϻ"z|:/P%~Z>q gg@%55ap4n0z~N.<THxA9gpXļyBRv*[RA+xl+,摭ܔNVPgP {$ 8~ޠ=x%NfadeYjP2aq^JP劧z<"(o",+CB{%ț g|unJ7=2# 6gl'4DZ.! 16̖+Q߂lTV M/}[.\xP!$TTɾݛ͋+fڼdzc4amD)nnj0rV0ru$"^ַa? 6&yXQ&[ߖC~ouVݯ,SOk7R֋bz6+_P<>W0vwId $ҭw)Ɇ*Xy8G|71%nl]~3nZ٩E!S,q)3D&OG ߖKlP'o zT%D{ezșYsN]Lad2c_ 蠿A;SDDNȜ* ;lӿ/^~ ʼ `ǖ r6+#;р3<{xV4'?̴:`D[PkK cSh\:UPgx|=vAP-6ƎG3!{kMV~_`u؝rlxyK41^݈qli~Vf!|YY ۝j8^idTEߜH7ltA՜Ձbp`7GTRʃl!=gQ, a$gD&PwD46-wM >zֻZA#v*ߡ)¥uĢ奄W>0=FhJ[mPtˤTt!摎Śx}ɭ;7ps;C<݂pf021"3^K$oCDj4H7 $4ów .r߁~?~9zd ecjcC6)iN*8 .rfw>Gf){d|%yTqlCvsQe&o/2Uo#Α,3xc9~^*T5oiG{ 'ܮ ;yÞH__|xrm>:0u%pWίsݣ;I'ݫM\ޙK)EMv"Mv7_yHnsQ-p@yi(K%62{_=Y_y 4MF.DXlCK[96g͗t&2y:NC uO'fUZ*-TsbXж`*>zu{@%XdС }n]6y6I~kLkacq,1ra,rjLU9nb`d&3RXlL65ׯbB|-t=]OS!Iy<ݜc^k/%~6Ƀ1 ZOkYK/=tǃ~\sWA!i!97t<'~`V*)}}4W۱48r 5!~ok;E@kN"I+MaWf*6oE(i =J$^i>1h馡d~=Ƒ&lnاFwZ)GBt sޕ|qiÕ۵`.Kȟ}yE&Hߝ{cyQ*- }@bQXˤIUUyڪZ2G"}\ɓjdcP4ǎiSaW)$FQM"I!F7@Dž<\vm 纉Ҽ.5QѪgg!azE&33 өY7%ImT!9XwVb )DZNJTyܯ%̻"s$ og˒N* 8[WtٓyYJO¦Al CC,-\a) jgM_]/a J4WW5YѧI04S堢~BL}k}{,E t1TNB 8֌w8aR_/_3C{LMh_DĜgQ98Z%.k|[C#򛈀ك$NC$J6([/[ 37֧HFʞs4@\:SO>A祝űj^@=HSD뱾k[*Ďi]HȦR>bjY`jE5ÀM2k.7:dLs6;4$ُŤ/&O*BpWB}7u[_}&UYvK'm5֥0r;INB  'Nn/. i[Fr p!ȅ̤ʴYHhN\H(4nk ఃRv#ccOD +,xkŰp 䦋GAbfAL˜Z<z'!F<;51fYG֊djHIĈw/m&pA E?sάGO?9qw.-ʥͷ;:7Y&|giGAXVA%x4پޥt\2w V=pgۧu0i>y.z/Yx`4UL ػ3rA4l|^qPi5Nwg2u>h| ZAdl;U³ߛt ֭_`VY6H2ްNK}T&mGb?'cǗ?vr) `XX([1_?@NhB6'PE(l˦+Rv0~졝 ue`;ZH  )N'>!g!|'&ԨlҴzPcX &9֣iv$9OD Dhz>/; o#fpKg@ M-=wc _.7g><(a Tp0QSpF1,2 i7k7 (_BPW9kam,?0ik|_<@gVgep&J O M Zɹ쪟-FxIU978Qb?]֞)`rW;]8Ti٣Hf-)/fLP-5qJ%'D :ïACC,%(`j7 Mk]`^Vk.ėn)GeŶB6RVZ_laq74RQX.*B/)wݽϻ/ Lo.,/IddSDm Kr_Ze_ޝ#op1FNy2͜}Tb2B&xbM ڄ?VJ]w>`5'$ߊB ё qnՠrMahxhkWYaa]<Sq!^_^~gο[.?}CYP1R$^KGVqܲ'Y]%*^|MKL7ώpm¹cs9춹 d [窙Cę Gn8KeXZ͗$kAoC]QFpx i| `T3 en~`9tV¿)B)B5·x|fVRŽoM;up-Mz{AB<UrB^oo5$h5NW,L'{K/=!t  'V6b-8h'#¸neBX0&qALzl7>EhqT.AsYr93_pqGYqa_lwʋ-ޟRz`J7wfnW8.H"=ƺIS q57$F&K~y.2ɉg֖Mr/'n 3W-{K+գ4\fCFq.ACX cwn:c657i'xZ DL=uԾqSs{_R"-dnh*rt P}τV-ϭLrb#X;IKQjܫK%@[!-!жc +Do>6CGkܩ q챉竔$%svHq&̵ C|ZT۳;aJqPc?"D&f' ekUW)p' P$(f -65j=K Ҳw4`@1f*[D֧8YF{li` FmcF\ gy\rY[[ULjK]|DbO8cu*6LSV ᛙJ0RErS}3+6Rh޺,pފrRAUBH¢/ڳf'G23UXYoo.EQ^.lꭿ;YpB /B&v٧mJ U? hHQ9~s]DVh 'x+(ixެgԞrG1/kWHiF"_Kz5%|| \"ל6T E#11#gUס$_zBR!:sLfRەԺW;_Aɝ-+;0z b@EVِgFBU&< Ul?x2д@bECzSX7D:xXc MoKa띌'EMhOB] H6qӪY_}= >EmuRo*"9-S UlLcOhdNA<5n3Ķގ`[' ;!2t(Ĩjrf1.4UIF(&,l~aKr#h¸D,~] 38tS CSW7_s='}Vޚ:mU:N"' 0kRaz8wNK S_njn $ zZ| e0 F)Fht oVCt `B*I[=$ve8sDco1 P3t (AU_-`T {*SA{Wݎ]J۷C1VB*'Ϲ*Z%4±ۄ? ,3H *Į5ȑEJ1bry]?ĝU4ÂOBʂiڐJ:!DW{ Hk}RT ٫1O6V\;I[#2?w(XBX#h?ԥl]cU~iM҄ DXD2l {h+[l}o8"#ky֟'3.LNߡ7"I4/ЫQ0""Sݡ% y9ִ(Uy<0B$@=(omQ: 79f\pREs$hpC \2oaE E/kOk2p:q+-}U?c ,j1 ?IO&I#2 endstream endobj 218 0 obj << /Author(\376\377\000M\000.\000\040\000S\000c\000o\000t\000\040\000B\000r\000e\000i\000t\000e\000n\000f\000e\000l\000d\000,\000\040\000T\000h\000e\000\040\000H\000D\000F\000\040\000G\000r\000o\000u\000p\000,\000\040\000b\000r\000t\000n\000f\000l\000d\000@\000h\000d\000f\000g\000r\000o\000u\000p\000.\000o\000r\000g)/Title(\376\377\000P\000a\000r\000a\000l\000l\000e\000l\000\040\000a\000n\000d\000\040\000L\000a\000r\000g\000e\000-\000s\000c\000a\000l\000e\000\040\000S\000i\000m\000u\000l\000a\000t\000i\000o\000n\000\040\000E\000n\000h\000a\000n\000c\000e\000m\000e\000n\000t\000s\000\040\000t\000o\000\040\000C\000G\000N\000S)/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.15)/Keywords() /CreationDate (D:20150923120222-05'00') /ModDate (D:20150923120222-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014) kpathsea version 6.2.0) >> endobj 148 0 obj << /Type /ObjStm /N 86 /First 776 /Length 4220 /Filter /FlateDecode >> stream x[Ys7~ׯc)s7PJV+PBR^{~ 1<iA htht7ȑV"Fau-dB+O%uB lĘ+O#BGG+{"D/$R̕.iR*Ȑ6| U,C*և==@@<rH<IǽD0 Koq*{Krj zM)(^~iLj BݞJe4"0,щȊ :QB<&j8ԑ:ǠX` !! `!&hiZh Uc 36^@w唎10GJb^dz'IdSDРVO+G=( ߬e` @QXvZB$=VFKH(F4r:c&JED ~_|v}%|8]\ tUTGgqyξH@yNQc!RL:I*p{xk9UoËvMJB'z8Z4ھ"9PN=#tW+ΫDVRHs cP!T$.%R[:uMH3QrfSڈըUsUÙT3mPsjĝA>-OeJi&9Mqיb,a*Lרdn ՅiE{%YtBa=~ O4є=ںrP. sڠ cB$mVd~9J^jiMw` ӻmVVr9(θس+Eл(#n Y88LǥM˂D-W/I.^V5$nR"-t.GI |!t%AԮH %8Ӹ1 dKj=lZ(+O!(Kz{&@(7HRڷINj*ek8\g [Ηo8?%4gA %xHslUsIcuŭk=bA'z VMWm`zى6)-OaoQ@$'^sl,tKɔtv=}<%u̩y hI -܏8jH|Fz[O$%~(z*b4Ah>.SoNנ4oO2}ǿ&Ȍʗ o:fUWϭ&(fMy!{<_'ʓOQ~wD@JQKNp?,`|F!|MVW,&'wߞ x$z⁦ hTRXF}W?eg:~g*zShxrޔ~H`}G HIOfd2&p3=͟ y/vx]ϱGfW^}jزsOłn:O/?` V^ϖ 3R'3g(dyT_Vm泾)Yzq5;55hf9r|}vpknY ??M0yv hzxNp8֦ҍ[`Rdy;D:I-.<@9HO=8ƙm=8_xwr aC$4-%=oo/c=N7H{ۺ}-j.o㖌t4;O/dž^[k+ [.>klV&ɿӴH)7 6e:"\TڬT%WdCbr] VJ>T,Upocwŗ6u_lZ⽨QcfJ^F%z9oAo]Sz.f~# q"(HQ~77ķ׶}1WnI# I[yv .2t"{!G I&ULBglB;,+w3 3.=ME[m T? Ja`:k(ۉW=yjETe2RdÛg;emɴJCVH ٗ|̦\,1Ϧ\n_N9]^p8;-徰)Hw؛@%Ajx|9^-ر_* ̷@ + _<=>QID ju+v\ە̨jףܩ()M=eWL;4۔QJ'J "pd "pd MEVvٮ&ld&lT&lT&lT&lTZUf^jǵC1GhGhGhG@Pn^7r+jBGBG tt!tt %V=Vly\BW@%; Lb8DZߣHdV\qm((R$=msծPn| s@WZ-2mtXB&x[<Ƅ sM֭.l׆ekh9MEпD>\ð ] /Length 559 /Filter /FlateDecode >> stream x%ӹnSA9cK| 0K 1kN rAAqD J*JB$4t!ofmba lݰA~7uސ/]ZfG v1fȡȻDˮ[XxF8}5tTSUZރI r:Y?'$0p98"\W\0 7܆;0wB`g|agJ~jH:[+J_9}jN<\~Yw%˖@Ê%J4[|BkYZTRaN9}+}QjnO[?joM~+>z4`w-JCN5-}F,AiԲRղWߔh)-p}Q)SZNi:uJ)SZNi] +,_qc:!3x endstream endobj startxref 869452 %%EOF CGNS-3.4.0/release_docs/figs/000077500000000000000000000000001343724673500156465ustar00rootroot00000000000000CGNS-3.4.0/release_docs/figs/Bandwidth_cgns.png000066400000000000000000004356611343724673500213110ustar00rootroot00000000000000PNG  IHDRZRDuiCCPICC Profile(c``RH,(a``+) rwRR` \\À|/­+JI-N8;1V./){ll0{]t NO@wjB@6_/cJ~R$ (I(E% JUKQ0204a`;D@px2A!BlR?1^: Sbj  $Aad2f` ыI%LiTXtXML:com.adobe.xmp 1370 850 @IDATx|uBr4AO?= V,X^#N K$KH?Wg&M2| ;;{Vyy @@@@@ }$"    |@@@@@0      V     @Zp@@@@@@+@@@@@ Lar8     @     09@@@@ ضmL6MnfRތRreIHH~3vcK@@@@pV[1h _䣏>$ޫҡC9|,[L~W9qtIZ ؀    (tjYOPBf[,X [le˚GzI׮]?P{     Vlޚ͛7ٳnYuҥKˍ7(h>O@@@@plޣ9s#5sշuM4O> @@@@@@Zy;sdƍ3РAm}    ^@k6o͑UT0BʕͶ{s      zټEHJ*e6%%%yvs      zBV-eLPB欁x-*r9c .,ٳfsD@@@@ њ{TX1s@lZZWlY    ^@k6oQBB9ĉF8uV|yϾP{d@@@@\/@5QFgf[-66     -b^n;VޙEP5D0#   ^_˭WJ@@@@@Z~    ^@oD@@@@ hub~     zEL@@@@.@w!    1A@@@@pV!     [@@@@@Z~    ^@oD@@@@ hub~     zEL:u*T(OF$FaRgǏ>Y-o^:vUݿ`'ID`M6ɓEFssI@@@( 7wc}XG +!CҥKFkΝ%99Y~7>i$ٳgìm߽{gG}TRRR^3xٷo Tz:ep9џhOorK…3OJJ>@*U$v5*/958ʪU2&@@@DS̫y6E~ḍQtâ`ӦM3ٜ 6gy+:u͛fvj`{k׮ ǻuCjj\}ղd媫;U5ڵh=zTʔ)csF@@#p)9u*0c$66&8T0䛐nњ f  J 6̈́ԩܺu,[gΜ)={/:tL}GD/R 45Zҥ]7͜X&   P`[ͅ"@||SߦתUlzڜ9s"h5k,\޶}vyL-;#@.]Gogb @@@ Кޜ ׯ@DY ݻdF2y>|9gNoJZZJ?K !   ּX@k&$$Ț5kdƍ^3E 4ih}W_}%W^y+V8]O>96==ݼIkj=W{iӦfO>m6j¶ٟgϖ;o阽z[j흛C^OE/Y)e큃ퟕwY8q4nX/.͛7~>קyڵK Dϋ/hJ%hu]'Zaƍ3*QU*VW.w}?~U"u:ǎkjuK.&    9(@5qh(Z 5f~ңGx?\r=Z֭['&L0/jٲ$%%. >c?g;wgU_bgyF>3f۷O.]*'O4A@ud=Z v0nݺ!-k[o5 g"ELQFe+Yzn=>HNNw}WFἺ!g5pi&s[6/4hyA?5:4gٱctMꫯO?7RPIe^auBV@@@EBV|.S倀[ߴʐ,75\#lxgݲev}͚5իW٥JŊM*UdqJJɔ/6PgSNfOjIZV3-mŊҦM/|}[NT~?cbbL͖ sMZ*aҤI2b YL}s=gZ~@?dy86 @f]^k~֔)Sr䈀fyیmղv=Uݡu7t^kefGҵT||k;fCj۵kYn[hjPnOnx]l:%f;?|zEZ_ jY k_`s?\m{e3; }Nqf̑   d_ (Gő 7x3 'КA:},_P֗Vivk}Y|T}]߽{TlY]9%>nMI Y vdYhB4/@:t)yr ySIF:x<‹p^Ώs#  /z! E]v i=U jif^(˗//˗/o|\ve&uR_3lo=&Yv t61"qW-LݦqC-kK.Zlj3wMF%VV@eH@NL\p.t(p99sll Z >>ߟ6 :f0 r]@~\M \}RT))ڮ] (W]uy|ZZy-VZ'Nhzmڴ'P7p WV͓U|msfxFXa ZF5l 6o6ݽÆzӡ̟ D@rӢegBBIW΋I!)@FQ(~Ԃ2qt3쨏n 45fgE}|*2ZU6zCo%G5@8j(_T5pO?IRR9J"0 j_MW ^j@k]ퟙ=pJJM& 3Lc޼yrWH:ud&շӪU{k.]]׬RJe߯T5{qp& R 1qkE'$M2N||Ƹe:Q;8 壉5FFk>q)DLQ0m:uJ*֭[eٲe̙3gϞ~CfjɣhgNރ(b`   Q @5 nSD ? K߾}%jԷ.\Xjժe6g9s"h5k,\ؘ;܃q,    GFA0gH=pf{5Jt =r >{#k*=UnN   @dOk׮ k֬7z _hҤ[^૯+R+uh'|.>)Ss?^6mul>}̋t}6{lرy_իDžsNl`n:B--K&=[D k$))IN:eԮ][4K`ιvZyǥAVmtyMY뮓Gz =;-^뮐N    a h @ |Eִf~ңG?\r=Z48aR-[@{L4lsj}TgT3}g퓥Kɓ'M/PYπA.;vL {-yn*5]ڵk'+V0oƼ;4՟Y/~<97o.ƍM6;Ò%KdРAg;{0rHc?p@fSjVjgݲev}͚5իWTX)PJ 2)))&SVw,^B4kS3*V]i}X;t6 HiF 3_{߶mLo{{s2eonϹ=y9]4{U_6M37nlw%\pgz?;v0PΩٰy}1Ef/B ^g ttO@5D?i  >澉EьJZ6=E3vTc$66}ae,_N׭0/W>rQ@\hPo5k֔Q}4]n@߆ #}H@fjT Zj^Hh[nE}&e}^: >jY}CsK*C{Ci9s_"qN/:=W ?&K־oY>Cܴ0/1I'P\ @*@5;K5|CZ#( 'o1 Z@y{6^iـݻ{-/ZY3H } :x."1/;զsjUo}W_ͪw;t ,0diuU2 |"  [@C@ xz:v}V!@=F(|ZUcl_}>ļB FGYYݺuۢE Yhy)СC3dg5v^ZG]!  Ӕǵp ]ve˚z@lG jN:IeLZc.wG7gg.\h8OYuϩ弘Wn؆M41/!{'dĉ믛zrPZV2Vf}Xcלl'I]F@@'c,2(&h 7{-[XDso]~m[h`vԩ@]Fqqqri1[j%\|ŢaGߵȑ#eƍ2k,c:>w\78{9k\[\99tn ipS/M3iX?4@BS5|Cjo#P5259h Ϗ@ 7p ZJLa믿Zl"/BݠAAFbŊr8]Tk0&V~'O}|u>/nYPj~'/ ˬEj^w_N3=3g>|d?ze!f^@ GXohKm:e:KKg:iv"7lBLM?r Boosf6 2ۯV{ij5g$u,}\}񒘘hFe^?{4Sm۶^Y1Bn-'Ωc:ϻ[-[&W*UYyϬJXnAJJ )@82JxB٣ F3OFs+O08) B-?Zne:?@i h ߐ@k:82Jxnh ᄎh~\$@@@  oH5|C@kd%<¨}umnL#     7h;T$    F_˭®Qc"     @ hǴ@@@@@=Zs/     D(qL7 L:UNOFtGaRrƏ=}Zh߾t1n{Y'wk׮cNJmlsӦM2ydiѢE.^]G\\T\8=Z֭[u+   4s!CdҥRF sΝ;Krrof}ҤIgѣYo۶ٿ{nϬ}QIII^{l{d߾}RdIOΝ;'m2n8)D v?gϞ۷M7 Ucƌ 6xhYfʪUu~0agʕ+EE믿~w}'M6;SN<   I8_.8?^fq㝍k6m >Fbcc\3hH\zӼ #5?}˸\"0`p,K:uJ*֭[eٲe~g=sLٳ}lСC8gzl0Yu֍XU'9.]s5`q뭷W^:thPf)'Sfe    К]9Cҷo__pRV->m̙@YL1lÇKڵeƌ}@@@&@mw Ov6T٬bkjv/G rNhѢuz}:)[l   . L(еkWIHH5kƍ.Q_4ibjꫯ+bŊy+Z'4Ǧ;iQj?~y9/}m۶5?mұcG8٫W/| f}ΝΩoxG_Z5qDS7xҼys駟sϟ?3ӧ͋%JbJ6_=S(8d@@@ Кʜ(ٍ4_J=?\r=Z֭[gjKZl)IIIf, >cvZn2w\{H}Y3<#w3F'K.'OJ۶mz ^Oz1y=UGb>Z7uԨQ%Uȑ#ȧ]B}#;v쐛nI^}Uyn38^   @. s<"doFiݺ'X&۲ev}͚5իWJMM+UTp)))&SVw,^BN:%Z#VooߊևLXg[biF 3_{f֩Sd~L?e:p)\C}N?w壏>LA3Z/2`9u,ZX՟3gΘ.jmӦMC=*5ܰaCa-Om'jn'A@ R%55-RqJZ=W =Rc95&Rq0,7Eo ﴹ5u2ZsK P4c\r?ۍ… UV'_|ԨQëyQF/ȪxvoG3kv3W-? jAſS@s|On1x`joNÇ˖-9f;tftc}8aM~rb7L9   DH@k 2 H޽WZ6;| k6`~hvj_~\]KQC=WRJ<-HgѢE-l:l ЬeM/\tEf]'g`q_' ٙz-kРAi3pfzuJcg˧j׮Yܹs{{LW_]5Q:N5SdNǎ˦>sgӤD $r%9,'v֛o_bJik308   P4lrPꫯ}!fk.Ù*z #晵kzvoذA6lY M+e4#rܸqHe„ 2}tׯ Jjpƌ㥗^/g/|:th@s e>>Zog{ IC/.O<]*U$u 73rŊ&ĉuV?曲f۷L6M㽆jժ)0zh8q vk[z~k6mj tBkVQx~0AVWnRʩ=II&>@@@PEY ʔ5SXPv^7ljn9r̞=n6;3lfjڡCZ^={(ye񒘘(M4QF2/O 絻ޮ f>"=̜9SΜ9cM'M$z/GQF)eX#*T .@tbmڴw{}n޼ٔЌZjɀ{L^u3EݧPD=~B6{V[xV|,# %55-7OΕP|w]yA1k=MD O .9:wU߿CGbp  w4L@@\ @5@5|CZ#( 5V8h@@@@@|@@@@@0xV   @&ȒÞaGخZy {^0@@@Y_Z5ƈKh E{-&)R^N5*Z?<,  h W@@@!6IJh],vsbX N^!ൌ،@k@v @vfGc@@@@;w^n8qc1^/ZDbb/ZX}tg>^䃕ˬ / vF|pe\M@ASNaÆeaÆ e2byg2\۷l?~|ѣeܸqQ3P&AR~B :q&Ueʔ E@Z#skz;&J5՟evj%I+;tTmQtZ>CV}ֈ C"y:WV?Հs6 ؞g3~i^}R> virΑjϹ4lURVig8--qzwSLWMbxgzf! $l!ҧt+x8yTREq_U7o5s`V*ɲdiӦ~]3f$%%ɫa_8:t ,g#lVu4聢,hKxꩧ~U} k F@RZAERdòwj2%e]rҺb9P޷o_ye̙Z?VZ&g Ι3GxPOiYfInXf 4yt^zM{ty_{51cKuy5AB@ceQ`&X+0⥕Zxο֨ 9(ۮOd-Urrg˺2iM,!_3 1G0$5%qklL/LoFi֬^k4]/FzɦMݻ׼DiRw])!h׋.HmK_%^y{L)Ml?󟦞1m}f@dS }[~h՚ڪ+dO)%S ҪbZdcYU[LLa':ը(jT͇۫;n'Odj?hh–pk,"$] ]\ifƍ믿H&MLVl_}\y~ׯ'|/zMOM?޼9f>}LUov`G_ձcG)YW^;7g@:>H do%Jw03-O6u`T/66VW.w}y9}b /%?ǟc6tb?g`dvCsr@@8bfG,:u2d{~~;zW_sϞ=k2m5̙_ʼu@1q|: t@v2mMIeŁæ%V`VH%HB/<[(>f||g՘:.s62ZZ8ڮzsZR~˕h,4Vreb͚5MPOG1}mmǎ&ڠA%KiTE :-"sײ>ogzra_ qΦ5bW\i=PƮ=-~eSkjnzo>/Xd ðaf}͝}tYVT$%%Z7oG+qta@l h6ׁnj.{PUkO퐚HIHT*kjj%s<hh }=;VY6:&&oYA׃~O*k,Woy%y17J:D H޽ߖ3g<`kej_|S^@{kd@ַN<)ŋxyɗy ^,Y][V5[oeKMC=${4ow9Gj.Pf5oh`qW)Ǐɋ? Jʲ@@ |Vvֵ)tڟ/!b9+k54*gV930B4 O(ej>fwufN[p-Yt+9)1U,' nFsMZURziUsV{P>V^T9{ 꿜hOv!KNNdjy jwy)Ϡ5eZRn[ 8lK0tP=qn<ݖG^~d@@ڹ3VX]nSW?bhPuDzaei.ɐ&5\#Ț!_\\"W._^Uxz?Kg~[4(Xd"q}RٲeM=E^=˗˗v}>o.\(Z4u޼yAexj]Yؼ˝Cx˔)#x`4xEbaݺulrL/YrÇ|PƏoun?cfe{9/0 83N}n8z\fmڕvaSMOժ+ɲiN^,wAԧo47i) A@_Tz_GUknET]\XȪZ UAy\C5?Yj@u)-ALyeS'N:o7֭+:u~;{hn[j%\|&@?6rHٸq̚5S:-5 6o^4؜hխ-hx__E1'N0ur:dJ48Ԗ9&OlIoڛM`:y\g4ԧ؛6Vym뢸@ 䜮ѪT j) 9|aR-j|V깝^Fk'x𘼻ڻkr}rO GsFk4߽3w{cA^^%ּԏй1L苯V7;oի4g~rVA={fPz*E,A͘1CoV'Yiwر&7,ۣGJ-,3r%TX'|b2\y=@~-K4լVm۵S2mP9 A/ +UڡΡᩧG}T.RcdIuށcqi[:tigˡcGBra)_ޭ2CFk0 f4Ζn:|\VXERLՃS=SӪMG5ڪBY l m\@5{g,jg-WLZn 76!V=hkZߝ4HD^τ#@ \}&ڵpW]u.]Ẓ:86]ֳ7lг ʕ+wuLV dUh`]n/veĈbIׯ/^ |cZ@Okf?=zhְ5Xz z6m9}_Op97x3ފ+E[n5u^]fהLpYP>:gҙ,8}-'G N˛dB@[`SXɇnZZ b+zIrRXODڷqu`egeN_r%2_ePrG:Rʸ!@ p\B7| 9o9rhkf~3ۯV{i:t0AH.oG4i"Fʐqj?EZUVW=wO단Znf{͛7>iv7٪\p&aSx>տf͚=tv,#*T0ҥ iP񚄋Vxa|x\w2]43 OV*oNFǽM`U?XdqioeRNZW*+Ņ>(:oVngi+M{dp!jȝ-HXݝJF;˶п9|ZD6~"o@ڵM}Z V`0WbK@8; @fZ3 oQOXE.\VXYΖt,N:$+7k՝VU+QL:V-o*JV˂hu^şY[ЩK_Tnr%꼋,畀[caZKd(Cg~Ԍ crAJ@rJ@kdشKظ3 ^ xmS @kV2X r#w[վ"Y5+2˕@}K"Bv+B0 UD7o4k,8@)@5{*_Z.._ƪa+'Se I>sVΝ3˵* j) f4 u[X਼&Ѫ1ΖuvyL5O9[caZ}nT4 pˏ?WO?.k@@ fVB`P:,+șs-,-˗5e4ڼ|))Zݵ)=σGCվçS߶[\mE kU-I:UD^h u+XXQ߉ 7˗KbdȐ!OF1{@: }m\DU{\]WĹ?Qτ@Y+{Oțl/61?5-m-JՒus!D~5h@@.@Fkh_GO7V`. z՝kI2ꭢ5Z/C&5/@4eZr*+0mVYk4NfvWͪZ7ײ\hwwؖnhoBϭ_TD@@ Wf͝nYv~x^Yo_kej&kӲ]Fkqir,MJ!К5kZ3! ^gr,wWocVcmK[ZZwpk,@k^}#"x^~"x k111R|yiҤGGum6m{믿| o-ϗ={ZjI媫ԨQ:! AUM@@V.tc${N1+Գ&5 MZ#?Z 'V]ٗb6k5+[:ҫZm}>R0yй1K8 /3HxkזÇʕ+eʔ)&EΝky9u )w69>}Z,}yrwHӦMM@r駟?/ǏyΝ3su-\0'N͘  ocҩTy+YZM˖թ&[/G<*++jK+6VIZZ 3?Z׺boyy֌xjegJ *[=ZMǁpk,@kor^ /W^ypޜbR /oyeС2uԜH#=zTʔ)pW_-K,?d~zڵ޽qwlC@ hv O:$i΋>Wխ&-JR 䬕K˾G@}9JՖ3/ #Кߊۭ_]øL@oZ׬Y#ZZ5g6Ws1b<32m4ꯏMK tٯ-:;t Z @4@>cY!^YnUEmZh ߰ZR\,.K-n+V0y%XּFDnrEEŋKll9{zfsۥ^zLB]y'y'Y믏uN[0> @t@t|Gk>yⴹYecʍ Vr1!@!qL/KH b:jrU J?\{7ДgI53喀[caEs @ؿȚ5kFž曒&v[s k 9"Çυ3q @ȮgeF^ªǛk[oֻ@V)/~Nvq @Xu͏U}rrQ]Y&2\C!ep wyL㮻 8ٳgKǎdɒj^dժU^53vܸqҼys)Qɐ^}ݞP98{L8Q7nl2j~%~i߾}}3/GmNd̙ օ}'I&֋$4~ݻw7~xZXv<ҠAs_|Q5j$ru׉|uPU>}d۶mpG;9^0αcJ:un۶wxαYF@[1n歐w6AV՗.m,uj!/H50{*VU״m2-;~J&/^'_R4_>[b>~o^?cg^bRT];E hiaGh&/,?M{Ztʔ)꥗^js=2yz%4[KSdҤIJ '[o>H~ip۲e^}ZٸqRnݬܯJƷzKz!rJ߾}6>΃C622m&L+B.]*II&-{gt̲59R^{5sٯrΝ CsѣE`ذa9  WgXmytդAD@0YuʕE;rEvn.kUDj惻ֺK#(kP^XxŊ%b iӦ|r5xhf&j7۵_JJlڴO3)˔)# 6ƴf7V{f^vef_PgĘ-YhA.]Tnf۷O+ϵ_=̰/6i5KUG?TTlONNO ׮][.Bٹsٯr~ . 6m|?t~:cǎa=^kԨa>u @cִs廽í{dѓTLQ_\WT()>8hPd{٦XkzXkbJ:]}PmT-":hcm(·@>hƦB]f j>ꮿ!?d|_35AV_ti}iM>ݬ<عYZl鵞Պ>Miz}EOΦ;ll^ڿ\r&Yc!T}i ;t{zʽ{B~-aYi  Xd9^+e&ȪAa kȬ+.!/̑ k&`g.jz@giRө2sNv'=9mg>y}"p~F#pi B;HfN8ajnݺUz!yꩧZ3!w-'O4u5vW\iz jVfVȊ\ ԢE S+VkjP48x9sԔu|riݺ/_^8`v_zhPךսA35sB~hY޽{xvwN⺵w+9*agg՗ '2ZWX/#IM3x7[WU+Wh ;KFkdnhd&9![S~/gV=dOFk{36Q -/6m N|X+ 0щE&L ˗/??_N2\:6"##PÇk]uH!}QtAI^$~WxG3%}W.hQp3мlS5B lQbDiؔc˖-xȑ#e3K{… _>}>gޠA$PygϞ ڨm5 /`x~ih)sbL 0PbX 2XHHEQh*lIbX^ r ghڭ]d=!ltCf=O}?c%V-V}4=gҩSо/<**JS\Cu@ӽi:=xf?)K.]ɓgkDDy9MΜ92gXX:Iԥ3f~@AA:{=PJO) 6HHHUI6lIӗ{'N]vc!)_Ұ) gjG!tiI@W_1H"a$U,ۿ#^] }5B}ԼͰj6:TTåBl `L@=_y~sbL 0uPZPR}T< 񂒷FG&A]6,Z~GXh! 3*ZziڎXy"spCw_4X^13 U cjj}ĈmaL vY5Ŷ0&@Eu)Kq?VX$pc08OzVX9,Z~_Xh! 3Z^0ӶDTzGnp&>qbPBwVp `L 0&,"PB<|}9;RP(Y)u`vB:Y4BYh! 3ZlnQ1} ;OYC|&bnB91 U c[j}C-aL 0&`Mτ4lޫ!±^ȿ',cEꍿj YZTyZ+cUZTuSVqxj*Щ}ssV D@Z &FuVåNZl`L 0&0@M k{\26\ 0OG/b>WUqIZ-9,ZΐVR T~-;t~9"4J IBtL%V-VS ˫R!*6 0&`L D,1[CTR M4#$;^V 3drԂB,v\YZa=vU cvևF͍3&`L 0Z PBk\^^_m/boArZVwBYh! 3,Z">+綣H- dj {p'&PjavU+'pU|7n+/,RGyAAAŘ1cUe=.lԷ999!$$ '|U`x"}t({􍭪<3g`hݺ{&`L Deះ'D8Ġ?AӪܜ`@DP8~_m_鶀XO j፝4i?o v58|0N<qqe.6HJJ¼y4%!X;Yn<==ϣ[nHIIєW_EddQ&,X)-,3?4wޒ `L 0&>/I'O;=ip;㝮-K}EL 0Z"5qw]OB~kAqI-Y0#%yQ"P"dϞ=|2|||dL4oƆ  U4J+E&RRP%='NSNŊ+t[ڠV}U5> 佪kl=>`L 0: O s5VL(26qrR :@%EI, fч~lxO4H_qγqjXh*ҥKhѢL>\< /_.ئMf̉Z.cl2L2:}4:tPVL\VCS2!;ԜO'&`uE51k/D n `?8BZ-Yh! 3jJhU#֧6 KS{ww ~R"z/V*^M_̷l"{$U4dp|w 0Rrrm~Gݻڇ3& y'/ǤkY6mMN`" <%6%">>C9EWSv?/(su͕XL͒i10i(Zzi`L FQ٧hS6? o{5 (5ZKdOz *7rܹ 8 0kyaڴi M6o߾1TGYa|0Uǎ'''4nӧOCMHբE@M\]]A8[Zί_ `lƌٳrAVZEiw\///Op&nnn{ۺ3goK%%%eYjŹNFQM Q%9݃Yfhr`L CD"5ۂ?NcՅPrvGIOlb^,0&8?:!ClndW=U8 )Zk bb˫⪢:[_e 0 d;x뭷K/U(C|y)СCr!@Ooܸh=ZM^xr裏b֬Yx'@׬YS#YYY裏n;;C .\/^zرcxGuV<䓘bVf4v<բkn 0&SDsώ"[`p.ÆV5>duBê&'ݴȋ)eTT:~ /vi;߆<|z"J@[R /wo!!p8UMêQU%x1U}ê1%jz1l-kN^ۏ"%NX03 2t/je,Vӝ'|h7Mb@NN H8N$teSsҵϙt]=sXt)t"Mw/M8֭wIy}a+P...)J0a{DZ\D(%S~Oi$"-y궩c1Q<$/bGGGs@cfuI"*}da 4Q_>-veKV˸qa&TyW*md?bbRqlLP-dNb+Zj{b*Jċ(+dZM㥯4 Bi KU)Q*xIxn8uMfuê=1Rje?XUPHlM{ϙ"@).1g+i*~nDt;\J$j}kgKA\F5i(,v[/U_"!Raaa' tVU9˥oO>سgl-" 1ʉ 0&Ek5!7ÄPxZ an.2aL @w~}q(6wG2NLZK[n-{ҷLrr֩SZaIzV3꼾JUJf}-ڰML 0[#@ [mO7\P mGoBjoo'bzmekxL 0 @Y?y/>?v /o;Ž+qX4 B7Y0lH}_ dJ1G%j;wfw}|PmX@5S+,7nS&k2>ŰHhtЎ嚒c-'Z4dʘ+kǔk5g@@( -ƥĉ%lx29RMD^kC޾^VKrP[T5C))0&l.c~s= e3 {Ig `#`')ݷ`ږC2X4k刞hWFao)jBw$XYhrDS)"oY83%իWk' oJ8pI3<8ocƌ(yK.] e+ڵ7<{l9=j`i& -P*<^ڵkg}V~,!Gi .줔XͫVRNedܠ_Tjj*Ο?M6l(Q%meKɔ1>}Zi.]ByLL&ĉܹ}gLK_騘ʽX=c~UƳQL X%Tև4D5}*3_\Ǚٚ&5 pe=Z&= ^ ~%M|]77G89EkI0M,JڎXy9!V;B7h(Z,*LW͌[eL X7[_> Gug뙀murN>V]ñ,xSƄ`T?z(Xh5 SXhQXhQXhQMhU <- \Kϖ٦wk:]||d}Ԫj}RpU03`L 0&j ,@IDAT7 etLYoپF`Y=jJbZ˲jWXh5r,fckZiExs) JJo6_O˪Z0ZUpXjZ.K`L 0&,#`kBkjaD'b{R* V8MeZ5(>`lt,jPXtPV@:?by`񐮘$DWN'V-V?;UZևJù`L 0&@BkAMȚ%VJ}0q "\- Ղê,ZVR EhUh\N4uǕ85e>Mݕ"W!ja,a1$z%5NcL 0&Uh*%`,PhY/,Vϳsdr,ZΐZoB+6 (Rr %ͼyW'<۽k.TS&݋y&j5:hn 0&`LJMh?SұZ,t#t AW*ySVsUBkE&j*YhĜ(*oǰKY5'x+ExjT‡`L6'''`РAOPPPT8.^:u2}c,Oiw۷rj̙3?>ZnmT3gٳg 1&0v:-EPWgnvnQc"r=&Nue]2tIg8 Qc#ck Ea6N )) P qqqXn<==ϣ[nHIIєW_EddQ&,X) lEEEѣ5e蠴Tn2M8!?ިZ+99 .Դ} Xh|+ƌ۷]vM-OvSwk&\[c[O>سgk`F5._D !poQ!-DVO!vbzj9GZ-gB [ZiE%pY)CxM2: @t:0\,a'j}&[]* ۪Xj9u el}Z0hٲ%^C0ƎA܏?x@4c&5&5k=1bWqO&4X CV9j9CZ-gH-آЪ[hB !V 0/7kQh97aLz PSJ;O=$`GkFF^~eCgL Rر%!%7 K+.EVۻR U)4|ɒ%xwK/|C||N!7ސ7ѣGcXxr裏b֬Yr1DY3gT.[G}TAaΜ98sLkƎBEVWÈy3~ܹSShO1M#|`#@`XE厏:ކ٭ Eu6AL 0&t PM @#:ϨDtY38!#u)z1ZgFQ'FpLHK$lҔ}q1t7o}ݧ)C@5k-w!\ZZ.^))=`[j$U.;|-=ZNynʿ/CSn+//nne|M+FMKeL{qvMxPRRݴr 0&`Tp=@ޕf>Kzn h#h!h!`1Z $ֹ;#y_xD==PηZ0Z-jևK l{9,]]t& tĉn:}d@84a_^$*IYΫ:G+yؒWn[ʛ:V}mƸhl-!!Ars} P=٘dcvdo/%< ރ{΅}-Pz<=_F|VP&A (Fշ=,ZΑVj9CjVɫu2xyks|ppr0\Eu߯j+Z@9>\uT?z^))?srrdL+W`ƌxwQF 8Ʀt ૯‰'d5o:!oXPAAAյE'PZKojB_ySǪ.HtIz#kk\}+ RCʹ7^]K2pWv<(*J2+.V6sL 0K\ǜ3WKRdp` CFdeL 0$"~G EF&fuح]* h$slfOO?ŤI@^'}RTݻ-[,7~r%vС2ٳ2jÆ A^i(Q,PJhVӦM |SjȰWX=zڵr5r?JVsQ3s{n-]ΫO7xC;KS'oQg*__ꉢ (bk0\_cNr `LB"Fb?3 ~{پF`tX<ŋ''&`BCM~=B`o{_,֫Gzu;y0Lz PȀ_~׮]ôijCMG?~8-[&Xᩤ… Ӫ[nTdmڴٳGBcUb\~ 0ydUɔ'ӎҞ=0tـjzGe$.B1qj˶ s`L 9ť>6 ?%!OLqW`R PZdl"OVoSjWU'+ 寿:z쉏?YdjU(*ۓתd蚡|j5OOң?(8/*F0n2VeSG_>gL B&6'cY3=7 F3wc'eL 0&`m8U#ЂY?fhmCa{ p | 0&` ^Z'|\jJ1uT)>3(((C=$3F $K.].](ڵ+(ٳh")ڑ K^%%%)$k>,6l Z _0w\)曚e=MZ+FKe-ŎU-ԥR%ѸȓRu+)) VRcǤw1-bF ޽9N>|Pnnnt`乺`_{… _UUiTVϜ:OAIQ5cx#ShXKs1N9 0&`b{b*F' l^xBa='&`L""dg{_dzױYxRJ+Xs@E%Ld o5A۰]Sо}{M6yOyTT&O^nz-bm۶5k~aMY:th:y@FDDG /9s`ʕ /,R4̘1?w+øqFnݚLƧmne:ekem/Y@N"keS_ti #FHO>Rxo޼U׎>>)$?_$RxN11cK\u[*&`$$:9<hІ,(**!>4K''GKԇ` aQFjgj7'ǕS]XZ5_֚g\=sL 0+#P_{ 0x ;~y2"P]B+f5[^BLFWObb,JLyZs1%VSh/B~.j*1@Z TtZ@닑w[Xա e+ 3C페i=`Iʾ|%$6^1L-12&`}Ndd˨x*$xI,jPXtBEdeZ-gB ZoXu"^~ YbICB`.r{ cԪZ7>\-KC۶m1j(L2Eb{/vZD :tΝ;Zc%Pp>h̡())+WnF+ꮒ+W_4ev퐝-Ǽo>YG?.ﳛ1&1y"1_lRO_/\GbA^x"<礟 B*g"SsXh5,R[?Brn]\V3T[vv?jXh'SUC&UN7OOOi>rĉXnN+Vh233mVc/gƂ fue4ONUчZ0;Ua#<<<*̙3͛7WZ6.zyY w}W_Jڰ꾒=>(.\K اOKL 0&@"qgeiDV{n;7gզ<`L X3 6 ܰ7: ]V Z$s;,{ ͛1Ӕ{kOOFVVSNqlbò~p7nÇnyrbL 0 ̒Y;cp6+NveC?UsM&`L oӆa\AVIuoZBx6 IIIt՘4i-EbrrppSO=%|fȐ̪̕`L@C`]5,::,B5;Wj*`L 0&`Uݜ>"[{au/xZw:]2[%@S)M6 M6o߾Cuȑ,G~~ڱcG 7"MaѢE2~+ށt}N_}7u„ Ҏ[9w~mmVxW*TuqSQFh4`ݻwkZ4n0j(\zUUT2`FX.ƴjg8'Z91&`0z`fv(.-Ou-Z#cU7AB{oN;\ Z,jɒ%xw[oᥗ^|C||<:\ٳTt_x )Ҕh=˗/ŋ+MCg͚%kJLLĚ5kċP؈m۶uhҤ,M^njR?7BnYgϞL.t en)Appcx&boNx80\)""B6iXΝ;5hګji`6D],AN+ĺXȌl"CeL 0&`\hp~>t ť, n>"u)jL{SƱ]oqTQ_"abx軌cǎ{>Mnl֬ ;v|*VN@̔ޡZy*uǎ+P|;婩~HT6lƣ!QG k׮^J'}}}(nʸ <ׯK? bS%SkU{),Ɣ53tP`j <$'gj5|P5gg:W]KTJEEWZ/V !>En*1!QhB .33Emy(ևbX @o qg{j3,{ԪjTW%>\]AҥKѥK9]8}iĉXnK2BdgWC} //OM_~iIUMC0:OOOG-J6i''@F}Is!DTuto$xcg[SB<m:P쪊 ⩫LC}vS'՚V~Z_VpL [yھ}{l)Ȗ0yJNN1dF"+%c'jP3f&,Xi׿ J\Xͅj:PBDB@٪VʒTFm^#uuDڴbLt:.HdS+'ZhZ&`L& =BO7c+5ѝͷB? ,i$صk)&+ҮHV)+y^|Y]վC%ˢ=M'QXWs믿"&f7 r2V+Ŕ=|7݋{Loh]Y 0dȐr͙b7U4$N9#Tpҿe>A9'&JvF6}x}=Mm3&`6@NO"! !;#6DL&/YCu6m1&0`駟ʸ>ђݻ-[, y@xabRaÆ8x-WAD E6muσ<6ﯷ7~a͹s-gn)>(}W"d??4ׄJb`k׮".-¥$SzVsQl0lJԹ멫{~Rs1έ 0k @ \Ma/~ G{;,M8Yl#`L 0&P6W?– Sx.Oum!־; .xw/ئӦMMWj:u-[&XŤϟ .hVO֭[+Y6mv)NBOT2eJWnޔq+P,V @ _Ѿ]vhܸrZ~QK]Iح9(6ړ0IS&y/n9uu6c9S[ ` pF 3r銍E@uV0&`VCr=b]U|>'ZyY8h( j+lRy$ZJYl<<ٳ?*4@$ٳ\v8í_Smc) AU_'R9sDa_g+F cN}c<&G1]xU{5!T`L 0&``WG=| ȻϨDt^3Wz9`LoXz'|$)i:uOyࡇaƌ#QHMIK.,vEy]v!H8$/MZY-))+bÆ R%NOo4@YOsW^yiii8y K± 5Oa:v(`Ϝ9BaZj92n톟{9p=|pKU'%%aժUrǎ999r v =}4|A)FSZdJ x_{… _tߵ옄I)NVVH9uHh-K7uZ=uٜ~̩sG>bL@ KJ6Yy4ofvxk`g8ˏo`LhHz8V7(F`»KՍ n b#~˫k[FB5H@ToԩSh߾gs/[NvڶmYfU t\<#""#^^+WDXX9IXD3@1JI%{ƍUmݺbN=-R.Nm־ywT9ۆn]릎[.l:ֵI)ɚtYw\.7n1b#E͛vQ'Dx! m@<ul:w@IpstJZMM(&&U|1.OA|u.g&DQQ-9VLNN& 8;3DٶK70uADX g{ Uuߙ`$ j ڠևaqu&UpjPbOTCd8 \t-CIxy >}MFѠkfr=p XXrB%j9CZ-gH-Z=JnQ1} ;қh#ch*ժЪ1﬋^Uxۙejp ̪˕Z=O sdr,ZΐZ`z8}lR]{n:U cUO2t.@ MߵkW5-7&)cgZ6&4Ĩz|,NBB²= ,ZΐVR ,VGkhHmxcIP =d(*׫U 3xm`Lh ۩S'<,M 2&@0RY=A_LճDdpL 0&@}!(fBG E0?\^?LqRryƌB>*bmڴkaѢEV<6 0&P +c_pW'< {`L 0 !&ߋn"tړW-h6I"wi}I鳓`L 0&@}p7N,T*±b'& mQUy:*BU_U320Re8t@|ʡTuP5\j}JnjaX1j#5^ZO~Uuz24`L 0&lmB _ӄljY4`L 0&P8;& g#z[.J֕G/ ]fջXBk<*`L 0&Ki18x祷,g2&`L@mh͔[ܳ#qH/q6skZk7w`L 0&`/@rQ1ZF91&`Lx1} &il3JJkȽUXhU b`L 0&@K"&ˮ'HWxrbL 0&5x]8 Vr_qڎI<,lg,l\ 0&`L G o\L8@L LkK1&L0@CW'w;˝V,EBV ryL 0&`NTvy!r,xy(xԺ!`L Q"7&Q@" =ZFplJYhU˝`;`L 0&8dx_xDoNL 0&P.8ǵ9l;!hS Vk,˃cL 0&mbz܇QXқ dAp?k^pL 0"z0b} `@O@: stD s| ~_ M^p^`L 0&!Bz1{ҳ`כɅĻ'&7paٳye>OAQfvX]2"*'O݇C}q%-ށ"hpSz7*}hc7`L>|11V39X*~.Θ1u.Sp V?'p'ZP|Rk^]5.v(-8e nBNǍV^A>sn[`Ko}g0wW$ DhOW,ilԪjT_>\#1&`DZV΀Id%*pce'VR ,ZΑVf9fIOLEW힜||XbCٰP'X!:jcZm6 /fMZvBpwUBѷPp[`L XkZwٿE\1&`j'vRnG# EWłWMĨ ,ZNVR ,ZΑVf=so.Fֹ{np?u&l6aT0#Sebl Sn W]k ! $ʺ1߸ *k"- 9-°bx4vttjXhYE>\AdL 0&J@B뎔,MFphW%-jar sdr%yJ~#n؏Bl+KSNN;&Xc) ߑp zEaχ,>d{8o h%|WBk=x(p<&`L Qh-)؞)qPʺf[B Z-Ba z,!lhp3LEpp:vh/W' Vm!B'$ )Yzf]BqNnUN^֯yq hTT{"TឭߔW>؄|1=yE$FDkԪZ=j}`L ڄ֤b,6\+PV @߆e/jBwVR ,ZΑ֊ 3p񃥈y; >EWӵkW՚b=3h~m:T%W@?KްU}rΑp6-y^N{ћ{{bKu\["&3"njЧIDNܝ'S &Xh#- IbL 0&B@MBkdV>ND,͌DZPVhBѨ*-BkxBkyLq(LIEGD<9ᏏSlƊa/@ChiiHKO 1 =j+H*?T| Źy6@B, RBlD^i}틇{ 1[v@ ?`瘩Z[>=4|p@F~fUG/B W$dk='sj*Vɡ &-Ɖ 0&`LlOIq5/:WdL 0&⏑NYϳUs~c<۶.׎F_2O(ү* ǓP羈kWײw˄G7WW{ۉpuH(uT0y7{91q[ R@Bmᩲp7 4\'lP5 ) {y @!b{YM1?YZ,h'@aFv<.ulWZlqv.JqP^sscpxB ?s oG|6wlAi)M#GE.1hԒأU-w;أx\ 0&P-h-)q(# BbTxV- Gk$&gGV`VXLʴyV!hg\rge M=&j@RDXވ(ppD8*B?EH =o6C;8\;] p],wNr-:E3H"EZ=Knebb[y1BtmS;GXZt)7_X:¬dK! %Y냌PT<1Fׂ":+O#QNn+:fYmDdv*GI~vJ ]ډzuY]N+tϦMѬ <'훆 f Y?(5ĥFI{ޮH{Ɲ>`L 0& D!DW_+2'Gg#3/[S^.r ',P(O[qVi=},N"^]vu$: ^4(ޔ޵NCBq)noΊ~Y5'oўwb+#yMړ悛Bu")V8 "+ ˳BIN"\@w^ D_Ɂu~ !^xk'{7vs›٣v>YT)v>oO4{dD- YW&GJNsHd.xh_ 6\nα>^LG ˄, v%n ^^D’IX&vQVv Z&m- 2Ra,bW[_oIX&`yaOزkg,:ӯC4^HMI$D@" Џ؞ +2xRcrD>&.22RR)IȥIe%M}X|ĨDa-C!X)R)PZ-ޏKKŠ6ccLՁ#Sl81:ɺ 컴Eɋ2*V{%'_R7]w^vؾ(=}1C厅%3e+*com]g͛jҶ\EF W"oBϠ`7֗SѶx*4o.+Xv#ֵjZ}ulmѤqc@wC` (UM 3+ay9A7ZMª~r !aӃKX%UlƍJHX "a eR {)%Z'J$D@" a$* n*&fuwRD@" 95Q4B#"WTDzɾ!q>hXyzQDV./Qz }S D4z,vHyc. )!aؔtC݅z@P[&Vr Mh73a3Tk QxO]C;bo 1-[Υ0vNY]֓9b:kUǎ^NW ю-\p5g37"Y9}/ m}̽1Cqqq/e#lL c7D+ԯg;RzzxPL56,e"ae-!ay_;pTITy¶(-!aUBE=;Svd s,Zo^ң-I$D@"pX omwʢt-DzPZs ZsoGk։&oM^UVu>dŏ\EtGYާުIj:Rf{xeSu|3>3D9ܤh";<},3 rB0)z +WrN^م]lӷcqx y럚|*ă9\KvBIo5u LM]+չK޳{BzL {%\?9iWgs$2n\(C#utL/Cn!VkvH~69y8\)y$ 6s'9{Ǵ?VTN87݂ZrDx&aY[Q[Rz{y Ux²U}#PLEcpU A/TX/lAвJʁu"BF冾^}_yV.W򤢵ޠK$D@" Ӱ&.zldDa Vrp*QTzVR SFGӉG?Ư 8Ӫ?!Q |xxTڕ/ڻBE93z}8+MpJ(#))Gu + &so4[mi<ح[V'>:"tD8;,ꄬ<¬RYMe[#IXF:=iKUu(_gu;QBsȗj8Ya! EMt0.^]zI|*f_{cdnX;~ v /Ggە%ͽ|1eKfPPPsGDBA>`|eҕUځ V w8n1~ӐږFM'X^&V֪%έ#ED]T?4{ xݯkIQܗֺD%X٬D@" H$@m)Z22 Ɛpg^W'KEka֚c-HEkqdڍ͢)nhӺ ,, S+J""K\DTjFf*rHźQm6k pU݌_m`MY'&X'|Vv_?wFdZ"U~-xŻ0 7პ K\8wNE_Skun&_c/h׽}N RMNyסK4u{`}q=Ln>wDe}ɏIZ/G8Y!D`\%v11(*m8j6Q llFbK3!1{O[}e @VhXgP0L΢<>/+/E\|&bd[s=`o$coVą`N'2-v+3(auȋV_{H;uQ&Ƙ]G`Cx<3#PXYay}P^8s.\. ʁ!kOt$!?9TՀyHny;?t77oC)bo7G[:|ЌUYޘo(B vyx EY(V!/= )1 HOK[6q@X-Lb넍GB]n=NvЯ~TזpXʞk$R5 W',\eu\q=Wmzl3W/CJ$D@" Hj#XR6@o[^%DJ S3$:\UTe͛4XYewxR222TmfM͛ ߯ă}DRJP ''"*UoxkuPI2%/GMm5{:ZMDצcGGNϡGˎb4s]i/;~ ZvMEq*|RS#ZAIHU%j4\'1<1YXC3s+짢zgh";'uW:{|\c]1Ѹc1)X;"N+ߘ26\-beN|yMer/N;"f㈘%0=?ډ^?|Y8gr6T)f(^?\\}>o @Uݫ̔x;al~xدFOJTMD˰ʆn<`K\z0.~P)wtpVXp-uC}E) pҞ>hZy)LDk㧇Q- ZliPwX߲u-V6,H$@="P]^%ps?wX ^e(H5vu@5@+TM#Nshɻ705Q.)HAERhQQ!HUDT昘(\tDlцDGLjU\lrwa"ׇж7V_ULcmBW~l_iӷ&:Ƌ>a,S+ `~m8BD̼IzMvvpy}0/q 9Z# 0"Z+:LVTu ~.z!fMYyX~!7ojY5rAI4s$)'Y9Ȧ{Btm 7'l.Ylb +76ӪpM-FtXZ[eMWC~B2q(" uDϠw_BHr Wy`o=1DSbom6,LLa]dBS4UZQo\e+SPyc'|qϷ덟^ɗfebė)V0gw;cXwpga}&O[" H$D@"PM $"i9/ac5[$",q&%&O_ĩnFcӂR-ZISȋQ>J"$ N5{7ѹ0Di1|nÓus 4;@u&Y9"2U]^Z4R r0^I]w:ͫN&`+JC]1x5o)Ҟ,v]B ]pe<`6^nB1N@"dM.!gh>ҘW\ooqkg|njn rIZ80)e=ե7xWlIdm@/RȢ IW`EIuD3FѤ5(\|^6E0/Kp+w94ŵ0Q9ò  z8q,n}}2FcOɎVwc~+pNRZWZQ6!H$@CXEl2dpaiA^hj=?-Tbh)xӟ?G#vW46>mYEr|Vy2)L )5O<W'RAe3YYY:nVH?kjj7#h -e)4f sR㴌4?Fӫ\](x6^ύJ\ytBV5Qƭ<=rT3,&VGȯ^~ 0,v:Kv_;Axj<~ݖC4E` Lh7Z{#'^kfmJrJrlDdU7>qQh?f.D3a׬u&boZ5cal a/*V `|A9M9E58VEF؜E-Y`UmVmۢl5D_,  hYB||~IԙN"dTB MD T]Rpu \=ЌNкZ{7mދNN@BA/m}5~ǂ/Ž^[| Nƽ~%D@" H$zؑ1Iclv#O8K?V=P,@`U(7s(8fZ@.mLj~R|g*5[K]%&6DyFrj^s&@MHeE,e '|L)æDyYSN*E.,~zDq>;Z_sdCLQO}@ ?OdС]z ?ZEDhڋ lNs/-T2$}6oX{v)U(D)ܜu&ji _ #NR.n*q[-L=|S+k!}Q g4xX֢mec~-slŢ/1:o 1R21 Z}Aʸh"g_]^9mupY=$k&Y&l <tȄcfI >r"9{3^:. -l aD?z h=t %3rHH2jsE 6-׼)Y-?\dE'0󠵻#<qoPKH^y'_kVKb=q dHE$?Rz{_?9zD@" H#`UI7QIؗ)T"=+LƍnI$jhe?Pꞓ"Oy[9D8s9PVR&6y:-mDEBiAOs<3S+@-ɫ"Vj()FoפZHOOӜ=? >SA7XM[&wܩtz,' V1CLN~6e$Uv./W!Qӎ~]6m"l}+sւ9IR+ `eh#ek+>_GŠ>_6|ZNM:Ҭ)sձ5HP(oO|4U=O^וzE˽^8TWu|>]? kRۑ=cU\v1kΘj/<]D=&ZCCp^$^H)V"S(8*^ay"nhř~o_,bVፁ/9޴jY[{,=5Zqt.΅{t? V*u!\AC$D@" H$$ta Ƀ51=p^v--fggw(DhK3W*{2qGAxMVD՝VV6B=e-ִMI5egG.yDe=A*4o a#Dߜ4Dj4l`SȂ m[s`,É[XνpaBDv0iZ(`]`HtDŽ)xQ9טdٺFUo|w"Vo <z(HV|`rc*l+/٘b\kU,ZSzs͑J? vtad&5xl%׵CGd7j `(cD̨X(cO:#ˆ 1) /-aM6 iV&AKOOQ."yLxz݉=8xC dc[V@I3I9GW8.h; + Y'QIWd9hݶ->7kA,4QgRZgPߺa+[H$DLz.3K)U ;Y*Z7!Qd݃ԃb~@IS&PdTE2JDj i%=S aG?y|YԞ"6R+"ǘ<*2( bbyz3~r @8\]ORK%$"xHX4ԡPQoNQX7| }Ÿ ?VQ*M1$ߣR<"k‘".cU6b_ cIdR]vfx7HU(C3ę"|&W7i鵉 Y-Z; o x$|RS]q|D1q(J'4=9 iN#z`å~...@~֥!9&[/#-=̶ɣ`40qM4i=aG!fX5VDdj"]P:8X7m$?co1Eh) gxm4v/OKK_+`Ev0_m%Kp&uĚaCR" H$Dx#dYDNd(H<"xg=>C\|4bb#` )*iʴ&)lmi=JLSY]ʤ)v4rHryl͛QwvX# yv瀾h>-Xy!׫vnĚ4<lXxu3j=m Ze`?dH^OaV?@Wbr6@`TqqsKfcÁ`o?O`5)y/$;Dv E1-1:Ze>#e+GddnD1񚄣Qሉ~ڦD6sWQ)L6%n,縧t7PxF! poCP|(^j3ҠpEyV T'|k;1=߆>ma%5P4{gNKhkb GDY"zZyz嬩pY᧽ IWd <I6ihS^3:iD# ].'iSYÉ`G'W;M:XuvkgB1HkӨ ~|\k~n'ep5~g394 Q%lLΦ΁XثY9x/s7/]alr `$[&dgc/K!'SANx4{K!wRsh>w1z{u@SXcp;b{뫮3$Z׈߂G-U6)H$@#0gy̥ z#*;DkED$!94Vd101JvDZ1jK>LUV S.[(B_wr$Zk~uhM?W/BPPGƣH\a_4RAh&?2Z}i)Mn~ύD}Țdbq1%XY^U$ZB { OœLMsdk3!KU V/ }ocJR[Q0V k Xe"/X E8KGkVPDG )I$"| ,-0W^w5-10"1}=ie9 K>|١D@" H$Dت-Q-w?-MlQ3_XT0%(E=RSӒH$'ghAi!-k"GssbZ~νOOOlk @ѮMi0rS"p#P/V zA6;cG'N]GC#U{5hִ%xQ酂cԻ=Oiy6A}dĵK4{Mh{7L4E_b+/ !V&Nh$?Fܫ";_I}2Cpygj0S#3___H΁;<=ZzZGw%{qB<㋓`8AڑDk}!/H$D@" Ћ U$d+IVLbLM&2U&UyԪ9YBՄك^Ӿ;]@zJ#;@ M[I%w$ ;/ d8~ ڋ> )h9m`ccѣejp5!=Omw֍Fj s2:8Y19q_0Ml:;hgIQ5qb_tr*X,z顡x{-nl*U6E0Wd0-&>}ro3_ SsP-"Zϻ2zsde7 5$ZM-$H$DnF m/% l'E`nE V"TU UR5/q )"TXuebUWZ(__€( fa-.yIo`}ɼ$/XI8uhOáXd*nđZR/"b%F+L82MNtfbp %'i 0e?xvX<~ >m}^w9/%դqcpkBP4 l\ɗJm `y^Ed?烺!^x[FK(V.VSKI=ZMQ,VUkD@" H$6 ~:ԭ;$ K]"'')읚8*33LKM$T*.4xG/"~b)oBw4 jNA'}˼b#mV,ۢ[.㷬p47/L<v jj+@Z7`ٮT _|)½D̽'Fnϫ GF/&L/=?'LY9c3/{uŋ0%.0驗OIK XdZ ӽ= ׯz'qY+(-,-;47p$D@" HJ`Ҝz: "E̕Ed?2J5KU%@dnnND*RǸz?[LOP`sRSp+lK"P(qe"9/DYi>dFtXZWSm ̽TӅiB{k~ t QR'_3f%IiXjw8wɬܶs~|amߜ ɗЌ\;r/&#{[JNTLo)=-{ԲD@" H$;جҩʂBǝ|B|*Pe"UD*H/YG+SDu%UZ՝ cj1<@CG<þ?Eí<=`2Y,:#?&hc =1M5H~X~[>CrsS(7Yh2K G&6/ xGXgR2ұ8+Km;C׿ [O b "у1=l{m]4$#|M^}nH>ї}K$D@" yj|LFv=55F@N-!SSy2(TujBՙSmo d $/!EȺ"7MzKĕfCVQU%("L==|( QO=Ԉiڬrs*Ai4?HU2Woˎ΂PuuT|sNV$4 Hi BD&=p~d7BSj8/? c4-AuYbv<,^i @ `n{1q'&֯_'z=XVe[vaʪϑvM9]56% /7W^yFIt'''5E>Uvz5̅ w·|Xd$}1?~-?m7n3UYG] -- BN۵÷l]x޲0a]E!!q^\~~.hѢ z533ѹ݆:>>ϟ"۔=SCOrS\\ N>NØ3g3ŋgmfA> :՛ÇER١gϾh߾SC1]Gڵ+}}ѡCg:^HHŲegE}жmGG߰e^(fpY\& q%8UpLz~p;M(S7++W%~SjUyA@IzC?J1Wɒ%a߾ؼw@p%lٶj;5$룏>2^M %5kM/] ƍDSO<1Ny D/^|qN~ ǎХ}xٗHTҨl}B|ފbݺNL>$Adj3ot[3gؽ?_4/=Waȷۂ;Ge?^TX'e?Hp} ߿G1w4R뫮7PdmW0bb|2MFx^!,0ӎQ2Y*O[3cw'F%[pީD US| $ D}+B~\î+R,8u5ky䇆#y-@yKHVu7Z"pK`QӼg_kY-bS`$RPޒ>eU#aake_{XBz4wGknn.&O~Q\$&Tb<[|.cN2*j0T,'Y!lJzAZA $!+W.Axx(x =5ƖW^s端B6 a4 :U=ڸY嗟㏿nZn\:#{1EdW@+ \4mtˇqt ]Ҳ*l+G6LbEfCHͭaTYES<Ջ4fEE5NG``; Mܨ5iYo$H_~R ؗ_~K:$~4Q}i}>53RKURl6qN={1}ۻv3gNˮhҤj_7c=o*;+׵}صkN^Mv /Y\G@IDATe2Lc2>DvBwfp{p$$Ơ7݁U5o5hCGCfVΜ;.:w"֡"=ʒC@gz綔A_9CG?gîy\?qHoe'4rۏ=:ӧȌO86} L/Tkܨ?댿>XQKg7aƧ%[n#΄Ú|ܗ6F;ʢ,ֲ[3oRC9ضmSD^Gk|>6\l_>_(9[(`i \7 mNLI&g(Y@rPNiFotZ\A ckUdb@Wwߝkh*rsU3-lP],$9FIU+ՖQ7D0:&"=v:d b"eK ˁd t+Xz{n>)0]TJ\>V:*L٦(?2#?~ aboS;[Mgȳ/-1koLngK,$7_OrDMNJ׺ A8s )hޚd0;7e"*>Ѻ9χ~Mh֬%yNY"ԩciO?ڋDG델Q?iE 2OOf¢#))Q쪣WUc:Fď7Buڐ3nMFltFet޳?YV.lxX/VOf#>>Fƒ3*“'@8~{lJMMFEkk[ 7Eߏ4/Z=ځǤoEկde*eהA]W_CGNڕWzp}V;y0}F xd+55mtOs/; 7cHNNϥj&k8О{xxᣏ11QPi)PSe M[AϏCr#SܳƽZFaz *9"iӪ _=pB[^) P&**Re~eׯʕ\Yf\{b۶>e7k{~SspQsGT~0zfF [)dnn_@k++"]*H' UPJfKn p_MǏCoWMs{*&y1䉗Eⴊ9(*,D1}QL<Ҵ% l2ʂB(ȊW\\RYTZ.}D1fJc?N(C5H_>wJl0,"Hݷ#?}ob)XkUT\ś~Ţ?mEx/Vjۿ)I8"oݺIkOާbZ@-7Q9}ߏ4mRC2ac=)ʩa/@&D_ }ݗoQ;tzɒ[3f! Tlš_c"VoKu]vMOk%Sg5f1}9E 끶Ud-T3}(L^r*"" %dg!D\fQPB"2sh;fm(4`, 4DBA'9}Ф<y>BR*TXiyைP%lQm.[^,l~=HlR={#Ek\uhYV=dOexyog ԯ}׺c,,_=OŒlC#GU;2I)W Sn^xkIO&*IG}B(Nf=u-ZS_W0<1AŸ?Jhe5.L*#F5Pkӭ[O"' U?Yg5pP0z"~fkwOϯ/"98;|(^p9cs}I}ϖU7-^2!mTvsׯ :zeg^^ye2fxC]@Vg j`-Y˯|#dd"*:0$% q%%@cSPk@CDO"6HYD$q9C(%W Xt"! U'D2If!Tϣ5JRz6#ns,H9N%aZ*nr[*Ө6K [QmXBf& 60m{s+nb*qL:X 0&uN#oB"z-^nto1!liilѢFzu5 j{E6nLޘ9szSVhOvbU'Qکu"KyU>҄ǫ/Ӿ1חy>":<8MSVIP2^Y2fɺĮ%MHzOk&Ymd|91ATT_eHV=΅r&Ǚbu_ff)eAv~I"<4c=&Vmz)=]W~>_V}YѴx3ҥKwaI!<ٳ']zVt;&)>k5nnL05gE#Z_zOr+yE :z dDNj(glzfBQ F|M+JKĿ(2dpum_v^iFd~כ/J[,._ q)FbR*ULU/ƀ ?GUoFz_j]Xf)]:0:y# Vmn)̼\Rl}N>Me'"3&R)FY( 2lRq*WD'O}/'wiSM1XLxy7K`+瑒tBe"gFuP-W&9f $ jkF*q ׶rw0 Z[U%-,ag7ma'Ղ[[Z ՗]ŇmO7?\LtueIv>/^v 疭f~ҬOJ}?~'Uz4C+5( IVYrv7D?A̽ب4ʆ?o]7osV᏾FXT7n@)UnUwaOItY망MA ^\>N\qkQm^޳g_qs-uY"]VoxL;vX͛'ۀ]V幺g䌾n_{*rͫ~ TV5i&9?k ²Jcu`b}ɐ{@_=Im+.BQ,9~鷠9%Vݻ,1J*grc.Da+m$$A/d:c~yfTJ|m~;:gېvL!A2q&Z-_ђ &ٺh+J*UPH@^|cwVnOfƌy_B^>~:W?K3yR5^4}96.QD:#P2`Ԍur]0cazݢkIZ@\RyDr擏gV %+y5#ĜDvӔD$ӎHioHM&D|::9j.*f8vXA=B&ZQ`~d5kF}GΞ5VƂSj?&G;Dn!%tpWͦv "=vXgd.|iP4x&=:V qi)X9=z!ݶHͫ\D$L|u^#D}+A9 1c~9vUV3ڑ)q}XӾ17ZkמDH$+cb"3^Zۺu;R42Sݽ_"W]}eǏE ‚ðU5RV;UЮ_6OA#W^DŽGiwR//د5&&Ja#H*&j#ZNui㑑aj0m68qXX-tK3v"+M%bROMV5>^1jH^رT+,NaJ2y@X Iddlyuk~fGؽ0YϣN*' '1VYO'bw`F&>_Ɠ#UڅYSc"Ke]xU~{H!ҥ& b,XPbAwQl|bS ^BBzlf7niܓg23wn3wfg{{߁̷F*ݜFi]Ss3$J@Ԕ\ڦJScb+OdOf!9+(vvTlW'#QcTP&{ < TH2 +Q5[R}v Һ&ayA- `Ԓ'pԊQEɐ@Һ2)5X1}£߾gX MBX-t K3<ŠpmHo&n4ƨcyE_ ?#'@A<=Ę.`u(&.)hV}H!/U{&g i4PWNw k"EDvUY5dr:Gg0h4qԾ-ڇ~w9ig \BBq)7~sJ@4%-fX=1`Ex[ dNsss~~)27߉^+#^w>~ǚenn?e?BUJ L`;;ʕb޼t)ex+WM~njm5g˖P^U(`0V~ uMSje^ʵSa?lm_!a/GX?+c6.}2a+IgP'әXa_v:u&vJ+,PSM&jz~0Us񆯓|,Sjo 0䑑3p8S bޓkf=`(ҀTG55ie^.e[;bՃK(A֫zm#o&dIt[a轷4Fׂo[o3Ѣ 8~2<4~+\H=u$`֞~ju]H9 'cߎ ʄ!mu'l=uß,GЈ^st KKTyczo.or@k$ftړ߾}Фh3F{*\[ +~Axo# Lm9۱cgzkDVh76`=޽MpG}V4z%ķ9@cm@ɁYx568Ю][) \Dg 'ɓuL|uׅX>FXZs֬&McW'?Fծ(W'[-z\) W>{f$&kV?8"Gj"ȒJɧLoG?,m:s=M+}Rk;Pe<tȐ V'i~׆=uN>.CpaKժ oFET ޗ !Uq>6%+;[[oKg__8,2:}ڍhJ9]9{FL hj: ?w/}-"a:,[|l Fv{%6˲;*Yvjbyi(I5N[b@Js[M^9f֝eUNF}Z~^86D< ȑ® 0=Az|ݴia9r}؏R7+W+XvkjꓩګiJy/aԙP0TN)kjU[Y: 6 04Ow:` xLBD?jd<|{k#W]C_G9oe <28=L)ЦMH3埱v,XNN. "pVSNpSboK97c\?c?FLRTPq16t޽\R_t5G ˟' }]%Yg]}2QSۋ?.8k}s,X0GOWcŊ* s>9Rڵ?G\~yjJ4}OIM*&M؊Ǧz҈1CtuU>$~N B]Ni'"1FÎ 3e[#g\O-88l+@Jj&yUК(B.Wۈ9跮{`2zJl9@-4x^DoR JI(KNK /*( <ҋD[KOɆK1q8v@2(u@)TpH,D"z)!sD{ʩS `=Ic1I15{C@jz߬6v 'CB^ ~ :tau~drYIY&TdCs |(Sg?!Fqef- rV$|U߿S|<2<{LKS4% OAj@j@jA4EQ ҞlDj $s1'۽1YChe޾hk(PNX媿_+aQk.Z+PN֨,塔n%}@8{ו,R Hs%0M\(K jU@mZm_ B lW4߁78x^{і@*~ڣoW69 XaH?X͙"{RrH=ylj\ NX1^L拯4E6Imx{ta:gΞDnp͆ }^5@l&zh,mD`' ΛAw<>D耏3᧥1-]t|_?qB]vqIk.; ='xظ1ʭͥu'&z{).&jh&T`SZԠ4*ە5pQ lkq#O)ekY uqqsshoP #/E)T; ] <§7ػڱ cpގY^HұC:S!Tk27“$5|/OOy`G1Z5~b[af%?HhxbwcZCM:j{璛Yy髣d& ;QgY6?c1SZS`@#v-+Or9]pƋ9H8i@’BgTR33Sk)WplaAeR*u2U"UAm@/TE-oM1 XdP?Бw"f9 vv~.O&tyX9pƲP'O}ẬZsHkC(;ug5:mNaݵz=Q{*KtTv ;B_[2Snjv-> eDHd]c'[Wk,)VJm?/_xrc8$3gO9Xa.tC@r5R4'njSeAw`?@HbrD Ȓ֍ 0W,* 'ӽlH[-Z_{uQ?[USᤢQꊼt[~k|} ep5PN)oꚹn7o~뗿Z\.Gq;ф͛=o9߆"hm.WJSj@j@j@j@j4 AV9 Qթ < RLnpqqdzIɱ(--vޑ`>mfd \ƞ0z&n~fER=\A֩ݟ-T3ձeI (CxL=$TL&K)cR L%Wh+ \֩jTcezibr4\8.Eva.r!+0,ѹ$ Fh'0~s6 CDUo16~xoj'wtI8cN%x+K.V]TFXhұO8 m\r/Aߛ폪2Ԟee;7ހКZT ~M[zêu_c3EwXUm=v7NfsIM'P)E\ֱ@uCue%[Sc.Ĺڱ}g r2d5 + tY~*mgθԆjmԅu )4YF23m~L?P<96ݫJ*1yWͳuc!^;{C`k[ve^`nőԴT=vLvn9_}PX\NK6U}7s }iks/5 5 5 5 5 5 5 5 5@E )e;ʚQ;5-=)Gkh6[DQ}ç , n2p?CܨpGAq!TOyQ/O1g ś])UQIz3L-$00ZIeffX8: }n fvIYu0 q1;Rh0X]^j)$r[+qFLVqn(Kn6j2!$XX8UE'&TN39 Z_^4K(g(CkorNĵָui~$) =ru5 ֫_YԀԀԀԀԀԀ@ @th\hU&<`}ls Ɯ fEj?Z)Z$z0ZbN .Me$j?reYg *s @T[RѲD58i,SL0L$P:(5{QGS>cQD`K{УClm?`L磜q*RT^$Ipd/w`Z^RYТ"HVf"pv|ksZHHVxNN¸W kXY=-.vN UOZhLEe0>@V>>,,T*a@,u7dU:! ʁ׻FL%!G:^OQ¨ƥߒʆ:`Z;"4*py%)SQVGA#4,No 6))}|/-4V%,"򨥍-l燓1x0F}ğq"joI@+R:9>mv .N]FLң69mdd<}s)]3}2i2^I3j P5!(S/G]gX{Dm[-"KQwSC22&ƌŒe/O %s,DaδL6 M,̯{^Co5UJh@WaڔH Ԫ41{m7O 11þ}dkȴ^["f痐 /^k{ Pk%C&<<)W[RW\j_}}y 92gΝc!>ML2.ݜ|/%s{|v˗"H xRuʔlu q Ymm5n.&De< TepyYbeaV^HLF~YLrB^;)0xS jA"k9S2jo3ȺULxډD&ӬBBH<,&@4ۜmѡM]"Ǐb2tt7&ӽ@ [#,8 +T^і9[٧0rQuGUƷ_FZrR`(#qsp)Z\doドOb`CIA|]QPR$P +.+A[=ؕq~p' ub(;ѵR^RcyS'8ztǎ8(5I 8;`^`=u xwpaۉC²ǖ`df’/}W픩 >bfj54cN~ץ/.(c2+vEm`+M#l5FP!P$Zd7|:&Ors?Z!y q|G ͮ}(lB~>jϐ;˫.!#ݗz͕ضoۏtD{[2EoߤY'MÇ6iH}^qg;wn?+j[1xZy&1bȐ5k.\A"{믿޽;#CREv_}ClKlݺ O>Ԫ,y i/T<_uSC?'ߴiC.Q o~gؿӇw?Zn%ҥOKoĐ.s={Ӧݢ߬N{e'ht`?:gr%>%55I^ą֯0#==(, +VnϞV9U( Zug. dz>%Z,RRك@D3qҽrn +ˍ␵i.!n0H$aI( kZ- mv!ea^"g_V&bp3Q(JUnKs0t[Xt]ZU\,(ƽ'DAM .e2y-ap悽S2`Jzn.tC'uq> Vkg +'WQ !u%v@Ď@S ZڃLJTWilO  *ݶo|0F.TWm2@&.4 kep^̑`WMr.MB9.8Ö.(XsZن߽Ļ́4' \KgVUo~->WyFvzOEO&@Umm0+0hG^5=}`Cy9^ZV >xCL<Nq\ya7 N'e}= !n>/3x Evw駗'aer_U[loUcɭTX@BQB{[0(aEܴcE!)ZӤBg0"۠--!Ap5*bbPJ5%;Y^ =c)V(`*>Zx'Z-W1 "'>f>*| }Nm& Ӕ]OܭU ڔb@IDAT- N"}lǥ ZnGm=0 >7'w|auʴ%{Є'/nHWNYϴ2/g_ @?̻m<[ o{3iIm5*O.з+o8=O_6bR SvA4+G&"oYDp9AywgsUU4>>>&Ę2I3&sǾ[jD/inCst.^|L56oF~_^Ç_b:ԲSoȵ4(K 8~r~jcupzGYRA,+V,`Wc#8+U29sQQvu<mڄAqHC?ܿr >w}%_T5c%pHM;v$?~7>`m}2h$[BO0V}hטn/8MsxU*1Ν;U넠eS' .5vs@KLfcu$D_H|9{",##":WWWO6KXE#&QCD-.d%7@Bk $$<&{"6EgLf&Z" [n.i媱2jz.@G7h:@H" UYYx,ܛSQBJ.DB\>؝' Y~5e!pg,YXLcA7{UFՖ Ys'7xxFK---@<p1x?!϶kpWjON`3Y90<mE#/ ZjSA02˩Za 54 f܍`7ox6tsԩ]/\nl}^prj>fg,]gK|flڐly)h e ԐבM>Dc :e՗xϛ$k |.4!C5jʢMۺ/A'qh Xڹ3Eœ;]eFO Lw74tR~dmŒEdR@c?3vJnP6ġ:lyw1wU|f0e1_,EO!jl]e>#KXh &n] l0ZR۲-?{M7V7{u0ƍȑ,Nb11\ͱl֯C_v.~ore]ןFL.g(#vb\̳T1D`jY|=5u-EMg~i7 :OI\Leaq:|sXgȱ=Zh19z\3D\&zcI[u9S/g2Ġ2Җ-M<ڎ@0UCK` =r N\lI+ԪMkZ*JqUhپ7\tk(,E%ҟkmMZ>8[~I9فip̽l[IKqɡ7u? ;QvytD-9ڕϩGtq$}gDQdwNrA5PHȮ]p) S5aPhb6lH T L3%Z?^|-x>VL.x9%YCڥw<7ʽNNbL<==1t3@VhH9ҵKWA\5ܘXi`Ih5tdZk=O\-(E]ͨt=|l'p_EWJ~+MV[D'e7]װe_`]idZJxo2Ř9:}Rk,՞ĈE*E)[SڎYtndltNV.:uCcJ1Mewht?[x||,qz(cBg@?sr5m_|DWp2Քر3gCaame5&]VeaM|_c?oǠEĤOL~(u6,Y!@?g:ְ'؆tܻ@GrJYW*?iSRVR)pUjS)yNw}(hayM3ڧͧSwS-`j 6,zU!L(E;'q[?ҏ'`E`D3 oi κ’AV n[?BIF.<Yj@VOD )7^Lj~4ЛKWg0vk2>Sz}xC7Gc>є:Bhx{{cwW;V<3WX hm,vu4p1dd5k>#a?"o^OٟPjKnXK,_xbȴvOzPHP/oaܸ):ѧ_ye/S`+:!:"BBS~素(u֋cZUk7d--zI|Ю\APlKQbgXX[cDǁ ^K^EEoU ^3:;ux2T&2"T+Fnܚ)rIp#ゎzvjZ"_-ЭKjx"Bɛ8 ^7 z F|eAXкuM^\(0Lrq"D?hOz55 MK7-M? q<&.z=ªJ>ûû'? ocnSˆ&{fLNh6}&&Vhl>V}:V3fZ/\8Ql;*؊}}{F9K2"@da9sd}C{bcǮ cU/-*r-{HdEY>ߡTaFS cPV.J82I7 = ׏ [7vڊ^V0Tg2'%%0rJOv3mDzG ڭjŶ1}9i4-Ř1D*K0˔)7 l- TgnW `=ptSEɫ5'cYL\fŊiAQ|> O0zAqdep/ [&Nv+]žu I5XSH9r=G.W [=4LIgn =3c69_6H9sO>5WOm 'RaCu4yZ%vde/^fϞO橳i==5LiA~()YTuuLZ_b %}z6R_ܢ|IU3)hU"mӧzyw +́4@]2,..VeQƶcœ\Nɀ|y,Q5g (*Wo{xx*t-w&.?CQuOP0FQY/G^xrƟ}R3Pڔ:MW:FMeR*TLjQS:5K6{\ܹS42S*-Cxu׻[ 6u`P'7]<)~Nx;vr?EՀvahz-"@UVP _6VN'CꝟNY4ׂ\,BTSUk`}y%LAvk?ڀN:zFdiR#2e%%G"#3h+,QAUWW* V4i@ߛNz8RŃ>$5cŐy pcĭ쮟,cİ9L $`j=^U]D7\u*3v&w>hmrXY5̐&/hW#{_UaR9(c̯@K- 洭c#")00H!.W%%On,̅Y 83,ˉGlP?L/Iw5|:~G xFP;ҌY\(!Ɗ^QzC[ 2uZ-ɍ/ ˖VK-ίl250ȳb70 0 cL_lU΀\qAvh#s˗/ [;S>q<3='bliTF 15ApaO1Xȏ$6VN?ݜFS"׉WaA5އu);y6W2 )w&ߐnnǬ!8(NW5ZJEAINlyVBTMCRؗU!KOTv)  yDA- 'Psxp1&FWZ MJ%p"XaaͽDIu=[һ7M7ehZSٚYc؊-M^#O7S[6>cuڼFLv7,Cq\^T]2&o6sgX7[#NTT$6>N|'kP] jO-B/#+_G\Z2̸`~S+ʱ/)>f9U#гg)7<..#eݔΧaPtƲ/MR!Q+l!08jU!Eeaw+kkgw!E5UiNx0MKTM 4sXs\`Zcu Gg>1uęjڇڵH!t!YўRGC۞~ܣ/!*".OVhAJ?2DZ1.[6s8::N' .ӂnBVEP7hguǎ@+>d.}Ҝ M|JՅ8F\er?S#eԓj pu}n4Νc~S $g[b)Ѥ%ċl͢m5v\q>%ov@n˺'\.R\כԵ=C ī1E׻%j |`1 DaJ>xhXO$^_ėY VKnpC 8FLb^UdC,鏠pl-I݆(iݖ@`r 0ۺU[⵽@]j +WL6W׹SORPl)Sk11pпʮX?w!+ b#J 2@DǜRrKj@j@_= :E_W q|\r7o: [؊uۉC*`Q<1?6B߸@k_^77w@ /,QrsNxK Z U(vjgnJU,7YxRW_J.\VRX+Igk>}0Shl#j.ϵĩEL25ۃ~7Il?J5VugY2gjD]~gc8/Y.&J;>>YO(p֛J'ԜgFh  ?I[XـMk26h56_|۽cfժV`K-s)ek]@rޡWj$#4=$2gY~TD' ԧDUZE?a9"`5VXcnAħ.\+TI>zTKc9W7gq]}ktx=(D L?m"jla]cUCh\ݩC_df7qKت QJZ?ߚ !r_À*ӷ!C+c #EAjhؚXPК Ӊ4p!҉wSO[ He{*MdK <8Fxμ_?~A<[9Y؛ba^eʇsb\9YKh@ fHmPqq1y4Y זjm%\~׸)m[3EOЂ!!aµ=+Zm4+>sۮjt0_QI.sE7߬/* +@`a .0a EELy5Yr L'օ}NħʦM!X9p[b2Ԯ]!ϳ `tXrQ掁?Ʈ\x@+ ߿[J]7H>|hk= H $Q]>VCIM%kMy׀C lhh1643ugժ3?`oa ,ަP),6۴ U|,YȢ EWǩ^ij܅b2Upzt+ܲkm =Ká\SBrgP5UVMU:EK*Ij6ʣ(Zm28UgkU 77ra5PDeo^l,J*'8 q\Dm7z֔Oq汰TBR]Dxhj'T%[_<k4Mo'yj:E-EѕC1OԴ$ 'u9:d vO tƠ1j uI 0+EI(Q_E}\X7 iL}h^~J{yL}>yW+'ӛ7٣kH:u>11`ڄKa+ ^5{b?(Bh'Cq¥j!ݻ Wwh+ *ʕK]`kqY8@gϞR'HfCƝw(xXϖ* MBzzq[) qG˗kwx[ 5LQO inN޼r{֧NǮp%[]02x[֓g Jj k; ʕb޼` b+&NvBIݮ[lzN'9c@ ; D`=+V_;J9P[drHXwt}> KLyfk)v=4ٕRX 1?u^.9c#2Ŷ9Ö̷p27/+ldb 8pYf9<'j U}:|_%Dk `<JW{) V[wmCddD1.")/lX5)Z*["KUWKO8T-C)RfTBiĒ2GթCW2* iX@~H}C6RFjpy???>qA&}p96-7Knv'Y_Ub_2Nvދ^F2K9%. 9?:ƙ Tu_4s2C̡A~RR*3bÇ +:SdĈ"Jߚ~rrrw*  2o"RM u?,B"R3ګW?񢪤3z~5ֶ`)e> l^-kw"nL?b(Jdzg-g;v,ڵ?MqD~r=>6`="s(?Xz%^{m Ñ^w|nIF蚭-vڪ=y@0gd]%ݻa>ycǬZ|]k[cÇܧ5k>ǤI ܾJxb6>eWoֳg_M9֫le˟^D3brK=3}N9,_Xv1v售_|$!CF="$Iy򳊽bLW2ؚ5"6V}0K|lo86`Pm{0(ۭUg J]Z&#\ ͕[PK|ېE@GfaR^8#8T$dU+@DsH v#sU^Wߖ@PSjb+8oW7[S1im 6=cmo" < @>uNC@󄳇/=CWH ( bxW(njjCKxINICڄZًb2aZ%X3єTҎ8Li[zPc]C1>АP=*~~wT>&Ej@ja5Љlғ8O܍[5 v"&]hb9 0:؆lJ5`A`Jk\zodw/96S JWc,])@A  ޽)u rtqhY8͸q7URM%mU/lʑcaA`vez9r 4/ 2V |`ehC=J+wuQK:uP4C唲]5kybccNSn}s[-FM~=MC$W]C_G9oe <284[A31kWuʶv8fNd%D|_6<Ƭ~O?FLTjhh&1ܻw Gx|1q``, J/_<˪qB+O>3jj{g~tլRZT֟p{?~bg=&OQQZbEA&{8`&d_ CЯPaeJxi(.+AG H򼈳.C[%0W +F?ȒAl T%{.(mʵyim)| sۓo_ɠeB:Y| !~}Om;GVԖX %E?YvDȿ+рKY^Ik+\uu]T/kNNN0v:Ե8﵈tN]g^M;CūMܡY廔+Ӏԡ9L&~߅*E4 J1MkZM~M:WKZ-ؼMZsRRRײrѢ(hkY vW 4^jAJq]]U&'ESTc' ` 4$vu-~+^q%`K~آ?CaQ WU^\7-5[)iܱE|{R_s cd &] Ĥ :`k1Pؒt}ZG-h5G;#ϊie6rr]w<(jd]iHo{,u'vu HN"Vv..oxG"C28SieM6V|@0b*jmȌRWYl9Vl%&Ej@j@j@jiĉլ^/G*x v'Y0@V8Jk BeU.ÿ1N "8U:} |8=5S4+mCŖo?]dIN%z ]~|;.d闖w U.ha]8'ȪSܑB 7XC>Yfj4d80t&*,7"5 5<4. r?edd +fKy\Fz)V$35}Μ'oVaDnsH H H 4W :xlo2޴i#6lq> ֐\95? g6TG)""3!fՖ^vEd.,GY26gV2skɒ[rG/'X`T~s,cE7P~y)cb \.](sjJh 06Zkݏse vUȵԀ@fq>2EidӚ^ge Yu>3"`׏Zzꨁ{ N%4pI,X(Gnt\q)Lv@̵PP'y1.PVS8 .AElqlJFvjd.MG[t6D[MEa!,(pV]П,X53) ]&@@~'·pyy\99!8(̻`/AVEɝ+r)zh[GSCԀ@Ԁ5^AVWiӥ ȫre:(5w-H H H  H~dc+ y@CC(H,'^{.{/? DX[2LD.st(Gkp`-A5cjllWc3.,0/x肭l/=]36|>>F  )tF8W=}>D+l'EjZ@0YuI3ء3Bڄ^k*+5b40koL0  .Z̹h@r$H H H H H H H \`OsXR;+c<Qm8u0.DZZ G.יl]Yʼnxь~nDK#^("L2]yj,^$i,ÜPVAy1!!.M^p+V۷ ײԴ1ZV$t5@][Js^9ԀԀԀԀԀUB|GuY+W&z]H$ob٭uhӺI0M NdU;)]boU[u!##Ϥe&d5\Nb/5qW{ UJ,X &QEz9,] D~Sٰ&j ҝfooDkں NN.u@$ng >i#5q:B".-A^WZ5]iJkzXʓ4p"?Pwv~׹N k~~؊Lۧ``2þ-рj3J0ïQ؄21DtqW9k%/kEQ>3֞ݎrB8;h?Ȃ5?AapsnBg)"542"5 55 A |5.5 5 5 5 5 5 54^Z@=)ڻv7_&YUay ga9nvBkvCo јٖSrVF{ݢȳ!{i^W>K!yyaԥH H H H H H H 4 H]Qy>RRRRRRR6-4(9 Su8lrf~8 ES&`]o~|u@61zFHӗO7DJKģQS0+ȏ^{5Reꔹ2U JKJ?=mS>(@ P/0u޽())@ԑ _W_pkw3(@ P(IKͱ[ o}[}.;~yS'ĢsV#R&`7fnL@VL uqXs9l'ǟJMܾ!kw3gXݽ;/<\"#R$X6u! Y՝ss ~ P(0>ocɒ%ַЀE P(@cW cB>u6jI,A&cU:e@jv7sn;n_5ٳj(N/τ$|][xH~R4j!bŊk~(@ P;2ѳY(s;@-xwX \y_j@Bji]kF_]*.뤎68֮j+81*>A$`!_Ɉ‚rتRl,#(@ PHg!W>կǘ7on 6mūxlgLz{юqʱw軈) X5{.7\ɮ>z:ojgQ%vcxHp˟B?5e[i:9l ̹2t:#kvG P(@N4ihkͧ(@ P`8qU_뽨 'XGfޏVûzelyNdtb}-aִQ|"u7ei3iR\37K_^tGhCۅw8c~6bJ\^d? -HMM@aS>ؑո [ ?? D} n> 3n[,4275T4h}'aL6m0x` P(@e[H YTgdGEdD]k2-ǵJR&.Y믄6@IDATl)'KwVGi?uEqC s~f;^@sQW85 )VJbCU=CVU (@ P@_׿uX,-pUCW^(@ P`4F' 5gR'cP(ǥ^]d^ѫyd[wMa 6քh.+!+'5/Ѩ/7\_2m|ȲjQ Ysȓ \=l7he"L39)@ P@F Zh>tn݊^z 7`2zӧOhv(@ HO&^TmLd;zz˚׫{ծvKitD+ 6ɮzIߋxwp yZ}SேF7ƒ͍py:iNꕗ_'xf P(Ν;g>mÇW^:1`VVVvG P(@Qm5dr*-0Ԉƾ=Yw\@R&*,(l2l[TNS!,Xʭ8U>b' i͗Kv*\EHV~Cjaۍ [0CkL4)@ P@ 9s~=[GтW_}zNj{;_w TWW^>655ц(@ Y@u?bILpg}}R`PS{L{֌;{qRg@o@+G`ח׆q `N(c0ٕ~G\Krspt^F$^ٽixa_v/S'1-Gmk3KD!$}^rr3$ˀE3w#(@ P YF<gt ~XO?!P(J}r'r'zTyLzdrS+V.FbV]k$2+*CwuMv5Iꋺ\td: g+Ѯ> Cjv-hXF5V]%? |܎x<ܜ]جv"A ¸m[H]~~>XL*75R{F~~EGNS hDwGȱ}Z:b:,Z-e h{7XInyTQ|(R[_aΔz?bhk?%俾{qEmt>JVF[fݬݞ?O(@ PFO`OM6yyyo~=:q~7[o (@ P8K_P#[Iϖ8zoD,.y&bt`+ެ-&%'qcU+P]5ݽr'zx=yK\\Ӏ!zIsX峐]T1Rq(@ PF@_P(˗b ǬYpFee%>( >`}k+ PxZ0K)CφP;v%t|HC&Iˡ7 PvMc6`򪴚*knpg2GJXem9&\eB >x#fG5?'zh}g> |Ä;m7h= cOYup}vc> |9.iS?~ӟƗe̞=x'o~;̙gyF&.EÇkA,qI)@ P0HO^Sw4cFsWGXþ*m@7 rBԛ*.w)h!R<r:Q<{d 6@Lg֛Ayg|l@ P(0J>S=)++׿u֧ PKt=ɓ=(@ P`>X1!ۂS՞‡v$GIbz.l>&\2{͉ڠ6ma4NM:AŶƽxj_ѡD!qUMr+xx P(@۷o b gRZ6qQP/2RݧTd$kwoFC=ªeBwІvoG P(@3p󖵂r%(@ PcGRdI"l!\X"cd렿:$-e@7د<MǮ(NJhxR)עN`RoPzm(@ P!/hUԄA{`2|oǎJ P(@hI0Tyv,t|5C4˂=vvb] $X ->ɮ>^xl'qHR3(W>Ў GaLrtSBoPB P(; P(@-5;̸.ϊv( 4ڒ7ʜI #I|h(YPn]e8#kQu>eĭ9Fz6Q(@ PD 3 rM P(2h 6@ɀ{ ,عkkQjAD1%d6KHn\\DiHJVC֙f=3!'㻞hl)'о_~c*5m(@ P)!*ʒA{??jnB6oܳR}{^ (@ PO`7(rz+8XhŃH"Ӌ+"K/aȚ?*WLw Q{1)!^j$NL-g(@ PV@'!jXM].נb} ;::N˄{olc>_'%;L P8އJv#-8kCHD3@j(hI*@]X,l/:/8)/ 1 KK G0laYRIiٖB'bDZ=UDBev}n6\pXhmPF5;Fd'G o8=ᜏP(>ZȺB]/⨌`JmGøDK\ɮRJn ak~͊ţ(p&OXF~y P(@fN P(IejI '6ÍΑ|q|4&';odW)t[ pGA8lK8ۜ6g98gy)6(@ P`F,hUGj޽˖-ѺZ<.(@ P#+ -!>$!Lt Vǡ\]Vo$o|1HƊlz|{nЍkzJ)^o(@ P@ Z׮] ^m۶ p^(@ Pvxz[߃>Yºj ^&!$+;sQQ튢*9z)$| "~X6CF(@ P MjoV|[Jn(@ P 5[/lXL)03fB@]ߪ ZՐuIM.rx,y |C&GK5(@ PF_к};7'? =*nܦ 3g=(@ PY /c+IsO -Y$'Jv#<2Y+φ2Uy !~|Ka(@ P t:]4_:X͛Ϙ1Y?RoR(0an 7Wݾh z׫L8ru3'J WAS^\CzQP> oނI)6(@ :/T%U!R;r p^G P(0Q0^zTv҅8mUBWYmG|1_ɮNijB"Ẅ́Ռ7(7 Zם@f#(@ P@ -r}G/yy,?.nB P@ 8VmçzZ&f5yb<U@FNv#3OI?wǰM]Cy2r 6q6[,ƲhA>p)(@ P` Xzך5kn~ﵝϽo[(@ P,ID<-,(^Qp\|%_x!8\ WBV-oz|q[//e: WR(@ 㪫BNNx |SSO=Ayy(@ P rKyKf4|5?."s"I$$wLv[yy?Y.Y=⽐J&Kw?X2v6PXF P(@Ν;6 [lҥK?~8#nyl/)G[aZecv.ٶ#'!kMu^ CC<{ro9XhPß%ԇCеnGc7vpk!k?(@ P)#0PT _\p~+hO~ /V\(@ P0NdGje֠DgӾtH~991J`^,ɩ ]"~zr PUXge#VZ`P;C\yhЂU>$KgnZ,^[pUײJ" r]Ӑ][EbPlFV[x\ P(@'/hqEo?駟 /={Lj~ ۴f3fʤdbt\Fl<(@ Pz Z7|3nƍ{1'x=>s9lU(@ @Rj66 nw  fQoiȭuNXq |~Tr:T2L1_F؈фS.aU:tBUou(lF_\O}k|u8*!a—wa}UA1P(@ P`~3\{ka V^I&!;;Pضm~ӟúuc| yD PFUL:VM 05 BݿׂF_+ڤ7AQkB 0d_(FjRnoI%/O& U-P;C2tj:ܑ[5*< 0?TYnF(]vS(@ AMf]ݴiG֭[Z|{?(@DtM݋-Ed=т&' FZmɐ2:5PU- w+:uJÁɨb+`..DŌy2:u 5l} zd D㘚Q'gCSk^|A P(@(":lUur͛7СCpɓZwu/^||:j|(!pyjZS.b 1?{ܘ^nO-aiIkm#n6W\py9 ZV@|E4.WB-6{w϶-=#lنOz fe_ Yb1f y{n8@aةފk?J ?? D;-``6Lo3eոH YD#}!c!q)@ ƁS6*ׂa̩[Brۿ/@#;ҙ*2TJ$%HLB>G3؁cxvڵDuz3fc&P8b)Gkf|[FeQEdz#ֳ7dz#rvX:ʽ)@ PH'#eqS u©5'&K U'$UDUESTQ#YQdIW*!k"u&Q0ʄUGu_IQB[Y*X- hI˅(@ P)u8IwЏ,$/:_Tp\b+KD"#܀xD/`O:A[ȖS(@ P uε`K(@ P*{{v".8x9睏i PR-.+ĿTYVYLl9}O(@ P)(5/ D Pi{6\ucD>ҥ#}:CPC=~G^})cwf^LHhVܐ(@ Pc-uy> P / zzZ5jGB)/t8%K$P,!״-V'sYp=pk~(@ P@* 0hMū6QF@ !5/=|5K=VqH=ֹ峑&ʚ#C S $j YB֫$SuK;anjE> :\(@ P( ZSڰe(@a cI|oNޒz1@^ >8wx|DL0YqF|m[#E=!ZRI#p6(@ P/uy P  Fخנw*Xŧk0zsǴ-<(C7aR?xvz P(@ ֔#O P(@`:z<2(@ P`z}$5-̟?Yr.O4]wZ(@ P@ 0hMkSz xd?ڭR5` H^k[xq};ĖS(@ P` ZM(@ P%cyC+|p+I b  tjKAt:=͘ލpmkW -ߠ(@ P@0h͔+~P@ XPu z$a'2czR@ hX}ÛR*@zہva3W6UXW2:S3a5߁P(@ P  (@ @g=v;IjcRu0^M^=bk3YHy `#:dzy&w}(@ P Z(@$RޣJ:[nkD!v^FR&h+ fm(܄(@ P)53+{E Pi$c=>tuohX͕JȚHA+!+ZZ~j m8нM(@ P 0h+)@ Pc#c݇/=XsnlP``-d-f{ѐQ(@ d̽(@ @w=փC F n<5#kn96t:ЉG& Q{͙,;(@ P(  5]I P#c=^ !XIV@bRL݉+/F0; E pfefG+ P(@P껤jʠk P( T{݂.R&XGaZaR(@ P d)@ P }zxW@~99Q~'Ȧ.[:ۼxī+P`q)xL P(@ d֌(@ @\t C&Y+7ulk R_졭k&O P(@`>|(pVj=V!pO! c6I݂i3ܙ%禓x9zwrTh(@ P/5!{@ P)*]U/XRu?+}NL8=E/ۄo/WDr!\$8Մ (@ PG 0hHI PZO^;$!+-1㮛a6wPEQ]Su]CWuQ>3O P(@`Кא=(@6q? o^^Y1ˠSl N ~lO8鰬!+.fz(@ P( Z?oR.c}Ta]vI]O⍘:w-)0vkqLZ7\(@ PHOyj PH1ONnFDoCyk-CfVTB{rR(@ P 0h+)@ PCx_ww?R`Q{}u%R@ i1dM&P(@ fl1(@ Z&wd+tPpE}b+aRl <\wT^NflB P(@ ֳ(0QzU#9 Q$up,=K?V %E926R(@ P u/uĚ_~@0T?nG P(0~:z?az, Z:(0j=7} :%1X%p*g.`4bKQWZD=(@ P(0껤jʠk Pj='p ^@>A=- g~f/\s'S 42=VS(@ P Eb)@ P`$G͖8LRrcY/]k DaĒIPXqB P(@ GApԸ(@ dZ] :| O걮e< Wn@gϠNE$~ߋxao~{a5p]bv(@ P a(@ P`z\#t+i)sr9VX6v(0 PZ ?yw܀D gV~|(@ P5FS@* X:P?ک 몐 vGJ+b:b*]3e:!C(@ P((@ Zׯϑ紐5Kh!k9Xb=C֔bl`M0#m(@ P8 p8(0Jn7s-0j^=X(1\тE Vbꔙ= RY&?#QL2BWrs6 P(@ L82K`()<3l>rrqÃw~=zQ J0,Z⢲`o2V*5W _{]v(@ Pi)5-/M Pj s(^EKQR">A: % 6[]ΜC)- ?G$A,kvE~n3G P(@(u"^u@^`Qr[uSnCp&Ø!X|h5g|xT&pSC1<|HA?XީnQ(@ P ]˕b;)@ PG (h Z-Vw݆ɶm-pƭT1K^o~HiD"PS}2ug!kJ_56(@ P`" 0hW}(nU%"ށ`]ax@@RX c\ R4 ;{6`fE;u*`*RvhgN'DZgjT c/ SV fyN.1 hl{!ݞIZ6wMGv!E^l>g !kUG0/EfQ(@ P 0hoP}8VJzS?C@Cug30xR&^x.QAL.'v}ϻjϬ v6~0sZw|U{MjǞjP3@5N>=LfX;wǍEȁ͖B} RUنC'%{qc6O](@ PsuނtYtI P 0zh;Hت.kR <uʂpk t5݁6[Dh9 -& [ˤ=2&9iFQLd}Bd}݅~+AKk#A,zx g`S*N;m]81(@ P(19jʠP@ OCa/Ǵ ;m<(h"rCxB~(\rKǠCPiƻ?S?;-jU*Q`:f Qg".#T%3ѧvg3T(}SGÖNYP'AҪ}>\;\,2F P(@1`:<(@[1[ګm$2T;DmF˩ѨHm @UG  t2T/L &81dR#5)KT[jxJsSL|FZ Ϡ࢈Ӂ/{ڑ>G P(@ 1(@+DK NQŦUn-5SO_tkV*: Y5ɣ&#ରKH댇4-f6F<@IDATQESKlQ9Eޗ}G~>Eba%`_qiOJ P(@ ֑(@ h W$TiF ABUsqz)M2KI`_/k6T S-2غ&Q]-(0jD}[S(@ P#%u$y P`b HQDs#j"hJ=1bw* 2ԐVŞOއE58k9UXYٿSgbڲ )(gP P(@ Ptk9(@Hz?Nr˿6RUsjIT& K<8L&LPD~n>r-Y8 ♲Y h{Q9`o"9Eۆ(@8AOt$thQevCMfPc+/ׯԽl(@ P/o=)@LtjOW*A[ud顪j-$EԪt5pG P`B(0|8Y A 8UDxu4GaN(!͓-WKvH(@ PΓRc& OP;Q$PUG;{\g):F'5TcL[KԚ95H 1OD @4K>liFGJ*c>i9ǻmش%4< .#S{/8S8M[:f91jDW$eZF[({g(@ P2JAkF]Nv\ @DFkPUcWkW[Ȏ۵PU 3*04Pk] C$N&.>OXP)-ΛTaRR@GABTFFc'V\b~rSg:pi,Ir瞶Dc(joR6&segl& |=Ѥ? el@P(@ P fEe(0!Vj\Bq$C8i9:U TBU AˍdU\@P5_J!+Tž(5<=oVoug֮.z'q!kRI )|$dh<q 0+FddCu(:aW+>؍XXFʭQ9E Q%.Ԓi][w>yosQҧqmVuj?z^?-,y>ϱdŹXJ[Sofj)H!t.wLp[ Zp[:y~ʓ,)ޒ(@ P@ 0h.Q PIBՃn`; QJP5!7$ȋKj&=9Iy/P%T,.ȵɟo$N, sPqk" ,JܷHɰ G+iڕHںSl: ! K",(CzO<|&[tL?꓎H ^;h_Z&agYK =l@ބYzY֕7 %4$V&<~ݾKpZ T;Ukkңq^OjzqT;X1kuo/G^QC{jz=R, `Ԯ7!elȶ8PY<<[q+Ӧ|&~^$@V4z(q@'#Y>:w(@ PR]Ak_! G}J"2`|Nj^ NtL߈!k_a(@ P+ P`jxZwu:Ì]fۆ@[Ο{j%VŤMA{v[O%V`P5[X ibO+R3k7 @"C 1V'DPc jԑ^O$NeX[47M{fS(@ Pc̳P fN_2-EQE |\՝hFuɒ{ :c!@RO['ʙP N#qA8   c2RF^ p`t}bՅ=SQ vucOHƵ7V+ kܸUVTk5DxG`^ްA[>^'gN+fϗ\b3P;y_@@@Zy>8͚ YI tjIgq̫F%%U 0#vusz}E@@@`LhB 0Ns^)JWvH~DKq jn^Nt|dϖ!@ijB0O5d&@@@hM#{A g"ţkEbmBe6A"@5gL@WGu @@3Z̥ _`TW(maM+-0) li/ k1f.~uSHʤl   ꛌ  KOG1VgivTM0}2!@f /)ӌgkW/Ѭ:A@@9p)"~HDwMCG0#/9tgl]FPe_L   #@ut9*)ަ=t6+T-_SO:KEyΜ&eTRd\+:E@@2Z@kF_Nh:R[]ۋ"*v4+8S+&LԉǟP(N#!@n?z١% H8o^@@@"Mqh+r 0}_QiZhvxN9KK!M@ yhܫҞB;yѠ)=@@@2V1O|%XF >]hMl hFh^ch{%eji"UVf sV   @ h O7{w5bX~Ld; k>:^ZWqsK#  d-Z3Jp :۵7QigD 3t%Z0l9&m:^thc+Fd8*   |wSޱ4_8[Vx9g8o /?ۏ)Pg0rir)   0Kr]MWWKA@S[9st)zRP~FM խ=;zuQXM1%se0?jŁ@@@&@uh~l@ %n4)O'Y=gN \Ҥޢ.w.|L.2"  cZ@똾.W>m@d]TӗW WI(7#0BƟ֭?_pqƜ'   pG?~oNl(ѢuŠS̸U1ɀNSn@@@`L hB@Ww[AQJ'x_jH&i1}>ه@@@`LhB@s[n~V}\Ю.GuNNr#0*N~hn nqT˿:*A@@@FN@Ys$E`ჺw`A*-Nՙg5x(سOFP#= 贙'R  S3/H.FL    ]߼xCXnE]@Vc7'QyӦi9=K㋊sTb#  $ КHV6o1}@J՟YF 8  NXꂰU#   G@kHD?~mU0"QWs.FUF8*9(pϕÅ9A@@@ 0_1#f.៹Ap*uU_$Țfgv@yf]fCڶ遲   h F:PYGDguOԙW]2 @h6=̠"? a9    :/*Eu׺h|k.]`vD ݪ1GC}4+yZ1a,.   0ZGScjۿSj蜩'kMא ܪ&#RYWM?S7YhG @@CZŤ(!{mWg0c":o鹚8y1 q=7u:;4)o[Z3@@]sLWo :頣ϼZg1 gVlX%#ҙsn:lĹdӕPwi֯z4[hN:Vcy#Ej/.SY]   @Z!#~N}j :ܭKkVhr:  d2gxN"|oCmmXHZiqe'}ˑ:3Nu;}WENM (pA JK_cUvjl=G?百~T%'ݙYzoV OzbJY.>lϺw^ٱ0Ǚ\\KϺܳŏ_m{y%_O^~˓eb3%һQV]ڷqQLdی]Ū),    !@u8TgN <{z]5SǜIYGOk[zvLY>Mui\sDo'qxֽkzi?ۘA&+'޳'2ﻪ;H]aX~|I ˚YV195hE3Wvm6U^PZWTAV]kø7isC~;wlҋ=zgeZv.7кv^*k;S&|2^g"L*im&O97Vy6sA&[L[ծ*lLpjt#zbJv{ @@@Htj/jWeb=+uWj1qfUw7H];=5r_(_}4|_TҰNKԙ vy&7~1l-Ng0f4{o"|Y69iN;س"RVOlg m'q3<+H0[י&ն-['4kwFsMuщbV,?AgZaϴb\ٗiŤ)/?W2Sfv0H{+ad^Of_A@@@ UQT#m۶M7x}Yuvvj͚5~3g&-`ag}%-3S<]2y:?Q`]&uϖu0Qs]48j~3}y{å)ԖF=ײC3Mim s7@hRX`"- 4m ٗfϔ_T" h gOv+m lN *޸W:hV"   0\?\Gn߾]VҲe˴~O\W֫ɓ''U믿^˗/=ܓT~2e@ ANfСK/y.%4mݝyxv:ovg6Oju43H*gM/Oshk"@K̢i"lߦ:8c-9}]Ҟsg-qkwDhI* aJ  yҷaG2ؗ]v^z%mٲE="744h޼y:tw:sS*ٗZoW|I|UH@6t44ꖧVu:F'\e\|ڏkICW*Mi{̐U˜RsЋ>j4e$0\PA.7@fM(QduRS~iG(p̽wyn5;55hPiږnjpW:t "3JAӿi4z*ދ`TeF*7RKErUR:w=oXo=%MW; G_AV^F@@H$~a7m?~Zofw}i_niiч}غNӢ[oҫf ;Jycauuu։)[5 3uO3MxHjvܯKP^ߏΏ_PCij/_%hho~Mз|3/Va;jZF[L'<4f L^@@@iQ>z'tt">s@kqq2Y'u^qn2xH[Ѥ8cN.V?jic&ʙP=c~oyNyukq{?x:*MLiɾ)7o+h;ziz/4RK JUVR8AU'n;3fR"    #,@5 ;v&M&N|ƍIiY` G+*.1ύ=m{oܥ g^9І= )Oe ҲredgwoԶ Uda N/"z63ǵڌ6⋶u=-E1iVwqa/ЧU_{FkPW~@ Y Ӄ;T[5^=6Gvk;DY't'f흿*V'     /Ip8pedzFh߿aYWZqfTyluB{O'oҐUc -4GOmG%-97:ۯbۧsfn{>u̓*6C<_P}_Ҧ=*3]uy[3_?ZMy:[܀nyl>{f@RvMi/Umy&]zs|X>Bau*:seÞJm@멑:ȴJYUUUw੘~b g@͘E@@@EIչ󽁱h}*]@dCz}iaYJs!)jR{h+J+TYR3S(3#&r~1T3>>rt{yXM`c@Mq6jV?x>hߥyR9%nM5}V wYPEErl?5(2    @ hM n*7@Yi9<{6eQ냊x ?nN5˶:ԳkpR82ɴ5E r).քS7{Yәk.J>'9;j5444-tZALkfLwsUE;;UJ޲U GB2׼R^fns~I"    @ hM/\Pjkk=փ#fZ|y{JO\7'ޥyZYwi)/xamj9rHujh6a:56M6:j6H;˶ m ڞ? ^l7O׭&0v̀[f--lP5 GiMa&. h kӸR5Bim9E7ȴm;m!.-uzu vW}X͸SOf@@@@ К^rz)}ᇚ3gN-m.<#1u65m,=BpwV˵,-)v VA<#571}v5Iue[ZMt6K;ݡ.[ z쵁& v}t1 I&n2]OyN L7&0gA/(V Vn 4޴dd)f;ڴ.WoYMZzlw˳Vݼ    @ZIꪫ|GO?.˜5҆ A]y}҇k!쯿XڨfA<h5Gt wL!2i:dۗFo#ӂEOV5:ֲ ဎM;;Ȗ x~fmfѾfC+ӍA^eMWy(*SQش5V@mEQ&k|I&-1A|ja[\T^PUحn83_,.ԬC@@@H@Hi&`x3%+kiӦM}85w\{ wu⤃;{L_2Aـ lS?#j45ŴmsL?+m˚ )^dηeA X;MP#إj32֛f.|uz*]4?!/ Y`ڴQ4g,nҤj55پR EE}Ku_]MM:;mwdL TU@q4Lb@88-6ZZN&f'Ck>{7UZ'?QEEj޽z䑾A38ý/nݺtJvժU*, wX1-MS,2SBd d0Piؤ.}B}Sbm}v5ҥ` 6~2g;L_/';Bf`o.Qg2     hɓ'-ZohŊn`sq&N'~A{nfw6s<2f4zfW:MGMMrh1-`LPVf&=b&0iZv%ЭO cݎڃwcZ5ΦB-     hƳfڴiIub5~'TEһGƍs_Gۨfӣ/ͫM ]wj~]Ot\4+    $K A{FN-8ҩk;`o3!    -Z"hoWhT3hAg69[uL1z,۵C@L2 s)     0|Zϖ=g _sǜ+*Ia@@@@: y+racR4@@@@`h:@@@@ ZG "    x2dj<@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xB@@@@@ pɝȅ    #,8爙|ϥ"@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@!ɍ    @ (ZӀ.@@@@@ xvW\*@@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@@ȓB     @ "S К@@@@@`1StT$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h    Nn@@@@@`d( G!КDv    pdzL uR     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@ȣ8KIDAT@h    Nn@@@@@`d( G!КDv    pdzL uR     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<Z=$$     B@@@@@ 02JQ]     @4StT$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<!O      @ 8N@krNB@@@@psL uR     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xzHH@@@@@ hEn@@@@@#@CB     O@?/r#    @@@@@Zy@@@@h     ϋ     G@@@@@@V^F@@@@<Z=$$     "7      !!@@@@'@՟@@@@@V      ?ȍ    xr:кm6]wu8qt5hǎ}N&Ml׬C@@@@,@۵j*9rDׯof^Z{M򥲏믿^o߿? @@@@2[ )Oqx.K/-[=HCC͛;Ow}we@:K@@ Ml:;IԞqM'TTΦSs)SggwF[TUU#ry*(s˦ 1̦5VSKONhݼy֮]7jauW׿#M`g  /r /;uv]cl'|~AӬLChjj6c dvm?Yƍw},c}v    d@NZ|I-Zs97MH>b<    d@NZwyleҤI+7qD7mƍu GG@@@@@+fdܤǯ곜}!      9hs/X~whZGGǠ5D@@@@@kaa{\.7ҳ.6!     9hrXssʵi՞u GG@@@@@… +V[[rtӖ/_Y}y@@@@^PzgrJ=S5gΜ>;ڶml 6c/|@@@@`(C@NZ*};O? /  uWI_H>r}ͦ/C@@@@?YW\^{M6mRYYYx≚;w޴f_.r R@@@@J^oY6yj7 ݻW7tSyghժU}#l˶Nv-;    d@Z'Oh---Պ+h"7j[N8ϥD"nPOYZfMtѝ/**]f@@@@O gȾK#    @ lL     df1    d     df1    d   #!РġdͥD@HyYԶmtms&Mocr ~[CDk׿uLDDͤ~Mo6'*-ç?i~ SlrG#w^d>/2=rꘖί~+ti_q=:~J:mN5^=dqYrDXYX3s]w~֐)@IIIt+:n-I $s+p8+q{ȭEDWWж^!qRr^3뷾=ԯʹi L2Pt2τ<~Mb9u7vߙ>s 7xN[n]J}d=ozD&c^~/bnIo]g:S+z}lڏ|I>|.e8766Oڠju ŝHz's"ǵm+iƍU$)y[o1P'w-}\)~uw\*?H~/ _'Jj{eϬ+P. nWH`ojuڻMk[t}g|G})<|S*9mCѯaþ'c2ɔӯcuu[?2ζȖC>~ ~6bGz>Q > |(.HzVt։_W_)4wMH3}ײf;۳뱽A9r-u2 n}- _}>n-l=\t $kq9ӧOw:::n\@/˗/wjkk{ӣ3+GSW+L} 4orb}ʱ}G_Zg?`i~LˑL^NT.\b:':Rt[FQdM^l9:B!~v}a{8:er>߯F~4}!wT]2MTt ۧh~SsJ,d@@6!U1SboC_LH8c_}݌Z/~љ7oK/%G.gHT~򓟸oLr?vpC"+=)gv:7P}{@.ɓ'}G?tJZej_rD-tmI=?*3[gϞHY{@eLЏI6+ӯc0(~ǵu?)lW'5w.وDeJ}H;x*e$L)@N477;u~S*2JÄn׾~֒/o[sXNB\QF`eĉ'ȒN?$B֮]2]~2r5|x2?ţ_pZbL2˴hwܑts^J^t7@-؟!fw>Ff0"`{7!ofTtd_tikg~/icTVV&߿?~gy0r1{ru4 kzh|G3~fCFlWk/S~O e<։G}TWc.^T{梺mdF .g͚5q2~mjr;Q'c53Vl_o6\Z f;&؎K."m)o[cu=L y駓{zŽhJ=\D.Q38ţw:ݻa f_᪻De]T<ڲ4>^h>{@ekI+ӯ}xΜ9mE5?wynݵߑS6+S>~ }6rZ~O rƟ:q58}zu=oD7,/ވ>Rq`?V/%%~NƋ ?9sy'_mWL $k;wn`י]u`G负gqg',~++}Sl=K[Cgi?ۛOh d_ᨻDelglv{E`@y,C*ucI+S)h}ܻw/1O=x-Zַ~/uϢY6-۾W'[?13}6blgg^T>/# N?gw6YhD7,.ڈ9ٿh>#zl=>9nh091۶msDQ͜3Q_W8zŽomJq[9WC>#g;|2L^NTv;/;G?4X}+h]bTqMh}衇Id~n43C>?>Gr9Qs~]*JO]zr^'?$/ˉnY\;uXe]?cf.l/pU{3<$}6Ρhv@1Þ,y.Ly 4qSu4Jz!$Sr`1O{/On33/_n3y9Qm[6ϖ-[<Űivg?Y:>G{De0Yh>lWF?w6@ҭR;CQJ062#=}sH[ TsIN@/]N~{ aȄ@Teז 0E;wnÚ_epx>XH^SOu3VžtD=r,-e,9ՀU$+oxMe a6f:ݟI/N 3CF)rT7Yr{?sџ<r*2F}R17o9WpӚ\}{QlWƵ0jiߓlϴtՇƵN{Tꄭodiz^heg&.[N?P۷O'6e|h4 X#;ܹ 4k,7tYGBr݌&cڵkhʊM~- 7Яʣ,~U}0~>hZ'[r`W^qW_Nn4f3IxF{ꪫC=a1ёc3$c{+6=)ɔўGn첝fl˜bm>bz>Xe%vjeҖN#uFAlDg{@\;wW.v}4m$*gR6zI'2>~> fc1"`/'4s9+Vp._wuc6}Vu2)&7So~󛞍숧+_g =58mx;ف&%ع5{Z^%SGd짾=ԏ@1-O?ݱS:te~02;)_LfѢEIr{G0F9hzh;ɐ?.SNu.uc& VWWk>du_ccaNn2455e*744YΝF8 1nL2jʿ~3<5| aہKccѿ.] k&Nh/_&Oޟ+㚄_: ^⵿1X7lN'2};L©PV~\K:=F5tLl6Qkjj#n 㣤r{{1쓯aܿpyg(88]x.ߖ8ٖIJe?"Gsɷ׽6`I     1 +&@@@@@/@KpD@@@@b h G5@@@@@ h@@@@@ZcQ @@@@ZG@@@@@ ֘pTC@@@@V/@@@@)@5&@@@@@/@KpD@@@@b h G5@@@@@ h@@@@@ZcQ @@@@ZG@@@@@ ֘pTC@@@@V/@@@@)@5&@@@@@/@KpD@@@@b h G5@@`_tA_~u֬CeY+---  jڿm۶ImmTVVJ׮]J.\q}pҤIbŊzd  {1 \eʔ)wތ7nK/=e׭[l1l"y۵kYF.odԨQRWW'Ƙ'  '~]=o@`;wJݝffXzTWW XQ5HIMIM&r 졇#w\RqkrG@@ Z B@ Џ>hټykr%-t)mbf5suܸqou[g}r)jժb>  P@Ĥ)@@X]MMr!'veK%-v%y1Lj.ːiޱcí_3$@@(E2  @ >\x݌V:~ׂvkj H  +@|;F ȍ7(SNu*麡Qή?}} tC'1A|Н:\p[@gbjKn*SZv\veҫW/9#e̙{k#Fp>uMԱcW_}TEWnf~^T.ū*֙~ҥ)F7Ҥ&LH)ofaK1F/5+=GT>N:F1(9ܬaÆӝo,J_P}8" E_y"! ~ npj ߟ$ռfW6o|im4ȯ3gUW]njcLb>#cg{uW^yBp>gҤIFqMcc˳AQcAY=3vˬXȑ#].6@жNl2cSO d:;w{|饗}ϹڳT@Lulڜs9%KKc~=Θ1ffѮy%%QQ{Z`ARVc7sT!Eb;lڴMgaX3k֬\3]p;Ğ; ;:O^2ӏ#  PlzI  @ s޽{ebk%jOUOO> PsL 'cgy.QkGάuG8O?=u}h?~|RQ]uy10@gi?-c;ȸqD=3.[ֹMl?JB?  @1ZLmB@Yow3@u_߮uX~n/N 9;׷:S|=v}~G7f JX>O>Y>CaYmm0L}sD@-PO9! L}5'|2L)f`f~tm YgڵSS_SW5;}uV& fKq̫nJ&vO-ܒM2g@@$@Ht J*mn%K.nݺ 7ܐLeڍܐ0֙}QV/]Ad]@+;rjjjܱT~;AZ[ok%nijjr'L{G@@b h-4  _^~},:pi]Oޟt3ф?[gipN7RYH]+Uv7n۷KCC<2o޼lܓU-4_N:̙36[vOcߗӧ˦MXO?L8Q.`,~6j7|SZ[[cǎuݻw)tA  rI  e"`4ӦML_nl1VW6\h.kYf[ZZuqu׹> f k.cg1Ѷ8S66iz衠΂ f^ݴ̌?>NQ͵ȑ#&lY9sMF) g9'  @]@@  ?ʞ={SlٲL0MLccKN:h0p͚5Aߏ??5(wךsӫW/Af_=xb3p@c5C 1/rJ?L)#^0gu1ψ#~}ٴM-1S٨cv sN8xԴjߡC]?לOzӷ@(@~"!    `֘pTC@@@@V/@@@@)@5&@@@@@/@KpD@@@@b h G5@@@@@ h@@@@@A0IENDB`CGNS-3.4.0/release_docs/figs/C_gpfs.png000066400000000000000000006115421343724673500175660ustar00rootroot00000000000000PNG  IHDR=akiCCPICC Profile(c``RH,(a``+) rwRR` \\À|/­+JI-N8;1V./){ll0{]t NO@wjB@6_/cJ~R$ (I(E% JUKQ0204a`;D@px2A!BlR?1^: Sbj  $Aad2f` H<iTXtXML:com.adobe.xmp 1597 896 =@IDATxEg9J8$HTrC$* `@=QD S; ",$qfg',=|fۣ3U籒@@@@@@       @@@@@Alq@@@@@ g@@@@@Alq@@@@@ g@@@@@Alq@@@@@ g@@@@@Alq@@@@@A-[ɓgϞR|w[Cʕ+'Jnݺɶm&@@@@@dG޽eժU2c ٻwo>uVi޼>|X/_.8qBZl)w.j]>M@@@@@@q+- 2UΝ;ˢEdӦMRD SѣRZ5i׮|ᇩ$]>Uc      @Hl=#^ 99Y̙#w}ЬbŊ=#}TVvvy@@@@@@ |ռy󌘎Mr?Ɋvy!6@@@@@@ lշ~kj׮F… hwb@@@@@ aQm۶̀/_> \ṟ 68y.4     -@âڷo5<|SѢE͡{:Y.4     -gW t3=ty .ŋ.k_+W.2Ν3]nw@@@@@_UM^%hwb@@@@@ aQ*Uʀ8q" ܩS̱ҥK;y.4     -@âUۿcs]i @@@@@[EմiSn˖-]FwhO       @Hr     @,4#=bSD@@@@@@ AD@@@@@@X  w>"     @H!(   ;&M$:VZO=T<-[|yFǝ265k&-ZU,-}JեpRHSO>33fΨv"*OJJKz4 . N|$@@@'˲eˤRJZn-u֙qɮ]Cfq&ΝСC%%%E~mslg4p ظxrӧO˟'iժʕKNjw^>}-[Vx2d^mj駟5k֤9r: @r@,>{X)Gޭlrfe   a L<ٌrYlذ!Y ,6mHժU%99}~ˎ;ҜgϞnM.]*z~&ڵ oGJu~9 L9##  ĺ@=hѢqF#ZliF sI5Dĉt^:;]#;F2m.\X'+VG}T?]T2u9Ҭ)ٸqc߿ߵeRu@2CZ$g {O@@@2"`Mѿ _|TX@<_gС&zH*zFN:fXs{ \H |] w=W_};vc=XPܳl2W\q˄>| xfΜ{u֦޿iN|(7 D^z%Zs ;wnSc.#Ats:JK֭ kGzNI\ME#-[Ν;͡%JfE}_zǥzfڳ> hfQzD=x戙,h×)kfJڵee#/6.Sh@ OF8@@@#Ю];>`oSi,(]XB3=Mh=CҩjԨYSnWNAoɓVoN?LZ'tČr9#-`k.Fb~xf-K5TB50>>^t?/:;c0aBu e]B]vˡC)r%vm3WCLO*VNZfv@HAq   ȗ/tQN* H< O2E{1͎>0}U7ߔ޽{݇#GJbbb~j^EG*h=ŋ'{]O>,}.o6#Ή6j[@GYoE-=d颟ѣG5dz%?%G|٬Pʹʧfg+`H=B6@ Y߸dקf;̵!  ̙pB3sJN̡y\P~M;_ V^lY9pY:O}r̙ҽ{w~ndRpa4ihCG3f͚E5hm뮻Ό4ІgϞm1Q7nL5cذa2vXYr9'=Ÿ/, &M/vY]W^\Ge|;^P!3Gu1x=ɷ̸h.nOCz*Lqe#=طiGu?f V՗֔1hQH(R-ddBs} #  dShQsܹ4Uj~b<փn;Mu#kÆ Yf;99ɷnQ%$σ><9Ϯ_߭)2lXSxڴixktOJJٳ+*k PISݣ>jиqcի=b-o\#Μ9iذiZcMse=p@Śs _)m)q+HdX͛=<d'$$x֮]kWɌ{m۶3p 5ôevܴ}؟=wwyv<L>by4 ?#=;QXƥ   @ S.\ :_tqn,٣2C {Ӽ9t*-]yf$Gj՜Mf;t͇!CS( O?${5gլYӌbK GAɿM?ڷo\슭X-bA ȸqDԢVZx"=nOO>|r\Le7:W^ySiʌ{}{mZ)_<ϊ~iE?͢xʔ)#O1}w@K#}}&nCt\    Y.`տk4-WVXkѸ5H84x 4AnŢ)}F@@@@/gҹw      @l Eo@@@@@@ A0F@@@@@ ["     @`8     %@#E@@@ K&M$qqqi^j2?Si|=oǏ;eBm4kLZhXP$$$ȑ#v Y#@#ki@@@xeٲeRR%֭[˾}dݺufܸqk.Сoܸ߹ssCyͱʞ={H"NP/^}eeڿ5i~Ǔu9ٲet)1blܸ1qv@@ k_ڞiV!4FC:@@@T`ҷo_Ylذ! ʂ M6RjUINN6#;| YFnvٱcoku4JѢEMݭ a <^8C@ ۟I3# $@@@,УG_k7lRʖ-+7o˗fYfIǎe`3rzs ;{^c(3 * zf@@@&PP!뮻L4xr%+W6?3l?o޼Lz̞=[/^=f ki@ 2u>u`t@@@ bZڷo/uԑ_5ڵkWVMR޽[jԨ!NFRwȑ#ҠA(<[Sm@pnvt?fGNr   h׮*UJ֮]+JWS`Ǜ5=|/m۶~F /`νprHKE߿Vd@0z E1@@@r@פÇ>NwvuH &?n{e˖ɓ'@8q1yW,}XjԨ h'Mʕ+MpIG}1Yw.|Mӟp۬[5ʌQ;ҥKw矧;=   tʢrʉ>W_},\Pt$NICw r:~#%; b&;\=;wn39ziӦyJSD?~<ձ@;@_eG/mk-U[Oy|ə3gLȌ6HցC#S>CnXu+Pj]苄D;7rG,0Wĕp   AzΝMYfwowK'?؆GA=NgնG8A M:;eF;n=x뭷DZ7o.-2Ўic5_" @vJw!   {^^^Fv{kxh)z-5àpRf+Pf݃[nEtzɏ?hׯ_Q9Vht { {    ڵ%J7au$ԲeK)]X,kr4hwQŋ) ,H5:;?Zۗ_Yզ= ?3FyNn 5T*j$揰FD;1Vrkz\T   ޽{ԩSnݺfp}|A2e\s5AI&ygٶ6Pϟ?>}:U_ZJ6l(==yѣGEchP{SVM#J4(i?H }$}(QDCa@@@ٳ\p!U@:ё#GL@ *#XѱcGvGv;8uJG[C {!v| V$7N5E|)~oqohSt>,_\~W)_hgyr{iv5 K&t)U7z∽bO#   @Ni(eՈ@sp۟Ip'&P@@@@@n&vt @@@@@[GTD@@@@@7 pݡo      A(     n C@@@@@@ laSQ@@@4iťyժU\SO=&O˗/_޹ѣG-sqLf͚I-B|xF #Gخ7{RR?^իHの!R\96ٳ( r0 *U̙3ie@.A%O   \F]A<4 ޽۬Qq72ȑ#Iȓ'.>t5}J'!dA,Ħ)@@@"Ю];)U]VSuK)͚S`}Ҷm[)P@tGy̹.\0r?zh9.]Ȗ-[̞/4giѢ2Jԩ| gikWG3fYg`Rn]駟n.\iȻ_paɗ/TXQ}Q^Sv"ǻN@LI]   Ĉ~_`k_H;ljnA &ׯ7kHח{4X2|pIHH0ۛfM ߅'L ?1B#˖-'OJƍ34U6z1yW@}菮1d}>GݞLGIG= ڵK~7{孷ޒ^z.fރݧHIUvN@HDx"9op uO    +_o^5jΟ?/`|ӦMfթSG~WsYgϞ2eʘʗ/RSRRXd Jx:u"|տqu=!V\)7x̝;ӑ!UV5N;pw#HOSFMݻˌ3.H&M}NWTGH}9sQ[oIII)GMSfM3zɰ6ݧH-)߶)}=C Wn@U{ QYyFzd8!   PdIe۶mW/믿^/ 6J*kRV- >;Cpߤ8K{2 Yo4)=SB|I&vfF{=F߾}Sb>l/QӌxhFbLp >z///*gR^]}@t H'!   yΝ;˰,ש74w ,Ϳ;ºti0ݞRIǏT-*Lu,Nf4M(onZhI"'N l]_w˅[9{{|kۜodK <8S@@@@ s=2e>נN{e' zCp]CןO>wu Mx52MPGh %ٹsi{E8mg= -ܒ*]SDmשziх%IFZOM]?,{,V$</H_QJ8$ j\3`krm(X@ E@@@Ȯڵ}oܹsKŊmٲ.]ZVX!|:(P&n>LGth:oCG[ޣS2;iʬأ`t*Ui'.^(SN5sEΖ.]jIq2l'-zTokcID%OLu6V:Hz  Aȼ(   @;vh0 M@ A{1M߇_^=Yjһwoȑ#%111M~ϬԮ]\ӢE,/իO>۩^{;/л}r'Pz\G>v:w$#xt*WVN''~)vE G7 o(7v3[?21y4   9s8k{,\Pttw;wt7ot;;Ͷ@<߫viHq:p7=lVid 9M@gnpA+@@@2,pm:UӦMw뭷JbCp)XJHHp7nl6m7ͨgБe钜,=@ͶtRJɳ>+&L+ kO5I ͚+v+Wʅ ѣ^3#eޮ]v0>7Æ 3-[Ȉ#5uާHq*玟R'J֭-Z n8   ūa^zɑ#GDGK7AH JKh޼QZ5*6mYl{֭oVׅI> ?HIIgyFf͚%gΜƍ˸qBz?jժݥ4۾+W\q\yr7]w%7x]L:˥rңGy'd;:tTg4O֓ ČpHG_K%q      KL\[      Aȼ(     . C@@@@@@ 2yQ@@@@@\*@å7n!     @d="4     TKo B@@@ RI&I\\\WZLUO=T<-_|yѣG-sqLf͚I-B˒.]Hш/ʕ3aذa~=D@ zd99 "   ~X-[&*U2 nZ'֭3ƍ]vI~ƍMΝ; :TRRR6({"E8eBm\xQuӁ/oVmv_|EիW˹sd޽W_In_{ҧO9yS @@Jr579ns   @x'O}J͚5eÆ iNZ`iFV*fdo5k.;v͊'ʠAF3}: hѢ@}y衇vڲxb)^x$MP@GϤ*6@@@=z07n(M-[e͛ef֬YұcGy9ؼyѹر{O.\R8Q8~KR @ 董n7    *$wuT ^\rIʕ>7ϛ7/Ӄg6 6׮]+ǎ/R^=3^SNN:J*2s̀p|>  -@[m@@@_PCׁQEv-:Jo6e2Ǒ#GTSQW8uL2Ezm>#w l[&O\̾cb۾ nO0Aq1bٳG-[&'OƍG<7|#jՒJ*6+&:ŋFk A{Nƌc{zK^z%9 D/_w}L4it4v#nw@2[ G'+o~p Λ@@@XЇ۷F9ϋ>޴iyuԑ_\ٳgL2fz+5$zlɒ%&()5E4|W\)7x̝;׮OGTZՌ:!5A{z+=A(7t訊[JܹB5h ѣGH5kQ2v'O}.*=B?SE#ܤ|}?w}9sdGo=!}߾ n&M#6>G{X   u}]\9 ^_}Щ41kxԨQC[3Rcҥg?`1|^kA/ީW^2m4Cuj*Re>|XWnzwjР^\{ǎm-PS׆֩Si@NzoUf-Z$͚5D 0`@D 5w*}cRlYG[hrc?18gFȦCJ)@ _r: m#   @ ͛W:wl,ש74w ,Ϳ;ꃿGAoL!+܀֫ tBEI6M,hBkeĉMޅw{3ϘCFr4nݺT̄ {Zh)TsG;Oí˱-{wkV#k<.͡M@ H'[Ns{T-N@@ȩ(N# tD.0^ۚ4ࠋ[7lP~g3O>qsxg|=u - {w^M4n:ͩG *itv@}7߾} B={4SX|4RJg ]3o);rHPyeРA2tPOx$tH(a,^NNw\]8/+T+KIҮl>|۝R)ۢٗf"!nԣJr\9k*w A S9Fzv{T-y>   -tAo}ح#ta1cƤ|PL"\shdҤI}wށ]@IDAT(_ϟ?TO_Zʌ6`"D={o7k@ב~tԋ~t4Un,_-_~1s ʡCDc`?~ G؇M(~~~6j6} 9rx 9p䰔.ZBnf#=2LH E{ п A!n_"  _@-Xp}sΕN:C3aynzn{[u J̙3{f[nur 4OK, 9ѣRZYVߴi|f}aNB 2tN >ܔΊ9]hKlkCرc͔V7t1G@1z¸,-r O9m6AZչg@.->,d;A?@@@mf4WM6Mʭ*Ŋ3uz`)!!|d/n<$>}$''C=d4С#:4iDGa*UJ}Y0aB ƶmDG/Q>߻wЩtT&Ե+ &ǎ-[Ȉ#+:.R?N덄]͂ʕ+(R^{Mիg,vjsxy;}nyou]CҤΝMpˍ @mUsA@@r.kP_իB:*$XG:e쀁,_رYyf$ӴiT:T|| 2$H g`:3|Ǘ/_.5rFye}=7_9|tI='08y+ pꫯ:5Sk÷Ov.W6uKnF;;{t#'U'\H:@{-)Shtn =]9#=t7qI1qgeKR9|x Jct@@@]:V*U ]^ɕ^N: b?.FkI`׎u2wH9rxӭJGJu   @8oYgG8Z/C#ƴDS5=źuA҆6GΟ?֨8s|sw>ק3gNEyG@@@ 5k_{.dY  @hFz6r] ߑ?&4m@<:{\xMwqSdۖ~Gr]~9   jJ:?RNp@@ zdbVVa4}n4xh?Rm;wZ4)1~y9{>w\"`Ν=y)`&4 ],ǜť&c MT_h34 u]ۭL@@@@Wvڲb )P< /a@)@#p߶:`ݚֵmށ}AփO=Li2矻H8kt#N y+I0VCt!rqqַY.ΝG-h+ r5 ɿt~.|WS$u=?|A SI zE8Q7+}j^ ZXRrӞy#  !g/͛WJ.-ҥKyG+ǒ_L:U~嗈^hL2E.\(vԌʕ+Kf[oȐ!yW'skɕ+ + DS ĴA}%K_Dž wM :BAbG3s,Ue^{ץn4~ai-(/M*\uؿE6&,kC+昗_]ԌomF#H:xG@@2"~y7eĈ}^J9|^Z^uywߕ@HF蹺ٳfӧOK߾}eƌҧO4kMp 99Y>SyK3FR(5-3 @""Dv /Ht3+.M1u9i$/x-%JT*nrv;!aܿUH%#_l   E^9^zɴiӤ_~}zGJU뫿 m&K.?܌WnÆ Ү];ٹsGz5s @hIh)T=B 0_ק3(A.2]M?@vn_koԵCtH6z,7K"B@@-`?0bڵruI L@ ݍd҉ꯉzJ&L 'Oz_N{պuk=Ñ:8͛NFB@ e/1C=ڴGbىpA&4EQ8zd$mXd XkԌo%EBT  Y t`ڈ̙3!X_};m6VTV:]W8m۶߇S!={tm@ z!7ner'O?u@$/ϛHM%[d,.@@B {}vTT^]Ce+ȓO>8DB9" 4-[&4u#1.gҹbܗ# :u(wu# \n tʕ[(S}L~>xෘf.@@.o߿̙3GZh!E1kntI֬Y5jԭ[W .lFTXQ}Q ;wNƌ#k6#M~)Uv~SYfׅu&>]e˖2k֬[^y$>>^.\ O?۝#q4ȣ#[SBB:G)UV5qƢ9y6 "`ͽEaCýN:ٰϼ٣=/xZy< پ`U  9P@N[zyW=փq sE2Ǐ\}՞s7Ɇ k(5%gٲe9ri/>|س{n_sᔳ7za^z%P޳j*l0|j~W {_3gX{5N<ֺ޿iꉤDq^_SS;wnd,^kqzs|=+p?4}6l%'';@ v}5=;CbM}5\nLq=s^j5IrUqN   }~2h )Sځ+WoQΝ+۷wt#ƾaCq-"IIIN9aPxqY(; ={2c ѤIo=qț7?^tA~nݺUT"W]u4fv^9ɕ+Ebס|>O+pfFS; @ LGl?FC8Y.H)YŊ5[ȕXfsp@@@ Ao?otJ)]_իL6_9XY#k]@vӟ$ӧO7 ~^T]yK,)֨3}NKii4i&>С/>4EZ^ϱuz+ x8;mj0 bCmwWG$]p^UA۳gOuc 1$_pHG_K%qJEٹ}1aA삅KjMjpGM(26@@@ fÈ'N76o,<;;wɓ': ~ 9>@իM mQ":ZDGR+W.U }MS^=ikDĚKΜ9&b iԨ.]Z8`zHV} <5)ǿoܹ ~5m|t7&` nny, @vC޿v=vG"?`^3 IܰPV`1zrַ͍v:yl   @@|fj'Z"En-qFHv>tj%]h[oWٳgEGvwW|m{;#?wVXXw2WMs]Ozp} zLS N_~1?#okj2SAL}e͚-Էn0 @ !n~n#/(p`3d皿@\FQ *U!  @RbE3bDNW>Զ8{O|A'O78כu:t)2JG1h׶ xH*֚_y|mksnɬζҥK%]:ez]OzH} :S< Y˘1cL@Z^&L`g|OJޔ\kIkIsV[iNOVg:DJXxsdprsЃnIdeHV`MupV+2߼3AЌa/L!  [tZ+]B߿|GNN6~޽ͺv#GJbbw-_TTZE=|oР{鴴px yM1ꫯO>$MCM4Bv}^rT+;3hDGB&NY#Y[oAٳw߀6XJ4=蛶EBLyۣjCr8e]xnTg@IMz\l   :"Com~Aڵkgph;͜9Swnvu&Ǐ7uM4I4d(TYСC=4z\?_~e4h4iD/^쌆^ߔS"^fd۶m&qw{Q3# ٳk׮fj+{aÆu'V\iIOy=x_ה> Zێ+[GQ:N|>["٣~14v32"$%']NIjTnrN#W@\$o|{"VH*`}bG'i=;ja^/=Ӽt@@B XT{^}UVyY#;ժU/!χQ~>W|yyg5kd8pSe/AO ®%@ liHkSGeSҏf![sshJl 봓R+:@@@@ ;&L|M>Y>֯#p3iѸYX?`YHASQ8slݼ܌I\PΝ;d@j]{j8   Ī5UI^F)g=yn&P3Vg3$i"9{ iZfrM&rUY+B@@@@p3iYIR;nE鲩ϟ5#@6%. ';*^in \gs@@@@@p3i2=w,y~Eٹ}!9qsfbeFVT@r䱁    %g=b󔦷n0wdck.XT،Z&+c@@@@/g= Cv!p`3d5(X̬S`UFɝ;    SϤ zsv B(#ȆrpV- \oFԨJ+䱁  пEyJҥ%>>^t"<ϟ_,=$׿dԩ/l;;섄OdƌaÆ` @L 4AXnl!Zp.ٔhDB< /@j| >=]H}KR9|x(bM@@@ 7|SFaӠB*UիW믿n ]w̟?B߫-hٳ\ZDoҤI2|pS~+:cy'͵,Y8haXA@ LA=aQNyuZRN[)T];Y#=)9  DORhQӀziӦI~L!z= ]ѣGxꯆPgqFU<|@5vbn'uesIFH/^2 S9q`j[Is@@@ C7&Ak׊Pܹ3Cdu@p͛ˢEE {Ln&1#t80w(ыX8vt$$nX(;~ŐҾ`~(  pR`Ak;|r̙75P9GJygϖ][ {G,A0ѽ8q␙%3С{z.Rʌȗ/" ڿW@Qo2R$ 0  x {}vTT^]κ<G9GJyG Ȗ-[\ˍv u=GX 3 .%v"EKˬXk}nNe&{D$)z\)5pOfXdiH  D\v^9sdܸqj*ɝ;jJF-uu#ZO>M6ɹs\rұcGy饗H"NY &uVtywRɬ;Ƀpy2sL1c[, -[)SHbdر:kO:Uʔ)i3!!A>#?{EյIޥ^J;]EAQQT@(H@x_?Ă"R!޳=70;.)\s˹YI>sDg&NcyxNC |n)=e(Wկ_͛gM2emxpm=\zx-_8w,A¨˒Prr%'WFzO5O:!(ROII. b8|M,xzǝc_ Y+m|eXmrx<8ۗ)$$U܌@@@@)`PX9s&-\5k&~Լysڴi5iD֭_zjjٲ%%%%IdJ|/ XaW_}լMnї_~PqƔ(~׈:Ty _|M8QgQfĈe@@N<śݕ( `G' !%ӓdbCXa$!$ū*hDO{rc3 #,,"wELaDN4~d{Նr𨹢6a!s:8@@@@ K@y@;vݻw/5mڔ~Wz'*RJԡCZnvtI]ll,Sjj dߞ={JC}vjѢ!!A8}42焞5p%On۷ᅲ/h7]KE\"~hU{qN}ث|V?z]Rd`{s1zD8p8ݻKAVZi?C7nh р;C.F@>9ija&62̸`<8ԖW"U4JND."󚰠'D!kqq7iO@b '$,ySD~y wwOіdSY 0Y\q Drzw!(aXq ‹y    G@o=""ڷo/7ׯ_OڵAp Zu  97{ pN %ٹvGy69lܙ><^?G׬7mǜa- 'F{uysprtɈE+x()H럂;(wRowFNaB78V.ۦuyʖ+s.,L,ئ\'RWxFM|) ]/i %3#N/]OײD9~M $wosX¢ %(moٖxnE|Q%? YuJizB | `kcsk1qA6D7Ix㛽[0`z87 ';wǎy: .,s7k4Xlk\L˲kCrl[5'0ӆRwC8'|"E1c'VD\Ѻە)LJLUѰ'ZxSmLJ38jEF=)ke'\fu1P5iqo +8tI(B I" %R4IV0,ؒ&#Ӌc!ۊ$xZZ]XImX#.5E_'"N.dNJ;qÇՋQR^=ڷo|j&n4ydTEEk֬IՁt87e+CyVG5h]~X "Szu"}c<&=)fRBX?JHbKUXaA8yܹs髯m۶)Mi׮]FNd΢ǜ9s yP͛7hѢʩk;˙^cGl3,,nܸ!>J7 [o_Q<|u&ؑky[>jQ)[OYmC+yckȆpCAC@$2 \%_فTRt9H^fęʕ+g|UWG[ `mE& 6M6vn[.6 ω6ၜ-[gjcZL7o `   G@lhK0V/ &((ȴ`SttFlȫ>k, lR9r)66$BWDt#L}D%SFdas_Wrww7_G}I<8SGxD.d ӧk"ڏm{|!u'OC\pAZg񔢵E[}]9ELlU&}СMC8q2ޯ%,ns= 9I#CEyDJKyݥ> ʕ+'Y-[GۛumlpZyFYL.~mq.N^vGjn T@@@rr@ANk |.TjÆGf͚os=SNѠAG W^ꫯpSҥiر4bO$DZr5Ѽys6mL͉y|]w eW^oϚmhbo^cO׮]i֭$$:/v J3L(Q^z%-h u=ܨ v,w[Zd>;DsL#֍?TBCy晍؍%ie \xfx"i׶{e,/] j@.39T9"AlxB6Sl.?65]=XEj%       .D{=t>L^ ^,|-,tGhh(]~]^rv~\(&S&E$]ݎ,dlcf0<I1 ,R4D _*))I-ZTv   G8'94rLzX._OMM[Ҽ={zzjX)A@@ z|ejȐ!r˗;5҆Asjt<$Cߟ:u1?WJ,)==M~TF ܍?/nV@@ @hXEd;pЀchy`VoWh//S >政 nݚrpp0u*8?`I֭Kslٲ4rH'7O~۷ojw/{CP9~8M2E&WU8?e9geզMK܏=zHO̼G    *2-?4urk>G6d`7=؜7}&IL}IxDS\\I&$ 29V^m}IDM03Fֽj;W^ڧ~j5۷ԦMYgiֻxLe~mRJٜ޵xzsr}^,W\ڔGQ;kpwo~9=rbiDD'FЭdb6/PX9uc>sX0mzw^jڴ)q'xB*U"!~!>yN3ZjJٰaZzzhB>[Si0ޑr_eNy.{|˗-'?M\  uG~ z7\\^.004:|ڲq!%$DKKWjL:%r   %3( 2ӧ7ߤSjeʔK.Qbb*F9￧/[*s {dClQ/syڹ^{Gת7F~K]RzW%,9n5b3QN]UY4Up  { l&Ev!S'ΝM/B?8o]rtxp … FcA0X )׮]ѣGS*U‡^?R]εrY wtz׺,VdȿavtR\ywt_AgߐGÍ)I=JtN42b <   Oۣ9dKۏCuv@{v(rl7Seۗ(0(41p@@@XڵkG#FٳgS"?i8xz[vS]zP&3}|Rc OGS嫔"[=rfgM@ 8Jϯhithj::zh-m$hݏ ;:,ڃkٳgi|rIZ #A)'OHUQQQf͚l_F 9-[ !z8V{Ak2ؠA$W&GGOpfe,5j$ fa䜯:e6 )6>}Il5UN:߻wZ.ֺZBt2bbbLB,v3.]Ǝ+p{!XEhʕ$0m4ݻ|իW6imlDz=kn\J۷'!xPӦM-(1ӵkW-Z<+WvS@ʤ圼\)>JQo>I͕:C!z0 A@ӻ)b\)g+ZZHj" Y]" )CKrɇ1ICpϓO( ,>Q  $`G#uQXTuj~(ؘ&* 3DP]Usq0@@ df[7-rePèLl $`=iw΍s10@@ 22?hƅ-bG:b+J      ICpϤ?`.0$ڷk%mN) 2ymP )\       04DLxa>A$%miώQzz*{ReX V  }Osq0@@`b?/~ Mf-{o9       p04Dxa>A ܼqD,G#&)x4j,5iy{j  K?///*Z(լYzAC%ZwIiɒ%t5Fhz{{SHHUZڶmK}5jy) @@E}O|li-Q  Ac?6CѸS` oܸqkzXTX"ݾ}O3gΔ"C:uhƍR)ų𒚚*M0LNk.Ueddӧ|NcN7oޤ;#{YV-k￧ݻwӀ}C"F @N{= >r0A@@ W\p0.z PpqjѺmL~+`FxPPVHH=!_~NÆ sccc)88Xڠg=͘1Ǝ+rĉ?˵/^L[nUٺba0@04DܛF@@#pnX7^9); -O j5ۉs̀   {$=!Ğqҥ_lvc\FdX'>xMϟޠtu6:u*[ /iZ-[   ' 5?WF@@ɔI6 Ϗ}+kdԦP*_Q>Yi@@@ONN&???#[(UdgkNOSdd$կ__Yju=.yV9>Μ9C;w&M8֟~IΜ@@\]& ώGh%ؓoP`P(E]:F+N+P9   ~\bѢEԿN΅s_<ӓ "8#C=vca@@@$Iv!,&ᯖ|3Tׯ  /e6/P֭)00P֭&ӄm߾ݲ眸~PE}J;֬YC.\9飏>5kƍkܹu{Oj_eʔQmukr}rM6#k7wѣcN>8Y=@@pEDqa#t?)) [M_|i֦O?hkZLѷ. @@ @GZ~/4LbԵ>3 /ӺuLqqq&!:t`BIKRtIαzj۷MQQQ1cȺw}WmK^OM"i߾}6m:K[>ٽbs߬H-{'BQL<ѰaC,[2(QBէOSbb _erww7 Ƭ>ʕ+r^DlJ[s9:2A@\3s!+~B|`\y @@@Rb ܶ{ԩߙZ X-`2(=R?^- ӻL{MүJO<چCTTAB .::N<bVDŽR6l Szg(ТE y^NݥKӃ͚5#8{nBsH"rm۶Q#뎬{…4x` i.xY[+-ڼ-\B0ZG  C{=\糤k?`F@@ @ 6*mۼM<@I^^԰3Լe 40@@Qh֬YԠAR7J~(<<\0V6חvzjҥR0aD)*C]qi#_³T" I[x'յkW%X!xc߲tݲ=뭛Ňʕ+i˖-ԲeK+1bMՆŮXqޖbŊիW5#XͭC<@nI8:M *" ViW. @@ deۻ    O X,ЎKi̞=--9,4   P8{jR$BO4fƍ$7:xC%x1c ),fh?#Ok׮Y'ƍ2oh_,xp'5!9ˋ|M9$?Q G!%R["ԘB Cd҉fW'1  N/1 z -A@@CECSg'S|ƔKϣy_=/ŏpX%j7E{Qs$rAȳkӵkh^{Y=t< QB@dcވyK?/46ڻn`РA$r{ПIvcx饗toٜԁ J2ì#vsG[Q'm֡IOU_|  z<]dX    OdBtA{|Ǿ?S}n'ŗE8șS;DR*VnF>oF|"Ю];Ni2︻""9[nUY,( ǎy: .L;v쐞$f4'˗bŊ+8qؓm۶瞓2X\4in;g+Y7ƎKƍ#@V\)mۼy&dO$%KHAE$PW:j7w=G5B SBN9M%̗]#Ǚ>wg zK @@@eե/͢swƿfӵ>;~VmPP0us;iWT)U? L:~w caՓ!k)pNL<"##Uуf͚l_F 9.絸Wo!!:tPUp^\wG֭ù;8'-ZjQٲe˹>}tӄ=LR[3(6轳Hat˳LE$=řyc-h  `NyOܠ>Npylw5nGgpLW,|p~󄩹oF GܛDʈ6l;+eŊԳgOy /PX<ܹsEm۶y;8'+u>z.ﱼ-Z^$f69(ZkGll,UP֯_a-'[燶2F{;nS駟G9s> Nn`Qk„ ԬY3HQ9:ߓTzyZGia,K䦧K? ynA8-evNQ}Oo&    `ΪZG衪ޝ+響/^IթE:*A@@ ТET3fΜI 0}4l0)d˔B> uB';s@Yf 6ĉo8!ax#^yZlMCN(os?[ܹsoPtt48p@ m~UU|aCuխ[Wz=zTáUANYvQF"ғO>ij{J:}4mڴ3-Z;:j7{tpKR˖-?oqTm6l4P!-*<;388<=%evFW fSm^B7Tz%oo>>"fwE] >V ~@@r`9ءCvj5{ 9 JzgϞ5kom-q)sE^W_ ϧҥKK9Xoʜ,4oޜMF{/QzuwN^dI:>ڬǁlܸUX,1,Z^wtZث|򒭶>cK^^^*YłGӦMf^B]vVV3cfD/Bh %(@s158c;CsE@@l8V.\w/ ,w!x%(uw_Q(dcpw>P@vxhl '`=i2g@ereeY8ߋJi)GI╒/z>}ĵqx[ÙsOOo!/H{zYu\{naܜ>O03vۗETr3&< @~3giG~֙T  <6誚   `E#H+|OORejYwCrQ$!!Zg:kY?E(qF&y&vIʕl׮]v9"ϧMF!ߥKV.%.]RL0i޼y_+W y~:8ycNQQQNAAA4zhjҤ ݼi ֭[4uT?sʕ+ƍ)&&F& 7|̯d)p[M~rJϟW+̙3Խ{w]vl2& 6lȮ5 I&I ԧO~~~tRɘ9/YDxXP6m_~J7nܠ?Xۿ?ڮ^J vZU 4Ȫ?w ^A8' ҍf`q};BBJQ[LgmrwB^ ; ZjtqFDD#Mԋ]vQ׮]X,qtسŋoݺU]#cp[Gx)c@@' ØRh`]}p   8ݵRlDeR`P(0j}~X J8dU\\8p֭k6ff E^дiS|=0gk\|{aS*UJIJ?hv5X)]xaǙwaoa?@+VY68,J{dW6o,۰x`hz-|r|bVP  -dy ު |&7ʡ.7_ h7x,]n>K^79@\?=3r +WZ;UPAu`/4p(8[ eA%6nƌ#MIڬY_mwQo'Q8?{ph;va=GP@@;^Czঢ়~)O.]XX8@ը9ؓot^Z< mjPav'jᕸ"o^qR|yG=*Z(Z*_p(,!˦gϞzu-ᾎOOO(yz8:ڃ@^著t1}I`p0t8,\!'} 6m/׋E+pssz R #MyNK p/ _^ק^w}D=87BHHa{DJ'~C*q 4j(*S >LZj%ss^ N=|B?00P[n1~jժA3f̐y&xO=q.{-^HPSfq^zQ͚5eNK~wСY r8|\C|5#3sNOf^#G9 ]/-{7n,/)}mUW6mfl   %$pMZ[| %)iT5Qn(   #X@^Aav%qٛߢؘ3B9J{%έaX4iNݲeK*[lzj w81ھA4ydA;믿N,24RXh`;y۷K8om63|rlo8?`͛~r^ ?ߣG9߇.]HX^w6 Y_}L"Ὦ#s~/Xc!sv;wjh_ _ɒ%m5WB~?=J3q+/GB[`HdN$ qԌ9%%( Jyߢ$GfRL,܎8J}GC\Lf &HL?r"oo*ںC#/K 33ZE7~CKME[^,,ŋvcd7 *D111J5=sĞs0paaEW<73 {:R,?2}tڡ7pMӦM7xCV^]8j @?o|+c8gΜJ*IωuqqbŊcrٳgepﵬYF¢Ӂ _{zPVTid越Ǐ'%)9}7Vɩϣ5RoXJ[qg}&9k|gΞ=[+hN|@'ܖRWi[|e mޱv zQ  ӌh1D#l2́84))XK7nѷ)YBH4JOJL"JN!TryfpJpx:$ Ad@@@ @|uڴ~>94Hrר|gfk&gm7٣7ڕ!XVtr)x_[MXMVh֬ }uqm9 1"L0>c)Gׯ+]9DR||Z76b {-͞,0kfaxpq:"`m]}]y'wbQ1,k;ݘ>a52ҞwX0y97jՒQi6)oߦ… KI7x"{7iKvc8K;~~'J_I} Ԙ @\N3ўF4 6Lݚblȉ:Lܳ[EE7)1%܈!Vbm!V"AB0&-9YHI'L+2]Qhp6;/[m=62<)ۋ2}(_or!wߏ<(鴈z*&I*$Pҧ$ ;L-P.$==@@@ @`P yU#nWtyZ>Vx4 cK5V'CQUw̼^rey7XnJ?8%)@AQqNNE?GH24d ؾ=nݝU;~"$U<. "Qp'D'17EJ4t %$ "S7 w])BBWwZB[xF䵶I1/>i~ޔ+ ?_r'7!Z?= wH! O`xBP0 .YBh}Xs2%#C_8T${S(!A7bvmh   GhD;.TVjv 5lx 7k5ǰ P QSmV>O͙q?+ %?^hQ{٣lNsX*E1N8,j(GOhaO"g"'P]v˕+wOr М9ssW^vNgZj9w3E ֩S'/'uV9R S C J4'V~ 3i2UrUwJd`,WfRbqUHH8!^]N ÂTKZ,<*D(!ZXᖑIe`aثA&1&^r']xUx [B/R|Ļo)Vw !h[צ%^N'O ~AB!J))¡{yӎ6ը oRg)   `pѷ. /̩%ңPYO|.ENg["8iժU2$֘1chɒ%uV IV%/{Joa0VDDmks0L,l޼NT`, 8P`Q8e/,Zâ^߲#m-ucZ۷/-]8Y{Ϟ=GӧOπ2-Bq6]JOfxq{-cFdbecs~z9:=MMjb*YuPL$~Ttc"2E FO%/{Ls2RTY:8inxzh`ET)1ڞɶ3ҤiT:y/b)CI$zi)B@e2vk_&w7qtM2 / / !\p(O!\x /iBE"⏅"'<.2 "x ɛsW+8H" B)Hb y!BE] b7oC3Thmsy1x,-bzA(s򣷭y?.-K),xdK$oU*< ߳)cQU7 x5ߓB*#oqP@@@ IrՖTb#}K yuߝԶ]1a{ pO E_ڜIA[س⧟~Ia_XX:ٳe~{B,xEN%҆yx7,zecS7Yb6᫯mgVo>=[`̙VM8 mͩ}JPg&:sB׊+K.I޵EН2''vW;XںBFNE Yaz!9`qgCi6Lk? /  +9d)eyOrZ+{x4aj޼b9GNchKÞ,u1G^@J"U@J;b_)H "E˻cxQXxTfy_AП=BIH".BYq1 ̣sݕ!w>؍d>^"G7L<ŧxx;^|gx١QV9:շni4yP.!zG̎Th~" lwgݖ3xW<˖"dIK =K#]trI!҅ں8KAWcdt_$w9i5%LKPprT4j 'K-;_AW}LNOb1=sN=o*]iSOȑ#e%Nb{zx#cOb= ̛RʬYl?|r=>ouVvث裏ʍyl)wcfD),proH3Æ {$%%Xx9]U}X[X,z j}X<Ji 6$__@xp/KPCIB|g!cҤI=uPҥfšӔJϥ҆m<.K8vKv{B|J\޽{BbkӦM7y)@Øb9FnҎϡ+S!Iw+BZ 9=7  "EnbfxG(-f%@lt\V_v\9syGP*G |Z}E-ц^#)`VzH LږMYt6(S֓L|-?u 2 '&/٧;Uu_轇]-:[``"H(Vu>.SzR yP\#ν-8(Zez^S[jx'E5SԠSԺ`6ʋ1&ܯ8=<'WCCCegĞyISDYm]V&fσ*Uرc_{u7›o[g k8Ok2R䌰U89:{h:;,h(]Qi9#j׮J >?wZ_a4VK=oXHUƴ"M)ze_۾}%"""\%p+@looN,xXqPKO~iV/Fby@\(a;aH{u!y _Apwa/P.9Nl׮AϬYf59BBS&TkG*۱U[{RѓY.&Bs\9Aq?EiS=PTLp V 7v$9t yb_R5}ۡ<ߞB [t,yq$Je_"&PcuçeUR(ŏ";/Sw1RiKķwJG~&RCEȫ =@"aM&9\Q {.p(FBn${sqs,|2OcP6dOB4uCic03ɱq{b:.vjGMD>"=培ѩOgWr*eSZ&iK\썛wVytr}7y?+NZ- PgjeJ "!k,F%CK=HJV}Zx *aT`}J}:E]:*W?:>: -w%pׁfzsp.۷o˄ƍ#ˣ# ld(.NH   (1I@iMX]4űd-BX=|eGA/OUMmrt(=̍vn:K(e*TF9P-\]6*?O6v@c=(y+B>Bh,[JbM1Z+%.vOK[Ae!| XX2J==ZKEII"q5k[cE-ȑ#2SPߝ2q6"^[Qqӎqޑem@@@@D38-Ah34-0ν8=~ |"%ԨDOΟN%xg3Brr2^s()^AR'QH2V#*HED"|H "ͥÞu#eu@trWnZ8@WGRjU~"6Xs3{ t`ﯢB ^Rʶ;6ځdhܹ֬S&i3fIh72%'ĩS衇*PFplpDg{!ptcQ]JI{uLIR 剟PsuX ɸ~L"[L5]LxXT&$T~TnMk'$) ŷxYoM|Kb7J[2(˛.;^9ܬNrD( 7nЖM[ɋT:Y]\Zm#}Bs0@.xy9ݸvFPՇyU( 1$I99wruI-H+^ʀ]a4{.xg}O̝cPޔo(iklbz󦆷ݖMs)f oxNL&T{v3|"eK䕒fQz7 GR GSiӅLjg2q#LOx`o9FGwN%Ĥ$t;܇ .v![{2TO'/Zݨ~3 8` ̠}~D@@@@@\!z'0ǛLYt䕚&7MZs3?%'f%dPX:>/EEO[ϚjmϲۦG g}FLCۡڦOnI䓞iStM "Ik8(uL7 ܨVGN#?pYA8Q)e{6(˗/0bY"q^0s…i&>\J*EڵAkYviqm۶ԧOQCa[ci8..զE=.J'-=P֮+0f|nx`a )IYJէKb>@IMtyfkX!¨| &zխco'D frg<૨?K7jMDEPDDYۺ*{_Wa?(eŲ6@AJBK%97W2/903ͽ޻9L= l¹{)x8̭67[f\8i7VXʳ`ڏ׬g3Q'E7Zmd gp|/aSDqh `slÖ,dxЂمpZ U>'m[)oֆ$fYn^dc E/*Y/&$66mZTz>mV[tf4'5l&@PS#FnLΠ}u\DQ9LIB@@'㺛sox獿`73JB@t.}F ͛7㧟~r-&x,X999fm˕( ~!buY* '3My駟6fܹ/;;} Z #FP‰e{nXPPg}s\mk=z_~98Nna*xp=W_}5?ӓ%g1:55g϶HB@t(P]ߙU'XC T}N-.Wz!0[m.<3%.G(r5/*f0_pblϰe$B@%%% R3:u*V6akPݿb&=s9G0~x[`֭5kkڵJ4*! @tR̥ela<}_2{ 11Q-&[];ī]j,}m z=Ǚy8pCU-ȹB@8I\ϓhY X2M WNҁs?jDtU%ضh)vY[W@ٹ3Mcѩ̯ߍ?id˧csc!=n W8RW 5 Sλޒn^L작Uc\\1lbWb_,oQbvcR_U/y<.NVb ~XY|'E긥>Z*2݋qƩ%XKNN̙3m6hcYyoXHB@87Lk鳻g'Gw߁4 `WY便ףvd. xޘ8N]O_j(Oߢ8]<2`m'EpT̼f+ r @–ce(&O#GG vB@P_}݇K.y38q"b骞FRRFA}WǷ~ n,qq2Xt.\$lZ꣥2hO=}Qس1croG[Roma$uB9gZK= w@/@D|WA‡gc}&mT w`&=x;0ʦ nl>o.Nz*fͩK^Ơw_ >8c"LHQ bZP#K!ޘ8z\{7/KD^nj[B@ | _|}8E[C+m܆۶5-K8ٲhk衇fplӴrJxxx(K|G8JJ ! h?=NZ n#9$Y%Ϳuޞ-=Wހ}68p" SnWo/\8 !3ϵFHo5^ KWٗ.$?!8~t PScWgC3µ^X⤓NoVG;aA?ǘW]u0[li0d;@||꟭VXI&)H/mYAw<_}T]777-2{zz|bA(ഁ\,X򣣣 9x)vϞ={ BO1$̺lx^xC߾} d1`(--5߿p||| ?ϝ  حJV*yh9@ #GXu呑 \ʴqV Wꘖ;0b M'YYY= kV-ae-y:]w@B\KMZ,Ӯ['B@!+ge2?M*ʡ> '9}߮67|>Xy{lC9Y'Dޤ5wEe.4X'DS 'y[NJ2ftG!m%b\~f$Xh饗tc>/"<>aRT=c֦-'dqx͚‚ _bP:۷X0;;|-<&k)55U哅=_ebTdvm> &)M 2kb M'555=O>2{{˾LYԡda6l=LǠzq^! gg"9s{gfc.DÕV{y'S1 !   XA' @c W.h;kWʊb{ᴉW:OSZt[ټy3L] vgxyvDA*׮]YD,u@s?D?9i\_Y'f믿Y`f~<|[Km5\e˖iM戬]fWWj[26t#YM_~/3Rp _bĈ*ָC|"Q$l94 ;67,PF>&%dQ^yV!<sQ\xᅖU>-ىǞ1r@FL+IB@%`YHL=h'woo\38e ZԾ_#iv*̈́iBȵS^WAxuز~COG8)}>n!Ɲz)kwkI$5-zlz T #ӱcԞEvN *?ÇW%GS7J'2i,8lgڵiEEZXuTw %?:2% zTKS/N Ua,8`3S{Ga[Iڵk n!+!=T҉Zھ7݃tOVoTGwC-' GIK![GE}7i9~x[QQ&AQu{d`B _-ƈyXxH:t^Խ~B.%@k}qw׾(,Hg=~0Jtn/)A@/زÑ4ydU>3V'QxĉƼERkUZ-g+Ne,?*ődk<"?pcz[oooouKqT۶mSm P\U{ڴimhej>}ZߺcJz=kҋB@8qo w1ݔKQ(M7=ꊥA8˺hr! @oc/`+ 0r3 Y(zzغ[rxxx3 _u@eB]h\pA}+*7UP.(4>Pn;֬[źP.A8z®ek.nVv:[-:-Zd0[[Ό1cꫯƇ~'|W^y%9P5vO[?pغW^~֬Y`KݻwZ][keڞ97,-Z꣥2_5-kZe9%)jBs 鸠A itLǡr;K'mJ>Ӻ]˽ R.s_~}|e8χ+p^Bd|sOPF/@묳l;1GxNLpc-Ȕ)Sr<0fp>[OPv{ .9tvTP0qLEҿ裏T\4tMfK 2DեJ9UU|96ʍ7h&xȤ^Ν;Aa)xT܃BsjʺsX1u֕ΐ8"k B@b7Y漢qï7wWƬweBBl;qߠqGKؑXK.1z:Ιv|Bw`r^E`|7{Ŋ l↖ز?N`k7`kE.,C:aaa`kGų>,h-Y|W\q͢Eof6voKK{ژٳA哓1p@&gW_}˳U [h{qyNA9>Y`K [i9sݲzjxyyi5a9oc X"c2탏آF;g$i|jړz=uMy}Ib%#:uu5*agྟ?4zaFʕIģw#6b(fM\W2>æjf${n8Q@ @ 6}fxgix 9dN ^vwX1k-[ d}ax@]դMyvk„ $0B?7º_ꫭy衇p}&c= o|@"3ֵw@qW \5hݬMTUW]eo Wq͟?@`v$d.֭[ $<9\4exꩧ8b klW^19ROR޴=yc|y Dumk>_^k@A @ i+. ..,:4+UV{AJJ  Zǵ^k{2>brO>dۧ3fXuמ,[L`Y6~hj~zKo-غeV럏9`WcZՎ,r '`ZFFFgx(]fٲ??3Hr?.@R־}GװՏ%ǞvZbVN$4T[>Y)$ ! P]Uo]\Du.%kfkf&Gw߁>yt]J^F @2V|\Q3/<Hth@Ce2i/C>.+CZk*B@t}{`7(s>\]1~8cu*y A.#Z$nm|@]] vaI&ڹX> iR`#9|cyww/ 6 Gl!< }qg`%S!E/λe~^~)b ! nj?JKr˫\3OOn\7زe jP@c =mۦ\_*L,P)99TCAi»puB@t DHMLV] 'wwne񡢼ȮՅQ ᢜ-0J V桄 /.HP"2i).[?xp YH.6^X8:@qq xq=8+T۷/6VWQԓ7̩SO@NVVN>\^݅ zKNB@! +2,&K\!1֥YB/-/ڛ=饣F DJᢽsU+K&_,m'E{_UYN>)++C@@,/󳜃 ! 48ȥt55ZwaJ殺) 0bzPL˶r>z_ѣ}U7 m+~gk9~CǍkJB@;'j[&Tpݷ`A=g2!DkaU4j"1{0҉f!CBYYY2C,E Y5ndҤIX~}+Z.7>V1?1ȹB=jkq|ҎOA|h! ^Hۋ/W,@iI Ƭ9 ?´9dYdyɗlS"z *1Qg0'_@pZwz#t\dF>! u~s} ѥC^d .>!3i"pN%`8g<򪮮ɛ Kc?4 ݹf(B7pTTh++WbΜ9's;mB@D`hOM'#XQwV65 ABߓHNYӓ]4黨0ez_ѣ+NNtCGÍwRJ"1q3t8Zz"PU|()SCq= S"z:ry~]r1~GC~!R@`$f_PޮӀ^ QcǎEjj20! @yyҎ2 )<,7Y@Y9qz_9#fwRУ l_!zhpuEcpٛ/ $\>z  P_ZW VУt!(+ŏ?Ikv[e@=hb +عs' w}09眃u֙fŏ*<ϐZrk֬Yxo֮-3ktHc޽nۇ˗cѢEHKKYg{}Y,]*>iW_رnnn}:V^o'NDee^z%sU`v,pN; >7n܈Ǐ7.B@8S##=I{ 87_3 }MZ,=xe@ ep|x~W2y>z.mV^|jҳP~Em̷[ lm9֮;v).ǔ)l! @pDXv-Lĉ8hvc5tP oŌ.|_Wp7SO=8t1AAA2d492>ǎg׷W U]K& N2\'@G:| ^F7kA_bP9LsqG]FBr,yZ{ OT||1`$AFhaX&B@ `kQrB3??_-iھ};N9!/g]0oz\TT_8!,iǎWV~Ƃ'GY,n{|!h5K؍r A Yߍhh0R@ *:v( sY;fX~.tΕ׫㦛VztJH 奷^S:2>{<.g2! tMbA ?Y3,=/}bYs(Yrp# yGSvwB2@䇳!Ѕl-[^؊E 7L_<0''GW]uy[.92>_[{G۫,`˼2,&a4j|,|̽unEF2Ni{T4 6E% Q$pޗbVc!`E?3,?Ǭ*uc#.#(}LfރSi/~!K,_o6lXn.lǎ񣍿:cؿG2ѝ/$= };)*UٙɂM*}8"Ik\+LPR}oVҪ73(-G P:f.~Dӛ0\$|sРAF tVV)ɿ & JcX tIWF7* r  M7-ž={0j(ҥKeܯy|0yd/صkѺ^>q$9^?䓱c7N Gk,C=bʕLG୷o@TegD:9)$8FlHij"+𖻖R! AXR}FҢ7G׫G?Pk/ş~zS729 !p$KnBIt8cDrX!pRmJI>e>}|0H#9Bڱe ?gڊ]4zGW֖CbK-``kN|NEDUw]-2c|Gǥ5|r\yjW\q^xzѢEXp!~7%CWYzǾ-=$KD5G,=:]UY7؊qde73cK>$px#G^&qۮg X[펴qHsgc< v3f̰ꊭ,f͚:X`a!997pn݊~3.89 (r2(&7M9YP[k*ݓS Q}Fʩo{<nh!zz+m6LE 3)GM°/Ea?Ùsfsa򫯐m'"ƍY3oև! }((RP}/1"$o M!cjfe"88O#eN<#zGizF2izFLUU)(*;」`.k&p%fy]L* N&5i=:uO`aߓ (9m$b!%~>? Cq#E5u=PvhAo-Ck0AՏ4B Hg.WB@!  5ן/DqQ 0/]he L?Gc( 7o||Uq2ǣㆉ+5S@r[z_CcVҳyJh@uq !T~cp,&Owe *=iChoY2! )|zѦr,bA=H!ڍ8xmٔd8B@! &p"_D*Z*bRVkUǥW=GqBsSJnn8bl*I蝀3?]UkeR,&wc_#b6W@-M%8JY9C8 W* !{jwG%Q~z'`@8t`=n@nv[L5/,$; LB IB@! @[, y9v.eaI%U$vp:rxV}:v G YoО- }MZD}??NX BA^z-\h>Uu&~,>\Qs(WVl"I!:lr\ K` E8];S.TZ'eB@g@Ha M#t*#qD%DFe8B@! Z&К[v[$.7pMMfS[l (./{(ѡZs]K仾POn_]ܿQs-UGL^[N[n*ظnpz_i%f{Ԓ+N)~65tGBAB ID$ ! @MZ&R7V|7DԔa R\r5f/ ֎] IcFS\ʓ$D)=-f.A$~ }O"nzE! W.*_2|2 C)U҄jŅZoh+P_%.Ћځ8 u+ĖƩeR^V`̷<8C=ve K@k"z8uD;?d ww6צ/f|͏2N}/xz6g%q%7uww/{hm\D N.?%OɵMʼ賟RbK%Ӄe [7e9=פEp'N㦣23|c1{eGҐG2$Tқ Yp-k~Ų3+A_&"j$ D,ɹw&!x4J5w,ƾϿߏ~t2?Wߌ뇑s. sL 2+!cIq@ܜfKR~Od1! @w0pQD %j(-n4**Nxp/ۊOx-ydh)<A M=IҺ5{f[Κ#z `z_ɟS?`NW3ٹr5zd䐉mFtd$}k|+7EMCfA$ "9p!&T=!qI쇨oō=x/ޤ}؛0p#? f4Qm\YÜx2t!лBaru il5{68$!F\V]dB@KcC 23,4}yi>.u[@8ci6?އßl!-kF+5y3(߫d-"$!}MZD'"99^~/%`)'D5YrRcߜ!RH =z$DϓLgXr}IIpxrU:sTZVJ7|I\鉩 ^Zw#?{nw`@O̩ [ o8W3j,! ']BI(5 y*w3p!"TYaU?YhĀX呅Ǎ$MTB=&-G{*t`@IDAT,HA?C!%G7 "ypm%%^a.PD ATL՛K]C'^Bup-*!l<>|êM=8t}A⁧7+*d;|Ump|rԗWQ݆^hcpw(V}qF聘VeTg[:lr<<ɇ1Y:KQ}ŕ1C1+9տ3$x-(ژf,yM}r ܈uLO=v&r,:ҩNB)A4ii9AU v+UT$ht)2 mp5$K)z_ѣSn{uHȕs0գ<=eҚC)>Fnt +zn$T R獺xF@DA<1wArh+ڲrXL~-Œx>kV{MLaaŒj*sQKBgT8bN?jLm@ehR⊡tLVja2k/5ig?}jUŨ^U>gT2 Ī,܂|i^Yո7Ll{tQ/7TJ!z6z^$Ct8 (HI_`(q@:)@w_P֮ٗ.TVoZ^k{Ք1Fǹ FgjmR.&-?yz _t+^l s-隬&w:d6>C jM gwY">>v3򫯐m'"ƍY3ɏP\X U(^2,AN+MهSQMHeq,W/< _!$TV@n5n GbGoY8<ުnFmXuwv˥@t8 PKq>OnrEq@$!ʰk}TxY{Rxz]M5 n)/,43)8YJB@.#5i=Q YKB@l%d"Pv4͂{B !l 槟ΒRP;07pN9[nBMjjjP]]Mq8 xq;A%OumƘ*jc<,#W[bRk6 L* $HV~:6ch2h$%DhEB@=[ ݵsnOOߦr{< ) 8 )~!:ݴ ! }MZD<$'2?`'27=}e~|=1^<4wOj-BK 4bEf!EM "uƓ~}NC][xzyλAݺ`AxW֨EN+ ń&ޤ$ԿM?ᑃvӕ1|8mד!  I z 6:r҆!""tB@fMq  i}^Thv]_hA › 4"UyK9B@g!5i=I3N?`vg?ɶ;iv˥@t7 \v8EV,vU \fz ]d71(aruS0sr9B@(-J(r5/tIŧ;TW* g pqPYTҤCjlwrAoV'>pusWT$ʬ\T桮.E%pX $vUz/OF"HD(|#> qC?]OBq=/1o>Wojr,tO )z%4=.\\dPrp:Q$r?䆪DQ[cTښ ^WW$d*ipwlB@Tz_ɟؑY۾݊JB/Mpq[m 9).π^+IBED3*xy{#:2hq|"lN3(a bogWUԣ?r E,dd"#__V{W‹xCA w+>xˢ-6Nuq\}}H(bȵYā 7" !,p7;KPszu2tI7FMmEϿ\mՏ;-F5oBő >lEL20Zka dQVG?#^ijZhdaR =)DZZv9(-Sbbd7_ mkO;2v=YVdW5u-\`q w"mE 5xaC0jAWP;Zk~ o]x*IXI8QEd%MAY)&qre!07Wp&'D",/Ζ塼4Z>n)F7X%J7?L%R*!B" ͮH9J[ƥ\3lB[)B@&YzKMZKk@W\F9œ79g*F#G3UW49nE[Jy{ T86ޫ5̓c .dNF#ȥ-WpDrQ5?w6%7yp 7`ꔳTB>Ir,O? C{^U !YA9@iItrk#'dlEBk 4 WO1h BݘUk 3r" r[DBGRjTB['o^w0=:hoN=] <PSEɧ}S/ڿR؏Yaܺ"7 sQuH@j@[ܐYj4mӣ2Bu"b]1 |Pvp4lCpx<>ڼޞ6/rm@M2Xo ENbP F#xG ˏ>dr(@yy9 QHBHvZ: GiF&sQݴ"lA > H?&QFj|; &Ssߖ>xW&.|\@D`PpiGwj ~c( ltEHV o4ZG􃻉%uIa%N_PY^h#1҅eYZ d! tGH4%] //wW’r74Mи'Aͻ]~ kH@k%ziYx;cC麩V?%K:(TMLĝc"<52UzJεgr6daKؓ_oi]/MWZb[`lj]g{,[iD?&"6CCl  đxJZ(|=T`?GuLnSX'?/D[X?O:B@oxٞ$! xK/VFZ MlI)S, ^DHYV6*({!ȝ!$ņw-$dqf(@ o #\Fd#&Ϲ^~/qOԔC! , _E|_!qYmGdL;2SrX63Tr#evXY-}HH E ݝn7r4k~CyE%=SʤJkݱ<~Ռ _8ޛu -i]*նy#q`kk Hb s #aI&PYYIHFX C!=GrPWT'y^M.ZY}a֪ۚID`ז8p\ѴeՕ$! :$*.lT,LP"ʯ,ib^~ʕQPH (ɵQ(^3V91YP#cev'^YTg Ǥ &.\)B@ z>x<X U踘,;LSF b)FG\ɅôG9L)byyPuw;-_AD讴+_xQo!>8xS);Y8$4xzJ$ jypӢ; bi;9n$xu83A EcUcoA92ʫCBFfy $F`Rlvpޗ;IQ L3mac%$! K?(H~A6</ G@+6Mu-xdxR (,*ķ?>+F9:}Jl2!г pL%(yD^8Hbv`PT.hwFL2"j]*#qs>WpIĨ,%1~ nċ/Mh$lAo^K ! @j(f&gG3PE/󙦈@ϖJ v?YQmm_9 & {_~H΀eL7X_SпzJbҕ]w$qX#njFWZgS,ZJ 6akzvوx IOm=,eYRF.r8m|MfHGB]hŒb@O{"mdjrZ 4'ϿZU)B@ k>8? ! tFD !!D!$HIqv\\\Uu^gq/Ǩ2HjoL G:&ᡊ&zI YLmTDMu% $\Ԩ8-5*YW3\Sw P{w/xy+k}v{0zLR Gs8v%őLv+9onBT"WU䊊 ȖGNaro_T" A,=B!D҉F`5fZ4}`Wol9Gډ25u,n7CǂLmӂg;=hcz?:[\DO\b$Оi@fw_uqGO=&Ot ;ܷy+-1_l۽xR&&7XgNއabr ! F4HYi>Eg+Ⱥ#Eⷮ)r0.~-]fǚ(Vl ,,ϋHP1-&,WS[͋u@&y8E„wcH xXmo8Z .K?LvK΅Bu}w1%GjFYq: .RyGUtm!e7tA `Wby-DQ("RBI $) RvMH{߲Ν;mknVU'_,.\~5j@ew\+OoJ.j+GuT< k/,.u(AִŔ!I %9,Ej)ɂ_/3@VrKwn`9]7 nYOT3k n)E n9qݪWFKv;ŋ) L) aђ17,R#K<{x|H҆-o.|pfg 'I ̲":!ђj2 [[OW,9{Mx~-V1zH~I ѣR͌'=$l bг o;jj!}O쌅;r[G pг0NQ6Sx"<:w՘!֘ttt!AD=f91H!2&A!UҢfs(1)"w.2;"9 D@|RH&p$e%,9{)~ xn8ĚJ#Z֨פ{=t.,fW;f"r9lrl7ZjbkX9KFr*eB@&̢DY9{-PB'XԔa~ʄK̅,/kֆǡn;Vzp7k- [6)O@]tǟwX 1(1ňYF%; tU_]zZhh@pzLnCr8i"@m܅W۫E"1py`kh=!bB,7c#pуj{j DtH}nbXZ D@ԲWS\U]MDEUM S`/x`z~~~{Ccţw I3Ͻj5Pq +EK켞' NSq.= ,Jj1qdѝ5@Xur1[JF̵VڂoVO=eKƷV.my.ߢ7đy흌s7E:% J '/F|wyǟ`@fad7f8BV,e8"hD=NB b()MDh")ODl5&AǫjZpK n oW"#>29p{ߠZ&-['[kUor]$ 5[8P#`.}>e(f`Ѯ0\)¨(LSbLĭ5& 40f q#(~xYƴx jHk|ۘP6Fx]QQ3sa Q[:%M3| <ݳ_Htێ[npsE(d JD]n5r.]{s;"vJ%`.jjhviyOAS?y.ןC[f|']v$şnC"@4)=W D@pRbz\շ\pnu9Z?/C.،Zs-#@7ː𞕕nm˅28-1r05Ě;nj~-sU.z(VF{Ŕ YY-)M1oSU%%' ..^OJYs%X}Q73Qx/e"pQ9R,"@ D"ЧJ+"=8s5-O|ϥu43_֘w|U e@6< # 5i=nُ;AAAXfPK{Q0zh <| s?8{{.DK](X}f"d +'1 $:emߎYhsd]17k Ruu5vރ;wAea 3O7$;WH hCa=q mP D"@@e !6)CIJCa s,Id1q N]`q^ͱ兢޼x,5i=aVu$z=`Ѽ'|_ 7ұ'JB&Ȃy/s 3{x;;B; n D@ p6OTS|i)##m/\}~)$AZehB\Cc봾Ήh$^d-xE8i`>mF"@ DDoNHA$rĥfŽFR! &tyܺR%_^}x{" 5i=w$z^?<~W̞=EfΜ+W_nqMO0U@eN`d*2eD-&NꌄNz@ii).[G\0sX cmRD"@ K@ƾ3$ Aǹ+)i1 S#C r#-Y0 dgݞw"uI #cԩػw# E111ǔ)S_ʉ'*c27F / BE#mnp6Qn"@4{gan{kncf_wލ?v*Y \4daAFO@bf*މF;6T+A=-_<~ ( D"@ Gd[uTY͓=kʼe:@ye5}o-jdXÂ%L.4]xoH7rssѿ yܵUBBu}u}܍< E#RnLU XR?AMHOLsk4++[pyq<] ,!ع~O·#юxiE 5!aK^ː17s`j!D"@!TLRƬ湫*n_IoquS")8Zњg{8]9ܜ`iFY|=#O~l#Խľ&MG7zIC`*ƨF"@Ԗ.&IDzY0ChH]{X^E@fP:$!+fַ9z; G"@ D@l=xՕ87]aflԕNx{o8w% ތYoT#b_&ѣ'u EDG|[pWUg'XgC廏@ E|p45,!qf:w_#T Ak.È$̔+?m=~L4\Uq-,qx3B~n.J D0{cUR 2"@ DHcV5UiE`hMKg$r=6܅}B ͏A&n:=n_!LpqqAjj*JJJ`j2+377Xa'Ph.]'q:=_ha+Lcj%D@] T1@@QafCws"bQb@KO ~%Y6? gѶr"@ D M"8^4ÒE (a{z_} /«pjZ+40 ;=&M">>-Z===1g/-r" L=GapPBs{E"4 x};\M ܂qغm*+`*(940!Dbn`WQ"D:3p0*C|=K%"@ D&P~45BGqYcCeꂻ ^Ղb/W%)vB xN55}MDno~mݻ'On? &`xg[\SD޶*eYr/ eXg 倵ӆՂfiQ!XN}_׆TXX-?o\^  IJe'h>ˑgtm+kECtBv1Oyy0bV AWU[tH@la9KU&x./ q1q& F ( [`Ka;r(Q%D!ŏ?dzo/#>D"@ 𵯜’bF'E ])vLDks^ho֬C=bm& 3sZnFmՠcb_&ѣ&QGob̙8u._"СCV]qm}$NeUx`~l\luӇB^"sJxOideȹdruuW1W[w8€mo‚zD@ pz$Y ČOCD"@U|7~f^4{/()Nix][*T-5MFOw;#r" tNJG̭TpCy.X|1,\tľ&M  B5 mB\|p9dڵ_vgl%0G~P"D"@ D@= ܨ *$&bMV^MׁP7DxJ.åbpIoQ7>4Rn&D@|SLs/ 1l#JKK˾`N Kd=&1`9;gVgN e0 tD D> \P=T *b?ve*N4@+8 V<0OFE D@5<(8 cwSDU 9.Sj2T5%g{P*Bp(\.lwksa҃T),bpy"K4u?,_~]SsjI衆y>Ջ@Tv`q*-OlW: 6mc֨ȨD$|w)ND@xj1T8OHL\^]zU8ŝ.^Hj32<"+wgZ F 58KQǾ+K::`c~.@s<G`\{GKtIb_&ѣTl>Ƌ5IEeX7倵ӆ¸k]Dh &:USmJ nwn1 .,,0wtrW7:g\ zv!Ms@:*QN"`6r1ZŀK D@t&g-1DOOʰc,͙HޯeFnkD@m p?Z]nŰ01R۱už&MG_ϐl_GxcLb\ ^5a)"@(fbR=˫͈w u@}v6X+H@QQ> YkJ0l# D% 7"r؂*[kX6rҌ6‘h&6S0wh;afF%5i=zadb`=9voW!<@IDAT2AHg>}!j&Ő$!5GةؼG;f4ykQuI_x.'ةD{26j=t D" ~eU8u:l<'}lS@gL(XlpT:bN@3R_ſu>=]fWPUb_&C')rb`"F]M{N#ґ~x{`HE7*xx>H};=`ۀ`] fϜZ\xs | GȊ ^4P"棻-rt"@5=C̺#69In̥x܂Wz,9" Fϯ9x)5_]}ľ&MPktU TjΑ(||<<蹷)>}h"@z@Dn)^;}BVx9O vBQN=_ \pw#=G'_A~`wL@ØnD@ID4^["@\ ɨaxmfo#经E Ɔ>fHx8#ӹE"ВgpŪg絼Hg*4*=F/9Yw8E[ cQ7>4Rl"D@ ^WODfbc) w3CF#7/iӐ]55e?>r?=(L4 ('Cz< w"]P"D"@I{,XteeL)`/W29k+UGpQ/JD(' âAQY>xb.+ }MDM}2>ԇ$F Ș;U'/Px8˩7a0Qt?&{]K/!ܽ Lccc̹{F{D_!eA0H--c=m:4VF ?;-z.}ɇ![۝"@ ""s6aWWT3 F]@MANa {Ҝ̚_YzA'D@)ö0:h ^|`rtA1IM.`RVS)9EXȬ>N MwŚ`clSMRDh./ڣu\^E?/\rwsã uiο)r4y!')yktϪ5| *Q'ч/4~4@"@ b&PXRCF׮\u?F ]1F4@so9G.4j i0LG7=FZ_qv_\DZKC VN!ނnZ'D@ ld' GNNn˫yEӈ % 7`u6t ,Wс{+n D"@L"$752ĸ!~=x |]ot ӍD|={nʴnIRLRo@RQ9qBMvpZ`t; H J'P\SRdǙ۫=aq=0瞻1[n\KT N]MDgaꤍhZJC|nZJM Dw ( H^B`7+}0P@rr^^L ŐSlZf}MDM}2>ԇ$' l'<5ظy3҅B0z,!s+ɬ>);X] t$4Me( }+ H4fL4"@ M != Hh,NG7iMo?jt\'*4*>H+7Wj:g.Rˡ#io=j)nAx'c-Alݶ UJsyם(xEv.ɞY}< { .ut@ 6tUpF Dh+b! < 9nB$֩AVS%h^XR-@O5Iv[k$z|>}TF#QD eeo-T#0 2jKyӅV=v ߀=y!!{&ŭCblND@ ش蟒#Sgx~!t 4z48"@ ]%PR^#.:bY '3cCBɻʕ#b! ô!H"5i=Ty".# &bt58E[,,V. ǓLJDx D@ TopWHD}Uy5lj7#aF;{:$PZ\xAm@1sWb1 D P-1 W$wKxmAɵb* @1^1//ܢ>IUO09 L%yٗHSC|9&sQPoOX_SLj--f.$4U.݌KkC]v{g 'aПb wDR=GY 6嶎nD"@4@=h\WG!ݙ#729hPZM_ y(0KhJ4??_=@hD VaiyBf2clՆhuExxg =3?0`{CBBP}~GC}=$f{j.|,.%"R\E— )@Ё-ptilD"Ж@|Z6E\ɨ/.m*bt d}X@r|: D@ħgc?P -ž&MG{OO }BꢈԳ#V`i( !X4"@ԊIyxY|D v6Ԕȿ-sW ;[[\B35#n<~l_. !5:W?5%W:O=&D"!Uv]n!D@] ϸ%3'``uF[k$z4F>znT&H**Ò=?.C^X;&YM~46"Гy*:LD;'-?S'ߎg΀ ΋.]eς/ȡM ǿw/m;6榐|: D"@'ɍX@r_2Nv<'p<2>q7l,Gin;ž&MG;O.}Cx l':*1?+BӔvz3AT D@ 1#N&.ʰmw [+k++̽w< ,PkT40v`^9l* 4~-'KTE%X #n*2cq"@fP[B3 ZM&\rJ{<פ;=jkkk.߿aaa@QQPL2wy'LLhv{'}ĘN"PXYW>ow[HQ\_)KpxDe)"@Bb^q'r`Y_YY9j#c CV<%MD@ wB-#sQ_U_v;`Ԋ0СD#.#bcQv2 77JD~;t [P?`VKt܌פuuuꫯ 33ِK/###Ņ( }uB%jR8ܱadV!j@N8!5urP߄S,'9se;vEYJ k  =wV,zC7HAԣ/JeÈ 5' 庀q-dc͟d`tA ZJ?~2 H~$oQ+3ڰӃMT"-|Ș!/<G+ӶBb_V(z{Ņ 0uTL4 pqq5R)d2KDDEEa߾}ؽ{7\]]/ ((H۞uWOPI`uX,~I|03<Px]-F1=N&W9 hPDTϕ#R\ Jjj $FU_BMLYG527QxwwiGu" :ؾyuudbGf5ˆ{8F0?Ot"@f/AHo= H>$4N "!/ۏOGaژ!Xxb_n#z8qӦM^+W\Xಳc۶m8pn&Uor]$ amD HRv|E.xs`xZNfFM!S D@N RIXs! Ulq>Qu|: Ħ<A(ZHO?_YR]g׽/*KNCyrzqiR d%,7GYaL\`tl}rЊ} A#*5gy8L R!"@  nUGT| 7P@rU R9"@:Co~At|`->($ 5̙31yd,^(pgСCB.NH@LaP1"2Ňsc4>2=9 e^a*e.nhv`i(&4 "r[`w|+7%"@@\q%\M P/-?cӁ7T)l'25%bHevj!$$ x-Sbn&!vahgB1t1Uk]:ADIp&=N$D9X@rS$A;n a~ow"@@wK2+ZjVk-Dc D@.z(볲@,81B. "H(RRf9ҸC[Qeu1mlQB_q<"iܻϜŞR=D;A}6JW]Zfy68 c`bb^01f/vlbtFxʬ\T BII\"j+*ۭB.p+n-"XcC[f=u,]~tQ9ުhVVT+-T6$ (A s6a9"DiY@ D='.\A5KYˬ`o @ouݪ6 D=ܚ#/~׺kb_&Cͧ'͕uts PXB[" }g%naBD=('jFwrLz,.<|c:]G* 0:dڢ3uaSc@laSfM"a/#A1Db LtuEKkIyz&X@2QDHЏ9"F ȼH>JlOLٛ)lѝnvK8zq|j_NY %(s= /OOD;/6: a֒v-ܙ='"@ԗ@qY;6 `1raK("@@ye5}o-Y [N} Q)5n=F ѣ|)O0MN"rD 9(oV^>Mm)̤͋1 }L@ne_Rb[z=ZVOŊJ҂*TԢZ 6~͠RJʹX^EEE[o^m~iO osS0.(W'bV%aڕ2QWp,v!{°h=(%~)БH`doX:fbseaަ/ݝ x7[Eg d)l;5 F~˿[8z7̘+o¨$z쓡ډ A@Y@rCc}cER/fXo;yGc =NNk*zp.Ǐ*z>nt|t?Pgy,r1R{n,C|"Уbzt{%s!TȄҚ:2$-@yUud\$ fl自~E>/JUIt%T(iϧ'l}>[ؗJ˪!e9*Ъ_@b }csOR0^, +c$G؋/^_dשqRœE2g61KrD I>}ՙKf Hɵs>Ш:-ēlDO^[ #N˟פ6I$vtG!PC+:XT үmVl^ `gWf9^s:B"%"@zZҦF;k*ҥCP\ 4~oE_I-PZZ)(.@1X*HYmdL-VPð50bQRި *J{/ceȰZQ:."_~F+|yN"QWYє\?vJ ďt#:M+\_Ig0c0-z,=^쪚%Оi/5bx"̟ .@QVEW+ -x4=D=9Q r71\c^Z\2ԱwRX3c揿L/\=fr qb+(70D̆dtL|Qcfz 34sa]UE]n;*F%/}B/j'`a= D#TL-gQB@k6VmXʆDPg/%~yycNk*o&>33WӜ|0c ̞=)z'Xb{b`UJq#n\Ypu]24~Aa2ܵ]|"@@s%!r%ii(c=+3Pzde">O?wE'gD3$`S 3`&BLZ=? R1~Vaef!|Z/4ߡAXD "#r㷳m#1#L),i*k632 "SlDzn^wFx(b_VIؼy3ϟ/ @TTT} ǂ _4A  r2r'&N(,m&pQ۬28YYNJo `TUdVD&$t@@'3(MIC', $iL A-%%k7ȴ)s5V?^!ss{Ӂ TWW#D&_]d_Ѧ*q?9 B`/U0&1 CוC b"XxwbZEk*AAA0`x L4 -`nذ .ڵkxg }v"@:C "),z`RʬEq8-GDtutEUc!L Mr_\ؘ8L !7Wy2T~cdw!J8C33H~\ԋ'qyoJE%"@srK+)Hc fYϷ>_K|mo ݷ>("@4@9s{kQ-\jsJ9233,XaQQ,--燘m~޽>vO^B "eeUEE\*k :jX!^56=;`b ; #C  ;iKMj}}Dz!(O.yXs#Gp}=^N5G _G[0W jF/>% ")76> D@s)p ?_C¾ W\㢾"@:K -Oca,ܴ5}MZ%c޼y{>Hs|ǰn:x{{ʕ+ PfQSDbz sƪCYZ d"ʏE" = %dJ[8=L,Y؉H47+,. ""PRRM}ro }x:)~sgsLU ąȦk`y2F%,ߧ@Xժ Dt@{:{)>KIBi.pL>w bZWuP]&Dhw}>&)cq-5g`פT믿bҥEee%Ξ= .9rD D@ G [qqQl(/\bUTB +kDF ~,˫PnB\$iLP"&FB,} Ix112[P!5p1^ρ@̈́1 ^;6!3%k6BaSҏ!fV D7ȹ,2s 1ed0Mh P{FD'aàK |*Yz8psAqEYf_e\檚,G a#6U*`9r]nE \s.pD& &v.BnFzc.76; Kkߓwibtz{[^Vk7#qܵ}# 3JD"5ulc?gˎ"S#C? v62ǑK/% i7x8DTӟ~|tT'jZZ>HIIbxG^h$ønJ$F"@@:$r cI*HdG[pQD.ڒ eЪ6a: jB[~GQeKj᜞&of;'a>SMFE@E|2⇠v)S"Djdv=)f7@Ow͹o(%"@&ǂeAs5yJ&5NJGI'X IcF!D;r͝Vs$ _ڽ)ܪ &.0v- -s@SbzXYSң "e2<7(O?os[.$(E{ɓ joEr NT Y^Gpzؗ\d^Ȝh̹nL}ꘟ]pe(jǬn#0f8IRWبNJ&tUfj1uBl&k8:e~pwRt D$c/43ƺWkeI;JΜ9 [Ɛ!CyOQ#1: D@(ςPZ lr(l-n|a"WӉxLnc]qwsG[8/D}g$O.&<2XVEM9/d.`h.΅TMGC&D@[ \NO1#keny`Y̲Ůbq"@zsmFRf.{ƅX;bXk*W4T@*6ۃ(z:V D@ Eeںz珄x[`cl8"ЊRX 6&ۄ 10sy7TmBD ?!?EЗ5Y;1蓠^zKx~4.% pƝcCakiDhD!c%}~x:gFEЊפU=ƌ~Ƃ7½U 9w\l۶ tkOZ?9"}VTid͙Lh/s#|!J"L&ÎǮ|Ϝg .tSb f^pNx=x$B6(O|Rb jZ? u-p $Sjȹ:ČPBǔ071j>4x"@@oa %0ž76ľ&sN<1uTܺ/!9tm'6= + D@,eñ/q`1U,]~!ͬ7\Ey><W^^-P#=q+*2k&p1^f2Ey:7*{Wߡhm{vqzG %;O!f#ad 4N"@(l{:%\v4Q;!5iDO?/ n١(k+WTtz'X&D쾜L+(J1n`;D W)d!yz8t3wy5ajj*/*3}돬cA+Yw@-LQRHMHOAP zmP =C&v3ˎbksS7 o DgZ D]%eXBo_Y٬Ik*Aq> BVV*(( ̙R%4 D@\[/FX}`;>8v&C X|',28abbٳfb(MHF Q]X$\73띓>X5Ho}KQ(3&`^"v*V{OGqY=K̾uXOWWD&Dh܍㑗1166tD֣khhPu9:9b`=7r"@:Co3+6a٨Axu? H*XX;/ 7ÃZ/O|kjpѰ2rӡ+6Ӂ`; &ЏwWjY`j0" @Rpa/<*x&P?ZQH}$D@k&g5?_{ ==פoH'&SM"@+ ta^Vx`P4 W\qٻ{  j%cXbzݔͦn$&QGcW,QT)Jo=ЧR0]sg̜{yzZdW$ZEU_:]msC]̝; .>#I"/Xӎ^]" H%2 cGi|/ʺmR"? uuv/gD^7?_̚9ܔe::-ۂQS&ˌ0qqj22SӐ|" ׳jzg:3 D";8ᝪCф0ip8kȁ EǹZhg -=vvu{nͯV<H&gdMC7϶ŭs{իљ9>| Q1qD|7"m ْD@" -sVT”>^'H4[Xev0,e)233WӦ>ceyib-`qIr}up92Ik}缅tzit:AF)-hD.^{KdK}1";:9ԞnfZkXkGSָ,(4.voͧ&6͵n>'add$qc+6/0`;&:8Saa!lmmQ\\Eh D@" h;\;{#\ >!(SD"TV`x/ş7 IX+zB+eá"#i^Ъ<:kC0RtJZA5ʇ ANmWަ@vQ" hLNFb8_f}0qP/[ըk4f{^,7ddd e y hr 0? ޜ s>}:x '|@*?X/]'|RN>9lD@"Ъ{:4"gqq~Zd%M.3I0wC|0Yt)DMK^j^p5(L&Cc ǁ}eGS?FJ|"[7m{"Jnxpt(BhάY9|($h_̟<Om0iF+":qxӧW)S}|;$m93D@" Ug]^P  魪kv"c]ldt_'"?"1,[*WS;XUJ#'DG_̽<9mxms [i?Ct<]l1Vi|JDN'qznfbabts[o_t/*3GYy&>~kVj+7Б/zYkkW_>'QVVz ˗/9,XQF Px lٲyyyW/|h |HȖ$D)(,gGs(!y_x쏎!D@"P&cK(_+SD$\}X<3c:)zNSѵTĮX/?J2Du]CCBOv}H;z N*&PI L]a~a?V<@%ҍغŴl (:L5()H$͍@I=͇N#-;W4ocaƨ>mr1noX37„"37l'a[BRC moJ_ )xBPk;z9iH h &$DH-~GƁ7C1;:l!Ui"*-q^b1.\}BB0`Gxwhg}"=@ .:h5qc/,I3iz6=IQYD>Jr/ԧsU%z3}9:#ZeD@"2&":srƔ}IntLjPxz!oݔk2zϊKJD }@IDATyC hZv!p(Xlf9LmG++/H$uM|8.8G/ d_<HJHGcb+:[$HdXf- h€Vj> }+6u(˩YQof Ie棰z7U֩v8#:ՎꐑJ':NY9X.eH:KBb5ܩ)ܻ9믟cH])+J$@AQ  #/*7ruי&X,T&#uXnyx2NyXD@"4,D&-bpTxwjZ>']:u* p^g~g!{iӦ{Ah pD@" h xcWr 0wuzӪckD(,,Odl߹`cmu_*/"y,Z(?8Ӑ">0wkJ$w=DZ|axjjQmEz$$$W^0s̻FwŊx饗k. ȊG@_ۏ@H$֊@iU/">>0}}A=`Ns2I$ #PP^ c=ҤEܕx,^,}ɿGw̚9.ε2+YgU LϬM}E r%HPɏ: Rj"nw`ooWL^Hl} #/"a6\Z9cDv qGx$I;AK$n4薖>ZCU5hU>{Ū03S`{F$$fbծ8#>uwqp& 'jo.3%*e˰g>1"99 ..xhD9mr25/ %qcHi5LD%n>z Z MҦI#=cҤIHJJD3f 333?a:x2a֭[sN2Pn@Mk#/X3D@" hJqj*`'k|9x8a˱IĂܷR Kagl_FaGyAA޶cppp3dttfT *'c2W2OOj$Q&PI#fz0}isMړe$װdJN_g{ࡡ}ԆVBsm|kSOaa%0)zt)N:%ysfEFi3k\WZ #O_<jZ҃/))'|oVio!d8NA@_AA"H$ڄIxe)\.bdžL)"hQr)c޾ X*# )qr /XqΫ;gxvvv^͈Y IvnD݆+&ᥧǽ> XqD$2sd@e ՓJzYp5`=yA" hѱX'B7o& y] 7o_ǯ\)NұXDG^^}pL~p,Nڔe%x8g1Sí5mnP# ׬={pT 4KKK899_~=zח ܚk/Xs ۑH$B N}+->M= #}AMK!2WF&#QJ3vfX;ƢK}vy d% ﵘD(FưiqF$8ucr 9mjl {a\@Xt4i-ClEpw  92SInx>X0olt,譐]m+;{ ζVgnƭsҷ%=Zg#.H$b| _F%iۘx/DxlY!|Z_x† V+'-YiU^OSWAQ5q;Z:vp?>}\Y=_^o8-Jeffp$)Arz'Wv ݻiHn7iVEf{Drj˵LmGkzU_05]YD@";N@|jI?; |>:wPvr;AYаT %(PW3gζԣ'h9w"lI:c~B߬#\.T{cdܟ"";^xn7}n7֮[M[=˜;k&{6雬#h/I[ ?pIKңbrxe%D`&?bŝGvv"^no-I&رsVtxh;['bWlQR3ޟy35yw*Y%{$vDѱ0 Ƌ)wԓ^`ɵC.խ񠹫e% PTRMNaYc =kSj]o))s!5৅`0NٴI&D"PX\YRkվ6-.4q'ju-;9S?KB1`FZ״D$Kd5D@" h1i%mzOF–dHn"1c0nf#&_&P F5  P)xEHذV#Z7 0*BVAEfzyv|Nw&tWW.v+KR4`ˑ0u4yŢޮxtd?XO\T+F#-X'o^/Y9͑ (V^4155œM^w9l=#`=}:|[ӓa^ҊsIzhcNH5%De,*Ň 866c~??"D@"|q;t {`n:݋~YĤ$͒WR>2CAGl^7q9`Yt5mv}`W!ujsFmzHsrX.0ჿ:Lv WO`(a;г{{Aw?,sт`2!<Ѓ-9- K]K_$4 x%0$߼_ޝG^QڿO]ǴX<#M=U`KWGK?پD@" +2,nckFcZ֗z%d]H/.!~ #j+VlZ$JD`򃓠hdGa'%JZc`* d숢3uO"A{&;CkTf4 !{^ Xj8N$pw$Bd4H=dF3 5p$- ?/ @6A>r ɛ6xyѽ{bѢƯ~G~A͜B^Q=B8$4>\0k0Lԫh;f???|?[Mz緗ǝcU5$UCvF" Hq0iMwa/􂿃Xe6@Ja)'1 :4SFp'|tuj˯dggfN5c{4 zFŤ7 d[6s/n8M&}! b7FQHۏRR?{W١^|=ĞG B֍wT# ''zudDPIIClXHn@II ;\4̦ S[k΋d3}d瞝C[ ٖD] p2:,6XV%+DŽ7,oVGѿluć$=Z$=ZݗH$Z/H@&' G{ԨVYy"hOTia xx家NT Kf,Z5SlR:>,,,Ԗ$(5'^h(n0ſ`P[<9cDHƉp\雲"pKb)l{$=U1jm$tc )NVH357[g 0t6,VkX8N_G$9"&#&Zd.@zz:ixS tA)$ƌǧ=*H徲D@"p^ 狑wf<ݼn^#UAVN> 4=1IVk%1}q믿h"{ $I%@{D |>=r_ҊJX}0$$yx|Y|9 &uM.bZf-x &}t3z]醟>s& m(ݺW+I1( aQ(̮[LIR4] XAXҌL\y_;| 7{Iv776oقtFndnHj2Il>tїѷw-i^=˞kU}=IB`ge.&GYO׮xao& `ێ4tppgGJqi}YL"*c7~RHɖE,Eqq1ϣk.iʟ%"?***`ii'm5y&P+څ4\{Sswt *+DT"b8NdF((:t^͍`lA1Lx/yo\Sa۾ҭ~>\{vufs'O'I:V 88OVd}3 IfY6!H$Z{~ ԂaD'oT;kEe'$-0=\v 6m[yy0P刌cFj+5j˨v 6P+ H?FH=k]$H$GƧϡ$SL znH}4-jW.eDŽ^X8V2K]bٍ_~]pq'g?3Vn<E>wVDH+bbT{vmh ZcuiN9þȎq;K.' `(֡U<>f=Zuz?Z\etJ&Ց7[8?[hpO(?{dxEIϔ<3{Ojce^g>|9E 7v+>7VN6$W⯱Vwk"jyq<[Qy.a;5烉2B3? ?N]BѾ{06eq,:c>n"-дwR++0}cwRʪONlR~q1ΕU542I$D@" hJ: ;{#{d ~ 㩀WS@["}xRx1=0gyMɴ<,-u I8_+J_Bi(֔LMHڊiS\8hebS3vrXV |  6HVq =h͑g7voL1(a9jj1qµxAE]ݑbcHHH@Nn.)2@M*--V""PUUSh8.]Mp56*I䳩LDVYM[ ՗QXIsE#G Q,u),mb=..#M_qsѵmrԽlw'2rgX i%a$:2SVSB"$,碘/we5}c}u4䄑!X*c:W^\\_5u?Gi~aE.dj$$lWJR#7Y`\X;9awyGD@" H$M ~{?^Xb:(~8C~M33DmxbYaޞxt0!$MУR8dD~7W5NM7xyQz#!3bHuPl\ě{yԒŲ 4+4bOljoOK7~[r=di!pT􅎯zY /bo }zwwwͽ\ݠW+|_bL 2]z|>;Löc{,r D]sScOx\X#heFBT|+~ _볠Һ0Ykko]e3kOjCw2u˪֓wq)Rꒉ r@ G[T a$#`B75D{Zeu?og )-їѯGjP\4i._ &&W7[x'fsD@" H$M@_W[yf N;w`Jww|>:,L}ys6!N qj6m``

E.E$VaD4-DKvH7 7z9# _.pdFSUU $4߳6|8 )C%႞.ȂnQ:ۃ|qc޳̒j*)ؽgR/|{)f,\%d733$3ƃ?U?s<8GԴCABRPZPlZjHDrwK';݌Ġ7#2X KKz`@~s7?Iz4шXjذaꫯo>\~]| ٳ'~mLJ2I$D@" h#Dr< FalIaȫrZ`IF?sݬp">I\սOڼ5WK~EܕxBjSORTV&pNg%Ԛ<%4ax'(/6?Kc%BXR˪[W%"һvPGZc"6)7N;r yBQF&KUK|ȡ,p6ڧ\ KZp)V8yWB^Iء |kwy1jȻYC#j{46D!xI9Rz$9ZiwƹD\II&d yC%OC@%z [H$!Wp57'#߇=)#mD 7oW<ձcGLҍ5n) %EDH=$qXR[! b7FuTk1Mgm {CErgEa}u1 !}a9m>u,CC}&mPB3<0~ZHLJZ$fld,)Šɦi^Stl8pGĠB`m{ax05)+'"F#FvKOԨ,9EEEK `٬($@X d蠁pZ,NDQyU/@ffhV~/χ?׮[8a3gO{VH#$ *#=]Ie&#h?>$"9c3Մ^< lُO mm{x)X8CP̓H$Dp!>^ヿi#:I~FE *N]24U,yy& sR%A0#$tn>M3 _hKI-|1BDԊhbYBknV#^a,:&F?rZYv7t<>aHW^qt!I~uF?'U/<=<犃W#++*iQ0Ç r+8ХFFF\1oaaQϧDY:;B#*Z稙>«#څ!;'[_MDY%U#" HģS'PCQW25:Ld\KN2FQYYE.*(:%ٱ{F  zg-_m;v B/^zy{蠷d&{ ?qq˯94 sV6"Bᛢ:g)us}B݅₝ |_ϣ~qLq <Oˎ%{Pfuk$ @fD" H$@ g~oL Fòc J6)hY`–H|;O:6'''բ_(n U$khFiS3k v;4J1Ⲽ|dESdgED-EtG7f};TSOAY!KrXdnoV/lX{i9Ơ& I/2&as+W3TPGPq2Hu)䂒]~j7o݂D*:/K 3|2(D&9zk4[?RSR*&WdBNPʘ|}=Jy#9zTLLWVV">;YL?u[ݦ^+))F]daWŦ*u?S&WܵW픗_Sceh_#oAL3O=ƍknAx?bax~&,$BeF &|*83CI~'PFu44L#;\E_۞ iUvVs+ q_6v_[.==lT{n[$D@" h  ]]mY%& /;zJd6_@Ni:W3P_m)$8ݻcŚm^O*؅#?lԬ@om. bpl鴱QzzDH]t H{&լ,J^<4ao֗hsyYTL`?q7Mx,BZ #l:aS⑇GtWd>OV3I¿glžΝiD)QF##J<.^Q^좼ğ3愺h8ƨ c{^ q!Q340!OzſI-ơ#G1o, 'eEe|^T{z=䏞{ДPE{0X&C t! 7dHz ;vhV$D@" 43ld޳3>/簌VshfyjWI"t7:c֞uH11ȹa%^m_( gw#G1zHђێ?(L#EiaKc^޻~ta3wścG';Ѩ m> H83g?cFEsΡGSH$D@"8 }lHq >nϧ/K^VDvJ"pL)n?!煿ujIGgOX#,<\H(*>FgOOtM[tů:qy>2A dbkEdFS+0bI-K.($#y5$/sǥ7CQTWZ]?WSP WVD;)ң{S7gvr由f Jb*o o尼9>)?m zT=UTxo==nyOu- Pԕm<\th<$'a4$?3y_)ض};z4@()7WT3~a;&߭=6tX ?dzc̨x|ڣ m1 PALM2%!M{ ebB .%^C7) X1}t\t閤mڑ%D@" h%|\1??GbKL2v^üpXOXI|pS~Gc˭#2F ?7l+7n"߳was1xB3>!qqWp!&4KƬ'.$"B(*RBSCsĄcXSRQ|N:Y8c *):Dėo__$_X,XGm'򏟂eUr 姱V.c]s+2gøQyqn1̫k׭Z8|'t`!qؽ_9%H{=x{yD>V jbfM0Ï^ ھC!sgBlI(*©?"pj]$үJQFv. tk h1X/=1$=nXW5"=~m̚5 nnn EDD ((HF{4"H$"O&q'<("@. QW`G}h鳓jF7GV;ϡ ش\aZ:45R>> L9D +WKHRR:,Ӥ{NOWtZQ[*ØTADvTҌ.Ms:nJfҥY95[63P"T:oKDT=J#9bUsQn`eQ{nU*)ث8{M nzݽ \1G1aiچÜTO5:8AKTCLD$a?TܺPƣ_УLe^j8.:* ]_;jsEEvt\΄Ht9b3^YKiLIݰP,8`Yгkv3y 7=uӅet}ۗje.=M,V'uS'WnKUqycRL^g?Si!gWJ9O|RRQjmT@_7ԁae9&^J8rDŽH3r%>c.0ew}u49+lW"\Y9K4p̧gӢE;/ ӟlNceTǞT Y:[8,;ŕ%6<#1!29չOχk+T" H$@AĐB\x$WO.daÅ^%D&@[Adj a^c;rP'~ 1|h?xCٯ++++6Ϋ$y6p"ba"Ib$FQ V5Q ,ŲX^^b@;:`N 3y啢+sI(+A%T|eVFJ|[ !ũii" i4FG( FOkkJ=vG7O`Y"I= ]ؓHkHuu$˵Dv #1K}),{|8#VQ(L#ң&+ I'gRť;uPkHE BQm?5̅T6[-x~N<}Ŧ8Zcd%Qyάp֌ NDp>}^":2hxn)lEErll3e?!H&;_Z[š?ցCDRdG a83eF |xQ!b r@]]40GZ]չ3٫ &ʑ2@ ]2xռtފh䈈(!r&NSD"„(Q$U9r0a-d|n7.ڨqq2Q ! =w[e$]?,;B#*]ۘܽZedƒ'0:'l)mJQB #Z7u$:_uE9սIS$c5j!y'|9L{d Q4:6yEvr C('8_uZ|m8mt~.vu8z&lp.ӝ!oF6t{bMD$D@" %;X!VVI0!3>sTA/HcL^?| [.`KQ?5cSz6 =0& 3-EEE$'"LXb% r:,\=QbY>sP&Ҩ" 9{*"-E4 aRN> oB D]4R(#;2q؏ۊa _(-' ?.⼵Hç9ވh qu5^!lhg/ V#yS #[{i6D9!c_Zt-`3y, ݜ;ԟ/ң7z&&Ÿ1Ci{gg JOoNH)21$IYI; 31rp%Kq),m7g6-vi*+EwBN6H ;jmLQsto~3Eg}w޷(%/I$D@" hZ$-*\HUR[+E0.f5{sWD(+"B+;Y`C*N0MsuF!i7uhbSJa $GA$}%My'iy^r߲("64{1(ب<J2PJf5=SI)ET&D 煮C ȈPM梪)oDTo`H\e>h =3*1.d^ט\uy\7&".SHm6iӜi[Ldt{Q꟯#w$$ÈV#[r>p st1o+MG$qKFspu|қnܼExEY{'Lf ӧ썿w ܏SnQ͏t3fĚpy>- OQApTxswwa@|2t̓H$D@"`rNĆ DHh%VV?\75"δ9 "Dy.ɑ͍@dyXƪZ'ZM֬wV!A)M!ohuvv$ dʓhR6YY4Fb, Hn!|$M3w v6s%b8Q)t['|C+ΙX@JDy sq"P]H=##QOK'_Q$ }СIb=&e4Hyd d ;g֘r1>K6ܥe&](J޲i3a5~mG_M:;ͤ{W8~SPk^OlS`B]:zHW#_a¬I2n0i y+;rڰi^,ewK*=ac~OU7{Cw>}7wÖaC5"= Q8LD@" HlNХp >Zc=v<9e_"\+}qw4)*Uܔc 0B"4"nA[SX 㚍0Gsvrvv /ظ+h2%@GEaLm&LŦJoD\sDc*˪Dj@=gv2g59C,,\=X(aD=dFeԪ{gia(ٹ Tar!b 7iKmEӉ[wjnv+%X䜿K.0%Y+Eby1?]~WSd-ҖG9ʛg BOQv{&/ WN>%e8++K0oz&ZD?;{ .F"y aa0;1i8 8҄ĞUΙQ+Wߛ `"fž$X充5$ &]eW[d[Dp萬[b^[t^,WD GBR.L=UQ+b/k"_j(QeqI%Uxy5`xew$/&S!/~T{q(HNp+pyk܁V~h4m꣈8~/x찳¡-߇#~>￱vzlڲ<^3gO{w}MssF^BLtgtPy q$!"j@6WMd>?XjM'dmwψV|GhCBԾ* YtKhbPx[>Rd,I2b=dͅ Hzs5q"g5z2gY,ۮKB`Eo}z}n{͛f>ח̮.KGv >>D%820W x /]2#P\Ԗ3hS9w`qҫ;dfUr`eV4TeܢKǑpӜ4 "=Xުم111c _RD@" \p(2WCy%G)sZ2sd(ւ0_¤~y?ڬ\ـ7N>Ł=2mx` RXTT"?SUXjزuN&Ŋz%.Xۚ˟Dw?bz~CS>lL~l19c0FD Ky1QB&J@,a&ODI[=+,UW[vAj)Y1A9v pm@Yܓ)`8_ ypi0z1q܅YhH~2&,) =^@d84m+.ۅvdF'$;~F'|356TrF1_u%}V8~V M|aaxG6_Rrs `Ϡ3=[ק_490H;1'QRI]SȘܸ@ECq2_NUɸD:kFi%Ƞv-x[dq%˥z:}3aeKh""E큠xdajr,\Xvb\nM]N|SQ65wՂm;]%?d|~+ܯl= yHƼ>8sC?x5,珆}eixoj!Q.3y@@h>C,2%?3?A7O';BʽT38aɼx_9Ecm{ByOINIFrJ CǛQX#Bw Xe]~޷+WZ۰Q\DυZQ 7u,F;>M8q%4]%1ȃ⚬EQx֗Yל5ڿ[%F21-.GRV&Eq8~ qg}rc"?D$s2l`GND7SF'?_Qf.si{ߤISAH$D@" *LM5 3'`{fyeB%lp3dD 0_a! ,O,􁝕*[he3< _4_=srs2XHK G@-<#ߏAdHEJqxC~gGij:|ƏŤystݓN~ ďǒId䗈gnx,Gr%ahO`ߡ% (nCQV@ ~(*6~U!:R48rȃYʑD|ƒ|ș3Ҫ=s )u`C<ƿ mOMw5E,:ihkQ^N7MWeNzgܵ eq>4m?'OR{-EfSk9(jA :U'&<_LB{;g%ZZZ_.lxQujm3O;l՟#džs[%^XK$D@" \)khFq}3 i݄&Z7#%t9B?lhi~.hjmG exѬ)~3f7ƗX6< um*nţAҤ@1 BFs"l߱SC ’X²XN=!R_Jf<3g0h^!e_Z!$-LEk JKMkLe$lOsƑ=E4d7/McG?/.w-FTV׉b; =7ze4fFskԊɾ!7сaD*ģ`xoh."^7鋾#GE3Z6olđ 'pdIeUK[ZY «#bVxgc+WA}S+#b8&M?!Q¡:GD.?6#s4ym~I&.^?aaI6O8H,gѕMv0k(I C{{q؆EwSI;ۋ?WT|(ʜԫIP,]H EFFƎ8omY&H$D@"0v/ݿ@kY)#L~)m I|*PꋺcQSL|ѶP1ߵ-Lhj^bVҲ(C7D {8`HAIWŜ ih?U7buR!V)Jutb4DAYJp6 Yb&3g( ?ً Z]TGf &/^"˟Crs PK[NFEn9SYqX4#ޣGè0zB:yNNQ Ut`Wh{Ϙ*HRWE8zIbGyZqR}nkZyxma8΃7/QyN%+?!ph&|̕ `aBR}a$&!S(AI,Ln<$e|`!s7(㝕W1 X9s}&~رupsuŢl-JY5E8LYǿJDENhR97K<dDEe$`χV"HڨwwPdeev󓨡0D ">UxudFGjl#؝䫦b qp[nXhgѨڏi_%ӤC`PoWzg2U?w+povǙ<Э 0jO""[QYDGWǤ тX`rI?Q61'Cp{uCF%kh> 23cIbv{bwըqcW}^Wu<~7<'>KT=XXKq.,H$D@" j,uuڝذ"ե7l8Sݔ!J9H?yQ"Ď$Zi&$6Տ=|B $7RcCȲxyz27L12&/(gɪ&y }USLanN|acēGDyOgW j3+}BF~1߾C?m*yA1^ݴiD0?/x3J|X:S/W\~05Ttb",Ɉ-cx`isiY۫@ٔ rAOɈ4466Tg9@d,SUPu(InA_wlZ:%fyko3ɯ1|Z;$ 5'o;:::j[Zqgaч,'# 2>lԓq/p/<=% n#>Y//O1933L,-p}sB:00~>b0gBՉcZ m{P H$%TFvߺ }' J_e?¿ (ߟv,^Y{]BV%z%b~'t\L|G "< ye|;؈}Piz݁Y3g|$x~0 PVZ.|I;gX\|XHAՑq UY.EьV4۪UxHѕ34~LN-tw0D`p8c_mjBi_{۫9D,*F[bs.q*=DžW;wb(I+Rz,_K.nd&!H$D@" 07 ^ErY Lj+c!{5ֆ,7OIdբ xT>VR,t㓃4<;n^]p!!7ߊ:(yUҺ'MJ j2OWLKXzꮓe$IQmQifr΅|Lט<TiifqIMBIY|%ͫåLhz<6 ]84TMqm,/> 8[? O( |`FZ<L-ˁ[xc2;a̳=0U[_|nnZ|٥dcҪV$xB~<| ǿ<_F|MVGD?̾m⮚{;M}aή /gq$9eUC]vƒe|}U򛡡!(..rSc$Eh.эOe͚59U#H$D@" 0~}blI+e7$Irpd sCc"D{\X2@,0{tבQ/' kG3O१8G3a)))Ĉئl&I(ITU=5#&X2&DFx[)63FbL~L:2a޸*aoLnLvk82=ѭ^{g"gX4Q+KXCܾ}?Cݨ{8`ⶏ`A:L@4/~jHI.yFb2`g`o൱ ;eDZqE^i򷿑Yx /.LWU>{X3"/|&{%RZmPOc]BjޟDLԜze;$EbJObxM]⳥. M*p[G[L&FD8;㢩*;p˯g '9$ZZ/T Y(HN!H$D@" 85gxȍiǩdQk <aݢlxpqqA$Z/>i<޳ K4vLn}TĠ}5Dxp&32?>}v&B?݇u¾,̟GR`^`sl~5upVDMMȾ`CAk2d|2.r'cɃ0ff@<*'ӦbQT\WW\uQprpB88:ɭ֞V=VmF EP\N|u?="͵&ctY4l5rC"Civ\8ڛ5 Te"%;RvD4,oF@ʮH$D@" kf!~o9LFu|z*{2Ԓe _@, Hń7*)9h`CL("b$L!u6_ɀ"SHgWYLx#©UǨ;ϙc0􃐚~ C )9ymWcl3{.)??GL*q!k086`)174jV] k $u gΐ`v%iSv-̴ V8`blaA~xy8낉 U6F.2vC{oF~Sb)I&__Ij'Z=Isyo`0m>7sѕaTE J29i37*r*\r˦"8DUiDnHz@b#C<&jh0z,8W q 7xV֍5?Se}D@" H$!yl>784X c"^㛬ro<GL>UP]9y|#,RWWףrfV@&fED%zǎ@:;`m+Qx\4*8_>qcCFL1leDoylBxؠ\D`!2K ˫^bSz}I㌎Dbt~~?w  RźI{䗪$vDvM9aw<5֟,^G֗H$D@" "Ÿj.*5c ľ//dP<=%tb{F8i)RZKi!lklm'yӚ|8谡AEZwBx2!΃fF ll4][NjRF?I_QGUb:qwK_1–D؄Q/„MP1>~LOf`˶0%.VGAnQ#9?}sՕWHtBU 6Z?W pߐq 5W,o3lÒ'$L|켤Gqq 8@d_n4?kL$̞-=G?kv/( jZK۷VC繦?nDZcpדD@" H$@;q;qWm%c!vjSscp0SH^G$F49XamvG:A}QB:t^+I,_~fZ BKB[<_ miOjr e{;ZHŁ%`ATr' qc|\8uɐ4zÏ?]W/z/W9_nCʻ:)IoA; `_v0M@;׎H6nh䙃+ Vբ^,%5( StZsYUmꛚ{ B W'y<݈Y55ϰk׏B-`j+t<B$þMtm^LL0r4LDM8j'L0eus[#9SgT+.3$0/ΦB .dp26ŠU&H_م ŧG^";oF¦&&N}I74LxxO<& PՈ9Hۗ죹(Ϫ *2Taec+_KTWM[i7̟kĄ|:Nɵ.#L>LL `˾zQ|[X})(F̫ě5"z: <@ŀ踼NCd0! lTϗ*CDj/p9?_$f!13&|VŇ-e]0,$PT``QIfZh@Až|&I8\ǔx8"p  ǿ#b'd =ՒG6H'2OeʬaC,Aflܴ.n9AeXU='fN&!66q11Vk`<4T党,9͖ߺWF =yYO;kqG7ºvP6,/zoW'Ô_%D@" H$=#`gmOG3ܽgWq=(Jڢ`h'gKW2L@c9 C1 JVRVF2_RQs, Odh25䆭O~ĮDZYչ.jL|P{\Y4%JLbN&Eε bޮ~uZ|"^E;\ngprv-R { bK3G/@IDATm8o:2uDY22Yz :w6o+Wɱ*93r `|fVx6}Lct:7W|B*tBD޹tWz7ЈT+*E/ zS!!H??2?gɑ'}ӂ1.!Dt CWVާN2,j2~iA(6s#¤u+'_2&憉2ud^%P?$4${:8hQLFӤ^ۅe֔n cV.s9¯\̠4f5sf㣢puPۛbkSC~A'BYY-u Dه顓k7#)>J$D@"`@ v4xg,X  ٔQF2W}-pL0f)&5#=eE3ƸtIN8KO"-5k됊PFC;.9vYm3I J\.&,R~Z*MŒZ9Ң!j\"ӄJEf py~~!f5Nӧ' 49n2nM gX_#|>P4MuB;}W_EjYD_Y;~@d8ғ=" e7|v:}j6Eg#&Ƞי)ʯdz)DЎlƯ01dHB3r6Jȇ#O%Wu$ue,Dt%e? {X~D+y/"<\=>JWVg'}5^(DZfe6edkH "3&O %- d>br.:Dαj;pzrΑZ%2J+n[Kќ+"93NHq05LvrE)l\Jc=&@CH I'OH$D@"F`Sr.lv\;>4&!.t(|:I*΃++i^4ǝd6]5i%M ml2S d9\)mOfRiVzMuЀ1-q4j<.K4\*. ',ե%f+MT ;; 7zY 5e zF~i%~s5ilk'Gͩ$?g\W|fC:i:IFcnKc>4eD@" Hye(ol@O|}%qlBv49f/j܊> C$ue<=o}}7qe eL G"=e M4hÂ憃`w  in]V7EiP#MDٷ'$$1kQT\,=<<+g|Ha6ZMQFw`9}czHF 4Xo>ߒ aC @|=.1"%)1V3x1Ȭ嬺{EJcn&ߏOQ+za7^ā(;(c6;37C]H¤brUy Q_+ለY**":|")?S&@NR@vhL rt?,dJV}fwp!';2] ~ '|&3*&$Bp=ax^ Xv'Lr.sE-(M'I Y4W ,vaAtkFiS#~4g-ܼqcCˌ7އ#kT~b2J <=0g}hqhJchpHcР K$D@"`&~,% HħEt 3ݓjpڝȩn@3s!_dp??D 7 U$aI+Xb<Ѓx+FI{qv:t@w?G'BI:x"=/4GX>_`N ;TJcבH$D`,w@g5aɺ]8VT OG;|y O^wp;.7O働c׍]$`]Di%[Q{~@2'cKoHN4)*W'!й1s"?˴' F8<3S8C3U8cESFr&L.GO,»E#{hƼ>Za"7$_~כ̲NmZ& k7hSUNB>`K3Mu 89j@"|> [ wv}fU!x>5Lj0$䪆,|>ao4RXǛgN4HO) /{STm֑|T͏]7]utLf5_:pkvtpuݳcY &YPBEbf7|(s𑣂 Eɱ/|w=GxV]X5M9%C}-"NVz~B$o͛K>{Pa+ǰAo K48V$D@" 0_2˝3{z-ZO.Px{'kCDԳӍ]O95`_^+P,h#-Ãl^^UUwweLJ&C+GRRϒORS!JBBDt=)ȓp2g;k*U2>i|9+t _?n[itz$ɝw֢(ۂ|_<8(Qpk@ksxar1ZH `?q0P":\}\7ov(My;?t̀8ř`/aB L0tp6oFqv^%,{gNx|5"r`XT,Ƴt<䪊K(kǂsLSerGp\xUӜ>&چz$H4lۅg̦ aag+ IiH !v8M뵋v# /V! ݎ Eyw Dd؇뻝W$gEK{{t"{9>?xP+vf͜9g ChS "x7)iH(G$e}mSDr}G:c*TT9UR pݑm%1``gK$D@"0r7ׂcV^;}dC3%ɔԊYmaC31:.قhAb>Lu^ݟ?9#.hx5s*@ņl`pNMD>1WO$"(Te|aI3Ǡx#o{ RƆ \UĦlO" δcǏ J16m "hhʹጏ7"}FnOrT7_+L'GuR@: 8~B4ѬW<=Ny$fniBƾl"ɪcDr[Y["(.aӃ8vvfuܙv85FԔH5,OJpn~~۷<Я4ސ}ki9Pd\Ӡt{˂3*l5~͉m8`8kӜꊉ'`7ܒ#XM;QNOs\)2/%eaؐm`} *| JXф/ʎ rt6OsZ": :8Kgz4\4b'蘑;PqBl4Ht": T꓋Ep"ܮ Pp f|n#yyzqȵW W%/w4 Izh1%1D@" H$Et3 J]dZRr QC?3)q[;A@vg{"Opaf,q"ŚfMcTB3c4kJ'وkgAbaD>ԙ*)sIfʢ`r}Ң>oglOڊHN t6Kz]Z# s=‘^#a򍷙m:_[4 9z0=$6lߢ AkvѺ^_l5)Sy NxO6;IcEoh=JHg._ 3> ӕæ[Ӏ+K:{Fs44#d12!7$ErXZA2Uc߄7iaIߕ\fOiA ]$EwyUݎSOI<xnǘ(x}f`˳Hƍ#YANLNYڎfۇ +W[u )N.rP|:,!urڒn\`)'vq`D,LB(mn(LNI:%u׹n6c/nvאsbUx CW ^?`ɄY0݈tU;[ 6tm`*caK p?!x^-͋1wFIQ=Hҍka gim G5%D@" HF%dȜ/&9 *ors<#27Q^]1qfsik&LZAk+fc\GUgs58Fu-@ NW‹ҹAZ366VPm&EDc^XQ]gG:ܖӛD%v=CYp"3;z$͸s=ӾszmZgEϣ~5u0FNd^, s&qv2W?'CҺbu:aw|sC}eD?8ҟSG94<ΛĢ-}e02?Y}Յ.?:گkGkDe\Q)N !NЏs8s~Suk j){}R,{K2)8BHU66PaJ*v/ A~7äG=^s| Dn)~|b1%4^ ƒg|94q)0=)oeF?]VAM#H$P"iyH!B";Hfkϔ&mL$cl׮8irúMUUDJy-\ 1tƙD %1.%gcDhΣ<1S۶&{qT QǘАDhL9gRcoe\&$)h=HT1D@"`h&UA/ 髻H2L|[ ;f[Iα7}Gh>ƏgҮU Gqr$C]^c:F|aI&F[tm,N'& "$+;[ǫGɓİa#>߸ 7/n>;|sl:6;P^:KD&kCp  Ύ'oT͊v}LZ&}=7E Ν;c...^5X/nAVH$D`!PU ŋ9x];8#I @ӄ;ah{bf\.Et.qC1ӽ~\~7…?y>.kx2Bj' l4QN8K3Q8[BLAHH% 0Y"'M3,0}BiDZd^#L#H=ݲAmh$mjՌZvha%:w&ιX6dH$yޖ"#[P 7FaR1e #4&/v8;"bvJjZ0#0%N=RMyuu5SR'PQY#1`@Ǹ;`*KLƙ]?fsHb_D_d4ab~( ~\LocҒ0Kw̟?}뭷 k<0@O/H$y#A2UIYȠ*2?'H1]mYPto{}LliFne&ڃ(OcbԐ3ڽÂ8H D@" ~I_/D/H}Έ~kн N 29҈;Uz!n `eߧ+6Iqe&;̚L3t2mz/m?N͹j?՝Hn;c1Kf:iJo566=qx]NZAp 0ރ?򷏾gqXv]Ǥ%aGE!Ic&kJ$D@"`64tFpa8|=D !W)2{2=JjQZU2d/ Lz4#GT!-2,I0ˁ4|t:D~`:cFo;!Z8 k~o$DLZlgWELQB] ߍ1:Mu{۹vUUё{u<`"9q!?kYns#GG>eh@Sƾs#i(\+z6E!#{^S&s=(kA'aE 4$FR#!dwSvVAa~K(6$1D@" R8)5\p$e S+ -} n;mŴYJ5SebڛxgHb .J\ѧ|dD@"`b` +H_pU7=C-p`ߡ6W߼{[K 888 ԪX/"7BTrUDt?ctj];S#23]ђsSz;-dޞz6M1`_v8J~<ų2.B̛\q>b V MF"9H*4f̚Y3gSs7>v5!IS8ڐ({v$D@"0J`OR6o$_pv q"6+Uhޘ;7fy]t-G.|62H8^{F&=xۊ)θ4C,~GyD@" 0Rqv'b ߷\Cum_vx0ؚ=Q喦=, -ߨIsPp (J.Ae *#68B6=.!o(D6ԷFWSd~ITTT@;mF m HTΔmjF<麂'vr$ *zܮsX0QނE8&t׎'3˫#|kǑD糭⏿=~IF&qt5"I^$ێ'Ob8z8dQ"z|oooxTه?jw"=hHc%1 %D@" 9%YP$H%);U]_VV집bɪ Qj2W~5 pwww.D@1gzP0\۝]e\DZ`G^vW"CD䜺fRhbӺ])Hힿu'RWCc40}B[{!ce3匘"a oN@+}qqM?A:3"hʘ BBIѕ=dR__k}睫C^maD+rl&6p-(32읜`CR4N`ls_6|>>PUY۶8IhHc%1 %D@" -‹C8[&Ύ$U*11vQ]^ Nj*hn[ 0t!dxtÂ8HUn]fPT3/$(1RDN%p!Pk>A(h G^w'./2Wi| {5lhPeM3( Φm^: Al+2-8ڠ K[[عa+2.uSo†ܒpձSסm]H^lңq:S?,9Eq:-#00 ga-AAٶ[I$փYIB`xm`$az:&I^^Y" H$Z²nRU:YA$c9ͶYןkòwip'q p?p}%C^]]1δtI,l^YMX8kt9POl: D@" 0G3 N4]p д%y7͸1~i`EMl '”w4cϡKɂLi}(TCP%{ɉw+ʚPL:dOXQ&5[wǙ,Z;(w xՐ$VRR9yu21 -mBuu5 V;ؠ&yFe~FE[D̝3%:t{NKsi_}¨,I 9˻H$D@J˘͑Vݵk`t02$( VMLr52:/{yA PP"d9,ޟO?- _ޤD@" 07+ptI| ` KRGP>*rEg;7m]G݊y`zA0(deK;1Qaе䅭:I Ψ rBɢTraM O't$E+Sm³|R^9g#&z$ѡ=k7H@ Zkn;+^@ :ޛmɽ-N8ْ&Nv$N6eSvSmqzCEt$? 0H 03y.w9ADE钳lZ?`?O$@$#$%qx ΋Pz 1T 3T|O%VM4zbld^CWi`1g -jB{VNCF&a6 AFr3d. \3a|\2Q^&3uEދ\?jl_C>=mE219FIHHJ !"\7z[^i%GBd(9Cox#0F2Y"g_=k1"GuC|;Y0TUܒx^Kw (qCXX>_E35p03%zmv%sP<5O0xv$! UM8wj$bx* Kua6wPק.9qM=$@$@$pea0c;W_H`t \dRV/{SxjZÒMA@i/]U5p YEZv\+'-adddj(>.vkyBGaoF>?wm:4=f񑺸عsV*hTVE$@$`>sZZG[;/v,AbnLV, Wgik&gG{;5cʓ|_YҞc(.AQy5%A99#Z *&l,pqr0󔀏|f;>Q_ mO Dmk#`#[xk FZ, w$}OCI`x"#{bPB(sqA]ˑzk"kRܠ= 744صnu5gZd327y$@$`ࡒ޳@So:ixH;C<,1)OUon5D8TRE5k!( s]kqy2'<%bpx m31?g{lZ^D? c`qH` 47+ٚgG{][;-|UIΊF$0}s7ٝQAX&%_"lKKR48}2n8Zx' .ux (8_%!ۀ3E t `V&vue*,eiCN ~MNqڶjQA}s]3&$pWbJ~;^:7*{}[W&EEtZ $*5X*n#F$@BE~;mڵllm5J:bG΁᫮1%;)S=Qf  ^]=xh>L?.jI~M2}εUkUxWq{,V1V @w?ȑz.*pqDp #E{2?)$@A@58NN&;XraOm'  嵍x} )JL,$l\c%0ߗ?_}^~㣣FBD("CεP J&]`ֆπ5GoCօfl|CsV-%" q~y~)Y DfeRٌ#=nK)H# E@*9> oJ{R $&ZnJ'rIݴ*I*#;A$@$`iTBcyga \V5_^J*ib,PFL Wڽ;Q0b/4y6o,B#]_>`˳Ż6`"GVgI|sEDoBDcHF7> "*l =CԌ]z-խ{X֬W/]D +- vI6Vꎝӄc}9v%֥9 e垓ru`!B/h X!Ξ^|\GU ŎUؽ.Zytշ ޞ ۡxɞ|/oJNGi xI[i* )H@IDATD3$?..h w"0zL A3IJF\RBGep$Q\AK`U\ļϖaytEwE?>6HH hI?vؒ]&dQ96m"Dz9]ntMbJ& me̞.s%E04WKHM{I$S 5nE8Uߎ~z"lyG/&"9JE1VNJoRId^): C$#O)eM<^w&Kbx/V: 0o* ;=yu$@$@$0k$ƛNa|t\ܵeŠH-Bs;qIi-6>!{`B<7z:{f-k5F/!u[==ƆQI{/Adl(%|c4^:qOFE,r_. =wF`Qo%tEg{^)%u8 M.2̘!y]wA,~P^*|1Ց5fj^=$vH X>:"\Ќ`nGOѱsJo*sHHN-ۇ3ߘEZKagkkJY" &2ۋܺVxH^=$0><^XDƣaAe'9@-ΈjvuDf%O׆df፡Nۡ#^ .vA*{h1F$xW^#ƬG fܧ-4vZl., TLg@X+Y[Œm;{A~#EQ"6DSQ_j)' w`c{yb{3g&t*z(7aW|tLsڭS2^;7$|9]*ՕP=aw*KHH`^puvxXU\KHHLD`3 52"f+_7& +2˵f1$@$vGn-/Ñlxο?) *]vrK rF ?&@-S'VG@-Sgw7P W %J0fOñ&+xWc31AH0^Dc*dS7]CĢNVI ]L%+\A"zz]QKWO*JF<cݲF`4*ȽJ\Q0f)f.yUQq$%åPᬔb"v$! rj{ N ij<<z89'5܅o3=6 ({$ C[gvY audx?Z7HH|3;׏r\xֵ/1܄&`8Zߖ.v慠?n8@?Ƶi tu)k̞d2 jm ZbA-/2> z%JęO:gXZ4aK:i<\ %4W\ _ģuNpoD{ xQ(qKDVBzf"6,P'ͨ|0ZgN7)D7Qe8FՄq("$)&bTD͸mW, !ˣuL=eRg3$  Y PT^e =tƒq4lH$#fiH`p?/ܹN͉bY|ͮw 2JPˆ'd}L^) (eQy;&3~w@-S1!^<8?VY3IpX%\ᢼ]Z""c-$dYUƽZ>+37Ux)+we"x; p)J\$  æ^U7e]"HeEH7u^ 6dZq ᫂bHAWyNMF3x +7СDd)0wc1*8-n.NnUT@_6-l* ʚ{/ӋPօ Yf,vG`[NWG`5N*> $_պ==P(FxxmW_(,~P0[IWޚZ8kw \3{rͽ2 4Ǖ< 3 xI)ƀ̦S8Oؔ '+3m$@]q_ڏ7*MuK+ $WHs#Az3{{{ *-šAluTLz#o:A1H3I6z$@$@C`[ZN-CU}B|gbBOd1$@$@I`Hf;wgZ넚ՠ7U®aH,%8>j?}؆(ٟkQX0B@d5= 6 X"gZa60p)?mɫTNַcOѿRK~DA޳kx9#ޖƟ$@$@"ix[Joag ^|t"G aUܦ5OyrXק"ܚ xأ7"ܿ+M-q*$` EL&o Y%~ MWe|7Rt_9xīAoW$4BWH~حQ=v 8!IH`E(]ܼ%Ġ.NjU kF D$@$0c*5YR Ұ!9.N3V7 & &wrg?KwmčGKpW }yz\{|t5yUūc۹ffGu}'"Ol7+oOG L& s"P&zIٻi Kc  POKf&rΕZ,!.D$@A^\y~zJ|1-z6g$`sOg&38ݻy}gWj~ȌGm3|ి$@G`d,GNғp/͹DO$@$@WK@yr||"qUQ1wNĮˡ<ZiwK?aɍ]Ś팞^t6u,mڵռ`=6QD+Żeih  0Oݰ'Q^ۈ&!J7C5Üz@ÜB$@$`*Gۇ3T{2-`pHH` Zc-z=,(zXSbIHH@ѫUoDFQbQaIoHH`x$u)\qkGRT{6C`HH hyR ˆ1>,A $;߁e"O՞?S?hHOIHLD`87?{J/`!D@h$@$`nUaN}Bg1\xJeQObNu} S \ocSו+HHLJ@ ߱28y{/ȤDa=f*$ q xh6C{WVnmi r݌?V@$`Vأ7`"H~$@$@%Ek1\-y:tԪ^8 c:$vÑi*s3\-}~5 5᱄u HH`WoBDo6L=C*IHOY]RIҵlqcuRNpI$@@>r=n}q?T4`x|ql g$]  C5m8&ʳC[.) WtcJahpN8Wvvʛa:[k#ʹz 3^|'c[ӁgI$@$`@@+Ԏ,Fe}JOfh +&E9l bF>L?:r[lIV 2!ĐIH`2W*\OmkqoBd8 FGH)%pqdOVߛ!BDCI~z>̈a_L6<4.yFrL H" pA$@& ?>:6XCƜ4f   ;$&{*V.*׭NěxHH`\=OO"v\o  ,M-8r2_AGCx[;]"rM8xR(lFݏM& U-h_je$<XďA%B \Pܻsh!?֎.mxhpmP0' :x dِFdB?ܾy%6$ގ!1! Sܸ Ѿڇx|Oj:zVH !AdsQ]5Uw xN 7|7pn'!ᏒϮ?[xzc%R|W%gHHH !2jћ;~ʇ {hF\ E$@#N?F'-MRnܥ}abwIH` |eM |["Tw;6ٞg$@$0.N!j;#DHApB ū['V/GSA :߈(/WIH`8#SI`dB@ow/iDV-W f( zUJih 8H-qi}*HH`v <`^Xmo߿~F$@$`YvBuޅ/[5"iw<-JAVh|PM+! i$@$@'`,2yU"z'5 %P܆wEs22;@rܵvC mKcs{qk6,qFf  &PQ7rq|u޷]|Szu\m8o׿!|]>#?nYv9Kȃ$@$0O szzz-iÜ9= HE;%'/,z"b#qJZxMQ{$@$`p]Q$z[7xlv)i}-&_X4  #ڃ<ԟkmuKۢ`7VQ/IWz@u )k!?TI+F® e .SOkxy?IsE <"ӇO6j=wrǎUؽ6 vH,"wgN,hGFMh[;QГHfEZ(9v^WepY 72Woݽiw$?wd5ETJg$58ڭ%?Wa޻eM# Z=# 2fue_lLx8Y~)C $@$`G:-O^DDQbHH`v t6u!8j6$<ձ=v( -7H~jBZf  _mkN8% e TFdUj٩9*dLL%Gib# lyH̑iWwk!#g" IÒ""Ց3K140U䁕w-G- &XUٶj;%mfxH` ݃CxI~wbf!싺IBsOcf>,H@^I%J+хjDC(٪Ztth:aKjnXc  P=qm V!Yo梽N@b\acgX?K38 ;a$A `Z{TWY;ڈ"x<%(l\ъ:E33cO4ϟ UPNj5G%|?VݵmJxHHr DPOWTui9Q݈gJpr.[N$`.db-WG2\Q}BTܖwsiUQ? -ՖUxH1!*N9POx\]JQr~mhnש>swP9,H@BD(ݹg*.A/CX .VHX%9eVvHHӵ-(k 6?UfvO <1[{[]yuD WZ.t9-"z<]Pkqǵ$py}C~!^֊WT :7aj&:aބсg;F8K8šA@Q.U1s2VS  s" 믞C}sۘu024ǜ uPI[uqq^/gez19wLJYHf@,T]aat=4zO i4 uduITt❲FBm,]};*k4v귥tFMnpU5faM  s&ڎW?IגJ(+=zlZ1g{,%Q:RdX8IȫdFdQуb%~L~>(jC2^#Ee"b(1Nnߛf+Ž=Fх< mo2걡VjVD u#pߩk)z8♯@ <7ÙqHDN9eHN1*뚌^;?: Ql"M)tBOC%1vwkǠP4  KAf~aEO\ߜ(Þ H{3n6$@絤EbW)& $zuXB }zCP?ϮЖ =pPi$` zqMnGP"hKVO8/* tqb0!bd";onb̈́~~ҍ8 MIBMO1ʘ$KDoN <6|a;E+{ 4`V&vT5YM)ؐ !t   9#6?SKre"xR\ øH sVVL$@+[DBh ld&u-WGp;~n; QZs#G,ȮD#xCd6m9V^e}yo1 tĕOVCI{Fo*Z,vola]BCN-o z*ƽvB#B|y' UhBWȇክ"y:Y5vHHr BcZAQІOrC )غDr{Ȗ X!}]Qr u^>"t DxH LaSZj ]]]хKéDWw(PѫyjuxkBW?~9Q^Xmh*džʣAڈ}7NC$0Jo!n X>>]E582ytU1ad,gYdIH`P3m1x&ݗFlPS;Ss\=S= Ӧˍgdbz["ׄcCţ:<=I}U0y KxrVyFYugO "lv),6(A-mDi oxh?R"<5:2{T3WgcCݓrZLvj)>7 /<{\S$@A_٨u LJ@y*WkEHP*6Z`d@бVBXy1(n !.ͫ?ƫ|AoǗWH|y%5ɨy-)y޳p)&h:1%xAt@=\m$%1ࡼ i3K@ 6v IEϺIH@6bfiI6a]R4 g1~x8.ړ%[kUlN)Ka7I̍}'jƩWqh8{VK-UI! ̻F5S"bffjbB51sq5S$@$`JCCH?'y: sXl(OZ08ϱ),  E@ bckο' OV7a_@"?!3qTD4'G4p,S>m=6WWQr G&y-W`- \19?Aws~bl X'%x &,o})zIpM$@VH`hxE' K#q>lml)BG4V/ Q/!\ sS u&/[jX PǞ_S24u{d14GWukllm+F& Qm$@$@$0e^S5! mh܌S퉰=$@I@.+*ք9gީC< BWME&  K"hJX:?ybZmc],Kl+ k°7G W5<4-$@$@$'6{J/_>.X&"G&r, ]}zy |&0 _+Oh} +"j|)-nN?BvH`*j[p0Oi`l_ 9z$@$@$@󋀽$DVH\_(iR~[y~Dxsu~}*[C*x٩J-T#}ɡIX|f;$@$@$@B[B!~~JY3>Dc$|լ4f+1ÀY< hi¾|-|Ue%#*: _8o WI ZR-HWfQG{[bgC̒የ/i UT5o/q00`/,Y)AGpB;\M   "ӏ_72[7Q!)6amO!yDCH/8Ւo+ģhN1kv(puӱ 1a@ų $|]5\ y0Og3U V5+n < JLBJyva`pHk4cyt8P;$@$@$@&'ݼom,ci*^Oǟ2_i1UG X QSP: ͕-OTxqK a#ah$@$@$@IMB%?cKDlX`6q(z(#JxF WsE,-6RWa(<$  ?|F[{|-<۔GRzgM /6+]ݨȮFYf}]cڨBRh9B6c qHH̔@zU KFzxtE?IpM$`"Bqu8Sq/폸a]%|U,ڶfȆ$@$@$@#*|v\5xt-[pG\BSUK99*ދCyp?—^c(qHH̛Ι*9*$|U3'-I cEcRD斁2_Rams.bU"VO/@ UqP"1/[;-FHB7>c    p?:gśO2˻ pI7(zLd#$@&")Vס@<8T*w)Aȑ, k&YT;_Ov \pwďS"Sf>Yֆx:]{\u(cϯN|*hŘs;yU]\%xF|3%ܫbɪţ8z5@IDAT^M$@$@FlS0/ę> ilM17FkPϦESdY$0  leQ 8V^@[g*nh! .w`ےS* }"nx)Ã2BD)Ag&T]!I b. xHHA[{>[ݬ]n?:^ˍ#Zӆ Iu(>xnl#؃cP W&E(k0,rw7KH;W4&7E#e$`.QZ]RIKj5nΒt<4I    1l$a5&fr4]]r-ǻgFQv_YR/ӎ&~UBfѮ0*ZPh(l+apX5Ȝe$ +-="3h۔{=v^R ʬ̀@$qC%W˙ EKG\J: &4& 2xQx qJsq…1(eZFCOb캣ugt͕-ڶ:nTN%\.C@?|Cv2(rC_y+HHHnH -}ZW;qct0Ԥ13\Y* 90U*xم L6*/GܒxOsM$@$@$@$0\e hRD=A j6\օ0/7Un*xKu[Cm =mY._(Z|D 󁓻˵}%pCX 3&!$@@iPT(H*JkY'VRpEjm&l&@/3}̞gsn}&wf^s}&dr<V/'e` =^$|ei=/YgLUow߈(EK \6,kxYddI|JJ.ɗ{|9)2tt:mi_i΋ѡa`@ç:qk%Hdmիdi^pd3v=f!0q޾>9t+Se?-iJO,KE<}@$;ղQ'k~CzrR.%ṄOT,ubXyp3o#s@@2zH9r]{MaWށ]A9*`=G >rTo^]UZ*7  (P~b|5aGtQNKt.u* +OMvwL~먛^T(w[V.ru/qJ6 q@@As].a6ϚRITxzl"Hwʎer[׍y浍͚q_lsZo.a@iŦ ϤwWo xG\EErM^"#8+@@1w%kN7_,q.þTˆ q80Ǜw^F[ZtjͭqdjE4# \@[@o>24O/*{TqFj=%4o^ӧaX+K\p#_EXV AU  =^'o/(!n|hmՆWJ4R-ϛG,uy] Zjamhn->)1A֭(X e$Ng@@"QjfY%~FͭbbL@ݑVпJu|4rzh8$,{^N5K~cq^*Vɦ KeAy8 $(ӿ_@@hj-O\.05!_]n  @tX33{@ĭ(k߱[-#4h@ƛ;4"'Dа׿kh|_cIkCiPv<[y{;,ז4# @ tqܱ"7^D2vy*8שiOlK4˙Ɩvz܂̐t)ϑl],1t|៺F+?o@ZU zh&@`0$j.x.Ă@VњuzWl6^FJ6uӁ+]cb,?lk  )M o7/?(Ȓ}jRIMrݱ|w?JNYp \6y˶c D)r dX@#73ݽ@@sF h4h@6l׶2yi.;#N1'ՈKD9f&J^a՗\'m^1붇r~D}rEWs[wɟ]"j,IQ^# a#pC>+]|5{#:x5ߕqVhhP@#^aW9,3ÂaYWoٛ5:'  0-==GޟR*-u5c#oagehp6\%flx==z{%ͼw53f$+J^=xHKB|e!@@Eޔ'TKq9>"ٸ(\NFӈZm >RfƙMhi_/figOk@c"Ʒ  +p%ӓ, pX#(S'O%.+-W,pN_=$?}T@M͓?||hM&~e@@ $Vݾ+j抅(_:%2^/~hm|Ra0bG`raǎ W:럡p%|ۤUjﱆ}-+1럑gh? }mY4 @@.THnrZ%k7F*AZ*-m,Ufu7)ɒTI ݱM/vwLA7J_vq$P*  xN›C~6쎴D#w9z]֯Zn9^$Rij,Cӹl׬o  SD66mtWo[7PW.K8 d4J` pvC.15QJ*YU͗xzsMZ;;W;O?--IAZr8.  Ы[>Ff'ذܮe^l7{׃H=FR uְkZهte|gͩ! DWb\rU4BV{sJwb$jKMFX \2T_zl N Me}Ƚ/'W^+o6im=65Źt\  !@/FTjo0;]Z꣗.qq~IMwU5bw60qsB7?A~@@@/`ZδHñF_Γk\VuVЛۇJ&i`3SCB>r7y]K_hQ7]P]W1#Ds_+?`-a㢢W!++d˾#/S:=5"l+u#9]@@YMrVpo*C坲0:Z;]G\\\ދ%g^_X/6c^#ڄv寬MJ_ݡS^;d@kO6`ǓKO_ a|[W6kɅA?cWʛ1o" ČHMíyG+FIiI2\/|p%t+߸Q>Y?cBG9$pK2勛/筫7Xkv=?>b Z}2@,'K/q_lO>O]R.)ed>[}8;@@Fo5jCR{.ixM&F& ]0#0a[qIBƔ2]v5-}<_<2@Z߿W>W_*h"kS:B@i |jK;_LJ2R:Vz@@^[+ |YqHc>3l>H.wۤ,{9!3G6k&{Hȣ-GOifX`$'W!gg \@.w_9( Y +]ff 3.~K"  0SAP%$HIEeK$>1~G&wS0B` 3w].pZkG\-S>T>1* w> ث)ybOt27,,{7^$Ѿ-@c?  @L h*aCuRs^Zj[l$I7W#0cÚid$J^=F3?l e% 5~0V@Yx ھÕ~wkuf8 [E@;R28*Ce2]e2%a#`q7~QtƏwWK_YU:3q" %У=J>m߻_}I<7#.s8Q@@hԦuÚWjqxVl^F .)ɕo\/WQ^m%v|JK_-Ik@Ǝnyp~yCrÝ҂4 #,p8M!z@@H8Z\tʁˊk\k8ʯX,@4 .CekذEK G,C55&tql@ g^=p!_+kz>&^6}3@@`UMmձ_dpXں{..q~@k%Qzu|bZzL +;E@<|wĦkF zhPi_yRPذ@GNdkxNmv:}2C>>\Rgt9> a/:STpJZߠMs'@#9W DenX ƹNްfW~p妺U VϓoRNc"TX@d Xԇ筗ZGa5?쳻䣗.x Y# b>͂7*]Ƥ}}Y4W` =p^  NJUTsNz\dX9*[dc;e󤵮U~{IҰ)op(Ͻ(hnG 3|>=~<}V״ c ".s hײUa8v|ߩ ]G!@q/UOv>[O P,a_:hFμl`#8+V)`oh[ք'oVT2C>n|xm$P*6Jj@ 6NW~4w8,ߝ?z="q  @4 Xƙu< -QeeN=Tʮ{@k 6{6۬G8K/woj+ |?K>rSwϢ?2 +FM|好S@` Y|k y툳 "LG0N@^9ذ9+4ЈVV*(SҴax+]f0a *mZ#X_}iitW7iO^Y!;N6ȓZFUS-[{t; .`z ҋ{cutwi]vܼp1zÛ  uA 88;,zt--tŒ?# MHNLNC gV6pVkw_*#9Qں|>W7M I0GG>f7~땃rŝbNJ|e:disNLZǤ 3/ptG}kse5KdnE-طܭ3or.415X!ۤHNC l\T$6YW{8Ng;oP@;e>yN @U\|C8~[4e˧Z)zZ;TzLE  0uϯMcayZF p4T㎔aA>z8[6 paE/O9z@|BNI3=.LO#Lv\ܯ20;xMМ|:g)  0eoX0\cl|gPI t㻃38f"g? TrSd64EE9Ү76oM ̖\[-~yזȧ7w-/&;qgJLIs@.@UC xطWO0ƓMZj༣ٗ5_p/*B#P,[Hߺ[ޮ^=rl-R"rz"yb s@ ;OjcNxM츔}9 )';C@`zlO@jKa a),ϗ⥅xBɝ-9tʖTA`4-F'ٸ81ls f&h\'[&1 4jGB8ձ4/S3RcuWɚ޸bܪAw.'I @(ԃZzPn>/3UZ_!~g k=bs !_ґ3kWj?`5ܴ?%I3?BCt@u])V&-5Ahk= (H?HaY @ i׸ZK\ycǾ3-)b:& s@PTkk'X:>"yE%~`f*@#Bo ]+cR󸛎v"(aW&R{A3<7`[RIH+=IVimǛTwhr)P;oa/q̢ }Н!s\9>Y:9GKTYƛg\0+do_CQHR2 7W,_ezXcqN椻++4Zzܰ ?(  ~^CJZٸa|ͥ_DŽ%0zD@V`"A{]n,P&/Ӡǃ7=JZ%&']O!7@/rx4h0FڤL,hbavT*F3#Z(wA(AV̈HCJcFnAG6ٸOyXO\R.mZ3O6r @;XY6?Z]u\R9ļA@`&zձ39F r =? p;ۿdD XhM-̰ eX^ ,WV2Xy+_pbi H`ֈ{ͳ,_Zvx/[Ă ^ֈ(_}&88܆ޚLͦY?SjB8̎ Y*'\t+_5Ayײ͘ Q'fm v*qܰPѾq9+@c\"6@@`@,9_kl߃u 2D%MEHch5[-"rӱ̖ƓM{l{W,ZhoOM*aK\X=@oz @Ӓu"!y3F Xo/G~r[X7#Fqz AX|HٰK3Ftu fXo"ֿ$-'U v<~"VJ@{$' ;X+,ύIp0d׌h?{N~(F T6/ !l+@ :{wo|Pv&k٪/]t9+a%@#n' .PL\U[IFAz~ĞG|B`lV+=F,IJ/DM'GJh mɐA -{Â8!We@e)W咖k"h۶7j3yD.s@e-R AP=^#%p5&Ϋӝ܂4 #,:a 1VYY)+>u]'_e≕>o̙3<:!L ?N AO3 i}=}|AZ] 1zDk,W.˲C22]eŏ7ǎN2pe XCc @&'0²2) @_"v9.ե7'"UUUqFYf+9O|Bپ}̝;w{?,k׮|B۳ ) l}Q%we3/[ W,reg9<ZEzs4j|.,kK35}ҏ_LJKy+]k6^eo @j vR5oErEĚ 0-GO˃˯r_0 ڔ3ڜ|㢢m@`=&uwKgg VO J9ƮW^@ӌSgRڜ/X.ksCP~~>,/cx2++KnV-_l@`V  GիǤ;\,Q~ʝO#(_祉MV܊b,k`?)!Z*OKg5ʀ&Nѯ:Y 1å# pQQtߦ5H8"P5SݙW5^?*[j ++[~|G&_|WO\\3R"9Xqs^{4'1x7oַ%O<|3>+@fNUxKrz_X^Oʤp< &"l۫-MH᭯}k+!)AR$"c@fL`"i _ ,2@fp   xl px]A lt=+^?"-]=n]EA[W^X,˃@$ XG15)g  I^so[#;Nֻ}@5 + Uܷm{ kKrm﷽!IZ6t䟺jнp zǐ밠t Ac;S[[붰CGff[US7}^#L] Xޭw8  $`%@\PuDk{}=@M,%ZL-3@XU6joO6C -7G[Sݭ? 0=ƹna[z뺻ې  tuicR}9&ғc%]qw  U U  2@Aɲ>,aY @M]mgv>Nn*+>yX%ҳa @c"200 s7^" 0!qx DŽX@w@lzeOmy*9}٥5 5 d=$fA[39 ǖgt:-i>F6"퓴OMZ 7wEhψ9$@cYypL#@i3 ;?\) D>mf9]&W,p+B plod%';Γ%:͕F66ٰf Oܗ 9~ z׻O]v6 GwTkjEkڥ#Wv/b[U"QL   @$ yJ9J$n$@ 4iVƯ\qT35mi3rNְz'd)nnZ&1-4&ik=ڻC|<`_^+:3x]2IϹu}z]T ζ!43p3dhNi]n74i}5$Ufd7G溱es[Y"˯Y"W:  @ L$0[,?ɖ d9,YeϳU֓zsXY6$g }c;ַ/|o~S>}Z~_q@^xᅠ=qFIIIch8}%ZЇy1OWz4롣Szae0X6=-n^6-[f.ܰw2,a:lXIiIg3)֝o&&5&&:,08t_Auq 2eHdR3,C#١_F\kv^nCZ0kb<_73V @@ L5˓Ya?x+_cDثo =ǚ9<# 􋐃276irB*O9-/-Ƽ O1739nLpcH侶ǃ7=2G'%rAV.cB3"zmY V>ɂ ]lpl; Z5B}tjV.4RYP]p) uWh@IDATSu9I58a(H6o>*gz Fa`/Ys*YzUiNH r]3`h6 p@@"S`ȏv1WN+'.Zk s"[E+A`ò9*Yu"IeȾzB!@##&o_z}{@ܯ -`:5kYy_FncAs`큧M϶s+@G~exZk^Q=8rTo3 0K~9, h@0;9ޡetҩrX|ďʆ(-ce TxY@{8k:+'a x6?!g7Nh?R3(,X˞hRdL@@ B(Y7ϒk?l{Cިm3'uno :v~l` dEA\T,4La VL rXrt-Q6-UeAVjJG$gx?^O;l6ҶNm )|*:Z/ڶlGWESk̼T #DŽk׋;ߓb9ZOh[#- +Kܑv:@@@) :ӨYN tB6=dSzX=_B^:^tT$YAHyn[$O2,&'`~y8J/ֶwwM6u}9l~II+c߀@ -B̙ڕ𰀁 *Xo4ql6_Smm$`Xޮ> bXvF(FaMM;_IL DVɲ*kXcr9Ut3{@?g   @WkesSnޡS<HmX`Ħ Xd!eE4PRE ti絴SN꟡RqU Ų; LP1jCuV:_{w$w^̉#JUX 佶yňY'ˬ^5ƶP֛zU:T[?ނ2')wD@@hb2,zppan6fC7-dC\ff$^ݢʲ)sTP-^G>鳚qesX9㍜$Wvnsy갠! y<:ax1L )3la1=5k/?-`Y1;,3+ɶ+ JB>p )5!n$rA   \Y!6ٸon_\R.mZ33N`=ɾ8Niol/ Q\ϋe,}eEfٔ b9,fqXɪk|*3Dɪ01!@#nG͗顁+E5tdkP"^q["0y^#   󴼕M@7p4vt{,ΊMòL,3IJD,[$U{R27d9,Ӎo)T J0G Vc)^Z(<1?  Zq2==1G@@@ Xy x,3+eM&,϶F+YeYLX2߀U}8>LDDl5/#;|aJ]1@@@@`,.uxu᳭.5QmN/ad Y㩃'JXy#N\Pn\n ڒ\ bW`N6"?^wW+@@@N 5QDd_] MԣGaVJV~Q@{˲l+YU<@ Fr}BzФ6 |I}@@@@`V&D}6T]$| \l~TVո+=WVeT{ꀯoOI{wDò9(YaDGH.@@@"_`2M- bfdG+ǶwfMmb^ܘ| ȭ|78պyy\5 rA!%< =rQ    Mm^j^) V_R'I?&YfD}8]KNJddTi:ꂬ4yb)LO mW!   .0ZNS,]ciɣS5Qfް[Kr34#Y.R"+$= }qN4Cw{}`h9_ePصKkw2\mo>h'; wRS-zp:|;>~4=t9]> -c6 ǒy:͕˗x{9ĘA\.   D@~,E^Vt~}D@}am 0݂pFQFl\X$ab8Q6}oelipG6aY{}N]Y` ~ Hc9D贀[+5!AYꅅGy#! RNv   ej\Mgi "+VVa6xHk{c^F<;%QXhG$1..WFR$޳mו/) ׹8IK<-K#A|t.Illmr|a zd;=Ԙ#"/    @L CK)GK8Y֟=C,gLeXfed,6a=FC~ч?5 0V@"S0X)~N\1Z3V@;p{VhL[;~ԕ s@ 1@@@a= ҒwF"K3]cL~=M+f @=@@@@`2nX?_Z)IwoQ ƕq [gmkSi@?    c >TT=WVM6!:}roӚi9;E \,a?#mMz5bzGL~.@@@_^1,ZNNvd=;y#    Q,` Q|i@@@@@Q3@@@@@@`zL,E@@@@@ 1 @@@@@Ktɲ_@@@@@Q3@@@@@@`zL,E@@@@@ 1 @@@@@Ktɲ_@@@@@Q3@@@@@@`zL,E@@@@@ 1 @@@@@Ktɲ_@@@@@Q3@@@@@@`zL,E@@@@@ 1 @@@@@K av~@@@tU5bS^ߒMn Z @@ 1c@@@ ,qw =Ʀ5=@x ̬Ah   $`Q.UMmRSz[<4x ̼A7̙3lֱ@@@`r[# @t 9ܯGߡ       FzI]!#     a*@#Lo       19/F@@@@@0 7B@@@@@ [#     @ i!     zL΋@@@@@@ Lz@@@@@@`r=&      =pZ      09bk@@@@@Sazc8-@@@@@@6gk@@@@`VՈMm~j7TZ,61@@ vz@@@{ n?$a'M46! @bOGs@@@pFUST5IiNNj7'# ĤA\4   !@ɪȸO% "@#p     \A       .=Np      pA=.#     @<\   ֪)pxm~h:`@`z">F@@@Y6uglZ#`  0=fSc#   a,UMR&9:"`@`z">F@@@YU|w87@hd> @@@@@@ zD-@@@@@@`$[:@@@@yU5b7e߷u) fMǬs`@@@@g n?$aM46 |0@`vz̮?GG@@@@0pA fx]ڤ4'Cto&@c90    %pn,@#]X     &@#n     # م      a="q      0A]X     &a"    [jĦὶ}[w%J @ "   D6|gSشG/@ z]@@@@^27D]ڤ4'CxibU`΀Xh9s0$׀    @?y q      0@b@@@@@8C@@@@@A      AG!     L@@@@@@_G#@@@@@& @cHl     /@#g      1$6A@@@@@ 3D@@@@@       @ {"     zLM@@@@@@ z= @@@@@@`=&&      =q      0@b@@@@@8C@@@@@A      AG!     L@@@@@@_G#@@@@@& 0m$̙3 c     D?;[-G1     sB(o/     DA\     g@@@@@BGTF.@@@@@z3     Q!@#*n#     =@@@@@@ @@@@@@      @TE      A~@@@@@@ *zDm"@@@@@@?      =6r      @Ѓ@@@@@ Qq@@@@@      DA\     g@@@@@BGTF.@@@@@z3     Q!@#*n#     =@@@@@@ @@@@@@      @TE      A~@@@@@@ *zDm"@@@@@@?      =6r      @Ѓ@@@@@ Qq@@@@@      DA\     lУR>Jqq~Oda?rmIIIɤ      0@L=dƍ$ڵKkӧO-6TX^{5yǥfBa#@@@@@4z馛^#GHNNYtl޼Y{q/B1gP۾Bq/ @@@@@b^ ܟI\Ç}<4++KnVO~"Vj}ދ/9g}g={?+0G]?:f 30gW`Οٿ|1xsYO<з^bA;     \@=yrax˗/wm6GXF@@@@@ GuuS+))W\\߿{+B     .sAZf=+z VRTPU[ãA Y-ZZ-ԧTQ^k=}`E, Nf7Lv7I&3d7  Yi^ܣw(Eޏ9Gkj7oTΝMTkC8N@@@@@XZIÐ!Cղe9眣/^^z={V 75k,c@@@@@@.=ڷoohժѣc=l<Ѯ]εk@3㓆[e˖o߾nNh"g@@@@@ 뭲s&     4V|ңB@@@@@4zdcM@@@@@hD4z4 +      ]Fv     HFFTd@@T`Ŋjɒ%&!LCL" \FF^@I{7 7ܠN8v%Egy<gϞy}jԨQ?n-d;O5i$MTT(f5i$o}KmiӦjvRvsCu*9ˍ &>}ӧW7s5ڴiԡZjzkիW/5cƌ{͵,OE g }5>uFr9xJjZk{>֭[`cl5״!!-nС]vZ|ǫ L[}hB~VR-O>-ZmV13whєC:{=&K\# u BR=4CI~EYjZʸ23r,`n#GjS_w%Y+{W2oi>9?6'ZP/{y=ܣ?#-aSLmڴf~CNgY_~7nn۶=z^hQUiO/"=f[-[oV)?%µ$KŁY3?zsO]纑\>.{gэ7X{.Z8TH 61Sv|M3ݡC}GhС.\ ͏mJ~r,kr\*g$1|ଳ-[SN^umnPj|}Eh|NѲ˓p0k$yN[}]馛 7j~P"MWA 5 *U Jnva޼y]tIz?W\qEpٗZȨw%8>5}rޑᮻ<" |'؛SOUaw߭/䒢l-сkCT:Y3׆Iߺu|Yz~m74z,%[K}MݾWq8MIK-?>pF>Dod=\~8ɓky~N\1nkr}%|Ѳ|ۇ40wJ=\XY|yLr-ڼns1Z E4e,TZfPCH jمk׮-ȓ4vHytر ofk/ +fYOEIW UHs_N 4H7kL?Uz}%%OR~E;-OI9lE˸6TPI}ڐ?\[׹n/ _OIM>Z*9Ҥ_ q|M\c&v-O'/%Ë8 o,r,+Zn-e:ɓkCo3UVW_}]&7*C=]*sI,_c2\nyNr}I[|Gܓe,Ey͍7+Wo𐶌eJLΠ(R٨vA^#s̱$Q/#pkӯ1_<2^}Ul.b i_nK/I"* _" ]dAǵkCE춎K=|?q݈*S׿e_Z>uKKR)_ӰH9Kӯ$7Wo"\%8uC%pw 4~mHc[l=.7LeHxpֹۨs1.cX|ʸ2s&b0΅@H.v$Gwa|0hoU勜/_nwcagm',بM^6k֬pf#TۭJ>FI%pNk| N:kCIߺu|zJjgy;U%C ^{}w{-e=JUa>Qj3ku>ɭ_~3/\D+e Y%Y^>z!ol&(9U^ 'ǜz>TZYǤ+*IѲ{4dTͺ( X|8k7JGX#I'ZjwJ>h!A'doy҄ hO>d뮻 zN<_uU\&NXL /=iFze@rm(,K}$\V\]'V>zm1-ht9:v ޮֹs|1mVI=L-K<o]\j'Yx{2x  PEܦT)cǪ޽{={ZLX lʼBF'駟*Gծ];F)ش:p$]N{͍/uG+ɧ2 SjvScƌQGY#~WC>Rɢ̓jʔ)16 R6m8quF68O.X@͟?_ytM,{?s`Y`״Z$qe\󞎹bwA!a7A^tQ|9gJdko_o޷_tm|OpC]rhZZ~GR>ic.Fq[~u!('GAe 6(3V) EIq60`۷oL B<=Q4JPLt;6&p8|t0Y&I%_gko+dveݤI=n8U~q=c }acF>˺^Y\9ߕCtwLFe>-k=}\F}[e̊6hh(ðHw)Y~G䭷eiC/сc!*psme̴ \S*ѤuZ|Xg5o}מD9qQ8fۨ$7KQ[cA.W!XZ,YO׆,F>eŋSN9E'c=zhMO?E%;TRYDh1$j|NIܳy)$~իWk+Ie:פ-}@GL“N 9۝\fWN|0SO8} 72BIJǑڼ>#H7ҹ+R "3Y%Y(<`GU XKy~kC9e>kCOsM4u#*V~>ɳӧO֭[|`%&R¯'}Dӯ$wR7P}߲37;nho>Y<ڐȧ {]PаU/*sID)hrh<'UsJw4rr,⌢.[EeSf%7hiYx $gʣԓ&M]aWӎ󸏍=ٳgdU>C4/XTE%ҥKdYӦM'`n-/n'>ܧ>c#8}.3sLi:׍4_IY.5y|tϱaN麥_MU_In`3o޼" ew\2 H:ܶӎKn$ǁI>k>i]TZ\9Dž9&4Vzͧ]^ӎT8~d`%T0[>el$2AG3 P_̫}tɀ@=nvܹ`w e^weÞ{e̬8n6Jqm(F>yM.S_`v}uPf"1_Kժq6D73 7K]zn|LcE8`ڷQftA6@oY=ck-XwU\pAA30Z?rƸz+… ر 3-#N:$Ӂm~mf:9/ZF/hW>|x6d~tm8W&sHֳ\jO<]|'|`%&RBωj&s}63g,ڏg}VA-K&D]pV 4>>a3 KP/)_8\|Kz?Cu<^ 2: #1ڸZ0;OKܸ?^23rZcW[nK`[>eVILʙ$_0k,ݣGlٲСC ip'p#=68c {>:SP@:."it&M`3,չ6DE*F}NsT[;O]纑\G|LjKeiؠL8ZNvGhoW[UXJ)8O $F2Xh*i?,.:W=&]yqF=Vi;46q䷒8lذؾwOW̸Ks:Z=(L^:{l_Jh ҝJ:מ+駟͛7uzرRFKg)t{j?z>_ך~9shP:17УG^jya6DE*F}ڐҞk|:׍e٥K6h]UMҐ/Gy8jK4ki>C3d[j_ҺɺrCy϶a}C3z",ڰ)HbA$GamkYSt}ZҞ|%uH[|GZQri4bTI]4mڴR iXҨFQ4rpq,{x޼'v2Ys](x[AvjAJ N6LeQ~ 9j(H)[tMq /!0n8[7tS!n`,qm,쎛rQk;8Y:׍y_k9'5kL5xv{%ZbcD54z(oGׯy[oep ?:k׮}^¢C]}>OZ8r\R+g$1ҖA޽4J_~fC:':g=&mQ/740w4^r3)j>Q%uq7i7Mt*-&)4@@@@@@ td#      hp@@@@@@IDAT 4z<     8=c@@@@@ȵ.>2     NF'@@@@@r-@G#     I0F@@@@@\ #      hp@@@@@@ 4z<     8=c@@@@@ȵ.>2     NF'@@@@@r-@G#     I0F@@@@@\ #      hp@@@@@@ 4z<  @4icǎ?,u7<.B/3g7n֭[o_t1bСj޼ҥt]3F͞={}l_?\iFkjԩ?Vzk6?5v \m͚5jܹK.Q۷9rZ@@@ '|8g  u&'6o#xWT׮]m;mK4Ȑ7t:SU֭Ad7/ߟ}:ԣ>Z5|   +@G:  EN{ꮻRsLQ p $dMJYo1p@u=xCC9DC=8  ѣ A  4D{V-ZPO=}KnR6Fr7KfJ^cZnWZZjeYzu#c  @} ЧG}7{  Hz&MVXa(14%K#Dܜ@@6   @ ?U'x[H3S/߅2l[:'I_n_~Wl SNe˖#P҉w믫N8AmjR{OKFWI> !}huQ꥗^*;gue.]/RwyċI7uSӦM+.6 2=x8>]E:z!ͳMO>YuNkʔ)nq82We]Fp:ӭK,MZt1F@@ y@@֣lͼIZ~n"WfϞmF#9r~'yDvi6#CO<6OAhbO=T`,۔;NS*z64Ph`ĕ $63g+Wu+yW4V4$_z4\}'7qjo|߶陎VsPL@:Izv[zM!;xgŋe˖?n.*yZQF/[6t߾}mK0M[mm3F@@ o[YS`=@@An8oz7?pxQMh &|K4d8% A"뭷l"s.p:lvkE ?&o+nQ_0^<-ZM=z }ͳyB641w}ݿ-"1o۶]_ nĩ6]^#  U[o0   lHΝ;oY]V 2DUˎ~ :*7nRmi,Ӧa#Nӑe.nF;-yUJ^%uJ2'NXo~3Om0hР- PهM7TIy3FuU=7MlҾY}裏9lC&̓u`%17v=NЩ 4q`L   Qd\@@@ suש_)Yf@@  T"0bLthMZl:묒q[f!7 W]u|O^Uy} wy)+dݻ7y֭ͺf̘kaׂ]zꦛnɇeIی#   +F|@@*pZ`Al*ݻwWO?dmp K.uU=H44pAr\:5j 5o-[ƍ uEqN?xmM6D{YS)nXj<ͳ}֬YOW-p cUG}tFO-_}h1G=6. 4q$r5l @@2 61VC@@tnܚ}ٳgQ>@ 1691 1096 ?@IDATx x՝ҾXb-yg1BI8餛LMLyx}zr3MB:=3asIX:,1 mlˋ,Z}[URTҩ,_~tww~;y7d``@>HkkkıqV      Ț2<3ܹS^x9x𠔗{{{eÆ rWRx97      <4Odvy'[o Mz22[;      @M &ڃ)|پ}hǁM8      @M &_gqF7md=m8      @M &#GFƮۻwo`[      aS8͞Vh _JKK'O6Ż@^       d<)eEdbbB&''׻-ؘ]޹     $*@ϦDp|AA=k0j||n+//\9@@@@@HP)Ad^QQaO;00q!2-@@@@@HP)Ade{wttu{n`[      aS8K/ݿ雚:o}㽞'e      0O<$ zr]w3<#^{mȕ^}Uɑ[n%>EVVb@@@@@X l5L!!EJ7^37,w}Iiii .˃>X/?hYg* QъIXixJ:Z1 :MCSG+&bQ 9z(uh$P,4,]]]|EZ[[C7qV       l|)**۷ׅ/lϦٶmq6hN555qV      `ye!t$d+ul??uɾ"ul??uɾ"ul??uɾ"ul??uɾ"ul??uɾ"ul??uɾ+uJϦd4G@@@@@X)+[C@@@@@-@ؔlaΏ     aSW.     $[)œ@@@@@Hc¦4\n @@@@@H@֔Y}ΟYYY#G@@@@@W6|z63Ɲ!     I lJ:1@@@@@@W)};C@@@@@.@ؔtb.     /}o;[(`,| _{@@@@@H@$]*6My,e^s     n Dkw%b=J     aSJUE@@@@@ lr>(       RM)U]@@@@@pKɭ4      @J 6TuQX@@@@@@-&      )%@ؔREa@@@@@@ܪJ     aSJUE@@@@@ lr>(       RM)U]@@@@@pKɭ4      @J 6TuQX@@@@@@-&      )%@ؔREa@@@@@@ܪJ     aSJUE@@@@@ lr>(       RM)U]@@@@@pKɭ4      @J 6TuQX@@@@@@-&      )%@ؔREa@@@@@@ܪJ     aSJUE@@@@@ lr>(       RM)U]@@@@@pKɭ4      @J 6TuQX@@@@@@-&      )%@ؔREa@@@@@@|nҸ(Qu@@@@@@DkOΕ?+aSfwRU97     @zW(sa8      @* 6RmQV@@@@@@1&*      $@ؔJEY@@@@@@     aS*eE@@@@@ lrB(      JMT[@@@@@pLɱ 8      @* 6RmQV@@@@@@1&*      $@ؔJEY@@@@@@     aS*eE@@@@@ lrB\)78wqh@@@@@9T@K۲둻-ѣ?;)-[!;oKr@@@@@\g PF屇>4yEmSFFU|G@@@@@ D?H_{:N      0A@!߼d˩~VJJIi}~,@@@@@@ үN 3sRkhBwr),6_f\̺Nv@@@@@pPJY"ZMJV,wLLp u!:k}?(wiphϣd.~)P Ґjļ蒩ɸ RPYUT\s;#     YYY|c¦Ũ+j,B t(?g`YU)s~J{L{0~P~ 'ȬG@@@@@`A\i'lZLߓ.7lTp~O}vx+ef?R^hҲjcko)/r~@@@@@$ ҆Oؔ NӺ.g~K*0ES299WSPy7ה~ޯB|e#wIO1:5y@@@@@`I %\@ش'l_yB?e3QyAU"O١J*~62/h?s Fo=      zouAki;69T$¦ũA!+jhWeX]24c}&p|J8r$7H~k]4P*;gJ/_r>y浮mZs@@@@@ F{>'}I,e_y&ѯs,? La)T bD>ѯX4l) |&V)h_ **<\a0):Mʣ    "=@~63ޯe7%=aS҉Ȓ¢eKd8Eys\} 3S: Ԅ{~lTϤ辺hd.Vi5`KSP`znMJ`+]er}~8 @@@Swϳ3noOیۓ)YGVfOjUW}F 6:߈VӁԸ 'Fmh559aI &Mh5ljr`#XHV [Q-e̊o, F r >sP>G|Ad|2]TrV3sޒeg۷SrYk 5ss %"[m   i&nåC&\:r-hWמ'G^a3J 6n"|Ϛ2ˢ\@VVA#Vqh*Ҹ";Rn"lK/ؚk0FB`(4xCSfJ٧PK2o:2Дޢ]rt9f_]9SC1]~q! *?' .RN\^#   (Qi=dz0<(ou-WGow]!^/ ¦Nk6`QKҏb3?$ubng{eYUkΓU;j;y_Fkfqgizb4Òg) tZ>_}{++8*tCZ囹޲sMbpM0u6Լ/?%3ZYX   +sBx`:rU x4vh\~Ls3>(%\0zju  h#v`hC]~yL<,W\*{펿Ys=y:ّc-Nu?dLJ{LMNj>]`w[HϦ` ^Gг)8!U+Rw P|lSakKztK]&MW-Ո 4+i8-##fc&f[̳VeRUV*VzXv#   {]-9[K*Lo wW ⮺:5Թ[&uey^i*ʨsQ{{7@Nc3%%R9>UX+&O7aY@@@@-0C__@}f5&TڰRYxi}`[/\i'lJ&xW4g@P`.մToIho];L7zJZ4P"G@@@`)D~9h%:i>PꍜZ#6_.k'+WosC'6%v蜮ꍲ@@@`t#oKh?T.5ӥRSQKW RZ.r@XZQjpG k7HQQyY   ɡ_MSG9ҡLJ>aL6f  @P:^ ZV*gyy    {Iå$]-A7n2+mMUÊ`W2@G`rrBz{N^PfNPM2>>FP5f2܂@@@ uz{N{{_&\j9'm0_l{,+mML9̕5SO@ ~-Bo2B:@@@|M__#M齤,7eå5.H[6ͷ38W 6@@`q9y, ?/T8j8:;;GʖHeτOkCF"mj:[[N7\dC5@@@:nz5RqI .7/OV=} ]i'l ކ 򠆖w  @~Ts!τP+BBںf^5fГOki~[v=rtl/-[!;o~.   3 VzK3J;ѕ6|¦*pAJ@@`^uu j5眊8ovOW62=Ww߷T#;/X   йz^:~-3OHFϵ~eKaѲ6^,J>a[]yP3"@@?%f'o>OOG[ DNn^OZ髲u 6@@8_ Ñ,YQ^֙uxK6_wu+jFs  d}m6ٞPm3-ϼR毤z؆  @o 9t09KK7ӅҸ"))Jkź9W S:<)G@@ -ןwC5>~*o媭z怚d  8.y\:d`^n S}YRͼZW :$<+̝! @*z9ўOK~:ǩ~8dGjE>m5!VY<)**ه7   @LɉZ#h6\b_Dt<3$9Kr\i'lJn=]yPS@@hi~[ΐiYyN =N9ѲWc&ӾO/mT[YVnٜ @@@gFpWd`+P\iXsm| .6^,+mMS){WԔ  V#vxV)/|y1qllXNO?4frᾐnҠ̗P>_~>A@@LLeb{鹤_'O'SS6\l{/1!SnnA`/_6|¦ů+jJQX@@ M0 N}5ۤxy3@@Y@Gi]}"F;o+0J~(M2҆K:Z;6L8YWT'q(  szx:'vdee/9  w=6˙l#oD^*[V#7_!xΦR;+\i'lrp$Y%l g_hͪ6<8[ WTg(  dy4|zQ{B[~I$#  k:twwW,y^N|/f1WQ.d ,~lpW6|&w'Jʃ@@:lC&|jc}:bJ6(~*zvOhXUʗ l  J=ݭvX:Lf¥vfw~M>ڙva69,u\yPځ# . O~zp|K^^ԙa14x!1V&@@БMd?d~Xz{NDDigU|eu3ߖSUwDȤ W RYm:hY  t)Ύ#vfާ}S%ڰ lYzhm.F@@E :̗oޞ6*G)EΌhK:L ޶y;ntV`/pgIKJ*\@HN9Ѳ70OI/%%&x:~Z2k(ł   #*i:cJbBPi `||Dn3^yy4nH|)β6-c]yPݗ  @j mB &Zi~Z\/(I  ,@P}yo驴̽ʿ=!Gp )Z. ʃ(/@@"gX8~t9 w>)  twNϩtzBRU^x+J()q-W z.++s0@xޫd|?S}-" d@d+:,#Q)LTMՆ 'J>aiZɕ5-q)@@ 3'4S).  ]-!=4T:.#QelT[gRT#V&O6|¦qZٕ5-0 @@ 3xucIp;  (0J:`?]G{Jzx/426CJURZuV"6-Fm5\yPS# %0סtU[e[yf7  x]~CYQфIJWK\i6ͷ38W 6@@{uȽζ!TAaYYpC  쑶*UV=驔p )FtAM#Rn@hx7~O   C6T0ߵ/󽳭I} y },[V#9a)#J>aS<2KSPWԥ{  szBj0bT@@z5TҡW=DtW ^թ}WV  x Ǐ%=2<rtB 1   *޿*eeeKEJ5ue+LO%_6D`A\i'lZLߓ򠦯0w  0\s/7s>m zoYb.t`twHyy4nHt@@OI:ۏɉ J^oUJZTW 2 }α  !]reLL}qr]yF̡Zߖ]%='Ǖ% g@4D?k*-hb ҆Ob\yP @@f^i=ReEzn@IDJmx,ΩT[ }־&TB*(J>a+,SwsAT@@`~ڸquӱ7w 5庛*[0@H ~I_{Tbz@>22(((6Pn4RTE9 ,+mM Wiy&WԴ@@U4{KZ(1?5PS͜]?˄1؀ i ޾םhoJCz:]%TRZy'J>a/crApn@@`QQy?u)[Vk'@I'ay A@XJQ#IJmZ+1UZV-k]4kI fAp ߷t\@@XUk6Ed|h_cN5.;Jdwq:qt aT2m ٟ7  b :MdBv KoωpŇ g{mq=ҿCWRфn@@"_?!Pq˝RpV:ToOtHwj5n7='D'Ȏӿv8>O\mˉu@@9 9+;;0|4Rss dEFK?]M&)]V#K!> n ;6L8YWT'q(  @ HӁ&ٲ/faucͩr2DaW ~H\(+ @@LLOIE/e{HQ"SQOC'52Ԋ6QQX @Z hΎ#Cޞ299q:dE@I?Rfz+ۓz>QHV ҆OشU^'tAM/U@@Q:'TP:< NQ-1 U.Dk戊I@ {u`\>u\ KwM`*cIMsEX@ \i'lʬ.uA  @ KWPC2*07$ Q:gł K''h譤89e>x2:2Pw  xAGtqm,xAQUk$7 aG@ mGm$P~e_P˷п;k6^V 7n҆Ol)\yP`  @_ާ{z~(J{Dic6Z4P:GT] ҞQƂ@5-lIㆋxEx)055iz) ̩tu}sR&''"ʖ!ίTFs"g 6-tͦ\yPӌA@@ eaMPAAP:6E[MP J)s,&z.>صl.o8+ @SoPzIOyIpwɍ؟ b ҆OشX5qAMQ>  @Z LN -DysUh0@ g k`jYymBA`{GܔN}/ @ \@O:Ѳ7[tj]rkz_„JyΉJXZW 9p{&D|+VO/\%4i#_~AIzz)ɐ^ /GG<<̷_|h_n\do=dHz(u5IG!sјUZw˂+mM,Q9]yP,  $A`hdžP4¨.Lu6a0ʥQB /U{ 4fèdp#A5󖩩)&M{LFv~lAIi&f+x  \6o]2~ٞ&,B-|23_!; +w mmԮ hj}f^U6P^? ފvWuu)M6|¦Wʃ#  a$Bi} *8 gQ30u+Kph222@9Sh C/i5j CGCoqxއi6{^Cѱ!;/X,' L=b;>jPeB+3tY^͛leޛtc>0\*K'RgǑ;Lϔ/3=@,5ڠIǰ (J>aS:>] xO< xK @@RR`JzMC( Q&sO#xry큓sQT6 ޢᅙ{kſO7cCo}k'ǗgCo)3E{&ײeMC^Z6-[7glm8@x4Q'ެ^][nlԼ66n^`;}MhqWxaZ~Aq Һ3|jheB,RiumO,sl{E[Ù[mɓ~^JJ&XP)7fPw:([k~k@ \i'lJG-tAM.8@@Y@{w}=m6:6Jz;$S%44) sC'4Horm8p}h{wNke-wJ}Y,)kQCڈptDC+!k FMhau]p ULLgM{]ia!wmeV]z t?]kk<̭K&u[Cbk?S -:ju:;K:|g@@?2R6-|\ו5E(&  ,@<`\v:`Ӂ*ҸᢐW<ᔆYD+}_:hm>IwJ@J{ku|y0&oaѲ@=Ys%jT%Uk$'lN.ШÐ/zC@IDAT 2Re;RO{ p )vR   lK fdbG ІW&'8huH@l1q5=d2fe^~:s2%V&cnO ֥wִG^e l/%֊ǂ +mMݢ$=<'f};66&۷of͚i+Led   [/LJҡu.9,bY LH/` jq,B/k Wi/ t!9@Lp +s=Wn[ʩ=|\ver9ȿ˿Iwq[Vb;Wԙ6@@@pS`bb̆Wb|ey[]b^<͘I⟾y1/|ί^s;@p )LaeiΝ /v^ٰa\}ruʃoHEAy'xqYAvAJJJRV(3  {>'}mJ˪;~ a ڡl )67[tٸq|_oK_s=6jll 4׮{Z:::D?ismOkCXp`O̟PNPK>VK{V<7ߔSeum#GmPZR*Uefyyy|Fѡ^#Dj^)^{Gt1:#{ .&4,ALQv^+z1,Y>j>xeQ1`zm*L p`о^3WgGy3Z M@f{lrB2>pω:LNϮ/+aVDHvh'mEJkP/:KY&Jm E`5ZKs/`BU +m0^_.K@@K*{ﵡaOu/'i[(ZYZZj֬^-Ǜ?۽}}RZZb?0BFQ @@@@i<1,Hji:v(N-[L6o,{< scl1nqߐ b_b'@ka-7Z$lf bxQrt.)   ,A\M=kyMk~Z<(֭ ʡCd\|mބ?}?C9EHu<D4D%X?+_2C>![Z,H#ۯ1s@@@\ F/jtK/ԆMl!u,C91vΐ4i.6W])_x=&RDSU @S\!ry塇C~gOin% @@@@b г)&;fٴgٺu|+_o|!׿._DCUVlI|rwߍ=X==  ߡ:=f^v}zՕIqг@@@RUR~ RSKP|Ͳ{nٷo_ȼM\pFo.CEMWE+@HGr[{~ [nʊte @@@)J>a<+p1_|Qon/2]~墟t_Z[[Em۶w-˖-x@^{5糸Χ@oIy[S{4tz]}|>mTW[@W4    69Cmé_RW]u0z N3usi )}ﰘE0鹲lSdztYuvO|EEuVN_geKnY}n$bGG^~%fl$;o!7O)@@@@ MIOL6O)5#+,scfnIhCWZ:\2' %;W -+,_J˳?HӻMV#ViFF3ie[ aM}'kϒ1HƢuu%<<ǥ7/SLMNJRqJuZ{prE7kz :?(akE&er"xȈL c;>5 vL>G{-|URy7]eҒWsؼ6A.9]/9Nm䘟韝` CTbʔ~d@_i2h wyv46@@@@ L) ]b@~ ׬^-;n^2ɞ   aSWazހ)?c{h'^5'Sie[6uW\"9'1?v2CIEmk̷b|(r8D٠=A8%VOs\|`nqzm:lzr6h4~P]fɯ,l_4eglֳw,Fd, 8=X{ўL=yM+) n|٨`KE _{o@@% #&xG!b |p x1vrѹZO,BQ}"xȿV V 7azML&ö 0oW.r|F{yu =֛.ߑKGNNLf{ejrt@lh[W٪\%G Z!S'vIww=ٹFK%' ZRN    {=QgM%spx 7xFmL#: 4\ԩuO O+_sC.wIQM>0nzhO.]4̚4L!.ftf q!^c6Qa6q(ҹ泬Y1Ϛy+kWXrv   $]?)Co 6x-XכRweBˤϐO7Q4=PQP]E:Z1 K^o%p<4t[Lw4?+^u^Z1=uhâRI+^wu5ۯ_zY~cz|&~3qrC&`@@@NMiW {C {W @ ьKi'j'?*g`EUR 5a:}ŗǟ--ZeeeFxuRTTsr@@@XxW nꌮuKaK_}uyGPSҒ# 'TqqqZ7   @: ҆OؔNOUŕ5 )@Xro}W<3;SnoE)Iz|k\zr-7K]mmү@@@@ >W ⫷[h6@  @rertTe Wֿ_𑣲'_Iɑ.DnNYY_'/@@@@`\n'lZ EJ*|@ʻOdbdt!e%t|K/Ą ?o|֏ɺƹ}@@@@ 6%Ԯ<`=  0_Nʾ{L C_.g8vǵ˓O=%O?z|d s>;"   ҆OشvgsAM;Xn@ytv=`1]dWY_sv<!vxgtٲyi\p񝌽@@@@ aW >+jz+sw '0r[G_(c+.sRyN6{z{|v 3x;7r   )J>aSif; \FLtߏd_F{z!&[/I /O350`zZer_& @@@@`fW fʃ 3{P޽{2c錿]Vn G.̦ayWǞ%]d.gA@@@W B7<= D  =*dȈ&'N_U);zW*ˋq$@@@@ W ⩵ ו5e@C?~B#',g oܞijjJ~y5ۯ6:]'EEE #'@@@@ \i'lpʃ:  #܆N}ڽm g'$+';Ƒ ZCW_]ɣr!{Ғ# ]+ s!΂   @ ҆Oؔa^ʃo@"&MO*}mZ'g|vY{ˉy]kˇ?tܱC** @@@-J>aS:bpA2@@`4tjy76tڳ^xUlgdgo켼hoB' :ܞK/Xn ۛ    ,J>aSp:B5`@Dd_g"5uG o˩7߱(ZY'[e*9QGʮ'^|I&M#]zѝ>ٗ   +mM),^]yP gǥT{ W=w?s;X0ӳ3.o;{ڂJ$?t:l{ebb>m[?&V9    J>aS:vGe    d+mM ul;BPN!NV LFSqs]ĸ Yqӓ9S2%AaN@_t`;^H?4(z>]Get|̾x˰y=<6j_k34:=>.^&M0y]^aR>)*P/'%!sDٿ3^hgEE&3z J wM(_y]=r$O?)[ǒ[V2ȎN;޳Vldz:*[>kga7@@@S)=5*|(-?qe)@2/4igU7=cM˘ Y!%袡3hX;>8 北!. yaE2옞;hxtGT^/eEˋO^f^v]46}mF掓rߣIm=iN.+?*EQT`ĘqS7ewd}$nhz1 b/XQQP){gT;{s0wiv =d" ZW͜+tKrlMF*IF⏖de*ݺMΚFfݙ(,ES/F {O!:{]̅碰 6 oj>ä7u FE~ V       3" RuZsXljM*๓e3gn39H$w!Ba|Ԡ@m8ţAl(77 ~A[p9"2*X[Wn\pq 6kPNV.4LJS)Tb5sڲsjϤ&<"eheZiSIH 4R0!iD Gzc䱽Ls!d4l_WXѣ\?\S]o}<[Z!JzjIR *>)V|UMaPU*>۴fZ/j!"JaQ)aZ.਼^CҊU7E,,nu#E1[ncK=ǖXZ{$5& ПsNsC]矀{chZ| ~ű,A:aƴ8 8S       S"@ɔfl#n9pgpI im}1(n%2,, x7!ҹ婠ݤhW&K|AڜBr셸#3( ɢ9d/Jg&O "#'^a%@q3{XE'ъҼByz _ p&p[Ml(ނ 7»VZ_.p^nY6_/8}5 !MC_·C;oqFʅ0e+VZ|j:y2  WF$@$@$@$@$@$@L |.uFVj|Zu(ljUXlބ>5UF ܔpGj}xh7mCl;nv8~rxvjƽK*]; AӃ>մksc9^%(ڼ6h[Ӗx*l:4R-&S&Ӂ]#&\)obi}Ex)l3tdڃ1uŪB!*C07ϋ& )=$5#5&ǗcfhHw֣R )< 5"knjFdúª7>hI~ol!OGW#x*ml9r_Wmc&`1,$@$@$@$@$@$@$`naBz z&s[az6VlPNz2聀vNMqN$Lsjsט2i* ?#B~"hIOS"B4YzuqC?<0|z6_pN~9.-h yp*"~4խB ܵ{._+W*x{cX z }JʐAԊ߿?]ॕ'8Ql2"0.d(4PNvrx.C19:sRF ^'w3FObdDAR|2N}7k`%5U1aRl k bo8KGQ[-,Rlz_QVXhn{Q{h4;9`f `x.KH8Z|%uhH[ვ!+_kHz:T~? Y p 2ʤK>%?\=r$MQl`'$@$@$@$@$@$@$p?jknT%WN_ )6Vx6m|z6݅'BbZfv 2{2Wkq-?Wfx%n&,r<$OfPJ3ԿoT^6VV0i,",ܺeϜUqa?{{{= qSm[ONHHHHHHH1R8:8SgRrUzm8ϜMuؤ%$@$@M@+:zW4SdPgj#:pوN9qӯqfw)+WD'1Ä<#Í2gRR|*:|Dන5 HHHHHHȽt~:kN ?@wS;=1pr">'~#/X (/=>`=c7(6؄\  'PQUǟ~+sxԬD<|,UjGįA^=2ҰjZܵ!1s47 HHHHHH Ȫ82ǯ` @=sbwL)8썬$mT &  Q TVWm үy=[黻^< 6VFPU#eHY-* nB^Qv3|*ڽ555Yxp,QoHHHHHHHjjprS&TTW(M;ۡNQ"HղOWB5s 4H@Nv' K\ _Ny  kJUq ~9* !W_Fbvv6͉֬f{f͘Ρ 0!@i\\\b;!     0]2ӥC䄓(+aBP!0Dxt4kjçԬijYG#&  ; TTcDuWH\>lVSuI)'ٚURtͳO(~=***5sX^$`Ŧ&NVSBT7 %k\j/#ba#C.-NjQvMJN/CFbaa!6lĺ&mGgd\>xyn|l}|%     h]ayD%}SllqjYfC#  "P{n\s6: e3j++*(ӻo/tq>ƎH_}_o޴VM{v9eee-%)8c@~       ^=3E$@$@$@$@$@$236='vQV>&Lvji9 6JŸtY@vxn҃Bt"D';dj}^ܻ"' ":_!jd^R[Jɓ94@g$@$@$@$@$@$@&P&=9cS>Ŧ̚UB@2 >ڃ?/GRS1`gߢr !\^ 7 Ϧ*ft DO"hcc7S7%nEIۨ5{Bo܄mw輝u C)%<Mm$@$@$@$@$@$@#ZyCB-{3kXW- s$@$@$Z/K3J>nxNNO0+)sEtKXr!d4X'wUqq1V^t`ԩprrU~~>6lڌ 1aLt4óL7` hJnA?gZ)6t&~,T3 QlK>w|CN+iE_LG{t쐱i;S\?zBs`{tţ,Xiعk7֬GFfbGĘ 4ʜ      h(S@D{DεiZ)6qM+,TSdGIHH@ޒE8xN-<描S::QM${_=n7'gXF_>Ƶ]ۢӏ9vtO'Mh%EǮ{PSSqXļNM*$@$@$@$@$@$ asC)3-4reb97jΌ96  hmRtںax&vܝ]ZHHHCDZ*k( =6z^?O/ǟqVCu+:J7=r$&O[W @kZ~޵ 5#c?3[VI_n5Y4vCaϋ\%\D^-"STHp4Ç :FkIHHHHHI&U/7N- I   IV~w4}p4^8}]ץg**A^)BQ-VJD/Ԟ6kaa!núSmNDsB$@$@$@$@$@j&`p_05gԲO9fuղP-=L$@$@&Kb|(Doƣ61$(BMr\+GٕknegS#h}}V=IXz .+M;::N#0u$xyO>-}rc[$@$@$@$@$@C4 W&qW}"ŴeeSl2$CjYc   K#pIN.iڛTz-~fwCy+ 'r9i;A1hcc I>~Bx:%:وІUDΡ @T38JEuer-"&tS eaj̛ԲO9fuղP-=L$@$@fC -*[|5U5հjSfr EH~9K˔9 tL{FKiXq#m$Ka:} 뱐 ! 4)26=v CfӌPB5c X,|fѩRE 3YQ[k!oiGuZr225"GĘ 4+ q h0?#Q 3팾3z1C-{ 0ԤZ91XHHH42rKeZWVD>$z$G\x"~{.,Ιa{2Çǒ+bkkb!trjiV%    h-Z5ebSzP4HHH d+>MXNxUUHq!a8?<+]xkc=$e^'E$@$@$@$@ P&6tp0LD1]Q11&=##L6'     !}>ρOWx2HS(-(S0STsR-{T$iZ:*   c!o\V~wYO@3גw }#.,]s+^P>2!eeaDlJK5!0)6ÆNE$@$@$@$@&M@ M-Due5lm N/)ѵ'dS"ޞyt`Tv=|M*[j3G- Um\h @("!:}{)HO>C jXUU=kYh׮z ;;;m~\3؛?]CU ZVV&:mê됛ecD+“m`$@$@$@$@$@M#pФ D4IǍ%/gSHvV竊 ebLSBU @$@$@$.ZU#X#: 끗Ut<[ ;'vFI&QÇѣG+ M{;4݉~"tLt8m m~MM ?Bt:{rGIm; R^B%_/ž%Q[}mCx(emIIÞ0:ߩZ)6zqjYO |t+N_ni:A $`JuJx BtzEN >Ҳp"lN܊ZRBǍ浴fߟw4}S!΂B]>scU˼N㦢kXXHHHHHO]ˎ63z?Mir}VTSlRϚP%jYCHPh%v{䋭Ok:/ hVĵJxknBs1u'(;ȼ +ğ nO 7j /϶пFsR?,/~Di{[gt{XLzׯf VQQ1hHHHH,O iy3ĦBlzb)Sl2c@nbo{r_uŶjLl-Q\ra <Dh.a5 Iw;;o.Bb+dXr,..D+Yv\'"Ǭb_? goCd{ ?l_?/W(w gacamx^#gS urlV~d8ksX[sClrvvF 8U<# jԔW(U\:"ss6Ʈ{j 8::N#0u$xyyO6H$@$@$@$@L@KkwL{@@D{D?3 j9~ ^\>.nb9̢A9z6zӝsϩTzܫ\!&h{ws:%NCJBԸWiH(!0!UT^sv@+{H2Rh(7pqAAF:5  >tZB]ZV7'W;[HJqlk9v"rZYg`d7E/[qD{6p){<`,M;\E67پǔ~u*eWȼ-0/N}ɢSii)~o ;sbog*+>cmI0~SH]g?_̫y{]<. ':XQ{kNSP=$@$@$@$@$`r8uތ9b¯Fc~LshwSh2m`M %O\=ȭO;Bn8ksȍ@;hoӼOطtIfPmFO7Toߔm= ջ_nY_ܲ T~;!@8 f5aBnk{9#礗YB#\%,1Ls|&cv1vnZgⴢ_}ԫA㥸9xdTԐeRٓK/30d 69)qTv~8`ډEj(yɧpq{ɇt8;iTTTE^hשa(    P9{Ǣ=TU ފEdl-y"@I_$َ^ h7<|h m7*_&v 4o#7U˷Ҝ~nx6ʰfڍ7r|* J!YI/B|vIπ y F>y?&'SyfHOGWA}ۼӘ!=aߜiN)L3O5M; BA0KR\QY yg,Jh̛Ƿa{t NQ&[a.4aY%(^gZ`^R7SAnc#]۲q&P'!:)??Z/|YƆ{ѽ00лӷV4\(G[{*_t90zŸz:uOg"Ǖ8^to+B? ¥cQL! 7lڌ ҩcGČ#/șe @Rx;#1I5BB(6yvhZ   >y vQE}1x`xmP{)}Ga{jƎ iR^^vcu̼t'9;"M`$@$@$@$@$`t"4xMDYA90QVnQ11&=##b;!    }¶QU^ Nf,"c3jçdɐCPB56 @>ӟSfFt7<w2F2!1={5ksw*WbbPHVBrsǬǞӛ%%%طc~ָ҆;[b0b h{YYظy36N%Ȃ0)6Æiu0=f$@$@$@$@BL,\9>M4,\u?mOI_$ʹ,T3a = TTˣxw[2 5=}=!x$2VϓsO P/r\S_0**+u((WGuƼqq=|uu qPTT͉" nb`b딶2Uo, t~At~d&gO.eeeزu)''WicD+“>c[$@$@$@$@$7%XMaܨ`/Lw"Bt[l< eby/J- UobC$@$@$`*kjxGN)#Nѩ3vHxbAQY)OMX9wOcg nFҝ @qn"2%ǟR+3ޛ];iԲOL  0"gғixcQшNA.xyP7<ӯ maնm:x$v~X{3oF4y7bhXr2v'畼R=,tܜf V{=*!gN6Jk׮)-[PQQDyprrHȄ (O>^^H3h6L$@$@$@$`įt!%ewäߎEІHSlRӪP-jY*DCHHH HimJz \W_ /v0+Wb}x|֭[[xj^.ܼMXbM<5a:'{2Vѣ/e__,AEnҶ nF ӲHSnuEF 3)8yzz"--]x@CzԀ|OzHHHH,@vj.) z늸7cbp-#=|M-G[- As$@$@$5)JNJK.xeP8~9+l.^z> BV2k$ĖL/nNxxڽ ?/[4)! !GX['\!"c!'`BNvg-QXP w(Y |=j4EHHHH,@t,Z\KV c_ G7F90MLZI$@$@$";ӲcHpU/ upS5%_h@z>k@ޒ/+dFWV(W{131kY]t{pQTUU)}"nTӧ{[v-^_J^}h:< ՘\<"d^-Lf*'?ֿ__FdDՅ&+6F$@$@$@$WXf%?|' 3ޛ~ljçgeFGڨ@$@$@$P/):\wU<^m-KtG35L:O-^-Vr3<|- o'I_/<1v"q 2+ a=>Exdit:^JXO>mbziׯ_tsnpjO'vjѣt1    "pv?چ ػckc>⻻ehK@-{;&כZɁ$@$@$rǮ᯻O X^!HP0,¼ԫX _oYҊreB14>v-i7_+9dӻW/Ex n6/Ğ c:w^Ckv^#   #u.K__K.+ qoGYl߈ղO֖^GA1   YxId'r̎BtVyt KKNY>n3*O ӫm6ɓؓgRR =|d>tfLޔ& R{,)^c۩1BN$@$@$@MFdڹ8 5յpsôbżѩZ)6jY,TE$@$@$`^RX|GIV˳IߐU5X'>Y3Pbڠ1[[|>u$MCkXXlieײqqvWӅ؛&z܉7"''WHHHH$ OeXKƪ q/"$(mpjçd6ԲPM"'  !p1s<_7Zx 2kNAL|Dn9t0:Ǹ u!O(fY .0f4žz>{5yǹyӘSps3M~x   07eXpxeu&S6TDeb,2S- ~IHHR o"CgQV&vۣ{ODzlrصS˯+bj|y K SIp7wWqq1zH1*4$CFdDɘ&{a,7Mei۳))iӬH,_ Qz3NzCɆHHHH@8$(6vH 76yK'=|M_*kZjR`$@$@$`IϽgPZU 2),@tړI8^x9tb&Tx9%⓵?lf2nWG''Fw; )#GPYYa@3hu7ĞBCB?6vj1B6@$@$@$@J ?+ފ;BaƻI*8vnjçd6NԲPM -'   ]R{PXQ jlH{ U3Ȕgp7WϞ͘ިņCI4a%T!E qsP{ORjB£5d ]SQUp?_{g5=   C(--U@Mښرh6}UeUprwߏCT\ORhpj%=|Mj]!*K- U%8h X< k|tϕ}DN^b\d(ѣFa)uXc Y0"f&f kkrIKKCҾCC WcGۀʂB@[ z$ϚP(&D#l#j:8MػozPݾ}{ȼN/lHHH@͜~+h=Jq '*3-3>'YĄ ղOɄ1L "f!  \E»]'p5U\~xy/ĭbJ;.+-*Pc'+“kXfZ8;9+Y@nH?yQOlU}ĆN{C<9[ @C\/x$CzF&˕ן|N15|`ZDj7c>Ksb};~/P~=&Oy5UԼr4$@$@$`>+9i \-.S6~7&=$dۛd= l?WS/(;;8*^NNNzJJJֻ@ݳV=#{bȠAP pkM[\^%ܤj +;8x{z7]1aoN: yƍaC;   h ظq3E|h|Hz; )GP3{@~ӒUy]XF<_΃u ?c;G[UKH@P>&{PBH$@$@$JSfFt.::1 t2>\=6NRD:ixD<3 6S#B:}Z'^OAGF7?+GٕkMjѯ:LSço\kILlڜmwHEC VIؒ^   Q TT!&cWuYO_ox 7#\Wo#9^0of; Z'jLZ)6B2jY''  |y4nKFzahD;x$2VߤH,WYr|e-**4)O`gxO1#ؽgՒ޽G 2ײo޳RvE]]'?FMxz;mܼYrgtv(Nc`!vQ ঀ$E#))B8Q~AMXyGM-2+\Q)+-+EY^V.B`TQ'_Y۶7bcc֞6}K![PZP{ 76&9(mQԲOɢ]|y @k8~Q]/RLDx9Btу$@ai ۖ,a7cg8ϧAx58"7FY ΜGښ t.vTxF W%۱s6lDe# s;6%  ^2]^^XatE[C')2]۶pqv Oռ܋/+!)Az9B< tT[{s``x`k*55ecH~^1`Lg":zlFwP>Ŧ'n'zM<&  0UBt^N~). [ d}tg͂@1K+E;ڟpIb;xh0e6zt iQ|7"L>^={=?.~^2!-a! u iJJn+A"B3zXg$@$@$p')I/#)]TG2WW;ŢfGwZܴwbE.+_s'06:Z w&%{b+ֻ'k5!e#nO Or-d9"mZlA+<͜נ5NIH,@S#ELGR\jHn+wzkJd"C7KӧN[d'kO#J[G'< ~~ӭ_+5;LW۹Ub$[/^-I8tX#? wa{}0o@ mNzKI/ͷM; ):M[[Е ܝ]h۸hҥ"nW/ 77y) ش_n^Mh`_,Ǣ'(L*++qQݷ._|!7ӱ95ӥ% x8N&HH́@8*èQK#]նN<"& #yr֙g$gÆX-AH&OwL{;]Gv֚W0_e"_޿: ޏ{oM"mPl2щ$@$@$rBsšt=34!p?,ޮݻeJ{;tPHϼb8zDbG˼ sFɳh>?pAAx'wC 1ʶ=S-**Q`}{jBMvKض}G s. 2cD#4 6čIHL6S?( Р7 ]W *2g9y\Xy/UTT4 qp 7w7Uu\L-:vA.5bs$ExJODu&_Kw4}" Z>]|'GJ~߿=Fdn'cr ^ l8,\ѵ+>t;!dG{q^?.^)RQsO;wQBm7P{#G o;>T[$ 9]`D{d߳J;^@KLx#ŶN(%CV":^)B.:K0Īx%]׽ Dr#%  &3- on9 WS^ v8~Hz '6.WPQU\_ĬcwG9~7Jؽ4px6P{ڧneݫ' ⦦\O;p5H_J)<9fMF`L4l] /rz:6mN;vI+@VA$| c/π(cu~H!DA!=#Sb^/>) Io$}$TVVH/w^vttPa#7} N>Xv{yE񈿳kM8,ٝ$gDRoz<ܷr}D^s}yFC@ SS1PcWx+#`+ ?g3 ԛd3HIHHH'D xW{[<;ox/@Vu|i>[E^xbdExt1w|Zo^=ɐOH={ZyJz( E&5|||=ztuRle u7j7b :LH|wS{y'i/SϤhO#$8ƌ!C 7XH@mVҌkpC܁j3ІrBP ڸ&MU4&lNdN%t8ޜ~XW}dÃBp7"HCO1?4CxNŲ?ŅiJ[]`Զa<ɕN <=cǎ# 偱AtE ʭԀg }C) `սto>b/   V#r6oqx8.v6][.v8 -h8~QQrzv,tj=֐OS8xIBn"իYBUਬR68EydUJwenTkD1k!< O'o;DnRM?)4Iilбqh*|}+< 0>7y'OiB5w/nRl*!$)$£)6ȜNV<=v32BԿ__8;^SU-مm wm0XD.k޻ bC@klhLL}^z1hL{ ED{ ]wvvνgfי{9fuTF"Plz%A0_@jjj-гYtQY,-z4A̦|vdSk#Ǝ'ɦ6vds%D@"8b X.X>L_!T[XYt9|k# uON[]ӯ'%%BԹs'hߚ!]N*#Σ9+ K1Z'!vn#TL'&\O@-QsVy j'Ԝʺ@_)$2N(2XH.L5pr?D (M)i5#JƸE J[X޾U?mBw.Agϒbd{gͯ“J663 YVM*(&! &M:-D@" XFUQ|p~ F%XASWֵgSI6k d?ځbLۭ+Ms^+-;^]i]Aܖ=#)7;NaOyDKJJ*:C 7/OvE)} a3vOVFB npkm` ^n(4II#-=STK8!)9EE"#?"h*O V H z>vĬˀU7orOċ!DžsBf$ D~,K}HgG֤\K+ꉫX}1ILbfmQpә>W ,@IDATP[1)mT66mxljc'L6W" H$ _{̺w& rѫi9[N>𴒤S 4MF^~= voFRVh9捚LN`iݢV/G7Çì3E Bx=}=]6sRs(#RgrRd>3s<7m.zviL^} j=]]4Q)xNUjyeS6"jOb`{ ՓMftONICI |+(-E L.85Fli[\<F c4ج߁:'WI:4ڟ~3`sπI-v 11NN9}: qPZ)yk.\>tUA^ R(ɳ6tL)L@k!9a7ɥlmmX#zcqkD z[uk$t:;Frv3 {.H$[}" W^X`-br ɩ+6*JBI{<`ٱl owo3G"Q1+z`xj}:`9H S("6?r >,<=B$P#Hз7ZkF\Cݸih4ٚtGӘ ~`nFɊ4J F:KAs9UVY:tE(+(ęWT߬r9Q(Ǫ>7t1P@.H:(_sfxH@K#6y'¾Ϗ$8rጧghB[x>l(LL BKV?_|\ ܥXᒠHnS~\2/ɦ:MP)[D@" TC= I=kk,}aPTor Xu*+S͛P̔yIKƏam-[*vXLzC[^u2RY͛p߬Y2h8z5Υpqjώ8׭ O1#z6R( -ƮN4>OgŤI]gZ[Eʆ̐ BRsIg6D0n5J5m(KT׽ pw2LDq"Ͽal5xB5qȭ%MD -*܁xQ׈dX8ת /gT&;*

4/Erٹq)rC9 L.͟,ԳȫofNNNK}ygCjo+IeOf.&}=0<1jj;]Bm,:+TKd}1E5tjɼtjlӜoj|QYӚR+_%y/p"{nieBt|M *+`le'eU2t.$G=rN< PE"PMw\Zr%B8(swwAdrRw/O507˰T̍C4US%Ԡq7Ҕ sD@" t6mތ'Oh6X t"VE-Q|u1 6ͫ~mj{~MD2 ~'"Kә^{el7m|`Ȉɢ6MY:gL0å&ԟկ6&%OivP K=7išxp JE3>xoPj+7iЫKAn)j=D@" X$&%ѩY;YT/D+)Qh0􏡽0{ì*s6xrҐ{yT=|NniaKw@hUtt +]Ĥp1jݴ}َ"Nly~9|D]:tO=yd1jНVf =Sq}R(dɠU-際QR_URKJI9( ;Xxip1:&-}%@f4??R?'q":1r_{%.Vxwm6$$lPHbB3` W&$TGhUs)EexHMaۙQg۴\1M×d򪑯u")j+%D@" 4r|EJ↑N~EA(iw6Y=:u wu-\&*icHb՞Wg̭0TAat~9aT<^mCzhΒQ\*? x;CS%3AӔ -)H$@+ PPVH)Pd[{cvO7aӡlƁًv_zc_︝(-/S+*47cϪzَrY$!&6Fx%ӧTvIScOc(#.6݋Ġs!xē:jI]SxOC7&Ҿ9E-Kesgb`8}&]f Ypd%D@" kNbX`7+ďp$)zٚա=UӱKR}uL+Aϭv_*ɢՠ%סck q&}]=Dd+?rSDdx弲e/lǸrK:t7{EKO#6͘T;Ҭd"㌂XʾJTIGP-)۔$nݍ[,Sb'!Um%$mтhΆ^u(R@K!o@\H8D ޘ|"LYRzx:W񤧧޽zQFpPgȢ>.KHIMYxr+Zt?~HzޕMJ>dz!PTT!=#GD!}!7 'QÇcFVH$D}_}\y`֯꾛({i݅A:Ee3)fpcN$G—l $Pb#F |NGe~!27Aqu_"+OU:;/|:kY9 >ݡ,3U4l!#/ޅvoBrBacjy&S,8XZ7Vڪl=Å%o߾ʶ^Tϊs[ یH6cuơQNA9C-V}L*!e^eD!7Iff82zn7/(HjXN˸0^l 3ӡ+j#PVQ]gq.@׈HH~흪7aPmzwډG79@`Oek3fj #aP"6"N5HDf߭c*نvDƑ^ Y*WUZVC :5O~n5u/jooݭkkذ6m6F/4kLNFcȌ6yCFADs+??B lN.xj ߶/]cO%\1}zR5ۮt9N\EYChA]|_ghU$~-[Gb7ë (`oCG9|Wݨ,,1LԊ-H$D#PVVϾIIIbZź|~2(׉I;D0>g`rN<%?0lT6lH$D 4_}5(F_kg)pzqĤ6kp 0˟༧ۋn_!Og)_ mp߇십?maFf&Ο?8,CHgVGQnډ8U  <)LݭM^X, }u,;+]/@v49w7(Wz,PL*"+vAmuN7"IpAnBe@OtuӁV8rv=T6'M'V&f0[}[)=lҥKO<^{KeDj; AVcD4ԧvHfHN JHLB &pOaeeC5e9H'S-i&|&Vo6Ke%(GÈ߾INhݩp= ΓFSYU^^֓&ef :`r;=Gndi>X-ٗ_ݺv^y@$ *oSؿ)So ڳ-G'N4/)KHrJˉ ~ J^F5IG]\K00g[aY)!ccQfQ;' 1kݙʶ5؉شyjs"| wRƨ o7%iq˴ pw2L7t_~'f%x&9ԩ3t4522DNvȟ555c6YD}vH͆I߱1nC:%HFuY[yoH ǕrxV{Or }+DHϞoF.^k8x0)?@Ycsϒq4r6@…dlHp31&6mW-tV jv`innBv‘q>[‚D,^={@,V5lJWZVcFqS-x6 /.{]V3$jWB43=<"Mb;$c7=YãzF" H$@[G@I6׏anxRzDOv F3JQLY;yP*e7mJUi?nV7(C>ݏČt8Y"|zѝ l9}[LEcƠ;:ZI<󊌧)0~<&OzӖ(R5CI<7& uZ{t;-gBdI,Vd%e KK X2۳4S. RpZb% TK}{ANMSONDMY,2e)4Ie]%;%|Z84 KU]qu>oh"}E;#;8˴)yMz-"eEe!5MU0s0Ž+&϶؝Vos\|N1xII`ȠAD> VwzM_`zDUA,_hս4T%k %.YxˮU&qţaL6~` 1j0Ƙѣl$Z6pe+r Ak#XgV0FF0,]ٴmvӳ7P)㉈m\-NS<zG0urH-^-B\q=NT`Rzvې CYR*I27q=-8=ӯFZDzW`ooB-J$D@"I8y6m|BS>L!X:ܣҬ|tB Xu6i~58,_0:<UmaCc%a/z@?qNjV\Ij'"*)^bX!y?Vߜ9'W `TtLAQKޑӈzueB2R}>LofUѓ#2l(#&o3{M"3מyE,VvץEG'jOb"ꤣyHu$<SUc2۳iwzMZ`{釜?OaϿVsw1"Yi/oߋçPE9\x2@8O궁4qvO~eyH?}ZE~ tQrF.bTRe&odawpIH`;_ͪԓg6$@VCwdu:KF^ky|7`kn=Ƿ[I^c(ȅ 5UU}ܻ i")jߥCkPQQ~xgjOY$MA Z&V/ ~+Ggb;qL`|g2Ԕ}زn/1}ԯx⌟["1!NNΘ1m _ܥW"NL1*7cǓgoK='ϴr!] aJd vF~{-^M-q <W&yM?|6$[$+pH)]0fzջkNn.YUd,zH$D@"v'} ;z N'~Z䩘n[NnXdfV(l9.^Vx3m;$KcCMdBC.Uj0 %PByr:mjUЄEI)(LDඃζ.SHLJR#MV{ƌWY*Q[hGA,1Y#w'0cd{'8kqqȻbR|B<՞x|q3< [["ȮʙM '9٪VͼBM :>|8ʕDƐMٻ#5( UUɹNbZضc;RƓ31CA??a3Q},H$@@?_%8Ķgx|"xH^3W| eO'5ή-,~&,br 6%]`o=Ӱm\MoeSn+5 C]keV'߆S|!˗~;*z*8qQXm<\II<6]53ۀQ,PddfؾE,տ0v<3U}^XebݯȅRGg"J#ʏ,TEOk󝑑ª>IHUriV7۲[lDž~NGÝNvs *D*-:xϡ!Jqx S}ʸؽP=M?ֶm/H*/Z@FŮ6cUbLĄⷥz9 GuCn?jF@I<8u ۦ,t)n8O I"g~"Z4r~CYx=JJk<^U~ܮ^YfB"~H4>ݙ![pFW4B& u"†?̢<3/†ua@$5知>:o镒ljiP?pBmJSóTnDE50үFKK X@/$e!wjgEɩ۲VYo<܈xb[5GHūk>!sD^bҒ2;SCQFVs?XcHϾj*c&4P| 49%Ϸ[U"`q2rOCr#^ůUze[Me'5!MNa=ϗ>KKL\r)OI{?&nw?' _m _uggg8T6ύj}dӒɃTh*lR-x\uMʮU#s >?m_s8q$1KګآBD@" H$KqKDd᫠H|. E7=ݭMtVޞ7ITҧkg5Y_OX̛27ad՗K&i:f9QCة0tb֑Ni3{N3yԔ&W!!!"9~UIU"~Ae~Y'j|>=2q ?kꎬ0L"8?)&E3_y]^^V,L8@OQ<\ZJl=H݈%S6:uA[*c2e&b&T?'֞;[Vk6S^ccW(?Q;+y.߼7j@kzlmR;(=2Zv1Ǘc"={ظ8镳yNG?MCKuer LNH"r1د>CEUTaF*F{]D=E Rl㈌2j?mڼy^ &ë+.oL%ȶmlb7!mpS.Zfj5{2{ ]\k }bv{ʦ2RBFň|,&s:W@%]U7'Zð{+no}^Q!Y aR>rEȃ}TAuų̰wlR$9TqFň_^&iYgZ擭)A< |<է #}LlKSG#"2lDž5xx`Ԫ~@~APC),rnYQȒ" ?kHm}9yL?r!85fS(I7h>vt3Fn*||½ǜ072iLvۘda) vuv{(ip͚e?W@w{i Y$́@FL,Yٰv5`lkX7,al<$Xy˶''g'̜>'U)^XOOmv!xUVL6:Ʒ$ vJlT" x Zv06+?{C^#[+Y䢯 d4(U5i.#$4W)뉉>F*'MjlK+"4lI[11w~afуhr:"?ۻj7[n^ _^B>k ,53?.ʪb&/%;Su\C=} GC垝y9h?|DTC?,zD.HOC~zz;`w]T-w rRE#Sprv2O@bR"9kƴis!rޡMؔJi+ L6u<0 t%:NvsT6;m[U\PYjm^scck4l:&T06x; ]|k߾}ѓ2["Bd@IhN 9eAZZ62"'>r 5bɴapV, AH:tB\}48Ol -IF^?#OY|bCXc'~51?6lĆM 8rp<"A*둯A tEVTRޘ4hϻTHto޽5|(FWkk *nnpws#ՒK$&5\|lb{̿" (eOlGYq1sFϟh?ג3g .c|m{~6ĀmuL8~\Mau*<뭴|PAg^s'9 #2&垗PZKVOS5w[!&8&;_|G<>_KWhldFcnZ#l~,a JG<~nС:77W#sTJ9єu@@_-ʺROs!m C/#mdn؅J-F _[I1Ϗl:H/D@" H$ Gؼ/a5]nߛO]G5Uk0_}eOS [}v ]^hEYOnDAއabl4(?e$Ʀ%㵵_҃?/oul^甆d: ۑvI ēMz̐pXQQb< W?қVWk;WjC;z&XBQlYxpOAԹ>CвK V17-uHoPߌV5caۉg$]W ʋ9N-L4emy3꼉-nMa\ sqRE+H$W[׮2xW_KBM5B$ NDRV~v?^|lY%ߜ"^X"jol'#^7G%pv& ۶_Efu[n5đ^증ȏS5AXy̙Kʅ`qݼ6;k19iϹSE4R]=u)&E3Wnǹ 3 ~34;G~޾vxqq-XPdUrlǹ,.кiBcL6uDK}}/Eo7AiʅڔľF?V'XД*>D@" aW\<>{ V3'‘?ĀW"*. yk#[#Lxip r'<v"M( $T3pz꫚{^dgpuvzpDa ,xmDDD{lK3]K^\ B3 ֯j]Ml.~5O<=wۄۇw׭BrV:ӄGLksμ &XavOY̼lgMX%3Qna_υe(.@!*r=B0(||<CUS.Ԧߊ]i&٨?c@РVl~𦦦>+$D@" hR~*kn?|.AiAͣ|kvǵ$$g(ͬ(Ņ;8ؠ#&'ϮYSZ*bo^hŊ,A=HmA_UXAi?nDyzBE (&jRnTLEa90rTOCWgzM[رk7!&&ELԙN:T)Ht]s?`ealp؆ > ah`(Q4d7=L>_~iin>#Esv]2bϞ%ҽu4ulANqe7J2n0d'T-OWh ڟ~cgQF^NL+5kmj}i0Fa~;E]!>, FDd.Xԟ&14'˅n/߯YVffpqq3ѫ{}K+(Bؼ0Ѻ^S%Ԏ.A*wpҔ ~5d]HO'x;kk\m;ѣCNďZ D@" HZ"n'v +ݙY(eXϾغnY%Xy&EB< kC BKZÊ7sShYYNmK;6"g< (Of Px=\|Y;o/ClNʧ:{soAZtI=Ĕ҇T}zUʕ@EEۏ?6lD!Y-Q#1w}07wL{ǯwHW"%~i>^-jeI)_HQ'0dbv믦bHUOtyH7)clRZ'rٸFڌuېv##0PׯG UF  ?Э|#H$Z̼wfN) ")X͚+M1?Jj͘As|:XYZ(\w+;T6m DTz|ПlL4? i[쭿N^FX"7-eCzǮ/iwDPR@ET+2h}5Z!ȃ/`Y<{E34p=A#Cʦȧ|5`BAUxiM^lI;fL ^+G`g)V遾w|vK\L-MP.ȏIPE^8} |S9@՗LeH$@{GgHLJD^E0kʈiC6`}CN@ n zuChZw|A^VOf'i#))JCQAD @WG?YJK l!H)"8I%"(6Ћ瀨Z6y2kzzM<%R2},@cw"+![t2tuk?>k>R^F&;"wǣnd(i~%&&avǖI0d0ۧB¯:jrg!D:ڷ 3ھAtֿq" 2W،& ٜCĤ!T-м_FC?^KФ9`*d}/9zbk/Jd˥Ĉ'm҃@轧5rrae`FV|tjVoh\"|M3A|\< řޙf`p¼'O//ٷFFFhΥ̸$3a$ t;쉬"+b ;A9ש1P1Uu0r$,KwwczP3\'҉9gK2lRݻh"|LsbᇈN-S.B~1eZiPlE\_TĄ#&E*-]<U^hJ&J2{9%cVHbo2-:UH-}G3Rna u\1:EQx%1f5ߋ&1 ];C non+\xPKߎ]ߌdޫk_Ľes]%Lti9i=׭'oLbsaHDr{=pKd8hзZ[ FI_EjSILҽF|֩ ɶcR7pUf誎Q˱}"B~WÞF@L>yM[X4*Im\\ʱ% #r)ŸYY%F-S$a)읧6=NLM z8ZyFCȦʮh(7j}\ӗx|gt?=-$5A&$ƀspYN01Nu"fӟDUruD׹%3k>qbwKE I&!SӐ(ntxG<LJh̼^"Pd[s#%|Hbo8I}N7J `kEpٽLb{><ΩjVpoDIfS+<X\W8t3ЇOtPxӶߗ3Qs6=%:GvU3bʃ%7{T%bW2dtLaˌ _\#,{KqI@Ǿ3j9S'23%QX,c/bvȒ%v‹yy71ө/TsOS!9~pfM_bvV'd0PSPJ;sHxf|usаm<+Wm̾9ˌ俧pMtpm]p2)Bߏ4l&2-ZHZpwB|Bw_jz#*)W_[Y^?M4P>} :^_g_$w${I %=Yt!𬠐D{;Χw}&ZPmr <.])W$B' :vWThi ą`VOBpY@AER%h2 |Wt&ue,MKK `q'61&Y@t|ݯtQ LD\3n-GM4$ѵ !LxޛxUf߫׮Bcc}rcGaςgI*] $67}3zLtuV1=5p=p8\ d>uP)vMLڇ7G y={芿'(1cvGީ=\Ҵ.~VԔRRC Q$F1\zg%QG|u1mb-)-ަZ5h>ۦ2jdd2]`f-TNDy6=@XX8zzD&摁 3` ̘Ņ{G9%Y|zyLTw%Fcqϓ7?|4ZFP9$s:>bld3a5|7$4 ^%>{z k\ ckq ,KmJM3JQeQ)QIE _6d@ZjDC*! (Oi}s2$pR+JL}/,x#%Kke@M'OqX5uUȐ5I:BPWk1IzfC&a$̫p9*AܡԴ5@6B=@ǯ>㧡u =Km-pgQ9Muɠ4p73 $,ikicYPWs$ %06O/ ct`1bdTa~п1b .arىZo* 5ʡı+^B@BoJ]Q,1˭5yzD /,|K$έ[7Ȯ39tb1/nQblOX@Zh&%3 #%]!aT]"5l][}_Ń !$±wIEIdda_" }?~1Te,KB)TTT,4}Tޭ^;Ɍ<dp3Xk?KcXd#cۑL1f۴#,qX26&tYxwy=8.)Vǁ\"=tG@@@@@@@@@!>`|GnpT`c lK=;nÌ} &ZZXꜵ!k҆"RBKk"E5yC,Zqz/ښbÉ56pIS|Zػeokcwhb6[zu0@v`fmyѱ֛?VziKM,%)R/ѱN#m5z!^ Kfa״Um|y$1}wq\mWcyԪ nj=yW " cRzAr1'U(Fc>o"у,L1%joZFS]XȦr%8=V9E6q2MvutEMrO~`dջ 4F .'&jyBG a[@@@@@@@@@!"< dslާ{7aǝIdtܗ|HdS~w/K&sv_)8);y<16Fka87)iFۈmD QkغED9|LۉX_(]Ȑ:'X >Qnhhb[dI5*$b?xcPPTIcP/8䤃M,/?0#Q*od]u\mwdX6Yt3MU?&顿$;nffqGõ]Jy!W;~ ޭNNX9a&\$eEnyiwǯZϝ1CѬc 7n[S+G|HMZGc#uDIE%uaoFEDQ-ѱ\I0lu"Q450qUseeǮ#{ްv L3V}r#WCN3>)'I]0 Ȧ7`dRZBڴ"gd}Z$K%\SI{Ʒ&p,oz;O9_GCa7e8)ܼu :vD]x 2zE )m^اP1ޮ>wcLzo !OP'<'h[!Ĉ#F1HMYM4r^KWs|H(k{W_@psͱM,\[desvd„Wim*irPFSO &]dqZhomJZŇUX\t \* ]ۏ}d` KFڟρ m H IXa=VZ{QV6f/6,(p[!\Bu=ve5kb* y/⳰: Z?JJ/waIe='u5i{.J2YBjz09dLc1o!\->譍x-XMy'hdgJF۹B GEN$mktq-b~ٍ֖F$%>"Je瞓Fl_G *JW"r2?g%eʷ4FL4צ %XW,EE4vo> *՟yL2/!Fgy[}OaN $@Ӝx}HZZV2I2Ξڶqy Ny C%dv6-INk~1^ygF~NZe1B^ A|WnKT0'e߯@JJ /$:;vN.B^ %1ǩٰӪbC4C}}nF7 :-,`)@fSt2@KEq_ ߲C\:cJd­yJN2Fo\PoWķokYP/f}.$ P6mDLL I2a'k:Q?CY!`RLwAfu@`E1x!~O){dO.f%PN&5r BXj&JCQ`{ Xj mJK)f:)X( #mAj:2b!FLјit[l-RϼZ2%;xFS$IrQeՆ%e#"W¥DBD?nAʩKoi$S=JL~ߐ*U}*DsIg{FNПXuh'b) yh2,$>T1Da+"Zr8Կ5zW]v]hWg.AȦD]v -g`/GiRa`1<5D$=AnpCwh?n[UNu X3Ž#pp*$3TbI]='m˱aV뿁r*)+\S~w٘տF<łb* aIqX-%I-8}Ð\AOc-THGHlyOq%^qUA1%&UbGPqrJUB&@ЩHTĆތdؽDvwB !,<#ccmcǐ7q ,fHP,(> H*ȁK[|7SX714nE9u7@3w>B #_{c?Mv^SLG[ݍ&?wH{&O~7vݥd7}ls#9eEE[:K1}O9ľݤ!݊MÔAO*y'ag`( ݗ>Vw,Mul#uoT6p]l/!]ТBCLR2<?*!M 'RpXڥ *6^@6œXv 320e O%X<~y6M([xX `ԕe,j߳v!5;ʪc< zsFĮ^dYgM%y|b/[BKUT\X7aFqrB_ bՔ- 41'_ ʴ$DZС&0E:f{!Df.up`HH(1tj刢gEȠ>"M~lyP/Wi גՈ:w].5 u\t{5[Vɞj+ ^PTPC N?;dOUmfnY/G^KBzMZd`*w{5xգ{$=0 u%-rHe_w+Mh#6nԬ\*J0fenN\׵AWioBPV* %̀)>6 *tTHUE а0]s^U/Qmն^U^bѱ?7\a30~Uft*|"CJ=Ľx.w$Xb{m30ݽ#ƻ@NF % 4,ұ)`HBtn.mJ N>yI,Ιfb^Yd| :`C6"N1|gL)}1Ԕ PUȈAzK jnRak~ZӦݭSBž@ îOG#`ɢn/¦~V("++|s'm@A^zb?~-U5kc6,Mb#.oM]Lw IH%'۩/$gl4ָ%e3c̙=[I@@@@@@@@@@@l[wK?>V KH҅IԻ1^0vDn>/##3ctGs+kn^qJ+ˏ|"'lt P?#?2Q{A.E  JL%4[ g+["3)jpq/8M$c vpp UL@` n!l]:w.sLy9$ʞ~{^*)8ȒwYURTT~X#x̆mUNT̤,으10Tmc`h_BAqISU , .Vv k ϞAff&:S( TDBztMht.. ? ƽ$Mo y)i#{@IDAT.ɦV Ŀ~C`l JSY#t3igƈup2.p`rh !CmGwX| !<]Ű;?*0H%ɽ`~BDd"iͼXrmƌͭq\FQFN\Xç@P4˂h>KG?=,1o\h᠀@uH K{=KL1ڦZխA/(*ĄM0L:@۽y-;:*&F*#|3N_x?6xupB]<&c0705Pkf.tc.&N8$MA~Y8Sn+9r"t܇k@sS];wASAA}|qqnemvJh+lh(/*~]{&Ca2>Q`-޶6.5wB2@th8^Ĉ*-| wVm/-K  Rĉ~`K8QI|dW%1KOMƒ7[\>~$ҳ< 61w`ll#íSGn8m]CNd<mm =j\HzI lmf Ks:t!+e% l![UɛEX_6$ܿCWL?H^| 劉ev`O|jG25<2[ol<Xbl|>x4f rF"p|xQ Ə%/`uI1vFNց[)iiXw".^cyHht݂6ƃ [Q Ye%8N&pi=F.c'.w4`@5ᛦ|=gB~v>`aPPnj?9yyjnLπNỏ?fb,ЩS't[Iübbb`fJ^P+ĤBY?QFvLR0ϰr<&OzhDP9:"+AVF2r9z#3"6@KPXo}e7Lj6m+KqWyO§ 8beg[h)ʉ|]Jh!uň~g<35;2kD>I$ncI[R–þ]89 x9ghĘAΑTCH<#A$"Xn5g*O+_!t6>c:u,qI=<#1-]EDk@iTdq9c`~R@bRmXϽ0{Ub!2'}(67Pm'99:~,91pEv&w,(<{wFm-̥ǵJ[?|B9/y8[qy? Ƶf܈^ZY QvhY&#4cx"bc t~tUgof_OFJc͸elظaaEXFF\[WzoߺE+̇'m0h 6&wm]u~Cono2~=6Ӳ21d7ӱ5:{j}궅Wp:piӺmmg/%ف/'=dY_LD CY5.Mg].ލKGwvPXeݼͨ.eNAb zJ y=m ,qVPbtJ!)Z'$ Zs5yA&Yؿ ;.'B`b5啒po'~}`!P&ʒ1%rPqn )FJl rӧ=x\(/ё\j s.0Ҍ0>IQ[ʋ;ȥ+ƮhFD G`OkK\-}4Fɕ޽wpjT@RmL☩y5*7ՐH#IWsW D򮮡Jm0mv_BqNW{UDfK3Vֿ|'qyG]"eh7&KP;rDUdVXl/LMG-/_ zEu* ꩼ:-d2%1u!O{G80_r|eK^ǹ%J`j &eC"!Jr fr/g$LLY[ڢȦ@Yhd8O hj X-\3}?ڷ`o BIH~7zV>R5*t6(6JAiþ5|2_̯nBIz<+aqA|"2P @#ekS(5?-p{pHb *KF_=ZٖFU쵐#0K{b/19PQ':ű o'g`#HJlt%Mvα8ڃv3rSw|l̏ES=eggKHHLĕ7"` zv }}="ۯĈĝv3gy ǡ$ Woc̢u|2"! T}U*y۶xN8E$q}~h}|tdDQCuZCF q{̳+?3M>4{wᒈ5k.M ]8M/ l2x zs 藕olD ݦDYdP ֛%rQUD1r /."I@@@@@@@@z`QBjme]N?+(D.Y){79߾;OWiB!rMP)H͇_SQ$H,q]t0EGS=mVULZ2:ȻI<jhMZ="ď M &8<ӫ'T ]ˆovsP_SKNn}*>2"ă&9޷q$?v [j'O~ʮDv+ŝJbJ$(*: Q|]L?ɴdGqEvϣ&oꉉ|"QG]ecӯ'޽$:NY~0mρ,Q!Y)9y"|FdJ'xO\`zΥj+Ob##ޗztsW৶z˾CVV7sN; "3I{OF3 gjG,WD+ik 3 -Y?Gx'(/ ɃCKcyp2=SaԆҫ[DCȦr9w*/+AΝ0K?Cr;,xSI>g+!}qNC2{vq؍k M𦂝0NƊ@^D %rC[~(5֡ M.FڥD$:3: iwEy퉀\:DP/qeI~χO-p{QkLrUF8^(Xaxٷ mމ[Ƹ(T(Igb?99L0ƈ?+{ 9֩#ƎCN Ek It~TW}k~\bҿ4q+Cߟ͚TI6 BW[]]^u*11 ֮EXSIŬpq{l܎b"Hi4OU+ 4RӰ}^?I&n  c# WW[ xFrF:umy6t]N.ppcgd`moX^Qd(P.ej1hbSE˾XJ<˜MFkiysg.Ύ="*̫ ۭ$ dS%H.Aܨs=Iypz̴d8L*):4sBb8%E/d dC/Jb:2rgI?WG*!!^饿Ԑ/7W r2B>Lӛfk=T)"q4 }ŧ\D@eJj̉'W" ՙ*Ob6zؕHwELfHtFxdp=''AȧyQ*O>uOjº %ɼ {k?|4&5vNg?Sx!rDG F)&,/̼vK1 >qӄdd^~=y7~GNxgaEb2**PVaker %5a(~e'P(}̛;*+^&?#)Fxړ~ve ; 8N4e$dGtL3rg vl:t66سv/8?{_l6l@Ūy&Wh׶mm H={t)*2>͗Vi-IDDZ4)&R-4Uac~&|#&ĺQfCȦJ/p!PnԚ^ O q){hMEQP4,LNE?D5SߥNJJ/,x M fPt=b~ +,=aw\Z!AIcŐ p6m ;/C@]YCZe93&oD$ %HdF>1'W.ç@iO4IWU1;y'<VĈ7I^OZzH&ieCھgnƜdڹo:3)) .^gPUUŐa`~$zRT|*ʮPJ/jfDځ\UcwR DDDr9s29=Yz& 45abl`R'4v&]{dDDUNxw@~͛r 'Z AȠRj!Ñ-LgGƣyY ++P{] '-v]1~0(TyRjQ8V32N$o|aJ8zȥ7;;+cN/O6ko3w0V<^ n q<< chϜUTgԌʧ#gxHA/}Q$ L(hiR ?gs^{Zi y* e_ 6*ʍZ[ɋ}E_}ȩ* s- "^6B,?b>UuTG@@@@@e߲GK\ptdE30_9?WaίK=v*7Zʜ5մЎ@(I4OD@$^tD (yTu6BsN>1Q_ aI$+~\~/,$6&cNj?ƃ@yɃ$2 %=cĪx;m{.?<zx9&㐄=#,~ oW)鋯惑e 4ѪI>/+hfUb0%v^6ٶױO哏/Ξ;[ZM$Rgww >CG ݻMg:|XTe8bSReFTy`D{B&+J**ht}8BZ"!Q#w&"8p5!+/QG߰y=SDՋnʆ5QY>ɖÊW-Ȟ%ΝÝ{w3 ]۹K06}HĻW"wʄá_%^ oq:+Wʳɜd():IOA$_,$QSINZ$g@$>~O#`:F_2!<1z:﹘Y7"58AQ|0&'ıOS[lRPni>q݊иh>ѓ_?"`ԪU]"%I1D2nz!:y)фhyB: j\$کrQcli=>4VFHrg{;;z^7U"y9g/dyp ay=^ 99ɬ#zt!K4u9zT"eGn Zu<Ÿ>E```225իMUaBfCD>/[zE>HEry5Č=^sgW#RouP4䓚9~sdX */ص_sy&`ް^V˖!+;3&P^g_]bD$괼Z=lRNHJyRE!ᐃ%=--M%UkISTy-% y-_')>%F0zȦz\lJdOd:<~4{N<Jׅ2؄=Lb'hͿ-`>M:PT 燝$?-ͬXnXLÝk_}>Qh|C I"$ƈ@:YƥIk̑x'Ĉ(m,%?"oʪz"/~ѹºq#K3CN>uul3= JEaeb,96 a!͉y?{ܾC$$&8|caI1j;L/?uu{Ko#=#}dA0D =T )!\['1iiiiS't:\U4!bDOAAzqżJ*FluڞSH{fڧ;-;?yU=z`$?/JDRh@KKK7%||Oq ߹I^{WB9cJÔdJ! . 9^xSJ$z dQGi AVd4MeI&53Pkn5 "- Bvĝka) dzoteU(oikiԴ}lӢ+͟qyR.jli۪B J xl+Rf1MU$Cs.z$Xco2ξ7ؚ/#}lWD6Â6s %/ /QلeѳH{T]}ˤ#Z9Nт^MIf&&$Q0WQ;#`͹C܋y31&! 45IPɯd )iOq?"ܢV Q#/l? +6}bxbOɭEkrsR{h)HoQ@љQ0gȑKcIy4yY=v{oZN1~z?/Jˀc =%+3%!3/1/s-&IW9< Y ZLn՚ ==]̛;N7XddAVIZ Ca{G o+KK$խKW*ț]eym _␗7'DɋAؾMS,L`x'7\UHRgt鑬[eK 5g${|Yy1߅ S#`vE/~;aΈqrǥPc}vt,2F"3<QGOʴS^FD1/DB]URϳ(Q<~TTD{~q&ړ4^Wթ-J䞝L/,KINŜsנH䚲=Ţ'/]A1c$laq|a&CIO!2TJzZ-R肑 wp)H&A@Ÿ$RIc[*CrҐ*lbN+†}1sd7: lz7ƛ$~E="ݻ'`V!⇅>R zm>p dF$ ڮOx2"I~ހd(a1FUZy*;AѼv'*mrIC[xXA6X 7.bP49 ?h 7;)avaqƑf$vi<2*E@|b{7}H$N>ODFIs*~Vʃ;G{vR!jhI汊=8Sπy0#W/!ү'4lB|,&\Y"CȻP$.y=mЄqx$Y"CR7\ Ann.ŹWsvI%u;| $ *ƆpLn3C(dee!3+}m{gwJ:q$'*t`xwoCW^%8.bUy0fkk cJrBO"Ǯ,,4cbیbZِJ6mՑ7B(\xyeyY7-{՞$dM1zd>/L$o{TW&[HD#Xʧ[ۡir Q+S=cnѽ|]dddC,i{5[%dSl2^\g:8{MT@{)j&Ob&DILFK, ;wxǶݙxsCmF߮/|16s/`Hp8=5:O3 Q"n&9yy6G@z(N xő?1":' Ey8jXFj`H@ˮ4+,SL\I>(T%n>F&XT CʔcYOx fV7Kg>{-d_9c.:Z{>H4I1=u555ˆAd#.Lx7+p ̭Lv{C7{g|䖳%B'eQF?ֱ6F8]ؼ:쥁G#<1tx1&r?0`ZI5HTLVCI|5G#PWr*,#j0'g}eQ$e?& >J\<]xxϴn{Ox0nI]DeUT".z}j~.`")# ؀} 9VOK_,9?.'0y!3ߐi'^Dab22) N&" )cdX,ygh(CKFEI)(NIhoP⟌KxܻUmQd ROF_FrTlH.l' >14L}X? % Ln$|Aγ)*A2H\\> q%DI ʶL___ 9C=B>L9GF|&ڍ$hhb0k&H0[߽#d6?Xswlď'vC,sNm"yEAet %D~p44s)@!EٖgG\`x}̾ gO(7@Suu cJK^H)'D8h頻ԍXP}QLӲ0iB\~Tn=);o+IRS]IH;ƼGMbFx濁m۾qBcԛOE{dž8XmL0U "HKf]U,+mIa)2s7baoѤaY%$+KUfL0UKwo+>^!݅"3BˆrߨqSq45[ h"EI7CЎ29K{Ukf-UX܄M_+6b+ol%N652tlzJK_`3!omqߟs++QJá?+,$+Wݝ<ܪ`p85"@41"_kHoخ_N>ƴ56$aE9y~[ wgpD0:]#=t$ꨓz6^ڃaYt@YP:{#:$ W|+2_|l&#jwVmoܺ{C:ww߇ )Gew@ddd+]07`QM&K}:ŃEatIQ2DǕRޫá@mWSbbcrHfK;;v$ВG(7y$l7|Wu5A$H)=T9%iIZoӀL r+vv8y61?.}2]#GbM*2x aȲiPCRr 'SUcg)#tu(J|ʼDTUi{^f7LfEDFy"WDĭ*}ZBddf⻍!jپ3VJhn\"2FB4_vd4rbLqFOx"ɧ|(BoEPG( ;kȑGg-<ɦhyF@ ՕʱwixwK#xt\t >HV(!{{{t .ε>/pZ x4uwsgH݈b_Y[}ci-7'oT#P+<q?.M_XqDh!H.7ma8{聆f|1䓜ܙ#uBr$Gտ__L&o-R_בOJVe|=O >!bB %D~%(!QD*Ub ; `mo#iQq֔.yK Y%'_OnCDp]R6xHqUV_"I}طm+Z%1%)l)rVH|K m "J0v~xyEp? `b2tM<{$1## Bg[ 'xY7A^WnT0"5%fPVMY&WS(hjO*euG#I^9jZUXIxި"ҹg-5u9~ QRRxX1\v$svջxfS\sPN6q"4U0Ƀڌ7-)Baֆ8NT|G#hyž0zliA!d%_Λ&Ɂq\{7ojSV#xd( >|bO^)K@px(Lafm\*O} {߂MLajRE+tu?8+2ߞB)uzLv!#puEقdԉ_CP1mLۂm,&/؁ú=~j8pj |%nGAd0T|܂/ 6԰PJ㹔!2X&d>#(%dD%"2XV-4젠.*Bm`$8W7{{ vK֒K{{t>$iʣ2,!9= ]@hJBbPH(^1 VdkN/7 ' fzN6߅+.-S-]L>o;ǣÝz;wcR-JX]Ya!-7:$gIvO[1ჭZ GI 'FE%TM F2ʸFSLLBT~W,(I=RS eNɱA:4tB"A[bVړcĽ ; >0n,R/Qjwe;pYaѣ0u$v&X\IUȈ*"H֋M{M8N~2,x̮Z/B:.˚R0ևL|lqcj\FGpD#(&o699IB}@>VEX\x $CI>d).o3?]l}?{T$.N棆|@4: z/]E"u튮]VLތ '{csxH'YMuV['w UWz(*D GqϸͭRj5*T` *NJ@ tD{)Wˬ%%d z]:A&gG*K2(ĴLLJilY)󢀂@IDAT|Vg#֏pO?g6= 5dSA_TuaӵLK/In} pdzPe~$S %u.LxtdK_p8RgI_A~G󠯧'ԸF2f_mH9jˁ]s.#G#PKzDP{Qed6d|_GKE vAY^21kVYDAi)L:6f߼. K%ֳ#Km̧[}p QyhC.2YҦ PS Ȓ-OyO;[rTPHU2l}+&BJ+C*>Ž].S&NDns/zݏIY>ojӗ re/zYFL/mx=#|ҁ!.C,dj&WL݇"cCUj.8B)'%)BLvNuըHP1ryCl(=ʊ244DGg\q׷%6Ptݽa^j % Q/ e&IwoCSsz,~CBp:z8x-} @Ѝ]LK]\H/odXx$XSɩƲى3T);@ HAzA14䰢-s2Ô>\Sj\ϳj ONG|jyfHJ)_N@32Y>e쪡&th0>yN[C DsϦj+N6UalG|,{]Ana[ѢrlOo(Y[@.]1IP4Ոpr;lXݻ<8@sBul۱]άhGu,n?@P Mۜp?yťPED6Ĥ@{ D:`<=|j{QGm L0ID [u 答vAOMƦ0Pׂ. iv`O~aB [$|AEP(,EU3;x _uU-^߀ "˒GҝHݫr9kyTE掑J#d]K]L&U%tS?~*q,/7?Eb[@B4>ڻ^ 4SFiêaFp ^8BPLxL"xR{Fw=W&_L{վ#}+نrZ *ZL$g[@ra!:7ՔI{JdRƕ#E^R Hd w}WY,eV#M T|~]Ҳ՝yA%gE%$K83SĴ?&PĤDXJ\uF61@&OgSqt$rI7{vt^F.F"eEwwA/?tK_+y8րoN25G)&C[sWn3`Cy#`/[aKR6#R0R;AY}xp8#_O߻$!/Ĝ||ѼYYiG9Ec$~8Z.|]qļR44bruf ʹ-Z7E)׊rˆ2Ĉ#^ן>w /A=+e3Qg6]za NGO7BpȷDqR@gG ;;Ggp+l0~ʲwb"@O)+WCLG%K |_AխPЀKGȨ*C>F'IҚe dT!N"SX׆::Sr=, k* ŧM 3SLNVVELgÿ 9PʅR^!| E|n J| ` wO?qp/vxY2 dc"٦/ /i&:MgW.yeGFC$'HrNT,7P&WӞ*QIw!pn.#)Ts֒  DpJ KbH /g*A2I HN[#R%ȤgmsZz,wrMɦF=WѰ|t!5`xTˡ5w#b> Oqf| E?R)7ЧXÃ#="'T\ ǝ0_E$@I 9 =#^4j\U:jF}ų}pNqUCtrź#kZ?rAlzkL7bđ>8^$b#2n ;}-")*- ~dOnidsm}aN|o`Ѯ?ŭX{puD%ltE3}̖: f(dB*}-eL~8 $uTzeƎe}H.6?t`5j=^Z 5=iS9kj H*NBV.dr}DRD K$dPH(Ê"%5qҨopp4tTxd\Qqx݁?5xY4t- Ch|bĖeiUGFoM)dVNlDbHJ.fn mgA9BˊRTTb_spا”}_# Mrc,S֭/$_ J?~E4j<DGNpҤE8u'Y&RvXŦ El#A_Te*3{Gs ʎdY1 hPDI۱ $6J4IWD.qmI$_PhjXf*V{OVi[c/pofMM{|com#҃Y+)c2u2=F$9e;+1RuPU `<8!uҿv:ټL=q%y.AXM4/OGԪ$ɦz"PB#L'gOW;1HJG|-GT ]AI #t;V\͗wX㸹Gd+'L lƥ$ >V|Ųnރ߈+Z$Vݹ..5,8xwVCϤ53oX|;8=Y>|zN7RȈ zc͵-ޤ7"6) yCRv9D )Ki}- ĖOvsIriQ!A~5y$I><l}а'maGg.]5![#ę]S}kap8K2L#+?O0y;+t2z#(=,M}dH %0T:c^7oGq(";!ʋR#8hF4j@Jb*i# %t2`Tc*jHĶ|XN$U## $$qFGpe_pƈ cLO'*0"Mhm}|mNDDRy>u iߋY'GD@YY?:V ycXƌ7!4bt@y\ ںqHQŇ%{WCN ykȹH J(!R:K)H- uzEF]'L+7t:^r/6=UH윿DuDDU$InX舑x _7MJF4݋ F^Q$Q#n``Yl(sMOlK[1_ -< o6VVujnhX@4eq|Xp9 :deHn$tCȑQc#2_G~D LIR\5e4fjs'agPRT10Q%Izr>4'IAҒ d(Bo@rA%?m잲*Yl]P,ٷ;501"U0r+8`W#)p)C6^2L$٠Zބ>eWS%mI.d)]RܼyKD!=-BE%:eSf3;3k(^={V֘ !{>r<$pgȳbRŔA$e3  w[ΨjWOM'2ا6HL오LMPR8 'dRC%=>MMZ9w_ZnT)IjvY=nK` اDH9DF4*Ӈ7S#AOir)u2'Zhq-2|8!59y=%$)uS7!j$xRP$95ѯuRMrI[4dTK?O|Gj:jS^FzXs>= LbXc*nLٳ8t(wn]=ԩ00n@eI8:ÂCFx6i#F\XOV\r Vg}?Cme`M:/QF},gܯ@0-;VXbV%Y$ dY1;Ra}UB@,( f}zMD g|:{f\WcȑЯxOI /g8 L>Ɍ,b" 0aQFJɢ .pzt@E =` e#5+IPH*ՆLRUV$<$F&iOL2ՄIXxs5s -7j5U㫪Ay$XFn stClt4")]]xyk}JDU*8s겎_~[Ԉ(K=8~[9GᛛT2ߔ-4_7|n#37FhgA 64Fw9&F1p넋·R3oW<=7[x'MehS?#%aR},XSGb[s^ELd^9z2h &MUcSS3 N9+:)fϒtRJ"D f+˿]sjFԕKg~o]jzN">w^BL$>X#0R7Vz|čLDh!qcƠCT_@PE~JQHMsM1vK@4`Y6>9dycӣٿvUe惸vW_,<9=KL&ŧK݉H M]v"$єJ D=҇ɦ_VYRZnV 4|#Ngq|5زjNGTwH;KkYMg=e҃ӒvlG[KLG!,lm;AIpGFzٌ)7RE O%l?A{XDk3rߒkٝYvǫѢ2-aQD#>w$[uX,m.<3r?J4ZAG8ݠ\_O9#`|)"o@;4$:DIXArS0k;t0(:g8#NcL:U )^˰3&/`{dЏI38ٿo -QSSnGҊxmd"Fgc؁xg'JY3en>4AVBN`"B_Ze05G|܉@;Z1P/$ʦ*O,J>5ԅ~|a4_}{9Ouzg&$f6~1Y I%2(L$'d 22Od"i;OLb|ϳ 6idS/]y\Y= ݇\9ߏ:ه#6Biީ(+,9U׀*rsBZX w9'Hgrm>"k2@x[cdXwE]T@"F^?xzCwa䒯TWL 4 *NhGU&pj L=\oSn*5$b<&XwHgoWg$_j\/5y(ߜi=5^!W. DP&cn ~bF@D6JҀR G\Ҭ~8koBhЉG]0|0(w〧]KƔ2"""Hz|;o`ʀR?u/yו@@Ο΁k)3<^/v"/AQMlj2*LCBZr [w⡷7zxlͷD J˾0e՗( 9#&i /_S=A  YGRC֖L!z%"DS&҅ok8rmnH"F܈%oPŊv+T"0z<\+OM{RLʡHشY#Xs4T`;5ϜN7#PK׀-%4 0 mLb/wK{0Һn1h#i>6tNi#":Tu;Qed<8*᢫GʆZX 8  TbQV\/ںѨrwNX7\,0%[`WD].WY(O LG4:Kqˆ:A,\wQ*'9y ܽȨdggx---Aˣ;[P{2*_)ӱܿε?H )ً1PVa8 ݩԺu߁8o?lbS_t(s(i cc-d*#D&MĤ /&&:fcL/>"|1-|9-(_\p8{5HeU/ &YRFƁ=+Xf#Xvˀ2(g'G!=pIzIDd2H|,TQܼJ1vRp5%(hb(*! _&{JqTU0̣^qOֲG^˙($==QQ?}@/O//ttq pZG>)WoB6'i٨T7~PW`>2*l0^uk-/>KfhЀ^p/>\x)IDXQտ{}^S4R%}o {4N(餃C;T/p8-n\m.yoMEر'Q,4߆EL`zUH[;x^?=u ~@˻BM^:!{I ><lj~׬UyMjJ42VO9Y̦frG\ Þ0eh(+) ٻ}*F)+(V0HV@]?2\5DBI G#|`#q eֹ=bJ/5umMd=p$'w3+O$ɤ(wL%_t.TW#XV H9 ;|6z|hZr 7i# }oPMyY9t6mt/^¦͛I A̞9 F@I1);4GYaD0zJ0RA+km2Y)!DuG`j: |=^?qp nFߘj'/ÛX)+c[K Mgo=DZVI}h3*Ѭ8Ԭ.WlMM2d[ZXP񤬆dXx4?j]_Saz[,.ByH@SHO~f/Gy PFm*dE Fcv]%6(tn !`?q D5h^$> @sP(zW Q`䈶'C^Myk5FhhMSLłAxL٬b0ßzн-Gb O9"ǥbgv!I:fa}tUEE# u {/Vc<&s$ؑO"&&$7nh{J{8h>xZ\ȑÜېQh,Qo6b 2qy_Bn'b;2Xu`+V: 5l l;u7|H&ԍ)K'w ǯz_0ènr6rU\H$7+u4:nMB hJrC"q4d#.큒J&HrʕvW]gfsVxPTo#Pwzf]Bn!{x0+T#/JqiB32|M^5P|c0rjWڪ@^WaW<㣱/?_# _˭O*7W ;Xb~wGt2nZSp^\DD@] ~7NT@|48@^|"|+nc eøxyfF )DȩlX븼@.jzNS7ᗣ '.ǠNRӢ!yJLKوVI4737|dT/75%'H"ɦŗaWvłsɳy5Oųog`>d9PD-nd'}_ "ƸT]VTFī|_h0 i(.] Zԉ̓#h\.\GȿqIiNn2M]i]]Z<-73#n> !VC8'e"5u;a3\".VXVhXvŰxAb$JefC{m1  Ń#\{j 9BGK&\ oV"qL}K4I3Cqs &Y}(ǖ͝~W ױO|6II'CYQ=+/EtO1?%wBGL{9aREX:FYJ/Eޱؾ$^'  N6l[[u8, s5% `VW\87BSYCڻϓ䞡0|!3rH~%mMx$FY_#x|ߥCBBI&e(6/e#) VQ?+iLnPx/K6vcU.}27{Lϥ lxS>Jvx@_ d!yB9'eAY!ύh&eKN4-RK6KɫYp%q7<⭗?Y>m%ULGH>?l0"Ǒ|0)Бg$&&Am:8KE30<^e<mS@A3]8ueY::e$dbEO϶kT}WAau<{ OI6[#q#BK~Cֿ }ʇ`5Y-uQ!D,H#l&Z/W?š@O+YQZs#qA$9P1mȼ`0cx]ՙ"־!°=:utkjW?_46%AIxL{^sS8x]4jM:{a|qx I :@c_>_ ^ ?w酑e_/o(t̊ڥE=xfχNDv^&YUS$jˡ&{P>|}#@=dдIε| Eı`T2k7e^ie3~^^7k$d/R]IC+44nBj>Lj*x}h/ tw, k~C!ɦBenT慰/E<ь|a4`GW1gfZzˀb#B[S!:̠i1e&,^%4("CF!9̣Z 㤛Ə3g&x[9(%B)M$O 2me Qa!2F DPA~/&=EhV=>Ȱ[fgi;Ըoh:LގE-/\|uRfGj+A,#WC0D'y!DN KcChRWmS@`jo܆xc% :% `8s!GFrPS~g]Jx>l'xQr p^og5!/]mRRV>"Ǽz J*Ͷm/[񃇏܅|Lix>}m* 5.qj|;^>eOH5LOM,n9s0neN!B]ax 9z@4SCʄ'/(? XȔnjG.%/Q u%r 9&W5_`1}xpay'c8vܞQWu0S>2>ǐӒq;1 w!$1q2$mGr2B'*>lM0K/>Azk"F0#S "O2T6'QȍIxSݽȃm":&r}rҪq! prZ6:0E{]|Ab3& =-F?#А}ui='V+,ې7겻a?#u2EGFѺ`zgɌ]ݻ vG5ycz%CꏨlJ>UU94b߳R O$@KA ?8@Ⱥ G`ԇhͯ dZ6-`b- yx ԁ>  ZzH"dƟWXՔਣz\NM*S2J'Zĭ"J^e0VWƴ6BF\%W^tQmmã]Yy&@ Q^;SND&3&CNU1.MP~Q-3DWÃ(uaX5̙n||fRdZF2ytr1Op/1l_a( cyL*okMNo ;3F?ID!'V+,ې7*jZ[bdi="&BҚgcp|N?n2mi^$C@TY!` g@Z.0 LMM\e^2.,ޱzJc+U??Bg`:ݤ(^n37B0sB8Zؾb̺D6䨎e=mz#dB1?( W\*4<⨇# 5%FՋuH\S6jBɼn|#P_d]>a2@IDATN ;h e9fA6u*~@#!)<%TƲDMD# Q\_q8OM^o^ܴg. d޳#)cR`GEo ۵Eod`o"^T<9Rʪ: cF?̷p4Hw̓H,FL%{P{paX[7kѠ'Pom--ï Bl ZlcܨLeo v#^X'3j^WOӃ0ȡ 7© Lt[\;|ًȏODVh^de!CBF)|Ĵ5=1t/uГYI&uej"]G6{Wdc j9Kr3I0с>5](鷜ס%,iř=X||0`ZA::L3O=nor[Rw% ozd{rxBf<%k#/^c GulugkV#YA`XB7CKeÅ9\öxhɮk 0m$u uGQCz Z!z(v}v}oy>S4$B IH{Yvn~?ǝ3s3Cv{g4|+(w3_'8"?Ka"!m{Pay)*ju rη~;2}'EM lz0&n1|gn]ɦxomYy۬V6_9xoYoػ /*lsl[_X9ȋp ??8:8[[lJp%A}^)1nлɨYfi?٥ITݟ0VSΜ;Q6IO~]9r+kR*={9ib?g0%d OmH&vh7^S Uwyy?x qBΧ݇t2dCEJb%'"AnHsSz~$;=6:ՠD!E*&5,z;Su'4vd &yᇉJ-).UZ~Fz7>N׸T8p:Z[EM!#HS!_~{zr VdӭۄA3[:R5ucCX;Z6xx14 Z yxmuT_IBe %K=ۿӺQ? N'6v _ =[r:tRU^C'PH[ݗlYMyy4 x{{FFk] ;WC?kmd_y S}״wϦE0 {aV">ZlҽшC*XgǸ)t?̲oJa^ מOƑT7Z[HT6. a55ش̜ݛ<-ʢ=)I$X44FqI L~z֘`[DV wBSGKX)?(^Dҳ[^t[#\8}Gfa@8e!$ ^ښlݧc{YTVB~ϧ)c`N:<8AMAFe ޢYGx%Njbm!P0"ĝÇ2g]A8aIR: GIB2L}aOM_ >xV{13UӠ }71(L Κ"/l_݉龁dehS?)ɩä/ 7̧g %; 6贍 aDflM0!$Imr|/&8'DVs?EB (vv1#/%q9^']؋W+ܶ#?z;VWYߞ݆i55umw(CPz1lOj;)0130_~îl.Mx0BbvvI|@+2ϕM. ܨ]s˰r&R:zgdO҉85զ<8w@͠x>763cvHL ǃ\T%"E]CCuhnmm'RK#!x4LiS `ynF#sf$`OQCcwQX|9muOxd̴~k#(]ft0,94rdAy$ĖskB.JZ S}q[O[U¿p PNYN 2LC~gy {AUr^P)eo"4 KU(%R[YToBflK1ЃSؗyᅣr5??ohP;L82$je'k <:w"{pNsת_!U"l/& +jM an|#.%xOVTi_z)=FF}n@^GqCC* =pN)'vMA>lFGC$,4eGO""\ Ӗ} i -#1#U^/$㻳WQX-YjGp6U(܂m$ ;s"ِ).b̎/h(0{yʫS=&j<BGKSa^iy9x=tj~phӪpVL6Zǁ%_kyBŷ嵔軺Jv]8"C1fힲ}8Ј"H.Έ&uDYY_`γ0<,tp>?s'CÄm"B9quZȥՖ3& ǡiI\,#XW3ը16::CPK1<=_~ځrʵ`e)7D}`'?sudj&:f1:ϏO{6G_"PK9}C.agi tb30w~X;t*= 41{;}utXXu,OK@bifzn=CS%ӳ=+,΢jsʈ,sc>D,L_h3#XS9 'ȺfKc,S+l)U[tKoSim=6\J\+<Pe.xv' M}W@YM^[, vl垷xi p3azc<&?7^UK+{T7Hao(D4HIԓI7p6v#s&`k_5q*.ZʦWOOp'PVs2$+9?fdvPhB˕#1HasfrNa8GJsaeUOݽCE4tiPmikcxi *t{eT4>曳aرM)mAV'r|YuaZ Qe;["=N>\LGP>|D6>LD<}ҼKw|<vyd'$+Cj|1_(E)9+"&f َd{(o,w[<^H-3űh0;,ixã⍙KE `ҁϏ `|D̫/&@RB^Rŧp7"r&߲%=s;WRYsd& &%+ d|⊫%)Ћyuo_56E}˽aihm}ҌLd^TP5 )̇ 4alc k[;1)eҡ70q'tS:̢$7ȶPc61}/}RS}ڙ5,o{L %KdWMLL͑YYx~| Oϰi Xn`p疝n4rhq@^$u#ߜcm^p KGNlr!>Yncopxf61=8ehhk`z[>uQwx5jqBŢc=-9G7W~,4!»I'(O=8p>rI,Mm焓qd9})cnRs]h@_#nuUhPIJ(Tf:sk[ŷy\-ۗ%iCO5TUUAiuX;N6@Gsm jAM|2JX*`XXPRRF蛛I||_Ikh,-pO<6ᜨh{~x/ ~]|p_87llM9WTc }ٶ^Fo#*N,],iqTؘY:GTLBm@962&JˍqTg,fJp&ڛvy ~8$|q4=MʎV ER+Gh$o s`w&%~E,ϛ?V6:I94Ϊ:;zw.=ed -*?xM`TRA,PfaGG@>A“[ .} L €~p=&ZgV_M-|G(kąrLvPdZxv:dgL{&")u-5M/) _A%Nv,8٪p!y{jI /XB3?=]XFTTTP6'54a扣 T,1eDᝡ'WwCtuVxxxxޑ[[KWS sMMuRtE4 '+2KO;TɊe M*rV3rV)<:{-}/& eEhjaӝ buÖ/eJ%ZAVVFAz,(ۃC?}dg`a`uP t=\=Oz 0m Vk됳y7N_UX/ 5-%5(?Ex(\,?횔5z/^l}|Q$0@7[E:T<P.GAnЦ']^&C@,7A"Za?|'>YaE/]-l`G3߿ N!%?9&)n4n&QeΤɧgUu=2K`,pz\aHEɷ= )ȧ R:ۢBP0f6<u BN'v_*tZyQh-@ wii/ޙ0hP%viޚUBi٨/23COD3UW{m9ͯ@#Y?uM>~^8[ ]M v;G޷zf?y ;RyWx( /0٣O$. y2`qZjmfcY X+9i/2ɦ;bt?ܨb#zt4| $όxTM5Al5Rh I3 uB7 2NJIs vo^B=v Y!ET3=W {Nj5^B3=k25kkG?(%<q]Y#9(2ƪU`Hm #<@m*{F9[ [?=&/¼^ĩhc+]^>U,jg켄IdKT_>uxg5FBA`'Z!V8fGXg!Vk TN<#Br|2O@ MJ6 -}4ޜlG iXq;O#&뚬ٌhzm}X5AYet1c~z_+GcSHٯjɾ`(*:vM .q_#`idstS_ snl:qy#{xT<tbDYBSCDjp ;@E_{mSLŔNYYd×3s3+W0}4kFHL޿'[ӡ:+STip9 lH8&&&-f$B}DRITG9! - +% V‚[LTb'Qe&o-7~ aPdR&8lbe`j䀅nݣriuBȦk'a T 1!p1|Ց ؑTʟAq IH5i@xp,vp:@javEG yN&O9E3?4!w}Cq(qsޘGCy+DG[u6[gSPlJ~L]@A]Q=~oȥ35U_ 9y$2Q!ОM_'jlX9ԕW%Uв?fa\rȂJ0}F@lbPG#dkPOyQ,Bl((.gaO+#VUUO(aV#*)e@RՈB%}Б<)BӨ1gowzJw%:Χ')*jZ>oh;Lc#[y+lbD;"3}Cd) IߙK\ \Mwim [1NvpD@AEMkyVxF#;g#u%5<) 5o+t('|?"rDo3ly?r?{[u!:Ir43C#(K{צ,$pr"k8X]soחyMP1m?} e%Bsh)]bROsIe2r$ ޖ>62ASQv=8|@US|*r5/O0"`Ԑ)Ȧso|pŌ YrV0o-  (yLqň*g ǰB9IZ%%%gr>f ɫD/dʹInMxaf$%E>xMoԒS:لކm)ӇDIFSBd!JBSvh7^S U]}lbbqNyV^S)!FkcfǬy&e\(&(~ kQXӀ"KhnTbK5TS fxl;I,AUŨ%'TUFT%(؁L$Eَ#qp2ԁY9?ԙG@Ehyח"B/͖, EC?{8 Nc?ƃ-&/X -ߓp"2B-=*Y?z4fϜЧ(`9IF U&\¯GZF%Uq.l7B9+xk'Ñ`Dm$GL xlaQC*Mwayнe ŕ*,9x]f'~瘲 mc/}X9@A9.!R~P7M/}ڍ2dzHbS'GU*b1tY\,p+I(v]c S TcV_[)2+71fNJ ֌,ߙ&Hο*2ޥxg EUdt qDV" e½ƔSLA61kb21ަzpTQcw@o"*N;O {+F6VjrxOTHY7T+7o^8,7~@+ߚ:|䆧h,'r6=x$*DRcVyLeM+,/^o~rx!~t# *Q^X2~: kR,cl}ܫ-ˍګ tə _j=>灙N᫋wA;,UJ6/$eX`7>1c׊lGfvŏaֽkCm=l1֙l'%4WJ~6r :菅֍pIF7ăf*|8 !PF<0r~TQݵ\Ժ,#%/>AI #>yCx{Z{%x9#v/1ZNSAdlk ffܳG3KH V# ɢYI-~kcCDNYb{ö:j"YD )$XHQ:=?]HƏP\S/>N+p4VTFy¢rC^DM#!&P&*ؽ'f7AѮ,%%JV:N%x[=L[;7X4!? IV326,r65"G/ o7P[T 3}ߔ!y>!@z^V̙/G#s 1{󸖟~UL\Kƺ;7b*g&H&/;bddF5ن?^ZC$n5G.F_D bX+b6Nxmڽ q) B9+0 }h6)Jz;Xᅴ,YEiple Yj0uH%D~钕:t6 Ri+˽vs bp: R@|ؐZf,Y̢pPԶD:)8_Py:Rb©# `!dڛSb-iG®kc˕t~"Y33qZNfa1+\,J|8*fM҈)=7N%y{;M2y$(ږ~1ȏJbp,ab!Ӧkh  / #<=+ J vs^$+P +D<9< 凮v1 YRD9B#Ї`S49A3 wTݒ#9:Zd][)ۮw55h߇?r8I3ˆȢD_䦨\r $n\}n[,H$4`OVrSL7UbJDzĞƐ?hi"B2У!dbMZ8qEzy}#iF~? nGMN;v5/ta| +;d#_@)-B-zT3I$,cp;;.H싸hjcnp M =հ{KOż_BqE9 d<݃M' X#٘xi,Z- sIw$UDXS؏GdIt/No-X8.C@J6 UߌzM5TKf8eP8G":2Lr.UdFֲ, :PN WSȫam6~XH 5'5%H޶N?7þ,|}*BS%` R{{BO[p`{-I!6jŐ زsފL4Hmßrn LnݛyuO@W#P[QSRx*3KeP'4Ǽ71j`,+Cvh?H$䓽=F!>~/D`U y!C}`X\і@UX2<:]r`cc}8I>IK#R0Ln6݄._,clK7+ˍ7ѽ}X".gⷫ9ΘH>{(1y|PlaQC’#cƒ#[07N' Uz]G!0aa\i !y"" ){njrTGG4R^ϔ1i+%{{?5"SCs3I)d!֦ĞiaW%Jo'B)ϳyX<4ߴdw^ ?M;Ki鞡pT̓wW<EfzL/,nLkŧbþȓ jߧQWhL >'bSvl/<~Y+PzʐQX2~fYe MbE&ܨ"Wˆ&F81P ;^i ?)G#d\ѶPDzE-eTdn)1|V&^"ReSjI%2[Ml~[ QDc'1G= 3;Z轎15I>1Vh:S]"HR? *Pb<8&<%F.MG%A$:˻3CȽdzLubޡ9WY+FS~F*甡"0ՍMOޙN\(m&8'+rŸ}- Ct 17s'b@^OOP<=^|г8, Vb '|]-̲U\,clRۥ)ߙ1|`Ѷu'׌fbp8@W #@teIt(?X+uŹxGnXvҢ*HG#ls)x.)Mr;()0-`ևM0l t< |O#PBH3C1 yoR)u5^ʉ%RzF 4⼓ž(숎P7:^jPKrf“(luÖSCi9)́ȔL P%Ux{zx`z0&z=@Ew)xm(,/a}HPWb S5y`sŒ@IDAT8}PdWmCf8  u0v3RG#HÓMt;p! \7&2Ƀ#F,ɇPV.F^ HNH2!‰-,jol 5A.(vY}}&A؏h`GKLwVeR61T 5%ܥmiSolhiGq`mjޣmO'ʦt;Whz;d[r>%r,&J<-KJyx3R`G#.ߒm+-|6|G# wb'YjY;dS{{j :/ORI%ɑ/O>pjO~01S .h00>`E߾yC`.M MHJȥO.O^!vP!ȷ@BZຢ(1jtB;L13G陊 )YgJt)mʆFSh" j$xTIS8*!JG)=s |nFdz*aD`Kvj6ʢ=] L l7߲#Q1t8`cSGc`arO³k>&}F:@5`^f =$kYI}CŤe _DYkyG# zuX9.?]FZy <J"r8@!%)g/ q0Bcq8݂#ɤO,ҞD d*䷫ @@()t$5G N zTZU%MR"b(*R"*J{ mOnig(*CܑB􋙨i!NuukY=[#\pg<@Q׼NZfU).V{5#ς;p04`ao!G#R;δU|'HѤ|SiWL[zM3sfP9B~˹"fD>fz6#eJ!H`Rx@.%Sc]Wow@2XȄKv]0r)#'iYP0KFK] un\rhz$h.R4߀!Y@=i-,i}gY7g®b;t_Ja=YP*#gRZy-W(Bn:iIC:iG6&1;ZOڰ ^D vgNΦx5("{FR峡Epbdbkez:S{#:IqVΛNęK?~=\4(úC;aKhiQ!X2~ZW1u8*|HT^k,'6Lނ6#p.,?p8@[| zrOS\m(%&:[$וvW*kB))'Ԇo1"plN/TPsl3+6XJ 4Զ QN=R$ARB~5ey$9憠 bdc0޴7f, sRiV_@ST^ME}SabFe>jsÍH ݶa >%aKT.<Ӥnbg#cƂ󈯍`+)HF1R|ma$=jlfk65`v*ƪxr2CAI@2E$ dMPUĹ#md|m=-܆Ō'mljިd43OXC`]92ϕM}G@Œl)@̈́~l6;G#Go3G7ۙ=p8{)S>1K=$, H>34%Z i) fp""ğrB1+;w7)# |f|0v-ĵl +$+gjeU\D .jhU:,ik hb8o%O~et,;mc"lLTnrrEª,&EFΰ_b>\ NORV}3l&*7P9ըFd̀x:d>FUkq ̎e EKCҐ[dfyd-\I[r[o-wwێFboE54@KS&ĂҼyÄS=V܈_?^cTޝ9Xd7X 񬫭s1SWʦ^]uN*VTu_Kۛ{55Gp6+j1=.V*_x8G38"6x4p8G@Hj.3QJ|b {#E˪牬R|~:.و>6X?WHX/&UN|"FD[gL=Lt<.#Flg9=Dr( fE<}E^;k21&AŎ /xLe!SAJ%$@>b (C\gD#qqȎ$bK]+D) /vR@$#MOm a<7af].^WN"˱/F9Y:eDOsJӫokfV0e>E)`4}QTLNnX9m#=v};X9tG$^﹔lj|amn.|bIdY^#pTCWlsu4dUGG#~8FRAI,bɊo)Й4v]%F!1A9}( -4i 鹅)哲*ۤuv1JKjWzx2GYB1SW:b1)WOeL w"EVrޑ_D$!RN|.$zlS[cN_j.VIћsogU]-~?{GI77>@jV>e tgNxtD pc=0uS}CaooA=sn8Km}Y&"&^)x`ŔyX4I ֺ}JsOV]ܨ]3^cg'ZIPNv;S7?#p@uK MjQu/vG#/%N磶ʅvo5&dh&{Z] H*Dv9YS4 'ZolDj6!R K}܍EW ȥ4F^GUI.Lr/9ʶ![^Cqq_xjju`(/)Æ'(X:m,&:<:[;>F&jxکyQZU!aob<Soߖlj$y]pADFF";;ׇ-1sL̛7-2w)bQE Oj+@6Y_3Iwlσ#pč@nu=[[p8BOʯrM_OUI8ѮhDUuZzޅ%#&"?UmbLNүV;/Ba#& mС:ν@um=QGytpј4:Z]3wz(Әg`kf8N+jalݍKBb 6'etdE,cM,ߚ5kG!'GC{_믿=VxmFU#GCNׄ,%ς%YM_1[[#p8G#8$IJ6Y>eHxxV؇WQS pwYm=u3vS4TL\UJ,c dSDD̙#,`w[o[СC9r)bQE oM,= 6#"jӄ+ÿs8@O @+#.2uȼNG#t1mɧ9 0v:fl=hS/x\ v~;w=yS}Ͻ'5B)X9S01%|:Z8.' m,Ȝ ZeUX?GWjJWXمG0W 3ݶ}+'~+)66!!!Xz5/_i׭[^{ Og>bQ{ ނ pϾlON˼b@v3c8G}hsǯb}a|?k2#p8Ere'N>#wēLS+MtbIdcM% w ^Cw!KdLxt)e.\M0/{=2  aH |y<奘ދyܽa3+T%\L>*2ߊlZp!f̘'|/q1ڵbQ{~A`BlA=Y,TN?6MDoMXG#@lQ%E\q5]ă#p8':~x0b)r/eDgI^j34$O!('̠l{ܹwK[<<τ~(;|"̌_h465AMNcrK4\ԜB^<`_it[ˎǜ=8p>u y,M,dO Wkn;75boE6n"0{B wJ6&"5iXc`LDxp8!+K~<>fPGs8G@܎|RI~FvWkLv;)Erx^JD"`,$gUke@.wA3x7vz]D+L3!sa;{Idd1fâPQ]53eDȠ|p(CH@ 6!]ۋM' **u559^GVG"ɦśFda"D Qybк:eS v&`/G<8GA`mn߃#p8}F>EdTz`wzT<}|AYcI)'>K-f.LnA}ޗPcsv\WGwTa/\w@`8,쑘z"?>bcW {+[7&)d)9gՋ+-¬cK Lp"b 6?{U{HB(* u"J bAWP@ĶҤJz!2|﹓ vg~=o}Cqdޮ]g-Φז˃@tLq x+fuvl{o\`zN@N1&{]xb!8)/=ܔr/ECA2Nط7 yp{Ll| WpO5[5xq%*A>}zyw^p"M0^X#CF5.#/a|&D&uE/QP[`74dP?l!d\m[˃}k>M7Rh$ LMřU_`L 0&`zFX gaң2nf[? ξ;$)o̩8I\S MbaౝK޽:XLCzf! L1Ii!0xP `@p S,^#˱WM35(t1\LR|\)xxx;[C2߬bqGmQ.jE9} K̢NoT$*_ S82?"L _iqpϙ`L 4 }_XƦFxapIōÑ`@Jŭ*Ft| \%{K*2ށxj$8͘צ1mYyxywW:]lןcSM 8}*E <1~>|Egfc396 Oz~CŤ6e &y4<GQ񝱷 OkGIjeF'uխ˭eL&dby>}]`L 0ħ})) oe$t/ vFcO"]4D)Rg)R9w"/=6zX. KBdc{Fżn ĦORegߋ'N]"B]NLa‘C,UKs3Lڻn~^RHyEvbR1_DDrto]m*SxDs !L·'挾FL-#M ؤ*ryPZKL@) M w[I>0B\`B@{x>: r~rqpv\`L 0&RjOH|*&5V|aI"'><]hr|К@&cDN352%_"ХEVٲĤmyx`|  4}g+ijT/0/O15tok-6-]VСCsN5ٳgcڴi1cz/k%6}wxG%zݺu˗$Ihzǰfv^ryP&%*N)|#B-Ls:`-N@ 8_sln-~]`L 0&!dۥ(ȬfЛTF/\}v-M&"DX=M WgkL[˫7 #'Or,kEVŦVݦVbShh(Ǐy x֭O} nJ}GyAw e _+/^FnBǎajj"F$ U7qF@P^"t8/rPn0&Ў8񜋩p*`L 0&@[t5Y|-U.%;[팮;ç͌0xnOHg2f.v>5i"|v/ZeLB thY 73vi_He_y%4DDB–ĸrwKkS>voPljUoj1SXGSFAN8jqIx-v̻:wծp qv:<]p8rJz7n>#|._\q?odL ȁ@9}pz{P{+.C, q,}ɐC[ L Yexr5tu;GL 0&(.(Q8#Ⱥ!1;@eާZf`Aaʐ@qY9 8,(v{i\)hBNa'ʋbʑSFJ dr(Qͥ6XzȜgF!ǦR55Q#JG!T\+sKH.QI/KJ\i%3tzP&1LemQuCݪŔ,O >˧y6Д_X߆ ?j Mӗ}ዞϯ#x3r6ݼyzԩS+ (( gΜCI-Xr%^}տ>Sv䢊 7H $cTlyb3~qG1{U" n)`L 0&c2$0ŝK@iQVs)p/Ih[}`¾OCLږCL BTNq 8e(* y%J*T  &"bn%" ,i-GNJ w"ϩPJʤkH\K L)R W\՜^$dINJujY'fNlؓD(} W> MDAչp ^pZvĻ<$AӸ -Lld8U$ 1|&fϞ=xO?@?Q \,@&}8^7/'?y[ɱ&&dJ BIBNI>N7з;)?NN6{F`L]('$t|eHd&d-3޽LΥ<Ё6ږq>o/D#.;_:Ͷ byT|hO?mq",D"„K(3Gv!11r哀UJJh_-U)nS^t%94:X)6|96 Ovڜ֪8z_v6X\8ZbL 4k-6'&&Jv؁x)GSK" Urot"\q['[_p P$D)Q#/X 1Ki `B#LyH/"aLQ+s"II!gS/=v6);[X/vaZAxnTܽm%*1W9zl:qH6 |I&l2(z <:w^;_AY(ϓ36л>sh:diaT4Ca](-~ LDM50&`M qqMn"-v&xvsK"wώ00䗊k:F~ѯ$]9H-&14,գIit+m8{؊F ag'{i\FVif|)ٸox_<6ydk]@ >M-tZ<“DߣoKvgJ DO.P'+ 0!z[WĮO/٠iZϿ 6`:KL 0&@[PUƋ@8dPYL .uc s"mu K`jTq'ώL|qhs'\qyɗmڹyRKmzCLe _kɓx7 ;w7|ŋW^̀ҾC8~9OP%Xc܈)i,+GUFK#<)EU >,/tŊfj33㈌Q730?4RS?zk-hBtXiAmW~V:L 09_zIg`TAnrj* 0QPXLOAn+JppP4/Ʒk@*K+.|`AalD8W`L 0&P@nZSޥk"u"%/#ͬMth[u[[@ Xa<;+ck|97uq/C5afv ܉EAgHB >2&z.L6~G(bJz'~nN;489\JlիN81cXF !jҪj3ϙ`힀4[5U>A- TuM3&G"Kdy*UGX!>$6!&U>0&`Lw5w>Q IS g7wɹuT {v!Tlx{-Lbl/r58Ul-n'zjo%+8^? Y_^QClܘ֞w»}L@HM)P O"3#XYMyĦ b޼yXv`B=z}Ν;'m7ktW`L@I>)NFC|}t0Cixjh)M0`!r@9hdL 0&>(r*CE d 2 7]FC^ <ۣ}ݰr|ovwhO;wqDU\)xr$W/ez_ςDž 0 l&,o܄*goPKɏ`M]DÄiժU8x RRMBCClZM/* \/N?LEB~QXl*$J}`窱gL'+FӕTU_Z9`L 0&Z@Ia nB LGu+[}=C߇r//{>^`핀xl(,9xX9D=?{EܢB|{l/8 7R햦f3` >~)[v8N{E N&K38[B%6X`X>2|w:!6վBlb%b[| #I9T,>;qfґ=&.L 0 @7[HO;i԰! 0&n | )Rܹ)܈$@@]%eX8>ۆO";~([0k2 jgTL@U[tFk({Uݼ$M">^?073:?sKM8^` &HH CSSV})D R"UjSu}#PBo:HŁL$1]tQ8><'\yX\70&`HcNW_DfBvw//s)/y Lr Xw>w`O9V `fT7_Qnzy?m;ݷ^xp^; xj'8)uyj`lX3,\T%{ؼy3ʤNׯ%{1,YFSut@}0/0&,{oޒ[û0K ruDR][O"SoXAL bkn%X𳒳IS23 ::?3lmml- 1|Ħ~ԡ#G`ذaI8NO>bYR\\T!=ap6m%gStV>r v6]G'o{u1C0N})}ڒ@LBr.O+:MyM((4ޘM" `L 0&- q(,T_RZ2/`:ک`-K@kx<;,X?w|<7zڷeV{RzP&Eq qxP3W>_مR]m԰IxsL)P27 [i0Xг k%6!##C ' 2Ǐ\L$JAAP(<;1n)hy.a9M(@Uذr6ˉQkY/C(=p>u\PBT%8aqF%8@ S%/:G?dg/50&`L/u%¹N.&ʽdaotgYgx9> 0&<֞ ]9Drwk&Ԭ yQ;/?|O /(]<cQa7/AL{@L\k~!.\+VHBSϞ=xb5Ѥ$h@7x@ii)ƍ'1Ѻ&Q8<%%Es@&t@AaMqNV \DįgzV!lL48P'rt%IO:cVg7>^`ғxTLS͌F80&`mN7E!#Ⱥn!xS@@k.L ȇ^|sBѫQA6^\OtúT;v.xv6oFa$z{?ȫ7X>З߅u@ 'a/_}B<'N@}ڔs"44?61L ( #~!+.(Ee&i]fF{:[KS}uf.* H0Il.'rBR~(cZo_\-)m]񨧓5hf(F9.t⤾8pϘ`L Ȏ@֭!_;Ң2um\$%uT; L@ 8Pfzog,>xHpבXw.o w}O=q%ۏ>2f&NRN^̊}rHb^< hE@ ?c ާnghu*^II -Z666Xv={6oߎ\eOfKw}y`g,x`رטX%Js X> 0'GtӇ M{c։(im-BN  1ĝfoy$,Jx 4e ID7WW~^0U`L 0f&P^Z"IWT}~\ Kn۸0&N½p(6UD'3*3B"$ާfO6@Q=~jLNAdZRn+O_6wgg;{`Rxv8sOl\+IGƺ9@8jVb_$0H⩧W_}U{N[cVXl@Kr3%!"[!NB}44 zy׹ٴ<w($_S(zĒK#<}JZtj&`L@#H`@ԉX(J՝01u~|`I/IqaL@Nŕ4exA^X97x;lg/ "!zaMԷ_‘Z348/Y| h Xsp++*HuY1k&&#  E8j/O?$9ju&<bBE(pB]#GM7\-LP" _W{ ~¯i!$i ;Bae.Η%oLeX6ӹ0&`Lң2nf[? ξVw>ĝOBERm]r.xd`%3}%0矹w>K^t xN =G$ Fij# ){Sڵ /_Fnj5<<!!!4ivYcVt7: 09Xv2ܖD)p^O irT'zCզӼ&D/1)Q9niZB'Srh)a70&`L }_ ƦFxapE"}2YUL腦.#H#vV9h gn? } XO3:.f:Tx>RxD@Gfm훰>>qS]#Rt#XF&G .3 64zxjLٴrJxǴc6oތػw@\\V!px 0&G DI/B.Uݐ'3R$rB *],0v4i6\OƎ $)]Q^di E3շ4F}/0&`L)`}J]0K?E9E)-.ê_ (I\z{c;Sc3|ؔ2}"`ibECC0'.InqX4$/ l5?<{7TgS`ib   &P\ `O g1yd 0$0kKC .T$9w05޻H?sXKn)V$k3rɞ!:`L 0$E|FHg;:d0&N\,9x?_U ^xkxw@≼~AgW?!<&Bi_^n^DQ)exxTKFv1JaI1zp\o}I [wO~i['߭4x:?h0Ztk8Y #].\(.+4 Ak>q['?xXG>- /SFI4֬Y鉅 b@ |D µ$'!,U/B`n''''+U_2ML GYjeo!erbJ YGD%U|]X,*K&)KjT_'69Ts&`L 8;NAFl&)lm w;&g'eS^o!F jnjk_(#:K2n;>nm 7c|ݯ4v+1^mڞ?p-N(Stw’{gN0Rk \Md9Lj)`B&(#݋CUU/,ݨ^aSBbB駟~9sχ1h ?^r@N㹖 z5V]tAc6T"/3&WpA]*;e0.%q[J9Ҽken(ҕ]P7׆fi&PP'+>^`L 0&@sң3yJY F#/f֦p t^vp0"ޖ[QVR Mq&# h|{! o"i`o$e}|zr a]g#N#hh¸!&CTPAk?޼Co#+4:Sz `É}o̅ -E]o!n>ذ~?] QI-Vh#mx-N_iػw/n޼ ??}1\`LqF߇HurA]'!jpDA#42~yH%P4 W)Y_!4-/1˕ՑRl։\OL"!M{^Lki$k~i &/1&`! IB@R9*\ RF915u pJBD.%Ja>AIS=m8m:zXs&@p4?vû/sxs5,uZ|F' gL|-y[3`45O\ /w΅p7wny$*}w13@rtrxpSk#Rmтv~x˗/Ǿ}0q4Ξ=Komb5*,_CVA.L 0}"`adSC%ht@$zӶ;U7ӽNB8l2*j89ی(`w[20&`L|#ޥCީ&ENvBHR:%nKM +iʲt3nJ\&C_M9XN$ޖ:m„ixl{Lɰԏ_مm"R&Z\mSo6Ndfec?^\:*'xsh^6m;jDYpe֭M͛7cҥ5B\Y?EcErL Y0"N# 9f~ ['a}6 9SP磤0{"C?ɽ$ĥ43^-g8;L 0&@3(Q"=JP̟D’*]}hJPP t L>1&ZPob"E'cs`@G')0fkKV^yf!f=(bӃXzF |)ύt݄6Ϣ"jzrNYr)%U{xd Xr.qwQIy;={{sMmY:9ݖw}gϞakkw}[lsJee6lȑ#MBѣG1n8i7tPi>. ď].&@x UJ$x7w, `L 0&j9ң3ȡ$D,KITKϯ}zN?JWީ+ '}*b]l>5u `LTpK1I50<'VM#cܭbuX 'y0GQUbDؽ}cGֶ/I@< }IlchSn+i5E%!2hPcib$ H!vvE-atykv/jfZ>XQ,1~R#Polv6.'Ob$ġѣGK۪ M jkaQ*X,j~&@xgz-73W7S-Me𲵄W|U&`r!pBdlIN9C%]pw 1R^ҾO,KBNYlhqB x+~vG%㱞x{T(\PvJm,{Jh}5SS-xN\G;aXϸgCx?hn.[@|fifd(+/fIEHDR*VxBPbN9CݔBRJBXXCT}j]D^ъT~ xlgL@', 4՗iXF&`L$UȻ *\ )叔JJw#O’ 9l\˵&MΦ[9fi{OfgS @M9|9t_!9ș`p0 Pֶ\w'gqb MyC&l?C 9'/?S``|5t$'*˃,L 0ŦBLR,]qd&`L@(J%r(Q;Ĥr,)r4 JVpPrqo1n1`L@ H{H|_zCuT(]_ޒIɵRF凭\{svؤ#{jz6RnIiJ̺#n`ciU/V5ו?zG꾧#;/iLM#VPKY̭-XRhBHr+!forJlpb[ں?NvV7܂ ;emN`ɶ%u8oOX ȣ0wIT%r+MΨ+*-gK3pt+*Δ'\7trJlӧѥKhjxff&ѻwo={1M[1&`L 0&(l]یygױQDTʡV),䢼\c](PrwBPrRUATX`mB  LJGBAO̍ |od;/i=ۤmr0>Q,%jRܯf#sZ@\OTJ*X#Yi'q"pptlVb% oooC̝ޕ}x'`L 0&`L DC)la'67+`@"Y}aaon_x!FKW(gA9HaQ) !52ll`H\`L 4D 1u"ѷ( nEvW̅Bs5ԗ_AӖa..pjІJHRɭD% c#rG[c/AZ^6b9xy`d۟24tP,_cƌ#6c̙k׮cǗnnryP_\`L 0&`A`ߧ!&mkWZTVf֦$"HBRu=m=w0&h u{a۾c(}h15L@ ̥t5M9)@]̌ )RH qVʵTDNƳ?ÞpeT }v|:U?Lg2o b޼yXvtBp3=z}Ν;'m7aL 0&`L Ȇ@SBɦ2n=WRX YQ\P (Xj"\D4nPO4P(C9E)-VNTG1qJXqʁ k(;Q ;Npq4w{ {'qaL 0&Rn⏰4}prۦBJO }0ǥ.z=K'F_zO}X9}~;ҭT9'a)"3"YbḦ́CII*Q)޶JjsC;$f3 ˷ 'Qr: $iQ^mPo˧y᥁A#9O3IBe#*3XSqIBH.=[NlŢ.[/=ume]\$6ɚ07Y'& `L 0&5u"ן@)E?גo5 5C"!AG2B#cGD##p-H:H83H8S"}/j±v3Kb8ک&7[MÅ 0&@c$agQRVL .bHWO ,zk 񿞒%6H^?voPlja?Rȭ - LY ͢B]+Jja޼?-$6x뭸(f.^={JST"alҵTdE/6zB+yk[CTR7rA6[K'?WNA '1|Ħt,ZCjj*JJ4|1x\TݦȭgL 0&hmiy~0bs*&pqG7w}rMBgj;DónД {OM:skL 0!uy_͆_I#\?\ś/ r2KGKr VÞv9&uyC& F>J9Ά&7%D$Cz*CQR5{(]rNBggG)X+ݪz/sV,ڴ'bKnj{k%6M8w^ؤ&9H.2&`L 2ʏ{&^5c:9ER9q\W`L 0f&pd_ wG&]Ap I40"Aq N"7r|X:˧~$Wv5먂2 ALHWhPG S<;@-* _F`\wxwpÿge7Nplh՜$:|5NŜ~RJ漖>UZ^೰qhGjr7{*6jh AIOj2Q)()%sIZ_^Mo7,6=N샇#u]ok%6) ̛7+W{wՋi.An9`L 0&@cd'Qu<UqL ѩҽ4:P1L 0&hia±zNkEùL<r\oIPh~JY@R H*GRFa1JȹtbH|$GI$(I% RSױzBU5|^dz޴n\;, McQ/!1|ĦT<ؾ}{؅EA&`L 0 JpR\̄]ʹ$r/csy 0&`r"Wl4p"ó}%hX?w{Btwk Jȕv v'#}0RM oׁ:%WRU;r$>g Sk̚eសPDyeoɡ`@y% 1|Ħ'bu{a M&<:`L 0&PH !,E{6ee#m$qI^ k禇0QW L 0&hA%eX&ĥƨ>!xI-xob.#r<+Gfkr 9T9.cPFH0zICY$Λո\|$G+80|puh\Ehk%6YXX`֬YxWѱcGuvaA˃gX;L 0&hWrp`$.ŜG~FF#] {W7j@`L _@GG)|<ٙãW S+*+%z9MIyIy鯄n#/! )I8} 8;R݋7'= Wl~dx;ar횇VbS@@.^KKKm  aLG$œW͹HT\Z:v'](.Zx|D*WVD(NvR;jI~VI%oL.v{8ݐk GM)G\V\#G_~ryP'w 0&`zK 5"]^?E&<\).  L 0&H˫7N Ceݧ3IXbSv9QӦ/RP*'eKbon"GIVKIIr.JQxfvv \,YwyGnؤ&9H.2&`L@$HI`:lwƨsIvC/0g>૮ a SY-nmUuۺ~ϪjjUkmU*ND AD30BB ; z3ɸIx>{|y[~A@&,^Q(<4Lrܡ GK%uoeuHt*YrzxԐL;@:LoZW6~~ҥ9j;l/4P\Z?~~W_\7hƨ)֦@<ïWiڵv;vmۚW_z4z-u+_c;  O -/3KS'wKr 'vSDtOF! -]NӑB]{):{eoo2Μ#6<=6E\>9?:2Sۙ)z$ƨ[B;&S[BkJ@g1Z1_~%i7@l@x:Lڵ>kfÅתmL.x=|~M|Q.! .`f޽f̚K׶;T\PnWT|M^J^ @IYumܱG=Wϕ(gm r:9YPf<%eWY/kG>{O];N`ϟ;zV;u׳ߪA[ Uz[vܹ  *px_`K[mW~痫NJJd/9i) L\@+/DxJcp$]2ߵ%*snfϟGܒM{2JlˬEA Rfӄ |ϟ_Vzzz}|@@@ڴߝ*/v74,"TF^r_bj<7   @7gt&Lt<2A'l2A|+)VL汇 hZiԗWw{ ^9x1>ޚ\_ 0J&ӷ2'Z\zկ~Uu7@@@ j쥃;+Lw|on fJ@|@@#`RC-Iɣs>`:~u^~qr\]?L?kڵE׿.AV|Tt}eg` kkjڴiڸqkdddo߾L`_I 0V 4ILXZF;5ޞ{UVXNrNnIC# 4BՏC=~UjD-\@u ^қg뱑QY/RۘȞ"=8ewT\Z^Rԥ?!+l _6D@ٓ6͋HQ١a!=\2L:)$8  Xa|mg6Mj@΍+E` e9jZd+m6Sƾ= s/W(-/++MgY@@hqm\ŝTuj.?)RRL%Ѹ!  eyzmɥ&h/}/pBTMu{/h`>h2-z S&4G?=w:i;JM&d»u駫K.DE|> 5{xmѶ;T\PydlO.3l  ~$PL]:/;4 i#|&ILm F3j%Kh̘14_D! ~+p4'_uK[mW#I ^{ 41\6@@/g_O*9!ήӔP# z:7| V @@V(-.A%yN߫r!NiSCqc]xG@hAUOu,hjA|nUiu4S=tU:sZoʁ=[Jok')UqmTlj:MTv=H삢 l: 2k^5/\dSl*uqϺ,I):LtϘsRJwRglov(}<4  !oVߢzkTe7ܹ’b=3zdkw8Ǟy?/?_m*s0s={mwp*VgՂMMhlfTS#+_" |&]"t8<3hv\ee#UVR}[(7+OgW:'*>R&qg/%wo뾞 @@x%jXɷT+㟽sW<~V:ސ[^~Bs(*oHCS{d;iU l~yUU1oJau&JW݋#+tQ 4z}iZ}j@ (\|p*two>c\9 (:Y < 6M裶]k=  '{$_w%9M=IWL{E4P`uϿ֞^9";V۸x}\F0udZyW7ULcbbtW`SC|D@]3X,r $96D'D /uSs]TxHdH'̦q q2LV뼵 r5iLUcJb;hD1ƔҢRW5"ֽ:mLY+_{l# o̶^]u4ef;?x+r@Uz T 6>|XubBBYM.{7Ѫ1pU3 F*),q+sLedߝqd t1s]S̔u ъ1vۼGW:sks&W5:R{瘺Z˜$xG@W_kJ]FL쿽*;ӻoWLXJyPE?Nt(P9_5=UFoܹ:}}|%= ba׼k^Lzk6F,jZD2/Rc\]}Kimnꕯ포B|bF @@Xm{u?P#:)`H ҿA\9w|~̦kV>N=T-A@ <O\&LƐɾ>3"B+2Yd3YIeWnu~@lm7_ 4}y56̉.zyYc2`S%>  +w@|eJKtQ|whY#L)[dWTyJJKf֪0TڥؗF܊K2<]*S#8}%*I3wC` UL_"XU3DuHm&9J8d6U  f]-K]ȍ3a4VY/A526஦Zw~szyQWWWl"_(Z  _\5WbZGeve;&('+W%E%ә(KvITnI*0k.x-Tm3jjkE%D*:ެG(Y:v}ܜ _SiZ{?  }bu!}bj12@5@`# W&d&*'ޔe~b(LyHX;}ұcO  }rEqNə" "`jg@@<]zq\>~tON# L?L:_gUtTڳ8ZxA4z^*LWR Vt8+O@)Uok<0EOWu,2GNP)4`Q D@@j8ZP8&uRE @vRvw٭ϑZK̦֒ A-`OH|_9蔆d/   u <6Д-EWurr@ }"@+@H`휍vuiNVA k5GSvA$CW@@@d*-vb"uNSxXh݌@ ` vWRnG|Q cV}ڶbm^Bxv$pB+/〞U]eЛ@/#mB@@ز;KU+фaAWlap|Qo[ l^MvwӔk'*<::D@@@?/,ҝ3ui~z-+Fq( n}ڴh#:1JSqWVAFr!   zwkΝڐK9@ i W`ך 4Qo5   D9_aϋqhIQ?]kda'  س.S<>WnTyI?9IW   ؑy@{s{?<]]ڷmt]\ P}8 qo=B?^rG91|XŶ9   ]b=*(*)h {jC$@@ΚLsA0M.q&   W9ڞ_SOjT P]`Su  P@\}-{JKfp2)sBr@@@yHקKSdx])*"yoH "ė@z fg|Rh%#4 j5p   @s :gVyGJ"xl`@gj[+U_ Ӕ+[RM@@@Ku޷4M1H mp;@ x6s@hsտ 2 iՔ'c_~w>#  -*¬ڶwuL֍Nk{s3@ 67#TuL[ů|#EjF:=MlRwv>;@@@ZW`7k5si:WԺ@ 6ߘc@Z 5%Z2ɷgMS~6I݇u*v#  @=g ?9{zvb&)@)8ǝ^#x8b>j[~zL6@@@|IY-(Ԥj|yMA3t@@Iasf;psRO'4EFvz:@@@|Li^$'&iѡ9 Li+ ()*Ւזk?+gOmhΩ;7J   ~ xFZ\a:M(&*ZM@ J@j(+-^/^9C:k]d]   de/o}rgNVn|  MA1tnr'>Hw]R4)8ڴ nz  @IYi}uđ|ڊV: `i)k~ҾWθc1PmB2MA@@Mj=6Q\~@oH{@ 6)@ 4 ?ZϞ ,Fd oG@@X\zl] @@l a .s6jScn+{[v$ ?{BB\   g7gu.;cug= @ l ܱg @P lj>N64  * :  @iYC-ИA1E&> y6}\m[bwӴ['kAo   m;zs\uge*+;ǮԱmk}ҧvtҷT83X4fz@n}ڴhALbNn]9ZsSjE@@םOͥrʜ3c&Vnت,QhHҳSً jZ#4F`=9 StB\?^T5    0J&YLx2Lg?ti*%=vK8 Z["4\`L}Z7w] 62.R~r_5Z&   26TeZ4G`S5=E|J }-{kƙ{C5 ާJc@@@_`]z6t?P45?:w@$@KT P?"}*:Z%B:=MlRw_%   PGWfLLzT  } # %Z2ɷ2ASn:H+i   @K 84iu zu?M~ M D@.G[ؙ"oѿ˿*L}鷝'vb"  u;uBCBt4M6'ic &?8@󗃯Rs^CslwB   ,`izsՀ]t'r= @S65Ek@TVZ,RCVKZ3] N   ~g(.&Jw]:M>l#&@F">"`L+?Ns]UzOѐ3MHi)@@@%]zq\ۤtuHJ@Flj ,`:XZ}yܸR3J)@@ZVg;*UVv:Mt^ CtאC-(ң/RMw 8' @ l  @CVs=[&iCƔ |@@A^tQ-]2'͘6`S-Zɷ?5E?=gj t> 8 W`휍ΚL }.{nBxdypzN@@@0J&YLd< &sܳTymd*-vb"t(mZ/:!JSqWRDLD   Soիs]w9z `6E@tZ7w˥HMa^>J   4N`׫5:EGF8WahV}[8k2ש\yf7#  {N^w)ҡm`w!A,@)#@ zP?A0j&tbc#  xEX 5u`2jW@ B@f8=[uF%e I3Fhɔ)YI   'ֱn @ l  _k+m)$4Dc.Sn.B@@@E`t};E;4f"& Zx]<}<-[*$ 2MqvM@@@ 86lc;jv2sG B@  dNw@ e׼k^Lzsw.o}-{kmiC5 軡@@@}m=&TRZOLc{n*A}M?FQfJJĹS\X}nzk-R6i:瓕үC@@@o @Sɺ釧{JAM~0H4*h2NJ K*<"LEtd:I\_ި8tգYII#|*@}M?F _\5w2kKNRT\ b##INN   ej W:|RؕGM zx@~Nr+7ySΞ\vW}#G+wɉ7@g)8Rk3^ym@@@,`fV`v6eq(/k5El gz> PRT*H9{Rފ@ҡc%󹸠A i23]A]hP=   K -KR:c ].1NT*`) B%.q @pl qnR/ŤDS@B>lFᬼ$')73LR[|8%+ywt>;m+9SIQ;tSvǻ @@@&3f/)r}]FJը>Ҿڵ@h~7]wMs ,u͚H;"'x $i)vfڻ%uIpG$H2%s<щQ6 8;   T5=^TDFcK'譤:ٺuHM杂 <5=h6 "*PW(u&8I6d3;A|'slLc׶kұ$'xT)}6"od2U]eЛ&oR    f뷸ku c(+-סf:$H2Hwd7xJ;SeT|dŔvNƑ5]|WvRb(45${}|@ kz`   pf>[߻Nf. qm}e3*GHuL H1N6R3k Y3 *$F+,?J@@Y^tQ-PlE݁/9=]Yr-o~֫FJը>>1! @ DU}@SIQEIMbOoXZ9 )rFqg;d22;A|!m ,2إ8J $1q9@@@0J&YLd< &sܳTymMT+7lղ6cTDFcK'譤!@hvMN_7ܴOO\w:6!`LqLOg>mûiك*{Ӭئ=QQjc~rSDEGigv $ͭ 8/LٓtyDeem\hXQR;%v2YIvz;mLZ   6TeZ7 -*Zok^UiaE&JLBtEL1ۙiٿ-pz߰0GW-숨!f\Q5ljeQqNz,"&\UOW3yU-\sMb6D':m>[:e,٪ݘ)k#YtM 8F&TpKض16XhIN=@Y/)y}fb:@@@@LWكO /P)﷙6O" 8ͯvhmdV;n2]LVLs 6; r Tj)+1s cCs f}}QatvH&d3bD'#Lsd&s7c @@@ x&LoY\kZwLwi) +@)pǶQ=KAw]ɵfd ʚM&T:@ՃP%e*!f-k;_N XbWdy›̫j)s-tZLQAsJ~N 69U-9s{8;dUIuJpt3]5ڙ.N1DzڪVg@@@@v U/9!Nx5\(6@ 66w#}խ;޾hjtBxbG@@P`T!!@)8ƹQte2hj] 8=ͫ  @@@@> q 8b-ron   @ ozn)j_>=^ }BhM-]@@@@Dszo6l>g"W Ӱ~=5Y!ExG@ 6h@@@@f8n }i INӨ>6{ih瑛 @|A1t@@@@!L-EvM     V"  8Ms*@@@@`zD Z}h    @K 0=^KIs@` LM_@@@@ `z t ТZ!   㵄2@@B`@@@@`z<B: xh:    E%%v6-[ooվCnP Kc!)} @&zR    @3 xNj6Qi}4:-UPdx  |ϖ@@@@(`[mg['yWNi#vK%`ӵIA@ Ԣ @@@@`=^UXmPQ)L`@ 3CAC@@@@ع|8EmKkbz*K@  I7@@@@(.)K2'#L`@ D#@@@@`r-I$3EށCmgsܥv;D!JYFJUaZ @ l     @kdѬ+dk+zw#7^Ra#  li    ;߮ӼanW$4$n)"V@6 @T`F@@@|A HWotL.c*RBCmiʈAޯb@&R#    %ZfXU7$Fj°=(UqQ5:tl3;@_`S3-[t}iΜ9*..ִi?A={Z9?{8@@@Kb-\^fH~^]5~_k04XŽ^Sm@C`S3֭[5qD 6L˖-S6mtM7iZx:wX[7JÇkVWC@@@-v.` :羮t!8|:Mtg@O`S3mݦIJJwxWշo_y2+c'|xs@@@U`׾|j-vs$'jNSHi &/M믗+dn.HO?yݻ;{Z+    P<]ôF;2H:0 ] .l  &/ f͚ek<Ӫlmzꩧo{vܵu@@@M Hf90۶[ԨpNKaU~@@`|2--Z:Mިف   8E2/-\AnܪR*X:rF*"(A@ _ sY۶mvԩ5)))vߺu:1Mi좪?u;  -MޒLJ 3X_2?6宻uNNwk<'//}6&LI&f=`]{ׯbcc!Cno/TqFTM?g/t*@V eG>Z˗/Whh.j\   eeZ?~g4zmKK4_OvtW7?f3E3y7;]w.]=zjL,Y~~G{nuYرc]vq+;;[>wwh޽6X>8eZ+'_+;ꫯֽk=M֪U]ۚ@ǻ XrJc\p,YWJoԨQJMMoqܮ6%3CkF=0'    P.y͘6޾j9w'4YL_}QVl:֫;k0skW}]C7f]Ctt|6}<6gZn]&͝;WSNU>}iӦ3|Lp3Ν;];tg[N?jLN;4 ??Ubb퇯Flv"3|~R5eSO=%X1c|I/2:gTI63)ɞ!u… ]e&N(>6@@@@!vVvsԱmJ]_z]a|jY5՚ŴJm54=k߽ Tg1AE_ 6]z2I&h4l0Ϧj6gZlƌS;sΩ;3ϓZO&fm̹fZAd2|$$T/9G@ 65xw; '`=rݗR&Mפ"W- umLLkӾO6;kJ,|@@@!T/=a+e*mJKKy۷6nX鸙ڷofщ'-[Cnկdfyu76ߺܛKO4g=Mi" 3)5gI@@@TLZZŕMo}ej vAQ`so'?ߟ[w)230AݻwkOCs5Of/r=g2Q@`P{J T@@he@r}0Mmk7+/:'س"o)[S?Tz& ؔ222l֓99^QQ:t׫SNnm3́ر=XuV[ݺuӎ߯ h2mJd?%&&j6SVpC>Ç,6Sqѣ}  1g    @̔x&6@a]S4e`OOh۶km۶M={… 5bEFFjȑk=Nܹsmp@Q0 TT-fZyXuL5_M%yСC2A3]Ci)^xaKMd,/`SC??{kO8J]jsvyfj]ij    PM`llk` 4und{ΫmW꜉#4U&γw;d ꘵LqMg}vaZj Tg3읪ktOcΝ;k:|}-̟ 4|:krsgo35mwޭG{\|=uܥ 7Li4\&k=@@@k#zgR migNP[\kM=Ru_i|]t=L iJ;ֽ@Yꮥɓ'۝E3cq3LVL1˹JCw]W]졤Nif=S~dW4kEU:ӦMvÇ M4I7p#N ?ϴYܳR'b>`q%  ZLsW:Mt^ݸ5Ow I.ǵw#ZLnn%bzu⬝S}:Q vi2 yo2\\Si׮/_?NCli WLYL3kLu׿U?:zin&b<<3%%%Ž/eÕ{nR-y}ڵkZQ?K,kd&@IDATAd=Cv:ov{xt|MZIO9>޽Gf}vf6t^&ӂ_W^yŮu5®J jx)]oajq;V;5.[Q2 Q  T2$bP&d0㞥gcl#@i-"]_ݬBgzSButF::ip_')2p:MO%VZxVd$2&3sLCM6YK:hv0=ܣ3f*X=3=&+>Ŭdh(ɵ=eC5P&d/*e72뮻}Z6 l2}0.7u̔mULuUkE-[f{fx15kP)=\{?3 -&ۧ%={pWɓ/g3F;^=+ kT_ԋ 8g Pŭ@@>YX~ݏwJ`01h1-++/O߲\~ob0W?^my`r'`Q_>CSN-w5N/(./***_~}*w&*wYժmƎ[rJ;XѐVXXX>rH{grg:=;Lnsm}|sOWm /N|[dWvUS14zꩧ#Gʝ&{_چi ?G3.+W)W 7 @̟PژF8 P_i؉   fZ=2OUA 4ܛc+S_,_ū7jn>];:k0 !}!m@TZZ7xF3YNNv2n\>YLgf8q\۷*2Ӫi̚>{."l|zWxbeffK :KN`E]t:d~rM#l;OޤrqUz裏ڱ3g,hOwVkd2zK/N/dQڵN;7дьSNtWk},/oظIdrdz~Կ_?.@ς^=`W9bu  @S)Z 0޳:{S-\^;2թ]4y=Rڻ мNV~JN:tԉzc k^ jG5?A{&z:  rdZ3Iq1x@M1XR4g=ʟ@hjljiq   "_XdLfwY':2B' L7XCS{($MܟJ@@` #O@@@ ؖ=]⬝d&gtڸME%%pXh k޿"x6  MK˛ԅ   ^ع^ZVȬlm!! LcUltB  6U7a   @qI-ZAsl 83 SrB&! -@)Ǘ!   _%TXT9mӬ+v\t;\N^;ei4  (!   /P^^[w?NiumܱWe:fLWND ;MgQ'Ek+wuWcN:xN^^E:6&LI&qUs}>Z|P.'~@ZG`SsW@@@8&PTRǺOާ^ChhhBLӐuv@:-]T=z]2efGݻuYgcǎw߯l=vwܡ{*.J9kWK}鷿۷o 8{ewy̆ =Z~}|@h6sk%|Eah#  @c^tkƴzwSZb\Z謽dL[vʬ*S9/ TQ7ߕu0G_\:wJ׵^hݺu6w\M:U}ѦMl&SՓVZ3;lJ\DƠ\-&Pfݎ!  ?&SɵL2}ws>F#b=»7#/+m]bΞ8BK?3hgѓ>id^Z6l1{l dl2Sy?PzLOOׯk_f,x  .Pnnnb=vh;V7xc*w&1]քXb֪V֖.*U4xmRRZEUž5"D$sޙ$3I&w>{<{@ )0 @@@@ $Kj9҉B\;5 tT:)feei5T~53PՊz<LDի&M _iȐ!A,Xp:3t^S)11Qؚ={6tI!p%TQQQ\B}^ܾ`Zd Z^xs}B8|0-? dX5kFIIO/?cuNc  /9K?sC.I.10A&ϣo/_.>+|0w\jӦ 04ycZNvhI ^@v@l       `ItU:)E/_Ai޽{bNU,N_ԓ9 /SSZuK."ntQj۶8sjٲe0aMu"X:Cē5_@ؤ jA@@@@@@ Dpv3=ҹf""j vk$йsg*S8_EzӬڵә3g~#>s7Rt~dSMĩXfsNe~֜{ /^ztI1cHrJq~ӂ .FsKog#:Bs"#.H՗!@@l7" }7Lw_ [ZxjRz5bJ@ ٓ6l@#F&ڰj?RWFѹs爣hz-!>L>\o=?ҦM_50^f͚%'NH, 6ڴi# O D ׯ dҤIԷoߧrKϭjJt4~raF~=s ]bC}>%Vsz69ٞlC틺m,0.\@*UiӦg}ìJ<&@@l=Ŋ@@@@@@qtbnFQVt(TTȯze!.q+X"'~!DžNY07v? A`r7a)eȆ易mC~X=t}Hqg@8^       `Q1*t!.A(88FJ/Ք$6<(t}ֲ^EĦX+M̢a׈ťsaRNԴ$0=]6<@aT1B 95Kw JLNQFqskQs)QjW@@@@bR       @\:& LtJP?&77l*ԛ鯿lbiB:khh(㏴yf87mذܺu999Q2eN:Ծ}{8p j@@@lz@@@@@@,J )%N\* LWp7)%-]񧬻+7~5ɯFer*-W)O mOM67xn޼I:tm۶QrR͛Gƍ#믿R˖-iΝJ;wiԨQbܰahرh6Vb,EGGCt&]TTM0AMnȯ,V=zH6Ak?Cll,\>3Quy_>%&&Rdd$=z֯_OgϦ!CВ%KE;=boH( >"٠@@@hBߺIW==]%aBN_k)=#Sqg9j۸|*{xe@U#9Iwa_||||իz>Snۺíwww១"""VZ1s%$$PҥsQݟcݺu4tP̡k  PP;| UA&l vK-<=I"(_r)Ezf~>Tbqx(:/"ˆE j-]v"#cN:E-Zj۷SϞ=緢M6tȑ;ޘ45kT~n5bb1sMzxhTz6f~[B8q"qDږ-[ 3ޜd `U}Wo-Blb? ,Y5B#otFS)4+sppuS &5Bѯt@$i^uZvt&>OzC?^i4cƌc~-mݺUKl޼y&> ]]PŁ;Ά]'I9RNTKD05]ܜK)mx@~bҴijqs8 G0͝;W<ܽ{8*cǎrUBɷ!0Ht;qdS^&AhRŭ/      !$9HAYJ_AΆ +hӄߗNIt#,Sl@Ν\rBW\rz޽ĩի'lT{gԩ*]̾|2}blff&M0A;qYfQ&wt5Qǿ 7wIm۶%NK2Ǘ[neӐ'==̙#Qrvv ?.7]>OII3g]]]ɉiȑ<(>bGm  `Nl2']  t48nFQVFWyjȗ$^پ$U:@(V^-RM4I믿Ґ!C T{ByM-(l͞=^|E:y$EGG:䇃*?cZ`-YVZE/ݹs>Cjٲ%p(yǏ… WnWP9J7o/N4fe~sb8HIKK wf,|#>rVM.JR&w^G!ыMChg `W_o߾]9ZT{\~gG9?8JԢOm\oɳP}%wwwcʯ ŸGy8jL]nﳜ>/^L?hs}gky{BJ{DXh-.|0o|L       `>ELKg>zLmEΆdrs)%hq@7j.+h`@}j1{J{~&ň D{ n2i]9KϜ⢎0i΂j vEdLL =j׮-R(_^]E>qSڵ͝7wFGNX% OHO      7OS)E:$95]=95Mzޥ{_G:"EmOS(v'y%KUW;וT!}:]r%r{A ???#GW_w%_.Ç'No>&O\;<.BSȂ9u1K M\Rů3ٌ#M٠ObS r^R\Ji(EB,=K?s%J}ҕv~%I6,\ĝKc{IIz:WMiG~ڿ|G1㉣n3Xo!Ħ`ZdI6_#ĦZhQV jӓbcc)C^B9*@ U3|ruu+V8*˘QPrs\j_ ŸA i2I<Qe9ۙU4w\ϩe˖L&SF#8P1O1d_]>$0.)|ʒZ2TzrR@nfuCլ38MmR4׏UIdAB4OV[IsXIOT@һԖ*}1Cn,C (!WgE {d! 互B8GHH1’%9cn_~EP֭K/:uꔭ]],XɅl)82f̙i&ٳgի_~Bad֭m,]Tˆ\{ŋӰars j?,ɅEF~X(㈲?L3f̐eff*߿O}oٳgE$ؓ'O(22>L=믿NV"-SM4) 'OLs y,Xկ__3Or +rG>/&v&őQyr 6D2m|D :jrĄWҴrV+3@~4+K#Ykk %HE9GG2fΆ]&5h껯[   0@ ,+xڹsfNБ+tɩ#8eԦMTV-mܸf͚Eׯ_zѤIo߾J{N}u;F1d#..>Sھ};Ji]9h޼y{nݺj=ڗ;8::R rԱcG!4hBnֺ_zUȤիSi̘14eZr1n8!@Cd-',ܫݪv?G73:skd 64|Pm\s&M-+S{Dt]kĐ%e)S*ȧJE|","i|Prj:Jz> K 鷛!R%ɹJJie{)]z.O=s)>}ڥsA%.R{Q,[~?J|ti-k(;|+7@@@@ vuN^=6.OY, iRr.33K9ɭOINK~:+?&jlftX),EwXa#X?"AB$baHs",(BM(      `K 6nW`!$iGpT ?ԝŔ#᳄X1?NK=INck*y59ם#[Xkr;Et@Q/rj eWTųX|UbU      `>A@@@@xZmIGm3OSAg u># +!p8c$I7D霦 jSH$ . .+tU3ǏVTIy֬Yz$&&*}r{m֭P{M]v-,1^%K+}R\hԨ(QBa&MhԨQB\f ]ZhAJ<d;LiZo✦w1-;Qpppuk׎(22N:+oN={ۖ6mgIc׭[GscV^MR*b{,D"܆ o v@4MEzx]iuГTj\D A@@@@pqq_]>T˸qFuV"1| s}@@ 'r6"G`Tٳg\łA@@L.$>燣8GEuQ)?8uU8e[o%}ʕ5U\/.[lɓyr@@@Eb A@@@6.ўɱMԓJ99m X=@:wLʕ#rV{ګW]z5[={PNTRZ_n„ Tti֭f͢kݻ7]vMP|閝;wR۶m±^zeMwwk͊4h ruu}ѭ[ uƬ-̙3aÆb>'''#GRbb2~^Jろܦ4Ѓ, >|Xh< }4Ŏ29@@ 60̃1iC{H՟ %E p \t~W޽;kzsJ׼ys1Z‚e,* Xϟ'NسgOuxmms4n*._]<3f=W#F(|)SF1k };=A@\ 6,g.Tё>9M6gp Jr$1J]ؤg!(;W_kG/;8ZT{/8{a[rOSqڼĪoٲEDptrJbnk˭EӚ5kY>H]xo>S5j8INS/^#>tzr[o6kG=Rqi͹N?W*k?t.i?x    f#p+}〰~TR !J, Az!4IQ@@TzMyM\:"66L)&.R.Sx% B{۷ow*cbbSkצ!8(U"1u)mժU;a?p197ӷ\ocҵ(Z$ N1w!4Yz0?"@@@@lsvs ͟{(8%DzAtYL;v=zT ڵˋ3X3yBW Sq*?uh'NRˆ#wڷoV%XbQG>OIχK.ĉ㓣RJѸqh„ '>c1++6l >T̘7GˋS9zܥJOrt(ATYo\ދ<[XIsZkV756҅ P 6,OXnFRg߿;ٳgEؓ'O(22>LB*u1oCh9\akD}1^McPM z PL -D+ Ǵ   N )%/@Qqԥs/<ǖߏ_]Zd`uV%p@lb2x`;wkV1ID@IDATJ\LN|㳙ڴi#Zj)7n(.~:իW&Mkѽ{gQl~q=G4kL+ ummz*q:Wzu߿?3FD-\*W,.N[jurzIH*TsvQM-ZmhM ]4~9v^k"3Պ<+ `[IKb%МA!dp@@@ ߴ}|*{ќ*nC0Þ^SNWF :qc cO~|u|b9yFJZ7̢X7U"XM.hӔɪg@@@@L"|rj׮&3 L{/d>İ Jg6*nL    ` w)e,`qvաC,Gry/}ըAlM    HJIwQtwVɿ[BO["о}{*^8#QF4tPjР--d3[GA@@@B`OGTJEż$G...T|y8q"͙3WA@6 m=GQPp*I$y!    H`Ŋ  1D܎5IiStJ8)A@@@@@MEaF(bRhΆQzF&oB,b\s(&&ɉyԩ-YRSSIvig9r{=]68hذa?tKNm۶־ VMbUo0FCp^@u=Kt` ߿OӦMSYȠwƍݝFM͛7(,РA0aBJJ 4ڷoOŋ 6н{(::6mD^^^;ФILk9q"P@@NbSa$} A.4^:mK   `*T@ƍSU *_j_Hsϕ~z`qԒF]v۷޽{iʕԲeK!qtGI͜9N:E+W6ռEرcd0) $    @ߡ{sJʸ 8N%S ͻvʩ[yxxp Zh^:thnr; رTH ` 6}">itNSW2 9e[j,DgT|?0+IR1 MXq>Ig.G+ԃCQ@@@@R֭['>|AvIm۶%NWtiիkOIIg#5lؐ$'''#GRbbV_~IOO9s搟9;;;~x~9U矢?nOix}Ԯ];q|2}T^=)=&L uM1m 7k,_2BCCiԩTN1ŋkF ZM٫޽{ӵkbŊI)ic>ӧo>W?se  P4( C+@@@@.F \y-pfwh ͫibX6D{… 5  MVV^ϟ4<~X# N:i$HsIeL.]ѣGwj>Q7eп_j$1Ds9$:]_1 *Ǝ+|oG.e B"nQH- jzSo6~z%`(z$00PH"Ϟ=K-Z]vQ׮]>*D%_\\+8#|}}rI<6 6o,WȦVZwcqtti8jDc<(p7o?^Ʃ82޽{gegʕv;Fͣ.rHNNJlC͇S!zyy 111$שFTJuSWl??ťh|RS>) "0U.A엀|"@@@@ H(L7BShmzX\`aI ; M\.w]a`{"_Fڿ 믿}/勅&.wR|7nի{'W{ƍs{w\XKqӧpȆ*,YڿlٲXxt8ݠ"Kܦ~4\(3q0e1ŔχYԉPƜwk  `vl2;b۞ZTQۦA@@A?ӦߎPYW㷩9fS!ٔ MTlKx*[Z~'/M2 A@t B%'OI駟ܹsuws%%%svvS)ѣӚ5k<7XQ9TbE- j54jHgO) I)(55U1j֬/_bccEyPN CLך^k1 SS>;Blݺ9YZ3[JYn} gK11=Rb^t6?HJ=R>߽Є&l7++$JV)3wD8霢ląSթS'[np   vW)S&[)GBl:rH&NƅS.rq,q/Cs7vd%ݔχtN>}sqQj۶-}lٲ<@Tag/}K4X; d{{A@@@HKxB_oU ׹5=WjŃXFA| [BQoe8СC)\tIĩN8! %2/zNutR!uξ9B&>:&ԩ((:fs}5edcbS^=~3f NrJq~ӂ i_jU}kլEj֖15UjW dmbTDbI@@@@wӣ$j\:kKA@@@@Mٳ_NÇ-[(,.psΉӧӕ+W@QhbrDR5>5|tna0|ӝ d/ m#>s xz   EG %99Y%777Թsgںu+u]r@  >N)VXA-cǎ]ԩS[A iϲt糔tS),:c\rԣGU뿏ߦ{Nh(l'jS4~v~ K:Kի?O^"ITWDtP9 դuSףonԁ@@! H%mh$p.욦5}hB"nZsmyu< Q@@@}… 5 _R$F:'INelR:?~#GHŽ&22R駟jh(Q cRSS5M6Æ HĜcǎURi/j$E#b {iii0$ij׮Dlf_^O˖-5ϟHf,lkx񢲞˗/gTW^U={Vw甋zSmM2E_v&<<\3dy fܩS'1^n4Rt9ydŖ>] |< rZ]_ `g5H僪9TkޚL2Ç{O#E#i!D"Wcs>ܹS#EbiW.`_7n5w1hfB,c?j۶FJ/4!{֛W,I˂z-|>G7o.>GӦMӰ h eBlZa- Aj k( KCы   D S:`mt165[ &ߏ_]Z l5 K_/^DcG!)-#`-/I$&ϲI@w MfXL@$GAh*E#MX T& In.deX@2e@N@l2@@@@܏KJ)}҆T}ޖ]dۈE}̤yvQbR PnܾՀ(aGkRD-c0MЕwbћH4i"!zkqbaɊ78q*9M&gdی%H@w"@!    #0l'iz{{]|2X9QD< uԉ,YBVp?>5j(-:phh(M>֭+W  `A,SKi4%PP6MmAߧiӦ)+g1'##޽K7n$www=z45oޜ>ƍg+Ò@&{Q@@@l݇Tūņ<    `֭['>|AvIm۶L^zQppV9s&5lؐ\]]ɉiȑ#t3gwqn~-3IL)ƬҥK4m4}_g^׮])::E5j +1sԩSN:I/gQ^{+uݻ7]vMT15ރӧ؃-[}Զ  $ɜta@@@@ CgCiTQ:rr4    XYhYfرc;`=zLݻG'O$baԩSXa)**n޼Io&-_KoӤIhСCׯ'(OA?~L .4ɔkn֬k\B1nݚΞ=K}{GN>Moĉc,汨.}8q[/d}Ae.FunflB۴iEFF* ICJSb." m[ p;!_R7^.-[~?J|ti-.q,C*,6p5OOg^pҢE ڵkԑp Gtԉ8 _\\A~eÑPseO1ŗ͛7+ԪU+nI֧AצKQF`۶miذayYs Bxdͻ@ wO펧g9MU+Vȗ= LC4bo護ޢ`R?r3 :uhh'8K.s8܉'T{ZyŘ(qΐ>3ucaͩOlbիGqƌo+W7-XGnӡJYPߔr%2 $H&Zn;MlFN➗y2FkRLb0@@@@T)i|N.qNSQuM5    :ΝK{ׯi˖-J'8S-[LRr64}tr"6x>/h߾}9 M3e!D}Ӄ|k:7J?/۶mt}MJ)kVszzzRllH'.޽[%GKK6ClP|F6gZ^;/'[9?1܆ R' $ } @@@!pͫiOYs1CAb=|Gsxf…~/)I#mJ)*Ik;M\\GB/]Tȑ#5 Hͧ~D}hh&$$DIMM4mTKgitzbαc*sI{|)RJ#k,e)J#|')GW_[Ǿkpb#<<\1!qKaJŋz_]2'ۓu=O2E̻vZ 9d1SNɓ')I3rttݲ4YM +сg;*S `g@K mhNk2    4xE+->] &F,@@@@XpWhq;_l★Qazȑ|3r&47?BS^j@@@@@쐀zvD, EjX,@"}\J zc B>M3]MO)<ݨR2v^,@@@@@@:ME@HJIwQZFuk݄ZԫYa @@@@@@@ @l]O    `>xD՞=:*6) 6B }A@@@ 9 #wg?98a@@@@@@@ ;Z     `!a7h✦1^!2` E!|Q>ԠV^@@@@@Ml8::R^zԻwodɒzznUxx8 6ghFMTxq믿 uͱ>44~Gڼy3]|9ǾXPrrr2eP:u}4p@u~t{#PL' )|D %HLJ G jf4Ď籘+(崑]Z_(    `@ll,-[M&QF z?,Y"ĝ{<((C 411VXASLcKq5C:3**&L@۶mSwjժ<-[V01iL{U~}JLLH:z(_N>MC b@DZÇؔ+:Ztc   `[זXN_ i~ F}M1q O^eKKv"e0/($ƍiذaB179[OHHҥKUc"""VZF CЭ3fNskݺu4tP™N=7A@ Xw rWЖ|P-  vA`_gD<Wg㷨|_0#΅>)$$8g;w L! ycȖijØ1sΥ'R~h˖-ƺ_6mȑ#zP  L.@l*l66|Pm "A;4ۭ)CP5ĺH(9)))L|PjjjAL/9jp^elsڟ0f 3]F'O͛~;v>}XŗZ@%k'ljUm/&$23O{:B&p}1cj yfLWJ(A0Ȧx7n\A  P( 6 fL   CiZu/>zL}ЀgqX X> zsNj۶-szEZ9Bj̙԰aCruuR4rH3tKzz:͙3G7đU<~-%:H6te5kկ__ҺV:/.)cǎJ)ѻwoŃ9jAwSp(  2;"tr$uw zCqҎK Nh"+ėcf4zh6mݻwOjKJJ-[ҩS1,@M:UHQQQtMz7i_*䇷~&MDCZ~=?~.\NNhʔ)صf0TS)իWwULُ*8=:E)v#x3Mfl%ߣs   `/Bݦ)n#wi}鹚UeiX*uzbw8}Zy>{,hтvE]vU| bQxx/!!ADBG?chrljժxW J'wWJNN&lsV,ϩmuפs4>w˔S\ŮLi@%kj/, @@@ @“4eeQߎ-!4`@2Ӓ@&P"Ű!PbEѾ !7nܐY;F$@$@$@$@$@$@$F Plrp㵄/V{:__Xm Wm8IHHH!a2?\4-Z3C$@$@$@$@$@$@$ PlrpT7nyMUWjXm Wm8IHHHU> VIDd#57eŊ%""By۶m2w\ٳgt]goo$_''$H{<>=xN<{:u$ϟ} [_jQ  D 0z55Ĕ{!  &)j ɔ1UȓK$@$@$@$_FhaqMqэ9rg~)%*ﭶm:"۝a)W;wNy;=nuٲeg-D$* x;|z6Nj"   ܸ-K5lӄBmL%   D%K 2_Wzm K!Xh[(ibS{tG&hHHds_4U)vIHHH X)SHU:JndT g޽{j[` X!Rő144Tʖ-%XBnd>@Hb][.@IDATǵ}C)SڲeԫW<a~mk4w4r y˧>ǖũu!#Ιbώ3cS{q* w$筹3C9HHHH Dk\O&2Qh; Vȕzjٿ|W_ܪ> atfGJ??HƲm6uY JS-Z$7oT9썟1cC!ǖdѾ3jOB>)m:Z/*ډFRAhʾ*RlJ¹H  @)    %rM)Y(r] g'   4L?`qF4 ҥK6ۭ+{ e'>r努Ι3f~Mo-\|e pv߰oM1½?aQ=a-n '6jbpѨ\eTYHR6z6Փ ]W&ڵdم   H7VaۦN:tH.`)[nrY NtoǏwqg3ka (6g   HiySEWKIHHH ^ݻg{Gk֬,^XZl)ݺuӻ˰aäSNw^W B!eҤI}vs_=$Q4| !䋚6mPdt-5\?lԭ[WJ.BoV?w\ٷn e1B-[79}/< &>\d]]w޼yU^HCWX,/VQm6S7ll53څ8dO|rgw"H\ @XJ$@$@$@)wK7tҳmdHHHR 03gy?~t] I&ҧO% ;- ױcG% A^L"իW/F*xܼySل7Ç _~?+ ^>m%K˧ƙ+N.\ C 9xV~ۄ6CH*U(ocǎ $_8qʾoZjelrx~ 9s߾}ݻwٳi&ב#G}JC*cqu`=z,X@ի'cǎٳgtߍuq(Wosg ĦŤsٝydF C)-lwpL*%`U[cJo8E$@$ }XFӔY~M) 7@$@$@$@ID޻ÇKJ̫ !e*UPA>XAgΜjK%^w}Wy̘1C .K(}oƍ';wVY5)XTѸfsvbYVXm6ZoEVxqXzMz3JARERy DFEIPiӠhlݓ @#))=x. дh6; ЩSJS~]&U 7 @2`dHH $㧠o.Gc,$c~vdϚEwn%u:IHHH >}'o?~~~j C (P1cc2e JӦMohM^ö;6kun`ݺ ɘ1źluޱcKʕ+'>>>޽{Ν;m i\c̙%ҠA1b?~xT9{nHH D"Y  pD!Gjm hi?y!Hfܠ)򮖧)Olig) ".v%ŊSjܸѣGqBH˖-5D_rLa"4h\vM !qㆌ9RӧO˃ի2|ɖ- 0@~iu떹~rmꫯKu:2eȆ $,,LØCRB k=z~)/^4ݿ_Ν;'m۶5kmBY~}\- ʧ~;ܽ{Wt"5,YȂ cp7o@8jذtM"##C͛2vXs݁{~ұcG¥bŊo˼ @`ΦZ(}r_$@$)z9Sok9reqDN=yo<.5q)$@$@$@$@5kSʗ//'NebƍJR̙3źӡC_˗/[7 *zS>}‹u1y֬Y t٢;%X3g޽hӺɓ'^qK9efdڵz#%K<gٳ?ɟ Ϟ=+VR-cw֭[+[༼ݜO?$=zٺuygl+t< lbS~}&F9 $#cgDNh+> Ky+s& XFZ7+ԞD`܂I)W}zVI& 'J]W~w9~5"O!䞭*ԩfu1jɐ! Ŗg؟HŦ͹HHH@#t#D&.Z-c] 5/&{}K+Q0+!w"dǑi 6Wn'[mr ߽F<Jp$@$@$@Bo0iV̝;Z=Kd$r?fZ\d\ &  H֮]ĥC 믿V!!r R@@E3P=zа ȝ+ىoWK/X{7>lR [`n=&M2cƌQ0H_5qDAL.\e'$$DV\XU ,hKz=ŋc9SK+%\}IHZ:rMS^kIH eسt.9~Zp:UUR7&.o3RBiݠEGLr-ф9|K,GʞU*("~% K"lc#@4f#E x&˗/KJ˕={v ӫCO+W(/(4@PaEA=^=ٲeSgϞ2k,%^L0\Ɇ TXqɐ!CC^???%tP\]7x@pmιsTRShݺu˗/:7o^u~yc]*o믿Z f9{ A T^Oh==|.&&Fa (`w znÆ  dݮ_Jt}9izCw}g&tԩ^_>3fT}Fb>7ze_o3߿/2eRhcS /ގcH{Nt^rnbSrOs{ʃPq$@$`Ae& zmN,^Ҫ~ yj.DFKWtF wXWRP>) OUTQA!ÂQr_ '"&z*JM%q~   F`s^8P`S9`pxrA|>W txթSG;qqg!c>|;V 3zu&ׇ:"[DDޖmԃG -   5q ao㏕U\[?#0x۞ qل_ IϟJpC?{ɹ+KNHH ~9DޤBAh͑MB })^T5ѽO۱ 0EĨUzG|6UαxH!GKsW եД< @'k({ɒ% yg!]ǯ!Rŷr atz۶m^C_VU))K:Qh7)! aڶmL-]Tq_|EyP{hoժٓ/RxWb㒪<1>^ݻw(o̦B.4N T DAw>>6sŷQhޑՓJxB= @%!.+'  !U[m֖<"\]9gk>޽9".IH]znyTp~X˕sҕ 47 N˕Wҝr[$@$@$@M@d sgoF)o_՜۪;r99[ ķkaNt3ztQtA[ ̙2Ald!6MA  % ?4/LZ#?;5[48-O=+I$]Z"  E X{أwW{=7olݺU\3K{TL9}q#b!a^GϬs%9x1!©͞=[yo7ZxٳmhϕsA7i7ozK:d6/*#D=z[vNwQyy *[uƹz{װiNk׮`3ftI}Y9{zt;ւP{!o\֭[ '§-YDz *D 0@7o^swUȉbTfɲeB&Pz#F$jzqe=/V^.۱cG%ȁb-֮۶Wɝ+̹6mK[riF^jl2i੅9eJ`Ν+ݺu36=P 2ݖE'8O\t;zhGkvW3gHҥ-"BCDx^d9r<g+B&$x*k׮̙3xWx4y>|ԩSGnȆy2Y^1IynI{@|knWɚrI.E)?dgKG[ %=v@$@iFδ~Ӡ?>}<٤y4q `O-I gZyI3d9{3'þ6?ݒ5k7LZ^"6<%  pۤ 6ګ\߿,Z&dlUv5ĥ}*[&ä7-]Ԥ7M2%-W3lذX\`ڶѣyգ&l 1&-I҉5 8hb+pO&Nh^&j4qEk^MrBBBT4n8xκ:u~?ss-[4J7_MW^5i MZG&4)-dݻ+Xf҄';vΝ;[c/Zx=Z4Atu>Xiw5޽ۤ?sԡ 󣯱XUL;y֩{SR%5!x[H^s$uĭ&-GiXѦ7ᚅH='z6iw>QE/-$@$hb?5;ɪ-{PrgvkKZ+S͝ C^O~=bƒ[-(~*]8dƾ)H%jиp  |rhoW*UT*.#tuU O/  L{!/J fm4O<*N|||pҨQ#e`ҽzo4hJٲeEY7ް65ºi /5jEkѢE,{g*!l0nWP{Nգ.׮]Sq5qC Pe^8։XQ@ȡ_*%\_p\}3;;m:Lm5:[6%mBhH6뱨+&IPPT0C=[^OAjBSpj{6v[GGlI:x8F|dER3+wH)ΖN >Of4}ѷD8   HyჰhM^raM3Hʔ)ctf< @BwB[B zG~wuXb+VP:4 Z̿zSt+O*R!Vgнt/&ErBT*+úUϟIHHH  H}ĚԩS2dmΊ;zXFT)x;qaѴ\IR2A$@$@$``g}&  TO~D'ضB5QA^j(76>]:)?ȸr:V֑ @| $OIHHh Z勾] ";K`ʤܸN|G۱,Bxf?3i2et.Նp);Hdh֒%sX    !p-=zZΝ;eNl M~[{ AY`\vM}͛'3g Z9n޼)cǎ/r}~ұcG¥bŊJoߖlCqy߸]s]pA^}U4ٳg|ja(4`åtU.]5gTG>wm"֓ @`ΦDśb GB$@Dą Y~=qV- KT|TC Dh}~Iyp %H9g~}'IEܵ`񭗛 UF    E <<\rxof͚ڵknAɒ%ʕ+oXXdĻB̳>DUVO?mݻuֆ XwlٲK{s~'ѣnںuyl^֬Y&q~``)SF=e2i$-C|[pS_L+}'Obm͓$@)'ؔD޸8 8 {@ c:UuELr;fΜiU9im K|vZhIe#XGJ͚5ta%DY;s挴lRcˬغN ֑ @)Hy$@$@$@$@)@>}W~w9~ rAlU̙#=N:jY 28s99ZEZqvČ$@$_KIH -˂5[$,"Rˍ_ti%)-f'B$kZT*]T}M8uu*q" ڵk'OٷoI駟Z Bg+Zl@ӛW^]F%NR/ jN 6wD20vءо}{-Lmf׮]ٽ{~*UdJ@C3;w_]y!!_QBv֐… ̆ʕ+XU ,hKz<(/^LE%TW:=>wܑ'ߖ7oʐ!CT_׃Vɒ%1gx;bv l40S=" iۀ=% K5\8y2t) x4_Δa/w$`.HHH\|Y*U$?,^ؼ˗K/$ٳg0s}DW\Q^Ph1O?d #w=ٲe3Sf͚%&L`wdÆ oqƙz8Cσz nvΝ;'JM ´ܸqC˧!͛W?^ gH|=СCe{ᄈ0 ,00PN1ŘsaQ TOL̓ܢ2q}ɔ)DGG[tˆf1paܗZC~)___ s<2)֣+ jJ>}5sLɄP8BH~9\BݻW*_gc)z͛3<֘bŊCjLt2qoKp㰟 X}^N(rBgO6{OH A PlJP4F$@$@H]mNYDF=^$_niliPO2;v4z[Ri1ɍ|J?b9  @H@8G/͛7 *g}&B$gKPPj+Y\IOd-6Qe^lݺ5o7:گdɒҩS'Y`p~i۶CS3-nݺ9O-r ߼y.]:c8wk]9 B[|ߙܷj$φ-$CcIH&t#D~gl=tR?x|J_JUw;7z!a/ \C   pDrʂpt&Ѓ@1C/~~~JfͤC*:A^qOÆ סVZq]Eϫ&MXۻ^r3UZUPo!,zH<5j:u*3{[?.~(?L4I._raehƌJ4kܸqKE~^z\^qv8a9p曱B6UOn Cυ'-l.cgj= 2wl.8H&[ ,$`mc 8C KM/?v88N];wٙC$@$@$@$@i?`tShh >>>_~łQppi&-E 6ͤ2۷XҥKպ5&͛7->ܤ.CYԻ̦cǎ&-I h;vIvݶńڅz~q]cn9sLnmڴQm2e2iy,q:Tn]S|Lg841S LZ(cI aho߅J; g{nnFZ,v׏~ #jLZin&Mhv-U'H} qHm5,$@$@$Pcԅ2xK4QANKNhHHHHR5S{{)\ӳgO޽^2GCjՌUN˅ b_cǎ*~aG2Do{DΨO>DãJ-b=(h‘ [5֬~k///A%x!U8EM|Zuhۚ5ka'O/EEyo+xa}x)mqiӦ:Th̚5܆p])?̞=[5W8y}DHp^.+:e6mfd! $s,pI#WKIe{j)^2JڕmZ*Xrs @J"aRŋRT)yw孷ފVC݈=_\mxGDŽ9lI .۷oWbi\}M={IlnpL?%~(6%4<)Ji@eՖrgב*דo֥I@4 $!%Kȸqha0ԯ__oү kH2eΌG  q6BO!u x;䏭e~7RP\ҡIԯ'35sA$@$@$@$@$ ;wN{1<_eСA aHHH nV  n{dݮs_([4@j2PV P@IDAT $"֭[ٳg~a >!¹St#gz^b+B$@$@$7Mqa+ KdY k =yJ$@$@$@$@$fͪ۷{*Pի/={Ȝ9sK;z<00PJ.m>I ȕX/1,XKKyhHHR:lJw0)y4O$ct.9~>]:iPO6%% s0$@$@$@$@$@IE ,,L&L ȹx^xqiРtM,b.Gp-Z>RLqy4'     p@,X ;wi-6s̑ݻ.BIylٲ)#%/)Yr. !))6y3q+Yy =ҺAM[D$UCg.hͭ) w(G )xy5ɟH{bSPP.\8^bSe˖-lo}Fck5 8C? ؉oы/T<~Ǯ8RlJ7[K=2ɦdՖ}xs 乀*Ҫ^ )3Mp&IHHHHH/6 *˖-[&❰sbIB$@MbG.HG Yu\8.O/i{j;~p4 $20܋ȹ`࡚H>_ilmiPO2OڤM$@$@$@$@$@$@.9 C'_-?lRΟ?/7| _|Ŭ>svZ?^zJ7nL0A>cϜc) {0An*B1ry֭TTI}]5kjJn eСC=zv5?oUuԑ+Wln۶M6m$O?;IR1\2IRlJ.:/#\M'/\%_ vtөV<2ѣGN+x"FȦ^:M>95A*cw (;in|-գUcWOGGVg c6l M4BC 1Opy~~~r5Yza7ÇX׮][BBBz <}A/#cqf}ΌwP/ܹszx1˗Oc ŋ۷O+WZ0WRiӦn:sO-V-"G:Wu>Ya1E-o BzəcQ*AUGS6F'ɁSūr=$L}Mq/Jd"5JJZriwI$@$@$@$@$@$c BI``G >|;V(h?LA///dϝoz˖-{͘1 m^ <ϟo>Ur^GeQzܜ-{>i()T2OH!C"ۧTJKFj"T ЈHzGnk"m8qW´6|.\i&R5!J \<9)/)桱 D "2Jޓ;?Uvks7JX}{˸P2 BZja!      #Po(E_~YMvզ 5 ssB>Pt/(fmLLExG'N!ɚqqdsHG FF6C$*C'BXS:5+JӳYG$@$@$@$@$@$4.Ν;kEfCA(Y_ٴxIwʦ-%TW&Ⱦ@fxfl /S%72*)adOΊzjU+CI諤!^WLՉ#ׁ'0:8ڞF"}G6(W^#ka.cڬE@@@ wrUo߮UK|K.$}Qu SO)W5\c7eׯ6nܨF콌dMcS/zrR$Yt]w^5o<4Wch]5_dw5|pUnH9_xug(Is1_Vw}{Tmu(W0|f'p#<:wd8ǫo$d{>{e}zm۪O>$M)oݺud9݌-_<>HhѢHeT˖YfM\wʛ?HBmWFIIrtQJTթI I$L&$t`^'$Ą     P6AdS?4{ 54`jSipnJ1!    C (DZ4K%gݮgB@@@@@&bG $j_fhԍKDEc@@@@@$JQuD@@@@@X{6qt'ڇ     @!8C@@@@@(MKz     ]dS!      P8$ '@@@@@ȻɦC@@@@@@pH6N,       wMy'g      @l*X@@@@@@ $N@@@@@@ T8'      @H6坜"     #@pbIO@@@@@@ l;9;D@@@@@ GdSĒ      y ٔwrv     ɦ‰%=A@@@@@.@)@@@@@(MKz     ]dS!      P8$ '@@@@@Ȼ@N$͎ĕQ     H]}n$3H,]0     @}WBs@@@@@@0 l Sh+      0M A@@@@@$@)LѢ      @H6, 4@@@@@ɦ0E"      @@@@@@ L$-ڊ     LdSBs@@@@@@0 l Sh+      0M A@@@@@$@)LѢ      @H6, 4@@@@@ɦ0E"      @@@@@@ L$-ڊ     LdSBs@@@@@@0 l Sh+      0M A@@@@@$@)LѢ      @H6, 4@@@@@ɦ0E"      @@@@@@ L$-ڊ     LdSBs@@@@@@0 l Sh+      0M A@@@@@$@)LѢ      @H6, 4@@@@@ɦ0E"      @@@@@@ L$-ڊ     LdSBs@@@@@@0 l Sh+      0M A@@@@@$@)LѢ      @6ٴb 5dհaCUn]5h j*_|ԟ:u:tjԨP@@@@@D(M+WTݻwW[nUWھ}:պu<9FK/pBK_S?     FSi6_jvڦ ۶mS-[Tr>}znFG7,f#ll'}#     @~]ٴl25sL5pHIYfMu9稧zJpw&uTment^b%k91M&rb%k91M&rb%k91M&rb%k91M&rb%k91M&rbElzML &ԻwosO?^w8@@@@@@< ]W_5[c/~az뭸u~mc@@@@@ȧ@%VZe|5jܰaCSdɒu~mc@@@@@ȧ@%;+hrO5j0EׯwY\׏i       @J=qe˫{})ЄCQRgIwnW6B+vmdij4We]bZv31͕lm}LLs%[v%eg=\ɖvij4We]bZv31͕lm7(1-+*Wl(gv)_~)J@@@@@@ El[ܾ}{;L١.6r]?m#     (d1c|7lqFSֱcǸu~mc@@@@@ȧ@|,֭zҥKU-bb ,uRM~ښu2#Sa Š(q(q(q(q(q^LУK6 8PtMjN TrԀb ~es9ѽ}     (']>[{/P5jԈlK.ꨣR3f̈%\׏nLahG@@@@@<=0CN # [y6!K 3=8ϖ}89&9Mlȶpܹ ?Ӕ+WylLYoru\{n0#~bt4iviN09_s;r x4Lp6oLݭH#γn,2=W^TZy'_~9 .LhγIiR^7~7_1!V&&VB`/_+$?Yri&{u*T`>]m; & 1mӦM÷gQ+HGtϚu{z駟tI4Iq6wnο8/QYHp3=8+g_1-ꪫ̏4rLte}r1[qmˣt-W~;;ɏZ}-2v#Lݒt1<+r:sك5g[o5qw6?=wOg"ޗK{\{L7ܽ%a9@o'Q(?ONnݜ}ŴKL͛ǔ>wδiL<%LV_6 =ƽYE<XyS~5`RJμyܛk\սgϞUڵkǭ<GȂwgt~II ȗ!^^Ox1Bm3O ],j3bĈ _~f*.=d=98Zۼ_s1u"]8ϺJoLkk=d^\x'Yy6Bit~c}#Qg  碋.2_vm10leU: бC=tS_=]{n:nЗ+'Є T׮]ىm)S)wzCSvgƭ<GȂL;γ gF=&9J1F^-ZԦLyORB1J$flR +rJܖz-|TO?td]ib98kƯߘF7K8F~ދߘ{aGq ?[n513뤎29幜G~cj[5FgXiͱ賎 ) r6;q?H^7~7qP' B#wߙ >/W3gΜH9^#? vw]xN˖-KX8Mb% U?#^[^='Ѱ:y6N~erqo-lm%;&9'yIҿqi/r/qÅgr翷G1r]n9k&X\ ],콂})qFsywp`MqN˗QdO8f'1S/z:ﻝ8ZK{\{d=I>0!Pbfm'Nz쩺w>5kTN ]v)=^jذ:CN8ᄃ ̙3MdꬳRFf(VZ!OBݿBjo[թS'﫥'J_٤q]<*398<,yAcspCtb$ZJ\R=3jȐ!J9fL [o| fT8 GytO5j0Eׯw[N;q\Y)HfILĈlV§i䣏>X}_iS&_yJdoL$F2P!/v~O?c*#EIj_DO᜗_$yߕxʯ~pvH[80҉bGEG5Ľ}100ݖ!hWZNvL|iٳ='T{qKX2IdNwLrN&t1n %ԣGLj|dU U;qB:ۘ:)ݔxN.4q'WH?YfΔ)S?Nݺu#_ȰzLHw0RO>P~:+u?`{%vo6lZVsqkh2YDMwLrN߲t1JkΝzTsGLNȽ\}M ],Uf9:=H]C)98Z%3i1FH2)qZ':}#Q}MT({bW_ t;i\bC:SNM5!K( fz Gi+=l&M4~r23Hw?wW^y[ޣ'n2{8Ϧ)u~;γe#?{M>Vcs[,bE/yoUVc>$fr&(FevoebѴiSsm۶-nry܋6ٔxLte~bI8ϖ.~i+^xHUγgJ{\{NհD1uO/$P'Po((sɓ˼-4 3{Lz}l/<+EZ.]?餓̇6/WS<2flsqUd6y~ŊQP&>N6qM&S~;{ {},۞ml19؋dxQ01/瘷1wb[kY..2Y|yFL֝{q n1N(Hg.kll=>YQ|^eO~be~=昖jՌgSy[W¾`d1=X#{utCt@nF27-]-/O6;ꨣbک8QzX=SƬc!]v5 WuT>ULTbߡCQ>?4ZmgmzLr.yQΛ7Ϭ #'13D1tgxdo_`ffq$ ,Peq.ꞷ.e<&b.hmEtɲL|5 tۍEKmD?.ɤV^8pd 2HS ~̣ iF^iQ!oөS'g˖-1 !C˚cVJP4ڎ{ub֬Y}xq(P58#ivtw:%%%[o]|@'N߾}0&quo9ǝ;x=/ycspټF(Y w_o;'p#S61@Eo1u'%guӸqc}ߦc=6z8޽_O _s1M,Fgie,l=Ә~73l.;ږs=H{w{?d",`S^2cǎ:,C@7DSN GgheJ۔XH;+Wv/':-`Wn)7l۶#a w}~>}8K,qv+NڵcEв;:7/v۷;k׮u$,'γn`.g<[>Q6mC=ѿvy-6䋮38ÑXlm\ ru\'o)k x<_lҤBZȽHjSGNم=Q 0fb'v,FggS]qoL3ypwd[~B(@w)6Iq@NwEmok׮I>%8k{X~ :zhPI4t{d)ϓI1XBsVZELγdW^YqݽV~펼WTɑ?psq^~ -1r㬌4F.l\/}͸rzk~LիW[6lhFL2vr@^c%by6ZS˖ƴgϞh`С3y֋R:6G^4Ȃn             M@@@@@@2 ٔ1OD@@@@@ k@@@@@@ cMD@@@@@@M@@@@@@2 ٔ1OD@@@@@ k@@@@@@ cMD@@@@@@M@@@@@@2 ٔ1OD@@@@@ k@@@@@@ cMD@@@@@@M@@@@@@2 ٔ1OD@@@@@ k@@@@@@ cMD@@@@@@M@@@@@@2 ٔ1OD@@/%%%J5o\mڴ)SlǔO%KI&xO͛ե^4i*WڴiLhyysUgώ{   P$7@@HIVRC QK5k֨ARwʕIcEԸqԢE򱻜cϞ=SOUS_|z'ԏ?O 6'F%n;wTK.U7|Zxݻ5jr'R@@(^Oz  @^~'UZ5믿\-lǟ}j׮I45k,YKL42c= nݪjժNQ5jHYr)jΜ9ꡇR#FH=*   @a l*;@@# C5jH_^=N6ڽ{*_|:,vdS̙3}!U%t'N: 3 @@(@)AI  $/$IѳgOUJ﫣>:aWnP;. ¦M*Џi~o߾]U^iǎ1MB@@| pϦ|j/@@\{jj۶m&)7nNP2U\9ec   NMF@@ y睧/^l##r]ߖ٫p:ĉ͕Sͼ7O>f(?"Gy䑪jժNS6l{/СCU T:u5\vWO dȺ=zIS|IL%K[oUiFݻW]{~J}l\a$Wa{bsNS.`):t0^Ͷ=b~&Mɰ}?]\f馛T-u]vU#G4-1/ullnG@@B+Q`B@@r.?4East‘;#RngJ٢EL]wNr$,ɣHQw}WQ9_|)?3!C8sU?ΰaLm"Ow:?}Us2rt#B IDAT(RWf[Nf͜ٳg;?yN^=tI" g祗^rtܹsN &83f~'lw=!nEd;礓N2>}قm󫯾jxW;֭slzf7pCL˽=<&6˖-szmԑܧ7  U৽v#  @($y=kvʕ+ѫb+%?o޼lC֭_nWB;vld }EIEvgyӿ5kFׯ_<_vy}ڶ  @XFObB@@ uQjڴij߾}jJ'N2읝?p;;ȼNҘyPg#d(@}Q(p}2$ 'C2lL +(E㎋}4`2\2˔oYWC kܸq]vjnl6]_Y߫1cD!3&3NxE뤒y2M2f^t0=/uΙA@@ %% ii6  H@>~}>:կԜ9sTJL]W/Si%*vd+W4{{&+e6%vZO?{%SzM6EUX1KK.CUzxȺL9msVM! "I0^SWrnݺ)=Uf><  aʦ0F6#  P@7xH+rڳCG {5Q~UZ+~d ^A%I M~_KR(\ߟI}cǎwQ=zP^z:g>@@ dV{J@@@ rE̓O>ii?FلN*^u5w\wusR\;d*԰aøueYruLJ5ebަM3W=뮋M:gLX@@@ d$B0  @#wNڵk{NUZU]y pŦI~?4+fdͽdl$d CԳgO}r&4k֬lrzﻕN.#  MdS"F{@@vlժUI[ߡC%Wڵ+ar_6olgU.ث%AQV-5zh[BF$I5k֨-[I&{Wp \r%橲h )|ꩧT5\Svھ}ono#GoFP|SNUs:묳"mW%y1֭[#ׯVZKl3sf@@Ą  L@6l?39I/}e4x`S>j(G'}'gرL-駟FʿK[T|…>,RGeF_ueM0Y~stWa9zXmv)SbFsɒ%1-\~f]vu>#gΝ2̴ɽٶmDzem{<箻rtR+O 0 ~yׇ{j.ի# DsMfǏlK}Fv   !(v?@@@Ȱc)jO3gN6nܨ.2%è5h@1B3FuI]tEUV9}-_jvZ%CItBm6vaڴif6Nb^%NyI'N6j;w6ӧO]nGsf޽{\Eꪫ2W:E{5I/J'$UFkgܸqJNi#  a n@@@@@@ ܳ)A       @XH65r@@@@@ɦ&      a n@@@@@@ $     UdSX#G@@@@@@l @h      VMaF@@@@@ @)A       @X?yIENDB`CGNS-3.4.0/release_docs/figs/cgp_open.png000066400000000000000000002244231343724673500201550ustar00rootroot00000000000000PNG  IHDRD/iCCPICC Profile(c``2ptqre``+) rwRR` ``\\yy | 2 U +'300%@q9@HR6. r!+ v.z H}:b'A2 vIj^ʢ#ǔTbϼĒZ@! A!ahii "q(v!( cd2f` G1G)I/15C}}sïPo%iTXtXML:com.adobe.xmp 1250 732 @IDATxE7/,lʙAԓ;x?SAπ(T<#('`x(r"w¢]6W=ggo>|WU}_M;+e ~HHHHHHHܡ       f SHHHHHH\DaAUHHHHHH T9 0Le      p.rU!     `>@$@$@$@$@$@$" S] B$@$@$@$@$@$0uʕ3f8묳:vg;wڵkCjժ}nٲeK,>#֬Yc ;%c4 25<RSN9?oKJJ SYY{s1s8%+dHHHHHHqMl+^~EEEgqƓO>YS25]       !L7o(`dѿ>*) IHHHHH'07=zt{o\*) IHHHHH'0Umk[ֲe2dw+$     0 !L]nLzTӰB\ꝁ1`HHHHHHq~7''ImaajVVn#) IHHHHHL~MmѢLTЀLS2&;IHHHHH'0M6R]]mپ};.۶m21`HHHHHHq~Sw.ׯ7lذ￿tJli       !Lӧ,_ܤrJ\[:$@$@$@$@$@$@N|.]Fiޚ8qbvvիUS2f!{5 @z針~SO=?949蠃czJ{)]avBYK89ʱnI#Rt?%V?ySBj~JЭ7&b?zK@eԩ+ Zj͛1f͚{sJƬi      g x#L-((߿-[Z(t [իW=ⲴsJƬi      g H,q@8޽Ezw4[#-ջ cXJj{=_NNMz?$@$@$@$@$@$@6 0L b$@$@$@$@$@$@ 05 M Sm @*0LMeA$@$@$@qXz~^^{j 袋{;\p{ ;l„ +W|7Bנs >DgK_ b-&qd6]\'qC~n馯"K-9\0d΃>h{k,;vT5?[n5/u~^^Τp}֪#N;ߺie˖AgϞXkv\8Jnp>V&R@r,[pIL39}&S\Z:[ڵkwJH>;++ *++|KUZs]`AEEEuu5䯿z}ΟYƍǍz#ˏ=ZIr-֭R:uYЮO>jQ_!C@I] n6U4߼y~Fu(~z$B}](SNQ¥d׮]Q#!ȁpSSN8u%W_}O?*bcƌQ| uo.M56m4qD%.w}TJ ·2iӦm>2ƛS;ER,N堆mMHKsTJL2ˑ)3 _~G1[h$5U㊻첋͟??Xn2!s >sLH֕>1n!rFPסC~őR@LE?_}Qol٢呈Pw)5C}";V˭%K%3bQF#-< r1sfΜs5-{챝v Y[4B*JR)w+.04췥{"H'9b^+Qz"  BÄK.bȑ#Kcƌ|}{A@_x㍸|饗t%SO.QJ!CMUpΜ9j+c]1E'LTbGTg:3uJ( X/1`[XX:|er#Øf>C- ҥK;GU [Cxj8nWIRݯaRͷYdYY_ k; '  pʶhbڵfVG2`6`34~L4 O=pEoZ?B?^LxkG#y,1s"fqiLF>-E9#{W- M Smk3?nvQQuZCܯa Q?Q*"BIuWٳc.rc):cXJz)KC=܃qH5F%0c\*Rҙ UG2fӘi/bM )1+R!brA,K@ –R|ɐNebUa*BLyϛk֬̌:R֭[ qjt4&H `&̱E P[Z:$$X9k1VtCϼW5os54ѳN:blcVrMl?Łf;;wF=Q;>l߾}frq~[/2E=PO/to)l 1}Lp駟'˭wy9~%?%6C=4@4/ FNnરӥ^ɽ[ 5he^tATf~pf).M6wZ^ Ly4 I?pĈe&/NDqZ2 2# R@vv6&*]'vvoe_BX:%0`e&Bԁ}P~jymu]x8oByT~ycU(H\/:"?Hc_f0p۷I>\=!Q31^l!6 JX (+̂:Ʌ :RW oXv,W脦J"_,vbb}G|?0ZLXàwߍclaBAYUԻ"p-p KC.8< ԬV #EPJmǎx1tBYہ'r -_!^a6zV># quCGЎdsAm(-vմFXVHHH A_L:Ӭ8p rRs; i`@3?tNԄ%Yx0i-씋к ɟVU%8bA&B%Ɓ@ȿ. Z"D>BK~KuLH8yTe'd>ʪ| !8CCqՊ (]K=:_%0, ;Up-5ؼ)*`%!AV@>NTHDF`:I(|.d3s>gp9Bm:GΪ" If%8R@UvvDv/JCxQxǤ@#ȸ疃ZZJOi155ˑlܼwZr,EcKV?J u۶mywZyu8 ~߫,nDH࣋ :c5Lc^1`<ּ6ŪTO2E cM ӐewuW# yWgIxIs"'TȒX2bW3c5(Y6XB>6+P8s f$"p@0 5z[*Q_sK&.o#\G)X@<^tqP/Zn.`aڴi< z5#M{ pT/ܨYtcKM+R5 ?T:r#\8:M YQw RS[2_M,jR.B\b̴-mP -b ^14fnNjW!lCN '5 ron<j0dÄF~Pshpz,j(r+?,93 Q59ŖN)Fb8׺{אEonc/. ۪+eyMC=E0K\ӧG~d%v2qf)Ώy'"j1dYXx '`*[!2G=}GI$~*k,1,Fը5*{(Xƌ_j`NC KyN {Wp#vڲ#-NASF:ӌ2_IWJl<^lVR !%W^ )S&fLs'0a*>3g}) -j٭r+ S)I$@$@'гgOG|bo2|0ZY45o}̖Dq5hT ۚǢ`!G>l / 6CtpE~뭷giM _t) @=p\ FoذNCmP*~w6RUCds7p""*Ɯd%V$iVCcG]߱1tV,9XdL˜Un yVw!31_Qu[F@>zCfN8&8&٧+`6:%tPs(;FEv/T)Uq% S$0a93 +R|+R;T,įRځ8;<#Zyp ؁FTƠ-,"~ 4z@+oY$B[؝=ï|D0 aͬ!4"CէOKYLhॏyɮKKom-SBvLKl b%*3$j$[Vfx=&{*r_#X٨WD W[uvF +]+bT^U F\y-'; ##3!(x"-]Ts[a;`9b {G]xbԩGjYwSDsوGI4+$\[OpbWU)pSUrŧ7[][N=FW\q  1.8b 箽Z`zY4PAA61rppj%ԚeHUf%>na#Usp٢J#z' ,;ꨣ1~HnE'860?<fEmNJ_a sbPðf)ilAٹtRG4pi -^@j8<0ޑ)xj 85"L,maޑ#Ge@YMz/%jW}D)l#9â/Rm ΉxQCV[>!,p:8i}>63l6XzZuWՖ.G !  p]y8#b`"_#  10@eobV@Wzl^Ν;?1 b>0&l}ol0Ps \$8ʒv0S5c]E`6DuLV*bS؅Emb l Je[LH2V b_"G|؈+d0WH4JO ] c*FHHA[`U `#Y0dfZVj8mi  HWt0>.G:l#    O ] צz^99ʱPr,[x$@$@$PTgmHDDr,EהcKV .N/)) &`+7x#.T_LVw-ZRr&TKmNR!馛+<.dDp9> kƒ߱cGU-n݊[L\TRMZsB6jNy*\{ rkbT    6Dqx{ |]徳f駟֮]OtsϽLaQG裏b+=&xZ^XqA ;Y^CCdk"g}6hٲ%ğGq0]-a')akvgb[XܔGAӫD>=#>?StQX׮]!yGlDž4vN8iUmF˫!G3F|7ढ¿/| M6M8Q#Kwoep7?n…s_z?@&!JHHHH &_~e۶mqY m$aWi/.Tۿ駸e˄A~zl*+} c*ھ};:Ո##swU:G'{#bGeD"lٲX Q'X ;^Xn-Y,ԃQpx[A`o 3g̙:'\sJi?3W;TUZ鎑b'ˑa:!9ʱ]Sr,[}̥q@ \rȑ#dƌ|}{^nF\V-`I}N6}z,A^~e0B=PO/toƎ(lC 1XYYe&~iOH0Ғ­C=4@4\饗'喲B ?Znt.nѤh9}b-Dmڴv˗/יi+bT\KFN`](0I8wq@P60`vT)znµ^/ е_2sU4bne,z2A ^Q5q=+R 9ʱnMq0Aڈ#0]O^b6+07 NXA lT2~>~-|K˄X]gB,D[3뵼Ͷ.w!4!8鹦P^)>rDN*SnpBj׮Np۷I>\=!Q31^pl!Cj$H*a%0wT2 4: J?̰\!$ncJ+,v֥0ck_(A'Äyw D/#Z@"\kv6Fرc1/8Ԡϼѵm sl~Fz #h+|Gj.kFݜpP[s*MŻlmˑGbMWrc)cXJ!TA3?ubkY3p@` Qu 6L 7 : |蜨 5(C$Hu%T5.~@"(f{"XU3WP9j _@L#D>BK~K,L [OzB棬١H#,7\*+T蜐 0AߵԣU CS RKB *yY8lU>dFW tu>\D竜w!ܜ\-~|+\%%PUn)Z73-96Gh`7FΝ7{n9-ŮSSh $W^{dK|Bݨ: EjFX@999炘24c| ." Qb_L WÌV DMQeD>IoF%NELv,{J'cƔ)S,Dt0CCjuZ95Z렶Lf)o/ A=zh509+Q1=R`i5tt>QYu  .] i2v.1_̴-m2o[~a"TK]DM$d- lĪs"'tu6I$b-TU1pX Jwy'(a7id쮻|!L5~BBU$d+1L Svfse1Kfv*fE8s>üt;NDh3bj\\jT_s3'tƴaGN]XV5yJ?;ՄauR   |36™RpgQj`-\puԼS23-iK[*v|f*bؚZCZ7hR*]BE&-5<N,j>bA1m4<j0dALF~Pshpz,j[C^"Njdq 'J 81fJcoL8jƵ6 ,&DiwxWw%}Xራ?74X 8zcXN(X9ҭ{Zƀ G"cM\b Ab<3$ F\4X iaXIjƩP!hiii1R#*fl&:u3NcC 6i+歐i]mMęؽ'@Ɛea1y ]!B吕X2ЬY K./^%`%FѨFUx̘4k~l腥SN+8mESTT]Ǜ# nG_#QU@Y ee~nT8ԃ[v~s8ܞo 4w8K?ӭt þO>QGeCLũ3fBŏ{ 귗YDb!13#1ނz0[t)2<cF5WC&\\w%j%Tfc$St\O>]Xꦊ6еR1/7nG" `"(fPbf>6I63wի 쭥sT"B%`鍖.UM)N\ a_XƾLpmݨ!`ƺROK7Sp'WExՅJ`ݴc^;} P?l_+`)Nο1P]b.rc)zcXJz#1քP1 N@cKu#<0 /`N@R[tB aZipq '"B9s&NxjZH`eÐ z1b5%6RY&b HqzgGL`)={E Rja 53-RXp&kNs^*VXx {&#淴 Uo[qԉ'bFTWD|Zo lR[Xq}GŸ)4b*WEq| ȘEl5kCQD\][Ȼ\W  ਗ;!sj'2:eTq=GMkp ^W^ywsA4ݐ.]>,w1ebR[pNLZUmْ\-9$  C?"E+,qyWUÕXKZ`zY4Ϋ@A3 SqL%КeHUf%=na(Usp=Б#GMiD8LƖ%BeGyBج%Ua̅^y?̌ IZDDtiJa?'-h"n!Z ^UGB+Hb ;B/^>Hfg0?7<fEmNJ_lI8:TaY~][av.]k!5uzBme lo!POGr"(8M-.*^4) j"X㵈Q (ŰG%.2p 7ܠ$W ks}Ujɒ%^jeK楃{ZU~vՐM)H3rr6R>cK5+R\wy{x{i1Jl" F1?ob@?-ؼ;w.0O~OU 6X A492[W5ffO"1 Z҈d0*O%L4Q#ӫW/(FǸ!څ昗ÏfJFMlڄ!tcC CnYc//ŌkУMu:HO]Cc(X9ҭ^{Ƭ/m+q;3~cZlJc9N4cn lCy#. 8B/DUȪؐřI\pHm`u$@$@$@$@$@ +hG$@$@$@$@$@$& S B$@$@$@$@$@ 0L-rrc)zcXJzjCcv`'Bzg64[m@] S풢@n,9>cK]+R՗av`a9MBaZdHHHHH@[O0ՓnsҳfrAr,EϑcK<S ;p955S ݚbnkSofo;l#    O ] GSw=      7`&oP     Oa./ &[{+RB9ʱnՆ6 yOnlhLڀD6.)r隽mS=Ű[׮]U1Vorc)iܺǍV7{'nָѹ`t9a3X xn8W|#     pntY`MHY9ʱBr,[zҹ0;[=^tkBZnug<TO JA X91Vtkj)n8Sݚ)nnM1p7ǵ7]6Ց '膣 0Lu7 '0U|-rrc)zcXJzjCcv`'Bzg64[m@]\jMt޶HHHHHb"P[VVLiᇆ%sgߧw~ZOtE79~H[HHHHHHYQ&OYWkjژ4Tf[$@$@$@$@$@#RSc "F}M-0TٳPcK{+R՗ev`a[phOEfW]ݣ?Tctc'cX X9ҭ <[ؽI@35x-*ʭu_4J{2]6Ց "P9i2㫡*/] צ    4%li`?ȢիWw5E9ʱ}Jr,[LJIJ}V[حHlkS%zg͚H=Dr,EǓcKVOXH{\Êok?{ݑ Ul[[MWtÝ~SbS$@$@$@$ .~h.];w0prJv1klv.BS)FY0m>$@$@$@$7<`^O|~_b%jvN-;6]Ё1:ώu߸6%Çj,X9/1Vtk9Wcv{l+@։8a?`)1b$ _ T"ճfms!@IDATӔə TƢ`/J @SSŘ[xfbh/`:lHHHHH55zy99ŷ.Wؗqm/ݚ fϞfцcX%X9ҭxd:;@Y @DM7nucVor45p]unmicX 1VtM7g TQ4q iۍCi(/e?۽ S=ݯ_+* +R9ʱnMC1w2I]4zwdϺI Eo¦-[r{l(x;87tY7 A a@;L@: l{ōBc? ct:cG S*zjrc)zcXJx@ v`8)z]/hڰ!h.ٴySFcc,uP&*PWWpm٪ 0LK 0k,9$+R^9ʱncnymj7+-BzckuUN{V"hl[d45]{NS&eTUajqm0;gQ51Vsrc)i\Džͽ֮R߿ jVIISeeҥFfn9{ۣGn}rw*,w Gmt5o+tWi:R-+qTG0    " Z,KÏmXuKS֖-?]cVqqsԺ9{핷~ٗ335& S|$wIc˚IHHH~E P]6͗999ݺ_@ֆ+W_a-k7C}{zO>{gL@W9qݺl]D歴Դ`C&LlcKy9ʱnH;^ݼ&E Ǡ(bWM .YgcomNK>ۿ|cZ 9;Qb xZw=M]XϛW GSp̑MfDӧK/2Fugwh;-RQr,EאcKVy]H@wԴ8^&/YE#Gد~9~.;wڵkCzkժU}ݲeŋ,YR]]}GY#cKN/X@rc)zcXJn{ٺϗdwXtՕ4Gn}%h;U>F ^P|u[oU=0y{a+BV0n*f[I"д~Æg FjӦSs&g4Uo+A[RR9s#GDB#''cX+X9ҭ|&{ݭ8aEͣ| N- 7^ mu, \öQR[VV bH EQSApa#mg?VΪG?ajdF+Vx嗇bTqӦMbG&r+2Drc)zcXJuV5 g`KՖ6[}NJ4<>jp 1[xi0Wj՚w< S5$j}oŗn[mN)hM8B@J:o<:cLjX:uԧ~C8$@$@$@$@G)0>{nYh\/pvoÈ: gOx"1w^{[ d4Ǩ8}{Ԗ-r45{M3d`/ VF)ao ;zUjG,4 @c6q޹j!hI.-߿EJC 6,e_~Ul9>']̂fօ9#LU# SSx'mu9%coXH[B)2l@ǎMR\.[Leڑ1 Ocrc)zcXJ]nڏ>j۶kkEs,UVC~[:~ǚe:}DbLrn\ݼRvRᇁ햪x$\[yD7S<|ޜ$ɬVhuQM;ۑ1 OO>]9ʱWr,[}Xf[۶U:p=fz ;jg 8h%aŷU'o9Ѹq}uK@ PWgNMjj?Xq_cwU,^RFS7o X'oVu{^ؑ13M$@$@$@$@]׬̂Agk&v_ECv鵫{wPY~ 6rWvdݺuC@r,EcKV_>ف=_vN뵞S)o՗;3O{rN^^M6aOnVkkjZ`=tXs>pfV!d)aj>}˗.\r%.-,cׯrc)zcXJ-윔_k+Vs{ĶV}'0H˪M}14ݼcJƏ㦾RԁgoO?4;;NSvdҙ?J1HHHNUb礼(8^%#Xګm},5o`1M~lqmslwC/vފK֖K S0`Μ9UUUO?駟ޥKcGFFM> zyK縵cK+R5 ;va8,)?2-blѿ7^kдvkkp̶ghj*a7 8fo٧[w0N!r-'[. *s-/V=-]%wݙE+Mc-eHHHH'P5u b%B,+X!/,âo*.[xgntVK䦦orŦ ߝaD&L]VcX.&X9ҭ.{v:;3YKʕ[|"19Aҙ]qjaaO8jҥ≪۷o~d緙7Taj:t+R^9ʱncnA3xZ!X--pՙ;WW%>o0_{+=d˓N򗋴ڵI*rc)cXJ&Yفv5o-mGhc&NE#Gt\BV(ֺּ?=0s]*7N>sv߽+/tԧ`?;$   wN*fdVvQ捔oZ_p>6[‰5c[tRWK@~~_`5gԷ_sؘ26T9i.Lv3  S%x6 j.WfVŷv:VV;jG!X]cp*iFSSJHa5VM|oS$n] S4kޭ[4k+Rt9ʱnMs1uMuglXM{hJYY8{tϔn]}Kn)V8)ݳϴ8O)V͹Tȥ'hp9ʱ+9ʱnu0S81~n\ɨd\eE)'S0p`+xGviigmNBkTY[O?qݺGᕗtS$``j`2WE۲rc)zcXJzQF{v0`R][hsa ֒a6dXE}Xt Yuo8}Ag4-W?/Nѭ i֭ c5kVZMSrc)cXJfفN 7݄v /${]씠DevdQsZXX`Oxy_~!MM7ҼW ے]">ul5jTqK rc)cXJ⌧2v=l. w1d S%{?!'LPyOcK+RSOVʲ%kSOcf82{睋Z} 0{a}u^[VsnWw!_~1[7;(CT8 :4Β,&X91VtUf(I45"Ibj;w o/xz9X=omc=8l:ݓsJJ"  b !еkW;bcK3+R\ )$N%"e!sϝVMW[3,C?_1vV5vѢ:ݡG\]4LE\Kak]CHHHH =6m]XY99E7ݔ٢W`vOmyfWUUYZ!ݕ&5'n SF'!C cK{+R՗evT5itFCC TF gݠrNn -8k׌n$0Ս^N$@$@$@$^xvب g3 ZYXEp %y @z4UVV:mY:=JU++ POF9FxBÇ{BOGcK1+RՑ'*aNGԴaC~>-O99-iC@{!gC ӧWT.X91Vtk*)k8er룏a礒 S(:> 871j^{7|(PK,. S'׸yRHHH%-nhll^.QjRVN0ijv"kherod7. vNdqvii59$~ S#j8{lj+Rt9ʱnM/UMUUơl͝RM D!05 G[7A61Vrc)|v{׭}X駧96A$@Q 0L / ?1Vrc)j:pe[S<~|ƯeQ$@ 0n$@$@$@$7hhh5$VJ$@`;3A`rH1Vrc)2;pRݺ}޼ڏ>j۶&!VN$@1`. B`֬Y\=%X91Vt/skbX_|Yk5 @J?5jrc)zcXJ#?MjO#|JHHHH -7׷<(wQDyHRNajʑ &Ŕv1VcXJFyP8NydiStɨu @&PnC1^r,EcKV_>فwk`۶-7߂j&Y! $Naj еkW91Vrc)2;n`?ꅳR #: 4ԌcsFI@*R= ,HT X91Vtg( cjk wѥ)A$@i"05MlyykcX 1Vt݇؁tWo׼9?xԍV˪HHq SG*!CH15#Cr,EcKV_>فr+Q+F7TxȬv휪 @20LMUI$@$@$@" sܥ!  S0HHHE;'L/h  0LSScSӐZcKѯ+R Lu`viŸqSr# H*IʧOg~mcX 1Vt]>bNܑ5ᄋdxmHR@aj    H@]]vUWfwh%* Haj(N$@$@$@!P+swo}њ H'0Uzٳg]s+RtB9ʱnՎv(iʻc2rr‰1HFa<}u]VTr,EcKքvn8TnyH=,K$@)&05\~cL4K+R\r,[=쳙%couNԃa8C@$@$@$@i&PgO>Aq9);`$@`8C5,X@rc)zcXJl˭MM[n9ݺ*B! z4%) Sg'dyyrc)zcXJlǭsbiv΅WŎ{LxGSZ|05-( CrX,֭㩂eI1*1PWt&T Gaj82cf_Yzu׮]MK}cK]+R՗av`[qއ~/@?P͊V{ݹʷL{MX&]NT#.5?7g͚ERcX~#X9ҭx v`y7Tጜ3~Zc:0R`L~s8F8شMf b*3mǤWuWPO   l8sp:OoU[8jDnq`A[IWtT 7WE&A SMط:Է&X9rc)C;0[=ݼ$5?<ֱEa&u*ilaP09v9ʱn R#GN>豵ee8cSKZ~.]%K17[ 9;wZ mGѓnucJF[$@$@$@$,Q᭥E@eUdiSt[$ z6v-X m9ʱKr,[]tRw`P/a:P*򋮽&I+U|܇SЍЭ dm徵-09ʱNcK֠2|܁1,uzŒ_?S >"tk05ل}[!C|k[arc),X9ҭAO/?d5:uZFff19Ctkbg+1ʓ @*Tzky T׸ Լvofy/ H!0Us +Rt69ʱnuS4Du` *P[[1\^32];τ ^TL:ӭ1CajX倐cKEa՗+9ncQ>4#֬YR$@$@$@$c{FOofd`/~P2E݇T̰:lw{yo&Mh%SRR~߼ Z7Nj9b(E#VRUDz_]nkt=5UQ璨p+h2IiS?ěg"" 2[og2 pAX9JEaUɇr۶39SctJRڇǗa uM=K?lVDDn>sdHHH&,,̽.WYY˜$J71^H$ mوkzl-QbΝg1UC }吐#VR^9b(eX|,+؁]SGOO)5r'`v'5Ͱ:g 8qolVDDrr2ַ3{IiiQG+G)rQʰ*":p%ecONN[d(ʝz}]4Ӧ%7g~z[QQ4;V9b(ՇV%VrªN?T?_IQľeXCzԳ&͊p8x$@$@$@$;sH+B$ ihSF<-- ofEDTm֬{&$@$@$@$8Gޤ'sb3Nqײ4 #@z6=z'O͊~g2 &LAX9JEaUɇ*ϔ[ٺuڂQQJvK2}Nub3P6,Cͮ]fED߿o^xrQ+G e5:phB[tt͕EG@>\: kCOz7ވ7٬M6EFF=={Z~J$@$@$Ǟ=yY"1*rHNw6,>}׿~ ܷznHOOsL`&//g   eJKs** +BH!Ź#dʲI,Ẽ/?'=pΧ:z /QoA`Ŋr8+G>̰*V+͟@ΝQ]47();a~ʰ:ljBB?D||6mlذ!))={GVZy[СrQ*3J>JWV[BB…D%"E5H}Aub 0|n׮ݛoj ?bT(AX9Jz9b(eX}|Yu;pŷ[N?Gn3=[ ;[DA^U kc*k454Y? 377 ě:2! hFb:t)9b(E#VRUɇ%;ә7yj? : %BQd]Ԓ k#Ojֿ|re&Gr2^*dXRmQX炭}8 a uPm, u#TJ  hO?;5flÇ~ms%gNM*+Ԋ L~Q&l eT>73eFyT(dCIH ,hSÂ7!  P2Ή%O\# M !\5k+G)+G K:p3+&}zӗ^X@X*U k]~Zj?c~~~bbb۶m_kMJJ u,Z?&p\եƍsvZX9Jc刕aUQl\l{j(XNU :ljUU/SO=zԽYk^;vXbEjj)SM^iP՗z}9 #VRtW9b(eX|[W~+??Fd (o~{a2FVOgϞni˖-W]uըQ4k,66h[nOof~vP '  NUX;vWII˜$Jj$믿+r޼yRc/TQ* HHH*6|3&WUUW7Z0gnyəSS2Qj@y kpy6ٵ8ּW  T8{.#i❁{T+`IH t݃5 RIT81$uJI@ukeiư;4#6#C NT߯aI & G0êJNXͩ`k#[J[ "WK4QÁ˃G4ubzԉz>6;Ujgצ6MnsЌ]%!  ; +3p`n!gic4Q hº ܍s:͖ gfE\)NG%%ټklԾ6u͚5js:    *-ͽvgAAW'!h% PPV+V(09b(E刕aR!T8?VյKys"l6RC T(JlHM}7`S}єJoeB,:.GrQʰ*X6O.%$-\hKLT6Eyp(Թ)G)T尥ԿOLtJ0I:j(jQbݣ7:wQF_~ޠ+{-Zg2A$@$@$@p坺}$d )pHU.G)D%&MTTTnKqq12W#!|rUê^LaeX-M\8岏?-oK}8~`"J} %m.n֭[?3&Ldɒ]b#5\'  :>;6}EA߽‚9s KΜ鞯^ZRbGE nQ0`OѣGiiƍZ?3DfU`(HHH@Gst:ڣ AJ$@$#o6[nΘ1cx F=uTL%   5*+s'ɉyY)j   okS;n۶m]tINN:tҥKGFFZE$ f ESX9J䈕a5#4VՁ f=Yבӛb/M>~r0vv@IDAT(KTAڵ 4x>Դpi+G):r2ABC:p?V-Yjkt=5 0KR%֐Ŀ]o^i#VRD^X9JVi+ص;{/6|߇b G)kHjnذ/OJJR7olH[yS   )Waѩ񷻊&QҼRe$@$Xl7|s饗^Z;(U-fdd,\wbydgg+ȋ9b(E刕aGayӦ9ӧSOZ[n*ajE5Sy8fذa[i?qĕ+WLB/TJB'Lfo>  '"#{~Kؔ4X}r7FS{˱cǞwyv3|MzT oM$@$@$2"\Q" 2ق}/_ ~ʈ   \eeow>9I, ' h`4գ@$]brQ+G uӏ>VwQ]4;vGQf >lumEurl*L)^?9NKKKOOak%odB:t0aB$9b(EW#VR5D@c Q.y.%%wW@ Q ټmtw۷©qjɒ%z+gΜocj4i @֭'U^6__gvXHRt-6!`6uӦM-I_|ٮ;4#6#CD}wx8xZ| IMݺukVÃӦMCb'|R&2:t}Bh+G)r*Vx¹<{(iS܁]{84(uBA }8M Rr(A 6m<3EEE<ȺuV?طo݊"+G)"-G #əS!z(S#E };m,ozccMD }Dj5ERH%VÑm!%ITܳgOϿw>pR0j $@$@>3vm$tW -F(wm4KOLҢEΝ;{G>䓗_~9ltx#   @ձcQU<^z@Z P.111j^_{5L *+s'<7򲔩SLZ6HHh*鐀fb+G)r bY/rҁ SŦMӛb›@Pp(&\Ebb,h|@އo$G)@`6g8p`BB-{]>G~ KA@i4r2j뮻N8`8[o{\`y   @l@P\eew*.ěMR8F$ Y _||]l)//w/5]v-akwرaÆ]Hmlyw9b(E#VR!aȈlb]O[ А{ҁܶ-OUώ !H6~TR %.ȅTTSglْ  4qqqvGwyÆ ovk֬ҥK %pA6-#VR9b(V/!Vo Qkq %oY{Ĵ_ũGB>lz;(dQb3a0i+..~뭷p>ƍ?^TTԤI6m`uԨQ^{mttt 4\)H$Is]{M@o̠AwNh-_uU5<8"2Һ@ Q|2 '<]_k̩)Yfngm4pV '`9DԨo՟ 3k0c}MRG.nhNsT<|_DjSR#c|yQn)J!_zצnjmQ w%+ɻި㮿\>lo$Wjc1?no1ziO+l=r΄%Ir7dȱa$@$@$O'Ov91ݽzLݯl5ުC'Lp|+"UQ;q"9_}5vNR mcdX¤- A䈕DX9JU+R=a3gg?_uG_`iz*+rΝa2  s}Q{̀a֋<(E_%֐']vAi#VRD^X9J+V:9ahߞ[ =?ܴi#~5ˬQoܖp-)u3V}?g#{yQ"Jl^mnذaƌ]TTz.]G0`jFȟ+G)b+G><%O7ԟiכ_MKyjmg@Ugy|cU98|8*==];L5rrgk7ћMo.Ҳ2ex駟fddZcsj\m?0˯n׆;ʻw2v/}w/|.ϼ2捍[ͦ~ر 9f[Q/_.Gr+Ga-ym̐#k=W?OpF+V¯x]x?>ZW]0vE#{ZZڒŶ69>L ǰǍWI0'NoC]>ܾ}Xu.0Ӄ@L$@$,J=>lD?-x9kj-*Puęzfg_}}޽"۴U̅B7[毯>< C} /bC}kO$@0x[}֯_嗻7*++ 9GY݋1M$@$@$ 7ބG, F<=;ЄzZWjUǏb ^] !oIH@8o6,XFD]fK/_#硇ΎIHH t\/܋C z yu7ڶm/ j5#oΓ9؈8e,|K$@$okS{kgaݻz뭚G}Ǝ~J𛀨rQ/GooTct^W_R ? c~sm[sfHB:\^:xH֯~u#ۧ7}K&lH !Ufy=vocƌQH`aZ9b(E?#VRŠVg :qag'izf9~:) 㫵k?s6k]- ܴQ@X9J 54lSݿh{ G3HH%G{n_ؚ( pW=cϞW_**jԓ7 pCl8o{ @}r7֦n+=jm&!  P*5%sE=*x__=RvUWiiQ~Md}Xo##VR QbQ7zI왤 S߿7%*8xJrk#VRD\X9J+ χ) Z1~cdz~5'Z8Ɖ;Sw i _Ք/ br3wBokSUVyKU|*#ybz& (ZcO>Jfwu߯32]Q΢7߬K{jpmq PQhg}v-JX/׶m 0Z8e4#9SqgW|`y6hbcDudx  0fS[n϶k.*s޽{õ} !UΓ9?YȑrTC[מ̪*oGU^٦( K$@ x7|ݻL0˗#VRR9b(zXW\=jnrQ73qݿ=1 [BB5B/eف r"ԢӵCm!eiim݆;ϣ|̀8o]%! KN?DL-C/'YKWiF\KEn]8w^rԔL4Uj5? l! ܍l^fbү{&$@$@$@A'@Ϝ=ζb:m}6Xi%S&HH&ͦӯ\?9_1gwL Ih_yy{uYn⧄@L$@a&{t}}􉎎gKM1wǎSrֺ;(=+@Z+GrQjݰ -Fa,E>;G䈕!VXe;mڴQFA… y}y퐾6ڶm>f=F`&C,ICu+)GrQjݰJPjƐ}|، kb(i.cX# rQ-dѢE]vN:.^G!zͦq}݅^{ZK1bߨ+G):rZ4΂x hV߱UrQ/bW^)111999cJ1_a6wԩ'j7eϞ=ڟ2HHHG~NzpP/a1  ]v"//۷c@Pܴ:Ԟ={KZ#xiuL!:$D)d+G)êr}y*5e 6J +O@T#VR|C}0 n=tB,Vj S7o7.l,G`k #VRt9b(bXYX;lX-V޼дDu`9b(n|_~'OƞDmڴ+SRRpIfoߦM߿zBiTl6y{۶m?ϼ\Q^[ ;pS) BlHm;1Rb ¹jWJĪc,AǸynٲvRksΝmt홄I9i„ ǏצG-0鷨v:0HH|$Px c1   >}zƍ6mڿD=`;8p ISr8ҙ3gbl6uĉ{lJ&HHHKyfΔ[3k#  FD1)HFݎH ^p—0o9Wz!abo|E`֬Yr+G)zrZ+K/8Џǩ,G~_?{lo[nygLr{?CΎ 4 g6al;>o wƍsvZX9Jc刕BauTlӦV*3Ձ刕_.ӊ=z6 !իW/ibb m;kSQ?N< p'о}{j刕=VX9J-U%%q#/׿秨W,GrJ,bz+RNNݏŔ]=zĘPg5kx.\{xK.|K$@$@$ ePj;+YHH@ݝ~N҄øa^S> G%mm*9rGE %7am">?BrQ GV kႅC_g=ouPy|.)b5;i$Qk?MMHH7nw]:!=(V= z1"UYݵQݺ1,h<Du`9b(WɻXݻ~S^\\\1vڳgh|ْsPSlhZ̫W^[}رרEƍm'˓ @աG\tuTNṩ2w(tQ Hl߾=''YfXJn8 }z7oޜ;SS9_%\"Kq~7LIHH?/r8F_O@^E$@!o߾KM6]¸bt۶mEEEZkSSS1pvYhi9fn96u?_ުU+37:mF][o^!H#VR]X9JMVC%oUSKTX}yPr*dѢE8Ek׮J=~8aΛ7jAW%wSOyJ ϥs=oݺu 5Z!/_.D)d+G)êl}R}]Tǎen6Uڔ' R,3gٳQ~/-W5>>.|'o.]У;65\XXJX]Fnl;YHH t$ko??ԷS~Q5EURQwE`nݲ=(wshHHHQpVjDUUTzFca 098ToMJKK7 "sQ1W8;(ձ   p[6J2@HH,G!+-Z(,,,++KOOǴ^,Lt_,F>}W- hc͚5 j䈕DX9JMRo!*4L kPDu`9bP)W\9cƌg}KRqLJJȑ#j*x#GO?ѣCQ+iA5Ž~HHr^'vkE*BrMQbU`4 6a d1vڽ{wqQ~?B$@$ @7ߖ{->>%sv 5yj&6$`3HH,LUcFlaal: <ݼyMvQYYfbǜ8{YU]g p4, Eg"7 +G):rV # &O+l:Qa U(lDu`9bC#Oǎ;{l< J?ؠ4LJ8L(-Cᾥq#VR&9b(5*íqVE=D5lTyՁ :<ܹ3NMriņ{gq ˨EAHH|#Py_]kKLl~Rv%>ݻ3{17//OުU /pРAmڴE$br7M5I`3HH,Ip<;7ӣZ2~l4 9>I&]t<5G| hmոCڷoU+G).Gk_-)) >I[@TX,GJO<~z =zT8c܋)3Cw ~fG[(G X|y%XX9J=刕4a-37M?؛6 3OTX̖ QXXߕO>'|?CxTy)S<37tS.]Q]lPJނkS(L=X Tl0Z*56Q5E G=G111\pN{m&KlI 'ї)k$ (7[QH psrr5k֧Oéyw9,22G5BZSeiSg+IH(_<;۞4N(H@`߾}K.=uFiӦ&LԩV39b(E#VpJMI1'*MCJ@TV[lIIɢEQv횒wdϟz#QNnjSOM6mĈ xTүs4GP,I`ܸqY꾗#VRV9b( [X׭+_ƞtF=D(ȼo]z5N7-..H-0H 9Çν:t]w2fUj:oJZ'f6L@i4`!G k_rkO.xYIV{rQ£(uDu`U£ڵKiݵmzz7X;_UjЦ'l ][W&M&n沉$@$$<|0 zTafns QoIG>b1OXZ{9b(EW#VٸQ J R܅/>B6t—ӧ돊Tޖ-[n۶χGŖV.JӧOnj_EaCbGjvn*G+GiŠ} vrQa55 :UGj zRqIxakV0|~/^ CuI3~x=*Z%ZPq05hHM6HH䵿ش)ijYU} ŦəSS2+L(DB0Rs0]?+JNNر#i۶m۴iyɽ *To{qn^ +0p4Պm& 0@gãڛ5KVn[ @`jT[S 8qGUjT/mҤ|)zGOK6XHH@$駡;'x*.@$`9H)|)&:N]FK5G0X\ K6X t9b(E刕4a-n7ot-y~ "56RmoaxHT^~m ¦4m*Qbȅ\H:5jvMa @\'rԇf$51X Z)Jlg_`hرc#Ő)KIII:uҦ—zY\~$N(w̿aHH!Pz5h|||;r7wx! ΂ /Q 3?=|1ziii ٳ'|)I=`PBf͚?U x'@?% HvGKHO$@ Xe k>t:Kv?rg̜9s۶m `}97սI@2MϚ5+-ur+GiZUU0[[:eҿ D^tժU=ԩSi%G2sBSMQ5  ذaC%xTKէC!Qb}"&oFLvKUǍ.Sr+GiZ}"ۧ'} iMFC8d],.4_w:tѣ j.]9,yX/SgÐI|ȪRRrNp9b(eX=ʼ Bv8g$}iREu`e:'Wս8saMwBBmڴ)5޽{RR1XTrX/ckMK2$@$@Rcn#E3uHԤIkdC$`<Tc`dggc%Ef+G)r!JI^3A)#`sp`NH؀W^xչ4TF ]+G)_*ʽ+7T9b(WWX9JkwDuM|Vǂ@8;0f0:tH[nwފ QQQ _v{6 X?bK(4QbI|1+YNMua& 8q񥎃Λ07&o̙əSS2,JlM1j_TTNÒBm'$$`iFZ۰$@$@A#PFupUʊHH ??֭8E/T͚5v-99YgHhSM6HH |\gVN$@1۷oNݭibb6j妁5W 4L T3KXF4_X9J~9b( $%o]uHT. O㊊ qyPc'$ҕ+W>SN]x1Gq0G1cƜ9sp- %@(dQb T\HdF VG$@`(U?F_/IٵZ)J=}'}kDFFb*/iΝ;tG弄H>FN/"' B7QvIZ),BԩS}NwUXXn#NH!IM! P!'eTJU&bZXJ ֨O>u~k/7mڴ).i׮]SRRL #mj ְbŊc /GrQ_XKFՏ?Fͯ,LV ŅMNu.]Rl'`NH/08T?/!!T{Ի>m%|ԐUrLQY޹䈕#VR?*++|y\<s+_|:]"Xg͈Z:QRRh"P —µΟ?.;=|FEE )-ݬ#9V9JeQbk0p C6jqe: Ax_~$Ww&CT{<3dez/cOW^_qqqwUTTBEV4kڽ{w ZBI0p4UE$@$@uJY}۶m*S,7_4++kȑVI J#M 2[foY#  -Yr'bkV>צD,7n0[l3 .`Ȑ!H,YvI3~xm_UiP XQ~s~  FPjqYdJm4=^@I3k׮/O8ܹsFF-fΜU2{g> rbM$@$@gU ƍPH$PQQ__νCAmӦG /C˷$@~TIp֬Yr+G)zrVWQљԩSV놩-\Xq+Cev؁Ɂ84iҟѣG:)[GBX9J D~ GSg(qQ.GrQcX03`@n瘨Z7LmUŠz1wݺuG4(aÆ 4(55VQꋖ+G).Jl<R82X (JCdž u5[jU,ndX:Nɽ}@۰a^8bĈ:l @n8   (ZxT:Jjh!?|6m:}4o߾4QbCH@)\T8)͇vKX9Jѣ䈕 -FLc*]TXeV'xb8BNz)S`lJCC䈕Fؐ~Aꫜ6>2o(rQ)G WR/w%VD Ճ{MV֋/^|}a$ SXSl_iӦI5e@IDATg+G):(ARR!צBe݈&( B|ݺt5UG8JOlNˌ/{=ULצ9:8>yyyڭk|&v$@0pmqIH'Z8wֻ6ϯ՝$:HH hS    ׋UxԘ!5 8O>*5s%Lp8;bo߿?+*J;($Fҷ'L`7rQ GJaGS2͝g~h韝pÆ5o մаZ{g 5U8  Ц6HH,LyfB@ʴ,,CX1uѢEiiiO,GyGH.>ꫯ0W?*Gu>zQ]űÇ\t_úzٳgãi11ppX99g3 d1x|A w]w=A94@AT`KprۈI[p46DC>Src+Gi3'PY?taI UD#Hl2ռ4iuS{kAA ֮]?j5mvС]tQJJM7rQ Jl:| s `Ö x#P=/(rjCdCa*(*--uo2jٲ%6G,ŧ* /T{=o}W_b݄r7kȷ6*t= J| Gr'sj͖2m{2is'#ZFѝ9&⦧Ηbe)< ]n]u#"7kثyhЌ، *ԀsnºjX܊%umzu7}[L'۰dań^OLN RSmPZ`c䈕]B]εq*fo ~@$PC@rdvZ?|LXӏ?R.٫5`GYݚ9X _ G kڪU+J.S2əSS2f_AWaXGW'%%i5MklK4Xzi&7¿7zɽ}pHoI$0p4UrvD3syX=}|=i:vPr Á=x1T}Tī-.mT7#|(#zIk Ԍ0S4O W* µjUQ:彼ݷoߎa^>}γ[c^>B A6U8R @<]UxԘ!5(@u&qcbu&ӊ*<+3kX~Rm}'ܷ;6jA蜆O8<> ^벯XV{N?BܥKB-[F~n*;;{˖-h1r;x`Lܹkhj8K$@"@*;k,9kSUX?|16L4ܗqcb΢+W45ۊywiT_K4HRȏR6P㭵bW-caU >7BUwoŒE]b4 >|xiҌ .Qup#VRQb}E`qƍ׸ \ZX9Jhǰpqc\QqW_U^>}F7(V a#0W]l!{y7v?{P4 :G_1.`Y~x7y `5<*£س;x㍡hu6"G'Ć{` "b OubrOh3nQ2+䷷l mŐ— w0:R8R$2lHԣp\x{yyy0"@vQ>}JQ=zaPrQ**txrhSY`*G ~'Kr9PooݺrV$:w|6 Gvd0:mx_xc^Sdw a;kq)ځSrv~2L @n8  8`NUySզ-*"Ǿ0]ճv#=xytؒ:vƔݚYQ#ޞZ9>xri35uG:sL΄i  ЦS*"h@h*1EDURسFu8F4[OMXS\ ]t5{xÏHH @F PbŊcpc#n)GW:9S{ggےSlq{r-.Ζ`Dw =FH#~Lo:z3`}Uֹ4m[ Vt~:Eooz fMw܉98ݴP-VbBo~m^9JEeXJ Uh6X8,ުMo|UX)N1ظ5E5GFJ{?b jOhOJv?IJ' D[< 'P90}P7ٙs֑;K][XSH͔jcG]RTN;L2TXգaU#&QAj@X#F^m)'^~8c1\rTVnեsdB*)v\Ů"8s:.2¯¸$1Bkǰm|<=%:QkG6?)0(ENov`)i)݇I$ݷ6k'5H} Э)vŨiYY$(zm rBr2wY>lHhS Λ ˲(ڝV?~N017^0eEcAksl ZZoK`HT'ㄛG0%0(\*)e*+k'!TV&6IN6:'>ˍ:V-lHPhS M/_C rZLUc|))<*L{rr̰qTӨw06bK!m_ =߽ppv{N[A3},lj-Qׂ`tankg\nic. bUV*+ٛ6T~=iYvvʪ*M.f]>4v{sӘ77ݚb'mFM{ٹs&AJ mjH+wYfYXͪ#G}ap;M=' _Z=w&鍽첸+~;b/szCH׏i5jzUެǢرc_Y'Pyqr ~>|ݚb#R YSUKz,G ]V,!;TCpqƩ 7 GLw#"Jz=0Tg~~}Iŗ_V8q6KH.]gK""6n#L0SNݚbcFk5[%wZZRvȑӇ(m5kHjyWi4byZwez bua$kÆ3szmp:#۶yYތN b[Y ,Z(??àM6˛?E]T ] UK k諑#Q*jא6(/ O>}4Cqmgn܈T4 84K)/ԂիWo޼5..GEEE-'|III޽{nݺv'E$@$@$`n掏[=b70M%6~>ާwzɜ3vOos(>~Lu׮]Z񲲲ӧO#>e˖&MjU{y.Q>*G jߟ?ao*)6]8<=>tر ?0Q#;/q-hgʌc_H3W&MzN}ݜQnZbb"FV;˔P'$G) Ja9JQE5 CpӱcǪ 7 RszUV%']9@co\.6@ڲe֭[I+Q{|LMMMEe#ȟ>}z||o[rQʰZ[Eaߐmj:HѲOVW]ީn1^#dFՓ;FP$:u2}ӚK{-~/^k7ҹͺw?~U$@$@$*TU#K]$ZO?َոK/ iP{ͶGLJKK5k wOl:t)i.]}`MOorrbja͒T U{(j9b(eXݿ*EaCgjCn߿ƌ8?^q< ָq~;v{ڟj#-9V'SZ8w^məSS2_e8]yԙQQٌn9ԅz5pӪbqƼ^car>`1  0܍ʣ>|x߾}+8q_~z|f@f *֭bY]T=vqaMа`UU98|8*=|.jsz ^mޗ X6uI&믿LYYYHx A§Rzb22"\.T[llUiC&91 Tՙni6Y\XEEQADMFG$u6:NfFvX cjb"ܬ#d0lt!;& dsS?Gydʔ)&F}^p>&fƌ+Yٖ{ã[n[l6-ZDAz_vz߷~Y1cRfz%5qdjTk(~_q?Y{ڴir$F}q`4?b֎W>Q*v4GO?=US뮇~;N0t -V4ewƗfl M﷝䡗bѪw>xK.6kSM~4&By;Vsz ƜevXLPaO$$B :YFzԠI̙{Wf.@}}ËZ)Re˖FMr(4Z]j?NG(4ثpDNf!:{XQ7tA+|-K לѣGkC=9U&RT"4(GSZ;@b{ñXb ۅXXWXӧO*L\$\ٖMtlL9 sVfHWy M9k^Y[I%: YS|u2bT .SS]h#}czjVDd8h}#dA]SSaB1cU _? ?)f QMyñ/tٝjH}rFZ&{k@笪@p:7:ܭ<-76<,kh*?vSڳ S5ϕWTdzgL4b„ z0^z)a7YY[-[eN5txh @ B3IDd t@\MŎ,>z;vo~5!ڒ? M?XХHvĉ[{qѕɫ(_vBnh"[ݻO6͟eVy򶹋i>}&6>.$ٍ\єHMhx2(6wOuaa=~" Q1i0!k[>եVѯbZ2[tv42(yj&LC|tvѾ"Ŧ_Z"& opgIO?u(ZŷS&lhi<fM!F3!cָWr*gFM3f2ɚR֠b(swhss_emU'N14#H!M5n?Y&X18nk#mգTKMhZ ۶ϚCzΝ;WS5.]WWA{-5RTl7ΖDe(hB)ue0kL"0fu25.TX5,tbe׼s q)ZkZs񱌚RGCyfԌjÞд3K˩uRDz7j%-L=u߿_5# @ $WtC3eȈՠLjNHFSk5[v:5;uVKNhfi՞n?-Gqlhh.GMGFlP!Пc/+9zGrNP &WtCSeȈՠ.] j&xy)|jmL|BS+{.hԘԩS%Rڄ]J(:<&Tjl+ _t,i& @ $WtC3eȈphNa=P0ELZ3R漦Q#kwj^wH]=j׿JP_5/TѩV;;TjMR J3;'0VA]YҊah*QMWRV5.բ?f+!LyːwsͫW7o=;|wcG&֜pB 'jiVK?(OzatQZ*]1k\vao5|д 5'?]oԬY/W]AhBT޽[ر[ۺ9jܼzu˚W65e Z[}`v鲦{ƞ U8]|4(S/3:j.# G3# @kQ5i"I헿jݾC?[}5*Zy٥[M].;vVuޱS9z[ڗܳ~{m64ZSncO * kFG94& @@`o&nkY4ںcrQvw[~xK}˘#z647oFowꞓ'M\;z%)MeLGSZR80fM;|Md ț-LCCW,[GRKݬxҌa*׶m73fVG5z躺:E:E^zrLQB[g]?Kqi[ @@B)F%w}1/9Vw8 6hDmr4vU*[lfІC6T†&̕!N?+VޱǮݫzᄑ>Ȝڡ) @ @ L:u]G߿ԩS/rͿՠ~{P[Z8:K^{7{(59UUU ͛7gΜ?WH\\;)5sɓ'HEGS!GY4ŬE?I':EˆYF䊘5)Z6FSF5kHܔP# P5Ω?ͬAN3Ͱg*@7nG}tނssɒ%h*GY4Ŭ$f[4$K%hjU7޸;xg~]VC ۷1sꩧF M@ @(#FS;: M]`>\Ũʹk7ڃ @ PUrM*.]p|u^rQe @*aj4<n.L}_MImEqxRE^.GSy?)f/- 0B"`&E̚#TMؖqގX  @'Wth@ @I"@$k  @  z1cFUWeT^菲hY 1)}E0kl 1fuDW("0bĈPN_?]QM1kE5a4&-"&"ՠ9@ @{qE7zz @ $IFdO% 돲h*GY4Ŭ%%2T˔$f- _R+c֤Z&rFo6_wO A!?e }eG^1k9(Zva0QSph:RDlmmH B @H"FS @ @[ޚ!@ $aj M 9#eTᏲhY#yKZ#8p,<5Ik&"/М6s>|CJ(⏲h*GY4Ŭ20k%X1C̚2nS# 4@ xO I޻ @ $aj*YfΜ*yKeTᏲhYKzKje8)I.ZVƬIL*"LMْ %K FydGY4?b%f-2Y cmjkvj @ =FSw=@ @H$YY @ xO0{(ԩSz(돦BGS̚Wq`H+Yg31$`m+)rqvb @ 0h A @@92}@ @#TGP 1cF8rQM(돦"߆q`̚v?zqH;bĈ଀?hYTNeŬΨTZ-"6Q\#V @  0 @@&>U$?eN8pR-S\$|IYjTEJ%Aӧ'Ah*GY4ŬyK,s/8p;ZexewԈՠ9@ @{qE7zz @ $I@ @a.P,iӦ[5}QM(돦5}oWfcVHq%TWR⚽(^Ŵ#l0M?QM1kH .]+b$[h0k\105bːAs @n @@&e̙$aQM(돦wVƁj¬%Kje̚TˤR.T- B/Y$ bGGSy?)f-[b{ }z( (돦GSZ2xyì\^0kWvwMؾqގX  @'Wth@ @I"@$k  @  z6mZUWeT^菲hY 1)}E0kl 1fuDWMu%X.ێEXL ><ܔ?e&hp%"fMu .nS# 2bkkk(K@ @ $p:h.qi- @@(ɌZ˃\̜9ʡ?L폲hYs;NrHYsIw6fM&=aj q,YaKeT>ᏲhYK}Kd}8f)U(Z*DǬ4KZbmjĖkqj @ =FSw=@ @H$YY @ xO0{(ԩSz(돦BGS̚Wq`H+Yg31$`m+)rqvb @ 0h A @@92}@ @#TGP 1cF8rQM(돦N%IDAT"߆q`̚v?zqH;bĈ଀?hYTNeŬΨTZ-"6Q\#V @  0 @@&>U$?eN8pR-S\$|IYjTEJ%Aӧ'Ah*GY4ŬyK,s/8p;ZexewԈՠ9@ @{qE7zz @ $I@ @a.P,iӦ[5}QM(돦5}oWfcVHq%TWR⚽(^Ŵ#l0M?QM1kH .]+b$[h0k\105bːAs @n @@&e̙$aQM(돦wVƁj¬%Kje̚TˤR.T- B/Y$ bGGSy?)f-[b{ jժ fލkv$@ @(@\MZGS/^{pE)[6'(Jzm쏦rGSڡwLJ4En.*fug5Er3d*)SxO=ԙgiY+UUU &uHI@ @) ;7^zw5HǏ=eU1N.C @H>TMֻKE]xb6sUW\?%>yI&K*b8I+s`#!@ @S 5Lw}5ڻw>S!CXX---={<3LZ:& @ @li\h @b!X`) @ t6&L @ EQ@ @lM!@ @S; $͛?$HR E) @ \d_h/~OMڟ'NۣGsWlݺ5=/W_:WS~'pB߾}kjj}M^3Vwg0UD;JXPSHÛKH_PY3iڴiV]vC9D D\oGQrrM](%t.My;~(묳t7 3|ettvESo~-EjY9GXZlPv$H뢩 ی0Kc~ tE E4*k֚֬3 ̜9sR'JAM|>zҗt>s^2Np{+4*k i|~M7f1ӈi|3з"m&o8߃N!Zr\ S݃9KlC(Vў*?jԨ\Bf:J&ΔQӂZ$-(fMez;.緣s9A&Be"%v^ሱS%L 27Dz"[kic%Rn6Q]zb~WRI2b.}ԭg:Bk-[Xӧ(O|h:e~:,o.4hV#Ϊޅ]o~c.Bpt[>DA-Rh`SL[oF`:3$ΔQS-bx ??ʚ4dvu.'w43](L$9v_{ ƂNR05$\MlE˟q$4M?V*޸йvFM}#{e>;m׏#Rcǎ5ӥkBqR[nO=T\i\FLK &4`EGg|g-$!U`=Zҹ֜m K$]*S/DgJ袩1>.B(iYpNTҮ~:OdLu.'w43](L$9v"?F )Ke.o3GK&O$R|%>l/;0jp@ӹ̧yκoʼꪫJk4X>,->Yt]03j &L]ly$T5Z28fәBTTE'W6?3PԨ߅,$ F|m~=q4裏ްaIiqS 6YDqW MW`fzy̧KNXw'|gmNxgkQPx~0YIN:'9餓{ -3'VRn)"oSVhoΐPEBMCej7SHi+IF/\"緣r4..l-t^y@Tӎ!O>Ď;*~ F=*@*Ι3GynЏB;hmUH^FCxYg;KI'O{Hqmy%@۶m[|~tA1jQ1o&Kc]'E1c 8P/z'&/UIЫp`N;j!1J{g뒵b~ T4W\y啺 ,ۚ36Q'Q‚Zm"S>BJj>L/R}[_wESG )=_l wA:U ҥ0ăKo3-%MkU'PE2F`{ *jє>TtBP(݅^juKW\q2ItNբ:|ߎ,EϯuTш ][:5AoJC { 3؊eHkamA\˗-m̮uj~5o:[sB.q0e"ioV!K~eO=TF]^yK?!mࢩ [.1mw^61{7"sB鮺r @ K-O @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO @ Ўaj;\@ @@SO Ў@ݯ#G[ݍ='Swn喱cvJ%4~K/tѣǘ1c`cM~}ꩧ%ICI05vA*@Pthjɒ%ZZZ2),[ /T ,^8@9Gy^;o޼,O|{;}[f׮]{ 7ܹs{wM7gq7`y gUL<<'}^z w] ffҘ?GuĈw#Q̬hP &Wqƽ+]O9sw=u\uɇ N05v   h>zw^趉cwU]]$Q S=GyHY%Wz'}s΍ B"@Iځ (R@uꩧ͞=C 5P.{5UaÆisAJm۶޽{k;v @`mjHi" 0iҤo}MZ&>âUѺVUZt T aj  C/h-S_Æehk^jD iTVqڏ~#%Ҽb+֨Qzygj=~۝,ɓ'kRE97xvӦM~W_} }nf)-.w2RM[")G)So_yP_bK_6:M$կ~!پ8 O0.Fz[@q͆dM@xAE@FMR51տۿ%iw^8h_|Qó_הOZ;Ϛ5KC&Wjk)ajia[oU93sbfN:e˖-*viʦN~?<9[7CIB}LuTi-5YL!)| *ys'W^yʕ+7lؠ͇}+L~,W\q{>@[sKn FO࣏  He0z-`e25e4|j1){1[k…*`خ 2Y<*?wRf}]eJb\b6:5by5ט*sC4,^=2h WjKS[7ϭR (9|*@( {G_)z7 貣9 B)&3TF!'p)v2Tl1V077*``nU'LӚ̕0_j߿nH01.r}饗lk~Y?OXF:khX$*Y+* @H> !xG@LH믿^wVfV.;جZzѢEF_ B/3; ޵%X*Slck.ŲqT]͂Rhΰg52qDV) @ 'J3 h S"tΜ9ַ"["?,\e$Yj % i&`yMkdH %6^E k<ĢŨ:^xAO]zi[4N ;"?c @+_ZAQw19R2x"ipUI9.im#b,ܽ{w]2$٩i1jkk%& P\{;m*қ퓀  LMw̨Y)T^)t.o;_{lY;ﴳuVǏo-^Xzj0S.b;V2hݠ$?R SR+oO˴V͚ @ IɈ@0hu&gVg̘a>_wް:Td[Δ[.)?{GPmrk~M;^x$W_}JّL#R4*lAKk:6bf"kS.bhLd˗k^h?lz)ESL3:tsf3'K GEbE0@Ks~%\bCf45yE)jҙ~Ug JM7|׮&;w)3|S_kW:GTghO~ QlUwa[HU+o|C-L0^fQf8ؚ=VjDAc#QОd 7]ؿKXTKg5Kj繥E74 $aj x"`cȪ|ccI֮];eiá[oU?pEh)l=G%G}_5j 8k .,d  J3lIE@[@tX }&$d%L !lj/:'*|ahiiIԊ_PYQ Tϼd=#CPCT' H00/e``3e`X?!f oNriQF&cB|I=piTXtXML:com.adobe.xmp 1734 958 ĩ{@IDATx ;c쑵,WHB%KqQW~H•n*$ZGu KBAdXޟ9̜3s̙9|>;z'캣@@@@@@,.#       0Ƌ      -eM"     @@@@@@Ʋc&@@@@@@      d c1s      x@@@@@@lI@@@@@@c      BXx$      1@@@@@@l!@`,[D-@%-Nma*q      @ c,S=.    \" q@ ͛~oXV    @ hP,>>>@&;wn v:g*,(@@@@@@%9@@@@@@,#@`,\oߞdd0@ ®;JK$&Ν;d<˗SNqF3g4kvhwˑ#GԩSuBsB f8>P1c" LA[7FƘ%'     :v( ={tJA͜ڿl޼VjŢSn:M:5jho^bZjժ&{yaoDDD CfPH  2J:q7j>椵 '|N V '|;N8&[-'ߜg2t,:`᯾_lYc:Hz2m4QOFa۶m̙37tgGyĬ7}tޝ[g @cN>ԣJ cm,, @@@<E}|||0#\Gt[N7XV-ٴi h[o~|TZU6l 7x9+66V*Udi^z߇f'i ~iov kn*-ZsONc Xm?uzo111AA˚5kLI`>r>P3;o4MR?̘1ƍMSzCvj[Z5s//n8 k6̙3niUVBR_YW7 u|:N]@}u5ŧ[-PP! -22%     FX"ELƕ!DFFN2uE i`.(k{V[̛7snC,2t4A1-KXu Z,:? 0hlSr3giZ;t-,+ޜ@^㺭$j\L5Z"""̮θ>C}6Qgb 墁͎ UefPovG@@@@@G\r9S\xJtzBZZi<`NS-vA;raeMh})v>+T2,,*VLo}:sڻ\ڮVR 54CO?fW u: 駮n:{g]Hۻo 9JޙKyg{*{eA/Pv@@@@@l"kQiq |fiƜ'0f.]PE)r!?[K޸qccYSi9| utA[ߺ#G)͜Jzd:-fɍ!{oVjԨajwpРAf*ͨsS 9yTZEZO*|>}Zx߬Qc?ijv@@@@@,.? 6jVfYk@I-ܲe^|wM3SYiPrn}~k׮ursc=&q4{lѣ]dTõh杖%J8[y ѣf}//~X!ϊ+ &ב5VNjaeʕ2~x)?Ckf5gԮݲk륵ѣ$6(U5SIv-crli+ժ&W%۝#097    $/;wniժ̛7O $2=' /`o1mg=*CҥKz7nDGG'u`^e…駟vsv׮]ߢk4P{vSGl}jH 48XBo~|fݱ?ܧ ϰwf6}7_~e]>};O`Lb&&L4h 'OҡCz7dj_wk:nٺu&:u\j֬i.tRO:第I&L&^ߖ1cƸ?Ѭ 6̾CJ޼yE*ժU3=7;wZEL4-ގru"##e2bԀf^zUtEͮ[L;xT{ d.]di):`zL-yٳvMT$Sn4ESP]Щ 0GzڢL y&xP @@@~A\6EYn&K :4#ɮTvgϞ5SvcKZ;?]v5 HJϟ?_&L 4A6n(111ʪ -[XRl[0]LzZ4phѢE'b5kVipjŢbwy9RiO{=ݻW  9vM7IǎE jL2&SO~ u>w!%K4fY빙B}eڌ#fnAz=TfP|*TmJҐ@ 0fe.    Lcԥm@ t\"nan(~Լv)ACiBi0  % !   > 󙊊 $]c92ȗn@@@@@@HWcMg      %@`,@@@@@@ ]+7!     d_@@@@@@t 0t    d_YfIbŒԯ_ߠ 6,9_zu'ڄ l9뤴ѪU+iӦMJzS:f **Jƍ'uO_f\     =zȪU\r&MȮ]䧟~2ܹSZliիgرې!Cd߾}2ydso߾ 8뤴q5џ,w^zmԩSn?111e˖$A; i`lϞ=@ ]w]UQ ,,Lx1f@@@/^|  |2`R_>Ik׮vIŊ^ӳl߾]:w,Yf/_ Wbފ4;̪u8*TH}u c,@@@@@@ǎ`&.ոqc)Q߿_6olxbL@֭[Ig{fi ž^(odrc@ @@@@@g2 py9r83+fٲeX"##m` 9;B`,;?}@@@@ :_'Oݜ ;vLtͮ;`?{ 6,`ѐ<͸cq     @)ZܹSZ[rtիW{&YGlŊɓ:рĉaÆrU>|TPGf0a4jݻ;qŊ,K,6mHrLݺuK26k?tmɵ˸v%ƍ;Sw1e˖GyD?nB:kז2eHNĉ]gTT;bڴif4msι3r:utrr됝l)@`,[>vn@@@@X9s 3klҲeKi۶E4͛7ѣG&M$M65k6Cɘ1cD6u _Zoԩ/СC͵V/u\e&`K]j֬ ,i^2 ^  =w}zjs\?Giu&MMS4A.]_+bƯA={tAaǺTaaawk`A@@@@ y|||@ڢd4С֢LjՒM6l2 tz?/_Uʆ o4\JJ! իW[Ԍ%-/,5j(۶m9SUf@eYi9f mR@S]^Ԡ5(T ^F CT X>    @65Š)"qKdd 4:N[hMXre ]PL=ԭ[t~͛׹ma%N;Sv=AUM3tAϗϸ\]a u[(S,az۴ZqvDDDؔ)SLƛ@fbYI)Cl1iR9(`Ӱ{GH~,     @rNqŦMk==X/k֬1h<_`A۷9W|Rf蹖@ie%iѮ=]7NٺukYn޳k"ÏiPl:Ǻn^~ eW!p{     'k~iq |fiƜ'0f.]P&&&ƴr!?[feٵq< Dvz{ߚׯ_o 2So^jw9†6}J 0b;     t}… 5DT{ Ӹqcul"W];gPFqr,%ѵx֮]z>X1XիW+WETzcU%ϔ8L+h?ɕ'w?瘲1&A@@@@H'ܹsKVd޼y2dȐ$& O>D^x̡yetF//]t1;k ƍ$Χw2}t&2b\է3PBߗ_~Yt>}Ÿ5š-jkɼ4[U {     ڵ3۷k-m|O5 Ќ5J/f͒iӦɲe|C\\O… ʕ+Ըd ̙3&PiO * 4G@LNt Ly;R{     ͛7 L'YfaV:br%**yzϞ=RJnhp*۶msgϞf>L4h 'OҡC1oȂ ̏믿ֆuĉG9GFFJZ$O<&8weݻw˒%Kdƌ2bS_VٵkTg`ǟqܹjB+*U2vW5k}WGo7SۧS!jqq=;wN|I8q.]ڙI׭[7A*@]Ռah.(戈_O*#@    t lw0K^*3gδL;{A]̵:uu׬WzvU4hհaCHze„ rA4hN%A`,`z!-/Kz@@@@$@`,+=MHYLx=(zNq^k&M`,9eZc1p@@@2c @6.yr      \X6}@@@@@@ .OD@@@@@lp      @v 0]4     ds}@@@@@4̚5K *Ueذa2u$K(!QQQ d̘1I>ާTB |2`2(V0t%?~lٲRdIQ]|MW9rD^x믿:u8qyyw\mZ1ׯ9rS'#n&Ӝ3ɼyL.>>8r 7)O;'ʺa%w)&:ݣ4{MX7ou]mӵ^ڷo/?̘19kٲweîasv(>9s[ڹsLV^*UdnMy{Nh!4D)TҐ%-2Ƽr@@@@@_VH"yf9x/_^"##M`LI]Кnr&@1Ynݺ֦3o޼m ݳh6NhMy^tנf;6I֘b<wz͚50- v6mEfW bRӎ]yGdݣ}il };Xc@@@@@ `r2)j/6jNOh|lzZ<`S_˚5kL3 hyvV`ҷo_cb9    5eMu2-Θc?\bbbL+5߫+W|"5ҴxY;]fܺ5^|E3dϹUv='o;fu?ѥ3C8[}J 0=L:)R?&Mwa?XkutnM[g     (sz:f1Ee˖uq&`˖-zju`πE:k]-|5>=j 8ڻv̛7~ڸpP;l~L۹o("OʖGM]IX*2S3bjKSsiˣRUNr~sfT Y~'2Dt۵k_l#    );wniժ (4P{^xlsݯQ/f.]1Yc7nDGG'u>ПO=iB m{ol۶Mw.ժUs Z? W$1c ٳǤ4=U#Hѣo6/c     ڵ3۷|:t9I@@@@@ 7o. 4XO2]*""tJTT&"]EkV%i{)Ǐ>L4h 'OҡCD΂ ̏믿ֆu̙3&g6m<#C'3 6ZE2 -R3;yޏU']O=GYM[n5v.\]6~ٳgΝ;̗/[[jՒHD2bԠf ^zUt\[uޞ fGL7ab: U]"GKIC|@#"DiweEѽK,1顚nZv!~nZs*]Oi[}t-@@@@R'%eJUB ze dW#gϞM4g]@f=_׮]MaÆ2qDTrMr0a~z^Yח$Fllh J64S;#G>N:IjժCJپU!#Iϕ)SF6m*Xn]޽{e_7ttQy3F>F婧2y{N6 I >]b7uѬ)K :+.3CIKN)0/ ?~\4ӵhJiVKvZ^<    1{"@v 33X}IЩS'SiʕI*.?\;;q#,,L|9!    @5kr1?7w=lذ$n՝*&Lc\"VZI6mDΝ;cǎR|y`wvŗ    da=zȪU\r.4ib"?WeΝҲeK_^=s~ǎN!Cζ5ydso߾% pIiڵk?]N<)+VoV< J{ xZᅲ;:իQFsŋ|"&_bZ'-fv||Kͷ~d]uE/Oȑ#o&Vk+t@@@@@ :CV:u_iѣRxq3s썒%Kʳ>kΟ8qBnyN…EfK6F%J0}|rYtՃV?7={vȆ5Cw!hGΜ9EaZW^&X[oܹsg:볁@( sy:yDw###`Rvm[MPL     H)Kl۷'iqƢ.M$ؼysz`ŢS"n:MzmO?W^yŜի^fdudo2hР4nz>421G-Eϥۦϛ7ObccE_:NV`׷c     @ 4]v) py9r8ꫯ|Bܹ'L 5r{`?eɒ%ҦM3ۗf6u-<)5ӥKsZǦZJ:dw9˽%w.]K&Mlٲf)V{%..ٯu]p)2uTyeСZ b]xQ~[zTV͹NDDhݵkdٮݺmto)uƎ+#F0m۶Ie̙o:Ҡԍ7hy矝իg:.?s@mtM)Z*['iOsu= Zaaa#ZϔA@@@/C4:ul)$!!Ajժ%6m2 z?/_,UV 687]JJ! i ǵO2e!fAiĉ֭[E2w\iu욽bZz)2:_CǦ'i.{K}'gΜʹsLF]*UdaeҸqcROj?iy+WL&[ܹͺkzޟqk}ov-J *d^XG@@@@@NWHquA)_DFFNXvmUeMXre Ynݺ֦3o޼m ܳ;fZFk:Fh`j͚5[o]c6ҩ"[jv^wRk ҳhw-믿.=ϤA4^0h)\ym]dSӎ^F}ƝSnA(Q̶˶G@@@@ȕ+NO>1YI} ʴiy 2xto h KÇ%ZJ}rI4v?Ckݔ-OE[Ef_2Y&o=#Һ}1ӄIJJ㶮{9k2b[]?*K7uƂK     @548Y1+7i`Lcf ]@%&&w!Ѭ~PI&I9{6rʕ&gMbZk'N/B:u$ g7 &yf3mfu-h}w5kv[/{zvoeݮ_eNxb%WxNr5A*,+GOc$c2n75TҰZ oqcºcE@@@@HϥtƕUlYgkƕeu@ox~wZy[.I`LdzvZ2#u]w[ej߾Yk2tPz=k.@N5VX1٦t:g}Vnd}7|u=y57oyt9;n9Դy+{cqRk0Lrű&+YAL{/҂F`,-zZ?t @@@Ŋ :u: vs6j@dz0@IDATȐ!IL(4^HqA>9ŹרQC~yK.nRƍ$SKNgux |,ߔDt6fҵĦL"K.5r[ҪϷ~ֽ۬{wVԌ858aT,Jr429}QXN;# nw? ᩘ245c.az|     p@l.Gsd$~}vYIFH< ?rʕdؼu’h׮ھ}hɳmx/zN~Ix_ ?)2p@yMZ޽eԨQ?~)ue˖YU~;wN4صpBuDoW>R3U6mdrȋOy>}Ș1cd%{fkIzsd8 Ԃ xtlS,wɔ"b    M`ҠAV8@BMlxGJ_50 e 5͛K͔,TDD˗OtJTTN]Y4dm۶YgϞf>L+=9ޡC  J*RX_%@L}+%{K|ZL:ǙS o/ 4JxT'N0C֭[իBwiӦRfݿum?T>;`m EP,Lz!?)xM7    _QJX/ i}Q3Z߳ߴ;7wL9WP6Wsmze&3gδm@Ξ=k2l+uP#s-Nr5땹p=_]vHiذL8Q4f盵4Uzu4hP]111z~]y_ϭZJԩص絞}hoS7ttљ H2e'z/_˞U9W\fڧ4knݺiO9ێ BdGPɂ_7S*Ȱ C: jf(iu O8cLa    RS 2"C׿ˌyeaLl+WXf{V't!}k%0T!28@@@@B_@9{ĠX菘"4qBQzP,De+Kwt    !p@Ǻ@yӻCrc פy+i.Irג +&&ln~6m-ܱ9x0cqcNndݺp\neСmۗC~;YStȄ0)Q{o_=8+;6͛c)?X)DEŚ*}۴{wǔzWe̘f=7F +l߾]&M$- = PR (g7T!   d=JQBb؜9]ۮرfͫq98%yyKnիE.^tD*QQgus"_w <ì-%={p&G.a2bD>Y0)r]V>++&ʔ)bsZ{̛wߝʕwHm۶O?ut{NFfS)f@@@@Y'&(T5sR~wf:/Z]Kxf͙`Vig]+s7LV6Wf0Ϡշ%)Xs?3bcdʔn]>OUٽ;V6l8k]/p!d5TZj| ?OGyD&@p oȵNX=   @ c/.{p~ԩNѓ'äNŽ0GEG,y -옢Pce˖R{k&̙qҾSbˑCĉqxV߿,XK'AuU8bq%K5{-iӵ>vǼti.֭[UY=l @  d1I6z*    A5xgcbZfvq][L/ 3/'u\K1ZNSdTfg.bb%Vw zQʑ#(@ ~y(    @fL0#GN˪UN$|ybݳ\+iMzu5um0O`̗t?#͛;>n+xqq)|l6KVi~J,XG`{>}#>]FaDGG[o%M6M֭[' pOIٲerҸqc4hc=E;T5%ЪU+iӦM:-2By0@@@@XNu ]/P 1<׆^o}'0fgLLGXtymeҤ8Xrڝө) ޽ۑE8Cƍg.ظqTPAΜ9#۶m{O^|E裏䫯]w%u~Q?4 _Hw5e޽'qqq~1Փsv{K=~ļ2yr^ǽ]i.83Rj#]Ǜݷ5T|ypԩ$}˓O>ZNJr>=;wOڍEi:u ͙3G5kfWͱn!w۶m(!E!.]/"C@@@@R% 2)rsJ&sƗ~"cLb=zcI͚W;bv}r,x g"z4p@shҥ}?"">G%k׮{ iUV5FA\`uI }J     5j$NWUѩ RV5ֱ|ݼ7w6vEɓ'1xO*U2'}R9x#qԨQC{S})֣ŋ%22 {d@2ht    hy/Zgɮ?HOƮ/||?tWY]ĉ5ݢޛ={$8^خ]<Ѕ \"gϞaÆA@$/d@@@@@@3dLnl?S\*n{Eʗ&;_c?L~Nq徯.R2N`ܹ={zĒ%KM6R\9Xndn/]d3lҤ-+%K4\?:gbʔ)ҠA)]uN?76leI~WSit%g𵾮k6qD]ua >ujʱބ QFu#**1mX;M?EW~})S`/?Nr;^<2$#;0ܒˑPq) נAbS rO$F]+&F /w;#a|y.y|efȭ[ӴkcLw}W&O,/׶S:ً2tPYj\xQ4yf5#FΝ;e۶mҾ}{9szF~W_ hwޑW^y:gttWbEU1?3k.Yb;'<~eѦI&IӦMkt;ᡇ1cƘlAE]cM=YiiʕҥK~_ȑ#] ;_mzNVc<#ȿǬ~i>Y 캣\^ ̱)[̘TO"+矟w|9Ҝش)hvXs wd$@͙[{.i@Mf8/>![$ uȏ>:ogzݺ%O˽&H޼mϙs^7O`3'c5(ŋ_֭[D Ѭ2fi{ w9s-K3*T UT[fziv35ce˖f3q7cbbVk֬ 6igujƕ;|[?66V5ܖ/_.s:CGìV9=y8p@j׮m_yϳȑCi7^( ꬁB+#VCe5bHS_$_ *TuCv.KK1H6@@@@h8p 4 A82vNJw)dÆIbIrE܂bzS)fRnc R5ɟ#pőurŴ?=eGp# r%uo 2mZ#rNJ.v1e5ץ_x,>ʗ/c$+SO7=V15vv+VO^̭_{+ťS4zA1-6lp^dS!FDh`k3gi\I)VgzZڶmvJM4Mӝ_H{Yn]g;ֆy.uazu[r1iYYh ó~XNi%l;T5(i';yOݧdc%C@@@@ 1EnbVƘet3Ne7`S~r9|#c>(cGc~|'fJEcX,!]DzY<+ 1ޏ{W4CQuZ6mژutm4}oyVVX}zYWtJ?Ь7kYͦA%Wp16^6/l)ɹ̍&&0.     o:8 6A2J ԨQC~sK.nqItt30ZVyA1m@$ڮ;}pB3u1r5mƮj׮m5z`j6 lK^F<c{6锕/TZUc'0T, v1AEkX5O`,=1Ƌ    fvY%>>m );t ,-[ʣ>jUO?-ޖ6F%: Ydڴil2gM̠)[6q7ϮtfΜ)m].]䬮kyfq9OlԍΘ{-*l;/زܼ4?J)^9 /i 5EfТ3 T iL3RV-9zhf.Yf:}of0W6l!CL3W_jժ9`_-wytMy3ţw6uTi޼w}&cjm۶&A86_Es/~[ƌH~TTՕٳǹmmo>Rٶms{Νm>Yi={4j~gw^yLL`Zj_4t| X) x3Rеz sD[;|f}}axY9s    Z%̗)A][? zr\\4nX<<"̟?_&L` 2YS F馛cǎf< .}RL߿YLʈ#LJQ9rK:udH)K.5S9nܸQbbb̥چfi[Rl0] 6iHEijj5쏃=v*ҰaC,= ZŗCǨ@ߏ;vHɒ%MgfjN_H!M% *T5C%A`S3e4    4cAa@ dS)腡@@@@@@ 0χ!     HX i@@@@@@ at       0 HA@@@@@m=K8)]wp: < =Pn@@@2ŋ%>>>SA"Q'O3fȸq6n(*T3gȶmޓoFn6ꫯ$5@[R˦I+\zf͒1cƘjzOe˖u$!!A>,/Wݛo8heۅ B IxxxZ ~iu ԍ0@@@@  Df@\\/_ތ.ԧO?<2iҤ sLNa7Vt5{;:z>H@v XjA@@@@@msҥK'#""&R3(|κ>n:ac!p     @@J̎ZWY/^,e3 ˄!#    Qĉ涭AVgʰaò-ro! @`,C@@@@@HY`ܹg<6轃"IDE@AA.*v)("EEExD)Rz/RB}{3d&o=䜳~0 盵V67olRJ(aruY6nŋ2biԨ/^\ .,իW^._,ԯ__-jZʻYH8 j@m66lԫWO\"~9۵k'ǎ .6jՒbŊI۶mŊ dέ[om扌 &ik׮GX<'(#r          dABG}$G_|Qz)dРA2p@(pB9@DYfON`3dټylذAZj%|;Ξ[^{5p}v#* :VxY3v0Kaaa2x`#PҦMéo߾3w--28і!@bNZ ,;ʏ?m9sBLgL0oǎ2qDٽ{=OH P鮩ژR>t oyʿ @"Ġ N%lݯ_?ӧ,XY>_n4mTU5x A;d٦ӧҥKKeŊ,^؈f?|rm޼v 8~Nϻ<=:uJl6 2SB' uf Wu5 ry_\J([+qݳ0 ŜK;^իW7.[l)䟣@0\o0=ؖHHHHHHHHHH@Fɓ'*cyqlx=x+W]Cf͚rz衇ϟo<<:8.HsaQ9M9-s5WTI,X #FTL7xûk3L ϭ3fO5ǥ˖.`\R0oN UEEriW޸Pǡ0 O$@$@$@$@$@$@$@$@$@iСC<\>!!uQl>6l1G~:FQ }!`\nKFQYϞ=eĉ> v> 0%Y3g_|Q*T ziӦI0˜ kCpeo7S{ƼHHHHHHHHHH iڅ LN){#GRu2{li޼tVK~k D_]O?59~wիWŋ0/k߾>mȐ,{EDDx\tw˗cjԞc(`81iĉ&DsJ?䃳3=A(c X%%c ה6>vǸ^         HΜ9c)չsgPbqҭ[7#v 0@.]$>K k̘1F8xfmRF {)5k֔˗˛o)C 1B 4xEFF B-^zU*W,O<,[rw<͜9SFi!8B۷sTRҦMﭷޒ)SHbŤO>&C6w\XzW_=zH۶mUV&3ԭ[77shȞc[` 1'eNpy뭷 0xX'<q6m$ 63SLl cTKXܹ=B&[hƒM͒$@$@$@$@$@$@$@$&PK$ 9$m0sA~ )MXʾ\= @$@a,e7H"OK7{%           H({ϝ @"@a,MnnHHHHHHHHHHH. cis$@$@$@$@$@$@$@$@$@$@$@$PKSGeD_lqHQz @&1e/'Mc"ΊVKHfbM֊l9'rj @Z!?~[͔)˗O*W,-[G}TdmbɼydƌdɒX?_SuJ姟~4[w}'|X"ƶ վ2g,yrIÆ ]vRbXgHN1FPA[Arvva"b(G=HHHHHHHHH 8۷o;ZJ;&7o &HΜ9eРArw܍b+"7n hvo:z_^ZjnWGaֆ &;vW¸/{ŋ ͜9SZn-- 3<#ϟw $w鮩%Er}q'N? qPE=JٞP{6/\uw+2\m}t61}:X"[L~I$@$@$@$@$@$@$@q!.\KW!O ""BJ,iKի[u&FJKҥbڵKԩ2/9kM}}WF?,svNF/C )bҥ[R-"GTtRy5ЊeΩP3*.E9.OE M RV m*qm[,Ȋ]fq #}H{L͡IHHHHHH 0z-wrЗ01x4)RD6m؀ *6.}hysϘ1cW_5^d'Ot>۵h„Y'@a,s"pwkx :] 5ɦOѨ%v%3QbUvDsx}2OT&BxKt˨}Ǚ]_> dDE2 @ (BmR3/JѢE>bZť-v`crԫWO# .ڵkvsΕGy$d^u" iE bF)N"Ro zGWI`Y"[פ9k{tףZbuڟֳh^MFWαQW!"r =X@ "Г,7 )Ǐ7Sf3fh_]8 cgΜi p ɘd|sB\9{TtV )y @8q֭+Hft{(uIɌ3~rgR@1~޽cA۵kW68{|z=C~CFh: z_ܧJ2P܏9sDcH1HwM-Ki8UPE=کj){Izߩ7D?T$V@EQ"h$@$@$@$@$@$@$@is]_'`'} zWuIӦMW֐ ={)Ӳj*LåtR|yYb|ҪU+yᇍ8g+зyűvtXbfltPraPaGwSP7- ˓G~FY0I?^qH˲o*\neh8P WFK2 dgb^5\[Aƙ !﫻Gs=jsWr_KLO1coaBWBtZ0 ,('N+WHƌץ`q9< %c,lbӔ){z>T/͓wg9R JƪG?9.ægEǍkxl>!-}:Fy\Q*%M#up4_HHHHHHHH33gȴiK8qtو qҭ[7#v 0@s/]|ЄU`~z#@8åFRj֬)˗/7|S bDhiBA̩\<Ƴlʕs`1&X$ڵ67VvuF}xe5h=B/?SȺu޹sL?CN*7ox@ƍ'ٲy> ~`ݻˈ#d֬YR~}=z7q܋sZ9dry/%GrG~93=!$u:U]AZc6Α#A܁'T,knO(KOPn\.YɢsWE kC8ܬցZm2gZjwg^Z9Ef*:][{c-y6+rJ˶8K$T9+8Ko]`` V$vĵw;<Q "Y,G       H%}fh)#͝;W)V^=yWGҶm[iժT7Ϲv4>mkLc$2edD?ۍyՇ{?9٩S'#nzJٲe>dEGo{cr My^n(R)oܹs{+.92pp pǶO'_3QV,CN-EUPEWO*<*8%UYBS5jt_Tꡂ" r|uT'1Njܓ_svP,-G %E 2tȄ5yk[;zA?eD!~ʐ3vzF2 Ue_uY^Q*2J*_,8SP(XT'HHHHHHH y0WC$@E 2\ K2uT|ʔX5OZJ1Ek dqm5<( "W7@ߵ1U8*!=-e`5&h-Ya {Qalzh}NT0Ra v@sy vL$*?Ye5b:.

CB0K"yDdߪH骅d5"BNHHHHHHH=ƒ;g% @Z0{"ŶDά;׊ѣ^uC]v}5gp\lbĥO+Qo0E@IDATz/vy_.I{U]a5t^"$S"S-^ k1i$@$@$@$@$@$@$@GXL$@$@q#\1eq5(ʜNL9Rі㴕cꭆd QeqQCS%.a"3eգ9rd#%zQYQ}V$CHfvb_k}J5&>H$@$@$@$@$@$@ICXp$@$@H˜@,0 &: rAN@U*y^TQ=Kzb ?Ddwk< >xX_9)4{ a1 @!@a, .$>='T|K}\ 8ȀR"-4"<>ІМmZV+gR:BޏFxJHnwGdmU$N,iog'     HU(͐ @$@a,UVn c$xZlImFy4_ eeܮ}GuuHU$VU[vZ$J#< B^; yeU4y RW>6!'mIHHHHHH -0~{p)S&ɗ/T\YZl)>dɒG- yɌ3dɒ%qK.rE5kVH̙3K}]V:w,Çl4 -E0o1d_-[\yn^YJiQ9PO2ky3WaTQMFW:XfH$@$@$@$@$@$@$"@aLb|Mz3gJndԨQI"<<wX &/,W\^H& }W3Y R. c)q10$:_NAžP]7pX~v@뤴ugUSoz\ @^UF Q% [=rk~ P;!`Ħ͛7{ڴiSi,2!_z%!C|1cȫ*[ɓ'o-ZP~"A PKP<PK*1ϋ^k*@U!hQD ȯR81vqqkŘ,fV0G1CF_u(G=fJl1/:bHHHHHH m06{ZuL rq-ZTaՑZc[DGyDV\)7G G-)>VWٳG.\(k׎VΝkW4 ;M cؙF$ܬ)$JK 3OE:hI cp- _s0u8zZgZ([Pˣk0B꽄8'&2\lY-1WĹHHHHHHHH ?9;lŤ[Ig6mt 裏ʀL.-[:Bƌ|d|M3gΘ)$F%$$0H*iNq^W>Փ엚"DXa ixEhG1vB;+9.ќ[L[](3uz#:FeU p]fQ⚻}U@e> "D]k=9i"㻀HHHHHH䡂u͛'ƍכ 6_|QUbx;V{ٵkUP!{M(9rxeL{JrhEdd~~Wӭ}2d%u)^o.s̑YfagIMݷƍUy*x{l2wMF.]3}Xϱ`A F@H+*ܓߵ:8,'2M.:)(+W"4bg"C@vqNJ`j4Qg9{{BA|OS*9=Ψx: Me.+@lCMG/4 mť*HާUDE͹x!g[Z2z֥ͽ EѣSOjĉF[:txb5kL~GRN̘1ÈJ.\0}Ə/ YQbw\,ZH*V(%J\rZ_~L:U s&MHD~ZmԨQrիرc,@ QUVrQ ٳM6F:*U ¡ f8$tbjE9RDB4Uo*ܐY@3EC.-p SլH bM^CXʌUnCCsbYNʜ)z› ~pzo>{ĵS~0Ƶfuú=q g .:=m# d1+jxׯG ,]e׭['M65^]8ZC*䪺;[N>-~.Kˊ ([x~a#rHu{1uձcGwS\Xwb{ɐaW^1z0eϞ]"̝%KifK|I^R׬!,B b{l!AЂ59 oذA a}⏷V׾ N:S"\5~oh+ tmuV}PazEUofIvRt_.Pm>)*Ҋ04 L;5{"KN/(a[Z_s/ o$Zes^w.zlʘƀvw.כsz~qmKZᨇaCC<QiI̿Ks=:ߙHHHHHHH @盜ao :j,Yb<(Ye4UӧO7b@rZh^|r wE_ݐ7,6ɗ(+)S&1 /Ȉ#믿6C\ܲe pwi1X"5GrTZx qz?Cd\̓Gg].Q۳z;"-ġw^c bj1D[01gt)#>X/:szu%h RXWvizݡ l @lxIrɥa?giP7no=qms' 12WwrQEDDAi޽Һuk#9g;MZj 9!bXX@ll2Ajժf&7.y(С-NգĦ_|QyЍXxq;$blsT̾Ν;g#D͘ bcƌ7xC֭+Æ h ,h]rE2f+qJ P1<2j1vEqhǵ7SiTAnH?`xrqjpb+T4{D tАouyS—U|y:5jJt߭^k|qD䅝"}PFБDJ7d,!      ך6m{'\V95nXufĮȥK4a!_,6|pdk֬)˗/7Bϐ!C ^f&Ěʕ+Oa*"$hv}>_CzN#     JK*Um&9CΜ9B}JѼv)}5cJ6mڸL"Ŋ>}fs <ի'CڶmkUP.xQ#ys:_.\(k׎=w_`\J,cHg{{&[)S&ۍyʇn|NvɈzRlY vKIB606VB)RKwT2X2)d[rZdQ7hz$^26:{_Q=wགྷP4HH{5JK*N=⚥{E1̏96 @\ P+9#+Ղ 8q/nJ1S 01<ׂY=`hm!@a,ܪdA#tkT0YsDnOM׉ɥ[TSd=rY$+!RRŌ!gT=WrPF?s%)?CC-jxOX\cHHHHH  cNp$v?ބDI B cF$@U1a a]t%;4ol6xe NE0+u+qcTuuuq}бFjiY'T;|I$n926f>Ӳo s#4VmH?zoc.DB-w㪨cmW{/ 2ˋ1yHHHHHHHH ظq5J~$  cVp!$ Raz1vI=)ٵxNf}{BdI%S? pD$@$@$@$@$@$@$, ʵkx¥yٟy#[\4EI@9ƒzRNPII?NŝDjD0]MTN*%츆aW*x[}Dy S "ZM";U,жL:mŖ9@VQ"/lA+etU=+_"{Zxz}KدHvma,{שmy aG?=M6B 2iזocʉܑ7 BHHHHH cifs$@$B PK7.1k.Yh,\'1<ش|4kL.K+>*0$kTx0UA6!Цec˻<Ԫ9q!Fs hϐ vKʽD$ܫ,RWGgZvRBʧe vX/DCW{5j bcO ' ڰ!eDgqwQ] PS"9UC;䅳v(w;4'WO^®{򮐚$@$@$@$@$@$WJHH@ZQ%-ZfMꫯbbҨQ#Q\R P=SҸqc믿hQ`;H V۞+yb(೮˛ %l I /2;u{ lY ۈi*NjFV bVwl<`hTM:t]`}_/ ]1-CIm {)gtecPt!R[D췊bkPĶ"IW1"q ڌF$@$@$@$@$@$@$>SyR|yYbD/TlݺՔ9Rzhm'9r!˔)˗O*W,-[G}TdX]SLC_L\g:ud15S_|VSʲe!}@ 6] 6纜u3g ǣK,? .TRRdI6mB~>E @諢rY*T-F9Ꝇee B"šp*@ԁ R"o.dnڂ*$+D$ʐ[ڝB06jv`?$2_*g4xWseQAg1lY<"utx2 5-;B.ͽ\p5lQ,{-gcݯ^cE'i$@$@$@$@$@$@$@ KUD 3 m&ߢU{dҼyss]n]Si&sxH[G6ep>hQ }v8p9;ǎ3N0Ar) [|);wCeeʜ9sdϞ=?񂀴`5! 6~Gkζŋܣ iΝ={/ٲe'GA^zξ;v0-ú7E֭[j 4gy&ZK^v=<0X]C# *|:O> >nFSl{x3blXO'ϨA ?IB eMiGx! Bk]a3%E1?jx9jŒc-չZHHHHHJIi_|!})cҥJ2e}lqFi߾m1Nʶ[n2j([>:߿_gn m'ֻ{8El͚5ұcG3?}^ ~gA?29>}H+ |C`ih̝; Դih"5|[ # @ kzUOQ +wӲ( ZwbVuyQoGc{]ZWbnM"؃'}D'"sq4       Omڴ1[5| [v |"@exzr{BDAe uŬA| Ԛ4i9G˜3gs+h!<ޜböy9ydv1Ɣ)SdՂ>N d:u2e[l;@@`xEiDJxa9mU|pY # $1<^e7k.R*Zu+#.,{|@=^}U[pR]%FHHHHHHH a0$%}n/9_~+j,CHDXm .P+RHP:vJ%}e&M'x^z/8x elpp@ ְҥKO7hc= BX 0|z[šG ʸ`~< @J"0HD~k6$ꐏ ?H$@$@$@$@$z @|pB`2n&M'|^O?$]t1ћlT"DM6Ӡ@ "c@X+xgo߾_7ߴAqC駟v=sB3gO v=֭3}-RٳgbX9߶m[ ľkժe;Dڵkg9 U͚5eFĽa`PBYrpbcF}Lr! m},mNg[iۿ+0N(k.9r)k}Qd1G?88xx>!Ƚ1;~2<z==ux4]G"`C6Q+P* @Hr KXCDo><`V1#o^eNQ E`Yo!%ejz'׃{ˆƒd)9Ys O\VJ˗/7$BCHIgEc1bε@4 !2aR8$]ނ1 "ux'qx9 gy gӧO;9P\I]]vENY^Mrgք##@aWԜFvx߂l{ۏG HK2oE;j{_Q+PZLcOj~WwTҹ>WO^6"     @>v#e͚Մ=m9N0p˗7u h?g+?jmV,U k=6ꬸ<:z@` ȆS;wYfPi-{qz2dCn[o-Al09.^05sga >%K6r;WC+ƅ2>ٴn>M왧ǯ=9崤#@a,}co*̶q $@$ t4Eʕ#Lr#CZU.2Ws2TN{t~K:oO$@$@$@$@$@ɀwlؖ԰aCw7=y9[e _V| n0N2eʘp*׾cT s _/f g6X\ٳرcYtR;E9;be| a=!`Czc}nƆ5Efsپvs7C@]w. $+."\P!l\Lc\tZggy @?&m7j۶ !%y$t>dAm͉[s"IYEWp%Dr d׻Dˊ6'ȧD^7@8qnX9C7G"     !ڵk=/?S{=[ԩSG.0@Fl.{hY+Ts9}_IrWAHPrT')r!B9kJP-FqZSFɓ',9~q$;.]-|モocS"LۗǷI8 F9u_:|&o!2|޻?IH Mdk "\RC-#R2KhqQNJfsdoqjjh4      D x!D^xABao2ࡅVVr~9,X]uW֣GwY'|1x@x}z'?񼂈6~P~c'F>h7 D:oC5pAZ~ۻ:ڵ3&N9r[6Nܹsq'v1Sb3!DoQBDrAL7o|F|u8:CrG5W VBe֭ԯ_?=m3f8籍\SlxPA,Jhp<}͕'_UɞC%a4O)S 1r=2#ͫ0JWh_;CmSLf͚%K :uJon,@D䱘 yW^; gK^% cE $;6 8jBzoQG/AV )*wJr\Ǟy&7Z+6P4      %Їy5g{|Pvwƚߊ'z潮`}l֬Y#˗,~˖-T[nQc'%\xQd ђ\85 @ PI=)E $"EWy54e53!2ac!.sz^D^+#܉x9 $ c9YΜ9#Ǐ7!/ӧ%KJ CR~[a^`I@S JX q\v(̇$@$` @ʪba"婢U7=TFyl_tB'{8󏅆0G!    AX\ iEG~4   o`5sHEj,TVB_7ܦ PzݴR=SF$@$@$@$@$@$@$@$@$: :)b$xk@# E aSPXME5/kN>_c"KmJj(!eD? z|}T"ڸ "ӌF$@$@$@$@$| c,,x0uԑ<rըQC\+,Udԩl29ti[hQiذtU09˜9ɓGʕ+gkN*Vl>79}I9ܭ {6_\lZ={u,M zZנǘK!yR9 'l۲bjoDiCU׸sxww߮Ȧz"ɕAdI;tG]Z(d6Hd"wK 8;mǎ/G3gΔ֭[ˢELgy&Ztܹs :=Q۾}{߸ƺ Z~j ղf9~@IDATD1R=f._$ c1a B *%+L#8lz{ :}H׈6+n nH8 CO>ѣc6i$y'|CX/R6m*5YؠA㉅>ax<*W,?{|NoX|RG˜?2,'  dTaGQ+~Ȝ"y3%|비*M91Bw@ D=&rŪfb @n$?FyNe̘Qyo {'UV5u3f?w\ɔ)4oܣ< ރ@I P;HHB@ GZݧ^^?! k^dWNu]GOl:“"m6ڟ63s     H:aaaһwoR+VL7nlNZB!<<ʔ)#=z?S\"< &3SZ53>D C-ZH%LO ⺞yI˖-sΝeFO06Ya2a ,v*O C={ʵk$&1x=~.Y,N:/ })زg<6f=RB#MP XATT@ RET齄@}793$d793;w͖y9Jʷ WD¢Za!O?No/==ӦMn3-zMȶ0' ˜9B@!PNo{ WIZS'Q%bo ּORs(Ѧkwz^'qB@! >;wT0DU'N"}9n4h@8۶mQ{LJ~Y޽aw}cǎU4>h Qc13fAuVbԨQJMe<+XTiiiJXAӐpƌYDb.ÇWyӡk1νŞW.,Q3KHH͛Pv~YI`|rIU<hz5/DK,+LII [k׮x'zK;k,KX].O9v!%_{\lll eG! *$U|a[:{-&N x=rGo'&B@! @`=CJ&ptM۷/6n܈#G /^/0ruq( @ϯMHHV ӄ dE\Oe1\2d"?>$[+** +VPhҎСCʹ?c~`ዅ6Ι-Z(ۧO;ux=zT9^?,\)g)^a,șy.\̙3b>M;?&YH#0~A,goosqzmhL*iz]{>Yupe0_m%aѮzrdZ(Qr{ҺB@J~bWI:f赬MAQryhK?zP`aAuP?^1=s8µńB@! IL%) e-[TB~SvM b믿ӓf+晫Y`cc14pMf-Z9,aÔ}|ͼh!ݛ߶6{ֱ I'c;,.zq08~Ό uLMMUv=;\#{sX7?o|A*:ƞbg?ÐEs3m`0(:!>K0B.{7=( ,ZjAbQe[qcܯޡ^zUִEiwL+T/4<91~bOSFĪC)o1NR9,[Ѷ|XPosl` sf5}QOcB@! B@TGyDZ~=eb1hȐ!ڮ1c(d=XYXx+y?TDͣ?{mݺG\Qfx>c#ȋf>tPSN{UWuCv=g~R}뭷HaGM\ t$~cRy)a[laY|1c 9wi8te믿+ sɩ`(;# zx5McN3c;ov:k?lٲK,Q_|ݻѱcG^$ZMHH3g䐪Ђ>MG)9Ŵc_{KC}Be<+V̙3q%E4C]CQq\[nQ;|mrh_]iS++꼢})"Y㔬~r(ooE3ut@kzǴKZWDGQ{p=[lQ<Wegc-H[hwXh"t-[K-|! @#O*JupP^KC X{ְ&֣0^efcQ2p96kH=5WbB@! BD>sAll,ӄYs<i "v4ҥ9HB6`q,  z{}"Xm~ka|t! jz,}p \&QC6> 4H)4#jzљҮg,HPC+&1@ճzmTh '^*sҶB@! @! X/ i07k*a8f$Di.\P%k! "ѣ01! B Rĕ<_e(uQyX"p!ʨgI|f_R$zM \if mi`etbkB@! >}ȹ Ty,vmݻwchU8B6a6]6! "20s9QHُ݀$he7PF'Hb/$&*xML|bw/䑶2|Y0lӚR8H$[|E]/\{e N,}y8wG\imNsh{¹B@! 3 2e ƍ7fkkWb0o޼>yd6k҄~cU!tf< B-Z )"&$X-E]R, ! c'buRE0s$.WEYc,`ŹĶŹ͸1 U=Ÿl> N!$uhI aq-+o@WULhG u??zNkgSZmI LX8Oi x#a:ŶiڋB@! UK@B)V襤$̟?_ xet:4j={C=]釈{Ue}MkOJu@] (XzYl|z`iIJ]\B&iH,Ѝ/y@60,.c/2IⰐ,fq?$W[=d;]kCe'ʎuSC6 s{$-˹غy)B@! "UtR! JE@R5c5N85 +1jG*$3缼hE]-ud-kK#pKs#CB~v 'qɫ)RʄB@! @aJB@!PAD Ҍua̺F!PW#/(/&!̓DQD"P5vIjKjM'I{#/21! B@!PDjҟXa/-m:u:u k֬Ug`n%ƍӋvuEbB@! \,L}\C`9nnN'S5f5皖 5"0y],KrB@! B@]!!!Xn.^LE/m?""۶m׭ncj8{EC)F"&jj]1 ! %P_5>5!rٶx5"vͫ4=(> elAx )d 5G=&B@! B@+^z͍rcܹ3&O\L+>zzs}[lZޤ>"Uj)/6+8&&M|V6BB\cu&f@سj*d\Ŵ3YE؉n@ww5Y}$ '&B@! B{Ro߾-b;dQEJU}}Z%03x$O=o[7s W) dwGXY$½ z0v%hC>D@V7XzB@! B@Aa#6l5=܃UgS#Gŋ"Ҽ ##3fPr5hh׮LTfl̙39s&z&viL>ݺuCvv6P.q:HOOWt ǃ>NwSmڴ  P5n?0;VTU)% \lV] g''4mSx cQ,N-zroe$ježڶ΁Qg ,嘞lrMpF@"eꠧ8^O[ZSh~xeC! {- ~T -9T!9_Yӌ=^8 mpll#HKFn"%eB@! B$bəB hUI?|g7o.ᥗ^ŸI&᭷*pŵ{cΝX|9nFEX3gϟ_|EtazJ6mp*X'3=x衇кuk+Xd 매3f BBB0uTxG0w\<s[hZv튈zwލ_~7 ?5VYוP"URΝ>s?&!M1|i &1W|(a>#u$dxEYzrp3dWW&^H2GJHJrv$Ĺ9;Y}uwF$9SAr.v bru'$_ox`2읐+Z'=,˜tdXB@95}^HNZXEG'"ͳhEҿuR1N[P_5Lcqy^nc,X|B@! % Xy B: X"2d}]?>B8db+V;?tBS~;o߾`f͚a bbϤzMKg/b3O:__aNf,걱W` v%rƂڑ#G2s!͏?X{ձ ֻwo^:l@]ƪEE,%ƍa Ou8{ʶ'Й@v<cL/\/i߆_y :U xyc!Jlȣ˙|l aC^[$d%E7 Zl1.ILE\C}8wMd6ιp--#yA Ldعcn0f@v\r9# uH]8]ENh3N#G8؋$`Hf_~!E16:},XNqyɉ`,}hbB@! B@! JKC 8&~NJ70myܶon^77 ҥKUE)<==5Q 45QxXT60r6liq޽{i#&/;i煾FfZ70G-z5EZ~YZEjy:S @ h~>xe 6))4NN8u GZlhX'N!'ŀq=_!q Wc`KV7Ӳobϓ,ۥykq3HLw:Ƽɦ2lHbQ,<TC R)!2MZB8Hds7^:avHOI-hHt&1!ٶB@! B@4/.SAHb cЊE ci=ǖ-[K*ƴv?Evefҏzc;6(+N3n5S.;c]=b}EcQlYWɰ= 3rtcFHgtx n4G$!GV A:$7C&^*nFX>KZ[2a$~eH&c,b'ĩ  =8c!(죖R/1_׎6r4B@! B@!P)B˜4Ԡ^Qӧ|e֭[ k9m ^Bo?qwZ|Wj1,nŲw{d#!NaO+^b>˿g7dk1N!]F%X/52͙/xx{#끬OȊrBedGz+Dϋ$i1ۓhS&9Ƒٵ,*9ӓd* Y$teC_/Q$ %ҹʹ1i(fc}ZC ˆ1HH郴L>κxڵE>fh OHJQ s0fڒH:HK6]bW `˗#q5swr0&Νњ\ | )|ߨ1VrG! ,"\c4s-k ?kI+$`x_F 7Bohp0B,ַ9E+#5t1B@! B@ t ۶mÚ5kйs”[o-(alɈʕ+k(`Avpa|>|8lmGzM>Ν+0ƢEEڭ5NdgsF^c D3Q7t4l'CN|Is1lcAU$V9IR1ۢW30tEG@`3ӛV3HHG-y1q1ApNhޱ3?ĸHSM"($<,-Y=/Ǿ lt (xxmD|\rܐҐhs4E D!* 0:$!Go$odhZa v{ r3(#ȉqw }P/ !4zI_d y>ͼSyøf%0r{TQ+ 8 \4B+q搰'/'\MhٝL&q'-~|sUZB@! B@NsOW_Gp4*ŽyJ(G6m O`ƌJ7x#>̝;;vݻ{aԩx{QC-Fj ǎQ<-至Vpfّ#GСCeĉZ1Ο? Bvʕr߾=h!;uT~9m[uv}ݧx͞=WVG}ߟVVҚ VEhlSn18iIzo?z,VlHYMz$IIX郴旧ܢa~ĕpw'b p\&z{$37LjͯM [4;d_~fĨ\o$$bj(t1n,٦!)"l(YNm'#',; zr5M@˶oȉ%2_}׫Fn /Jo\>U[";À{_׊dMD@e_/ޅ 6F=CaG5GLTvı qk2񎅷N՗E$mwg-r3XTӕHB@! D=/*˫ÚS" ooWbþ " /;1bEѣf͚K,0M0A \y]*ƶb ̜9.]B˖-vC [PKWD1MIJ3⑉RNN&*~FY-,\ck>E/#4aLG0:eMR~6\S '_ 3VEXB$ hC.ɱؾr (Kcؤ"9Jj(."I1c a0DQG\(Y2,fGaLs 8R*s2Z8gPn9{P#}uq$ܢ͘H!`遞w>T ఏ60$ىSH;=m88Q4ʭff,Q\HZX9"N{G#ɻҁ^{z,74{t{;B7FȍòJ įZܟ\p8Qơ~(vUp'B@!PDTҸB@T*4a}^h}Wc# ~=Wɵԟ^xdw jd5뇸+} ǑZ*<<#=+ 0E4A$PGOE\Mn ^, Tf\NddFz\" / E\S :>K k\\Hԣr5Rz[,+*sIӲݑWf ۛFHpV=@]|vk?%L -ЎʀPFX볩[xU579Q>ldly6}ğ".d̫ he6v S gy,jGd Cye)eKbJc0\DJyf皔9Q9Ȉz~c(|2)!k{Gk(ʀM1c"ݻL[yu{l !p5S a7Yg? {)bÔ.[F"B@! B@L]c)87/ x?==Y >ldfQH[psCj6jLri@7SY87dg +; ی#y夣Mۑc"'+3ЪJG~99h܃εũ;#h i9BGOS"I󌹮Xn6 nٔNl]r|rp[)|g/nV&o/PFݢIۡzgBzM '{?ZRZ6-Z_e@*#gVpv8vgSm>IYpp+zn`OJ*kl(}z NZ5;*B pnUO2S/erE4fl`=&vx21! B@! B@ GadFy^, D^L.[1d"Q:;<Bڸ=9Y2m]1LveS3yLjBUdӴ,1" rgft$reGۈ#7!%)Z9?9:dk嬻kTE+ k&EvmG)}ǀ,u;ĝ̇B.T{H(k@\ńB@! jlIB@k%@8W h"Հ\C,ϋ"Q xwETķm~f7tq8±rz.Maӿ]GeXĒ&(p,gfLv̀tŦk@{5rd8J^b(!QXYMI4[O!!m dQvE#ՙm! B@H@xdB@E@uՊ0V:ې-oesw`{d_f{*SH!23yHHR2CjGmJ@j+#/x %Kcl4qs̙0rEX,cLL! Baݳ4/&L(t-ZC+`مŋJ~wyPhR,y O>s۷[Pr ""Biܸ1z;gϞśo4oܰa.]={5p.0 ٱ"YͭT$*f:79e2(=m̓OeoT5@zz117?Q+10 ͱQfD7 oz찳c,rޱǁ$}L:ȼ2?zm o$UdE΢ B@! @" X]un9_1b.][o?<%22ƍæMн{wZ*8:IIIXr%ƏSLgZ޽a~ cbŊx1j(nZϹszj|gHIld.yxx 3b1 HX-ƬC@ЫsR퐇~*%ȃBM*VKdggm#$G%w#;M}CՀ4 D ı!G$t#O2s& 7 B]T㨢h@$coh[GebB@! G@1'2Eprw ko( k*CE[Fr&'jaw%$ikF1{C #gOK-Z9 n/81! B@% X*`@pp0{۷/БhTsxD5صky0gNŦ۷/vQ(BE.\P^|wu c| NNrZʼʅʟrak$ Xr!2cN+|D@ҊN7Fyؐy+{?S1H+B?~ч(VA$y}=8ubBx}*n}h| HIR.%os>2$c]Vj=@IDAT֊*( p@}m #{B@! ' XJ UC`J_oFNo۷'O{WM7݄z w}wce-XnzJxжm[iwhWBJZT+Y0V׺EuT. 0VaXz~8:oy1G+cI@q>x6u*8;z@&( 'ꄌ p!}f_n>&7 U[JcӮy$p3i77Ҳķ $8D$(f*iZ! Bb0V1'e 2DX3Xtnڴ)=jzW^{q2GNJ蒘=z 44Rwy~!f̘F+pA5|Zʾ56Y0Fń@&f@xl?'cl|+h0ddeCLRN‚M+UFs+urN5/7l{Ǎ%1:T84 ?ظ]!XS.`o݁ZX,=#+ qFSF XCQy>H$ѿb-Ű.;]]7 hIRG! u~JL'4q9Rr9C3Ll͊V֭bO~WӧHQsM>R!܀J,GYܹi6l"q! =cZiÆ 㣴|lMwܩӴ۫W1]v,_7 ++ 3gDN{׭[7%fQĉxwaϼy[WѬY3L8))*u"5z뭷/5aҽl BJ@X $Rm'V_$*OHM?CK1~L6&\Ƃ c?Xl8SwpZ7C:/z F *iC*tWc?G6"3){_z-juN> 1-o7ll5uΐ7f"nlƍ0`@~}Ӎ^z &}zdd0""e8M +*Wٳ1|p~0i\I&)oݺ]t)Ԧi&j%ǢE/^ /Çcʔ)6mZJS$nO?+VW/\+ЧSgfǂcߵkNsx7kaq`EE>c% eNSsܹp5bAN3a'YcQ_ič=X:t(;{cG6SqQP"_VРA={V)?̝fNѢE :DOL"!xpuU0gOXM2+K^rJh9l? w=c*>xB 52KK=Z<.;{Iovʚ]H2W]wwޥ];6rXFfG]PkT]^O, ߁QTS?ϥ "]Dc_\u?|+'aA:18]z]t2ZED!4>S8DoUorPgQU<@ȣ=X.8⑗-&B@H ^ ;};M.:BR8l]ᨷwDu5Qۯ%OOO8paaa ?AEcǎ=7ox@HQiֵkWm3ymws3g夅c4?gB...`q#JkyL̓R5 `|aKƞ}lOzQJޞ>XĪxU8p'hyf3f}ix&v4 @_(ۖso-k+M[y\ey,\zbx(Ki|-D$c^R˳lNZ@^HBep38fpƺx^8,݊iY$6~wp8$~#K۔u@vv&ioX,y9#+,o|CDڑ &jME4L("Hំ׿0@,hyO"c?-"ʹqn(}B@! @HO!ӄG> b{z6;I|}u0 xUG`a8khҤ yay8, [}ǹÊ3M1`2[q.go.2M*-d=8xFYriY\3;McOp瓊3=سϏ*\눯}ɒ%{ ㊸==z(Ƙ5s0o"EɯǍE4ʬx0fe/ fͅq=uF8TIoK3m[ mol '8Ӷ].dH!D],਷ޖ Ll QXzl,dlxXfQu_pO }[vm8D9Z,͊|V3^X7sn{Hω1B0!t#8c3ݭ_JLX=940& IsBGNcGˆΉ៧;6L&' gͯxfn=דP@4wP ]B;"k! B@T/s9,CJ}4,xG~n#Ա >r;͝l:>}GxЄ!6?Eߛ8t:}W`;` 025OcpXuA BU\t>,NwLq^,ck,6ydţE'|MhYBAjhaM^Vq\{LqKE S+*理~!/_${Ǖ2PYT&Ъe |YXƯggjEVW2ౢ$C)7qsa/%O*~EVoZto9ҷXm=@Qۼ'q4+`'~98>mlaCb]&⣉/ř#}v TE2ь3zFO3yb=M/:mߍ> P?"[>3ŀя%*]kpV889b']ހUŽ1x4T8kk;=a;Î1=aqQ˂ֲ6y6y}KM~ %>6Ty؛>&s5m_B@$PI3UyWg7 P}Ga[q4%މ~?I?ӝoNܙ Bel]=K?Y6]{ pl|2"cB3t@ G=4_WϐBv۷"޽/li&r)~^Q[nUΩUYf/faͅ1v*1;P|M1uΟ?_Hrzr~I<9[DDsI%ś~++!Kp8ӧ}'O5Okݪ%W|َv*X /ӊWa|| zyGOC^ǩ> YwфN0~ &/*ElG)R~5uR8jƞbl-c簱w<9y'̀M2J6ac[bۧԟ=YQ}9WX+҄ ӱ2D[j̙ʵ͞`"" pHR ;f>Ƣ c/B-sѣ`= Pi駟Fv03k4O?CJ[_;?c-ˆ#򹥧kq4qi朵rKW5jtmFyDv*nڴI#Xe{^c/1ʹmmڶ.kYDU܃4C1?K%o1˧֟.kiF@r]cQ;V<,2 >x5 ed 3A7jaTPьIJɗԼkŴ큭!99xCIDh"b3{=:O^O*2 V)%9}b%hpDNrйP>\WrʩAxf6@KzTvB,n"Q2՝E5kCUX$co2tB@! cg^M顝*xs.{&}ġ4Wsi`!tech, 1Hc㜥'A0hLᙹ0w@?eM~\j_1V{e] z|rQ9 sl9::sCq26jт@Lŵm*%4,ヒ>@z쉏>R7YLZR7?<쳅ʋ+p#GT/>Cx'1pPlܸ/ĉq̴x<ݻwlbk(Mq~1H㐖,ڽJN2/55U.cǠy8pr!,njiӦ)% gVxػMaJVsG@e͞c NcM8oN ͚6Ep^N7 ]1VN͈0VZb5!X W0CJ=6ɉq/4W{)k:c/49 |SpS0y<$|yKK Ȣ`5ӵFDSAB/" S؅a K*O;l7y`8zF yQR(5a=\:M}ĂYu<`iRK;#bwRkDG35.>+A>]iXk.ņ~ȳHOYsMjĹ<= SNAzz=5;jk:{rm|rJCVYSoq_V)6"2S|dzDN2~#C)U* *&NBz՞9"ERo@!ɋ2HBj`MD2Sj-Bb\&Mm'֝Wc㰅gӌ&hCǸIihʼaD! @&b呣 _?_tP*0V_j2GE-M)/HbT&~>׹'>~z2i_ZfR g8_B^t4gqS]y;SD3 h85{eV3Њ3X+Xcsq( ,4SgrpRϫk€ĉgVmؼa:60&9Cn@Fh"Y=U*Mhco.Y4<\\c0]Uv/ -1pA#f.okyG{gwU_NHB{ޱ! ""Ŋ ( bAD (REzH yIΜ̹w߰1YL$ܢ(\?9ߤyRMH7YΜey[`v~梖k:WTkRYH?e"Ww3O2XrѨIO Vqȭ2" @f>8=]'yDL]Tv/pS mv[Hy+XA%|ΘI %j2oe B@!(.B U`smsl>%ؒiqY˅N-$72XEb6\@4SQI~6(Mߪ:.{JS!P^1V{}"*wz=l8Kz`#ÌÕh9ickc2h;oƸo? ̯S]eNqȹ\z͙sYA+@l Lַf8-q"i֨󦼥#٥*sF|}T"/yvnÐ CZVBBd1Ec더wq܃bdYUu4s2䢨ɶ؉;oTN9ۮL!P(WB`oKy?1`-MErKSqA[J.!TeG{EM-F)sb\fj0q_9 A>aO*X-n{@l1W1VF B@!P(b!V 1V3 %'>qD>| TZVjڤx4fc}R8dݚofJQr,$D 69 dxE |=2vJR;Im1F3K̖lOlm'([-:$[$ kv!ʮatZe B@!() V1Ȳ$…! /-[/%p45 (N2.;bCV*U4XE1VwB@!(bBՁPXQTNYd|,&>Vܤmw`T4o%V<1! v92{v~16V_٭NN4?i"Or/^[$ޣ׾cqje2b19)_*=g뎜(w[ǡ]`-e  D lIr&4>! ey%IQxF5!:rDtʧ+S(  8NE }ϕdI0+ҚSP-#4^R&r>SOa0u(:ڛ/SosA^kAR!oK9iյ\cuϩv+ ڃ"jϾU=UXnQ A'Ly>V<_Wᑤ!6 K_y=R-Pb@-N~D/SMoϓc3 | >@k oXBś2! yB8u-81}[wF/Gӗiu,I2^d* kLGmT I]ϗbSSB@!DZ6^D(Z]xӈdVeBp.+`rBpǢJ{D=䠏"iY^YD@csV+ ڄ"jޮE}UĘe쨄8LrVnGkP0fTj3b툱 ';9q4@:=;NQ4Q9s@נ-33 X /_HόAV7,n[2q4Wq+:E '!w,ޡ+DŽ`'1q~ I&2QVoNp=G֗4Q* e# gKia{a1!71a!Sٶ#AtUF%tP 2r@S:i0޿$ģ8VA*cT61V98X> .Ą .kh-o> 7oe֭|ƌ6meDEEՕ# a 5֮][g''KNKȑ#矱d iE!p) 1ڑޢ >6 vHjmΦrU0[| cFl^\m[h١]Ev_խ(~gYz^ x^Υ֊ ǧ3k2rbݐa =p,{W@UyR~^G9 #9ȲT8$ߌ8T$P[Ű6. NkB@!PV z!(͉g}',+it^ZWB֣Ht!2OɯAy-dCu)jL*)d'7=vo ւ.]}yv ڱU/@jj*5j$ر۷d\mGܴivz|1}tDFF>l^Y Z[,U\q]#╈*(zEee,U>EUj"*2WXoI5ǞG\wI*JLƟ^ęm;᝘T'{G?uI5Z&oLPT:v 7Šn7ǫ{JoN 1D遽`o #3V69X!u_38غQc.V# C~W$O<}>Z*yjqJņ&j&RQI^2qհzN2U#LN{RBl2U /0@x<9db}=4䷲_FuKdrȣ ^ыh|]ar($;$~[eRLnT)S"1S4w>/2^y`ׯvڅI&᭷޺l~޽kᦛnl^i V\ѣG(J[ϕ+-UKWm mRĘ%ՆrG@ciTnNL\B#5F;mz?.陈swB^lm St슇?? BU(6`I@cqHn秙\%*,HŌd4c3GFpRbVUq+%G \8 Emロ/M!=urcte !!F֬Y#Fm۶fP2mڴ),Beڗ||71}aIsfBRԩdYi S̪;#cWEU6!far,H^Q !֒ٲXqr}Z?$$@ Lxq#6q&Dح|%E@c%EL-_aÆѼyn/Zwqȑ-JK,)Xr1X/7Q}իV./_gc5-63WZsb߾}^BAQՔ_}ӮGbҥOpBo߾w777̞=R:ux,d٦g޽X`>3y?͒W>¬YĨRGa 5U,&+&PjꅀcEYe֣1a8 [lv'^U_ﯼ (z yY2x:xih֬eZU3C}7}&M&weX$&c͊PqKlg1RN"7Ylܨ/?wRt;*::90U/XTOsyN;~Ln{픧*qv5B@B&"F_Bv&DAj΄X ??7iR9 0-N͏_L-bA0r%i޼y5r[n8<&Nm۶᯿5\yWچ\i7m+n||| mڴɓ!D'|Roq}i}6Wq)kǏ]w֭݅[k3ВpRgԩ?>^xdkqxc%׏Uh$K ||,LM$/M(_DI}e.Xr9Nr8$;.Y!hj$n0N[ԩ|"{A/b߉v6ʵu?Yd>iցeBbJ8c<"r3QJ~HS3\_1W:S588n?=͏5< ʯxM1ߝm@'@#TX30)vE#Wrl>K4bff&4h̊Jn?޽'7o.'kkkp􍉉IS˖-Ӕe, (DϠA4Q~A\iWT ]={B SNSN^=Pi$Alj'2WmFGGkJ< AV'}6M)j>4OЋ-Z@DDTVF,+[e:1V5,K tmCxz,8|axkܓpv4|Ҫ'<FJ˴=C*jK:!L-nHqCl8s=wu {2D״{@ ^_1+|biq "p|chdօ8胈SKӑ~.^A` hjB$[J[M1tlN9O|:T:{:%L S_Ro϶Ib`> ,~j@q?寻 9vwxyNV8{ hkZGJ (b&EՇ@@I8E!m6mTDOL!Up7M-gM$,͘_$! řރ>yE#m.QDmˢ܇~X,b*jW$3C[ZQ|zB@VɊZXTO?4TDhաƳQ9$SĘ% ՖrC@ceUK~BɦFu0ok7 2C1fy$@%1Ǐ5ˌpw8fdIZ8rG,6|̰mV6r\Qos(G ~GBBHGhLz Bo ڎ1nQQ[j9HOFjJBꋼ ;88")au`푂D'֏FGw]nB?Sġ{>}d`63?OOc+KULizqj8匩8%\ sp}PSB@gJz<.K<5H/cZWUT,|WF=ӶYY&Dy>RGEu%?8#${x[Jfً ?F=ZF`ZCk.C"̴Xn`Qi\WB]>|LWK^_+Q` 4!>m gI0O#39fxx}tNHߑ$b#&hU\O'$BґmH'BJE L!P(b2V۪nH8NOka7nGyD늄裏 -o (YQK2Mjccc5E鼒~7m! 4%d^Q땴]E!څmʶjQ^>FسgO[5-~}~,1fI{CPXAY>yO-c! bqTypu[j٢]`Mp4Mw_žEbH(rA,9SGe iH > @?vhVLVZ Dz^6Bi'~V'V{aرA^= hzr3Ixyip={+: }^.V( QsFGA<-CXrFwWVJ5T0 fF8%$B'0ʪu<%x282+_NxgɗȤ?=:{X{(= YH("{aТOݎoK9|8nNq!`GR6qL 2mѡm(nuڶgÃ#$ ͨ|!ZZУ3CGr[wȩtu:pIBe ML|&rrХ iL!P1sL:Kmd;p#Sqp+5_0EUbˢ@ǾWq/g(KrqOQ߄X܍0ZPB6WܱYA_JTgt$D )&KkL q% zJrdO2\ X;"˃ەzGrCJD (& 6$, KHF#,1ϒe9,-5E՜}zRGB(JKTA۹&ad0?~RϘ_c,kn$BO?Ÿqjijj*6nܨw0ܶ,^P\xҴpF-mF;e*o{rlL03g4]MC +L1!i u*11پUT[FE1Ye @uE2wc3qsStaBr2!FGMY~'Lt:~ć#qfYsG˦(/KB,d0mۅ[wa3τ!@9V$H< QGB6$o>|o"d[dvۏU>u)TtS_7hmwF܅XD'\śjh Gaطq:聁#+VF'Ā`Om$bU: ]]MTq Э[r ʄ\fGqkzJ(}DSÌ27)k?hT_k+U+5 镔_r,D~Bj|>X_| ^ë́#9v'kԟTZyN!|8 >jv gBXT&G_Bߝ3cb;QaK:N uԄT5]ϐaFN(& QhaHV$|b2, gIF繩L!P(,!A +S(;m67?G-}61g1krz2kmg ͵O%Yҹ0ه0~GiL ;2㕐6pE RpOYVn$4c0+@Z}Á7=[2~6&K3ò陪sot{Ӯ}+XfȺHJ }Pt:i蹽&Fb?^/\D[Ke+y}6 VhwO[ Ǝ!Gwoc.4'4nm{Ddh(B on*_*=m-ǁÿ`С j9*ǖB b}~<9ihטBEI5!ˎh1J$MYDMۆIH4Q(,kȰi)pKH$~\dX]zN(g1\B1CRG#դr<ϑsH !Dr?-5=D?$,~^-jLGLH&ר?xKO1r3N܎|kA-2` ۵ *0!Dv#2˿,P HHm.ocE_*Q( D@B)Jx`Μ9mzĈ1viM)t,) #cbbt&se5{i͌3\ .IXr2oŴe˖!јdծ+mަ}zj$$$C$dp;" \"6r;BydBYElpߴ p̾XP(66z={l;u F= o7j%!<iwR$ ]!n@6n)鰉Mᘙkk<If qDžD@V9p dָG!@#+b;+jUgy"`Q=ΙL1 6G5/v=%XCz8 'ofP$'F]FkyTgu@Cfi߷7f"#-S GoIAD`fZblgkFjZ,=YC#݅~=C:`8G#-gVǦ|,hĬG^ǚ0F>hڸ/{Y%Fͺ렛pa?W5o@Rct707de9-W&m6 ww>*Q-iw"c(dI;ǻb.FdZ}K|LMtIij2iFH8EE&$YkI3!$ǐn+N=K 2LSly%!-,Њ#Bt3-L} W3F,˦( _6=|8}*(Q[IUPƾ#jK9GZћ !&yCIHC!g; Љ19> +X7`kCQR 9/V}sn?Q2ɣ(Ä|\iق"jQ &Jۍ zZ=r=AI>53QSB@!PT$7pnh=wW]|s|8 2uwCeѢE 6r0UeG;#ŋk9f͚O;w^̞=K.>Fsν4::_~eA֭[ѩS':j䜄yժU:mBvQjJYv:tȨNBӦ| :t~(՜Xi)nZô-2>ocƌO>DK˒Q!fWQeBbL*eݢ."r]ĢV|B(d3kV _/Grlx~5m'ڏv$$B5lIeps#Ihtzh.v|=qKVxL@pp0]1/|hr#MQ+&$0 HY^MdLz+I-wq[:#'W?}w+Z j·76== 10Ģg]7lSԡHKN@y@lZ3t4k7+>'NM:`S^k {~{ \H[wIMԵZ@vqI V26x1g@dQ&L6*Acc]Bڣ|w{NLQF⦰L~\H2!De&dڜSs"C-EbDFͺ(5"Y%SJ !L[yeK)I6w*XPGO!"<QeY֖,5* )Ut=$S]<$1fڎ\]%a$$ Ųn.=?DFBr1,&9 j_/zsrZ%F$3s$i}nIt YV> cVq5"Cȫ42/aDe`Y'9s*-(Bϋ!D5#"80]TY:Վ>ESʄȹn/pǠA $NP}FK򯉲qZ#`e40⠎P: 4x^v\wUODe*! c/|q-TeLiq -H IfVP MID'Ъ&䞄۵x(S(*EUjK B1gE-[Y,v*E m?Fj5̵bQ~7HIO/Ii~s Ą\$ڝx\l LJe S&+wRow@0{[iHOO$!Sp XZjo29;R2&kj|/ȵKB==f̉,3N.Gtg譫/n:eN1( ,/lneFh3tv 6"fa'Pqđ/D%!ӄPfTPNM˄(3T]R& {* \(Z#!{UunQNF'zDK2}:I+! |kGOrUa5EY>a&! [g &fNjResTy}=. 5 A@cUڪB@!PE+d5B@cE,K^%<~/;UmB"/OC7ap^$xLC 1"R'C ux l32aCOAfrE(ǥ5/*ɒ6m=q>t "5rš&~eʤ:._r%BX#ܐV *ǝ&xljQSۗa C4  ܌Núp\&A#!'?7cFMV^GZdHH TTauŹ^ YkNu"2>D$|fLH3#d=;f;5;o* ɞθ[FW,bZBNZMwc:Xǃr?)O丅X v;w_T2sj+iIF$a %<3H-Qu)~e6&q' ֕/ɯՐ-:BzRx>9*g#pܑ硑ǮX {,q])ܗz g&"r֖#4gggw֮3VQ11xj3ȥυ Ghykjr28d99w6&m*LAǾa,vAcC14MAMݢ kGY+vk˶ܰ ۸aH\!:_ wFZ|zyN3\.ί5 )[eNEfk;0ŀ`;ZErI N-PQ|Yp0H^~:QQ'J}]si~N܈I SJMOչwuC 5$u nMKWZ,3 P(",dGf ¹^ w~*: ONC$!ݝH``Xk Qx-9$Rѫ~aCp8N"~i`Svjb~N<ҤzeL|⒓Ne0aR{Vu_H^ 6$TZ~ 2yJBQMtu{,a}H8Iv&$y%@"晔hYHqC Lԏfbf9ܟB͎琽]~^&\?g|qzK/1!㄀"N=Þ!11$%*`e9DtÆܤc"90ћ&%j7Gٝcj AfU?Ѫ.>6>_H$g%K%frlI ^eS0З=Q0^*'<NCKrmҕ^@L{pyX'/Qn(~%9ԹWԲE@H=EnNeophVr@@cI-P(U"ƪ~BXP4:i_geLZˎjQbm>#$oG:; g.^p'8L ͸SЇrmz ܘG(:Pab`#7ioqF/ⷝޭ;Sğ䕕Ԉ(9)Ԋ%R}XSʤc7=lHe&$"\Ҹ^F|b)aȡr*7)$pxXQY%6#flto|*XOEz‡.l' $YbXy#;1/9ȲErssmU$0 ө1b<.%۴niR*6CO𐾮w{qE03Ku@*j2A߰H<2ILe "Ǿ8 :$v3׏غNU\>,kҌ@@0rf"2])<=|4$;IϽX90Ti iD4 @t= ~ŮZ4SI<ᱛS!gA-/+ ,Ó*KXމH a'ĢIBMF-Xsʹu34lQ1&D-UX svc8bW Q̷_.̺RhlQ Yg[H0ڗn) 9itzҩmM/K Ƭ]ɯ.=apGBMB+{"?ؐGᔞTl-)=0zt:Z;9&iM =lәzd?3Krن I.%[񥼷4gOMT0eK'HDHweg^t/{QG ǯ8K|\SVHuϖr{NdIC *3aw^=0ugxu1{ԗP ڀ =rEێz-RN1V2 ߻w/ƌsΡEϣ-""O<V^ݻcٲe󥷲\Xt)z)<ӘXY> Ҍ:!drq_|^{M[ghӦ R ֭[}g7s̩4ו E ? `JuHǦϠ/!5W|0rHQ(î5fΣ$A%%a[БL9ٖ9 A8t'id̳DrnTSRX_.w i@B,YWhNEKe)G黐eEvuk\[j4|Ipc4dщpww܇n j$BOFÈ9uM$ڟW -*$5kR*.Pḃ.%0tv<'yX Ƈ\]MbLtd\V4h*"8ΰݏ# .p=:"KtF2|gy<^`0lΟ]lzYiY>>  Úd+a9ީCMK("cU &6.dّ箔|V7IXL=Ә:&d*tN_Uz&9Qˮ? /xy~ z%ZaI[`}0ad_c8xYr} 1+O`TTP^8Ԋg{jK4B&.W Rڟ+-rj_Rp7n܈q8t6p2ފSNeepA#N>m*NGMztӊ̵ty^m|?~[n&+\]}PXWW@ëJqada廓1b{H5R‰W&[Cɥ$<ݜi>7kWiHtkі)hF;q(^-f"+:<:\;'xb__Sy;TK'Ţ=\I6mKG9¡&~H'X(<]p亮xhjk .Q)67;oaf Cp{&׽Fdk}GޜnЊ`afl\H~"$tP /{$ebFK=y#-QQ&VPmfˉoJ!ٔU=W ي! M 63'O88WǙޟO H~緓kc!ǐ' @r!Z Q'h?D'nֈތMb7UXaj\$BFkߞRut 2_#nڴ ]2B!>}:"##S^{-(3Bt*vt%]^XufϞW^ywq2uSW VVX-ɵ^@˗ew`ĔwZ@+*LM .91t*3ڇ-א-[9q?AuݰaVɷB2=>b;AŎ0$]VuIW[ ٳd] x%idAn&XX1^ݯ?ƑSө}j6_jBT9BA)>v$!T5߮'BQLF}BO QFDJUH4zEW_Qʺ+lbg13+o^P 2O[/kVm=LnջNk,c=uX">-PP ST9|OQͺOC܅q`Xmu㐥 O`T'8N߲{k6FEJVcePP=xG5r_Ȓ­Tv¤I[o޽{kn敶`ʕ=ztjGq+KYIYmYGoB9s/Ru2SVVRX-5bLmF1V6D'z H%! )$CdEOLʯD6i UӞ*Ĉa MY@ vmg3݇q4$ 1 ٔ$`.ElN*يrMC E@D4e 9ܳN>5$1wGSc݁3\˄`N-um#SH(Ί8*m@K|=O섴'Ԕ|\Bnzmq$sֲ6*>J-VR6JNnL2Kņ;gNeBv")}PJ2c_mQ%F__W(LlҒBq"RNb׊k‰ןajBE>>dNbHٯy7|kh3տR!RVY#F fjcǎiӦMq`5E9:LpS#m*RUsI%fIww}W#4'L3g^Te1V~ m?ӵ3sm`1ia5eʌsh߸^ r ÐTLswOHNe(E-Thcжi4RRv I! ܨbR8 &*:OMfh+}z)V1TE\Ъi>HLŁ(ֱIs9:cHx|\ZMIh nL$3QXs(x^61jcgC+Iz8ǷIY&eCIژB邏NOeRt`{vͫ"?![M+$az,7D,=Le[m6˄X{i zDe/$ەSI1S!P[1)^_&wL}fZo] w !"% o;uMpaDS1澗$G"ZQp3 l{5xlW?vIJ+b8DO=81Tu4;>~ɁGM:>Yt}(,o; x], Oϯl?r[GC7}nYm/!rͰ2LVX|8?[1f(OTUT9B\^@F4||T B4 'v_d[OkI5U\ jz[W+ XwE1v--_D/WLthRޛ*Og6k,,] ǐ]4a -cV~˂Ņ2o Ș. eW“"p1_"Y~|zտQ#rܟ`gAhY?4FЊӆ~fݵŊ`aP!3V9{NGݘ$-' > O?Exx쩔5v~35], 3^ z(7 e)Ibn7z8ǜ,Xtr>N՗ MGG/bƞ1jŗ VUNS;Y2BQCXH_ã|,G"Vq9rIDbZ~-3WV~=2 (d܆sϲHBmYN1egI0KA! &Qi# bvRr*RT(tB~_{.og>$Dɰ^/`pbKl /-*bvk#b.]yf 9ZlÇk%ֶm[M% dffٻ{7A k4F?[$&hbDczU5t1]c`AH.. RI73oy;纻 K1JR)bՓ>=,J߯U녲LĹ6m^z RYjLb-k<9U>px9r$ςpN:U1VY[[4lȅj 7 iGu*8c~zd4\u)ڢX%ꘙ߷o`yʞ ~cׯxBɾ;:i,Pzq$GѣT ;8mF]ؽ)@K0&D%9EOKG5&șzPǶ><ˣdiCop1f D`caA: X;;m!Y1,dibl$\LL 'SDj8%b@c*gm&UrN=#Cw^Ix$E_v-3p1'5pCG_ӧRʒϜri7|j *h"C?nW1#oD@.c`}"ܖ-0Չ'} *bDlAZ+^#AD>J'g@R)$܅`ߑ%/OK]@-E ̅Пl+aMɩ&5uf2K/"cU;Entb+bk^Pc5u-q&%WM+dg9 H̔Ζ~s"^# 䘳hI >CC:} PEfWV.R|f@IDATLSdRmy0g5Ժu\bJ={`֬Y* &*ZDzߡT)?~SQSٮinu}'&6p6=VB19mWwTkG޹Cơ?`^OAJlqHbL _.7-'d?W.%TB.]вeKB>yd\t 'N(x:Ib6/{ 뮆;CDx7{:}J:#%= 4 řPsL7fsrs+)6 >ۈzɹd^~:&lf~-̬lB! G-C"?[=N4OxCti_S4{gѷOo1N.#߱O4-1 ;xv6C>kRWKٿ:msrahlEPfx8W>nvu2E@iȖ(SciXx$@^n`gp!R~<7w.)mg"|dy TXJsݢO͠+%1V !'N_}mN*^^^xW:~mq#[c~>иHM\LToooaP`^}Ms3$`Q2J]ƣn Ve-T=[O-*2y*6&CDuRKqT"b^}/+acibPȊB)o\' f99%YT6>0%%?a3=aib4R Zޏ$MbgWM%y8oc9ڢyz=q:~MO ~"G(\1xIŊ#Vl!~3 u]0W[tiSf:DȽ˸pI(2r?L?Lzh׼.+a^ s)˰1:U+ǡ=0cBʫxCR:^]Z6(5#[?m)aOz>|n>!\0Dz碶*\)'%o)5USuu6~Eئ."Bq^{I&"S32GdB'9- !wp x{'ƹNd\z=S>=_~[y 0jGĒ- LJ:<%YPrJjU 4mEfld#Af0.sG~-_X9fI1.!6혃j D|xTPJRIV$G[&ŸeH$ A%EPD ]NOY9zgi}WY:ֵ3)ƴQ8!!⠰rG[Y$@Y>|8eÆ b ?8.4S8[øc(󓅇V>-Ji<i\ll>QShXq?m3!mҥڋNܧ*cmbp܄R&؍7ШQ#SS-~'KI}[ӼZ ; V"1#H$5VeF w,ƥZ XԄ>{qn _^3_NQht6TU+%,/8=?*{  \r'vVkm޼*BCCK4vW< ߇6y/Xhn~СC0`@zMֶģnNKdīW~W׿P5ڜv /_9|||HAAA 8~1u:e;q');ر-*.~;F idhlo éͫ6P-ŘKKPdA`֭b}Xv-{bB`7}۠+E: o<$,YE1}?CT@)0 #"-L7:13k="h"BYhդ>o= ,<߉ğD|m:|¨ms|b\{už(4 Ü"""Jt{akmX(J*'NUV&̞=_ oΜ9)l>cAt~3|L4hucg\bȣōf/\"TRd"{J[XS}G}(dŋE|=RSŋ-AE\\-[&H/:~Pyn6˗/Cyz-c?\L:.\lq3֬†Bu*8T'_ww8m݁}W۫X)Jb ^]cNNN7coldDio^)%1Dj)S+0Ǹ4u_bKUꪝ=)57#n(NaֶE Fsm?;K }4/ wƎ9 {#1SZ;"yS&ëv/?Ql99ꫴ], ѹzϯ–dEjekYSlU3S2abi-+*]G`3)_GH$D@"P5%@hO[yD>o ) y"~Eq^K@n%-S[)cV3&дp_:ʒ+$(Ǝ+H[ǏGrr2֭[]YK<.<*]#F$MΝAUZ,,,LL.myƧms&HLLć~7èY@cbѣrRt|e_~nnncU6$$DĨQk rҥb7|'NiNePUt+֗:ט0{WR$1+WQ1ON0clV0}Zo%15T|qPzttw1ai" @$GН[M*mcI}".K*3w/fo0UX%ތī?Wsf_~B֎+Q$!>97rQz,нMS{'l-֊11Xw\:\=~Igƞ8d=z>t>L8qukJ&'wj l c:"hA_ZzOՃ q0=M/`WtsD@" Hj L2PXv64,P!`A@MqoQ3}{AQ-&ˌL ?Uhxqu9":ҫD=UWX9KX,gH$GG@c<d:[7>RcL0*2SUmj_cZTҳs,:$554?#cPFPG]ؤ{jcR%Vލ$"47gFSkv`=M0G{ c#WSѶMk!YpLxpM6&'䒵lF0cuUcvɮR" Qli-^lI,T[}2WX:Z &*.jK.D" H$@b $E!Zz)Ym,,F؅L o՛;l @˄̕H1[W%/71wu!ry$1V]S" ^$1V{}4b}uܹ#$VVVaY1{5(HAPʁ$J )N!n MI7_kRt4~1e8D@" d&"=6ɣnmAU+N)Wy!XmY-^QbnB$-O>7vylK)KX%DXc^kfTd8sL̚5 ;v w^ ,'&,kXY¢ϽB=< #LfQFYv286rH$WNnri!HL}J[\eNA)5731)m;{˶Sxars.hHdاT bGA bm'2a<:q, m Y)E5d);X7UXY_F?7xKvXA֨E[{ܚQ~džc鄕sp5eg`՗#"$|3] ;i[pD@" HD '+ #H0=<];[,l%;Q L(b4 Erlt.#$*eD@ceLvH$JG@cy홰4b,001cΝ[9s?͛7^MDisD&cSJ '[,śW㳕;Id8XD%!:1E(Kf #HbKV.vBqVgu\`.:"ZM*Y9N^ 7+CziiivwYt}>XlSzjd DV2Pclv6+ !ˈ$.H$.c.qIir9KOOѣGѯ_?1ڵ+LMrGFFI֭[~ ^Ν#E8/GPT.gÒp)96=e|9H!t2}|WDEF*IuTJW^J/ŵ~:$r\Wz[Trop)Z߸ {)0 -3cǾ`PKE )Pl'ш,r: sW1h1?OI#/톷ovKOl?)/*h>kÕCK$DdO|dBfJG%rK_^yK./KR} fDx5K8s30|trj&;΂Kb^`+'?} 4Lh$ƴJvA,Y7xXd7ƅ c…ڝ&>hX[z%R(p.FBff&6mTաTfffj5|QF֭y++~L#V*ŊI.w)ȳ޽{իWt%15T:񋃗Ց@0QfH=װ.0.go\AI*T M((?SIX΍TvS|ʭ8|>cwEg&8O,qqq_J> K530wݠAA}!{/4 47JOa7x D ::> 10MQ X1r,l /9סjx5x z}~Wq$D@"-| Y8?ҢG1Z'uBf]Qvf^v]zf9[i;mN )gSlts!`R"F̦`ӂTQVC@c \?>,ܹݻcŊ#zoFGGcʔ)رc~v^*INNƺucԩx䙶GۿTHxxyyqz*<<<*d4!!K.ŧ~*`wf͚!55U9~x _w}sG**~$b!jIY/bΑlx#}ԩ+YssH|hVqIhGca6E, 9562DYЇJ.49l|Z!Ksz~ްy9y'b)#.\m"`JkDB]p@w= ό}^|/u!6pvp7 ;M]({w)B"6AaMXMqZԙ;Ylvrm"F6:X+H$ =- s+r[1H/.K"WKg6|Samo'Qsl,alsm,L+,•cG؅ɳ4xvH>QNݹN;.7^ѢRغCYB@cZ$;8˗/ɓT СC߿ ._Lſo]t CEHoH11;|J]>a9Ɣ899 M]ꫯ ؾ}L]?YW=XN22" 2?{ $b`R.0W+kV[BKNKE UH3Yj!wE)]O76M\"9{O9m}!`W¦-[OO '9.k# ^LU3/,3QlS ?sb-n\;{wl}dG p[7AލCDs=^ZtAvIYXX!=- v.r+H$G{ADn]saD\!p8܋8DOI>)h[sfVP y)¯,C0#bL+JJgdb_J?g=%1V}!iii_>߿SNa#э*ng{ÇT1:E6=1m11SSNB={ׯ_*-5cy駟_X2cZCOX }YY \$jA+Szf]隷vӇNDS@HSP}b3]rS"6'J-H0%vGuw.EBt Ld];xϚ!}Muu\HR,ͩ%7h:1EζZsrr,~Y8^O@¯/.cvwIq'/ ّȾ'ӄ2"ܚECz^=ػaŸ~+hF9D@" TwTI1ZX-s*d% ̈́`B>' K?I\=bom^uШ7cWnN:,Q/waX0ܩ܏;C#kǼҒ{L:ĉG 2h`w̙3x뭷_mFΝ=߀=j͛1zhDuItFѫth[kkGEcn,|E>.z£1*ïT♹pŚmɺ@HjTe8\<;+D|3в- Xoíгtiiƛc8["aFm[ QDtt * гӇD@" jJ .1c;}9nu>\wuc8aE 1g ),|yGYqeD@@ĕ9=^[#5ZnK@@c%#v!CмysAϹZjz{{#0ao%Sfjjz#'%%cǎ bmmm/iӦI 6<tDm1oo-*:9Zr$jɅm˔Xͽ1p>D$+$Eվ.Z (DŢ3.oby8sXc0w4^QfΗl٫!D(fq辝nc޽{pC×y`>ˇyn<TTx9nn8AO޻h7h9'ӫdd$ѕ c}35T +Ǣ#, dGyJ!RM&O jFa~<2%>˿ )9a21Wzz2%1-HD@" 4Tsg6Cdk;~ؚϒ)7I0 ЇMI6@dD݄zZdE,=<\No>'OO^? ت Y"nERn-*.wl+^<} ;r6}V 0F_^kzjL㫨u?ָlK 8>~h5HiI!t8W |e'5Yrag :0|z?OOk0FJ$@-Dc1!(AdRn/uEb.Ā_:@ pd"lj:]e̚@(x+W|#[ s6|d_~\UjQ_'r8OOOs;.ƭK\eG9ܖI3yF5@@c"Ci9dx;o9` }zCTgo\A͊M+~ŚûD[+FhӠIYwa[5Kzo6Y84 A1Rl΄_jIB'"O(ml &̏(9T+(Td!N!"Z5If=4=-i?K֊QZ~]U+eD@"('z&ug8y'zd}؎lUs=tDX9)rvm۶$į&Mr %j%TV2sq)N'&& RbE?&fHEI&T!Ԃsytׯ$e#jڴ)z%lҶ?<|ICyΧ u eAqVZ;ZSZqlܸP)aUɓźS-%k"*6kJGall ERXqx,Y I=n,G@c:~1OtA2֦]ӘS?( _g+̔eСxW4ƨ짺U]s>8$n߾]1Y4ncU4EI0ٽz q3wb\|Jbi-B{(OLXLY~ض\x:ƿ;T3)z18vv=|ѻm4m3Ɖx9Ѻ1F| 005uvR} \/F('d4Б4lSU]|H_M1#EGX6@м/ܚZХL;ٹ:]m"F=eGvH$F /7 :_4 a8yr)gPX:BJ=( u:9 u}^uJ]MC p;Gu[WXy)&N sԩSV^^^x~mv|TJ#a4s!߿_hhoooaPRP'-,Y7xl4uESʾ+1AǪ?Sq\_bӧ ͛7S(ӧNզV۸.]$T~~~~jOmtUcfU"_6kO=L#Ec:r!dc [RXx";#ɯ>mzf_L_2go\k߶<nN洌La} z浈 r~[pTWHςG] xVA[>RFg-4uq %ŤT] <ǑS 9q60LvG=vhӳ+Y.z%m9٘Ӏ= gABuU`]" TQOS"Fk1Έ|\Z&+O#t_ȓαV͢%1 JOuBm 6L(XĶLԫWO,  r;vLV\VZi\fi$v722 KKKERV=z?G݋dM ImM+ok֬8OLRd>>>\cGy8v.9DE)JKyE{3g*Q5]G,L^;|%!G ePn5VMckэ=ɈTkJf*]g&~=Ϯ;lSsg[13ڹ)u&PD@ (_ӿ4X[/ÄK!Kd|"Nk S17E}TDu=n)|0 dɨWLn% A5DR)HNk#1 u>T#7NѢC/m +'l$Lh87''eD@"-)YЍt|nIbO\d?@"u} ,ҡEơKbLׯp0Pd޽{j0!bW_Eh"GA";0ڹ^5˷/_|l7СC+Ԡڵkb]4ŮXR;˹"y\J:gB7h ^͚5II\*-m[scl|28r\7U:>8b~ åOKtpي mq"nDÔrv)nF߭XJXc:AI$5"ݭq9&Kv`γȥ\JH8gNC:DrZ*>{x2·^Х:bh?|=9vs%eB^׎xv7uC>AKVb95y9)Wh4 }xx`Hd![Ava{t)G {o7݄HfDby#~'|󧼁 V!"PA4 ޜ+ƽ=e|3 +4&H$:@nNSwHOEB>cr5\/i4Zb9YIt#Aڏ {J$&08"l1ؿB`>eiӦTE%|+f`kA&T˗_~e˖Vij$ &/_.08#4UeTTaWK۶mܹs1VVRLyX /b\(q:0)6o $*ם)q\sS<ͤ}j(HEL(B@* QEkufAqu;RҌJ[W{= :hs#9;{ q10 ϼ S Du,v9E։ Һ$>x7OE@RJBʪ:ze{0Pؤ" '{0^5,^\rR a D7qj6]i%Z.fef`#Zs1|<4,`"#H$!_ r;dS5um3A^9YE p+`./Jy~}>1ES*ƪ% P֭[1r$}'{ntJ<&e~B\l4u^;ㅕ"Su 9" cbKv؞I&`6o\VXAφE{QCeڙ"##akk+NciL^YDk ՛8WJJ Dous0):o<|gqǎ07x/kܚcY)mySlEh?G""!Nup;6 V6q{޼M(ՊRE1&1ի^ %1V .rQkDxgeÄȄ|EdEWnFٵ"N^s﷮!d<]1w4iU9})ud\It4\]܍ 0% 1|_H\]ЦdQ@zRԷ@j4C`̛YYy4ۍs,Iְ6l&-`oMR6l# ?@~ &}6u!'5amOMÂugd >k#1<n}D@" TA@ͭRՀDu@\v4m|I"Pd&?b'VAb'Kb^4V;V3_K]?~P]zTL)U( #FsXx1䃲j* Vn1Er+ ER6=*ȾmE(=$$DxgϞ'F^{ L$-]nnnx71qDe8[Ɵə3giS4&9FFFpppsS~~~B۲ƭ:uBA?~-)HTÐXqLdM @@c5"Vҳs18#f06^vfR=VAa+mF|vR`caUtINMChD wCi|e(AaL$ ԃ1y]׊zMYzW''=vӁA߰-2 >D?py)!L/vMЬuOt؏,AEGPT ʂD@" ;) Wym<ֵPDEʙ}E~rX(12RH bYWǢҝp$1;BF"-0Ç r[‘"1]22B@c_8Xt2"zs(cPu/-_-'uh_z+elOvW̧/O+́e=Lw\9xԏf Qmz`#K@n#φ@&+H26 j!qz6GzmR=Me \j 76ؿs(Yi(-rkKA.C" 18R/ETNB?";3C 3].N% ʱdT[cE@#h"HbL=.# j~+1n5J27agKk *_;{ ,[b|g_fpl8xnEb % χAM'Qα``mWpE,,m edpy耞OM y #H G /iI7pap~u&FjΔUڃC5,\JbL dDt ]vf+@5IK[&}˲zgNcƮs"K:.&ȦI4T] {ku@ 9-_"[,+NޭWZ|Y|$IO+zafѿ3s GĮpf EDܭYiqDGS*d͈"Oq֣͡4W[W} rLH@M #SL3 lb"9rzd1hvJn%Do̪>&Կ]!>s0C9B!&HصU~}[sI=BI$@~D^|Geꫯ*f29jD@c5EIbLʊ@DrWoK*6#)Q%um@xk<xt9߄S%y<i8rr@a4xX4Bpa m |:>׺nP2ϤÿZ,j01D۽A{F \r o8YID+%Cτ^iz[tD'P,D"ym9nH2O8 c3 \D@9 JJ je$jeT*SNŪU1k,Wj rꍀ$ƪk@@cե"o5dhaD7YI=MOCc(;9dؗk"ll,,0q0z]W·F&Ţ㓰l\IN>S㠟P7.Ip=z'Ŀ5%zx:)̕Us{WbՒo 4TܻFf{=qY.&^ax䥚ʁ򓙒Lۻ -&@ܕH$5|z^ClL$;E:|ع J$$* Z9D@" +' 0@ћFWFߌF`|^WP=[TTH8a1"؞'E}|1hRϳ"ONMq.93~̝= j"(C7Цmm*-*q?X`rא?xc`6\M[dG8Se,D 7~X v#)$2Ӣ$=T[Y$ K?Wت$ƪ|9D@" h@m! BCvHj5#Ձ,6O~hhvnh`FbkN*3Y$'[71tN]B^ƔF`B]-Ʉװ%Kƾj }!6%|C<6m;=A"`fF###ۣiӦʷXMhbcfN6DY *ǾNMXJ" HNKka 6 ^~Pfv6^ x<0Pİqqst4z%ߞ v >롢πka׼ v>.\&r >:ҳ۵"kF_zD']u?aEhD@á vU^@LRWiL,"[MR wORϓ$@uB ^oܜ4aq$4R`Т:-E*YC! عv+t6 Qc׮ e7ΧA/uSb *JcrpO܂-Z`Ν,J4lllx,UFF&OkbܸqD. #%%E,,cW%УGA߿*Bs0E1&1~VDhTkϘ߬E)udMʢcKO^DX܊Xew[S#Գ@Kg[yL5BsgJFdC#peL_2Wc7M8Zۖ\/S'(S+tqi"(%t(H1~h߼-Tc Fמa/ b,7#C#. :V^80f :ɲ;1#,D_'~PsXԿϳcAzh@$Y]#cT5K?BXRWc\!ГoZ yN'H\G!ƶnK/ӍxB%3#0ulM33EcꐒuANNN^WŕRǏǪU/cŏ2E ziz;} Xc{c2ʈKΡHbL#'O(1Mpؘ#QŚcR3p:"R}ܬL|V\%ڙɵܼ7:Jm2cI3VQ'Do6տ!-3V칉xS.ԍk DD>(^ ;Lf(|"qY#D;Xž,vC7vlQ F0wyrܿud%0h : 73St1AoYI0S65:oC6|UHb](b텓Iu& ]n*PceXi};`"vSb-ZEC3 n1qL}nӺ|8n%n\wnȻo:9Ɍ:t 3ZN0/D!B>膼 No$y__ IA,D@"P"5X7,k.z]@i(5&FMIL3TMSռt{J)қ}d29sSY̽뮵u0zxAWv|m9xQ\\3g*fX RQ޽{qqY5 z-|7BJ [,=Z1^847|pC1 I5rE@c[]iX:y:a}C}C}qy%e0cXx*yEdh sC}LBNBpT>Dyӏ Τ4J3g6fnOOc_aWqK?Wکc(nŨna6\.þaIEEjΟ+ݸ` O+*K1_w%["3#t+13}$vtGI^.8 âbgqzqe}0%kGV+N4D3***K!D?kyH$(UɿeIc Ɉ$K^W?v;c "8p*\+L.ŊvE;3\OCZaS΃0x#ppR!_%V PuF1!%w\͎S{`G:2[F@c JLK8-blg%ax, 9^`3eHMKN5JSڶrSS Ր~_9D:`0pm#lmQEgl4W{8C^BOKG|D6F/fQA~xI8{1A=1a@/##'eH!?7)ݪfUS5YNT=WFd[_ZA_ѯ_?QσkDZ.[;pN8>邈sFu-qHbLsd6$A!6+grWl#Te?\2nKj$j0LY95fh'sR\+s!!rߢ粴i++ e63fc j/jJ{nxOŧf` )$Š L W[:OOН8y 'O%00$e=dN9p~FEV8OPA W,Ok1z0&$!й|q0? 'hR֣!2$;O%8:a5J PM_:5`uI1(0ť@e5\ tO!).m$HK+_HZy)YI֡c[7D܇d7o܀2;egׅ{ o_Aۃ]H/W aTd#%v }Շo/D~ӛFA⁈^7ܮ+Ҏܶ /@rev07=Ws70TKѵk[Dv"Jbnw&(䲷KgrJrHYVVlmڴITs\r9___6Sسg8״i(q1c&>ZU__AJ ֈ{ 2>8(} ȕ_ʵkڞpqqr>}(_J&l:* wwwQ*1d%?\]]+/MGCE83(728,# PHbL  I+ ugBVtv% rE"`9_1[c$tDSdBcJD르+>{B,Wӡ2W2j1;)^߿/'] |qtqȲmV\]t+&*tZQYtHe 2f̱_HV^X\"!cB֖0),K^8Rd6ѣGbz`?v.ryȬ*J,v-Pe܄. =Q6^m\nW$lqUG4GĞ'RvR ,WdR5eaRUOݫ3\adSbƍ|۞U$[1)Ms%L*1ZnxuQW*2&R\Scm^b7*E:s{P}QN16݉oVŦ$TѐIC) ,$kƣə8CwēfUD" PH9[†Š?3WBl(KF`=xo #C4_m_'G[ziyX(v?OU "jHdҖdeLUOZP lRh]U蛚>8ND̶[q׹H&{P\$E=QĘwNjHð>W'L BaIȉ>>}8BAy6UZX<8trsg#,XL5d;>kP"ZG$ mt2lD9`Xju@3d{kݩ^"p~cN ^o۳ZeXbҘ)b/A+^R4/ r6@]҄IEdB&8ҹsgaS]CkW*j0EaXyTKXUfֹspR2JJ*^[1/ZbhMss+87Jnvk`E+T&[&BσPq1^}2d3LvcIwKHb`$"P\^\LFqyEaf7KSP_kohfF̈4v%[kPvvv×^ƐZ/(9='Ķ#gIͨ8?|:aƘ먰c ?awvcg„ߺ+("%Y `BbhǾnLپ_Fqj6ڿ b|p!0g{@pAa۽re+ɇ(kxB)/)|l|8|/TY_aXh>pd4;_CKnh{BH4wmXv"p5,No]JWψrmkL;W!HC՞9)a׬]7sq1"+9zJzz )X5,rqmu +8sܼy3|Êa ɛ;w..]*\=#vl57UXUn+o=XiQZ12(TA4 ][hڞ4[4oRAI!Kq|׷dyb1Q|B$$1ּX+/cg^JQuYaYBYF$LAX(@{\I %͉wtάȶsu0$1::Gtr83Utm\]6&9X ZJ5 +mNo#r5W[%urEp:,AIL"І(-SƢTU ]bhm@@Tlzc=zRtt; 0^C>҄pss D}&>859srx-k5%Q`# c+DI)کCLxxxv_+} #Vq,eޫw޵C\ZϭPxkrk`E˔ECُ O?_~%^}h!hq["{ڢ~ O c3=@c*`$ϱ+^.C^I D1VE_s(U":Y!Duʦqp1?HՁ_ܧ1ňfml"к;%m͝jVE?l\'H(s ٘9|87v6F˧\]*Rљ )C $M+--ÅhaDYR9³iY(bldƥ%dk ? M$ JoIyO-)?XI1$S IWy(08Cy׬jA6j#D)HZ3S[Y^}>˖W'ENBVöLBâjz@GwmJV8>rJ@s Pw}=S 91K=Y)åKq]Z8@} ?L!?kwL>Lq)e,[LT5 cЭ[7e3ĐrEa z(OJZ> .\x־o{0|֭[g}Vyxx䱹hڞ4[4X) T2Ɯjs:VY[[#55f{~<29'Dؚyy1~p𲫩kXxI]Ci[N|9"`夈:{p`.7`ٮu`bL]av^DiPcfelܷ׷[m}Ai9rKN֊i%{3h% 1[S#]-FU}mWs` Kzj=mlf=Y#v. Ƥnгn%흺Etզ$E_a﹓"A?t KAQPm8p W9<;8b͏Tdg k ]:,p%U0IIG5ʢof ^[%?+.Z)p:'΋ƈF,ckIO>@yHI%L %Ij2Ry ЍVĤ"=1Gcp1u33F' :a0 "ƺtgѳ-W+4;!ʊ3ѱv=`us?doD?`D3Y"iKptE(r`dֻM/K^G7 HgWo50%hvXegg'Q+lϞ=?~pƩKTX=$ Q{EPPVl$\ҢPJośo}b5UT\u~`ذaHLLyx- !Κ5 ]v{'Oȹʔ>ÇEӴ=}r<>87&NJ`\VV\cʢDģA]*q޶X7}mu:TP4yVy )Kr7m哑Y7xm-B@*ƴ`P-ITE*[L)ĞgO֋3D4hU05Xb^*´1E$6&]LG+Ϙ8c+ǎVfBИA 64_kKo{\ŻK)ZjX(r!vrCB0g5!2ʹΒxqaOd-',def\Gs5 h{:l۴;wR ۅH޾~O<dג6RJ BIv̎bY A %T2bwlm^W@&fcګ`H8a4R( Wnw*| 5lm#Y)Z6qkEXg7v a_^:xY_@F j H__{Z^7qqbRӔMߝ5V66l}*_]'KD{{Zc]CmLRC` Ձ|Wxꩧj.H'|} RxoF\o>}Z2bC1Y3&v8NKN:mk& V"]> ^w<]nڴI^|E1jwd>}~~~Bhcp%j(ο5*;hB1&COj_~)׭oٯh\ꛍ'K$!ئ;10NRWxGc)7Ȑ!C)k|_op믂 gԺ[Oi:$1tXʑ$WdɚqsL2) ts>YDDT ֘2 {՘mMiy^)% <n>}CQصe#,mo`n<-;<&[c;L>x'=A*HI9Ɉ$(ͽ=9N$W: dUz[,>|)ćGa33pxJ? *vT!0F]a!ja}o٬ K$r]\%;N㐙X*Hl2 b܁G/cДc>'1}DY"*@-YY:tON)):(l/U=vjw1cJ^]0)UڬU:")=[benqzAaJJ(DnsD"8ܫtCXIUzP9La^EKƁpL(J]Ř^p , Fy➱#0[Vl=m{pzY+ӏ[G+K@IDAT!nZx/BGeI):a5mVn1n%9y!S]V_iebJ¦_À o@IU:X^Z oA'"@SS3t1BҡzD`XzgO(/Ap;!X p!%w 1FyIwĺocpȕҖbv=<4r\С:|Gի &Ta$rgdH$ [AMz$1H(cPc-ؐ8X:myڥODm 腯f@Z5'"/R#L$ #C 2x5uI(7.>E2]t(.mzs–r5vC33^^`lڽS0}7Q;QDU̹dU`bhWlڼ> ffH{ѿ´3vMJC\ Zp#8bS. E%흠GzN.mH"bll#týCƲyqH3gϒe5MAR(IsMy\}%)}>~8 ,͕|58 }<)֤{ߒl7D{0uuptbU007,'sߒ͈>'>{gaFC&EDdŢQg"ku6.~^t ]]:H$M@uUVʩL,<}ugGWBIH z/X9Hb`?y9h; 9mpp< a=\/,G3`kH u,{ 4No&^U8xLl+ːqJ$Z@eE.rjaM$ƚK9RE$y@-tB&o 6cnN}k#pĪUl2rO k'e$1vɎڌ$ƴ$!_ZWRP^+}]> o cmo6×p q_va{_kRS3fq;I«4Š L W&s[!33$#fH&B-yn_-o8 ֈ5;i_WT%8X 78eB/ǀϩ6D M۩G) x;zƭp!t(Xk*L)_ "4Qzݟ3{ee;(C!8Y\' m\ݻQ2xJ-@[hȈ߈3Pz5}CGd'MّZvd86@jbb[a$)*naO??3<dЏ?ףk׮غu Z8ZYYYL\$j5׷`̙3G쉉[VQ^uVnQ4kڇ$ƴȈ$?ƪ˨+voY/H.OH+oY\M2~F\G 폊b蛶 t5%}73p{T1u> =X-Q#/-ˉg׿%~}p ӫ2z"?z +adlfdY%7С|6Lj1cB7j@Zm 0 6nނcOC uX"pTU KV]Vxp6֤$4AK`'EcaŘ5kV*??NNk[u fSFPPP /_%$㫯iӦ<nL6Nnh/c##H4G`_BF H/,:buK?DV\+KU&6=c8a9"dM?rp$"og=K޶[9Zqmo(D]\QCLq@fz:ؾ,#diYb%X*̺&fyb]Ff4Cڥ8vodf޾ cc Ѿ B,v$D:Aq~<:ODYZp[Ͳ+|*{`{#(K"ІHN}Ϟ6fJbL3d;:)<<{ Zb/[cjÇc׮]bMc*#<"jXzܹ[lأ>o^nh'"Hn+ŸOH1[Rczkp+ݳsӑW;G~iB%H3q8u\ZL ɘ0ЃU4vFN>?mG^ϑ 3F_>rwʆYd:QDO(zTl4@+kc&& @{A :D{^,ܮ+zM@$,Z w|Hj˰ǬAp/Ӛ&i4qkEפ͍Jb1ok"TRR[,vi(b><֭/m_nĘQe&{>3=ztPdѢEBO>I9(dZ$1F&&yxuIl!4*d0ٿWmNݣ.c𛳰w7-IIdGIQXUY/.0TcXD#j;O\SAH@Yb5ӧyV=w^+u ĸcڌs,^o#UYKrN8>ptڄAHL?𑣤Ah>_%وs\9m.g>GZ]!f5PaDkLu6>ZYV}#}ݨ41w(|};zE0C(0>Kuo:]½St7[|"XZjtt?a8xG{H}Yۊ&_CUo'TCz:9DYGWB=ƭ]ZKbE"aDx{{p:nuC E||$ZIbLtšԕ\wյu$Z$Em1p*n.CXI9`WMDy>bR*S#ctn1UY~a6:uOD ݥs8?;o:`ȑAFFof e\&5Y#Y#/_\,_pe ֺV3f Wk.%| ە+WdQlS|1SZaPWF7qumdv 182 DyH-ĔpJ , L>٣y'nc+UeG$;ug.]hTP ؆plx8`ڈPעY%O޽g/6o݊ ZÇ1agk+ꔿqe$o+r+ݩsL \2foNOf&"Rk3m)z --y4 >.9 cވ^7.oE>Y))t`nf>oAOkbQn1LMpvlXN%~X< ꐂ*t_~>*-ѩS(x=BY``K^H<RA/P{BLUdV] SzuCØ?/9۷#88X5qDܹWF~}tAo6{Z1=ÂPO{ڥKꫯ&Č)'+((,;f}f~pZz 3f@3k0~xA>쳂c{9`pg,yw5{lA8]:wx뭷L19DZ.V# 1fΜ)UWe6%:-A@cZr d@ p*5ZqYb>gszr<\,LZd8ɭP2&UV\Zc)PHl{`Hz 拮'NbMSl&Czcq=u [lJN)rr@.}9xvnedQjO|oj'Jcٹy?<ŅLWBWΩ0.:e;kl} ww=hZc ,vj{K,)_0s_߽g^ )2 &=wt~7T*9p5\: ,X+ V=2M1v0Αٻ3үɦ?o&c Mk c'\OJ:99p={`ܸq6m cnK1׺dzMe D888 .G CEpİ2E11h2gff&EWV)8 vͭ*ڹy/##F֋|8o,$TdgϞ뮻+?|'NŽ{UnjӲ"ÑHj< NjLAƆx% ^V0TWleS,ا n$()+cz1d_A:Za}1"+ rK(HDyȎ?Q󤛗'S kxb & zW#v>#Y<3c$K kj+K֊' x*JuWB̽RwDxaЧ+¤'PAJRZ]\ l):ֲYAu-Gr,rd] |{2LX)C>.PeMtcP=W0}oLln6/hqZJRq|`ʷgC z-)Xb%\U3$4r [DąlTYhd%nE0@Ȕ=NKb)Pc)%4m^WŋUjm bVe7<1(Dx>%KR5ea;FwUJ׺SmNJ?w J]?M׬n N$TZfJYbNVC=zzz"rl~ 7|S(AVChvĥdD'#xuvI9.۶mk}TL2EHIE{ĘD@"мDf㝝&JqH_sGKDɢ8u1\ef&کsM=agaDԚ]'±lad6V4(cBÐndI#;wa;(\㋠Ç }51+.ZL8;zIu"U(2g0j0:N}18=K0aT|dd.*H(`%Řf/@t@K-lf)^V7YtBel PKvбJ']0![ | [GN|"zNgs:XuױTN3cAGr7=UcU~x()^@5}G:u;F۾d؝wN:ub[D/ds+ə:&}8w={V4Q%Xmƪ3V9M7T7Vu׭YVV J5C]?M׬n*0iȥŢ~$T-lȪ=144TWm+vL|Ecj '/qF!d8a!3dhtUZ$ƴ@0$VC`\set@}~-K0qcUe. A^]cB}P]Gxj`L_"(VKbʃv!lشtŅ(d؄cfBWUU5o? QSL޲9`ױןz6S"8yPheDdi@dQ__헸J@,T͜SfBT$9 FẁG,rnhaLj2g?Z@!zFc`l|=M4V?GX⥸K:eѥU\]z=M3Owp/n*2k oS#LX)6͛1x֤gYaKsbҥ"#<"8JYYYLX/=qբ.VokV7F}cWsPJ["##II`>믅rn[mz/?uГa>N9 p;'/CH$MU雾Ʀ [ap'G2/L[`ii ʘ$!7UזC碱x!$@]"35V\G#b7[˚ "pY܂Sϐ^H5f1難KH_XDpq^D3sRׄkQC+:䜋Mn_&Ȯ¤TMTǫ1ؿ7FXI)mO}$TOxztAuZR׈nSv0Г#%O(--atgE8VΤ$(d=7_OKJn #?%Lo.O ߰]mM,;O,6"S. ʫqy 6T]Ip2D`!N ?r|sI@[A =n R~C04i?GI3PƩ Gp~Y4?LX) _1ap3g*wע"a(7]@8'W77aD&e<<xKzo!ꆐ X\K* lֶX:^2ZDy6őL11-Ѽ߁S]HJƪ8,qHDE1]lY(-ցI5zu}3e@@ . غ};? x쨑"׋YٓG`dn& )g3O%?/dn߇뉆9'3Dt|U+KA(l=vA:NE|SmieXWݶp-F")&Yd7Wg큎a 2ϐUWQ~1RUg;ͯWNal Ȳ°dӠkzN66*2KӏnZr@AY0I,o _%|!ho)sއ7YD5CIIOaA*HZ=O"3a @b.YQN؅|6EWAfHzvmAt [(|̦m!{#o7"`a.3g`޶#~?AtL,RٳY/Y5k׉9s75}ZmAs"6&V^{uqHb!!NV]={`±.Qb y v Yf)_˗/o^1裏_3Gl2p+VrB1 @5 6w\0&ߧ~*Ҥy+UM#Io ={o߾"f5۲D`aan݊/o&~iR>0Q'_G#w\ٳDgPˋ1O>☥#/[2뮦SN_ԧt>tR;3. yLѣ W^yESQiCM ($3T̴i(o J`L'7!20Fƣ+WȝR3=-֋mC`oaذe5cBb"?>ү4qDRfg2{; qgϜS|R%si"s?da`WB6 mm4x'8VS >DEb$RW蒅_7\f1R>3|l+W;ɿ(\)@f9bg}m+mܸQX R1x{})ܸeU:2lͮhfBw!!ĚgA<'|?0l1fUx20&5o-XGc?ح5ƔV2zo$Z~[gdTtX hb=ItJnUx wq18qj`oS]s*&tsIh iE-f`Y!Ul}`d^߻wcמBj-Ch/^C񩚂G'$&#Ջ$^LRInqRIn1d4geXxb]<5bdiP~H3v(KguURӟ7,dGfn~)U+BQ1 `X_|GQX k /FEB2>̠FوpqGZsA@uE&.Z8DםbU(DUSŴɜE> 4~ݓLU:q\ͥ I'?_ (^yTD>/{[ 7[G"St| "QQ6p/wG[{)@ghaW:|[E+M06"&L2WƆ8oG`?\0rN[K Z]PJl}G@xi(:#奤-Q=>vws\hòo F%˴PM ]7J5X7L}dU<שL 8HŇ@Ab'?'rN0I>2y)-K`iV7t2|TlԅP̥y0PP_ yp Mm5}绷#6'tb^^>Dc,ueU~GzP8 _uUzo?,r6%_pr<=0bze_4h_=ppLk@f9]20r% %K`,źh {źu-uGeS_~SgdPpX/Na᎓<~}st0^mSdS/9w4Ƥ^:Yb树%/ b2&at|]2<*㶞9;vT$Ţ=chq#=WM "eH2|_b[VWQH!&Yν-m_^Z)&wfm4q)i6c솛,^A YpTWb瑓_=&/2Ƴד^ > gCӰFCmWjhBA:gv7|x)Q+P#?t䜀WJd%'Ә 1Ui1oHK/NTY{x0oizs7Z>w<uckD_S|Gj:G.&P;!\B1,V20֪[DdP#شiS]r%P qdÇg㱭Yz>t!{@7d`UZ|9^~ee9h(z{@Ƚ= {@=?)Ol Gl8ay?~ NzN]RZcjh*v>- úCLwƌ0$9%IldUT) D'I\W[kyQXXVGZJ(4 摬0}TXZZl'x"sΣ,5|P+¾@f7.Y(66@&*)nAu lʑei4SL Y XiBg4AopHg&~i߅ep zMۧ՝+ɻum{Fi7$oMMt (=}ruu5_AľؽGTZ@nr EuhCKզ4b4Sw}/\8H2L1¬qrDznyՂϐ``K'Fme6|.?QwCoSe0#c޽{E_yu[pp0^y}ݭ20nWD7jIroف3xYԓ>&p3sq6UuN_@/+LՆ0$!)'SÆ+A2Č1Pv.1 uMq%tuOL`oOFNTʆ'N#NM{QNV~kѯo0n1~>}.X>JOʁrr-`SXX7[b]mk) uH0􁙏u-+GXS,ˢ 1+V~1,gzu$ wٿH K G&Yx}i"-h>/ dƭ ;wiR>)OG⺺j&-mܱmÛ9.Liڸ;?݅,K.$90Q~_IzQ۬ f#G©_bٺɧ?"Ǣv'߇&5`4'9 [$f(u<8r\҉5$_N(5l,|0y7o.@]~'{|aEb@](sTV}k H8I7kql](s%EI('e:J$=Ғ!?/VyM3bVuBt9ðw WV>Csg + "̏L?FߑzXxն9rG$({P(ͽ|20֪[DdP#*X7c,(cĂ y/{@tXJq DZ7) l<"?6O*dPjS j/ 9G!B`m:jbdB 5* յ8`,!=[.vL "~n!jLXhay4eYyp FY<)6wwL4q8VYVvFkz ̋ƴ.K*UBXWd$1h7$>G"Pr)Ilk7<W"֡}a'N @Oۑ2JH0rcP}Nlf>T:V`S,3_OQug0= Qp!Hi;5eP06#Gw985PʈOH.W2diia@0|b{{52Qk],ԸG#B:"-]-8pS[e{1@IDATYbFCC F]+q00#VMZv`]ı9BnsE1q&ǿܹJ 4.j7 㶙X!v}OR޶PV5㷋3{&0y8skbk5c5ևm)(+iV~06q̭ܳ"c.lD 4k GzX/POceY4VE06mC%PKd/%-."f30C`I}1~(K8Ih0L*u;ɪ+3I=q:U[jdPcVU $xl?*|S U2ɤAEeIH/.{]l2bq^b+~n6m;ƮݻP^V&Z ).cc̜1ǟgVK򇋕I/ţ*Fj2=l)&8G@1BRQY Hf6襥jƜGމh8SO7q[.[.SH2ΓNJTf2ێ̢$60:B|aZFmGPZ Ca4$B* }dǣ|/h_?4YMlWILY ڬ e>{F%O{w 8B:#MHLWT\f^&={O_w1"M;w2P|JwLig4\k| Њ-JKRIPn)XgH;hm4l¹z)o_z@\:by ή#q1wo-Ip  /PB""0f`dCLG׿̴8 Ҹ4&،Gz ZI[ӧOǜ9sDlV3xlݺ?3[kUȰ=ؽtbcc`ڵjbڷU3MÇc9;[9Vau&~LMM1b[s̱FFFxGhѢK|cح|=Е(w<+SLDx;uer]Ul%)jfmr jփb%,2.U5pw pX *h}2,^V+C,'tKh5|ꊌPx?Rٜ%T+O*4aI(^p/컄OGVaM@kzݟmEbw7shj_1z-Zu;-cJbM]JȽ~E 1Yi=pI'~N\.nW9|g˭3^yEX[PRIt~Kij=й]߬GXVܣkpiw=šiuK|'{i~x70Ϟ= 777o'tV\-[wIj˺ac6 j?YĹK8!bJYi%2>t=nW/^;p*n s ab`h(*hR(_x5 ?fGUmp2fFD"E$o}pԖ(q3wP/DVL!ȱ:m$d?JyU߽@s E>QˉCZy2S6E^EiBNv-Ω5E j]Ge8ZX KVV КܪCR{*KC e='cj{i.끁ZkeZGT-U1|۳g?Pm[>y< c**&T~7xxxC $K(0cl_b8\6 ﵑ{&{@@@m}>=~D mĊʯhr@G&*H)GJ9RbZESܮ8BhTHBǫL ),-{?lB_7?,OR_lοVVS 3zBmbjIW:J_B'Y~%I J2*aKVYkbqeWHYXWGs$J1b C#Mr;cA|0 7tTv, Hf{dTYtP=dj#v=$AEZ9畾P{ji)HAˆ1?-=e܆%5|laz }hQ_b@E$pL9թ 1Aey@S~.d^ ~#>!J3~0*Pn Scckɏ dk̶Q޹I'I25d2k^rOme-\ML-Yuy .8O-įHRb5N֑xa1Ұo=/--ƿW8i9Xbl1;ΊDXܪ(W|IgU07wK%Z]PWcHʱmUsJRm[:)9_O85)&& ]Mhzgl~GG,_\fNYo5ߘ1clS񻾾AgDq2tPAdvؘBiMr T%v ydH(,{lO"dVz"ʩarKR$n6]H6kx;j UV)gSb3 )@z_Y iEut;lز};/קl'׽.wa0/i ĠE.'h\keՖ#u.xLG(MHa3D,1>ԑ/${ú @6Qpd@é/& o+Ab% P,Yr"3Sp,2#$-(Ҝ&=#}:.5ԅ %:AT$KYv(% {9ٳ%?C!ߟsa+.1|7}Q[,*M *`SUY }Bj!*,nzPYRV4P= ^IVO W ]1Y_Uw=&6GU]ZcDZUB?_.mFWL_SD( (6ۺ(ޛ 3(SxqqRZB_,Z-2r ^ ,>|12bWí߿ѫ֣Ze`.ܰx= PW)؝nmjʴUWG;fgs?:R߂&Մttm޼s14ʍ}!c*vww:/"}][۷7+$4y@ݑ= { iB^1T@O/`{[b kk7:PZt%Ρ`DKCC#3r"d1 io#[좇R_P^Y^g.1xشy Ix FolsSdQ 2|痠B_vЋO{ݼ`;\ S4sTnq,-0w8;wXbk[-s!̇Tڐ6Af4p{2:quE#jY^#V< }VR<#(/-DedðsӦ UfCUG%gb2e<=*?"s8<HCm>,]3a+C)(Hv[Y$i>"M'幙}o d0"oB g%P-7!@ז4rD =_mU)ܭOWJ+ֶ)uo+5`-`mW^,v>unKEІ8oz54BprJݓ2Uy0=ܪ uob^^^8sLչ)V]Mlh>@#{g{ut|snРA\7JSqE0Nɓ*LRR>T7]?d*(i>ei%WPWܢ t@$F YYk 0[?U5!dⓑ-5wG[쏌Ő o;a(j5"1ˤ/cor 4t1VtgǬx kiB pô="UqWʢΡrkvְkN G`W(p ~Zw_G?q_<.SbӪHDD/.b8٦U~хI f;/ҨAEKq^R55HIr,PbDzв+$ ؠX7b@ˬ(;m!ӐLb1h)/Q`=9l,$.DMdG*XJ X8`H )SfPH5R61I 1(&@ʡk+ } >o MzT\fhSE 9M-}r TKT(9Heohn}&ft t9tIQ[8QPGzW@qgJ7 'dIJ++3Mq  hdMl#sk0"Xxrz:+Y1aACh|88D F4QWW\Aya6H30moLFyA~yaXf15b1h":fjV짲rQu  (6exXZ0jpĎD;w_~}܍ɓ&}x:RǍscy9gq6Nl?XҵgLausJg ,|?LjGuE6-Gb]nx=K, +֭[G!**JĹ>|8/^,JR~fq?CH2g-N*ƊR~>!8NVrrx~{ȑ"Kg'~u]6lڵkq);}GʙjFK1b#G\'ͪ|֙zU n`~d"kO055ʕ+~P9xݻe`)= {@[ft<lj|!N'YC0-虞9d=]L " مd&1>v͜ޮb[\bNO@>-:}Al|~+()G\Jz{cGA'tEu4Ν(yz7dIj.7; \H#0B-L9{0]]Cx61&Lyq%4M@54aB2 aG+@5.#!f]TV!/bY8*~4jڸR6@F`Q=-$e0OtV `= ZmJ14g EħJbpb< uXs~S w7K$ɾ25c+$cԇxgcA%Y.r4 e>c"$' Hr]jQC (LPUw(N)^=Li%٥x{ |Nm+Mht?q}*Ҿ"c5 %9ؿ2m|kq4*X1SL(#3*10ƲGE(<Û[W[ z69yMnLi(/Juup!X]] {;[Nug S|j|hSڄqc;Z ghNm% {Ž*b١(Ib::F&1Uh{~A[bU+=w !3v:Nd!o=p` /6z7ӭˤ2x_s='[) fi`@?'|"d2DΝ+~| fcSOc̼"::V _Nqֶ}1+KNtz줅6m}iZz@VҔldحrq=_k)1Ob2{L޵ΜLQ^UP1nT㓝jb.& F?7,;WaG\IETj!DZl3SРJh@铏AI{Y8;5TCf ,4rO!V1l.3˴DDԤĵq۟Q|"B|^މ??A# ݎĜib>hx*ff[!I'o 3$&&ξ3(L pVs*5'*PYψkɊ2{g UpDU#‰Fm-ǽҀ%He>IRC[5h[G{L*'u PaM@1Z G!135 Ct ,"9iKӖֈ[04E2fHNr:-;*$@$,'$[a']ߋ4f=Q=fd=_Ex`seeA̫YoNEeI6a6֔ƂmhCbMyy9g!G̺1O qǎQ\|1vYC D = 0TpcQGL?^߆O@1봉Xk!b1ӐOqHqS&-Tc 7M'F]eseo\y '=#;'O{/<B#:Juug$w1Gp^YX;V7$~>wrwok8].3ƺ̵r=r D1emmx}$ ׃YEq<+V4=z4Se6fgƄ;;;o>0@u]w~~M1eE-$'󱥥ȡޙraɧutոToYjLQי!Gx7pzgi5e'(+IR̚ƾ[0QUY'_/b}sֆIB4R\#|db?(~0?2{bO)NB+} ܳ3giB5>'Aqۡ0(UcH׮i) + PR^0D|yeƨ'#VOZ-I6ˊL# E@ LmBW׀10mm]6N ؞ 4m.]SN`ab2iRWZe"1LQaS'qqXC]PV,@TVw` UB cՏ%Չ!]׬;~}5{y NnBWSZ-GQAd2s DklH1~WbG%G [X ѷ_曁 9'5Bo8NoWu4| myV>}piJ w]d`ܮx%ì EdBzV) (TG[$agU.f1cq2UQͯzʤ Z˺ZٱVǍWK9saaa0`<4B_.Ѧř (eݑ[FIqkcL:7IwGZkVƚ-c-א!?W_}*d=о:c=?F*Ď klob6Ym~.xnݴ0S$+./ß'>썎 g+dw 3 dcL +boSPz hp jE#ҳ' }{#IZUY qq`YzbæMbU"ٌi@*s?Rl+XeO<5Xeqn8CRs]ܖ.˭i_'G3vsUioT`\ şFaN,m+#=|O`+1LW7bA þAb5j adca`gTC׌3Ă.t 뉡OĚ0߰GQb2Ws9WW|%6}֢+׏W=p$L2;~ mS.  [Xl^V"pQOԩ-ɩ&nԸ"lNSBG`hv]xk ٸ8bڽƏ.PmwŸ~7.XnrEJϸc1(&L}AvFy\;g2pJ@)M OM5O"-:r9_ki>D}|^>)' h345bYxw@ɑxhgvw>-/bXkw\dmɂ&:scs_V`MUѲ]?Z۲m;f6S\󵿯Ǥ iٕy0$փu+༥g(~;V&f^Iuw:bȊ:V3+qOe= {=L//6i$|B&qĈWTLm4x{{_qeBnn.}]o={6[qغYT-A}^wvR9j|w^4CG;$m2ZלXV}M 8tg{rڪy[l4ԈoqZ1?t:6D o_ed=@azt~ Gxz&GcI*$e`5ܜifFƘ=b؊KAvTd{@CTzq+,|vvw)8\34va:4j@Rf PNZIt(אA y'Ti9v&̫YRA( 6;{ۇ&A']Rj-U5cDބvɥ$䝌F>my'Pw Y3xu4WۀZ%yMz+(VR$fQ#jK0נBuw2+09C}:b:XE2QW2z6C"2B~;8w!1C Wʛc,hu)oc%;6diDEW.dMm>f,ʡ߀Oi8|"BvȀhk0[}m859hw࿡o< HMWtHkO3~Gzi1E&УZ|P _0(g()Mi):6@fK@E7dHcƝ9US8CW%5t9A+ȱD>մ*ҒLc;>`yK}lSap$';^0x |0Mz˪/be;>"ąq.KJPd[퍾{d ∍9=$-8 ^ONhO2>p߽"ݻ$yTҔ,2}׷w[<3vxxOLhݚ+(uIVqTTsއ+@A1&{@{y᫯œ9spĉf@=z `8p@kܛϋa,Ȭ%ww6;ɱ2iњ8k[}q5LO?$d3C*0v5HOKqK8 FWv(&Kqaj}ڔMh5Xll,fΜ)P3fi3pfbb"UdWnAmۆKP%׬Y//j#u,WA@}T<Jk+aWh2@큖 Y-ɷiя9 $@2V@ y4~u>;&.?ܘIvqօEWhh e@lapis6mG>?E1cjVrŒ}"]ftiQ|'bikOFSkC1qhBdBL`K*A&5")e:$h齠5EQBfI6NBEzca [L2Nvh3L():aЊ7ahK?!CcՖ~Tǝs`qPzW9i1oEOʣZGw wp`N8T)1y̢k ^s%`DR}W?,2?1hXAJR$iQv1ȫk{O)̗ ʎ싹hW\Qx{W!p"-_PSQ#5-E[OkJ'.~?=MY>iMxFESwtw׳yQ]Ut'>#\=&ΡkL,~34~ WL:fքd @&K)vrΞdxOX;- Z~ cPI/^ڵkEq!oP)6\ږeF}'e7ʋΖi-ԧ^7r\cGyDčә! 5\[׀7C[WnV*RcKg]O>Q+V()͉Kx*a)]ޫd`LdV""el4yE[=:4WwIfs'PFU)!(,+S &pԑ!1 S&IRiR|{9 .9PZРF Ŵ,ĥdV#C V &Tkd,,ǐF7ֽ'7D!`U` ,hb7E|ĒZUzv'ON&1,^sY#C.yh~첲o-Vؾ}0eЪ%g,2VGppR2 ,XƐӥcq@x_ xřqƖ,+:>366n#gSjqYΌkPjbFI i[|9/^,*OI:ߙeXv2??_kL#kkhќ*c,%ޖ"LLmՊ1vc &)?cI0vdSoz_wdP'p@!<&gU5wxe aagm2JL၂yL-dzlT!85t~'NMi!&OϦ䢑&5hJvMĥb6j"6~>Â{ If<|)O9PWXU Mgg'WCƐ $C; k EՖ1H&2kB18ZND]y"1(MF0ϥ-Ve0:ufN2An!8z&]om ]SBEY UW bYF3<]}h|1]{g&6]ʶ݂f`k )cQgX3@vu.uprC} m;up z΂c04lcRM vj-h4e)oUƘr? I՜8P jZף#dX‚|n̘1`cٲedamŊ"^rdd$_4E5j8mܹ`MܿO?T4ŲL A FU}QrxX51cJuZ 1NS}|/[bϕ$3A,FyBB-HCq+ƮNr3Fql*8˴q$s=AZhS6u_ТI -==+s$;jܷK9GoEbli 3߮IRk@jnı* :JѮQtd=Zg*8ww7"DHHBpŭ8uhi^_J[S-qݓ9s&3g;|߉<72;iFz!pLCr@'#h ?Dȡmzu;6GբQZ,CYx%"wRLEfdc;< (,ov=Lc8_<""cL6=عk7X^jciz.]ɶ};;rNx [N)61aܬDRRM1ȉ&F_c͑ ÄR_ݸpmX/'KŞ~$`\$}rVS1 C>&c!T(RZf`"@/eyL( aϟ\.DO?-qy{We1ߏ ===hQǁXz@@IDAT/۝vVǵ^3}ٳf>vO̙#@aÆ ҍzZܨر6&Mֶܨv+crOH[0vK]N3$DeU@Lf 0Ӌ%A%a4F#|0sxFʪY^`N2 6Dfȋxl*|-߈ȕ1`,B!S q'NeA_S!vfx@h9aZϴN=d`ÂIv@2?0ַ鲡MLuk|Rq9@<,1klf ŦRS")FٹH(zR~DMMM9~1C_T>u?ZNC%$ R7E@d:(^je )E47$HLCt:+jhTUE5=tkN,~Rl)1Xk-$YC Fd D`\omP71i<~*<b;6]z^b1OTPuw&k$OJ tu3:[ Be⨜\$8xԴPbePwE!&u?#&9[Fח$ʐ~IXZ"=u?Ғw6bg[h;mrH\Mf{!l2&O5",].f>uURA$RhlCz .oNF[֓:#cʬupUN)On?X2l{]pX nuf'd!XY{q&Ъ ,8-H!)F'f qYvl$~h(ñy;H[5 MѸ҇R$eg={p*bИ& 54P˘>R+1ȣ?*q5jWz>5K0Ř5Ƅ])eᑑ,Yr'0S,dQp+s?]V急ۯk|IddGP1cJ2+ 9M *Xҳ!P]uJ/86 5 6 5Tc ft QRAD$\Sx7 yΦ_T6Ylr A1ځ.mҋ̘4ptˎGv0ӉЦg/?Չ-2dcĨ>W9gdW_1KK |ч{:=a`AC_0$t^Ok.!6bܓkڤg-PSɛkXO^x%>69N 3[$`7T$\KU`q kNojIuwcۮ J< yx+IEW|>)EYŘ? FMǽ\0d5z(TJ`ڵѩH',7>$cEX<cl/4ˏ7dlQ C]8|u ev;acώ:`E&՚aQ=nsL}Ĝ [ klbD'E sClڼqđy,5[FhxE6#9cCWY`Űgq9?_prѼIRepxVe_ (pSGvVׯb8E `ѲkU1~ `عX¦PJR*$iNpg*18-#O7Ι>7S./it ]`j?1?"#X{,}ҵ|~c`1G`[K#mWT:;O8Oܔ*&_qtPUAĎbMMĆHK}M#"mueC4xBi/-Y@ uDlߞ`5 FBYu קm|}*ӳdy4ԗiB.>/82@َ()Qp!e aa1(@[C]5mm (9/$0mFʴ q, p 2.,|t1LJt0gN)` ı>sN#n| 9梆e8d㋯E]|Du4I̦!`S[Bea>{ `/ uA^"1vG1( 4(6a?bM;{/%T223?ÃXcwӌ2i}&fcއ{nWn),L$Yc߄7I&Y8jB̀bD0YjԐn> 3T}]˒oOb/^q6l,oH䦪gz͹KLܑW\J7u$H2_] !cwٿsI&ČcHWsxPݘXg q4eS /-Ho֦e/q̵*9 xSܱK rI Tag[g5 aonc",W\a({ ӆbL7]g@ٹDb >?__ѣZwEN_b虙⥿W Q#cb@\zEq/] S WBKUj=X ?j6JC{bTAӶ8%Š蕶epV%iE=y5鹨zQI=?/8jLcO`ՏkCaEޅ[ +R#.>`1*p "~܉gCR,8rB sߜ&]/dL3y$x޹qGUTa0Y9=̍?ֶ6f ĉٛc-J}m-~ܶfz\TYpK"CJ/$D|jI,vkUt^4!^~@&v gQY-'ľ1IC @eK(BD$eĎRb,D`_l,2N~'PJ !%&ji"FYEYeҳ$HYs}&8{ X:TbM!̤ ]y^H㮚1Vs %هo4wr0YR؎dߴޔ.=`Ѳz6M'$+)cY  ^ᦺ:̛.@W>b8;wyV&DŽ`hTmDV=' Z,Hf;PK Ս{N0xAŲGl.$gHJʫ0I[_z$5KmK C~&.M2PUot9E bPz& f&02@VtrIu3lfh3")N$.ߟXd!cr}Ʃ{ߞ ;prYc?^~/fuE4 Y?܉kDYoMy[ډf9 Cp| ->pXzO00Mg8IR "Xwu0$H< yOy@[TnN0tb5ѩ|0#kZz$2f1XV(_smm.c06iҎcE+/?ي<ӚJ17NGb̕ NˏS@}>@&bΘ0auˀb SBH,9&L@c^) uqɊx-y„SF Ff&쐌Y֞QFgd |Jɇ {Gvo0w }Soa! I]s ʂ-c~Q-lqTڥSyU٨̾=|DsW؈вHOuZ퇈+lb37eXo##-n'^CDZ:qt DPIJv6y 0u0: 4k J%?/H7W9y?8d&Sb{x0s{c) ~)XFwX@,`u(Ƅ:n2 F)C{ʌȮG ;QiuE,+93KTrb jb` (jFXw!rjTMCuMhr1aEy[5h]GHt2 +TIYt4 )Exr̪#z6C[>/OE_CϥRLfٶ6&0ؐmoLİ{u:w~g!{~MN ?G<1CL|nBW@xw8߱5;fJ)(aISHPjkKᓲr!kjd*ե5-fSi{bS1]P뒀%H< yy@]'OW^/+Iրmǎ駟c@\Dä> cDjnX^por`mb1L'& &)u}٩c`l>8CRugĒb]:|J)=pyrI HD<9ECOO<"dT\@xJ]4S+8Q9* z࡙wʂD;["&²^GǸ 66=nfH ::Ċ2t.d iIFpI$oЀlsg$V5 SnWoo*bUz;sռOO}Q>Cq<^lFsB1ϑ @VFq28:Y3gXV'Ɖ_)T "7<d<>&)aoB:Y0ѵ? 1)6 ZDL2*Zh3|eӑFDyw珵.w{NNTKL:ffcC_*6ժk4HX: JK@]c@%ÈW5RYX!CvBzx6R2`?nC)hd"VC>/R/JUDr'F<_.jă?{qdIQn* /I.{À@=z L}y`t?Ĵ:#;-/ܶ(:"`gD!X(7 ]|"ccaN\! <}+P608~ &IXgޑQ|^ꉆMMI?O7ڒ}v8uJ6͟?u$'u+9uդ KFFFpwwȑ#pBxyyH n`/J1cPbˁ$sgШRc O`n; OtiqbvRr2cb{<am=X蠌b4>B*ju?5lQcPMKv&07%2܈gn *b di.c 1SKTaMBP& Y A(i1:zgPR#6wP!h1ئ4A#dA X/t bp$d͌ 1pv6S_d"3X7S2dlL+ٽ@ nvRTE8$OSܧ[d`,`1Igq_8)8)qk⬃Ȏ֯zXBF~ZK?.H%233wwuGoAlxrJ޽[eވTDbdzpXEEEصk-w!fof GJJ ?իW㣏>}݇> Bץ>P!) ٔN:;m4puu3CYc6m]wݥKZcc}H͑< y@@@:RZɈ/}u5^"p#_f }1Q%q/d'o$;B7*XQ4"^`_ tF<Ž~N>u 0lTc5*$ -Wр!d 5l1HMMl¸xp& Nzz ߟbԊ9&&ƭ~,wS/2[i1fL&Jlβ TJˊt4VR'& .΂Q1jUɷN@Fd|q\ !f7ߋ7ƘQc$S7~W4|)+ҚWc`:Al~Gw84 )Rw<301,VR]U?׿(kh 92ISS}@03XsS 1h.I;>?,d~K̘a8Ĭ&Kw|C,2;o!'I71lb \EU+EǪ#K\ bu5, ,mu4 eW3@@hQD*$!h sNjM"1]H >@ H U?ݟDžcX}t88աy񏏅(/MDj#'cbGıw<= CM`KIy*Z(VTCbL?qLr&IC1[so-ȬQ^NA@u2? hnj@yy:JQVB ĈKEuhvY/AUu"^Mft5!k BjjAR5U3vQ1֫Cy,,d-Yk֬C=]Nq+(0v1| ^~e1َoٻϛzr~w<#543L c[!N> OOOKfffaaa7U Z.cE(y@^@L~Z\~$G( [S\/',dUbl}0ZY.7;x6!]l-gkS$57>s3,U(iزjqrd'KDX ;wgj!PNc*4 ]SLLL}WHxQǾ2sȨ(!fei g8 N׍cgc~ˉ_MK mƹ]hFa5gd߬38c̀@ c͛sS$ɔ{b KY{Al C? 1OV\P4kcTũ3ŭ:‚LU!椫̅IӺ+ٱ"_#OiNNGtzMr̜:O0.,6a=w=UO5!$!D*b Xbֵ4-ĺ6YZniȥCt4 0B#U4NvH;!$h VPb[ǿZ%5 N1HfǨ#5i@dA Cy̿l 7P^~pqc d$v35-aI,2+ X/S"8 W)aUW'5I02qߢFuW~)^{5̝;Uaܸq`M S"ϧzv###CEiI7$H?< p+))AIi%R,\oEE( !<h,Gl54E\-,${Hl8R .E$OfS- 0QV@120RZH]2|#ɴ w{~PT] T2EYWrgNt EOjĘرYإ䀔9C(M LhdZtCiIVk2+ obbSjգKW|xPY1 &a[E^254E: T b4&X jYfmhaY>8}3=s+\&\@qF)?~8X~eYeFR|,qv~Om6#,{pvg$~^ bZ%Cok)"?[Pe\Rfrv] gaBqN!6W>%, a#Y[^&0fgL[czdhDd+gCO;q  SJb5&|eǭ"I tO]q?֮ǟGHb)$ {9 <>&v̘1#:=ui-3Ic,'7:kkWmcjEĶ#22ׯqԺ:f_q\ضm۰`+f]9cz@1b,_Ǐ }F7l )>d}0w2$, "4P 6#(yMq}|z}*`6n[2jħA܉#įX-]iV|c}]ҠV’cqcx:X޹Ml(;PG$F4lYXۈĮ h&y1ghE%@kn3 ٪J ?_ qA` X"bUTVdbz[ޢ-:(S#F(D3꾊,}`C9E+ ^T,8>>w=MVf^gqJҪHSZhWe)PSzp2bFN2 wm2oρ$}u49*i~fAt|s8u= yE@ձ-diT&S5ZpO o&b1HKϭ =^C0ٱ9p qƬal|9'4Q̕ 41h83hɱmh7nKMY R|K(@҉Tgc#V1ʓ!qѸaŒ'3غ|8EAMXZ!csޙ86hnBn0?i3SK}Og}xt8ۓ|+[V=3Je*H?`?xRj&>'$2dz  ae 3Y=}%Y q,mVlM ̘Xaˑݱj]b5SL _z@OVYW %}jY:}EhDK-*J\ /5NpL/)quKy3㐹I3tv6N466R=yL4 gWޔ뫏?X#{ꩧ 2DkX=P: z&ݫ "25@XjX:Le aI B[1n\G 1ƒelgDco)Zw_V Ĝ8 xesْ!Ռ$u`DKDdgXcjq9f6'Ec #0L=w/ϽCGQbFKrKĵU-'a2I 2Bm ZLvq}׉V*`XM9"oO|50tƂ -Õ.ux?,.l[a`6n rqAбCvV6eL Uh֫6r$p`Ǎ]ԧ{!S{:_$H<`J2J˂EJ^kS\2|dHFD.&m_Rn+< c1{!eU&bu1}#y+@Wsӱ"m == -56c}p|268ll'I'"0|'C!2J;<>{\$.Ĭ27{  bU c+((Ď]Dqc**2>.'\0 Ų2\]lQnRY=QU]%(rL8 슰Z߻wP@FP5$WJYPPTo6,X[߉ЖBu U5&ćp3+bc:Zg`Kh)+Hd.SԷ|edzY+Hv%Y G/+;mqUS;*?0F.f_}#@_cxQl9O ]1.nN,zx,Y~E{_G׫FtFtG?uFة8{zC6d=sUlN(竹B03*G86ٹϴ_:<bݿcÂg©4}H2>p vDui b%<} 41$$ȠcowZv2i=QnX0!MD6N3Ylzhq0e$b '4a+O 8vФ ;C?%DneIQn3YDy]| PGn$a0nuWc';j!9r2PWW}П؄*  ~q( ,nL*$y6Olz O>Ҟ3xߊHR<;;[0ٻwo4ǰڷo`g1Āg}/R{7C oS'O 3$۴b\X˳}Gb,dzu Ô)SD,>[HHo1`\o27'Ȭһ= v\wqR@GP!;*I cDQFt%5Z(y@[1-2/ Ftz u0'E'=7v%,- E\0ВXAwp 6=9uG(Qo7T,N!,.ByA^X0a(9rKh0d'qe&k]=e0 VmڈSCbsY}b@c0-fsL o ܙҋ<,m1 64COpPia"DkVJ)E0(ۼf,ؙ<61fY¬<$;ySOmS1 H!J 4AF_$a[Q_AMjlպ~ki zb*Say@ MmbIz=!'`3O>.@fyΖg?EQ){*(?Gbal]{LdHzQvXx"p+C&?/ᄯQKK6sGSu!f=ERUSD/,.!IC`sh/+ *%1nvG ie󁛛Z9.\.3C8QH"~i-[?Ib14"b$;1!D ZGԈ $cVK1衅.@IDAT`rVLt)(ݯ:`$ݩ)*/% gķVi3QP XPb!)aS ܬB/4*ΚU!3~!3:F!n2HKSzz _EL.׮ʾɱ8drLa[:|.@p8,*XDR҉.RNQx Γb[Bun>B<0~%YmMCfmsKl&#ߑ78^.kmb+9WqF f&hm^ﱲWcDBAnx ϨuOQdӟ N^3-Wt.cye˫75CCc~F{_#XҡGRlNCߣsH G}m%Nd%+99oRT88yRIRH(=ĊÇ DYw,Y5k(%Xx|A!]Ƞkrc5uȏ%gWLq###qF!x|]}jť~3@PHrcf͚%,Yz&oWWkL: İNLY899*Į_508udv/u2S&}Pe{N h+ǹpl6eBᚆ4 Tj\'ݑ6up羐,eVmv3ݣdD~4]?_NdFG/O̽k8f>0Ue.+X1fki^v1 vP6Ǐ?bDYv b"y8&ȅ{ f ^1BvsTS]X\*wA]ML.=;ٹsu ΕdTmIlsR{cdB@,9sј&79c,A}Wc7˒A1fDDF!(#A<84p  (\9ܜiY8ỷHJ8iw*t̂/};:D)y;#]v E 0eݔ⸺rFYy T1IcKN8!6$R4Ю8XQQQ7u:)A/ J>m۶(ʓ&MR<]&%WU[dPL{60acoWSE iD%1 Lt8Фk'zAWڇ_ 6aӘF2.I) F˔T l n46 )IQoŏ-~ʞ U~S_7*= f!򃯑wU]BZZJ#vaxmZNWPFw@ wU?_؄'Gӭh<Q#^T-{KUzM-Z0&83ڱzS] M L6drYL+VcJ~su+x׫)5bG20׿-S54/L5p=CV%:]Faܱg5翋ĸPUѐ~qׂ`o"])* )3_QZ\b)uy y@j)2)@ ڹs'F5W]z|֭[г\6QFFF".2 FєUquw`>0XJqe[WjweK;r䈈mg(ة䣫v8o/HONn=i7=lo=7j[Իc^Eck7yJ+172Փ d$H< y@+&ĠT8r|y2N$o #q 3:2ŖTfИcN#c}wGa}aO 2{Gq"Tbxw埸s56F^bm;|Fy~lNۗ`eb6pocA6ť~ YVZEe!dpA2 tuqݐ4n-렣mM+Xe9Mh6-(؆U-&!`1(&Efj?Lwl2pR4m}M~oЬW"':T#Kuae\E-0"E6M}2< O}[u,+SIuIq223e͈*[LIIe5 zA=9f hۜ"ܺMoM$+:$&&8|m@VT333Qb467 2RQ17?HŴZF-ԷAaon[siaG$0.bE[ce~X~ѵAOm^X +Aɧ'>g)#(..v0 i *3#`P.T9ouElӀ+~ezTjxGc¸1WPL[fmR>bڑ@\bwY"0d2gǧf]L/ݰ_M&p4atԂEZ@(*L8& u `e!\QJT5ʉ>La[o{uv{MDZl{,]+1BN8~erp1X 144..~uʗr?۝WL u\Xbʌt]w /W_^I^O3+ ڵkEw%f?zj`zn>GەӾmECS~$6G))|SA/)=) !=Gc xc1)ibcF}E2SÎVyr&oZ †]_TH Z% y9 @h@1ʫ+QKN 3hVCu(|Ϋ٣5ֈrbrWC+ n)~-]CáK} DSh ~ד g]V#( 4`ӏtap,W?(ntL%IbMYlnumQ":b`F,1Gі"ϱ"b#ġyotp . ݜ.+I j"u!\F,bUV j-ɖr5>?!c 8O+V7[kUMj [ZbMnc"C6xay:V4JLǖ=$f̮۰|@ ̛ ubCrL-yǎ-!!GzlrA".ϓXfR@Ckne~N2ـH\υj# 5 0Y'hf;<൸c+l~3g܉CǑWE`@;= a10#J4%! XfK2ː.yLy 4*:d]Gش\=f췚Qb+ j]:B\ IVQ W{FXτam"5l)蹑l!H4ESЁEIDbwIu۲++b~ p->@?!Y{%ml%eylj*+ @,t) %a߮/fnwAV8?=s_@2c9' QVj'Oٔ [, ((at  ;83 > ij6wwm{:A@Uw>] 1׸#_/0Uq.y@+$O~ku w}ᄏͤ{O>X3PO)=v[r%-Z)Xڑ1\kgb'| )>==1[cܮ^I=6([*J Ejvӷɻ7҆@_~EbHח_`.о}<8Kg< y@g:II wwDcbW "( H/{ !@{̈́M @0\ٙy}Lfw9W=ӄ$ZĦ9ZF؃=H t)d_Wb)K)F1$)qT7~Kj󩯉FJ~3@\w˹$x_8Mn;Z&O\#٫RLsK 1O'; Od<8zvzwÃz,WZd=7ǝ0)FTN*S_{+)Liq6|I2~N9s_da D] 1'_uzSQzPm\}?D AiA K"T z(Ҧ:!`Hpt\H'v`]\JRtdƴH> pI6]5\[x8Xf7{x/Xb8wC0T XSd pM˲H%'7&vĤ b8YQ!X2* ^Y# ) UTI,~{D1cSc\O^bXiSƱ^ǰ7 HJT:%Hc|:i7u-k8l KKp)VhiYqQ^Y2=-"/#`0K2 - yD4;_@PA0lnxWoH'WN~d20u:?txo]TrMǤjFdR]).!I)H*k*-6"MYJQJclR8>J,0BNbfΡ "¶ +_XZ3Kh{G(-`33&rѢ2bjt`Zm^"$͹GBHl)M".XKEl="HJN}^;S<W cq"O vQl8'x )X|!ބ+m\fO,CrRVHkO@Zj$֮zc&`j̄La23O(wIzj4ob]S9^9yV8ÏwڍAW+\MO7|oa_EbQspt:A!K)|~/yYYYKR+9r|rLFYlÆ `bĉÉ,]T%d~~~"ҒbN(A.sNgc$iݻՠ JJjY֏A6&vEDD3Ȕf 7溕dI1ƌ}c^fC{ٔ}+UEY/{',Y.Jq8ns^ &Ycۑշ,-xbCXI)2˲I =*~RT ciM䴻20vw'yd=pv-N#rZLfAr1=^U؜dEf笶aw?i3ܳ)̈dnF*\Xq|ݰV*J=Ic1I)[Kb)K1Ol)3E۳B6^84*FpOB'&.u`ϊ5lB4 _ՄjX穒**dDWR"607v"WFA\w¡: ]#ں{H3 M( (֗ykX @@M kL#ژy R&4+i"qOہg#6 giUE`x5j.G "dlZz5 mdj2Ȥ9ٙbאHhWKp@H706" @%3M8b o׶E'Ɲ@l(xD>(@0g~3Pq:ZT7c4Rjxk>0r*xeBA:ecKZe҄` ^}itҋdW;\ѽI1e)MH'6uB$Y1TZPJ n.%ՊeV6x|o$I?<*`i9ONLjemI1/GP[11.4CbRLbCNjBp11X NND@[&ynrR"`V2_6bƿO G9b׿騃R -WR&_8w0&XC>=p|-f+5}j6t>LLLg AIVTVW7OsO>NWЖ,Y"Q̎b̙# |} fuw}_6m/z)))5j.]$Y7nl8}e oo],1׭0b9HeI㴴4XB^~gv+**JH\2; 3ƍ3)q31O>gϞXhll;R^1ּwV1F|GM Dۼ/Ҙ~䲲d= {9V4hcw GOqLm#YQ3HLb}@k@o/~@,bP|/fcJ(q 1BT6F qZ.xwhae1pJ2Z50Go 1ǀs| 1`uG<+|8i͞!YU3e2#'[0Xn3;ľs,)cfFS=S5QSaK! 4i'ƭMWa&t*5G 19qDu= ER25JMhF{fe14`a'`Ѱ0?X&o$Hu&ΊYI zל_5B[eqM#&L R7{N!CTꜟ$ fy3w9'ʇd$NJ+ 6<kKHOLx+cLKߠXh(`9@$БYPʦMLCssO3SEd0zx0nbRɧLje㏄|{$pvmcSKJ h.(UJ4vťbДZ4fwϮ!vfX+hIRe!k3bNr+_H; 2zyT/"$6n+bgP}ج!& i'U4@,Vi?x,(VYVxZE-- 72gEODet*/Sԣ],HY >a\Ltvt}IL`d>ܹ3lLvZcE{YWK@4i~itL4Gb>s"o&6o,nݺ eƌL}TY2j |mcVSc3 V;v7ou+kpuuł oz\{LRZ5 vJue&L \^ƶSw$M 5oP ?THeMR'''Wsvԉ~dk^<.d?=Mr.E])$Pf.MJVNӱ']cR]޿7Awqm&J̈́k.jW"኿ř~~}MR%ry< vy*J`omFO7EnFY)w w'}Z4X"mGXs%]ʒusoH'd)E%3:tm۪V)>iY20ֲ<duꡨe#>1[L:@.NںfHJљAm=Ǒ!OɋQ`픕 _΅c3 O cNG-8ACXs'A1OC9$FdR߇#Ӥw` t kj`^K8g@&my JW1@*%p7A*]BbLVE!XJ`XbD!-U[30Ї3BI-@ȺMLapWcl#rM$ն.CKWǀz#PcOb,LKM(RfC|%oֲ x$O)]բRe9`"ҳ%1ʻ7mMc&^dd$hxD/>NyIvtLQVP(dOY(5 }_̨?M/!46D齿ޫ-I6,J$;c7ڜEL͝=w7.1-s/c-ȣ= {@쁦y(/NZ6wA\ YĺN(-E{N>}+3EPcR N$#lxm=s\;` $Z$ݕpeMD1`Mv)Wom(K[:^L֊V6;cgnAJ,ե ^մQU Oi҄11xN4YE`0U)i/l_Q C[^XE>=2MؚP!RVoBcp|)gH&@C41Lń30fbWW|e{b{v@f3VfR1^_vqdǧA'jkF ѠXNܡ8ə, Lq ~dPcjtt3V@Wz{R=j~>A @`TMSG.#'o4 kDZO- T EdB6萈1:A!oG`nn'QoL^҉Zo3u i XZJ9Y-]pƲ~$IJ=,u%:tB'?jP^Y%QoȋE '/nG%HC (?ֳoSG8N*K9~q{!~Q@]bgH twi%ٰ!a۫ebS)'= {6{ŋy={Ԑc_Tôr_~e8c -..~)~*Mڿ?'IIIMoL){@zVV)ĀG4WoՕ/b>k_jM*9>BXl6PRBvdl OrRC1,MGbK&@>&9M)$c`,dp~{ޔF<6%Xm׊'~ ڱW?^1N|t#]Q& M 2dnߝ6;BŠ[eeN?QF*,܌K>|=Ťc\/4~N/ ֥}DF.5}>^~HkaG2FlOqmT>/"@;;TqlGt ߻=?iҊrNrwlѧ͏u;`cf#2!+[#>5汎zSLq4d[NY {}ce`H{Nz{oMy\Ū\mO3̺LdFvmkh~678oŕ(Uf#R+^p,CA~Nhknw &$M?9zH^#F卛v GV0x4A-d/X`D1ՌIh`6LCu L `eㆸ ^ݦ?Wi;&FN_+4黦s0ua_!B!`JC sLq\ YA Jfa?(ZWG9bhӞ{ux J: rI _h`:tlkň4u>*HS=[w !O<;4P &wf+1lˊ4J7p]}f8fG~ew䕧 1"ńޫ‹\CL)6#o+Uաb7-l-(X& uQZmr &g.﩮xa+8z8M cc!AU40P+;Sn@X@iBfa@/YYbɒ3tC/@Dwgh{(/9NF@1K>qW(txi>M|\c9pG?fX/0&?d=Ќ2d;&ø^xAŚrw8ޒ%KJ$gbA>}:hEMdo`Vo3!]mC LPs&֝h.)g1J*u0')D"j <;_v뮔>DrSaZ|rR ^\@Qj3hfjۙV64$kecebK"U|M1yn8#$K )EeN.Ҙq8hbBqg7jpvHH>*mE-xe.&ƺ~Dch@nՉbLwi&hE9`m S9xGjjG`@ &}=3V4$KcrRZ~nڶxe_y:tC~~ rӉd| Q/RqgϾF9gR"yBCJN[#9SФ:^KK VV#C]0Eѿ_ڽvDNh.;1)^_{Ŷ;`XΖX" -%#dXlDo,/3g`XT{:b8Ɣ8WEd ݥ/~3Λ6o!Cgb{)X7.%IT{c>7v&K[嘭FWub׳+PQS!aEQ#34t-9M'$CfϞۗ=pWz@~T@cڕ~ v= WVtlhd= {@@=a";8tqj3[c1q^ ɿ/@STNƥagIPi b1A]*gcoAL .vݮ#!4㱩D(V#]gQn ,2cNZ߲ı7Oh@(˶%i#1*)Һ=tHX/ҸE; }VwN4j7h9#b"|v3$yêIφh ycIlKFcۆ`ډn8۰͔Rdzs#۾mXE[V~h 3Àc ݈[TQ.XfS=X1POq<=<aṣSrj?z|Md1QA>sc0^d'>05wǥˑ$i7E3ŋ: mm)[ZijH?MRLu4G^wJ7s|(m$=5eX25-M])vŒ:$v[YNخJe!3(`*;r9+Wʋß~O8O;`Z~[>YY-Z2,] PQ# CLT,6NoM }A{l6KxE xzP??)'E zw+#fCWV9n#nVR՝rcd= h9sȷu7.yN_֭[ˠ*b ݢd=b=PILrf],o13Ժ$GkT_t7 L{iIX Q,2s Vf 3}RLX/~+砧 v>2f vWSڻu@+)LŹ-#0ƸE;NcO Q{^-VL#!YmDxKBk!N1bg9.cu{yM`i'>S \W>n ~sE(и1ճJTmA/ÑDzie4p!Y fffj I|X/F /̅m <,XX jgדaUii2eO@]d`0C҄WQT3 ;PWڝ793SCpi);"czk͵F' F遲~ti"aZ ѭ=c+M2>vv{π5S_{ W@IDAT%%%<Re鉕 ?|ڔl3xRnkXt" F(LDwVZeCxT6YIB^˱v@*[a;aM#(8TM/.G羌]a?|v"TL<\a&RH )iMbxd`#g= {@@ )Rd6:^j\kҲd=2=R})gpDri?i1q\1`S܄Dd%COQYVIrfc-۲ {aga}4.tSPR^v}|otY7*z? Jpt0!ݣB IbIr<,(@V-d0@IqDڴߘ !0aQ߾p_+7vC;OgR;࿹UWI)2N_nG*ttoO{18sM[)͡P^gX6Lƛ+hoeiYrBƭٲAyF.a+PZ3׉fg}C=#5!G<rJ(bQ1?SwOs־% e9  q ;"c9K+o8ڦ=o,F`0+//OlY]S͍iok68\`h߯@E|K>۸845$Ks'?v};_t;V~P5IZN+Luee)}߱e`쎹Z{`ҥxgЛ`"OV,rOUJܭ1+d*ӡ1ܦM3?XpPl}kS15kȔJo+4TGKLLKXr%988_~9sJ9qIm󞥄yc }Ŕ)Sҏ6TT_ʓ{@Ɣ|?TJPyrRrNc< nG;\VOҢ طD@/M8&b.|3n1_.; ޔrjI&5M >.$gB$> &mYȤLȀ.9^V68n%`ZA1c,j<;[} a;7@4f9K/to[ $j@ ܹqST1ƤY.7UE,1vu;_pruc0}hXW-rH4ti҈%b=F=BI{DEEHآ ,c=UL#xTenܞCO=$@0Y!kfVN$6;'}_^}::w㽣A};Liݗ#'+>"tbb@@ӍrZD" ?4PV鄜| ders[)Owuv/_ a\lZhd-0t9@J4k .|՗^DVV>?|f}'"VOQyZA |Z{3olz'53;98'Y!Ë  |x??*ǖC'ϑ ]1Y/*ᏼ8m4t,SpNkw1uT e͚5.LNNSO=;w[nظqcu>_ɡ҆ < ^~j3^O?ᣏ>>DOwwwdK[nE{{n);߯+V[o)ދ .b@ȋ#'v"&HEŸx<&_aaaBY_~GW^yEOjOq&Im8:O>E:͛kk7駟ƦM0gL6 >>>"?44k׮1a|w$|]A ;81SNm۶"gdd$N8Ν_֨u_ܮl7 )vFe/)U/:Ƞ*b ݢd=pG+vS-1űT1BEzn=jflw7{-8~1e(,RL67 >6Q bpAovu%Oؓ,<ɓ'(_2W^s `n6&޵kG&U[*# X{mvf7l/Z  EþgΝUK<btdגs;|I1YN_c%O7r a= {@Z()H\ 2 Ya4G^T=-=n.dâRQYy^Kc,ቘ8r l뢖 bp8:mmpahh^K1U.욌bR|6tRq)<"bEw=](n f}#2sad7?'[K|v$Ѐ %Q\1Pv>, $s&rwAWbd?Ra/cw]ǨTCf֯}f\($&WtyFHظ8DDD"&"hKHH$`Nitc0&KPz HM7 s;Ȫ 溰4ҩS_9A[@2hm/ɳ ZΫ'`I+(^Cfb zh s3oaR>sMOMHS :ЧУ{CG VA R)\ , r:V$h BQTꓗ0&%=PiD*'h?]5)S1sL[ ͊&W)'ߍ $} ?q+?#ǎaĉڥ3VNA>1lzTZKzmj"ZДKxMsz\\.'9YƯK.a#o V`,Nc9/~aYGe]NcAO pWVӔ=(G dIm_mǬ969ܵk`qZ}v3f&r9uux1SHmQ|~k_1տowrmd= {@/ s046чmN3GׇDԨ t5;?on=WbкCx?c]o c>(VL4=bc[@u둴&EAu{+2J>ӄ+3X ף1ȋÒxoJJq4`MCLs KgJ1V:P&+*)7Ѻ!{@@sz@@:-<1vo;pbz0uJc4J_&֥BEe!%\U s67=*fبg jPEV.Р1ӘWUE,!Kc Wx"?8;̧"cq 6];!7*GO4p=!۹_v QH=yQ+V.Zo6iȼxA:zÔ _Q$K vɗth1O.5@D)b N{{ݷ7)⒝>sFcS~v-XQ^$~ld cX 1kI0cǎjƎ%WjH7Ǡ[cܬ{9kXhtd0JƔ rܪUczÇ:,ict+/M4Dv+g;g,jRrj\8.2dܖN Xk ։@NA>8 ?blZcCL5GN-5g|d(@~ 09cŋe )Fbs*G?_v@Ev)]Qmiyռ>n bfz=9e~ʹW pwE9Ǡǒў)'Fw^q.[#6==k*["ǗhP̹4FFrz0"ө3g)byM_G|Ï8|(+B$2 TxN, hO^#v:;;Yc^?LѺ޵kveسg|AkgϞ1zXN bqeK&2?~ebuhժ\O:nTklY>:Y[,|],.\ zUR|M|W"FS֭[Yf^x?\>,>]FJ-yd1?plr|r|,{@ڱE{UsMn_4D 3((=IX:BFaFn  `9HLִ2Xb{S/a:VKCq3c+G91kbޘֵ1 ƛ>ASqK Cw ">"``6`6mX<5a(҈mGl4(;w5R0n;zQTMQžs'{lվmX;cXch("Fϩ@)K,b x/44j8oѷhjJ2 0KMM+b"ęܫ$h}L`Je56q4)T"nCRu*Jӡf]-G8QΦ{~8gp"ydu@Le`cDm܎ϼ)Yw: >FEIQV:X f@ 8vCo4Dm3{ncB]DV@ߘ-fJw66 KlƊMT} ޔ͢ClvV̝M&PL2 ssDeJ`({ ZgŠehW"e76T$?³O?%5st"<%b%_@_O?CvvAxG.#;_cCuޝ$ioH0fƍ`)Wl'f _ZvgǽbqDRg۶m^ӷo_{5X[Ƅ~ ,X>qǥ*{$Up<1eE{Ťvs|+'x"I)U O?4>C0д|;v]f-1jEi*\C]];sPfWB״cў04vcyd G!1D3VpW0tLRƠ{\u9>`9mp`b"vZ%5iYrGQ7z6e`of ޔA5Z=:m*Wʶ݈$|Ϛfa״\,bvŕkj }bkfdNsm ?2r/6{z 4i̙'O GOA0 0`C=$/Xgz聒zB%.\ΐ̨(Ӕ>K, KqL+fL2/>v2n~@W׮]E\*߿?[-eyff{饗D|,}>nt;vۼy3^yv)M&&&|e`eGY]^fn2т n.Yjql0f{1pϥkřYYYؾ}{Vr111Ԟs5;;=f5X2Y[Wc{PKJQ!C^/v0TR[?[nvsW% {@ڀOq^01w cs_Hƀ_ k2Oǭ*Mgh5lEY!z#)lMTrv#@_afvݡoRG:keNǧѿ",=:ZdP'&a؆ ]0«Q&-I K;j5x. +نUxm fޮfvd8dal3SLHfqZ?aDRyk,RIEAw=&Mz 6͉D9}+.h!r(mQ @KP#hBAEG|/ׯ<Ӈ&ŝ5m؅4ĸH?Ӏ7]ڶ=_n͝0Q=CG{q̀@999Yyj";&L>ޘ,$AL Q5cJפ.IoRr)߬OԦT7'|R1Ϲh7?rVW.s=bUTwLRw+؝JY@9Mձty~RT kҷSw|҄rdh ֑Xf pД7g"!2X8?'Yj-/Cq~zc'\3UتFor1 a`NeSf}y|sND+ U%/;7G&#<䎚N%6'|8SLe2c Kq˺p=xPB۲7 ; {+sXb@8%> jn&vŝ[/c]8ޠ2|ݚrҩaGr98ESoX)0Vc>‚4tHJZ|acGɗi;HN$!KO%뒄91{*;FkØf2f%'3'5zޱ+ͥ;t BNxE`vj"PElx+ƃ{y-6tr,OO&:~)fh ۴L!&X,\]Ϯ"YK/3n=vE0bY02زeKX|xbQdիWA}#% 9K6&N(= yx|ĀZ I̞֘=k׮ٳbjYd4`J囲gP YR 2Sp\0|`)A&{uq266 2O[[[1\VccmV UW*va@2kLUZLK&iKjN+*Jq EE`%>)hjEC\sK$OJkD3r,ciD6]ř4e=GOLPnMLJǀeq64\lܖ"6:y{D1y=pkขbpdVs'<i5|XdSްL贛DLK)anF&:u6x\w#h@+Q /͕}%2ү!!(R.'yشtaG@c7{ɸiݽg,R(V@FfQ9(n8jpcFuSLpw;d!6 ǠY(w@h^&44[g?8{ëa >6'ϝ;$PRcYajO[˝8qBgp7Nc,ը3uR.#$E弦3h̘1Xz58^R{hc^ |r|(r-%k lIƬ+XSӧcҥom KX}!?,k.0&I ֖n鉉"IT_W}mܜh\EB vԭ:M>u }G51ro~+rf#;Lw֧o= {nŶSƥ0 2"+/* s"kJ0thQ^f(A_Be%95 r0.mCm\Z<Ʈ=(GunTuڟA1 D:b0#BV cKR_tVvc cEbxa#zWwM3Fy4Tz0֫aLȮGƌ2>sx]xib1yWO7'vaM7W}OOKH Wks?Bx†% zc )5ݮdT*|̡ d[=ŤnM<)*L'fQ$'R,#0kVIa]eFΎ"~ٙsc|m])ҸWcYoNjYXD` Nt (~۽h֮1R³[Ц K^HR]Q~]*3Sٳg}3s&1ҲFsY2ꘪHqqqyN;w0ƒ 1xc1g`?CcFm_$cHq13nŊcQȟ,y3c9͠ 0z8sݦ؁DA5W;mDB\ %RӊĐ Y /PhY5k֠[nw `hhX28iZ.}(& ?:S.ZIZ Ɋt-'TWvI hXwBcӴtsda؉7Donл'Jb,3zu~J_ -c˶8t 1Zx\ݺuXz. / !9AgǚqUho \/\ D2UogRWb ?{ UePLD؛`\bF[P;+&Jv1)]|=ݝ(\K Z(R -m)*^彺S]_ %CB &ldf\= 9sΗ?#b05(+ɘ$;~>V(XUpÀBQJĭZ "fވ5տcL̑SwAU"Hmn b຃evDjy(ug_ty JfZ#lFʌUg&BR^d;Um]G6 vm^w tLY%f*ЯJ '_>8$P /|  пȊ-ܺW}.+\Kb0AuA\j"ھ};|ML_y\_TS{ڇ2LF]ee%yTd$(W#I'il #/觾eiLj3T։Nci㎑svDFrVh멃&C?zb|ns%f`ke m&(.f#>G3l-7rGUd.\c*( iY|dl]aN;f]|b(|dl[jfv=#6^9.#+Ò,6k'cm!ytclG @mdf 紗 3*%zP`c>$}5:)aQV2.sd7 _a^!a#E ^(3K/$Tioock-g8sY)/[x0 (Uc2Vq/RRԱ+8]>}d7&sZɍ *lDT4 A5GYZa9=c5\ }ȿ uN {7}S@cqU  LBZyi0˲רx$R9&M1E" 2:2s.MӘ>$O, 4jƜ K݀嚃ߝQٲebK_ʄ܆ن^Izg9sLyk|V[N%t7e>L,>|XL&wћ;-2N:UVuY]4fAɶ9#LbQFh6ydA0|\Vz*O> ,#2Yy)Bc 6~ro~ Uo^L.]u&8 V+@9c???mG}Tş%IE{gK[zjA03wqnFYFgΜO?$c"ՙZ3jE.\ hL`g5^!)fGS]0u"oe~͎0ݱnD枋ܪ cƎڛ@cXTFP DeoFU5 )wX8\Bac',Mt[8yDpO/:=wÂH=1l%֣Sb]Tދj2 g3Fݮxn|~ RbLAOK+j>K"yڞ#rOY)_?cHY,O.~؈XHŅ4A8$\' HI$Yndoc?ǣbџt $VE@*ڶ: `d38uoR]#Ri8M] A=|,>[ع enqc/X$[ųВXCb1Z 5~KGyHJ,)c2i>;4W^[5i^E99fm^}oSPO#tŘ"h1B}!pxl3#xo_ЛA{y.˂GwYIK@ ,Fz:A"}Rmۉ_%vW׌U=5o6];I׳`nUmE7hX:킚t&G cS!l1J \-ݒ_nzPO$Rp*:^ԓVנ\ mc +}d)U+b9`$>08EH/(Bj^1r z9J+Dy(?9f!5$c~hoQRdGpp~x~ (M1jъlo ETmdɐ썑NK|зo_$$$$j,@G^< zqʝ*@IDATzыHU'; 1V5(Z$+lcQMG!P(Z2zxGCr0\|w8X@D>1 1#߉c8qI'$ /VѕWI="H3k{0 ډ5L  kOʳJp:-44Eم,-7EYX%c陰$X*v?'6'{[|=:z 6?Yv6P\R8)Pɞ1qi:N+ٷ։V-&{)^ _`~0.+'cFg L6^f;McR+9QHqcYD-EROPN"p0'u ZXьHxzVCBim$aBJKr: +&hꬖ&_&AOr/GD$+݈hr8(T'òfƦ[TI~i.sd%)+ "8t,MIJDV~.qi}~gqz%a3{G-NezJK6i8c }{(X*ԚqjMu{ꩧFWVZZ ELi_SN5DK5n;ъRk(B2Y m3Tq*m?~{$MiKzVlTc_!#f@1W) j g5{N dUU^Sc1׭YcƏMyݷty7!4+ն"PH& fN֊}ngo`kF';[A9^g0Ng꺦kt^CYNvڊbTQ=L;<+p(/ܴUկD{ 5= ə#>Hs 6$p,m`; }\OȒ$^(j%j ̓ȽJRp568bˆ#>fBIKD$0Qe!(KIb  _pRQ 5VF+S$ekH-c(ӐYrȮ&!,rKo<9.53LjztT5g=Gj7գ_ ~M6ok2(#;yVq9<z}*d=>k;oMͧ!y\Q(V1+89Mq}W BU8̄mBV#%n-[e^ePV* T}8x`T(&`;pdb-N-\HX ]=6/'!Uoߘ`lA2<7fnm#`km{MΆ-8;9QPDE,VVHDox:!-+dZJDgS"ړE'xl{cfO=mmt(u9i'FMddQAhUX)ɇ1r쓐V 'H1 dBq/#) % z_ ?yDa4k†, }+MD=MWEIJ9)$9I+QP\DDe)-VCgKDa !2Rv%uQĘ5}aE%vҨ˙Y^e47*T?A7?z__ۯnД5vȒ RM&IvK7fnn$ϵkgM֭1f(\T66 SO7tT BVj("""0a„Z kO^!V+'7M6)]n}Pmej 6@m8HA+'xYcCpkVAims$(XB jahjI "«.õ#ꭐeCu;ѽ7c4Y;r8 -3r3AEOQDO A]N%f t}b"&QF!,CD4>?K\jly6&zw9ܜIgȸd|.swvkE`ޔ1b :u| ˒C(+'"h0RN3DO#2ll̡AXyȊZ!u 5 1ޡȥY -jeTpp09S{5nL,KoL_mBLG%h_W} .V)S@ v'©PyܨmwRq̛@o7k"a{jUcXu?WLZuXW\;O3OFF&Kb62NZ[MbHJeh^9C9||1AB{jGU{Gvn1p16/FΕ{~xiRӽh/{9%.L">ɔC11cZgghsftgweIV\ވhU{c"=\0R f8Yp^b"Kij+='}2>63WEĮ h_jNu=oq᫕j-v۞FuJ aQ2 wrb} ƏWOig‡ UX!T!tm[ ;bR1iGVOkz` 0?w DiXHwc"[,P駣e70V{3$C(X7*GS֕GJ_-ߌϛDa[J&JƜ IFVq!sF)Hڦ[$kЍ4M7XiǛnD}%o$Y}T{PcuZ _R1UL鳔H=тlH)X:S.Vِ+0v2LW^DtU_\NJ]$-[;wŹ̘DN;ic&Bv_h-ɵ^D36,a|~75ѦNEei)xRF] ns:n'>=XkKUSS|g"%Ͼ}pϵSO=K]~~>^09ֻwoQԩS駟0yd\wuaGd/ϊ={o߾>k.xױ`zp_}xn/2nVq?"∉8Lq'xx<֯_/K/Dؐr;==O?4>xx;s_ƚ#<+V]S' K!cB]WvCrM@N!8aMAayLF)o&Yu0DR$|5;w¬4g8YCcIQmHԝ (I "&wV0˷'[3)n4EnƎH%VDj1`L* izAq1B?&%=`< 3$esqwpqT%km@SbҰ~o4=KE]F9#(aLiH/&rڋ"XǦR^ /V|9j/ڳ bSGYI}.VdZlk?OW?ls63v߲v#;il*"z1g5gp1(ӫOʉ|>W.80qY&kXcrLB#!k{ 3g/R&N(Ȩ3fz6L]3%NI4&mb q?0.\0JG]״08`,Yu\s6mA˺O;=utbjP(͎K<#N| "†]>=§0hɨ 0#qe_ܹb6ODW#p`m}[Rd!*n~ժ meuhX!tk))cY o[LWC1$K`2LbơLߦ/KE&ŔHH̀y*N#5vHŪј+Cۄs~ɼ_ƚl93և66nBEPbXĤ&!O&CW=&^!@4$nM,N1v"Hdc\uvm5y@GC`v@ mwaxvLGW SebLƸamSֿ.LhlA»T]u]!"Fw U@9iW5-tl& Ʃ)UzxuA/oMkJr@B m0I#F ؿͭ36]טE`yvLRJFgdkDe(? jX:w->B+\ljh.9^bW_}6mBvv6z7|saتgvLSCll,&O/B/lW=ߺ{/7_~iO>DXDDDbVCUe[Szp۶mQ89UsGUs>(NJVn"7sZ}gu]oUNYZZB@!dg`ɵ-} -fX'D-W!n`kō9֋)58XbۭWbFvM8ProBNYzq}Es>17I¹v7|u#>_ WEi5?4򽝋GSqUY%2J-EE6tw_X|c<_pC|VKC}eq {y^-&5Y, slU+Z&zz{'&UT-Dw(]b_ ;1:aLjc݈nvA讒s3=?Ο?&֭['=Y2j(8wP 1YuAF^dŋزe ͛';2{>z駅 :0a8~?0YuVA,Ħ ǘfeeaժU?~k@Vk54} ,))! 2TdÄmzz:qq-YlP~wT;]*):ӂ;ZU PT3 i$Z dg@R!8E܁C07낇 \SAiÂPnD]*TK!d+]J U;f2'VĤΈ]iIbbؖ֍]uI#vL4؇`naaokc08;m4Q-4s(;>.98<^ڙwfKš6k&g4\|FNW9TV 8RڠHcy5>>^8LR}L\B唜y1/%aLL~Kbe &hd8::KtRz׵9`@LH=ڦxcϛAh|X5n8z}p?'sl9 8d]hh(v*H3Q?8TG=BqwwnL=]|/?7p8ekϫJ^"L>xfhPV_FP2k34]vb`ipS( @ #PYYN_:Q+E|8۰ZxFj8B9V䍅t l!d(f`Xz8 9sIb9yX qM&&~T:}$U.6}<;Kr~^܂id8ykAS;_>^Xm?r '^\6d`cei#U.`!M*pgU0sK:wCV,ہ ᷘLi k֬-d &0 Lt]\|d 35XEaHڞIØ5k gx蹱" $Im\G!bL5e0A`|xbg[KXmc!m M%Ƥ" DLZ*6نkK̙3UCi;:L>xLXD3(̉DhװvkitP9tP B=!P\胯aouz}#fo'j.5WBn&xWc1[(f4ޛ6 #::Yk2gZQ]PU'&4Ud6 e!,x'}'H1 K[uQ㟆o\ "Rx;'Wb+37KWE֗>GGLRGo[5"t7I^\({g֜BIw8{;EobƇE.g{G@*L.OmLѣM'َ!).H ɸ8Sh:7&Xg KMm 9XgjHT5yfqxˢFٺRQ#w{ԭ%ŸnAiAqC@cY!P4 3c:,1D_=G\cѨTcB"lcfůs "0UX~&N(XAfkim(XHCQe ;+L# 7^KJwdD2/ksx~Js`~7"lC ;{o$nG~n,O.fd8Qp^k{%zG JaQRzA_ѨTcB .yWl8]lyE>t u$Zv%lq~7|+"UԐ!cj/SpqqU9aXXh̻ŠusT:oRۦk׮-j`̝;WX[~"؉'0cƌKe…dl&,/Y.o&zl?Ӗu.}sR"bc(=:!bb؉׃ɱpmcc JQ} @;A ;9==N5'!dj @S"0_F{`_;B2) ꆏ_?*Ź! j$^:HGew.*K@͉B]DǙ twDx1iFVq/Яb^MSO026 O}3K\"0n@o\3a8<\;MTU(еqġճЅae$D > ɢSc9%2wƻヒSu~zXt-7n(4tM(..6mڄAi]ȑ#ʸq.Uaaa:FG/^R? Ö˙tb2H"r_/2Ν;WK76/Kxvm`]cqn7֭JرCwO>U9ݢE m+kF/{P}c>^R(7eOh,/k,̗5*)΋Ņ/֩{ϥIt 7_-]!h?dGƅb n~VfP4ؼp ;G7wGc{L v,6[*ۿT@@r`Q4Vv\lEDmCB.hYZ6ރdNAHN܏ԓ 嚇in|.\,<4^g[V}ܽذ6$_IӍ4,_\Cˊ[[V&i8ַ~+VG~у>h[S[nCꫯ^X~G37CudnݺiG\bӧOʕ+7 22R{ݤ<ֽgN c0|,[ C$([eRP7X^g[o{#FǺXV 22X'98h&d){>z:=LD3Akj8zb|,M][V 8]!aϢ ;;: POG!P(ZJc+w8f=4*88Xk行ykNOP1XP_|z":3Kn)''Q^_ichӑġܷىĤդܷtRy(mv&MlxZD&[0b(.=o KEV1I#t6Ƅn3VvHH7kVRLomio-¿f -U%_{ ?ێBȾ^!hH3 *ʋlcrQY)JTgbk|tՂ 0{lX)2p@2SNĈ\XLq~^*3qfΜ;kY 6&>߿a3qn|̙zHg=z>,$UȱSNCVXkv9^xqj zU}QqxzV o|{gT V^I&1yĘ⍏pŊ֛ ÇEr X 2&]uȟ;/Mi$u}s1q*CM>u(JL n۶ =5j):>1Gs ~Ko1& kfpmr\F }ԓj<:K-Y- ppt+ RKP(Zr<> cEVP^/Cnq)? ؞myWGm|pHIIZð(M%K[KYf\w^ABn5&rј3???%vV̱ .2o>_cΣcx2V-;Hs Ehׂkseh סpp44TW  ;G#JVR;2C) R EDBn!-CrƤo6b:waO1Dc'2jKNaڞV&b.`Wqv݈HDX 0ރ~6n2X$ҤY׿[ : W dYfn:,3+Gdub+Md &ņ^v=dQ{E M/o-B4a:˓1fp1P0$޷dee `-O!`r4,&wns`Y1c9>=OB@!Pt|B[9v7K8Az 9)1h}UP(LA`Jw_k:XN{0O |lS R<^++PÃ8Biy'WՙD@ZMʽ,W@%R#b23j'{|`ff氲r ˘sv X{p& qYCuD,䓋%X~g7Z'O܀/opmpxhM4F!Тl9]}fcu% nѡ`L~1 0G)aa&bbt.\SO=V8q!ITaׯV S`2(bV+ iqĹO uzp̄m!C10Wk[`*Xܨ* L{^8=rڋ?Oh-QJJio@˲ξ/ ΎZdfCm1"l<0!+mm!ʈ!, 4y?-K] PX7><^O>ma 2wguduG` >-%dz!uAdxc1,;miLY=&-}Ծ#p,]aC{`rlC=k5ߊ&(ŌJ 뮻zyocLjxRej۶@3ux7]Re B s+B Lsbfʊ21-VşV8ehzM@~/5oVu9( a|nkvhp2?tdYguɲ@V#Pr߸:n`lA2xB!Q 8#54gZK@EdX^eV(Wrs,f nb B9F걦XKy8GnErF6dl=rRGqSb3%eҌ7o?Or.j68cw @(,5 \&:ms57+~AbPX.©7g;;;QƹI雔V?kKF=hlU @A@cm^(gJI~%t+.CiqP:ˊEI+́@"]Ee E%WWlNF6bQY9l,̛cTƊ&'tçU.V?XC(\5GیUSBWoս~yt (w'y ]eʡΕ>-3LJ.G/W[G}>SLPS.7wM>Or|o0)b^9ruBRfyxvy3}#cΊLTYN~!6;&u]ʼnlo$"9RhokvV8x&~+W36ydex`` Ǝn /֛GXw6-A~MभGb7H*Eu۪P.>pf; %ӝKey rӏcuIQf{I+ fG¬ IVmcRc#b%+f?X}U@(ҟi5)nkZPs`k21 Z|$$77aS#[Dss "QRG6cE\}: "2^y3ƨ=[T\2.&a8z"N_\;a‡e7j娮;d+=TwrA0ɣyZ;%3 X/}<1eYpy\eS@M ޺*1{ ^uq"gyFlD|  @GD;" jM BH^ k['SJ=.VxB@!zwbUTd|jFY 2O)2#û˪r/Pr)A0ajRMhބ}`A&9ۮ3 K2j3fD `j԰ۤ=X 2򑘖%ȄVlX8}\5j`***QTR ;RcݞHN\wg7`YI$Y*o;tT]Yw-bL"yӉ6Ęe1_8FSS'7'[T&B|=׌m @cprr$q1,ZQQQp&rPcW7f]ck Bo Y1+ `U,q{IO 3q< f^/Cq|B[9v׻N @k 0+$V'|z:co|$d`$ҵ~nѫ+ acqXOfJ͎)&N'R3ϓ:l3< ҋ9/#k5zNHfIüagA…R&)4cTq='v lޣg1 WC(uTt<>9#O`ia;_\[B^&UYquABʯbw;;ƪ:MW^Pd%zH)CQ'ba5+'>>pU( gweUC)7acaņ[<22&٘m٢Q+<hE1֊ૡ @zzimS}@ApxuͺbsvcB@!Ъ<8*q,8ikXO, ~?yl>3D:W OL]+ӱX3RWJ(ӐVroZW9sgU")a/cw.\X")v<: #>Nix+Ff9d&#.+YᒉղX]z•nAWOW/i>jEdB8vn6v0fOAeޣwK̿)H^_,S›W'{|f)M3DX29 T["8#x9bL_%.E%Rk\c;ACɃuή =hB!\Ԙ3aHHx%K )fa刊2[Al-"E:B N$0^.⏓1xbaaVv(.ܾAT84!PrQuIIole">f+v$W4r@׀qvDj"17 OAnkb< &t H"žsݐWub">̿ZX䱊l{>dᇵ?{0yL3d.]cѱ]{I ۮl\Ll<jorA¨ 2$:]`,xiH6"H-'?w\~>L"8pͭm`N|q'CCpYX8c!\K@vh*g}c3AiY) *|\cGcP\8o c,t!T"zB9|HXтRLLQIc,^ocs- h4vKrҏ يM3IϕC)Jpt4@n{U !  `QC@*gB6 o J0EtUD:JF1jJ*8>ډ:1q]Ubk_ 6(@]C c\vx#h¡Vy <$d߈k,mC-PQظb凐sDNEL Z1.<ڞ޷S/1p?aH3L&EGo]bʿ?ۀ$ΰh[+Q1JHN,<' Vxr>(YfGC/vǔdߝ}G놋 +9ϼ9\jB JQj>Say{w6&<_xOѕnYP8땻,\ SQkuہH}||mי6uO f!aPN8kN`ALDSgNNxno&v蘝~PXXy k2+ ""qm>Ps߳g._ &_I-D@3B@H6zEaJîX͓űи 0uǔ7,~D]&%W0CQ~oNMß(I.d G{K67M6㇈R<jR=ce kڿ8*qa%[`El\'ͥnzl\X8hj,G!gAH]`H:Ԅhk߼z5V͵͆5;;!&W-,E1h}VmVDh$DbU'ƜU/#)I18tħ u,rcxQͿ]Yaxh;vyݔ\S0(/UU lS;e2=a/>jCmCi?sC, T|a]s-߽ Vb(B!"tO`R"Y|U ׿s=K7x#~<裎?StĴ^{-V^9s怅~?<_R:dŋQ\l|ѹs碱~p7;T]|9)!}B$O":_HON*nJ{-P@RA9J ߒ&uI 77S=p2~6|Or؄P(;(\+=ӹҗ"B W2_I63Ԏ([{!,<QQ_W2IƱSg=)Eu"~2+W=u f(&P X,tu\,xم.bZc%?8>I!'yBa5y""Г#GY9{~~~xg#EWnr%! @4j1$'>BIڲmJKP'#3K;x '7K;r(.1#kZ7pv$${ 9V%傃BMj mdikB (.ް-WELlM)$C9ľ}^$QXJ}L=eeMƖG_RrP(_Ncgos3F!9>Jj բ gզ|A|sq.-.fbqmz "9Z(TŪg6T~P>s"gy1-+'d3TAGT<DŽ "PdLY!0x8|"!M&tƸ??Z6lе ŧ(x!!!&MSQ4QY! V+Jf֭[뮴Ra}xj>I%m^x$[?Jccala`5ql*\عpkNЫG옛(Xӑ ! B2s}̂s9x|AWҴ8S?߭0>F!nҷCڥ+siK#``=,Kp2 rz܌1z F%% 8KO^7 ̟^- g _cFRa_<?X|Vzxf`[WxM]*%Ϙ|+M6΂v,=,m۶Mkr cŽ3pXEw(éǫJ! ;TUU9BL:wUרçYJcQ҃ivHWe#WHc#ʼ)لmHCx*QLo@4IjE@p2f>tdB@%9^Z2K `byxD1=9)ˑ:%յ!q;M8jwp9cy‚8|M b/~1bUi9t,%Q!}:s` Øy׈jO;ru2'Jx|bVGHAY7T|׳"dgM+Wf&^*E!uȥrP뗜V&Gݓ0V^^'xoQ/nKaw RPP1ca496İim>j;#_alxU`6x2KC E&/Q"Xօ/=>~|E9B փH޼n>G ώZX.Sݟ@ 5BjPV)9VZu!ʯ9^')^|| MK!QVKpİLF:^>GZ=گu'TP>9NJ'OMÛ'2 ^::7 ˫/2|6<`}"b뜄a;*&8vi˜撊: VwXvv6/^P_v#C&…w]F|*[_ep9?ئj,ԊV?EGڔl<75QщcpȆBji@Eާ(=RaFQH"3RTn1KDҩ27B`hz;3>߼ջe^zߛBR̈K^]߹ Iuj|r-ԤVʸsU*GbGZ̓׻|Y8[XkW<ϝ9te8(wV}΋"Nzׁ]mO]cD*rhɫ(܊Z! z#0m4|xw0}N]^ة7~ވ4&L={/[nc=~ ctH#1ZG[qeNqOKB蘛80@!+B@>v(߆NMՐN > _?;[F(gs"_NJUJ]ǎJzdd, 0pg}~jRGt4=Ŏ }H\}b>JKuجmKǺG3L߻ϑV#vK7<ވ䄺ү̝=޻ 6[ (6kc|&ń*qu.grusiB``V`4Nwީ1tr[`ؽ阈TVVb;vD MMM\=>]qma׮]Xl #ɬOd}=/ a,qQZ=mf+f|OVLp(EẎsȏDJDp9( a+PN- 9lKt;'B hza'oZ|-PԊvK[S{(:&juKNaFIm6 M}O.4q-Xw Sb8FuԖmCHkS#hű}nìk7iM_W, * &(9ϘBpް_1kiرrW.^z%\uUx2^'1~N}?1gWOlƨߟc{;Pژn&. ЧF[(icd{8GwHc#n\h:+HzJ.h>vE bLDԟdB@% Z=#; zt[ +P*ʱu( 8\s>j&l>ǴrmEy.r{-Ld^Y֦z(M ʍ9Sh.cK+ڹu2Lq_O-i* ;|m_=T5[[1~qw>]0NE_b!,$ܖBXPr÷jX{y^/.7WnRQȗùskB@! =|b],qXE)G@c/WBd![XFlMȜ4| FB@!04CRg*$W ^B@!z= BMجͨ<q!8rJ֧ۋRB` hV|X 4 6@&Ed㓧m3â #5r61ipI]DQRd\!"K޷TKc X[ a>qc =W!qK r0Ul)aGQ%vu9&ń[`nb|)3VZ?w6! O@2!0 5W?p|[ʕ03Ff|ƷG<$B@t"aO32/坹ҋڕ-#H2gnyCL@eA`$PH\kӼX_ʊNM!g`Dd+ π1;Q:tUCk$K Y"A-1ɽ]L`9뮺g5{oGzɮeX 7(@0vqJlCԶbbF! nC@1U2P!ZGUN_`4;*+ bbQ)W#2jB7]kv2! gp!#dKKf$GcPH#~0g"+7ͅgjch 9Ed(:ѱWS#'"1iw#셵 ,Rz$"b+V=ϵ#qN\3\_H4֑ fru ȹf#L=EheACxx^\@KՅqIj,?z+덎B@!Ds{$#.GE_;W^FI?Tm^sD셓 k[ơ? | H!4C]x,pV0GoSSk!u=wzgs>-ԤV9͊ !ai(-މ{^Q 0fCssc8%)$ caeAlk<͵r:3؞j/ !^`'1l: A9²Ś%6϶> ׾dfa|TZ2s@b#E! p/" a!PSf ?0 Tosް/Flu(=VK=Z"aܷrE1e0 Z]۞GC}1||1ߪ`6xn;||AbBRX60p{BbL" &gO:9<}osP$( 4v.Bb#l:L.2HZ|}->8\n), 6zno}%&n^N! L@1W;26!"t>A ƚðںe)(l<miB@!0%E)cې[YfLtOƬs Z=sp(U cB0&Ҿݝv٠c,n*j V>_#ZZj:"QRUMyM[~ч0vqn1GŏLS; [| u3ߕ87 a]HZm>!INǍu,7$hy(8.ɮ; aZ1밲 KuP5WHq vB jG}~¶\aҭEBq9J AIλe} Ym*T"`ɡjjAfD0w8{[ocQ쑵{ _t_! Ka%n B =+K4LR ! \3K]~}M}R n$xt>7'H$C ^?rsBv n8 8Xܠ9؊ɭ3֧45U:`ސER C<,%&_Y O VK3P\5)oXC"YttϤtO]}$V:jC:=ީWŻ a[K$vG͠\a#GsGuz!7z~ ClݲaLxP/8OYB@! <cueL%5?7 HkkTT)s /|ƐLNpŸ3 `ۿ_* ALV.p_Z,vߙt?r+,|F:5އ6 A(>e!uvu"8Rӊ_:9Ÿ'gx ,@\=bqK, lV%bQx2Qtr#}PձQ1BalGdeCermEE~zQbѓUİ75dl=1OȜ9a@.xF%"jV c a uߓ.f_iB6?vbkGec Jb3Ϡ,*Yz=x"B@ /m(4_?Œp X]_VP; }8,W?8??rN]D"J"W=7C ca*!A,$q Rڠ5GQVK--f/:>2Hy.[gڱX<\v80wt .qNE0v1?mΜ,<^JՅV ʮ#xCH'GG\%N uY!Hn,B@!0xD"&}7 RB@!0vcY_q|¶xnS6V"54oѾ)`Mʙ hbsc56rq9n%'*?JᗍF0.J}] X,pe%;; cg#:n38W6{amub̢k9Ⱦ'D(GEUNYfPtx† VrWӀ{>_j[aSᓇp1^D Jr-! G@c)gCGaVkC4+,,fLc,4n>ոw7t+ ! +B9Ssgś*Sq[p܌UuOIxp8)l{pk-G5._^{gwvZ]򃧉b9aqfi SBo'`_hN-7xiy|0[ÌviACYG@t]ݵ2l`뺁ѴoխJ՜c,q|~0cHG a `Gm %P\=6 ^b E8E-CB@!1D[- jv('lr%}(1tj? S9! p}sgeEKqnےUGםh {q @%-~(m)Um#P_"PQ vy.L_||VUz9oXL,%yy{Gh#|V\N+6k+Oo_3P:("B9t~7.N?͕^|1vd<W! 8" K9Pm-UE`VK=ʎTi9HZL>?mB@!`'s!4/jp?נ!qR%9CEcK푳ѮrxP_qm$U,z!!q"Q JJ9XbaNyÎhQua+"rW |V.D-$v|C_C4#f}1H! @W\J@_5"V?/+:<^)v45V$fthk*<ڂ3AXx& b +zQ %q0 jd;etݛ2 9ܮ#N6B/nQ㨪zчzNSb)$ý֯KMƛc^Hy`m "a zCNΊԀ:L2+alԎgxLtb.S}]>FSC ; ֩9Ӌ11 ~JS0.c.GZUSd}) Z֨5 f6VS)Yщ);lwq83c/iLie4}b!|_}!M/6\"z5K%/.% Wǭ9SC(‰*n! B 07E4GUR{ ;SKXQx#ʎTǘK)a,i bZkR ! .D쮵JMXD$q)Š/yx@f'D#..Pij6y(vP+qԅ(߇cW` c$Vxe!Td!\LgE-n6[&/-G~6kۙX]@IDAT9T#ДfnJ'^K/q}I7}~`VN]Fl%v73SZh|쪶-٨jjEFxr(ƴ$ةό ! pG"]1v=jΕa[KIZON//AqloX)' cQW h c]smrb! gA dwE1=J" *R`?"z[q9 Vo1'6&í3q+5-l-mt/[&S0=V[CQ]yǏ~DFODJRk0K5/K/ښa ILjֶdS]m arw da癞f[G466sғHŹ"7e C u\+#ȘWPN³(}JJheA_2yzAYH4q ƅ{q1^D s$CB@! z#F>yh.٤&*Ql.Uyʎ=Ϩ~0w>J7S9_EL/RB@LS; p@R:kb4&)L` 0-kLlHǻ٥.9 bcܘPe ynoSbL{/XxrZ/1^SQW$jy|ȉyۇ^>z{Տ~>zӑ{׎M~8qIvԱcL d'9mq_O1H&bﰻ;z ~ F/=3 A}$Rg^uX cLL+ )Y{d^ 8.k)H;reЂ*=`uE/(y< M:؛ZXl4Є p^^}^HxJBբ˴~ܧknᘬڪac5:bi98GbŹSh M#s+58+/ ³Q539cKb@eX0QS?_Qo SžYAE0Y. sĘ^o#p6B+bϯ ://lx[. 9".( s ! ,`2v67 BXPthZK௰[EazZć?(w ^7b'}%-YOk aRB@#vŅE$.%wNd܏mY۔Heab)ъŪ6=͂CRh[է~7a9Wr\h9Xң\\Fc4:p6vjxM/xvr3~jj Plů<}mx%{sq֠5`TH no/@LHbyF.~k 5T{&WanwA [6 m,"F ! H' Hn>ڲ$x)*i聓7vMc$lb-C'v=MlZ ?C 3 (o7?KbZ$8`3٨k4QaY0 bS|)MkZ! [`/͍شޞ*sl*iAhxr]nQ" ]6 /j޶mm }_@7KG/r-1HwXY:ع9Tn-ͪ(ۇJbPkhIkUKAq~ĦIF!$4.H޻B]n%x`ޡ[u%S+Y彮s' Ⱥ=`#wC.7"JFԾ/m}nGSͭ3k_}D#|s"2=! Dֵ'ƢIP!s違/lU+>&q+ ~W9x61cn_$r%"awUB{QU9ڞSc_,qN1>(Cź%mB@! ד ˞S32Vs/yxyؙG."E6VmRh[Mu/f %6%irNh"l漇PvhZNP &QrѪ Ki#J,BY75rpkg/F^MtږC=vU"Cӷ9P6{amubBOw 8\Z}ys keﳦܜޖzzN%GMG;)\(b;eE3tRաͤ5&)E$Q'̢#kJ8EuB@# ˜3q[s%9L*>|wPuM0m֯kK vBeaxq?.J _`bOj7X&ȱ~.+8URtrB@#P_WӞ`e2rA]Ua$Px W\K [Ii4BRWƆ2%x'ͧ}SɣcּCίcXrxENWNrjΚQ 3s\2ߨ\tmbKw}E1>V+Bxnt X|c+k1SXE_T^0 iEcaeA«[ Zr(ayEXF&QzU>\SA, $`=CfQL/{TjT \>-B+M/*\w/XrDKB@! ;aYdri;: O]n+*jbq`ͷQSQ\ASP|_\ AqhP)̡+m#*<"UOG@h_gql~r9B@a$R%mŔ[=\Ohoֺ i47UQD q?cYnSrI" 5.22cqδTPUcUD؄|4mfXt!Xv}Jt>ٮsN\;5LW7ۋ*7k(de; y:[ήv{\ޣ Syt́:8n'Tkc)rI ~A/cnD\*G#VW#2}j]RkJڂU6 v\V |=^|jv)B@! H@3"7/y6;WʞCr6ʿ/cH&@QSY9̘LѳU^u 14S c4:bV2n;(̡a\-g9oʺB@!0@|5N؞Oc)⥑`*^:$-Oy9Da p`rTa'M QS ƥT caca4@ ^!jĩwW$aeKl9DSp ˴szyݛ_bnRrM4|\ '!3ЈF\jPmkciڪ8cx1òb Ga/Թ|r< "#JSi 2K*~(9Z"J烥1f.EY[fQ{q Ņ$Cryȍi ! %߬G,򡟘&I.6k3z"|HNL?|7L3~=D&_AajF,',R ȹ9w<%WmێYB@! @9uꚑѓ:GrCQ$D6)/FUE6ː8j"& ا()ڦ*aC3Gn1MKH:Q1SI-eeuo/G'7XI4sKⅭ9xns66䗩v|p(GLS; H`==lv4CU*-*z6˩"MT ^!D2c`fI䫮h k]~}ZJʯDCF$-Bo $f@^n@%q6[XYVfm"u9x3B@!0X@04]\=#kO$cP_|$xͤT^ޔKBw(.-JLhC9ɺB@!0B0KD0UX/xx_om掠j"y`P<ɑ)N}z .@ B,7r]lESĝV )-$עaZMBFҕb%qX)vE#B@! @{ ;'?L1g#p}ߪ[HNd 59)b pDu! B`pTUB΁וh(&E~3ǃf 3Z_'Y6vkB qaR8%BcP! Xv%AA:>QN]1b:K;8Phfc=^<9xq.>tW-x*~qDp@qziG.u&DƋI9fV$`Φ Qj!z7+ߥ\_Vв!Q8vѩcy owahS8EPXKi} \O"j+7Q=]2y);sB}[MCuWvp4Mr}M ΓEa }~rfj"k$b(zj-vM! L@1w{}K^nX:JT-Ql0 }ԇ3J! BU (s յK q7߮؄>o%cfLl()Ͱn 1\\J~~JcXiT+^(.!*"7r^ܹ *Wķ$v>5ЎوMONc431>7*\K \_17^[HUc Uuv!jMs}`h]qFv0uCA6:xbcAw%|o%(#ϟ]Tʕ$ݩxD=~-x}jjW΋^]fc?CO/t~Oj;.sB@F@vĠDN#|2Z͢%%S+B@!Qt+9FJNI/<'xf6:$!QhAB@! \@cC)U<^I:1?o/dJ„)hHg*! 1v10 ƞP?Dδ1X69?rTP6g#G&rA$d2\!'bnyv z.#Wj&C: % a$(ű+! *K(F:riFQayrQz]ǐ9kQ7z9UEqp`|K5Yq?^GAm;OߗFZ=Oo1^|+JpeL{wҙE\dK! a]9Sǀ1bAxF9\! jVj9Aե[[jqgŢ HLqj Q]i#ꭷ"Rgx{i_.&<=7r4֗ \bR\ Rpє#~Cܪ:vu:Xl6<~?>m!5*Ws>iAM5$ -Ǐ|K}y((wPli(BE'SuqDv 0sYv*2^X >!v8#,s[ V4ŨfT[W;`gpC{s[),vGb grF };cQ쑵{%;<B@" ˜} "yM ! [hoRb `Bġ4A|L0PN1f+}O\'׋ 6 :ayyy#}ʛRʧC ub29_|9j6+bZl~z7n? %F:VkH*~!QՂ܎%]Br nkCM>G%A\a+5Bp >ѿMSyMV_um-݄bP`6:}8Fzgq 侒&ܹr3Uq$@cΥd3%0wBB0Ʒy3!1;ɆB@! ܑcxdB@! [hmS,Hj`{ üW EC"V;> FKKXȺW.^e=؄=;_"QBR1iwz8³^X[zPEG7 d%)az`?_On<sKߒKTQbsi(*R 7y8hA]mi,!7zXή"3*߹cz+c˹[13 wNJp/N@r'A! {a̽^! F6 5X 1JU.ns/u$]D< J^*ԡLn/#frI|?7!4 oF`PږB'@tIF7_Jl/Ǩg?j! kk=OCV tfwBim*'G*o+ P7R/ WB]0 n&]I@B1Z- *&)l?8o/t?E0Ha?n4APND0ռ #ofq 8gmbA7T!}s"qӄQgf&^lUXW_h<2O{9/"y@.nM@1}2x! Brq#.-(8g|*gUDhOW˙(66 %Mn.oz|:De>JX:]# N@|qwGޫ%ٲ-7K;ȑ\._.?K)@LBl0`0%YKZ3ժd-ǯ& z 6۸SSHjD`YȖGZF֥Jsi*sH@O\6VDΚzX,Z9? Z16(<%7kOg_*ur)MYIx+@ݽej8Z0uEڮ>:׎8 û9_y=5J !E1]788U\f 13$qα$@_&HGrh/%O9tLb.u/ GA*'j4@`CF~ȏϱW{1P°! "U9B@!zXQLWxnUe)iN6U7`P '+4,A%ŷm?t,m8Y'YJD2H+6iX`7XG[{)JK,fo[alIxl q=͸`; L\F&C(.Ȍ'Kn1/xu! D@1 B@&ڪ]ӎ>4pC9dn#$JHZ-ԏAk/N~͍)#R(]psY&ʝf(|7ΚK>~ xq&/e5ʥBA8CѶICd?Wʵ0}CTλ Mřx`}5sK9:Er^ X4IȺr]ĵur/Z+ыēscDٿa/?\aAR(<R 0̹XxěG 6?I Ed˨nt=0pZ5W{ }İ;Jldܹ2;<B@!D*B@x4אnљjBGңhr%.ǣ$;oCCv4`C/=s:NȁGձcr0" 3G&CaÓP^}T1v_aGMQSvh WR/qorg! [ $IȾy% =tFb}OYE !(ЉF u;}A儢wC(+U>@;) ! O@LF! nЈç}Dk؇t -s#znl ( MBT jyZ O}MOAvSl]ݝ$=E`zJڅ(( ਉ"uD@ϳ=k ֕KJwQٵrv饵@_^R!T(]JMqӴdd})~9 ӜP3B]{^]G8o 5uie+ 4&?>oaALD1dB@!D'B@x%іgk%im.O2=`$Telڃw:`P ++^QZBϋ 6La/qvO>suqq¢e#>q|R+0_nXy vdS.Gcv KOpc;?D1aK.YcE21tZqgYĸƾ Uwi~D`(쿾X:( wX{J<2/sO's$']B@ 0>+i)sH0ua9GTQP|+- K d?c) h!)$Y%xq vAvLHr5Pn0m 2`%_@/ii:S]&x @N5`AP|+UVt;\VŸ쇰ӏLj戏u/Y FJ{rgR0HkRwvAVG*eiB턚SXԙܲ}5u:i\JK%/Y' IEv$w^@B@=B@'xSlnCG);+.5+ Wm%-!88C Ka0b[Rb&ůtDuMᰆf["CE,Z[^DR8Ⓕ#n%v@g>t5;5cXRd[j-:bĤUO+z`[A*){BW=pR_HhjUƸWXc8q jrB?9(Shhh ʑv&!{jT/΋uG~gZeJd7 A5?szێvh둑uryx,Ѩ7q }V]eӚ? cxqX?ۢ0x!puG^D dDiJ Yy޶7cSV(޼bv챟wAG߇w#1:z[FD1ovBy=+,r/~TB L&ͥϽ M_Lb ]N(B`06W$8B@!Xh'DeZ˟Uoʳ5hErz`jORka> 9[p1rԦ,YQr%":HTvn8C咑} ކsH" e I+ = 8+RîEcpǟ@CYc*Lbhx"L=QBPQWRz=QUTr'`lc˵loԱ$xэW'*sgi3߈M覰j1c0S80Ǝ4vjwtA>Hy a٥_DX$)yu׉SLD ᄚV7eЎ/{G:vnMooX6N՝soBWr-i9B@! p ! :fb owA0H'LxD TĨxrwhPl@V˶’ە3D>O%+ u. KHH,i9W㺞9X8[:@`A9{rX@$,w$:5Xޒ] WMڛE(g90cPCU+s.I)<4$ŐU_.Z_tU|Yم\ZT{Wq`>^:Ut܃@|P߆T۞/ÒHPo/(?口/08=gA,k x)^Kz;]{@c'^! <alaJJj}B$&$1ʌ8ZvMTR36Rnըډ޾&D ; &j>e:i6I)kHX\Klnpm,ֱjMQ_ھVd\/؁_509vVK syç: E$G3E%#{3X 7^}7/>m'Ip^enDAፔomtG`>\79. F[QY~V{ 9mneq&0j8\_e͝-]SӬps._|%Qk.5olllB@3ƆJcxqL(IRl1ٛI1_tLvu[i76]nZj\b㖨V8W&ՔVUWBS<Qv/ItW5>>HP?:O&.1ԧȨtao$P!!*ŻdrćK' X D1aF&%QK]£,.+sB1-.ӈ:3Pa Z49ݟekX_ cxq%nJi{5al$ŀoʎ^xSK!q\ثX('o;܃*' 7-ޟ2CC64~G5hr.lR?" Kcu>TE{ϳoc_]+<.IwXCN=hϥ! BW ,_JU]]M6aʕؿ?]|3Ko>6{Aii)z)%CB Xm'm.}X P;wɵ((c3}^v[#t6C 9])kR42's!dE;E|^[|=ka>C{J"Yug.IChށ?@ՃY%gnuǽO\O[w{p&Kb>-"a9\ܰTsيKsZr?c9B@$ =s ^x?tQOn ?os|f9B}6YDb]aT؄b*%,UXIK(bɨFkaβaaF:v&Q&/se "_]vӎ1eي{qܡShh(,#;ͦ+KDa-o,tCqŦbn;B([pK};8;ǟTn?nv!b7*G;K 0oxvOqD,6;vS`pgA6uRn!M"Y~\v5!SRDf!$Hzw{b>'z=;jku=xJl"_Έ˟V;]g P֯>~k/j#ſ "SЅWw+;'Yzƿ腀B@x6EZ޽Kj ׎={0 F,~r[@ww-6]m%p)v'6htJ8A&lR-IagAοԵDbk.;=*i1$+N7UK K@BqǓ ')L?…|B AN.Ļu-n)AVdgOqo}*lN1CNwQ}n@ H_IhPgz!QcQˢ]KAEҟt> ?_ڸ 91؇o?ѥeGMy28ǜ$DN! Gal/GMM:bJJʸ#''ko&B@%`oA`,E(4݋~{˪uGxxrd7Br,\Yٗ'vr>е[vZX,aݵ]wm-\b8Fv6 2m*~B@+{Hڔ^uSuxX5Nu;;~w[IxB/^S>s{~&rfR܅@CX %(% Qc_ GZmFdz!Xݥ@\_pbg0FɉD}# $vqQ48Su@~! I@9,Zn)6DFjnjB9.B@t`1*׉cDgG:D{ vrH,[]Z4EUG/vnPyޯo;.LıcHi :R (>{%{m%i}?Kh%Q_`#>Qƶ*=$B_T/$Iд}>$#]Y<<Ds%"B@! <cs|m:::aV:U0' !8J:] ^R| 2s 1e5CbH[JGcXƊGR36"1i5:+u`1=: /ΰur 8$HD/ZnP"\,oB ܳXVv]dxlq җ~ 1Փ'O2>N _op{ɻP1f[r`m]}!* QQ:qeI! B063..N c,Sf=e.oQSzABV6Z,lLU8[c"+KoSot*:ХvOMi0SO !01æbU,vMJK"!08WxF1ZGuY8܉_|pOR/:{B.LqxDusAgYMsfAx.E! J@98{,ZZZ cls|V9XX|wఀ=jm)?3m5r|mA~Z=ۆ*Ns^)b j(t^.:r<-vRYl]#ǟB ,iQPx# Ʃktg xj1xf!~-qR )aě6t8xLAH =wGb 5q8 j7[[5M al8b"ġTGKWsbjX_W ;e_Ð ! >K@96lΝ;q):zUUZ6R{ʞV |wp$/,qX4_j98OXdT&2("`1ۂUްucΎ ƿv?:8؇'!W~ IZ\r'8!0qLEgd >6 Oo^Br>$A,,Z;{ hEjpliN7kf@Ugs9td =:d:C=̧Zi.6jH%^}+̃v'ܹ<[qe~B xzQդڙa Uu&;! jϵZ)B@" _Ϗ~x衇kꫯu ((r˨^ pn.E0ev7b JehE?̜Cʛfq]YఆnKpH  k>S3mBwW l?,>*,msrEQp%|q8@>:v7\wȺ]~?&,Sz3qMwL&]ɝM rh^›r:6]7O|ln=(O? @bu.}a1na7g.ī ;˃q}%I1RzS=SlOO)z-}x>ϪE$|bICqw;rBU]M9ea4^UGo5! B@?wcCo}/_n O>$ O[oEff{.\^ W4 J#5g^AooS Bf XHTPزMJ}7* K@MNԫ%ד# _DOYUB Gԉ UM!X㈈LñC}T42pGpŕ}^ W>;UuD}quFkN㸺 ƥp*,Zkc 4Z_'i oQthC#CUuPP4 )d:r:v`m_:FcqL.|܅EN6?&|ĭ9w*~jA %w!*:{dGY47/cE]ٯP_8lWq[ID&ro b,IW:ׁ;I6@βcM2EE  {}x:@knZl~|c~&5hw;GTxS!񕹸{E.CjY6! B@xwy'<\G}֭ÝwމGyַs_uK. a޽yl6vֳ m&C 0g|-w;XW"to(A)%B%ZUzr퐐E%ŷ*EΎ3Ѿٗ)Xggo2faX9P͢s9EWGOR>p֥t^m!Yl?p^eUݠ~-rحj >d8oF &GWhXjâa^Q1$ -}U֬~yB*m>Zsf%_CGǩ)Gk|}6sŲgd:rq15a.. g]ŅޟZ@u 0'>Ƚde[QJa4XS":* k.qt+B`z\ulMSthrK7'C_bp@r1rVQIk?-ZrjzdvU5mrhhǙǮGquA*+-K3OqLRI\f\ES$F~,4Yڮ>%=uZzA]"#ؒpa=Sz=hϥ! BW Jdƕ{> VZ-[1v ]XXبl۶MYV%0֍P8?o|QDܡV+$ Հew*ȁrହ~ΰJT:jP.*&[V]]UhD @X$ja4XXp]\RBn,|񘂨.8T韑u)RQ@b\r@z%.<\.Q.""U[V%',L{TSpӕ;\EGϺtxV)1QRWM0c =P-flOsHȾszI! 3)tQ:i'C[<6f'/sc8:츎'.Ÿ vqa!5 i6 ܗ-C$<kM8ܱme &'R[魥 TQ<ײ9':9oi~_%!>orBq7kqK N{` 13\ 4gצ#3 wf9B@! c:##۷o讎EKdg;A$̘9utlLH`FgN>WBq NAZ9%&quS7&a]U]:Ηz?PZ[Y9%JQʥ!\KH 骮dNNrzCw~]WM9HWH!gc>ql0cKBҊU+$آǵ^\sG""U59Y(,ݧfȤꔋ`}NSwչ6-)H|ֵ-ݠ*D&aalE8X hY`5m4Nh'| ٨ Nܪ ˟I|~b9xmyt=]|Ɋ ܔz $,Q0i <~;9.Ecjzp+˜Fj¹xi#SX\\"J?LF< ~}DӯBhEjP ,A4G _5~P/t'TCix=&8\ $.ƚԸQb\]##YݩRB@! wa̻< S(7+d'I$ @$:;3١u 5lRr_Bk:M r' cY)!< a…E)^6FnBk} ꖯp"-[LQ*]ኩ5}}!NIQSE9GuοB][oe _ƒ, sxDWO[pY|NvXno=6Wn.'Ÿ\ݻ*fXltn-lP8ǧXXt e,VB䛬$$}d'Wδ06rsS4p+h4&$5ݚB"pٰ{m1UgN;w87~i9A&^F!g՗s- W-q./.c*+X`8:m!H0PaŬЦ-H@Ib B#[cVCiV&xXZ-/D |y^28r4w{=,s%B@!]D5깳'Gv6LǬ;#;-ؕe4+q.`Ç׾rP8sVe|ZGԾ/1ïXiz^dbH{Mί! Hpuu*D!?`gw%#;J֊((uU-_4ic 3_3_t|~ގnFtբ[`;tI[%~/,Uum/w0Vuf:zNbtk15܂k't ɷ"0Pm<}EH7=X*\Qr"jðpkΖ7={W2FJ8^8ST|nJC.[lsBK;ϡ2+H̦=%h.,},VDкG˜ PR澳 ;apظHć.5WqG~.1= g{ZFί7(ޓǫmŢX|X0奒+, W姂-d{j!i˹B@!D3';,ջC9X=`aI>-YkZU)U]wrZS o&r M},)zMw떭RHcsqqINY1; V|n.z47",$Į%kW;AXJNO.e|^_**5pnOݔlحzy/} Fy8?L X ,6%tjmGB0!hKnMG/-炀.Sfl5K@p>ڹέk=VHRUz?R n'=J7 y8nIsSEH84ZZp!FF*qv SX~ENYvʡdJbpQۋH"&-$4V cPna\ %ތ]bJ*z4_Gc1RH-QPxʯBΥœkM~\e!M3VK0t ``psg&ˮ9g?}l|hi!]:ϽGwqSh"W+ b .$NbفH%93`S_O;$0'Zgی7k_{q S!+ 7@t6)~B`P9 .'iCHNGKa,x<5=A! B@̂cM4Կ5N~D L!XB.U8] &|^QTr'It٣xEnWXGՎE h\En--69:dwW\RȱBVVV֫!%w.H\ʑ5&O[-pdY8$u@]@OIHT^0U׶DYk =B`rsέ=T|1-AZ') ơcIcG[fI E~wu 52T׷> sNHc$_ZD@tCfzRi/B` v UL$}iE z{<{FUS 6 L77Y?Mřqkn xr--xT׷"d$‚=r>9~a.[.uX\|>qdyfXzV-r&>FCFBG֥YJ 8#,zRl܇wGub>Ga9jй-:bĤwBu>w2~! B7 09*+|ܹ>v!AvڜGVޒ(H\Zq+uHvErgy~w.w;--CCCP]œF#2L9X"B`>&[_ T^. !hߋ;\c>{KB@! aW&˝eǏWDd'! Ο@ 9X^-ea~g&$-''.rWz)`} ڦh0bX0IMcVDr8hwT[ Pыv$t*/8„H#YJD(V;[W*(+ )NIĞ'Q3M{I P[ݤ!XeHw>s 1L] Y PJ<4\\qBGO5%B@!0&2X&^/9k<_!k8am$KiC.cаx%~)L˄9݁:D׶<NğY=1Y!m֎>Ooe9\c߅㲚[qOqqN$\/",fĽ!wKd{JWsQ_ߊ8_dWY 4gP$p%urę`H#^HZS@OwWc~?^;"Ђ^G9`1svd}u(ܕy)*WiఙPt>1fgs G! N@1OB?! aàVk9zh}ܭ-[9[{ӫӔ C0W4π:^ phD 8-fBKΔ@4~RPRAXtLSsIjފUi9WP{mb19wVZd(8DOzaaCvVÛ58C.>Si3Ҍ`&a&/6"jЦMbO\P/L6X۵\G{ʜ]vV-,! &h[\bD~\$&MdO JruSⰆi[~r={^a|n^͝ u\+K匋1 F3BR*#AG* q3b}·iexl 9HZj-vR^~= =8D9R\]»JbQ}Ԏ˖dzaeXB@! (XuT*cS.^݅֏׈d[ s1АsH i-}/^4mzv&` Cpp MFy=J6OPW)6\̾b!* ! @O٥ {̞}*;m=c;?A:h@{ad-fRnqP^/b=N/̤ۋӓc8MxsSd.R9o_7V\|ϯuuB.VQȶ̡'ip?S#P,LN$vQ u^\Ǯ5.n3{9')ruMtK5C*j i^ ; {$X|/tsձXy}ﶅ9!y% +pe! B_!1KdB`׽SeO;ܵqkwfl$?G,<^{\>*1[|C1t͒4`-VIW>c?6MN7Fd 5l McE.], \m&:Ep86i*юnoZfV4Տ-bnl0aЇc Yr6,ڏ- h_9ҖC<ěIM@PyL瓵z! B@x3ƼI߅w(D7v ^N BآIRְK[]zhT\z0_5 k&}1/. ma!ŷePzRB`&(H"AK [$p)Q.B[-m`LK`Pn2c)!x<~?ͤdϹ-3D}sI[zϢE+VTIo}U8nrץ*@zQ(CA%H 7 ьD,v=~J OM@y!?81e>mV?h9},\ˎCfʙ}E2AXy"uv2B@! {<{!p^<)Dy dwh?9NO؁wXz%uܙ.)`<՛a >Hϝ#1?A!0K6ج7-i|X2 \,x \DB:R#sJEOc6?AAXtyͭJ$L]nUlra"aKÂ)/3\o'jGhxGo5Dw8݀S?o9Z! 5"̊lCd6ʗ•ݦTCzH"FC$R Hկȱh)KYVmcvO(1q*&Ff }B@2 /Bp5_vXW Z,rήaK@eS.rE.%Ѳk>iKF#c"L94a.ebcב&n珵b@~f'\p>G>cf׎6 L\#76e.B@% ˜^Z; xEdt“U(]5Y`N+zhX"ы[]8` <[< 4`%Aj9'n0:!:RbqzXie'BF֣F }:r '8c ! (µ>:,![< AarFnDygO8Fåe}[=4-ib/O;H)T׆kPqTrCz{~wD~SqndG ! B@& ˜_= TʩbttuTNˡ|а$&CGD$l\ct’ۑq>N/B@9$plljb )QhePB[!$v9.H:`aDq=ACKd~ϖ@N='B@!Dk(#CJ,NX J3S bV-Z G\BeBr_ӊY},hY—['F$~%&FMN5!"<0 ! |+'pqتkADQ+y=ǽk"9+ N KZ ! B@"|옆00 m4zȺ6ʵ5]pa4œiBZAme"p:x 0fki&Ds?%~Mό;\CrC"+3! LhI4a1Ru>lB@! m")Gܦ/ ^f,t9PrvPh52:К{[BNFꄀBP瑤7B%%O]fw_/횸5IB@! cN{c_GJD{;q+q׹wsb"M! B@& ˜\5V|ٹ̵K^!JPί^s5 8W$8B@!i63N,CB5(4jHu`J>]4qI'8I+ Ą=B@! a׮㩧ʞVxsMNVBq`^ӏAZ! o :O3,E`7=qέH VtWwܽB@! /a˘,$m'QRD*Vl2sk+88J2Ρ6j0"B@LIܩ\< Xz٣R\g~r=V՝>wo/i%B@!Dū2Ɖbf:А^=v xbi=rHh'W*B@#v MuFxluF,#7\\ ! B@:| 4L9Bǰ,(Ȉ>(H'!!e/lB@! N}zDį@Emz|ܻ`qOqVȉsB@! F@1_cƓ5NN1 l7 ;f/YB@! c?C{.cl/(!z|Eq}N;"%Hr"NGLܚҶWw}^J! B 0WeL,z܁1VXrb.dQ! hx UG @ѦAHD M!vW7'.sմ={;rQ<؇h6}$:XUwܽB@! /a1flDbjT- ;Jd_!lLKYB@! @#P|$`Gm^DVQ+瘋0 ,xݳ}K,B@! c"1PO=U k_\WeY! BCN VĦnBΚ/{(@` Zn؛m~C=" lj[=V91؃&\B@! wү@IDAT068`"yu^ ! )C La(R|`kueb3=軜&j7cǽ%{rb|u=B@! bH8Lžr~! B@֚/h?)4a*sn C.WMoa@6BJ=#,Zq*:n4> ! B@>|B@'Uo?HB/#*qXF'czX8XbAD@t=VEޝQ &6 7ȥ,wWYVEŕwu]uS@$95S鮙Iw׷u=>ET)E Ѝcثb"@J#߷)r[mîN {.Н'%{Xފ'>-!`^ВI!󸅥]G @G@b<}-R @ nGidakHۅdBj@[#a^z^aQMb*i+%skj߹3Uaus @@$'@:X`_. 5ap3&Nh:r\?K wZꚰvU;ݟ| 웳ac˾A>/  @e+sX nOXܱh82 \oK wI7~j'>Iw [.I pۘX"@(Xz\ @@ m]=WW3:>& @R@R8 ,&*1<;]|X5|K @e+[p$s¦+]G;<'P.*W:8v؇_3H\} @'0B @{K᡻Ȟ'χ S7XB{ܟ87 -'9 mG@|ysgfy^k @e0bL-V @֮mXv'z!ǝڷx.p!*zÕ[¦ްʛ*w6t%&Ğa3K* V ;wFVe>ou#@+-%@J,sŒ/uaO. tWn3|;{Âkª%H=1vg;UV`$Tˠkv @ PR,MW T nz0̙WaCJ+pb:C'Y!j# qn^ χ/]޽&yy%DN `Ęs ˯v5aa_ڼ4@&%xv$v$&&\vpn{=b\6(*E߯< @ Ul=.^ @,φvk,2 ɰJ7)<{ÿEG3,z,V\{ʸ1',,_/s>*zs d:[ @nn @ش~E> >mYMq\@LaOCB [Q: @:S7&@\矿9m]va'.XxY dnbUor˳C]yS9aWőޮsf*{U ䷚, @K@b\-Z @Cݹa#i=r$@@qpg w qԩ & jcg .B>*c[M! A c]$@:M`헆}3L{ɳ;-%@NL6mê6onVOG)g+/#9 @^ @ lxOk>󀧝fn w~6kߚV  @@}k6f;yRںfցQa'4? bblMYR,n3 @S@b.j @Mn?r[C_aOiit@峳:yu%g׽нCdhc @X @%Ha/.l@3ia[ȅIN &j_<_& @ @7֬:L{X|Ⅱ,휞pTt@|޹h9 @gG!@T  @J, 1V: 0w#a÷ ҈{!0m~%^ @ @~M" @@ lPXz߆/y؛.{?H`ͪkUWԾ6]Sqa΂ f @ H5+ @I$nÖGW9?MS1S &VAY}MiQ"1V)b @"cE%@4!p׍ kV&L[\ CO\M)B@(ʧ [ה{reM @_iF*} @:{eXqdXo8eɱ:l"@ 8(  @1Y @ lpwX ¢%?PS@ @ @@ Hyi ۷[z{ۺ6s>G3 @ @ HJHX p@=cw05 @ @H@blDlDx\`-8L0qwZ"@ @h !@:Q5ۯ@0kף:1 m&@ @B@b,H @`,o7}8:  @ @Z$ 1"H @7 =8xG b @ @@ HuXi. -jx`B酪g~1N  @ @!$Ɔ P_`wa @ @$ڪ;4hwm[oC\۾/l&k @ @cIOgPI f P-$-W=lx_a?P] @ @@K4Fsu{%:4v]7]֬u4u B_vzh @ rIbW.#@Z%W7~:'\LߣUU @ @`$ a @ؼឰ>G# F  @ @%+q h,o˞+ַeMIaёMJ @ @cehaͪkUWWQđK[ה{+,xz|ռwἰSá&ka"@ @Ov, P@ &3N.JW˚+@jE_[&NO L2 @ @@G HuTwi,I &pb«rZ"[0w1iblY" hl5 X?ì]X @ @뚮:GvP9͵4XL-ZrNsuy" HLqOWm 8-,<](< @ @@9$Ϣ$@@[ 9§͎i5f\"x =(xy @ @٪3ۛ3al&0"~=<;if8_ o"@ @h?-"@@ Ԏq{ p7;~ᬽ0mv %@ @h,0q% @/mW%oߚ>Sua}_A @ P2#J%@$_+lx_ဧ~N! PL`ͪkB|fo8#+x8D @c' 16vj&@:D?~><|ä)>z&!]Z &Vm\_ӢtEbR2 @Z/W֛ GEX~ ==a)3vP5v#brڼឰ%}MW*XD @c+ 16j'@X`ˣ_3V0wgqk5N^^ @]`B(> @@=[ʷm <),:F @ Ec]ԙB!@ڏu\?5f%  @ @:R/@mMF?\ؤbMuK @ !cQIFѵ[Ye0k%X- @ @m/ 1] @@6{k޷1ž_ߪC @ cIHFණ!l\sk>pkMj!@ @* %@F#o;iF8/މ3FS @ @tXv& @6

zt᾿\Utүi4e^X|g@  @ @+ 1D-_<wqa͚5}ƍ 'V\D !׾7ի:BDɞz2son&}!۱#0e @ @J' 1D7oTO{%\6mw7QC#㗿e _!tdOs=WI,TGCֵU- ke2kQ"q  @ @ P>e]>0w܁ҳg/ÿ뿆;/~jZQGm  C%{slyI*c9ZzW߿ޘ{ 0q򜐤\M4z[:omI=lߺf[_ؾmctTmi5Ʊ6U7m}%oJU]&Wׄ:&ߡ @ @@7 H5YO>yPSN9%\xK/ 0huu @[=pmGgɞ$RL`0<4{̏Nz'ͨjR|vXoeA XpB|=V @ @' 1֠g%/^<mꪫMA$зeMXÆnopG%O&V'TZ݈މBOV*z&zUNgmm\mV;MR'[9 [9 {gUnJnT7-7\OOoVUf%bc5 1?9 @ @@gH5+Vd%,X0mK.rC+ꨬ2+f5aoնy=aK2s05}UNs<=]pL妮Xitly]b;5ttO}(>"-8c˞4GIշ @ PF~g%3jYvիkwU  ж1)On_ĢT'ƶnz0`qDM;?HT* ,3Oh½^1y^],(@D7-׭ gN @# 1֠y䑬ĤI̷mݺuо >@/&)Hf5acœal'M6?=p}$)sݞ2( V/Vɞz*CoڦvĩM'?vuZ 0uW  Re @\}7u԰qƐ$ɠe;wa`'m#GU1IEKiv6jHITw?$PǔJv . 0BG#@ @$ l7o^ɱ։M6eKuԭF@`ۖGºm8w0caI9?5LO ZdOKUBqCq; @ @Q H5WD@gm 9K~mH`1iW0wj5#OGA @ @]hzGqDxK_.}v^zi{[K+wJxS@ o<0Ql.Ok @ @ 4MMb} /0}ᕯ|e?̙>я+W/H¯~E߸iӦ_:_Fwqaԩ, `L_Uz 0I*+ @ @{~wXdIzֳm?~[Ä ŕ"uo>}zO9llƴV)}Ύ۷߾% vS%&Ik( @ @$ƪ=\k·!;*Gxyu%r s)}$k}K8a[$؍Iuiv$X$`\;j @ @v_Vw8;HG:`p%?o}xk/{nIaaS$XτIa5#$u∖ @ @1S<>~~x.>lDps/@l.iVmx_Z<2l|p_Kq4Cw_1mڬEa.O^v92&N= @ @V@bmY[/S?dy~ 9VcV58%]MɮՏ%Wڲ11tUضB:I9ާ0Uׄ:t[| W훳acY!@ @W@b}%-==?H$GN 3۷0!}nQyzzI3+{h1¥2TW懳Ax x뻅&NEU*ݼឰ%}MW*Nq#nz౤ʰ5Mzmސ&W:+M~!$ Z)H-潽}K'NzNTR:D &V麭Y_ӢtEbR2 @hoQ?y@I>hy[ªozDZOP˧I3BOp˧IStߤ4974Y10LHuV)#oi|ڐ֓OxvX}w̓1Ivl/_HV ,SLjmMGtDWښps6t'I&攙 w$f, Sה5yt9MUco^pȫH͸9Fj>dF6;V95cʲ  @ @xem8Ҥ[e^%boӺeyM㳤v$v$z+oKmYB2V=郶` ،yEKisocz<^i+{e8LG#658fOG^3D^_PUb(Ge ;msL/Ir=eV'%}K8M'}>:}nayp$؎և Gz'LO=M)i2lE>m&N~x @ @ ===-Ab[Y 3~qlY-6?و*ҋg-#ȸY"-TJU$jk}11_#$Ye^b->S++&&e#]b1ɚی61Ay$4UZ1l[{W6+MpMH~MK}l66;  @ @ @@=II19$w=.ׅ#{qˬv$&hӎi.lvq9mlmێg&;qF&L6+}㷩ĺ'K'NLY^ wp[Ng/ZD @ @Z- 1jQu@L >_U-GڨP۞%*gI}m7Ͱz!Zb3 @ @ @@3=I:5Sʼ%/ կwΝnݺpO>9\r% -ZG V[UVS> @ @ @Mt#npeO?} );j/yoy8T;}#'#h{N'N 4_9՜'N 4Wĩ9J985'|)TsV85'\)SsNJ @v(]b~qdXt)d.]UE(Z`V @ @ @Z"P؏ nŃ>lUW]5h_冢u-_y, @ @ @(]blŊ܂  Ο??۶tA*7hcY&@ @ @h@c&)V;͚5+۴z]UE(Z`V @ @ @Z"P#qjNR'N 4_9՜'N 4WԜR @J;Ç?pWSO=?N;+E(Zx\lV֯. @ @ @@ ]7Vz^~߆[o5̚5k0G}t8·mC-hT®dL @ @@1.I)IDATT|+#<w+W~U|8㪶c${6mڔlq6o޼c @ @ @(ebl=F͜93,Y$,^8KQdϯ"u >}z8Sb6iӦ @ @ @Jy+> @ @ @t@)GuI  @ @ @X,E  @ @ @:W@bsN  @ @ @ HR @ @ @s$:ﴜ @ ֭[|6h6q @ @@$Z--[,\tEᬳ ,h? w\:ujc=96lذsG{zzz:͛7O}Sٳɓ>7,4kQDxN?pw%wp'3gy?>G?6V׭%'v**rtH×$Iv|͙3'%/׮q98,8,_,gg38#Xb=/k+jkZ8:]Sߓ0mڴxvm|u5+9-T  Pz mo{[٫D QnG}t& U?OέN_rer'-J.dڵIv'k\wu(HE۷oO>%[/`?;WyK.סwٯ[#=?UUYݯz{{}{yHͪJvJѸ /_upSOMdXr]w%/x dwl$@҅vSeqy;5\1΢NL>=׾}_?'$_}N׭_iQw]Qn,_~fwБOަ8otWmvhfuժUɤI~ mZZ6 @/_M%ȿ0!qI:'y_,_ ~vSk_Fz~tuyM׳矹wY>_o4٨_4}>ze(I:7Odj4y.״Q)77S]qJGg;<*o۶-C9$˵S]F>EFr~rQ|ב|m4s14;IExLo$-6e/{YW;5=u=u @``Rli t)0j?${l_'&Ģ۾[NgFɴC`ƌIbMTJoיo*ݼkQN;-2eJrWwQ7(8Z5z͝;wо2_Fs~tuyM׳]^^{%dzfќ?^e]ٮVurXܷ(;s`Hˁ7 rM+GQʘr;(N/mb-YrfS;^F>Eߕc(xfu$AG?$""/yȦ_>3HLUNC|h]+k/.]/]0DwqdFt jKetO4nlߓ]Yo|93~qha+z5׭en5|=ozV4/~Ryp #=7nm.weC[}VˍρK/tPs+Ǒ42o;]ӊQ)9Λ]Qi]vα۟l_V9h\FӢNEJ߱Xn_/Ex?Fx+O|s^%x`_ %[kt|>OLpos뮻&nxK~QV3fǖΛ2\φ={dף5gΜ˿ˠ/?vq׶5h}~h(٫>`v>~ =G']ӆc$NEnkW8:#N~ӟ:q[y'vn}N: |lPP[Q|fpj&S_7nܘQS~k, @&_L4!&+77M.Gs=77,Y$V 鏨!1.cH׭ƧPMgC+V˗/pgw;ϋɹYUAUZUxՓ*~vjYfeV^]kptM*8]E(1_v.BtNϾͶWԮ׭NW|x_:)rޏ֫8:N~~N8ᄐ>#ʢ0תZ!@ 4Ν)э陑`76V1/HN9唱ꍣhsR׆iB,E_җ/PҥFKWi5&$>T;O|m<054wqYW\T~*z~5IY+m?z;`ak?V`qvz7cAMxFPe]ӆHnkW8:[IOOO},>GG?JN>-ݯ[#FӢNW|\7~-)zޏ֫h+گgqFo|dЬ@4p+ņDYzQg?KmWE?NέZ$,Z( I͛7CjbFKd,sM7 bug3̆!U(uIYy>)OɮE~97A C]XؙKG dF%e_7 u^v5m8bEFw]FGZre7!IGg^xq/NϿ-yl֎߹F>XpwE1Yl_+{;h3h=V~ݴiSvM_n]mU#|5:`6 @M H5}}GQ?+wuYE]T7*V5˟$]Rfk`Dze˒xbѫ޳ wB%h̓$~fY)[s|pSY[EΏ2^}jϡFM7_^kU~g9s l.rn]Bwz{ܨ#i|~L||Ppe']ӆ#^i$qk$qqʷ#ƾks:PgSmFwmV7U=;hyj=H5E/zQmUz~(Z6 @ $ugF_3Qܼ%/I>Os#?w1EQM7|sUx+O<1Q?Uo*<03z^CQykL}_j`h?q8 @K!>w!U%l&0@z PU05V̶]wuU<.p1d+(7>&|>@n6mZՑG9dten9?< hY3&-ܬF#8䘿c͎qm :VߵLmnh&`$Nnֻ Y!}btydz7X]Y~g,_3g4CQYH53fBЪj`h?t@ @@ h ;^Wg ]v {'vq ׭n,>nen9?*I9f|[͞7x=k6΃:׽nXssMP/Њ~}~zVW\10^{m?kƣzUWX=6f)TSr[-ǩUv9kl"NyXk_ڐ>C,U:ZrwhVlwƫ9h͞y5oUHIJCrV·#?H5&ŞԧsUU͋CתY!@Hk*@za0B,Y$yG<,U; 8(y{wk?яAʲ%bi}I}*O|IOOOrUWUm~v8zjyX UY؇m۶%(xF+VpqW`eL|/}K=#}S򔺷QlyLگhE;5T1:w}X_A׫ܳ[:ujUxr&_&k׮MC?$>+lSkߟ(K%K.MC&_d&{Jvm쇫tAq{Mbr5>&>v*uG]|=ozV4;,e]tEY4u^&k֬X&87U:FwlXk6XA}…YR"}bw+ۖޅE˪7WkH(TjPqwڵk8bEs7w=3PeVҎ׭_ӢN#9k[l|XHj ;k6ZI6ɮsi~uuG. 1V3 Y;/ð/j}*{'񡽦UW*>%q#eePϓPǿ?s'=IW򕡊w}cٹ2iҤ$}]rA ?T`ená|;m{O67r=+?8eʔ$^k/yj}fUe;aeqמ{zmE;k=v>T{^͟??@V;#oWm>8u*kpq؛uzֳYg}gXԎ׭_X;5(4]+_fu$AF?lí$_pm5yVu @zK @ @ @@W LG @ @ @11 @ @ @@)$J͂$@ @ @s @ @ @B@b,H @ @ @1 @ @ @@)$J͂$@ @ @s @ @ @B@b,H @ @ @1 @ @ @@)$J͂$@ @ @s @ @ @B@b,H @ @ @1 @ @ @@)$J͂$@ @ @s @ @ @B@b,H @ @ @1 @ @ @@)$J͂$@ ===!wC l^r>xҥK>'>q4?o~sXpa:uj8\0=_W+bl @ @h$F+ @t ɔ+V3<3٦{'qXvCGydxn8ܘ/<9 k[׾aÆp% :<=܁6on|$r-SN o{B$, @ @`=?2+cO @NxGÌ3vFa ը?O#Ȓb-ظlILS'+_Jx֬Y̙.&f͚U7[O>9 _gݰ> @ ЌX3J @ | ,W^Γh۶m 'N[f<7vǩc/yKe]V(IN8!,Y$\E @@ Huq  @@b%&TgiӦwC˶K"jQƷƽ;T1.73gf*۴iSFI @tgubi3 @C wqSTXn]6b,޲4>`KYS^ @ Pnr  @t߅WU[nɞ{LqR,oG7b{n6"-&q?l9>y{^v;8)oéxA/ᬳ {x>lٲeP!޶FUgz/7tSU٥K;/vaa=yO?UZqV|XwAţ͛qOTk6{ˑG͛6{… >nUf9??x1DŽ-ٹWLlgN @m.L @ xqKҤJ?|lv7gek Dm5\Ӓ7Məg\}I:*yސmߘ7a`_x+xt[<ۖ&45P6.#E%W\qE~=~IzȁiB+#OO_ɭO~@11~[>'tRV{Aocc C'M4&'xbvK.$X?qdʕ#<<9Ɏ~͚s9?d}s'rJ-2l+ۜ @@Wc%O @@ DKsMz{{5?Yqի*t$[l{,mB^e=q ^=_I:*?pwfec,*tN?ϲ>OVe͚5ɂ }czC/iOh!#NvZUxt[s\վѬ&M'$' SDA 2(2HdA1C zt(N$T߃Q38]uw_[e}wvyRy\rwi-q}]za2֓&8㘛di^ ri1\   & n@@@J?q/=BFFFd۶m6V'3j܏v;{>e2lx?~3le?)-RPP ?mݺ5u!ٹs-"gk'=ǝsIIB1VBVc#=_J6ni1@@ v@@Vܼ޼9w?\9sǏ:o ͤqKei@o*q{;} `e*qyb3)//Q9|444H3̦M̴F>G@@ b Eu"  L{٭nݺ%7okpb;_dslO?+Yh+]Y޽{ellL:;;m7=itmk̤ @@@Y6  ș_qi;v쐇… +*_|iΧf"ig7Kt\tD-|_J__˗}۵^[uD lٲE.^}ܜ\k99sƎcillo߾-ǏGll̇۷o#G뼼<_M\@@/    yQӧ#.:yddEic2lF'NϟL@,2gE.]uڷsebb׿~UG&x?'''} f?fgg#bd\nֈIm ܼu`` m☯^J,ӛ&;FeeeŋϟɸsJGvxM#8_zjdpif-q漸;v__Z5kjj"N_d]]]lh\@@6)   ЭRK:ݢn822tۧOܹs[ٳgM8 N:)))Ƌ[`\v͎;==-Sd߾}Isto޽kӭ *Ns}]m.m]kv f&w3g'޳Zl}/,,Xw"4Uٳg ıu&@'&*&x*wߝqZ2?^@@]X֏     "c 1565 936 x q@IDATxE,9IP" *D@=D x*yz?( =1p/`      H&      @@@@@H a$@@@@@`Ё     $DA0      0g@@@@@"CB@@@@@t3      `!!d      :@@@@@@0F2A@@@@@=|彇@@@@@\"8N`A6MV,}它@GpڅN[hMh#X }Vm@jGU=%G#X5 +{p     `!p܆      :{p     `!p܆      :{p     `!p܆   7n˗/ū^zG}4E\WÇ9t萗&-[J֭Jgϖ޽{KڵxRD iذȑ#sfj%yRR=Z7n" 8@2$C@@@)pʂ Zj&۶mʮ]dŊ|ԨQm6ԩ9o޼ߺuWAIrrZ~dǎK3gD_;&wq\q?~Mw)'N+]w%̎]h` 6A{K X#Ǐ7[^:E6f͒+Rj֬)֭ƿvr_{e˖'NkFϟ/?ꫯtAt%8p@J.m#uk_|.f%1B{L% tȒ    @<=z%Kʚ5k|!ߦM 6… }=SL9sؼyf{'tvڥ0=,hO<#ubt @@@"Э[7SA={r7(}v3K"23㟷~[N:ek5_&%+m2 | @@@@ gArdvڰ:~WK05hI_~)۷:+>=Fa=}Xl /4믿^6nhNu=m}ESJ֭ͦ՚g.]|OϿ;se˖~1_D*QYJƚ>-7ɓ2rH_-ZT5j$ͳEk~~+WzJԩ#>cǎ5InAtРo?3ŋK…jժҷo_9tPhRITs6)ϩ3VN@ N!1sǞE@@ȩ2Cφ=; 믝Ax:,\vܙao|~i/p܎yiӦ&ɹ{ѣG;3c ۩),Xf6yݻ7j" ⸝ΤIqlmۚ|xǓ>-72e=;8,^Es.PCqw9+g߾}o?aqUWڎΝ<#>_dMk?x`f掭͋w@ ʬ7Vyj @@@ w`A:v(^za.A9_̂и ʲeLn'N **Wd3B#ΝkѣߪmS~ аh"i֬L6̈5kY`^P!~`iR8sLèQGB;Dgxӧ35tvI?י-Z0硞ќwm6 veR7m$5jԐ;O~Wdkݒ%3Bgԭ[l"܃DaŊE.%:WVͼcl-gٵs1nҸ:RH[ ,v@@@I@;˖-+?Ft#gwV)RD.ӬYL'߀ޯ٠֑AI-hgOdx饗@.Ѥ-1.A;nư۵nL+xqOw1y+C4ivnO9뀑 Ǻdݯ#4H4TR&̄㌶_)ܩSȢsyc2ꅗ eԋ/C<*kTry @@@r~k׮2: kNku]gZ7uX G1[L-[Ey~0it&@dAoC}fY'o_XeLY&+= .bsY{ m7xY{g6|G~e1/ ד.u:kXJR5,k2_v>H   @@ r`Y;wug]v~.tFDZ؎gZNhG:K8]I;׬Yc6@/[oɽm^:<Ӟ={|u=K#=O4ә'zݗ nJ:vm-tk m6 4w}kŵ4֊dOfm۶w)./mݍ@]f~o3pNgv5Bw r(.`sƿ@`Pz!   @С)S쿠ߦo}`whO?7|c'Jm!H棝c[~S2:A|ҥR :?>]3{]D:J*yU7wc;a۶mf(~yժUf/ }=4*$m@י#f,`. /U|w{&OIQ̏;ʊCV(S+CS:   !Ppaܹ|A9N# EGvXyƍewy 6L֮]6޾@ɭ*~|Μ9#?}tCܫB7aЮ];ě޻1AF *_i6eĉffauS}ݸY`a3.s?;}y̬OV=of>y#@,QKX70r@   R`ԩӦM.]KӧOOsC_cX3XE.däI{[n2zh)^7NtaM,/~7n8pO.|^ 2eDZg92O,=,Zܓzs{ҢE ٷM-M#~i"r+VnQ;ٵnƭ5D摈6MtmiZ6iˀެ͛A;,ͤ$:3R߮z oC4˗$ZfM65u`qF:t7D_Zbg"Pnf};䮻 ҁh8M_reÇ9t萗&-[J֭JxN뚭ʕ+eذabu@P    @{eRZ5m۶]vɊ+Qd۶mҩS's޼ysuVkРA,o֯_?ٱc(QK3gD_Yv-=SL9sŬ ƙR@ w RjϘ&obz!   @Z:v( 6e˖g_{Z$))),~RN}:묰߿_.bB,>#o/Z=x= N@ AeC??@@@@CR\9Y|]6įJt  ="`/}GĈ#̽O{LJ.mB4~ryכK?4ԩSuf#ͳK.C[vjRUVͨuSNK/d(^ٹs=zԤQl?f`ǯX\r}mV ' @.`!4$   (Xh'% ԩOmi.L,Ϛ 4i"کA+ "!fΜ,ș/Y#eP    Y_lYoo޼Y?|sӦMH"r%Ne0k,D߀٠AI-u6RD:q:o<]'u](+h;i)Sl=ց 7_kRJA#GF1A :0lUkۈA: ~?~.ek%# gyN@@@@ o *THvj~]V ܏\I㯻tBc.)igTСC㛾dɒү_?8.AgDY@e[_F_GVd&G}do lsK  @X^)Ѣ9 ?e7BN@@@TZ޲eKӑvVϙ3'Š~%Bgg{3=;UeFulР駟]f魷2;ֱ4=5"C2|2N&$r3rB+%A K   q yJFFڡny .7n\htci[%qر,!    X7kN}K߿_N] mMZvfw jdЍm%}.6m_`r-T#M5#uEfchT3Rm^Ό25hm۷,\P-[&+WpЁx:h!ejE\9U@ٟA|*\(3@@@@ȱAeyѢ     KA`A@@@@@ 0c#     ,@@@@@+Cm:*     @tV{P@@@Ȁq$_|)^3>)4}ʕRСC^Zl)[N+YB;kuʕ2l06hIII2zhiܸq$aף=C"ERJyjժ8AǝR@@@@ ^Y`TV޶m[ٵkXœ5Jm&:u2͛77[nj3h INN7|\ׯرCJ(I̙3 wgy+rΝ8:yl޼YnV/d:h1tPYfMXN6l(=,]4Z{g}ֻdgꫯ[nʅ^(z#Gxi9@z|/'닥o   Ǐ޽{Kݺue)5k\yRfMYnH;ůZٲeKdT`u6Fɒ%M~zUVb)3RtT^c)ߗ{Gׯ/sʈ̋s@ 9F@@@@ @=L~mڴ+ʆ d…) 'OΝ;ebV2r{2 .H؀V&2C+]TӘc)OZM-QfSjtrz R@@@H!PX1馛u< ի˟yd9>}zLb[ 3,пQL4)`R,N(`߅    t ~ Or7(}vGAvLD~NqB ,XPt_ |I M 'G   &:HrdvڰG u  ="`/}rYgݧ'GĈ#̽O6">|\?_lܸќz SN֭[%4.].y_,k2Yjh}t#G}-*5y3}^ǎ3lkŋ… KժUo߾f/{Z;œOh#yIA<+   yH@"g;|ҩS'|S[Z.˪U!u&MdΝ&/2d\ҜfΜi͞ = CСCeǎ`9r4oyȶRܔ Ց @t9eN 32Ǖ\@@@@ Meʏ?(7o653g4mT)"\rTV-l YfIzoA3lNȠlyh^z DMo_:!=Ki}i_"q&>)wa꬐ 3ٗ)S+Fg8hDRL\x{N'2>?Vnrm]G\*CD7Ə/v[sz5 +Ud堛TEeevкq   @^(Tt0 ui%FD.]w]Lt:k!יm@AC-&,}ɒ%_~aR;ID}~S" ~dg.YJ;V.b4v Mk>g}dĘ T: @.7c.D};S/^lٵCC7m$Z%pBҦM2}hY#   r9:OFluft :C2b ֭[MQ3b);i2TW]uUXVQvm/Zk'Mo>q;3O~) y@=4Œ/cٳ/* T+֪UK:t }QX>TNR{Tn% @@@'{4 7ӧ,]{_A+=#KqVAx׀fgΜ]+Mg?O3DD+;"w>=C3ץt F^yz>,I,.s~&'.fe#I37e܅a29sZֽ-Y]NM/+Y/Yņ[eRKîq Ϩ C֭['SNO쀃^o1l   Ν;ˇ~(<@ {O?㔹$9yƍ * Z' &k׮MQoDG;u5 fCl{eɒ%ҫW/oAtIWA%;`N'Zz]0.$M/-Sʹ0 Erlӧ;uFCd{|2`#9   Oo6:W^_nFA/">*T={ȩSt]~'eRxq7nܹsmTuV D%iuMD}3_c.)_|uKkO sɠAyfφLuYl UV.=z;׾^}U/MjɎAwpvZ]cǥWʕ+?Kٶmut7һq{{(8,qAg;3fnVmo&{3EV-[4}uew'w%{})| ?w>:QR<#?m!`G /P_H{n9(^өnNV4N٢=W   @Do4i3S܎lo^}6MةL]iΜ9ҪU+3Aa„ 2|pٴi4h@hqGkF^{"Rpܗɓ';af!5J-KT׫W/J)# *d_T"ڵwA5kfuk]rIg*T^]z!? [oѿ'traIz3Z%B'?#^/̹A(ZƳ t"E9|ueZ'@@@@ȫAe!'3A oG蚁6J*fmFwʦmٱC3@@@@ȋA͟%|YglfBfPu"ͻ齂8@@@@@@ tH'|r̝vl i˙+@@@@@IAtMt#Ȱgsq^Tf @@@@@l`!_~sڵ)rظqf=ά)*@@@@@XAt|3f᧟~ ȍ7evztX^1fG2@@@@@ _itHg 5lPz裏a|rM7IժU뙝+(;Wّ @@@,7nƏ>o|ʕ >7͡C4ilRZnV,;fIYQHN"EHJL; {Nx 3O>cee;f܌yN tsI@@@/+~&O/իW7?zaҹsg߸^2eJ̀X|tyGDJ3^רQC&M$ .L7EVc+ɍ @@thP-@@@H]@7lذ JLk֬vڙ4GN Нwi[oU]vIАޙYݎR @t"   @ tAʕ+'k׆UD7ѣ4h@֭['K. ͗۷o/guVu=Yz1{iyǤtrך?|pэC_/7n4t PhSJ֭g.]R-4}c :qRxq_v[Lϖڳ;vLyWpaZW:k߾wy^ܼy󌍍"t`{/X7֎ tc "   [[A!r_|!:un7>t˪Ug+R4ibtbȐ!rJg̙; / =^;v0uK}7R^=V)TRf6NҊA{ȑf9'C[o_t DRRSt ,$ItjlbOǖ; H:Mxd@@@\ ;vK/?uh,kذ,[<'B fy%1JlfP赹sAG)!k[;u&BhXhzڴi6NgFԬY d̘1^N]Aް` :`ӦMJliܚ&tf&HݺuL [K޽M6:@?3yE=b j!<'O: &:z 1|"9 2萈VayC8.   @6 hsJLGv[gRF~#_pS|fvp"D ( :z)&LvK.Oqo>]XB_,K,1ml[-Z|hyXԥt@mZjٳgK˖-mYk#o[Hs/޽[*Vh^;w;&~vsI|Bp$L@0a#鸇[@@@@@*THv*nݯ_?ѥ ZI]iرf 뮻. 8uvEd.Thud(DQ :؛zu>w}dm\|A]JIVXFe.TݝҪǯmǚO=q|蠌qE?ԥ-Q2t$@H9T#   [Lmv?[}4>AG<~պ6y ]H1[/ץt#-[Ěe\ve\T]uUaSoѯz=t am;iv(\&L\֠>/ OɉH   :t eʔ1/3jժ)P|y駟D;u ](Bv`@˛3gY)l0k֬KD7,ҥKv\[7.[TEjA\߿O[}aZ.ݤ3EtAg;hs!Z:H2dFWWB &%K߀_= 4H?#['>zGkxIѲjk?o٥Ȟ|2rUfi==tH R@N,L2#1ǞE@@ve'Ox\/Uv;n'y &ǭj@IDATիWFuy- w;M3,xwFw__}U/MwƂs7ݍFKG8]tIvp,Y⸝&}ZϖV;۷o_q6lปE; s}ʕSkq~r=\IqCwgĈ&rrN:߿qg8cƌq6lho&Gˊ ;Z;ƛOd=|zY~*Q>C@90m?E@@Hm&OUz)nG謈ԂMvCZйsgwCVLu`Ä HQ d)f"ش]7>sY/Y?8_z,62{#ѥ4?uѣGy,zKTbpxl޻. %9*T}٦vډ; ͚5a;Z;ƛOX%rrsg -?ZQ G@.F|NˠCf 0(HF@@@@ S5~:@>àdƈ7BߗʾP2G :Us=APp^   /̛71i6lݻK %S$$B :$sXAP0N   ,]TtYfB*)BE cy     W\!7{H4nXb# t H@@@@ ԯ__+&˗'xBF*R@L`yL rA~d;    d@w鐝F@@@@@  0萋GA@@@ 7 7;^ s9Gڷo/?~< III2zh= fϞ-{ڵkKťDf__>sdz=вeKiݺu!!Jq`喤A~[y@@@ ٳG^{5:tX;kԨ!%K\tE2sL@bk_nE'Nljcǎ?Xze6a ֭>Lƌ#;+9h<ל9sX"Y![ :ϟC[i."   hG{ɒ%_G~Ϟ=e„ ƍfҥKG_tk?իCuVs).!J @z.+刏D@@@%R  0ӦMK-Yĕ*U*r|I5kQ4zĉ?;nHCf׳UV]#yVy>GF@@C@ ]hѢ<aoț7oZj.Et_$48dvEL"7x'&@ AeC"Z<@@@@ w68Qx*o˩S䮻0dAK$@yyr@@@roO>QmԩҺukTХKYtiXz13HFxfDժUo߾Ρ7#F ӧ3{V\{^8h~Ç73; ܃+WSO=%u1;,'UX1D _/7n47 b|s6Lj֬iڻy梟9BTDBp?yy\@@@$Fmv;cƌq܎ivΜ9ȣGvYΌ3:nǷ.QK29 ,ꪫL_|o>g#wyǜ;4i$<]IvƧ'iMCs=+Eślٲ޽u BQ.ouv[gAԲ&ܩSl9G3\>o!@@@r0>|콰ay}B֭[ȑ#f~D>>w}W,YbRزD-t$TRXu 8iܸ[B4н! L.$Ǐ7{PO?ɥ^*˗={xM=Ozui}I3JBC<ҵkW3@t嗛ϜĠY0ivW^>?fcrw :@3B!t&FC;N_ީ]l>~>4 .n-[oewxl1isjuj]PKj]pAӤqYbE},4slt5!大n) xr|    nG>F;[/^{ L(P6l]tu:@B|untp˭*~U'3g?,v]>髯fs{Dn4mC}-hi+GCo]&Nh>|٨gϞf 7^$j2=;vprk֨)e("dE"r9 \5teM   dHA7\݌X7be:t &M2jG  ݻoƺ.4n8yeܹ6,\͋$wqtx7Dǎӽ"gx!ҥK͠Ir ߡ.?I."ΎA{'+O`tG}4dA$[^4ݜZ8u1>}v6M.]L6y'lqH=Uq=Pl(7{95@z6/l8r1cO"  3f˝kx4&dɒ7'99Kv,{|]K-[4InR#uwggwfK.1uw%Sf~ܥOD+t܎&qfΜi;qℳf,q}&w$E6Z_}͛;׎;LZGAhС =f?zUDПAArn% yH@yyT@@@@4er@wtȁV9ʌ>#   Dݏ"z*b@ Ae!LW?d    hѺT@@@@@#C`      tG@@@@@i *     @`!gG@@@LM:^ s9Gڷo/?~<J?ˤ$=z4n8-k6+Wʰaä^z x :x     ޽[qhSd2a)YV{b}fyvA`qze_wu>ܹsw*6[=2 (8I\<큭=3 <شuێ6  @f Ϧ 6v[(o4ڃE@@@o0,SB/ZH5k&ӦM3ܷ6nh>;a.kdIJJ̷K.mVx׿;{w.w]g:hœQ=_}yBʕ3謆+c}Va˖-RJXg_~1xY]vmM6Φ8Dgv}5L2X4NcVyM1 h7g4?Wʨ #   @}=Y[\Rt k[G;t9 !4TR&7o6wy^2M4 ;>_.7׿5yezځ6=\!2 z&=;zݶ.sftSNy @֏J!@`Coø #aq?7    Iv,>|조ay-Y;Ϸn*G1k&.$|d–':h%v!*U !aQNҺGgF١uЬpw$S۬*3 4{8JҵkW_n>Z Mcph?e,{H]Bf\T(Z8uR ]@~F:c攈   9T@7:?~twYf> h\7{Qy衇vڲ~z3V24)S/:tX;}fRFDVyvp$4ҸqcffStA:pz-s @u Ȟ@@@@.жm[q7_]NYti vێzwbSN~ ]zIêU> %n߶mه/Mv\QǬ*oAߠAѥ~iez- /ښ,$o{^Yi[PDv3Ȯ# :?ʼ[/M1!=\#@`yӖ1?IЧ $D@@@ lD:tH."Mu&|2M6ŋ%\bAP]VLb^q[~gtWW`ٳMj҇%9o]&N,[XY3Vv<׳"EȱcB-4b„ =t~ Kd؂IY  M{.8OVv84[kWIlv-=瞰B9Ad菱n̢Dt"hA@@@%3l8zh %J0,uA&Md6ЁݻO?$AK1Lƍ_~YΝk chy~;0o߻w/_k:pkOSkyo<yoz3LpzϞ=f$ӧaҥ6'lh!Z\O-jt{j**^>'RV~jhr;"BcG8=1   @|n3fG֗a">}%K:ߜd/!oW_}K-[48pq7vMwvrJgǏ;LsCqY2e+]),}#Fx̞=qYw#g۷;2P#<.\yM;#ûOb}e˖yy$%%yY{`xݙ"+Vx׵А25?Bz] b}wmnvl߾n. >ܤUT}$4;!L3G#붾Q歳]:w,7GVLZjwȴ~&*W,wu9v:l ,^=#'Nk 9?i9z;~JN<)gqp|ru\Μ>#ErHaGpYEܸSĩrtQ9u;Ph.G"JԐv($?͒Wt5     tIκF~^o)Z|bjR9v;czΙ3rzQ/)l?.O޽ qΜSn|7'3rT; R I9z쌜qsw-k{XV(ȩc[d)P{[|rF9y|:>dJ)]R)Y_@~9G_)*< ЛtA*]Q_Q_ R""*RH H rﲻMvl9ϳ{Os^6{ϜĵHKc%*zQT<?Z\/Hr՛C=<Ne_QdSHGAB@! B@`wBBBЦMp {)枇UwO?>vUfg!oԻwozOwƺuU-5oh">(̙իW+EݝTbv=ڬgc͞=/jpC낂$$$੧_m/]H`&{uy|'xT|ڶmK37b޼yx70au/mu\RO! *-eKp1 v¸}-,Y9Yj;/7 ?B /^Dͫ0-̟+];/:%<Т{OrSH.)O9#-Ù\9b(iȤzg'gz"(V .6nnT'~~>T'$$ "P򂧧q?x+tCu0ٰT 8!7KduU,DЪE$ΜGZZO‚l4j~;\݊ )AfѝI)VӑB@! 5/T_;'0~x,XwZ7.4z PZ5?ns1DGG+Öd؛gK2/׼KyaÆ v}˹B6p@Ңt OYsؾO;~ATJ> =gL eѝ<%/}}iW ˀ˘:LZd):wjY4Bؿ3(6D;NtGNlq737RJ#/ AHQ^NB@! B$ {}٫K6jm(icMio}-mNgyGŋmz}-IB: a9&E`L﬿0oÇHwNR9,ٵɴ";!PzA©8 Tч;""v>YNxq(E&(uhܤ" ! B@! @$PuNNY{{WjmdicMio}-m؅x8~8lقnݺ:z?n&^3\!P#+$CxYйS[GsbW> Y/ y<<ѵ :wsDf]Շq", BD("?!h׾']dձTB@! B@S&.ȴk4]]]q=lPCjj*&MTkDUMBJ Zo?4kZ74ĕO]PȊ-G}rhtƑJ1הiR 9|8̸}= õ G! B@!P!oUҥKѷo_1w6:te9|P46LR҂mڴɼZO:ez)ǎF܉p4zP "gq|eEFӨhҴ1pdB@! B@{ [3g7T'N(wgG*C=={?/wƴi{!44o-o3St%D\s5HHH(b3/,ݴiS}C=cE{:! @# 1 :ϯ:xKlʚVc{p<0RRqf&@h hƑ ΨW"v@m*IґB@! u&Oꄅgw؁ݻ ?Yf+W|#Gꥥ)ˈ-[- j*v̘1J糥C^ԥ^ƲX]{ʍ>e_y8.=C3 Eo}5i(B@J$뻢tě]SD9CYS8ֆq8߷IIQPSː}ፆ۷) 2最(4jr4l)JpeB@! B0_ G0c tY4jKiX`"n222s,ƍ… ‚z҃ZuY z>Ϗᥗ^R,շwdTżxnrObbyɵ8Ņ<ԷvaMՕ_?7 D<<4DpHB@Sei&J˂ձ:Cj*%9SocZT4h:U%qhШ S[~2dvB@! BvbNMff~SN8F)wJYYY ̛7_|vܩ}[IٳgQ^=c5)raɓ'UlYՒ9ѱcGeyfbu?t&&%[Xk[[w %wZ #b4vPC>('5./L|\"TLQCǠgNp=hz-S(60Z1,?~Ƕd5Z! B@N-8F;Xf)Rd%%%%GE-1X`)ǫ@Kŕ׸qc읫AVռ]\ 4Ȥ7)~Wޮ:bO*ߕ]Pۭ#O0t -@# ۓk= *#+7QVD#8}}ǩQI酈mдygZ6MHGB@! B@2<>#vmJ~wnذ111&C QPqy׿^8sTTjUo\ :UTT+Hcǎ5 ͞7t(]cmH[RtOeis;lP2IpuO'$"DظL*O?icҩ\!P+ҡVF )! ;s&S) k<85oؼu7~5hKeѬyk4f%;&! B@!`v|r8q?/^lhC̙3b}iʔ)8|AϜ9+Vp[Vrׯ_J{30?VǼ{=ꮻR\1s?6呣˳tdCٖTem7lWX%=}D^UDǒ!@' J eB𮕆 ԧx:ΝGAn Crrܼ}sIlܰ E8;BŠELWxxT$g! B@! HSvvIl___fiXd  ɓ'c̘1ؾ};x=bbLg|[[wGFF?K.2c֬Ys}I…  /AyN&pgW ͛XiϣgϞMeaaa~KHc;^9z;kGfYg9+Kб#95?)K*m*1W:F:6cnuȸm_j>6uJ_mևk#^[3mW~ܷJNJB@! B@bW{5~/-Rk䟿Či7*̙%''b.3f0޽{z>QjTkd߯ݻWպt>,>'Nh6}ȷtvC-[j;z; |b\weSe͋EMJZjjFuO۵kG}6On/*ysՎ9M0AW8 5]ZmS`mZ܋jߡwq$! j>tăAJCxׂ:thܥ]@R!2;>L7]ኋkaZQ:]ݢ=YDtG4 B@! 5|{-ZyW=_ߣ,X_]ajӦ }Yr-|B`?3iӦ{ O>,bҤI*'H)XvO6 zVZqUnؼy][Z9/777* )н{w)k{[ >O>ʚ%::jq0Քm Ѹ?}K(]kG(nTX :򃪏Q?s.$! > .AjIˑ+I?Q]X@lB@! B@T\܀xx6mkzS.VzB@M\Cowm蚰KVF^Q8> ǏC^IğލBpuSN|Cht5#PacPLzZ ! B@! B@AwEP#?;[V %DѽHL:8 ggrDѹGWA&iLB@! B@! ҡ=q6J U0L۳gΞAVV&N E38 ?I+ =YBtB *XAA݌'7N=*&e B@! B@! UJwEPctcPQEE8GfV!__# nEaAs ?HѰq{Dԏ9pz~5z-ipuˆQ/Azr"B@! B@! ҡjj@"]"99HI>#Lb.̍RER xz7DXPw>.hܸ1#cŲ n8XY<<|j!B@! B@! @M&뻢tOW9e9%̈́Ep>)t%RKKލ?!\ ROP6aeKB@! B@! j+J~"?G( HKK%+H;;/bED-O`ؕ''WdGnxg8c&dxI]|)+<=5x{ȍp|||;YQ..nps;}I!I! B@#ﻖBBBЦMp {ɢc9r?ϟ]vYMy<\6կiWwwwcǎE֭kdB@ 8(쾥5?5̠&Xf92 gV"7; Uz^k/ OsFz KB@! (~dIw^[ǗG|)mtԥKV<'O Eiula5uT<3=z4/^\)ׯ i,}}W;LG( `SݿވlW^nnmP9N:R@IDATrriN ;I94dfqF!-'t&Tu"Rr#/y.aS}\xBU]jegxHyQm (S8I B@dIKލ܋'z;$/7nEse 4bWE)HCs3)4իÇ&ſ\}r܁'NEJA֜Qρ7nLV#LJ`J첔GF׏w} bϞ=iݻ7]m~~6lӧOM6)rֹ2˪yfzKsu\ꫯƚ5kԐ>ch,'B@J&bP7\ ! @ lG@ dp`WP]H~cK`Pbq~6OŶ 湗ͼ%??wR$$/#(eϻ8p׫_,+"wQ#Vd*KST?VީmFoA\]k {a6Mvԇ3޴^USH'R8\E bٳй h٦?WܥޛB@!P̙3o*ĉ-vӧ>C=T EkvΏ1~`ϋxW_}DߎE)߯=I{.~7jJ)cO?Ŕ)S,ےo Qb"#TVfOTcǎŜ9s|Y2뮻N): tҴiS%̙3^UW6쑣BKvi D,C⟝ .HwTuby6剳+B{ # i7bvv'Kh Wt aʫnғB@! L ;Msɓ'+9aa֜;v@? bЬY3\s5Xrzaȑ#zlm-[*`ժU1cA7oױv@C5Wz<`EIFiL0c.vKV0Ne3oV}ݸꪫƸoVY}0k[~_bV%8n=p_C-JrʹB8(*N 9P 2T! .,ٵv'K[wCMS\E~Y[|Wë>p!oz;B4 <)~9"=FM&FFHT! "ӏ<f̘Ν;y1R?~<,X`HU===#θq;#VXBOlVZH[=Q1'Ν;.Փu^X7OekKߓJw"Do;d<VǨ3>*[ na,ҸYi2$krli[u XKc:?;꜉T'}[! ,F,If`7P}\E~7Rή7bZBA!(8 )缐Vchݶ/_ Jb^u'! Bx뭷NjqnVԕ+e`޼y/T +ƍ{ h׮qRNdxϟ?_"nqs`M׳pXVyYߓO?4~akXbϮBV<\Uj%>^JK)MFUa2 5 'JҏJeB@! mBBBȵ+SNȮ8;rH\?d=[߂.v`ɂ'pj% ! Bj 5EwyD`}4gϞUNҳJ=&%%GUVLR|| Tlwf r5B8o_ Λu]Ǡغu;PetUb֠A7wlM`rM25/A$! @eK&*B@2lVްaRgŻ؊zZ6l"p( 3ovght< ^ʔB! B@T&+w>}{n+{sÆ 1鞭֬Yc؝*)((`mV1L] 2*СCؘcJr-*^/7ӞysjjҤIxꩧT^mݺuB튊0|zwΒҡ|ؠt.8tiuJ.5O?Lj {5(؝+rgz?]\qh>mzq{=ӂ-,3nK#G#/[u{dQyJlIu^*xXIʌYf( c?\pҒ KKKS?UQW^y%7ovw)ˇRQHe޺Xf㏫x/~cFFFuJ?Hx衇oYZ=zR5+%3f(KN+Pnxws`gVNuDaa! /~W_)gGW_!<<\3d'Drr2vڥHRJLLTq]:(-[r{m,G1(q f\Ts0gC;v(Lbڵ` {bԨQJ1q-f~pB7{9/ҫzKVӆ<ƚNOy\Q΄-KmÄ/m7A"B@!PӧqQz!oHKwoҒP^:wm $wGot'B'gk0/5׼' 'N@6mϖ1‡w7mc|򉊉 dʂ~Ӏڴi[Շ0jJɑ\ׯ_$/l\hk׮%20ok^n-V%M4Ql:7^㊅*֬LbCbfÇ+[B)::Z~羛 /^Y'~ŊE5[B ^4~RZEP-ثSG(.E`ٲQ'c KנsבIB@! $8fŃ%nc-52/ҡDZj* :T| 4o?/oJ}rB@E:uv@o*vlW!/"2S!$4\/݄+ S݂#B@! @ '7mڄD/~+J >#}U~gΜ$ff{V~?ceflxM%oTuRO! j7/bU۸8}Kfha:t/ Af'B@Z@``Gk֬1qsU &SB@T G_C%=|9t9r$֯_cǎU\?--M8p *yzޮ?e_ʅB`@~Fطo|#;$ғw#q3tb84ZwLB@!P֭3|rm8rJ` e|%E~m sB@! ={6222pyj㈣Y'C@ñL)Ë%)&&Fe]Pdo}CC9B@!P xxxCKԫ}ߍf;K ,|&~񘲄(**DdzB@! B@! (^ũ"""JX^=wAC D! @"+쭬zvn[?zXJ1ϏXTB@N|miժjO(:ßl5\ӧ#77W7G_YTZ26n۳gOR.5eXji&s={/6olLcb^x؞3znU! Q:TэNJJR=q 秲/-[\\ ! K<==zc(x +q;.W^ŒO FKxdB@! e4nX.o>u=m4СC5/sy||A?d|*oĉ8{ZsW^Qeϑ#GPPP3g`G}ݺuÅ  /bԩ:ONNZz1k%Nx_ѣ&ڶmD{nx9x$'B@ZJ\TK'Ybm7'k8]]]QXX"%7᠘\qyYV[)B@!PSK'H (ZQ.$7tt< N/%7Ԕ98B@pw+tk֬W_f͚ѣ%ݻ1d>}Zof8Ճһ8//'|zIukksń  k2-Iz!GiuiiiP?Ћy $**ʠafMV0XpKVXJ[n%J+bxCl_~;{Æ y#K-G! @y8(sW-]ʦg+ePA2{+ʲ/B@! %;G;Sva5.ۇΤA еMh^R_! xLJOOǮ]СCY&vV{&| {~֬Y%85{}7 |;uwz]zz>[l4lDy`ަu;~_M/ ! ~rû;uyYlAy< T>mhWo;٥O˖-[Gy5˿kUbnE~-\s\kiὼYtڡx#FP̲_z%(~3s*x=#p8mڴQ18~qZ|98es<NYUԩSBt1'886[VfV>>`ԖYYO׮]UZ=khڵ֪X///@!P ҡn7߬zZreo^馛 e74~QTB@!Pc p\%7t9;w| M[Qc&yBzp0]V2p ;v}[VB& Ž{Fdd/y{o֔)Ss='O? m8AE/8ylڴI]=&3w}Wf '_gϞ&m8k)<^X vM~+x 7ܠĘ[;}:tRppVbE|_uu+:j-rc%+8fC\\\ 9U Ӱ5.NY%z7LT>5ӂʣvC[wwu*#EI{.h1m4f)))]VePfxhFJX #7FJ6YdD\\O5@哅U#)x"! g&sԖ|[X;m9 ==jd͠g tB ՞3٥bYnnn&,7E^^jORJ2:h(B@@9ݡ$mlcĢȏ>HY'N55ljo^B@#>ah߾=D&QwZ4Z'1lްwPQJ+! ptTgLyC`pVQ1FX9Ė ̙3[z&-O8٪lIo.Gda־[OW8=DY JR Q<B'R $K`U{{d`B@!Pl7b/%uCLFEհpBho[ޚ@`>{x'0|l@w@Vzs)k}qb+͛ꌕˁƉxlk9'+T֭[w6` Tpe®(ډq>C`ʼZ{lkޏki<7 .fwW_}5(vzt9r!믇n5׷v>|` ׵$\?BkϞ=cnd s\nC8[VN^V׵ƞ +9!>rcyU\aY uof=UMʅ(2Tik& ! BڭZĴcGpݧFѢU_r!?j! J%qMd7^@FZ VZ᯿;9^ }osґ]pꪫ,۔G-[]+8F!cYJ:v\ w vrLÇ`_#/\@%|ܹ*&W$M:{cwڎ;Y+8Q0g[<|ӧOcҩԲeKUO>QJڄ0{DPj#{;wb/ͨMa*9a2.db/G,KU9 GׄU% K! @e]r+R8衆_!/7A!+:w zݭB@$sn5/حη~.ݝWb˂?>(JNJJ2 J fQV?c7wQO/x|ǎ`Ŋ]F3f`m2v].zks\t!6W1bl2_[n8yUV)Em޼y?~ݲ3\eR.).G@n\_Y>XGEMr JaK=U4z?xcWI, l`)m߾]z=c~ʿy~ѣGƩ,um奷KfZ'X+B nm]?i|dbmϴO>zRv3ډc[iPEU?0Q! -fjp.K|y ?-hkZR. hS^#SO=zW-5+Tzp5 т6cƌɓKpaݍ6k-+6i$C]{Nx #vh08P|O}iq[#%quNV;g-99Y'mڴi|y扟rTf=n5]~F WNTŕF4RhdʬCK4rdD#IM6[o$Bn c!ŜFAMظci[nH >|y\s]d>WRNhd7ڵS5J2n2*yUuM ~MnLkל/IE^:rKCu-9&B@zyENi=#APh+n ]ehdB@ZHcvÁ93-*W: U8E/6l2͖aaaf.'N$WТE b;nvCR(3,+Yw;Euj- y;5ص.[?"7ޱE+wǨح_* ۟i@`k=o.ґ-OHdHYi>FX2LOqy[#Ņ M$$$p+ne%+k[&%܈k2rKDzxYjSUy _OeGUEBwe%VnKQ:T.!Q)BΟ? >_k"4h]{܌T i"5]Zbw9EO}Qk}1QiiE~k9S2vCT`c{J}! NwEOeC\#04\ ! +(!؏G#//'FSwBPxx{KQou EYܩ-ZVWP<>Ɩ-[0n8P^+Vm۔`5VP1=͛W+G{X VC! ! @kt[_8&fє ! \;##ٙgu˟ Qdgg\(uNVrsU^`ð7RрHB@*#A94uhҤ Zl|79xIGB@! ҡ# ! p=8G1N'O'B4S ?7R<зHGC! B@! .G_e,JGf'cB@!Pa % puah8O{?\wDTO! B@! "\E! B@r`!!uQQY9#J80_///̸-8q< K똟ׯ+x|Z!PҡqB@!P# lUn`wdDxJW/{|+Qػ{rs3keB@! "pk+VZUVCٳQPP_~e$%%];.\gϪ᪫Rq7Lڞ?o!oΝGbb"~W=;ڶm ŋ1uT >>>zl1DGGu["ڵ >(>,.g%̢Eyu]#8tZj%k.\ !P}}W~_?OPF(BfaϮ HMME ؇vYz (77WH<~ p!q LA>K9[\mad;ZLXr!56lP)lbUIOӗ,Y~Ie/&;>LYN_ofn:pV̙3Ǥ|Jl3(ŋdVVBe۷]tQ={(yGbСضmAib^u]XHBr\ξm-J[(ղ:P22! A}سw?4dǹ3>HDddsD\pwdIA! 4inF|ݻ7^y\{Ѿ}{_~)U^˗//iF6X 7{.bbbK 'K2J+W|_p< kV!VX`OFRW!P߄ʐ]2dK[ePB@! pp-[ 7^`9a"! 3])˘X`o|V2,5@3Wn)͝;E3fby\p[{ T,Y:+'OVJ+WcS~A׶Wː{BCݽ2s! B v;&ͺѲeKx{{Rnf=BsLVG1glmذ =shIL:t0"p~hР}ozSN7oQK쾆ws@z`;zb&]Ay4jHgeo}Q9>dP,]}Uy#FݻMβ_z%~},*TFxwVEΘ1> {EVvV+Z)0`*Yvesg ¼%&O(3x p hNxJ`.ރx3k! @'@%1PױtB@[LWhߚ>5L:/i>|XxڊiG l)uFڙ3gdh!d(h]{4 _^#Ń"g9 @ZJJ/9ydzw^b(CDdy;hM4hǼ ! p4YYYjcDDڂϪ!jZ!NC>4Rq [OMC#OFvpuשúP>| 70g[n[+.2eh_"5YNBw18q"{==ۮիM'|Ж۪U+"A9;;v-~g2XѬY3쾇ӹs@ <)) 0I)(e;+uz)BDY3̜9D,} >#[jLaRK;܎?yyy N)``:*q1n&˰aJԱ5ǢW=mey9=v {cO]Hky9B@\&߷ 'B@!P Bٳ_}-zCV i.> jB :jafX` ?W|mPv !P /j[6+n0V8pɓ"7'di})..J7nܨ*yYaK4rl1V8XC"`Ce&rM & ''GeJQ+|#+,8;-u^dʥ$/۰ [ؒ8*peǺt#+Q)sҷ(ju ! B_>FoÓ~DN? ɵ o=7?}2^A~3/xDBrЕl`Kׯ7{u޻woC^Y'좧IwĻ͓nV$K+ɖS駟Vf[!pbWK?p5'[2\w۶m|Pnԉ讨 dgK7nl:\֥{/F%q@IDATJqUV! #x+=ga^8 2ىH>y9߰ Z1o:H)@ %uxў- R,+UЏ?\2Qj̟?<;w6a5W"DGGSsPܞxw6[A+ l[55+ϕUš5kLYm-X-,Gw7n.\_cƌW_X5v:b\uK;>lI{nVkI^c.]g1)MFie!`9uŷrQiu*,bR$%T <}Xx J"N'm%o/VkAF B@!P x{{+! va5Fɳ[@4o/d27BB wQmյ[]uŲ@YQlHJB齷d&3sIadw}~o9b.] \E;Z6jk׮]XT9֭;ptk.U=nܸvTkN.XmѴ%XhdJz`l-U`v2:61xg)]&v񎕒ڲ2'&L8^SU痵1vvjwލ{ 6͜zSO[omӞcTG95L<^Ldg{Q#q`I;A # ]ԝ ;uI?A@A@p>bQQQW$ӆ̏H^:W3("!iiFx:bdF pI"0w\{j/8/ $/\,2^L.h# G=)b~>¿0`N1:@ppp0sߵ /W^Ν;ĊVNe> ,Pw֬Yal}]E:lڴܵ;z^ɼ3ޙHLLlׅS.^XqTGhKE04K<& YٱcOe˖L(኎:p,b 0߶cpD#r|||]'v f)9չ.&F"6Q*5^QʩBx^[vӯ] tMwۙD:Ԋ3a  0,^,ib-y"8|`l!$^)0ZtA@PpN"dlQ wj|m\d(Qǫ睜ŪO$vq \8bu8ՕV:::".Q/j]MEAo|Nފc_Пs}Z1NjCD5/~q#~IvuULg<ٿ 9  8FQ[fX҂%ps+uJHJ4;*d* @U!ot%̩8] ʘ1cY3:C`!m0wA@83N"|f8JoAB"]!.ٿ9  8 ,Ji 'ittLBs-*K7RD&y0)'h N \=zTi1W|[}].tIhhhp@LF~3g޼yJKź O8}WH%_KDBA@AHKK`&gA1wJ c}."SuRXĝPt@ձddd੧Rھ5k~'z? 8D:vt@ ŎwtؿٿLYA@A@Pp믿lQ9 d,w,M @b(EBvWW (9GuVvm AYIT֒%K ^ Rsa .HLLTꏳ͇D)p  Nwtpگι)ʝs]  ) B;YYY*f΃͇I "A!1J:1y$b8)V    p^pH"PVQo//5΋͝"88R:G66qHR¤M8J.%Hd YE3{BCknͫQVn{#37cˆO; Ð{z,EA@pBz^H/ypСꙮorݺu?{) pnHsSϱiSn{9m/ A޽1fHMl6d)=ϵu}iBGq}eŚ]טp xUBK7>x?  p`èFR0TE~A \\ijӥF:ubAbi-4V! \G"!i8+KsX-k"of3B)SƍÆ;QG}΍TV <:^^W2λZZ \S[m p ndʃ>CC+,`ٽ3H-}> m?Bi@6[a۸ے {GN$vCSYyaAbDZh <+ KP+E:HA@s0ydC܀ښ,_BEٟlX)!6~rs/x2g (a9J9;I[A@G@H;yD#6&ڱ_2O< 9y;ϩl",Z(Z3cPP7Ëը0QFن,->U)`H-{U[rM@T+Ix! $PѶy7K67….JvC7}"Tp+.D`B)`0%{ <#0y]\L-=b"pyIF\qnRS#IK2,lE@켸8n\ExP$Ep_" wXW/>w0m'3xUO 3c 84"h(QBk*3 CWepA@KE tD&**h"TE{}m*ۂ gW:s zF\ >@+f‚ $ 0öZ4ѻ72۪Qi63^Y2? pٶ)cMr6SZ!뷫p:*`d1t?Gޱ-gviknîhh\..#7i4XH38o"B +P'Q34b ȝ"%Z+HKAGڪvhv}Bdĉp7:tc?>u  phjjRiXZYȆDDdSC"WZ`+ك2-C  \/ҙ@QSS5N x3ߙ8,@WE7\]"%N0 "CqgЈoVy۶u޷БQF}~%\}\8@#٭uD&Pd^k^3ё:%\]bx #U5G?1_ kPJi( 6=QAf {Q܄zS* `\V ʂJMvNBii̎!P}+*zM()(CES4BOGQ#p!fŶ]whrz%Fxzo=h PC>}HAA&o%Zzn&f)wp?XcfzXUHLRaqC-EA@DNrs2PUmDQw#pE㏕-1PŋwڥǏ?ׯ_ǦYK!.SnOjfv $&C |)z+E(aY?F|PKBGAY7`gA*sy6YhuGEc3LD~xفˇÜ yW! # !d`[lWzFr$>7zjK6wD&' 2!Xxˮ%? 9Dw^{5|>}:__=}Y({BGAyWcٲe0R Fe?OZΙ8:c2dgu&Wnvx0w\{JG#<~Zxc҂?0F5k`Сm˶ B:\j\3hg`/P7 ^bC *264b0u+Diht= ,Q<[ ,n2æ%q[ȀE36{C;:oj#`uHyV,ޞZBuБaVղ)UG(mn@ iOCp=:#::ZXUpT B*uF|<PK\"Z(J"l(I`^cH\$)\[ύOpz%=iOXuTbpHw[DF-ό+GΞRGʑ#Gcǎv?cQo:"u˖FƇ #z4æLnׅoMSNNʊPOލtTZb h6UE co2%4} -v %h yW:!4;/"7 3+aЌ*$(X畬()ź%?R4 E0v{ɟ@]E%%7̗f/t^'"S@:`bAOܧtvA@Nn;Ru6"#e͛7|T&Z 4f4` H:sǤfG{DA@KΌ.&ِ6TNC8R_+<EkZ}wzX'KG̯OuV:ڵdzw9+?1m_0\sUGGl#giB:88sa-@&6E% %Hr@YQtu^1RkƝH8# :⇎D%&X a f2h t _$Uq#^FipDD41 rw `_"02A@ΌaG40pe~>6̪cT (@-ܢ416ng'xF=/t=zf!lNVgjwCC13c?ԑv cH 8{7֙&yr9g=^j+: 㮘,ܧmC߾}O{PI텛罇MV#<8B`~,WC|lǍot'OcG0\seåuxcݖRm;G)jHI. ҴP!Ə`? k?}zJb AGG8V加8DD # @PYYJԑt`b X4}*]O߶oWff۰a1_W^и85f"'{dɴ?6<^]m)8$Jluxː~ EH.r4 ;kػi|#y7KE>s sf;BF^`"$m)B~u%91`ud΂C>^;Q#T C"!! V9n*y}^dh-{VX|Bs QSP3&H+W*;"6Pjy%uK鰒źuQ!bkmjx*,vAG)j/`SwtϞ=oٺ-^nQG-$<}T&Sgq?f]CŋX7ń[E칤Q>@́OYXz!xFӴ1!|\p'm5t_w76{oh[L=ʁ'O!6R v$"[au}Zxn|ڻN'? (jc9қ0QNk:fbA_\1+ǝ[ߜ|rx λ 8 ܻw (^|>lG=R9a@@z-)W 06nC2]6JTgJ3rq9Jrq@`v0Y$~.Ѣxqzml;ݿk.-5ϝ322hѢ-űÚK%E =3{KÙc(#N@~}אNYP«*L4d"]yFm)S~tjU7|]e%<y"šC0Q1NDӶpB&<(-6wJdוRz)+h}Mni%t]d FO 5Q6 5gt Z(2EC7XO}233}Iݓ瞖wk^4U`oIEEȋ΃~xH7TvLhAsMZ"wѰc0j(p+V+N#ڝ7ѧF?"ZbND:}v%u'aᄈG$F 0<מp`g8e۷8̈́ 1t Hu>'Bkxb߆$ _zִ\Dܬ4v oHD?H _|CGs؋ nqL\q߲hϡ-Bw`&vvl\l1'#| Ep={Z}5aՎp}[\œoQYG|UvQ=䚨zA@gEZRi۾w}t϶K4|iDŽD11 $l۶MmsV:Gkg~k{6iDC3fbfz[oߔӻヒ7|6m:|+)`9 $H={ռ^) p#ӕ_PdH!_vƑ<}͑AG8% w f!ť6җ`{"ph)(=fj\az-zج†;}C@ٶq^;>,;M9sMp+\Nj:}z!fRkϡ-f6Tn"+I4~H.|,7:sÍ?봱Hj];|ZZۙ.ZmJkD w?5.1DX! ۾vdTE!EO*m UAhޠFG~©R>2.h1w$Eɔhi^Q>=-#\"=!( =Z]9i(tF>i^`|~4a+Au/>XKll"SF:Zw W{I%񑎾\MNŎcp ݣUTje/:#pFRA#$W]u,&<<a/FُP=ط/~,hnEQrTU(2B刂 -~O?u ;V z衇S];Xo1xG/i^x/Q|o~ erTƩ/++1 ZhOQZa筤$=??_z.pܵHHW^y ,P/o8VwwN5t> L ݧR)u_(]h:tF> i# No.;sy/guZToٍO?Jޑ^;s<=ѭdƅ\ٸ|^Ksīa#({+)d90mܸQ=aNw$CS@)Cȑ#1RRR|EGGQsuَnݺ`0xX8NbswV7Z;Ag埫8}Ν;!Ř_sulX?fٺuᾜ6oc2I;85>wL@)2Dp݅+}f.[PJ>A@pwW)0BF%6ùDD4xBF"&wĮEDĴEF%" \pׁj`#9ڹ}s=SӅgg̘eb|]{|?={lsskێOe}j9[>%|xn|/ߏQ1?UuˤA$tpq>_ťv &I۶u/?㣰T@G:ӟ\ח .h2[H "e$W$ϙernq/|R*}r>P CAѕ?M*f=7TST~LyBN&79ډ#٘0ݷo"MA}&摶  ([h.Lq)>?+WTi>,, HWW#$'"]֦TKXj'NH)߼zJ4PdZ(+I!DD82EA@A@FB:8ٿd2"y7_zU@yFIyCT\ 0LqÇ1l0E<|*w[y50z"[#w) еLDDFF*PրaB˴iӈaҥ07CufTm6ZދD!"4@]A@A@8ݾ+)̋)/O6:tuuuJ/'wqQ6]f\$[<6啘཈D˒ 8ŋ+ҁ+CߜlT|%;C77&󊣽l@D!82S@EsΜ9K(Œ-jTm""I!VbinS]Hy=N4A@A@nҡ|LKy-)/"zGatT2=|m#iH,¿-#/ !H[ncyX+Hb=.HM,] &U`$"@-BWUoaZV:C*pjnݺ#8"ӱŵ^Ɔ,q9ݬ4WR4w FhXv#" /bG_0\sQ'  @WGB:toiٿ.e#ç%Ո M+=u 6S'_ MH` S$k6zI@A ??_CQҍt%T͂JSm]]EtU pbd"d2˕ Ô)SHȺk׮ %[)"DDt "|}C0;I_>pw'ZsO   p1 ]!.o)ٿjn!#Z}S#*+h4WZ`q0m?]aM\WĐԙ7WJ~)yw`o_zho0z6 3Ǎvy$Ak  \d֪ yoR 977AA@H&"0 6mR1~xfbpԘҜj{+7 n-z,swtGl  ]g Е]8wMCػw/ACp֚[,LMmPVQBjs}#,҂Rs󄿛 + 1)RT{[bG~v$g2līc ե";Mՙ)H#"Z7-'bLiȃ6(QJˏl9ٽm9]C&ax\U؜;LĈsŢ=;Tݜu@eus0<"[o@".8b$E!,"E ^SqGa%kUclkV7]|GNq?k$O1LNrd@W@O>ի}`_"65$ތ݃{%IꥮpRei uONN.0㣪M-06Yh=^n?T״(t"`^_Btlw뇈ɠJA@A@A,! g Hg/>caB<WY?<3b[Gi(,؄&J@^f[ [@ ܄Fx[uspyHU ',`c!12{~s56d[MnԩmcL]m0"8tU``DB WYbEOtzP^qO_xzy/wzy>kE?dk+s+én;']6\@X~:b;qٍ3Og[G.~i߾}8z(̔f)gPZF8y>3Ir&(G w2 BCC55K%kQW~A@^EA$fmm7("""&z?HuNAA@A@8{ r_EO4qYfa fOwT55&ADp)P@QJosAҊs1>7F'*-ͨ+Ƕ^5G0{X9oZۏnBk|jڵ[g=6̾00,dJ,@)(uh  .:Б)߇R >^'mgSũZU&'/fzp!O{{yyy@I=l? z7jL𥈉#%گ+279ӮXWjv4?6Fq~DO[(';+) *j^b՝O: $ұ^.rrrHňEh6U""n& ^jIIIHBQUY,nߑvx{""b`2!F   LLg_'=B9Y7#ؘ X7}b_ۈTw#/O؂2v~L&!B_ߊ 0Pá D9`]mB$8\Wzw; oһ=L0ZTEaadTF|):!Q0ˮ"L>}#U[&3~g|xQX>%1fu"UvÇUQ4ٕ pgLGN|xx3~L^Fxk,~" r ]+yenC_(uS:;FPA)1@IDATZnoh.nHYX#[p=wQB9 Ѕ`Crѣ~zAWP a퓈^݋x~gZ.MNDEZ٬ ~@]h0aE6 -m7jQRՕGMUtE;  g'DB~;ӱ) V]KBTǡO&=%ba!yd戈?=%S#xHYEcCY61 \j\qU7(Q@ng%*"%'VgbhҶ<q/"8|>//"#./ w$@eEAT[jQ JutEu`ZXF3iB&K"EN}|`6VI>QK~v2ӎQ`` nȩ*EXp& BM,mh,CRH"m:~L4j(ՁQ}7 K‰jڀ鸧HLQ-f(̱0$0j-*Q\Y_ /@σu% !3c"4x~Fٞz_ a1 CѥG`P8QdU!򶡺PQ FdkJ&7-"  mwvݳ}O4N.!1QӡR {3f*eimԴ1÷`ݎh`3J޺s36bUB0PDVE1^#݇kFLx%]R]Jc=ailRi8?hsn̵ p#͋ cGY.N"1긜$::6lP?`\=HVT7VaSQ̛0>*I+&JJJ1# e:xxPc٘_X"C#eSu!ꌽ+1]!-:l0PnQ\݄/) pҥKUe<ELCE9*d p`+ |Lɚl()CPX( .po# İذ}+vUR+̺b:$F,Zn)*I7:>uNkb!Ϟ1qJ+&,+=tt~4RTp7=X)`LhdY p㿬*܀+0g\_~:ն>,~?*bc̫͑=(*-APx{=eZi\7[qG CdL`;>ܷvmC'@JE%# $йTq6RnJr某Iԋ=@ƍ}`=)EA@: `00x`Uk%3.|/ĺbETHZ 3yBtƊ#%L||)S?@5EB EJA@A`#͛U6Opi-9TCG׭[C-hj[79!R&#IHk&gzϞl Y~&e(EHWPQS= cP_\s֬Z O:Ay5}ճ1e=B髴N,ܭA7cLFQ=k)BCC_SZJe547=\Gࣾw:wxX)\Y3c_#c##?d Q]a!CT[,(ވ2aM1XS# ",(r"Raa"HԱp0QR_]8F;uBP`H|l/0-ib|QHFڍf6$q:RS/%%%/%VEw{papǎr&a!E=0a2Z`ߋDGw*ۉݵ wEJT *z/DV$D8iBD}|  6roܸQ{ ռJ2rwκC gOiul{Gl#locbޗ2p]ee<[h*qdCyY"L"VQ˫(Yq,u:!)hg=tҞ7:~uJ8tq(8 ibg^dTČm`z$\I䃖c0ն$b~uV`Y(ݺ %pl5Ԣq1*#٢0?ҡlvd֖%z#r s{U?Ss}H7&C8U#4Kޭ@)In-;k2iPTIDz!t&'/w(sHݎ5YCu,kZ#msk7tm-$B磆n&G`qHaZC$]ӓr_ 4K,݄òH}.tKaAX) t߃0%&&F!P{drIFCtw ,mjٮ^<Q=UJTzO%4!C)  pa`P6saÆ)m?la[̾}X9>>^9>F}}20@eصkkrW Hi,)C֭[v\9 RiH18 k֬QV5q"iRNJ+}'M.mxulƍC޽Q39H+gUdMEH[˧83RA!'=x@NտOz]=m:,!6=R۶lş?jn= n,,~ {>}+p&vA".j`JŐމx'.2j3UR箺ךa$"qO KOJLJ"/ֺfM.WYjoPX~f;re &_gΆ/^c-~w"B[==T_H񖹯`OI;$]Ak<Q_lE{X.;o^Fܘ@Nf|qtV=71g&[IoP܄{ڗȘG'^1/LM7q8B;oGE-"-%7zUK͔-+֨o%DwG>S9H3,ZGyP$P|?‡"enE7/~5ku迏ss%BCV.ͦ* =Tr&uw< ^Q{Ti61Hm[vB}p??Yܜ`22A@8sIoA ޻GIk@úI&πy;SILNBDȇ] ۮ|˯Pu( x=z=H踞[Z+( _T"ž\Ru)XDzO׆`{#xz+]H vbcx;5RLXL 2s(.s A({_*PWQ^=oOPDŪ"T)n"HHHPh簪(C3(t*90.鎾^n*"EUc= טN-LL I$n#*Z;_PP\oO#O뛶q+bc,_܁AqE9v֎܃}-\8N֮mߚZ ~pwȝ;[}wـmַ;߿hfQsd> I}MXI|0|ńCل0nԙn\qM`p9E-Fpv~qjp`"|tZNaéT p:(kh ثZ7Q/L$oȻGPRMd؈,zq# 諈"$Z)T# i Fu&^6lP6؞ϰ05bA:thE܎u'4^NǫCjDR#kQQ@|`H&!5Rz,Y>7R׮J^m87=Z wĥ@O$J#'ҺJ4UT֑#8b'\rs/S_?^9iV DF/C]n1H_܊kNW^Oxwby/+h{#_?i'HltooF1V k:/ ~Ah{[ovƛi^>OTcAőiuܗ=8r/L@p 69.Z$AguL0h`9r6&k`X-"kւz҅ ,Ge88đoVt#rhjBpvId5#Gg ?'p%&2r7"ć Jq2RDPvWOnXV^3EDJR(<@ LLPꝌ~u&7;-]BnWLB[lo€>PEtXZӗ ?ԷQxQ}k[I%]۾'^@|iӦ!($ wrwpq;Ak۷v\ׯ[2V/_oo]vrGȮ""|[#L5GZJaslx::={ ̙3U-G!@b ;v '@|g=us\k&MH^quHԙE(+ًv53($ ANLF&k#A@A@ 9 --ME9p"gQ)|HK@nHg({C3G (ۃߘ(h"8~o!{9MzBmh&>S{~?#OeG69!6`gڧS ?SSq aL;W Nc`֬YX`aP'gγKHAҡӘ>smN 2>F=#!#p@:?4wWYb '@ lBH&MMd7aH_B L{,6tMFlClpI77{ޛ7}Ή&]{`a`|5c!LNZ0cu+wlUFFMgfjLAn!LaB ^/IIԈc>7ߟR$5&^ =W_.|X<ُؓar7 ;ߛXӤǂo`.IG凣։-O_SU6;1?,_\~Ǧ.:־Qߞcc~sR(e<"D[S R33iOD9 M^z$P+( Bhz:1/5`@ρ/< E!"bMEqժۉqHqQVq?`jFffϊHḦ!i4F@#u!DQM`k&(tuST%4Ac+*Xu|'\.۩}{ B9 H O"{! bgL|/$Dz|WR`2)Afb 3aTz9iٙaTnd71ٰj+Vu[ohĄGU7ݨ|"ߺOg& 9xGsk 2ҕ$&`UP]]$ʻ[⎙W":0l% H}ǐr=3zq"2220k,]pAk4c_ "QܹsԄu1Ќ3cُ*zK5NH̤'D$_|!2HP4A@\$s9çg~DH#!AI#JyʕB&,_\)AȽxD7éIR.W (I6:iؗ-|c',"*>DH@w5p񎅈R눘|}ΐ6y5-f-wcʈ1H}}=+}wo?GAnfgS;n %";&\yW_6g]4=3ăR0b@C Db6-Җ-[za콷t.LF@#8ȹHQUqvB^w'.=']p2(uw5pH\PܬPyq3Vm~-XŸr.?5"2A{y%֮\Qc uO܉?gfG`t4 ~׃ۄ-s~c9b;G+b-c㻚tD$l.HH!QU.Zjl**Go99 %zͰ&;x~ѕiq}w3/62)%qqqذ{ScoG䝃 m۶qn-A+ ,|!d@7F@#p)TEYMi3h4!Mb6>7]6>;\0)5\Oə&D !0U)i< %5M#q!yl6Ei&DcǎU[-qxK5k }_GCẀehHaǮ]xg`$$ĢF2~mX^D#ųp%96t&)噚dY8[dŷ߄Gv`wSfZIqg:MQQSÐxAi/CGPJqP7SoL#0!ի?X4Ĉz\N}Wj{ECCᢑ?ʌֻq[0~eAcu7"6X?h=zF@#8Wli!S%+spRUJUJ(`kߋO |=vd.Wí ka6K.U^1敖 &`<8@In>GȻ|PrsMMMXnZ6119&466*$\ԯQ纜fWIIIW_w36M!\Ni$`0 `8 !4a r50P@C qhkkلGo#;!C7]/-ɩw3}+x*܂Kl=fǀ!-e /$m;ʋ/luh.,r.A^ ;xu{h*&$kh7~kv8 OR(fCک0t~Cnk^DwS 217;γ:h4IH)++S! NpduHLQf|vVٌnVy('!/>/5INE,4^wVI4 ǁ.J y`y'z%sv3N!ܤ* 9WV8+8=AIDF+W-e1aիתiV˖-S+KD,\P]g8p@Mҡ@B,i!."-kaEYawx^"2x-66FW*ӦNDYAJTM.<׍1ܞ&qQ$TwD5VI4m)9ʰ7-s:ϩ~`]ݓ=[o%H7p:vI*%T*Tax =HM/_ Y#tUL Dz|W燑~PN^2Eێc!%kŦXAGn ?ԟk~ŲBͼ@Aڰ"d ҔٯXϩ r(iÇy卡ԁ_*7,wBϥomBkϢ'?K`˘mGy% Yi] ؘNhlEb,Ju|CJ#\|$('~YݐAs9eeeAnNNNN@ NE}]fDW^ʭtbMU:ż:# v 銘' c<T2!M8LE bTua^W}R,jG.WdļOB[q @*$ȑ#jLx׀Hi&E*Qbg%+BDH7&U/Ry-'-%9qݜrN (VљM䡼< a{**絴bd08V'r.ǘ>r|._\ROE Cg{4pvՐ\qw50H?(.TCL7G0gYqKo o4-|V:w%$T3~ sAON b8@md!k(Qۓn! 7ǎSYe]]T lc|e<}ExnݸsJD -)S`ww|;lCh4KeKPii,u#2MwVӲ1c %$A@iyyy7oU30IL"%Nv8\,3hWA9=*s8ʚdM4 N~L& M63KLPF"d2/vzܧ:UBHAQY:l#'u+J{Ѐu iL4\^Ax%neV~:ޑ}Ø3Dkاb ]fJ̙ؒ3={X뽋դT (AE]*$;^&J*++䦜31-7'Ay7Ho1=hfÑ>42<XKT2)+KUe!=c'k*_>qo8dp*!twj '3V0dq{\F!]M:|; r@;}*#^R)kbIʊ{1yӖ^.x1Y^L(²u/Jfl={9lM.3- -/}H7>wbڗMC\>{tO*兇IY79Ë.V_h4! OQfi:w40n,ob|v䧤@ c;|0j*+RCUsj'U<('ĩƊG)h.7sXH R IPp(;1dsbLXGW2tw{'- ]O %D_IZt.T9qrVqX),z?p[.7{<YO/V`¤ylV\䑌(V_iC= ~kE<z!XE"_% 4p2D 㻚tGCl+Iw<"p!۷OqkMmflU0}\^/ ]]xkt]3wb2A8SƷ>V:Eǡ;dvD&<`Z̟^ZG c$' r`}i |)]=8\p=$(F5HKGn}~ݡ'A|]nb=yj[mǻ e^悬h# qgqcOq#]h :sXpT!igK2Mvb+~vR,7+UhjN 43h=X$LVƯ.G>^"Dv{7`4.wRm [!%sRpѼRu|Sl\.HK/^B.C#NH7pZq#[vPZ,3$؅ۙ Q /*դE="cc~PFJT;x sw_GgC(#;1h8v\;mYO2l٢t<֬YWf,CnCO͝hhmAw8<+?q96~(ӃPW?A0Afl -1 E#GB4t? *<#cmgQ?E ~\K sx?y.0<ɭt݉OwɟF`#6k>1MMMUNBF9QTTR^^1vwOfg&HHˬxi65]e$&)yB 'KNaIԴׇBػ;r+$bh^j&D$Ǔ]?{\VxF8H\uu司W εJd@0t04lYLx|Y q'gB&YiFLhh`7 O\zx ͘㝔b1ȋ?Ѽ3ffzcR8+"XKJ-triLWxnXtu)@FTrH&Vن`U514OV:~E1B\InF@#pvDdM\]]yFf[]4&2z8:[2d+&&!< {i,ZNL@F\Lw0|H% ɱ$D]%PI&\KeB:%\Dmh" $TSmm T&tsNx\:&ZZK[p;#+ 2hxdde#' )j ݏR)'2_R&B.P)СT]دev;E3&s IZ~:,Y9%C\tD(դC8[~P^ȱuG6YdEĮ:+1k '=pV̻Po$@ w7$]>| p&G6aZG0.,i X8R~.y;Gedb;|ƎIK#b<-UVDb`gmh:eKQuzWcwShj,ΰ~E+1鱇[=2D`Ҹ?91m4$&L7F@#xHMWWHHHP %MqQ.b}8Z^ΐuR)a0#>y@G_Br4^VN7a0,9m4r}'^2DE $@IDATE!tf02*G@c p<#Ib@@A 9}|\l$I""* $HS-U`2=wi7I"`bd_Do5jBn'Mk7c/ɨjfKJ-}"+35C$By ʽHIpUɺi>r<9 Sh yhjtu YIeʿ1E HND]ɪx"ζg9sַ!e^HUTcsIɼ!.ύp9bAv %SR@w50H?(x"pݻP~@vhDv0#[U>{L楁n;jZ])fƷ+%%FZͳ0p M7`p,5-Hk~ArD_1we~U9`s"~X!@L^J<.D ]m]K~1q٤9xqeɤ{&;v Y]2atP]ȕk5/CA7Qzբ2SY vDu4F@ȉpJDyyӕp3&9ȬVzKXfkozP8O@X= HMB%|iiHH }\M h'^@<tin.vp'`6ɳxY~O݀ﭜb$Sg1֯fA3rV*DC 7p-'G_TRFg]x33e}D=}7IZ"-g LP3ǭ;`N|QH*+11$;˱z% M.c"tj|^nJd^Ɛf*CfLM#)Q]u- CgG%5i|[^E|:s9yt7O}/*Y*r$\53|ɏEZVfnnnºukbu$ =m=A5p٫m+BB)~h>2դG޵wH?(.ўi1tGᇫFdffHZ@~ChaG2P2 8fQW+r0L 63a HXt?oQ/1hXi71Xѧ5ռd`N^] i3" #G! z''11[3 #a(m*v'I:((cu vr\&gRI RQ "" y$^Hs1QmXKDk7 h9Hx:pI ys^n8]B(X;w?S\5m7NWt5SlkI|T!o$[9!rvR4 a4+^TD "=Ir nFAy>z|a|Qj @G](a11'aOW>y!!zh }vMx[b. ~fu6(bX%Nmw!(d>LFԿ}otL= )v!XO?57jbf%h*7bZ'7}Rf͚\5=3-ZHYf/4!|#Z{Ԛe𴜢e%)K7m+L',$Rx9Dr ?Ey$S/66Nߣ̌T2 2H#I 2hlVRCB~Vtt GXٽkE<-U'S&GIioErx(N"ZU#:['QX`D98f)=87F?`h|h BzJDea4?`9 ]M:,FA9Xpq\afΜ4~r޽>/}J"wεqRi+&w]_v0+KYwtEc<7q,])6x =a8UӰӝ0 M IЫT5ACIw-!̘1/L؆ P%ҫzXvRE^]=|yĉJL$ uqe̹)4O _F"^DI*Bd|$*D>-I t u5@# RFm>aprHTV`} ڛGz!`P&xM'=VU!if%qd1GQ.(&\T>XQ26tl"QCO[1MIIh #e~\\.1DMV+G숁rMTrMf]jQ<焤.NOV4@w5yQKAYM4w`nIAVzҟ/t1f_.Gfj2]tnوl:U7Yn \GDv'$jQKR6zK8Ƀ<58# $.tÜ2V#o z0̪wê^ ,XI#M2D7T2MJ%NTdXQᏨCz"kF2֬]IDu ~,ZxExҠxDQ__vk~]D_LffXY*"f/24j8jGyQ:f͘ 1JM#hZg3cPEȡsW+~pǎcs0qʒ FդC54DA{Ai2 cw{I6 ez5YhaA4f"2͡ReLo$H&"F8Ho9}N<-~(2!|U8'@~A57Ihjd4FT>qGk.4vw)7ߍi#K/E4/h{iIP_Y@4e\_k99q%W1zډqZAQE)6M;q_bp @Ư ͻxfL}?<Ͻ, )jkQ2H- #.@"Ɏʎ2DE:ASH!,\$$dBEZ*D|$M(b71|w0ӱtɵ6 &"j*u|C-: ?POdNB/]6Nk1XE#xg'|.FO v 7T]iA\w\3.OOpv2PiWNuk;x SBger3Mm]aQ 6QH TF^PoC),~$,e!6AS+-08a$а ̧^$B |>N o鲫fǣ|v WS{lgNzmJv9cх`3̲Rѵw ヷ0$x{-yjv0}sJNJwfھO-GWZYVJ? 싥A"wVX`7ϕJ7%4 YIɥx&Iϻp:gjË1uľ<2zV--w3->*:_dEHNj XCOS+Ҿk8|Fc@~/^$ؒ4F@#h4σ[KD\ 9'?@!g"``!bdz,oۥ;($䀋r hXZ$4@ωD[e1ݏQ^ ʶ6tpOGч;x njRB227B ];mvmcǓ" t{@I~c0hB210Kdq$NnN=IIq#*,ߚ&&B# ?1ԉ?}7gZUx7 ¢@)2dCx Tue"7y'$RbSCf8j/]"$u?E;lxG|Xhxh+1`3y.‚d"0޾ݝ6iaߔ֥ΙV1;᧜$RApsQ:(O$:H|E[=ݎ xjCL'4sLg%Be/G2+I(>,8,ߠ.ts>e [ڨiSi>+#>{~ttt`޼y7]|Ӯ${iKzɏt.-fV&|Q@14za L_{LK z |UI)C,0$h%7[qb&$J`8<ټ_.YơI+*KV{@paRJ *BJJ ("i]<ƈ@7rN_QfLр_5"F\H jrVux;[xڄ^iբ9_ GG ~aE*} >aFɈa3He9 [lQ2#;ځjoŊyW1۟@:Y.2bk=E^~n~;ysaB-NkG /U ANo$y%qj`b:"D ]<P 7Z#:X1LIJ>oTg|"z^7 .7R1 鏎|) 7ER0opyxUFď9p s!ɏZH.ܜC ?JI$ .fA;o: I,Yud8qA h|ȯbB4D3pJY򐘑$<;ZժU A&J$1@2!)%v))bamVz wvv*NنEH*Ƨ<h | *e^y ;1t+"h]O U TQSOb#}7ro=@SЂ<&jm ۅ*k2n8 gΜ !x~uuĖ(|1sjڜ9s 7oFuupb!i (;iM2•8J^K";ڬٗaGqb5vݘb ՙ Vb`K|#Uٰa࠿ƻL15hCMn-4^@C y Q!DTV\&d$_E֊'Ca0C IT>YFijKzg@@椡UmXRXshƇ}?ΰJ=c 7 eNg:G) StȲDcƒŨ&N %&R w!tEm۶m;v,՗_Y =x!BQB4rX =`nQ8ɨF@#h4F@#&NFC$5DTʬ;oyY I w-$}#G Ispe&7hX,rv/A&7چک5hGۓ{`tSNUV`Uw:pkƷR0W+aT,?֭CSS(|e]-(DB\ L)>&G!+1Op`d͞T{.Ks3ONEʒtq\=e6O!ڛ7~q>{>eY Fyx;o]1C V#3}G/=Xъz\9G={$X݀1 q ol 7V>T+v9ƒT^۷O&M£D.ez\}x`L/\w!URмa_3"anjWÂk0$$[8vF@#h4F@#8ohAWQ85,3?vrׇgC{#E=HWF1BV:ROo@Ǐf8vxHN,> ӓsNTI\(n`9$6tfî]ĒKw::,qA3mzv0)9O 3+$XH1?oG?# _IZHc4s* =i I(#"y>16NVGD@H {"Jë>,&¨\jڹq#!/ɳg/C+P&A<(Gj% <577ѩH~vGBԮ=ow`Qf;!7/kX8CG0GF@#h4F@#pQФE;7& (}ճM~Xy{zzpW?!(Cp-Y?qDٳ3u{z@˃7vFZ`R0>oe/p.Ht1*&zXu;j6oFM%ȑӦMӅnMDߌu$yhڹQ8I?;$y9X~pƤ$$>R=>uJbฝ36S/HD\B226!BẻNCEE"]V:7P;M7',]DE*<"M 6ج Ұl&%m}F#/r'U1M'A {vZ  JQ/Hzg7g"WI&?ҷM6?{4=|/A'h'7)44{3{WZcw/ !Zyʜo!s֩ߧzШA 8JZ}X~4R:TC R&ӂS&n_&pK~ @*ˎua^z1~vߗNo|'_dž<Dẑz~WMSpHO8V"sHU>-U(w)6bLהTyj*&2G{h4F@#h.txX--X"_BW?UVVB2$x?d_1(-ʏ2& ݺ#Hag9𕹥m0Xv5~]$!j3 x*h%fbP4IIx8H|I?M+K?m똙? c 'ybC_'F)RbQŊ 54!ﱶqZGߴ%K(Y7xCM=|2mmsq|{}ų/""δlx\ח/stHWpe0 9/ilfbpix˶XX(#mƌUo$9npzJ3S{nuʴɓ'Շ1ՈD94aن[SH1~xuѕ!|/ojzb(-779>2A'V\RuA7B+H_OC/lh"ER9>۴5@s'^^;`ݗ@ ͜KKbUŠB89Rr`ooA<+'LA#1`$u2j*x,) ǁWL">eB') yyW,\@nMWӚIl!1d"ɑt 95 ̶3gDOeeG1S}'Ҳ@7evY`n]nY)&^vuQ* KeD֊M W:L ces+ f0Z(c4&a̾" U R!a警PmXY0it:!︠9 6dZ,qѾeEິ4++CH:R&䇫7nGژ8cMߑު7h#^ ]HfeIɔxO߲jmPR싴;P34͉nQˊo:j}kRU#aÆ)! w/d3 {XmyLK0rZ3GHn2F>ftνyvYY2&- ?yɨ]9kT4552D|[.B@! @ 8{|WD>_D_|w{;p'Y*`h>V2y(66y8 gFIażWsPW*=#4i{Ah6Vuyvě0=*fn{r3zVLIs`#$J4 ;n^psq%V\:;A4D dv1U 6iT(0Ͽ@qcKRӍ~0xz$2k!'tXg:n>ܳG|!eKc== _yzʐn/BWWV3J{C'k{;tv&Qv1`XǁTgMB@! B`p4.':FʹzZZ}n7OP㄄U3}ݺu>է>)4/;R0HEکb8|'9VrBm[ngS%;RN+gG[#zlBMTV%EE5TPQ6 H&W|yż1BTYݸm,9Qm+ko.ܬ4dTφ55TV8  n(S RJJ,CH9.'͍0M58b29q.8dM(or[d_!x o+6OL_!+>p&Pqq1*`, fXィ0ʪu j0 l,}&0t,F,LRe2|(c"JF[;)!<(8vD\ Μ*ëcbbjsE ޯR}禗\HV,>Nr .ע C~튙> v݇Hg`Ɨpʈ?`)y! uiJC c`w;Jb|3u^/\Zqm$zs%K%+mOOOu@DxF! B@AG":ӔN2$\VBV91b ]}R^xdGDa)vH;K Ň)N,GꛛPPY{!=:/l KؐhÛnN@_F{@GCea4`a79e$!699YlڷoZǟf{c)sLL#J~ԁMoE/7²-e߾TAߦfPT2 Ri]_B@! =+K6tqEu~An4!p3ąWt{bX޼ zhZ#<0OJ9 B=?/+ܥ~[)JhLnv R= AW Lzm(@z~ڿ?<`ٽnLt3;7 _ FzZ^\Wـz:_ y𭻱XQRR~9VxUm}wgS=ZՓgQU\?  VjU:3XHcNAh< ,ETl/-+׭ǒI٥zgXƷ.XA^N킻C?nY?ЍK,#.ay~!tZhhF}Td{#~#( yw7fDzc)3yB@! B@ 5OW?t8~8O෿yj"}RkeKOA&1 n*G|;pM#Gc$QcGŷg%jIǵM꾎m]w=QP*t%l0•n^.tz{W3FF w+6"X|#Q A!it3g ^[eʇb(L nݥosgWh8"8x58gmt7IJJH~j<7,^BL -p<8* +tAWFݦNؼ6GkPFy pbvd3*Yl*h~!,O†o?{ =!Q y mKf|AhxX\΍-[JVڹ[Nퟕ !M! B@!r;sVD]|ɱrJUԩS:L J<> Y; 4u൝).Ɨ6/pZ 6-Ciyhu?^Rr}h+Dt W"XTUjy"mw2Ӯhل)a#fT&A\]u #06 ILzuy)ω͛7 8w\%<@(e qMB6gf66 (lƿŅWsޏ 2R.s#죱aTSUzMcc>%3A8q8$P*LmAC[ʜ BAX9g:s)7̛q#Q]Xk*#vnRy[h~EiyjX>=.imvB@! B@+&]^ 8uϟ%OK/̣y;j)>^MsIy5c/ ݓsK}t`5!_4J"\# .,)Л`QV[M̮iC;ES Wl2bNd|w5ex<OD'ՠ=/B@|.6̮iW堺* yjmW&ۼ-\&%V̊J@w|\IpuWt7*H}` nTWO<⮾n\jJt.~Sf7+GMݭ|L~][G3(INi)C7>s-= l%qCK'^?y(i8ϽE,>wolGY\=ԓu'dމv.FG%kVlD҇#)TiA԰h,7tO! B@KppyO~LaSCCi>6${poB8D+Oٍze܃_RtY촲Ӭ8\tᛳW_^=rb.yDa zH&\]Ɉ'h&>n/?;Yj=gjN**#e\O.vDDD 99Ys) ++_}Y".0jNկlyR:Y4x~e:;"q獵0HCcw4J7^! B@G": 9-8d7@;յx>:p ]2ћUN%n8>z9^(!/@Ta}*٘9Rh\ˮTUUPF&Դ7ߌrDqs|ཋq4WT?>&/.هؤÊ*2ݘ/O{{{#55Uel?|~#RwM)e.*ZPϪٮ*K>*_[UM܇D]K3 |m-)G_yӕ8̪KJOY' 9ሤo@! B@G@Dw͝~>)t a_ `/jGր 7hը Y 3oޅ #wϔ>k[“gD#_շjܛȑ#8Mu1cƌY%hip{?҂Ww5`u7ue^9 wP8 !Xd}~ў999VoxӜXSd=H,y?.wgZ߀c^=w]e.wl,@6.aW+e0c TTT`׮l#>Fг/eU(bhnmOp/_]! B@AL㻒0'ߥR탏‹iH/Ư ("&<2{]ߠeDB`(>"EE] jmyuo z26LXt*sދn/=C݄w?h>y?<::c|-j PpܰWݏɏNJ&ߋ+p ׎W[,G{>>"o݅O!ɗ0/20_lsɓH#!KE-~ š[{9H?=c m}="$$D2 ̩ B@! %].{ >)qQ_9̴pS LDr(}9#!p(b/y{fi cQOԑQw<#>>^An$vzښswP7,۠Pk?Y~Ko!cƊe~Sn0~j%q|ܹb$RBݍ3K7FMagq&Dyy9<<8Y+Pga$#_neҏC{K :=0:QqK[pfII vޭ}"ZPMM rk07b&aw&ʱnYqB ,pVÖ-[PY%DwƼy[?F݌O5VCЗV`Ν_%B@! B? 8{|WDtngENdTcǖpsP%jAV#H?z[(χQ]/k> {퇾5kZHdr7;o677CCƿ׬EGWQ^߿q%åAAaa*N:G`4hi;/'x.n-+lJXaǎ<"| - 9J3Q7Æ Sf,bpQVϱOꁈHx!M! B@&]{ܐqiB*ç|j];lx&ҀR;> B}! >@?FD]+h[oWၿ9Hm^1~q8qB&of=IFǩ~ I=?;S9o]دc0R&J8q"yx? 6>>.wFu877WQWUUlm ~ }rc̒6Ygpw $7{Ø 4\8Y)8C! B@8! 'ҍ+a7zrIom߇֮2'8d ,!ItWaw ǎEUk#BEIP]Y^OVVZeԄUe6L6(/ew@}%FoQFnF!/ jUbݺu 0{zUiGf<z!$ܰK0 |^piYܿz+ᡱIixrB$ϜFeElv~h;QR+"">\ ׄjnMe!} Go؟>bD`٘x̓K:a0?f؈C)?̞=me$`ϱMA x 3(ĺ'Ʊ#HQq#Zy B@! %]nwʣ;tJh)#PԊ)ЂF*M NNa6~7Јq0')5xxhU5{=MڨV3hrOz+##V6aocdtWQWzJq=O@7oVc5LXt4C[QTaBp|q,|kr9SYؿ3qwwǬ3PQdD̤mhX Sy₆`_i̞}G%B@! wEts:òA|L9F|=TH /byJ"m:NuU"_z?tT(&&GVi*ӭ@VNy'Uw0c + c&8J`?]HMO .9Awn&yyyj~šwVb˂iׁlGN?cpY <===q*B,XO0auЗV >yzuG#B@! @/=+C/morI9n y!H|j@1Rb-E}1B6^w;VOBbPZɳѡ V7EQPP9XWHo ±`h<,R&=f^Ie>`3cdͫ5 s8:] x`@%:\4<6gCÇLo]S Z]r(/cH{Eklef$#b]];"B@!  8{|WD_AOA\tS TTWchkʆ5߂GbxE|CN&@NBCNu7s\֨ _oٲE>ނ *SDV_ކtt?z ږ6$ϟ=Aw~.Ao.;w*?N 9 1SpWL,}As ^Mߵl>k.òepi9rDyH߆B̩-7};:4yؽ򍇮W"] F! B@ aPL+O+-z'PIUxfI֌QnZ4k=|I҄MBIdOe\Rw/\ o7wFLSSNff!L6^fڀN \8?G¢>wtBuG`Sc0v"''/^={(cphxyϦ/W Vq7y@9|o\j^)َ9R 6mBmmz fDʧ[]C3LN2&q?vKwkC4"N /_-,lB@! =+ÀbW>gW>"y fa!zLt"AyS+n555ضmT ' ͞]X©I=0>p":q{Q6^gj~4ibƍJ2xcm1lL=- ݭwIJtg`~.z BU 'f͚>UqƩL$VԽSRP~] `mzx~tx9OA퀞Jlxp9`B@! =+Teg:>y>4PFZ  & j:xil0jꉏXxCB@6~uj壥 fR*8. %!2"BՔzړ'O"--M=AKw{O+n;`߸+" I'*B=ƾ[!o "N¸93FYraaa2e"Xz:q׍PPGX7AVbhno_ic1nbys6LYpssêUzvNLLGRU ]J:̧rtcU h83Ũ!oƗ2!`{c5( ˨7 @! B@ Da Ϊk쳳Ok\?6l6^z˞;R'4֓), 9Td0.ѧcNB@|ݦ=jGN֥pjxwvv6Xtr Oc 5h~G跾m2 {oEFyI?IIIv!ؾtvvPPrjj*`^fD㞱3˂ӊoܓj{f-K_ftͩY`obcꖖ B=6lʸӮ_D@S -f¨_kԯ1⇯w?%B@! B`@prZ][}R^Bo^|Ck;zvsJgR-hΈj{\ ۊPWY\`1G!пtͭp!%vL8N jEu⳯)ZjOV{"Cmk=W zm-bc'\\6Tȳg?'˪b4aJphhGYc-ݽT ?&j!gSvZ`})M.\AA$XVYZϞYz~m]h4M׳]! B@H": Yu}vIyÓ >hthD) Vz\NZoLzi'UH#TT;)p4:h &TXIpAVxZ@& 8&!m:oOr ַi1",t 9دl4Mi=ˠvx8 {zI^5j|`(':ѝH D]sE͵PaQ;qo;ס SG"9*VWUg3P HOOW>s/y=;p}_dG! B@!=+3Κ'g7xrx!p%o}:e"%O) ; hCqmN+Z6;^oB O:&gG|9&2x=ΠQݦNw(ψoЪe5È/D[)cՈ &rwQĹfuV~BE]F5e3VN/9S9޻u T_colhwoXb?r4hv8p=+nCe9N~*GHeRzAJ|6,7#'QUU]wlE/ K.~O߹.ã{B@! BY 8{|WDg97_>)oB"_:vx4XX%6txbۃ7_tA46M(jykhUզ .t8_T 7lBJQNT{#/Ni =8':(Vb匹:.o Τ9Mۡvʎkno 7\}hUG i????" ,@ě@edOFe p!{`#3gpPP}w ȑ#9x}}6񲸣J.jv"(L;wDԼ=! B@!,=+̔g7J86dqK>445dTգVVZPN2""<!!;n$N-Q@ f{at1b GOƄsr/Gl:k{Xt?TǥIi*< N+%š%" ^D~&L|SI+lO&Q^{ "|##="#]|"C ;;:/́ǫllFPPy>111j?Ζ+**7Yru9~1?VUi2yBp]*p!`# m߃mmmXzu.GF\\݋ l%m"<yas?-.B@!p3 8{|WD9\>)tC8;tonnV}IQE5223Ih mc>-S9O#ĉ,1.|IUQDFZ0#ɋJ:3]) z&+6p`7NEWJkɷˑ{Nדٳ[Yf8j<ػc;|||&(@*m$BhBVON^O7;l?5=@QIJ(sX$\!0v|F#6 ',Eu=Y_ɱS `qo,DDFRBu,y|37$d+".0 'N3566d'99Y Biii3kƥx 62atb67Q B3֜zfNDnu,H&B@! n&gp3g'`nG hqQO+d eNR@AoqCXdGz;^(Dw-U)_Q 8W 'JjעXoAńH*dQs #a゚Wܕ]7[gG :nu^j$ZvK[[[q˰D|!q*Z0~XL;_al1޹nD}n$6O 2E {;T(BIIc/ʆ PJkV ,Fpvڅb5' Ά 2ى&ϻhϤ㎿>.4}XIuRx, w읒2%T̟?_ ۶mS4{lxzz"ſdnJk z?lB@! בwEt{'@(K*O'dXm3"y9r3:3vRfJΎ:1Ko hj{H= ܴUJx"݄P7|o" 6rN7bQu .2{q'l^~k}w!ptzJ.{tdv,L+a2MGgϦJԓPfAvLnUUUW+;Nž$}b{X)ͫH̩sJۼ  8~ 4'(8 QpL1]ޔ3 (JSLQ| 88m֬Y`sVù7W }O/O.,N\ȤBnoW۷ [/ݹW^z,?B@!  $]nwC;tVn/!0)'`qSk@-h.+Wln6" - jYjUx-ZLQl=jt.p+aňHo%J  u\OԝL]f322hq2RxN^1xjY.")[YYE ]¢bهD'&@OB'Tk41>zǁcpYG^y\lB@! WL":\%/pI9 "DMmJjj*&ԕ¥z rl7?v$ZqOJU6M`pPӦ!_2% !l?zd 6RpۧOoi?/}bh] "ҌnZ:=kpϜExdJxxޠ3_òy.~QՆ#s$+oK 2WL Q5&4?|ccbJmBzhGC{m@K ߘh%D R `#6kwʕJXUI 2@7o2/@Zy>btھO1!PIxU| \)''>|8Rٵ[k81}u$<-p$FQ B@! WB":\$:$eB@|Fc:N.,FuS3qAJ;[J)E 2G坦yhI4igUzD50 T;Ln5a5E>nfzBXa˪nr7Xc+;q~!gL4hkbĄ@Wzz:H,hjjWȧ2>l@vN `~fWp,DrUu /܎OSpIhݼ;7 [gAu؝ sl$qޕ=:.Li|x="ݻW}5]h G*3K2M:UXudݸXBPr﷔ѽ]J4bZjyKLL Ə#GepkA%io2.D|B@! }#]v^>)l}";\S>ѫj)*2=G9Ga}oF ]yON\+zݕM*yZO۾LnlkTi{Z#l ZjգfS`#B;_AV+ ucؗ]{v#|y 0!6p)%)׮]\kU>l{@E3&F.rss11b+"a#}: $X Mk6ôtnf88(Mp9 s0x3sIu<쒍8oyx:x6C h[34&* Rzg Y&5w!Ć-56|<(ӶOi#dh=ߪ^IZ;n#"K8BEƈA$F>xHl /)3,]cu1(p`q>}/l[J?~64f'Oŭy%%%%᠃Pl<]f#L|iD no!Ƒ/@]m2m}PW_Io`=̇3g)4 t:ɨڑðpx"XGlltwܱ!#齼GPpL^5}\`X1C9 5{k;aܹ6gyPy4t%W.Bck$/z..uβA! B`HpgT?je+WrV! 0OJ.$txbۃչZ5zdf ָxaOM;ĆVo"ɭk:Ύo1ó+mA۾NcEU-#Ztj8aDތ8Z$gԑ!z7wX(Xm5HRP$XXa%"-tre`UxCuvԐv#Z zyT^[7?!vZފWlǽsoÃs irOWH+^wqK}vҞ@5sP_zՓ{A%&Κ _?hdSO>1Bo{@i%a"!+: Bh=%a8fܺ gð2gFpl Yh%s[7~: MWݖ/_N"y.NeE\,p?ҟ<SD΂pO+Y>^! C@^Rtwߍcǎn YcWMmذAGDDwŘ1cuv%l`P^ !p#tglmZvޏAnq0obEƖV< ssH, ok^;N<(lϫܻJt@G2ySp]aSIh#OŴWC, tģ71`*NWxau*b ]dÔqX;w]D+헳C@Ny1߾D# JFhDvX)3ge@IDAT48Key^<"^-fg} eix7g,qf LgokͨDJuyf^^upW[@}#u:rxOFwHH̓;&JΆ` =qq9XAջϜn*ɴ'\ ᢓԵ4a}ÄIDE R\\nadggab Y(9 w6@UBwbJ"C3.B@! @8{|WaϞ=Xd=sjMƪvaC'|>6mڄI&M"&a! n s _ЈZ j-^hRyhiCg{]}PܡEtS -*Flxډ2=F~D_ѶT} /vw:8:d9\0MWA $+ T;jקDv4TJ YxճM9Nކ{)`~aT|FN","__r|؈ r9Pz֬Yj6Q6cR =OeŮ$ӶmTq:ZQAek*q:3K#2c:=>5po!$DpBRYlSb$!…J% j c`z]I7/o4K񉶶6 Q^^H%FرCxxp;%BQi9EݐE|RmcJp1\|l37Ά`W<ʷEXN²B[_BC! B`pE"_|E?*?O|Wu-y8tR! @.rT֣tv2~iw:0QpefPL i6_C79dd?bNo?7dL23i{'n9YrV ίZJx\niذaH!zbۘC'0 4*">)ipJIB@! ={rJzxǮw֭[F`rF'uH!0 t 6䗖V6̀kHUpP[ڤV{ Ն:9 -ʹ+U|B݀ǿ_$Ϫ2B9xe*$Qۈc%y8Q_n 3.%xl$@Tw319)mFm5!˳DzK7vЪߴ\ɓ'& n:k{*-wlc`z % / / $$`mLro%YVd*V]:#mdr%}s̹3g֜;k757,T9.ąd3L2Yբh쇞77_-i<-dP "&Ɏm%VJX߸VRgEpXDD$Loc@Na6ٰj*0SFVWWW+IV,-4]..;Ȯ81Hl{!1Ng$58M'K5oUT-{yT(F'άG& 'vT 뮂]F@#h4D_sG>(GF`"D8z#>>)v-J=){\Cd^8gbrwV&'Kf%p+%dI̚_t@S&bnXt҉z.rLtvs" {*"a`K"L$E[%"H H#a*[}d, ~KvmF@#h4c KjaL 팥ʑnh4%;JMPԟh"RN+Q o{|;7͚ ^[cftHضgKCa]6ĂpF80$l&X]~"yݶxhC>n ĭ2pacJ1^#iBD@uR4J%١W͋ C pncA1[hg ظGa +i)&Aꢅ+BmȊg)'ϗ ,%e-$3Yc͚5*ZQ̒a[gggw3Vem|V;P+ svB~h4F@##X܆wC#h4QK}V*oŜJM?^h=ZMغ3y EPVF,`$deg!7YU۷_ſ>[KnBWdaKx Y ,#܏9Hw ݂cz" P0dǹDRom$1#6:eY=JKKQ*}4~:B-rMR ı;~;%;`EB[w{wwܢI9@ eh$H\u<֮]"nk@c-M]^jBl,8iQ = /9cQB$äZ~q>tt !Ѩu8XKC$XdRc]jj#$[M\v"jaa4'gˁKj):'4_4F@#h4g9t9sz`ؼyYtEB!`L؅AoG#hce~9fHQY R$xoz$aYB7-$"<@>ljua.)d$–U}%t2ϯy ^!>/ʂ67EֶH :U[Nܿ~)DHm 4FtV1[Qo\QgWNM_kWuό@^t)(_è{Fӑ#RE%hD+& I"1@r.d,R5/JHoz2\nRzc$&J1=R<2ero۶MG,^m|k Jk[(2cdNJEgEUׂZS& y\\0nQt|oٲE2q]wYrZN(//ܾ_UM>x+?SDe|7%MyOX<*6AMՇΖB P2kҤInFԴ7[>±*¡5mMt3H>>>￯df,X@I`߾ {1!<={Ӧh4F@#`X{tAiWY#hF"f65C}vxtb p/Sѷgt"23 ^:%NclwSN9U}0S9GS$7Ka1׫cŋhm-H *{>yMvlܸQCfѯEkt0c*2mtBa7'r&5veԤǀdBW *Zm'>Ib"!$#F \kfPzU2vܩآJƑeprSB~M9\PڀqA~C}|&Zq?I'9n?Kƚ&aӧ+}]Ep?;%$@6|_ߊ]SH| mF@#h4w5`cyqbF@#P%Ǘ}< "~ߘ!>?uc?onp?!on%{ugDpC zQь|F#NeD"==%21? "h@<1fy‰/Iﭥ謮V8Oۓtq-DdN._cH%?+i1 ?-.aBthB +.9Gml!u/il2گس?|.eNY&:f,3sdӦM 3ք5kU޾^TKY|o\;|ydB̆cu"Nz4F@#,ݿ{FOS<&?:v-[oqh`X\t4FlSP"<Ѓu~,oe Cg7]>7f9 ٘޻i Ye5)+B",F:y~Uϟֻk7ߎɠiB}\hJMp 6M4IMWW)kԐk m֎vi7H0iilǛ>G>v7PY Ub`68 ޓdFXKѥnbP`c{|ɪP5?ōr7w\4KTxH픱dimmUu a.o*X MxQEIR}ŷ}OAj@x/nSS:*,rc4F@#h 1ꫯVL8J$?X&>(-5+F@#Б[\Gb<7Dg+u 0:M RA ^YY$~Lb$l{YۂZVRCŦ:Pڈ@4}̣x !,RHyB#bny*b?,qY<o؄s?px(#Rׅx1S5}>Q~3ۇ(m%Ke}ع{:j88c[$#&:2TND7e RR#FT{%ƙLj/w14 :1( BEY:88XL/yUG{qˇJBHMMU2;9@Ko!P{z;@߄߭30 r{Uomx3qt ̛F@#h4gq? ?1@<ø+Սy_<g Ch4V_~l[L(-ꅵI 3㬝R'N>PNU*U vAp8N:,YDݟQBz:ag@24TJ%$AMK#"E5BJy.n""4R#1^Ɍ Tt1am:Sf")]5`]rsKd͸2ލm;' ݻM" w~*0~.ߔICaaa(ڗT[ۣ5~P8\+!#`}B6G|к/%%%سg:G%iiiRNjLB3xP+++KA6eovb?3NcM"cX;''G=O]v*M|h-%QiKjQVq?t)pB7*i"z~{fL:h4F@#0rN~//LRtuIRƽ0~x Dϳ,}PZLF@#pk>%uxvt/nxS~[/s2B0F{`]:Twءοkq2mPv)Fw4hsA`C䃢|ɐ`fI 7Y[]xїwʿ0WfFd_uUmEE[7ƍ!Fd=17}Q/_dk^nTS:s@UU8TX}Yjl"]SLD766^܊b!C*^faM թ 霱lt\  r  v̐0! QRbaJ g1y_3 =sf1cO?hIJeeb"},ݨشEph zE à\]> +b:"c!t P/F@#h4#G#&>4 gMD)õ.>>(/>BF@#p1؜[l8{ZLE?t1d4Urq"%DD)p綶6%HVqq1(3Db(..N=p=9?@][jC|q&OUCWJ01m̙Xj>2~Μ9JnOS€\MOՍR$]1C&Dbp~5몹XGh4F@#0B,ݿ;b;T7O?~㥗^RZ|fX\t4F|# eWz/2/k!)qiNtw@#2l/>8T'¼Cv"㧲!(,f=)*Mg a-%bhn>x /ۧ~+ &:2o<]z"xJʎ`ԁ Qd2$b wB=#Ĕ t`A)r++~>gܸVaǖ?=YeCxIƌdY\u<8(DTaf0Vuw>ىw`kIjwT|ȯO3)b$GC9,Ra}(,*A_@"1iR*D=ed),~JJ=N4؇YxjZ&B>MKUKJ"d<BF@#h4cKÇgyFiƒ)III{fXlt4Fb"N>T쇽 *di?nǧ'`b%m5Ñi 5'NiJ%۠s_<7 ǪWVږa1s?;G^}"6 ~)@Q7hqtd4e`NG{D#nPr㝵Hmذ''\s5*jUbU6W+ׯ#g۲epƌ#34f;솇Ȁy¡^`&f=)hټ TVʆp0O鈞h4F#`]M:\a Ai >h4@j$N-IѰumAD02Lb8ekh3gTs VP4DB03"0 0ն"#OIk:ֹ-۷9~(oB]3~gsNg?7 ?|f5X`!_Cuڴi8\Z"ˎR$: QDFz8uw Kȣںz_~ M){`b>ob$F.秞Ann.8јi_E vF<T铤L\gAjJ9RE9xOqyB#$ S_A;<$dYGqq"]&)6b"}$7?+!hB&*9&W&enQ/F@#h_v5V{~zF~(5>>CSO= 7,}P+h41jߛ_CǠ5qTx9WK=,FK2tȲ`ϗ_~99A9~?~.Q$;jȒ̊fGs`04߽SI a:J=IMOws"f{3j?z .RvF|ʑ!11,rh{φebᆵFaɤ)-u y;#84!`-7x5I44$"[Tpg}6D… y6pߝ "X|~[565F@#),ݿ;bҁc4qțg{>:cqg,}PE>i4AkD>H`zߊ6zX]wnCN-ũ}&%3>l69$҉uV8?jooWdO׮]xzzbʔ)p:'[rxgmǯ݃'tggRM̠`v ';$ 9$ZJ\[Akmt!yxsFբ|+v;oAOM $oxm5=5 ^cp -b&7#^C.))QYk0218~99V9vY'b6){VaT\#Szx,_F,i$q~#nh41@w_?.MQlEL/qCJ3%>/|@lA9:I*2INy;{lMrI,\;c ET0r7HM9v_+;:E*I-tu;![zm*FwLG)+mBS+Niq~f9PYU- U5Ǥ ~RWȇӧ)UoxP vGY'HD?#UyfXxÌ"}ՍAɒ :W_}pwC qJ,,, S~}%$Oe<K G{Ig?XؙgD+s}ݪ9ې}ǰ-.` %6q]8qݩF`t!`;7p=rGqP#p`Jff!0sQIzvݢWaW{'o~/cn{UT?;h48HC@g4|K6D~_DP_ڈgà`n||:!)c,1-22RI`!&4"$O#oj+{ns-E)'y1I9yIģq~L6du DPzRʺ)ɔ]MN*ݼ(oN$X[}nmo Dp[a2iuhAlQi.Sҫ.+j8R/'˲M;`=g2 XAG@Ve&O,G1こBf?Ъ+?*=th <#;h|Xe0[󪪪/ul8Y$RL"VC]a:H\!c~Q+/")}7^")'б*dc4 F=QLRJ\Ju;%c싍ȵI}_,f,ӈ38pv~po~g3aF@#\5[vU=s #pyt%EH~gCE|MMIV$DjrPsٯq mZ$sePH +O7sN"ZI9&#~>jjGRz*=ĦW:93p(Dg9TKtIYl@);WuMܐ6 WO2D0g} ։ɒ'"EkqD(;A"]im&zcYS9 Mh =f\;Z_ vsue#aF߫N(̛7g)/rcPp;8ӁgUڸVfc贒BՃR ]ǀD9ۚVR J4 -RS[g"!2C)H}=ɴ#:qw@l`y Z Z4y;zɌ0ՊHq=F GƏ2B?̐pB-1rO[i)5C^"oz) zEJ(ayUѰi6Xr@eDD·[lj:#ޡ͖lF6ȚGP;d2m*1ld?X&';{E<,M@,/#cc~*ʓY?3.>BHtwuQrMFMC YD*畷pGє["cْQ)~M"zf3ߏ7o1k\&>>{]fEF<)^As@AyC 22b(Ӂ'hjlP;Wg0\o^[Y:F@#XiūK|mbK XE.M~+ۯbi,NHGw_/U 98 ]F!~. $83kIPօr9k<>2qb~,r8um-e7"TYapVytÐ U3!{Iց3]3#l٢"ߺc*B465#!>NՁȐ:.B|3dd(+fރ0f=geN BHn ?` ?%O@SPcaC9'wuurߒt`=t(%Fu)App0ݝ&wݗܡ:6ןnz͵4٬ăҸ޴iʒ|۬)SQ׭VS?D|פITI C8vXÐ:~h4gF)zoٯHR#00ݡܒn^K2 e,k}&ɶ|{OFh;8F@#hC6H+`νhH:(͂Pqi%A51(}=pvB4pQZD9i3jrbp$2T6@80`J.AۃWҺ՘;Nv Doin*T8PߦqG:4IA~!|_!5 O˖-S x#vكbD33%N BӧM=vH܉عj: ЖA!} + 6r28Hqj4'%EhlFtԡ0lgk9(K7Jdu'E>8rYu̳m]wʁqb> %L# ؉ڒE@/BrhYw\ccmz̆02"qO3 "SP#Kh>&~.l߰I<_Jc]"vWipL0D {H6;~Uꄣx3s۴{= ?ZdL,!8JJJG6B58ۚdHKKCtqkd=;ܤ؎;TfbŸ@IDATF/X׫oTc9eؘ{J?g7sZح_]M3_)SԊ[BS{{od+L$$U;!T:T:] WSL tƈQw:V>qD;u7^GTd1S2 B$F"aV$Z3ڱ`Zk;[F)䊹H2`jtuŇ(DQFwyij _*qIڱ uhjm?qI04:HU777#;;[-wmBR _~(@\+2Lsb'JFϩci-!e6T0MJjllTD, JOF}NDgPƕa>E=\Q/mw?F}Ozf{6r <[23.RQ.nƬm+yw؍40*n׭_ZDܸe+"#P.Wzۘ7X 2Ӧ L>q"!gy@ؐ'׹H-R]WfMOS<͚xpb f?0^z% LO~rF@#hFiW`gN> /up Ƃ 7\6 ׌T?ou ߻wTydS{fDO2ex<:4HRPs$&.2D)G$!bn)N^vɶ/ݏT_/Cm"-45!F&"'uNnTӊceO~~.'pȓ ,H(ԈM++,Hiǿh69ϰL?=-h>TB6{Zzе3VR[ YnTROַ,AMsc^pvrDԸq2tzq|>N~0׵(UYΖ6|) P`b7S֯+MPU;ۑl"PZ_c}pI٘7#xjgNNc͈>t#ggs *Hؾf |[q8$ⅰ` ~͝rí_?p MpM<meh)(AKmn aw,LQB=1Ej)M"ː96[IV6bDևDY}}:NMV}(/ޕ"ˋ~_k{c[+?d2J7Tv3M[^m>ex.! d._0GeE=+2LŠd__ogD\9_=3Ҕ 4|Sρ=+361ǒ͛s9 "2>7mV֚[Z1iIsi׸Ao^_Z!EN_*g]wށ%zF`, e@"ג&@SW ]%kOc%J'Eg0^c7&?'|~cW_4F@#U 鋟͛*lٗ &|^Նw`ӞHfixiX߯bHf Fh8:0҂?X9'-QǪ)g/G.Bv؍NiQg~ܸXPh+q {~҆VaKe2_';~PR("Exi$-\L#ع P2Fc?]{;%d8U=3z=`ۇ)],$kE9]v:ޓdwa\/(VS,ʱk˕BFXD'=PwQvqft#>2 -RI~YUy_3#i76!S'㩫oEQMVfoېE 5+QX[ D ,MǚAVU?O̟6Kn4IS !6&%:2~itp.EsrMW7„HFF ̨dz0: XK6ѠH A> c혪k yv{ᵪ@uii(R>"C1`dWv<_EZwy0<듍^h:8M#|y\Xd,$ǟ55-'[W3O^#2noX|cpP0^u) zo2oe99Z:-$]ZʤL ΏÞqi"طo5^sTH^I)S U7q5r-(**BFFP >0]`CO'o~l&7))xꩧ~MkҤICF@#h4cPY&F۲qȻ4ⅷ?Nu|K"4ACc FDYSRUEmnDaE<5oj+X~&/4'kq<Ұdz{ VkE]g/>+oPӝ㇯_Pڅ؞fďUF= NF4mEkCZ'YtSjT1qհf%RF{!5]$:HX1Kl4G֐wN,Ъ Kߢ{Ly!QS9Jx(@QQJێKtPBgq7-\$!xަju]qv.^.;s`3љ[8q,iO3I GͣwV"pfU\\dP[$Ą :c!̖ەAI@ 'gd?S27)9qkFNxq<~9߼.)sƌM˗:ߊNg'ws5BR{HmS&YB1*(.AP?>IVRE dˑk?^ɳ p߽p 3MEE9^}틌&G:0KjuM>7Ñ-؟5L^!v8Mi?p6Xb˸bQSPwNF`"sYN0nXN1px/g16ܶ|UG'#&Pw7,&m[}衇s5:нh4F@#p8J452f xgn 31]jCh0S>q2ڙ/?t2]wu*p0+FHYIז|ct<&؊|! (T\PhEIBog >7j${uVܩHz ԷvUS\o*V!Ū= Drq">FikbD-4ddŋw|`7o[M"cE|?yW:kjMR;%m^hu=%Dַ.UzY Xu$CH˜hO`Z=gf>p2p; 0:Km Z$LGYW+"pkcg߄Uim[:9XFc̀C9{O9L[DNjYȧpPFǭa !8` ŠigkN$fLA!h_3Yd31QCeg뗛+>5/^ӏ>Htgqq>ɼU$]9ⵁY9=JcGbO9}'!K̭_mx\$QN>߸z#ÁcVBzJ5^BՔbpF7ef3_jHgkYOp𤱧'RO7%q|`!O6p ]w9?Iv_;+/Q,22?F[g c5L=۳^͛7 ޭi؛ߌI誮cN&lsrrD;*2 $"##UBpx-eF#a[U|T#%2yƠC>S彭qNV OeW4GL:84/ՠ|n0o6 V|]/MF@#h48_1}2a_ -AbLnEΖxQxpq2h;;0jÛ90NEj r:tp"( 8GNww/YMF[gwmN5J-INjQtvIf 0Eiioza'N4[, OgU"Mycۖn"fVRM$$vDێ7&εFvvCգa]|{c*d08&ENt|f/ZH `ԽQQn^{޵r8s&tO/{G)swtGxY-MNvH B)cXOEQJsq3sDs> O۸q#8V A|8g?W%9D 3^?xn()Y۽wݭLG:ۑumi:͌'6v~?Rˌ"H>&i9u97AB56NjzxcbxO~?ۧ}g U%64Á6t#$I*q<͜>Cg !H"cD=t"3$I', :-т n:[f$K4Iuyl9$ v/d;qI٨Y0Jq {%5)_(x ܯ(ib! DlI\6ڞ~9; D9ޗ3ڜ._Yu&;u~˗OW4,*B,rJˑൖ֭[վ?w\x]f 1- I6{-|ۑt 1Eci$H<Ќk0)$xh\N#n4^N:Hq!g"GUnA`%OeX!QWZ+)y5JJ:T}j\'h'6W"g+UdQP(8J*ҌzX$O7hj=75dxɹ{0Y3<x`3R!"NҁI~]'uto5F@#FS-#˛ǭXCUH =-An_8OGn.[(t~vqԩJ*:jhtiFdisTh8{!ƾMPDV$̒{809g͟`%aA@t(κ>j2Pe#1לCKX ")B>,=R;QVIAf;kDJi!M.䃎=b}h鄏mç}#n``5)GZD~4J^݆/b-֒#CEUfDhۻWv@_E6߽|`Ex5+݌c8)d9J 1:7Fin0K:ʼnmnsc$yUeyumNtni琌.ϮL\/L"I U,s-"5 ^d\urr1ӧOWm:Bo Ua;6"َN!:8P) oYω3': F~[<}E5"oOn؎:q6Ü .!V@0Ny#"1, ][JVM]r^X~a^"R, w,Yw8m WD^lfѸ/3jYSYtŭm}wߞ!H],S e ^B$s8{"dߤ%1*22no kl;n=DMe:v;Smy756H`cI;o=~f.~З^2hYS" iKo~Q_&ThbM ) "wD:fwĐ%Ss$ f-tg^Hjt/U_(a֬Y'a2YS"ܥ~ERr"L/&|w1k|cx U*"غu+z>FcӯT6l=`{=#SͰ'' ۅ X;X[&g)-b/t ˁzvvcq<0ey)N5ۜ9s p"^ "[[D .Nq(ͩ*eA׽(*Ǫm5R$Fb#kEsF1,0L`Y ƹ%WK>]ߏ4Ɂ-mx(ʼnfEiZ;zތ.b(?5n}*0Y3QLP<3-UouӦL6+44 $l)y VIR4G3#7ߴ$pxNFLo,z(jݻNFp{4E PΌ/@-y7[n/ECƤaIѤl\k}z):2R{קNDtXG`REƢm(V.S}{90cOmU.BDDQx2{eAr6*bmL #G'=|}8:ۃ߽n_(eoB>{\z/#N76ҼOiu!0Dwh={JweKH5CG1ҊֻڏhEu- Lo X5;v"Nn^Uӡ"_mCCJ4y&u1?EgI9*وAϯFMN@=GC T˨ EŇV6]d?ԓjN#)YW Rt!"$ :RbԔѵu6s(DHFK_6l0Ib!F:>Jdυj:GOPL[5ӽDND-HlsϿ/o\[n:<l}m+)77;zEA$-Iq-7㖛{3Nt~d>#o"S_ݱ}q^ۤÅ~=`{O:bdowC ډfxuNhmԁ}=FB0@mγ%<כ= F-AF{c3PJy"7NK&HM8 ) w)=wS-cD>YD}GR"Cq4,! m$|؆rMn?cIP4>uP@޲v` `ŵXdȈPPVD&e.䬈dDE(9F26T(UDo'(hbr8s [\YLcĸGjLAd_zx+uCYDӯ6mcA54U_yl/*)#'',!.so5ijAt?y gzeۥw"AE8 0{P-~hE҈>y~+Tm܆M[@k QV$ARNVOPNdZ|-T+.,>D ܼFm䈑X0,2S е+[`׮]k{Q!' ÉOg?[uu H:H1&&/dسǹd)g_݀z65stnre ;[A)DA"$Cu CSYO:X{Τ3YĞ_e]f2"kwl{f{z/֢|of.-NO$x;M\/xAh{K- ܎Pz@; !Òdoz|4XX4. _wpc->g)c]qiɘ;c LFA-_8++pY ym=*&@Ǚ 4: YH:== 3ST:/[FᖬXL/aqc+JU.1w@5 z5ys$- d" !ĺ4О[2z}c?\ nt7TZDg# _[W'NIw$2eK P4yѹeM{Aaղ`d1j(V 3>lv.Lo1  /̊wvLt!D)'>ln l=`{= bZ7!oZI؏Rkcm G(K@z8KZ*(+h߶ ?l(F[OFD%^جC{S0ݲmUM]m ĭYqmT ` `˯݋/Z }ͺ U!ic(f#>D "DDHfc82 Qz |(㩙C\21vQ" H$ mʶu P _9/)TDZzGIߊRt*EM_?M3Ĉn|jtkJӉ_%2E$do?Σz&M2T $KK(5I08uP#R1&Cr۠T~&,?_8otʏge oxE_v^]G#gy6O'#y6C#-^w%fMyKYH},FOhr\R ~^nϞ=W(i8ˬ~Rv5טk6U@ي"vz;6h"b+>"6mdZݝKLgKKnJ5𒞞nPm.Dޖ~=g?>8{7\~ Mo1\l=`{e.х(>n" PzbG"*"[^iɱ(֋X<ۓf{`y`⚊VR毟9߸ ذi#ʊK޳H¤ "OSM. _/F,ϭ2R|k>vU7c5r!ps`Ane3WFto6bb5tDaJWWiJMINnQIEIlۙ]h$A Y2/h]zun܉#il뒺u$)Ó:ދ,2fvWF"Qc_7PƊR8q3,t~(d!;nڕ Ǔ/.CvLV|*IL+Bϯp{hS'801F#{QD-{L KLJ+|5 ǵ ]G"U3O.K)%T/Jg976[ǚe׹ *Fgytҧx<vE:boIt%cpυLWuH-@IDAT,LDyXmYħm Y/?(~CduH 4 iq W&Ȍw}#ܪTƘL}e5qF(CBiO״͗_~Rzn|I?1rAԼy^rK|><7tҤIDT1IT*cۆ7Pbv(dFR[oų>kN^:z8n}=` Ƴnl\8Ԧ7pX|T06,kX?`x{DO"[T}"ϽMٚ(HLaD$\8:o~聏g5 Fn<,@@.ʸle"䖒lp";pŧoM#b|bDlFaO/Ŏ+pl3KzZ*[F0u/HftbFD͊P5~ < SFwlIp&2IOtr(as""$waENt Aþ2WfD8nq'Bȼ)oRPf&18зD9J[.oxGv%h^)|㸛5>2Fg D]ajбHL+ ,!'O6yXJ*R0 Y{U?XVVf)@WkfjJ(]5타`Bw_N.W^i:$~ Abcq"ەK|8}ڧs/=ĂtWڮS Ou{C1(֦]9ƞ|jU(@/FfքIH\wo߇ ߾Viw0sj#"zwY,]pPf&\7`Fw6.QZSVJzW?12;j# (ڷw߯g ײXW{,+Nc-v/>oӴiT$yiq׮]k3U2cL<'LbZIȸi)R$YNS:KK"gF _1"Ѧ,6o !ws&;y|2!D4D|f~0mMHk֬1[DAu1|CN(]u#nڇY`+"jv,}R ]*N.G@ʚ9f@j\\$ںj"S&"U$Ҡz.6~Yꗵ ]3Fdu=T03\47M̖\vKJЬ<ؤy>cl|xަl8н_/.5 ( Ɯi*6;/tصq" 1+3S)zܶ,D/|?lf0cJ$EIsMEjmF$bLrtRה5#UXQPf<$T5^l/GqIz-!9Hp-/7mF_3MD"Q/Y ɧW+’M6,g uϗW]9䕴k   #Bf6M|T+M `YY``eO;xy2t~VaO]Op|9{š[-Ԧզ?ѵ!j^'2cE3:wDˊ'Ns2SL1͛ٳgm[ȿEIiYr 9.4'31<(9`&'3UQYT ZU5f67_X\u-џ UZ}GI,~' #tD! " )!7=-~1`}ĽELn_Dy]SSc24Mˊe@Yl\dx}Hj]oE0ɧxKJGu+ToCv'2Nl2lGڢ6uN)J^Z zм@kE׈{Z G&Y6T~iD5  $g,jσPMDו3][ZV\razi"^D}\Z)`-25Ak,y=̘1Dʚ**Ķ"-mƛ泖,rRr%7䖛oyؤ>aV'q6mol&ˏ^KQIi[|QTRE"uvsucLdfcfjcJdEl 7{)yp^_ieEK.F:dVD0榌6[72zEb "97")MA8F!_7,3?DDe\/!^* t|%׬E=Ic]S֗~bbBXFɧ|*7mK>>LdϋѺ=wrk{)$ӷaEK#jP!VI(zW?Id0D]iu|+kE?>ɬ;3:s\Zʃ۰V ~qTZYdwt:Y#hAǨ_xvgoǶmۙg|-/~S /RV@Esutﰲ,_2D&BL9sEEHfQmBM蒟4'"Ն%!qi2{ʒY2c=|^ڋԔ$Fqls}Zv ]OgGjdtޔ%(ySοD|M_(eWW*ey *KH$`!P\Zb2(&k&vcʕOӴ"#_EBVC_9k2Dо.RU 1 Jv8&s >[9_ۛYMחwv `ퟹ 3&qMS5\cS `{l=pP5уH mG sZۃ2fIx,pjf{|{@^Vk/P2][/6"b<ߚ~ VZէx7:%",цw݁\|%ZP\ocS2@4MNGw4pL1;vap_ QFY/+Xr |y?BֱuRRyN! Fdaov]{o/4<)(7cg_BAŬ , rAѶt2+FmQ&m0AGoC>hu9}]iVT{`" Wk⣐4m  vFA#iGS]Yǐb-YTs;b#Jt5 %C+uoOdG8hB}D_-t }bڷŌGRL)x~ּԥKH@,Ě)Zǚ@X ɺgN>އ2?6o*\-WAaGϱx}FjD8%(%h\^Qn$ Hb?7A1HDL!D `P,A`+SsuoW_)W(x.jl(]Lۓi~22UkIY:G2kY=Kk2OX ZiZZFڝ0e'tֽCc-2k,ʰPЅLD l8 -'_ktu XCf~跓2 挏sqV}&]wOղՆVImrڎLSг!죑2R0^^2S|x""IΥ2d"AtٖgMڝ;pLU:;uf{ǧ ?a\L_?6im흺ԗ=`{> ЃaNg+:4 <ՉfPLOO4$jB6ziǫϣ Iu7LOzY "dLXbym(A"Koo?tPDnM9PӅ2P c˒pD 拥P̫c.rN546_reUk}=fMѺ tQZ A,g(m!ʥW]mCD|]e3ht5#>O6ra}c5~f}qIHu'=".%5,Fճ@2@/:ΪG}Q|Ciݝ=8\5[ ~|/=Je;rwNi'M:bl-YiTVgC=~;g>bsu{l=`{ GNSos,F. 󄗞1FpK lK'>L7߸i KWׁ^Z^.˾~{)FavetuH͎\8:]|WbWР!AѼ|T 2砨cZ0?s;݉@o?/GF}1|;6*GZ+cG|~uq.wUWvk=~Z̺[Y E 5ˑV(DIBW^y7}U?<[!H ‚ѓn|֗bicnP+fD=yYY~u]Խx^Խ.m?\so~({~wmWR7=Q,J"oڃ<։z> !s<>IIBFk-`#wYtZ`/#Y&  stB,kT&Nhy(wo@[KHZVAi{<HEn ~5=!bZ[̹SqY91>?ێ%o{StG˜N䔂3f͚e2>-RFĠar&Pֈ*T֢$U0)Nwe{t3S|D,s&pV=iy|Ф{>}Guv>a~^.[2l=`{=+W6iXl@Ҳr|Z67""={;W#;1Ѹ1%`JB!ߑ[4x ^X ,{W咾˰`RT@0:1 qSf`A/(,){ D}β<`\\ <[1\f^SX8+!c21M;HAK&ڮ$t܊ƗOnFr)GBDTtcwMR҇ɿ̼ )i'n{n|i(EI']E!BD{H^hk?/ڔeĊ[)JVMTLtW"2O cjvEbb )zA C?Jm{4#=8卹#ǣe,[R_c1 nܻ3042$DT$Gaf5sQ? ?$%6PN`j Xo%gna{ e%S/72 d!M@U$ކ _^G]f!YM [ە4뺏݃(c?>&m`/6lAn}-fdDXtԠ:ѠA {4]{,$={1JYd_VKu7^p־X~gp>,#],:]ǫOx(&.d ˊpЌ=vq-; &E{oDR/ZL2>>=A2AAfOs$ǺOY;ẘ?one`D`cmC $Aw%eH}|X@2Lg'jP[ʣը:RR/FQ(vK+bl᳂ =N:x2g(?iAU:&f0Wb$yؤ`=`{>ЋtL5f&"!j 0e$ί}!YF,X/4 0.ԄHf{^--gXJbCK$ >zi"T&-b )zU%d¤@|#6: 0/p`ժ-5F{`<'fg1?.|ͤ$[amc(:>%̙3(70DnZW"EFPQ浾Y?F:hݽE- 5p!{8#5tj:Nr%?-Re&Gl"$t% tt*ȅjTF;ڐxy4|Xق76:K\^ѣ"02% Q# ѐ{붌Ϛ rDpо(`a=4 FUOdzYxN4=l=`{== :9/߀Fb#0:6{+q@ζ=89i" qRdy>s6`F^i(vh<<"#oQń>eGC jw޹koZgODh0/v!2lE?^y݈#'ǨYoE!+-)1Ȍw/u 9&Ijˊ*E"4^_1R;v0(NF53I{%&DHTZT$[xc* YYyVKD@e!'*/GXBM 3prɞ&h eH;B-Ō?HGtҏ*Ѫha!<酅x @VZyy#0. H}e]ee?7l <%a̻mAQ1i b!W4~M&֓?»ҀWρe=3R}"- Wfll-~ϕ,a(ea&ѱPI&9!_x~\HcIoz7}K`oL:fFFE/}εϜl*l2$ġ\[MG[%AOﰦKtEyyxcBD$LD9?~n=_:ǹ`s= πiw/|=J]Rԃ.ُ~K?m=`{>覇jXئDJ/\u! =IxY:v:4>_p˔z/Vz֊b x@ ' + jHV" n)C9FRj Ahsp$},=w 8f,BN/:|kH85d7qKS0nKĚߓ'M~3T(S΅橭5!efz-},Q!MI.1Ȑi>u wٍԶA袄**s l{s &gU4~Sn0Fz DȨ^lK,)-Ejhi=" $oeA`LE R6LׇI0[)Z%ă${Ol_7ri܊!'Juk.CX1x熷quJ6v(jUO܄l-_ f$".(ҁ>d_fOQPE BY>$â 0PjNT:VlGWT"XŶ@={y~~GMYiƤok;ӵ:D@kPk&BY[A۰1UZR^ .g#-HzMnKZϹ6螨>;}j]{QMo]}#.+ݓcT?8xKC} 7BU/PI |ki'HG%pt5MBOxxݵԙxe<8i9YO:Slѓ&:0p5טD{NIwl=`{}Pȑ#~^4%%*q;S'8/hstE,"pIJ !FeXy`( I t/ĬLeP(b_HW@#}p34#gp"*z`ɬ跻59kȥEAPr7с<+gb$Ͼ (/Ϟ}}\GSSpѸ `G`&YFd__۷oc&B b\'"[N GXtlҐ  WZFජ[_Effb1c5YBxwSfvB~DK a!Km([׃%=&2ҡ\" Dv:iE'Ri'%ظqŒ|">4YJr[H։xdS6m2n.o1iW¡*L i3g" Y`]Zu~E~2G7KJx-Gĺ]Mga^{cλ ڦL[S;U?"j' l݈ CsHj0=.cPFwOEpx#3h>" t Ydڵ6WARcJI>݈ҷ֙C ~L]>vk"?4soGlN]<^LK/dtރ,&Gk<{e>vCgawK'yl5~]w"Hta{>,伬"os!vc]3@3ú~eHC̴~ӆaǑ ?-#W(c=GL^&D<{݈MBWH ЈPܫ 뚳l֬Y&OOfmL3_2jT?󟴼3ho5kvV)Y0ZĶr墳l=`{$RюԶj\l'^A@'GԪ 1/-Լ"1~\ %H7 G[K+ΉC:ɉ@R~|55{hME` xW|nD.)AO~[GbB]DlH#GhUוaU!f`kX2kg{M1ϞIM4+/OqV-I"ߥB3]#*n̆FfF\8gچڗEt2ۣ5>mjpQa$._\BE(dvH g{'&#<0ڴ$9Uv#2!nq9bH]N~7_PG7+Z:+nܑoW> GO2ߏ># GO>>Ր>֌ӧwee0.2<XΏ2 DIN ÷ M/M_`3ޮw܀fFTPP[>A\WzFܢKqP\<}g{D׫?9}\ .@ٝ\:~mTH,g9mzAp46ɅB i 3גа=d+H$X XEYX"H*SKlg-4(_dA ~N._~??8=)zꩾol=`{x@  ]5?`F6adw#Jr]Q剩I1}RLS"g;U!2ExhD&eT2L]>|i~NKyZd$ GpbCh`&g2iك QEy(5WU[c$X5TڗrI~IT4%Q%d֌p3)Dr$CdD0Ëf쳊Z۾V] wSa&O2:,SLy̺ l'&(8ee: EDP+EpPtp6ɉN6#]A£DW(kzl?8խ X%Чmtw`bмmjpkN+^`Hվ1 ZPi ` )cD);CŽ;vRqK9 WĪ|l#1Ǻ;8*pj|?a]kcx{,}TS ֔;c$+I#l+.“G ?v.x6_q= "d]j^zď@&54t8t5ux|Z3yȫ)G48$#"/[6|EH*o-fs1~wfCH>kΝf>V}p'&F&)`so qj7\dպS*lvySWEw~S}Sڿl T+e+[G,9ZzԗI"NV>I31`9$_tbwpLaӉnNdz EbB]Q=ژ-I9ɀx_Sȹ] 'f+#RQؔf>ߨɾQQ֟ڎjpP?es_IZE¼}sYcN=K}C3rgu"6l=`{+ P C[o\'8ٿuijCv8QDEt 15!™ڂJhp4cx0d4v<0 I 2I\Q<Ԋ"*EF[)e@?ZXވAY6J%8PVg H|s2\9_:7]gg/Ĥ CX 7@iXCWj3==kB# $ʏT]̨rz|0w v{>KQSPڷ@?xĄh%n$+MHt7u>ztxbf>FR͛ʹXdڊ*8lIFϧea̦gqgUB tTofd"P4UEϫ_S;WumayʟyuL(Bd{N1R^ԥKdկ1JZ)qꦅhLFDc f|sϿ/xҋ|2rӍ'=̨6'E@*@L7 $?NY'wMlͦ:NډK\b\bL$BY+X 7=ݹ3s盙;3|$ LD|\eׯdgw9>sFRD$Aus#kp@{9:  8C0 $& 53CGMRw շT\f_7'4R^]zۺu$yS`;R3p_zжJmkkkkkkj=dؐENCBfB#^$$)y)% Ap1gbgf) 3އ}C!#ٔiYcو  Xm?oXT֩l>y ۵W_!,~dul{Co?Kf<<qe;`#;ƘH m*A9fF9x2J5RGb+kBlF 6%O@bGRQbt;`I>J9,#%($;쐔ꆥaЀTWԈ.uY9bIΩ2BGr,JzTi>RJ hTe$2TDjcYu,3Z @ _נ (8Ewquar yL0U]L:S9] ʼnоj5 9Sd(HNgsZC@v"Ntt\0:SMt3&95͍1dȂgn%hx|blJ77|9$_*"`SD6lAѳ+$*$ΛqQ |h|38Rc>^E-y9s8'2(tPl eDWr"u(ӹ%٩kr"4~kmEsDDז/7i\T91@&ov<UnE UmA/uJfü%?_,;-;텵@Z@A 2/"ʩd!4wf;$sE99,SEcj(,&i;j D)^h KĢ)M{("< \z칧H= y.196=ߓ˷FM@ 6s^("PM۳ж,xbqR$`~ˋ"^{ͼ7/u'h'Y&+n,K &󽲝/U0^DH%ٕ840O-'2c΀t#}\yh;LS mw_9v𻥟RҊ?Ӿ]DNonL?a@Ϲ_7@=iS)OuE}?ޏWi_?!*bdZ.!p&DSiq.M<Ռhq=k(C{d,@ rj'2z|\_Y9^91SJ;#P쬼ʟ>|W| 2Pe)za!$\y1_UFӵZ~ VQ?s"TR( *gA1:::v$Y@,}y`+AD~ /^u9C&羰b:DS9'xpQ$4, qDSⱝ{M_-<$|!SLoԟ`psxގ3K"\ tHoС~b c;Oi@q."nQiX#"bHvmKqsG6Iאlg8tm] e&*)?*1˩ K棺ԔԢ0kx_gx@8|x0KNׅDgdd !v1J*+j13#vx;ƠA С(Ky;u#nγv -",Hjhnn19o zj^3'Eh8Gmmfm4SV"nb:?<'̲\ _U]cPenE(P H40WFB|IvH檅18A!Y&2NĜ;e=?'PYYjZ :S+%(6*JXu4TN02IhzGFF>KPNDD-"6t -Bi: ܕ!;&p\&iRkZdA-JIvoU1hwd`Qz'h7ΝY(/~w=2?3wbI_%_؛"t\s7vjC'P=pNLBɈ(u:}j p6B/) K h\:]'M*N$zҽsicf}tVƺk< 8 *-ǂsꋖfس +!NCI޶5OM)ɅcN.hE^Jg$wI41?[t;OhLR I.8 2ROEk9;xpp_}br6ŝwމ}{ :@t,*%z1=tгKAj"dYro ?wS.} 1%! 3!(z/5PNпSNՉ|q,H)i y&笔j#b _VɥsY!J } @Tj@DW9TVk?=]lD9h=)W$.vWb9h$}R %oHPউ09 bO(’$"H$"R8/7Fo X_w3|*"1qMIn啭*9ӥqvO^s?mj-[QBpFk*d_~CUQӗGoGhΝ,| nki#5ŸWΏ"J^·D 4SUXb9hˉR(0@)'CKYd+}c *Q'p<ؠ̍n)ADmXMُ61>-u=CL ?!确` xWrW(OF(#/Db0w䮔K#8h3&_@=#;{~wdN픟c$#@R9u:x@3 +:)24 ag *P̜qᑈ`tJ.ϹB/i 4z,+DQ} udQKcx"k{Ah 'ʋQ^_0@sQȇ+:Hu{sihzwJڄ1Hb5$[H))i\m}꧈EIKij)r}-\.Nz71#z,VlC)hb~Zb/o@Ctxwl] fDrNDAws["0t(C쐄5m;M;#iFl( /р\3u_9DvиŮu6Aހ>M1k̈IE+ұ2hwm&{jU(xŨ_jɷ8$l߱'12YLw^o;ִf@߳<%E"8Tj"3\Ni"'m%zgLilc mm#hHzL}%(irQ+I(p;~4Mo+/Q>!1Ty}wdzެ/2SQ>wJFRf+jݻ⳪uk ԆF&Yq7xfOWBg[8}a w" }G |dxzcʔ)hloիMSʋ-2c"y0$5vJ*N==\^:46 WDHE_jyH8%eW;=)GHIz( lgčډPk74}U t:oi9U\\ByNvk1|kfݛk`lNu j陖wKC+]4~fm4blx[g{o-`-`-`-`-`-p lQV$ 'EXS5L=\BߋI.y:ƷI\H-O]hzeZc^"=aEZr0tr2LIo6 S4u/<NoZ@@cCDxңRwj,IXPDG#A#Yc@d^R6$0ZzL`QfR\OnuI $"R6t%.)Z)Ɵ2}7J506wCE픋CsNŗvlٳZd/(~%YL?Z2$/W݁ [`?xA;20 18snE)#bL}'[1bhbMJEWpEoI1wȍ:FW\@ 9sӍzcl{9"t* 1<"Ss\( @EDBPan<@rQq!g2cܘ&cn}__F\[@I%=f挛d+` qU~14cc8PNeX6z:.Ehk&iާ%kcVA;eTIw,ApJ9z(71w*/xW ˲}9\Q.YA#xݺu@x9z4& lפ+ kݟ $ꋚ^Vq?ǍfۣW "5T aםv"^us(n4x{bOJ=i"u#aεOC3FB7J ]?>S Fo2ט['^3^]\6玹x{&SRR"#~2{JDx0j΃k']#3BqۤT>??oR bbsu{-`I{llϬzv+UD^蕺& IU?!h n&Ҽ^*< zql{vZg)_軂Pz($MIiY7O5q]@C@A"KҤr,c?=juEMLFiY@^vz߻dĽubÑQ HM ȕ=EPGNՖ;il+2'$^QOH gt=|u_KW7~ژLR[_}cįg ˊƕFw=vZ֩? xޚg3o22$#Q ҍԕ#EOWr`7$ H bwx} bT e* /ؾfJ!:n"T5.`ry63YHvw g+;vdwnw'#$ޱ7Of9p: ˆMFRD& UVCI!iͫT{'{W PJJd23/ÇeL㢤"HL׾d+s9ѓH\ɷ-Hᇀe]K$Z]o㨝3%b$OLCXa&?+'9$'I[HH\G?mP|.ݰs+|=|-|)D3#Z"C]9N#~+2A6k*˷~uFLjA&BcHrzo'2jG5ɾ@[?Jo&!v6 O"-[ گeN`q zq4%1*HI"uu?:t+پsyfB2x;e!5uq-0F霓,^8sUl۵Q=uN$M=]o|TEIg}ӟ6Y]t^ Xҡ3kkkkkke=*B%QOzd '*kŗ֎->]KzX t@H@ ԶmLX5Ӌ$0XH@c8AJAxʲ(VK-[J,{+UQ}*Av{ {KX'Pf*ߏPz3|ie\jvcob9]b҅{CC=h6bdm<x$AE *$|M>qM;2J*:4`Gk^^&ZWY@ $."wrҳVC'|^}DrԵ4RtϹs]a7tsNw'e*;vloN@Éq3I+é6-N״ӗ8uږEuEQѹ"R@ J:y;u ~Nֲ[*ǭo7|ʴӇԵ(A/Ya$F0&{ST771ĉ&HU!NrALyyg!%RD?^֕{V! O]gajjدIQ } m!<^]  ^|GP6n܊]cͿCY !Q:{D[1/I_uj a2r?aӜ<p/p|k5Eyx1W`T!JUQ6ඓ^ZNi t,~IGכ#O:EϘ~(tIy2 _:̬&Fw\ZFזs7&JOx+he^+ sεꜣt/|k*M{h4(&"3AgHIi[EdD'PL ~$VpY[Ow:$f]·Wb$aWH5\}0 !i/k*2Af83|o^g/s!ASЕL s "1,ϻ#aG}v_x|~W{FyQu!'$WݎtKv]w5MйY9VQֹn<|[`ڴiHOO#~$"O*8w @]?*Xu=arUD1GrF1'G]>G8x0ϝMLf9ºJ<{lEcQH$3dA4 ڏ_$ɓ' ٣?7=3rPSFbFAHc)]&;3(B+5ۂH|0-Vg " FJ͓zd$C&hci/:F:$8&BOB"0DFHvɹw[c1i$ P̙3^aȣ[D@g$V7؅7wm;E5\9#cNx D!e9J+q$ Bj,ۼƫ}Qasq~o11ш#!腏Z4 6dؔxueqf!(3Fv#ǒ17 yV^w`zUy [Κ5xWYq I\47l i7)I#Ur,y 5RWX /F06ѳ>/>rH~LMsV{oK&\<ϣF|,$(ܯ[|_GTI>9GYm-0g`l8~3 [xV? wC8qsZ":ç1OX:!G_1&Y'O6 98\f sccdQ+Kq_!活cpC74GvD:8,DUS+B%`%Ӕ#0f{1lcvĩs9$čY Eʧ;”#1-"" FckcƌAUUIh &HZ@Ą%g9@=@b3Vlۀ""T-!Psyr999&*F6t"$DYkTU(#D2d8ԓvߍdN 2;&%9vBAiUz#qPSO|"r$E4ĐcY9M{\ݘ] @=Q|ƒ\T4:%hwnVH_| W @}6,=a['sq{bz, ooCmU%: y=/[׮Fis;+jvL10’Wp:yʣn|K(aAy;|1,}bp"=ZYbS[ꏱA4O( /U7-둑wY8x! NP GrP1ѶmL[CžMe>eEHB 6JꛫM7uXxsZDEF`F./ySA1?˅WG%.X.U.eVmۇvz{:n C@n\hμ&fϡDScѝ7ā#HvVq^jn!a!$@cTzBsTY[w^}u*MUyQq$Ȁ JAI)߻[X$]6ߔgw< !0?w24w` 78eSNbn"D*tX@;V8eOVk{`[[ X X X X X X |-hwm4#1Ҩ\z2\PBA/ÏfDj_;Dp{'.u2T\B'>*uy>hqT/M?6X 4_YɋY]"-pHJ&8u4ImcϷroo")on)PA!"Wb@l8ԁh4LH {x/b-7[o9""WkHXo-;+\vLs%I"m6e,.,D=SS[cth(Eqƛ,RIWܶc!SRZfɄKt9Oqķcf,{9z)ukQI[JI~߭~[@[fY_2ml-`-`-`-`-`-`-pI,ӬFRJ)-jۘ(=2{p6gRW_72>>X@(9N;%Pży -y+E~ܼ_Đ7w :@Z0JqNiGsP3Zc,x~xDVJ9D8|XؐAy^*(ĺTIjm a䗢NTt{ 9S6*&;okoƚ 8v~GFc6P+sp%ƛVE(9\_I%*bӦM7Ք",@Yct+(WsA$# H }U:!>N]wPvP}?Jv?s5#n4l߷u.ϭ_Y _?,[0!q =A$i%Yq9n*2S&%m|o! eTgg;} 5 `yuNib~:נ.)FHt ILNyd^ؾiB"&yh%L %K]\&VAܡSpKɫ%Gv5[ M^\4Թ6LM[I9|-|.noÙRxi0J ?Qx೗.:Gݩs<W +enڸUwlW=ɺ"( GFWۑWvlõ}[ X X X X X  8^㙺~zy׹i{yʻ[/#g Vw3"$b\/][ F 8\0@cˑ8qb@o @L  u$!up\=^^ZMp!Hm(ީzh1q/Zk8CD:<ܓ(mFEsl>c++h ɒ% ~c""9|Fp\S霈zQ6z4WމoZ3Ք;7v]cQyk|>v,C-]@6zw9'O7fb<njr%Fo/.C/ 4^^$?}AUVİ\)v@L@B#Ra$ݑ,Dv=σ"9( /oxSk(ZI @xz yߧ >̙/ 𪭇We-%<N9%v# K\=**Cb _3ugJ?ugGo߱7yr=Umv-u/A;t/2% Z \*׀1τ9~h_ёp[rتwyhJUk>s\M(B0rY;%d-$u\S̗>Γ6B]mF v:wΓ"IhF'By..Ëu^(?+WD]AN ^g|x!'0}C0u\ӏaIpK:tH%i3H$pU!zMLL(OJ` ?:BO4O7*ߚ6 1fp6QBD(8E4#p={"Bu͚vo}w=F̞=v5[4^=ӈ["ܐ&sks$ŝ.ZX@RJh""KFFajFe`*ޗz鈍2$ի2"v{)Tr7h2 0||.YQԔZE&A'spDX}Z%;<?~5cj(TrJִdI Ɲ>Dp0aq'pw".$Q~}Ҫ{p=DE/z ػCr8/|vױasyR*ЇgkO?_C$ $r;FL/ڽ)SQ_LN$<ryDӗFn="Cdk/1i7C?eև~,Aprr@ťh _4nl?^hfT7ܸe'q:! %?羵&f?? #ǎѮ(u皒w.ujwn.y{WŒN@IDAT;qf}eS҉2>w-_)m?=%kkvJc {yIÖ>.We@r\ծʣȑ#̠zl?q ?9/!uy@o8 *=~xCUTTOÇ2BکMwH%]Q:. :~ 9!oxzG&iDO90um0f#aITוEڶ`f#Z",}\e"S"]UBcjtp61;}[w x.<: LƂ  pᕭUnŭ9/?F_~EĈ3h;E=v8ih?9:`HnRd/ζk$Z w\mpa  .9 ֿq5$ Hz~W $HתkGp0Fg:wzGB#"3ǸHf$%9Ax+oȍtfmQʗC`?-, 8^r"TZјՆy(,GmI==Q] Hcmض}!h"I$ʟXs]sN"o:xQɓ! O2OSخC\S}MN93mDމ,~ MfѨ@}r>vBrx ?@Ňշ+_BnM)%Qq}(|vغu+N:9kʭt=wFlA|N;H|o[ϱ؏g-IB ֿٮq,1;*]uuw./VydmG;IUL6?[^sEm4f\~ErE cԉw쯕wuma4Bή\&ǑuQ[n|ŅbHDxWQm>L<,D~%W]4edvs'iy{ ;M#EFc-/+0+tW+=bLoKӁ\HM6sUr ? 33ӄRSS52 tFDgc-`-`-`-`-`-pMX@jzճ^Q`ێ͕m˖cFv' A=ϮxkBuNkVvoi$r:C5*GNe3U6Jap&~\(y+v"kWz <=mWrN\Y~L{*ofs7ZX吪j&1u?ԸkQ]R>Aax.<8N o'~C?51'GYqYV둇})1=_x(lb~X6f1{u:'_^]K;#0qAy!L8tPEѩh;vlZQ=u*trw.Z: 79}ވI&+V0v/,^W UUozfUuSB"PWY"W]'}Hm#Z+fw?0|\zt)hND=s("FR=B< B%%%\0jc X2w kkkkkkk Y@/TݎO {ۙuxx~~GD<|~>ʎ].\ķQũ-D,x6{%.?Jb*΢*$ "B"566"Q7܍;׫ $ԵD@tPLt"oHk׭(M3柋.|X>?zۀ^]X]pWO fט4.93g\JL:" CASqFg׾=+|zdRye+_NH:~^6~s͟uGe3+8>2Sl@DkrSrg!Et-bt]&#235uc0xN Bb7(8"#Hc1c!&:{ ܸ pveHBَBdTJSijϏbaѣGsGaKD[ygE7lGVη|}i- 'k֬1nz ZZZZZZZZڱ@RR`<_VUnEMC#g^#:ɇL _\ Pmv]=Su|_ćzw;?[7 i7 ỲC1fH)''ǴqHսkVr'O6PRI]mW "#ChD&e+Ы1ol[@k4fCsK3|IO#bm 0F| 8y(,?-I}|C)b{<27m(-D%\XݳcV+(9JϋάK;NHE4.4y cЌNJBD> (*Md_'7fw]Vσa":ӾgX@"$'Ǭ|W0@OL2)(GXsC^u;GQm̛7sm@װs[2r-kkkkkkka$ XWB@V#s<#UN>:oWг6$գ߁_Z-pkj4,ȈjȈ=ͭmB;Kv(3g8NٲfLd bCߚT{N^yXXX]]m۶"B&E8?~^aiGIAZ|z kkz353NuFNiMhiBF5tg;mStGfԞhbS<7`rA(.6p`WcTDZ[cǩDO M{!oSNʭ> ">$_Z'ĆGၩK;T9VTTt~Bcn~V7Qqq|9f LQbZ$3ƴ^njon"Ծ'K}UoreP4CM9ejD-}bjp%tHe'=dĺg&*CzIS7she qDDtJ*9:K()qlWfE*̞=nH04Ró+At#/*E@ȓYzLhk-Уg'#hΗ_CgcQefRbzDo݉aш ź>h/)wF/4~qZc ýq;o悿%tCd2d(8RVłJpt3!~| FdffbϞ=@)I&i,ajG6I28WC)+6?Oo|+m1Z)_xMؔ׀ܗ$_Q hhhH''Pdz- %}y!\HnAynkJQVח0(AhkטD 6\p$AR #zIqg{W;.U<*/yw{CGG9ivakkkkkkkkKjyWH [\2;ы?IW5[D:$&^R{ە[ rYQw6Y5(I)`#mMTDL;6DN6< 9^-mŘ wTcD$J[ъhWT$%%H<)#ᔘ>5!tS2dyrCS`P|a-,pHWD":k!ҡ-G㍝:E./Pܖ>Cb珴C}MufU5͍19%$.ޑR#  Zfƣ"'*+L:%uEKxz{ ql?L鏁s=i&#O'px֬Y;]cccjv߆8ű15cXpߍ &7rW3c}ͭ-{'괭r`Ng}^˄|o$(/^` !XXƱ HrM-xW +WrJ Ń|1u^ Q%(2k-pX m_#q*)XLAH)9nRZ+h~z~D]$5ߞ5Y#wiN+YB(B2G14h{uPɓ'M. 1$PFmMP&E5h-C]jl:׀LZ-uiwsL1wI M5HGT@në 6} w| uӳyt2q ]%gLJen ((7yYpVXad N>HmQA'%.H\sK8;F`y*hK9s?<{L;d~룊iO=1rV,C_"]Qڌ){imm7G* 4FìG)&̀u+ѣk!H=[E'Uy.ܴ%{n\ wYd" n`&wϐLCIs-rFV4c[IE_`@# 3ukȘ~H7c%^q*<ٛ0 Йm }]U|Y Gaa!nM F|?3%o-ZiM3{ RTci ?S`}3Sߪ|'(MqmɲxqZg8qq$&]Iiҙ67i6g-˒emDAAw "eSH=Ž{}xA|#GtN`H:k? {LR^g6Pg7he###_&'X3xpxII>gR55) 6_%bBA%/@">t΂lgNTK n_]=fkt(rގ53TlM˛xP/)CchPrIH2h+.Xc,(ؙd]T]mz3G#F.%}s98ي, >)dg~ٌ˝l??,){qgO?g:z|cGqusr`⃷oӏ~YgҹucQ""f6pd05L~{=yVp43PFlMl9s^y}%3ë㷭qCZdY1ϟۅ{NnDW>5X2ax'gFtD/7pm~bSXP wtldԗIK>:D1FQ!J0rӤР$9. B?=XgԾK03@Y(7_ye4ۂMƠAقy=ܱQD^F;{ N ͨ29zfHGtL$Ř]p3Ғ`Ť'F #hq )Ž,NyHJK>,?WKOé6F'ၒouj<##CIqF^k^MI଄M6Ig)+~K?4Lj0UwIIvL?1JC+:Ѓ)K3h:>f{bR(a2!Xư#a2(X8ۣC.Rqy15o;Wq~g\_SOY韖ɦ\ i:W?O~rQoH*A@A@,l:ԓ>RHi?ߋ;g%/ab$W<$x-F|ϻ.=F"?|5 1e4ӬбO\nxiCNT8轛̰c>2<ĤSU<3:`LK:>Β6Φ`-n6UݸKKQ?h7{ߤyQѸbrhz. kN/O{D7\`T 8! 'ɍab=jJi<=H݄cD$B=^is% A>TGᖂ Qm93ڋd@-YgCepߍ$܆Q l-Bfazi(LHhT`&e_@[K+OVcq& o:5˷K<{$D3XZHr(ް?93.%h#,7<0q`H%`7=<.7]1!]} lI Cή⋿@c_G2zDp?2 7dH./NƩ:mSe"10e6 Xgx;f'`:A(֪A]7؅8E8hCXU]jL+!833EMLp;2#>+^px|~uͩ f=F]LU` Ewtعs;p}۶mSfc|\7gLs342LW'j??fe*(5_FchpO"AQ 3N3իGMNbcf 'Iv/A,epk,dP}'F ~L6 }$aޢXE&LF$1W>fB{xӾߢ'ZK,#\1%sTFdt/dٌȈDimA ;-ѓyNVёq*EQ3>T+?6򏾅'6f%g H,OtX*w%  0@?_|Eujz/GUI=صHJ>rrFK-/^/{q}Ώ!g4ȵ3u3ONu4 $QؐOYq*mC}Ȏ(unqjn+Wԙh^w.|;P@77v"0%}`$h$lv[" ȁ"ѶZ$|}_{ܽ%,+"H,_yIE[A@A@V<gkFt ˎU?؇"LWo + EA`!fO YʻY^LtnV"g Ϗ(._ $b8I20<[ D7Pb6!^??yzK3;'g48[`?0xl>tQuv'y ${s2fy(&+fy}cH>:ܞ`U9&&d{yZThh­ \ [#̍lSei;NZFH#G\pc})`p0?viҡс,X^(t??<)mNy8P;=#l~c^x$ 9"䄌Dt5 tH; j=G$ qWy*kZhme '&H\"HN9H"Eiii؝Y4k\^*".#o`sh?g*x>2c[#!9 }-pgO_#ҩv$wG}ܪ+e }P([V,M;&oft`3{ 7"vH,/$ay܍  @'pj?q-t{/Lbn2`[[騦DyV<4;c3k=|l_|p{̛o֤36Hּ1-XgtÖvnFH Ʉ2 A5,40SSy1hf{[2] Ӻp 1^^yT ε8Mϑc-fHawYػ\j^h5RLR~t;:Q%'bcf'{\H!"e8xЎ}"\:&h:HY&]i[T`Kq=I&d_R뇏%H*#MH"FHn#,;BQQhUmpz`H._3!3VĦ8%' 999Cյ ܫfhr7ɰE_566=>G⁞G){"hF6p_@co›]ҡ4j9W?Fs1x p6NuC.vrsF݊(P\m$3("It3K@mndSic{gU6:pj}ai!&#ExMD0 S6pW8y5gN5drhMr9Dve%M $g"UTT`߾}ʿE]J;[\DDЀ6mG?YɃu%PL 6ej*CE$$-S;v>sdzR dpKV)?TL!3Hz䊂   `\~Jȶ5 hr_mvtBӫir_<} Zba`eH8^qZ>nĮXJĹ~^ZεBH" 2U̸g

`p؁Q ن1T\Ji$R]%ꁽT:R]@~&+=@2q9JKKUQc0+@\:{z4>ujdYBO;wsR6 A]?;#hL+j*unWm>쨚H ?= ",Fu?~8s_'#.&`8pLnN9v9$I(Eqb"DL,1@Zy@+Sg3<@} 474`0nVEnig:>>^c:|FLns͘gVZl&U7n܈GRQ-|u 6:J~"{cLπݣDN2K'ϘA:g3U   ~0Jy4y6|(~SLK"p0!0j!8[]<+{h-p hwyv&l*\1!%冀6Ø֗N1f9@ve$j&6#= }{Yݠe:_ zH[dVCe)O~ﯬ ;gST|"y< 4~&}Z9&}hfS7(2A-fmplkeөAO{;ؾ7rݠEnt$oy(^Ԁ7̦Lz;=ү/1X+j2?sD'/ނt\G @'8zT83&T L0\NHr+&5$ɂ(JPd$0m%r^ ,Yifact9%}8{qkBDUVE8~ yZhA3F3$Q6B"1?ECO|I䝱~]4\=H<\cC6T:x(WA@A@X@ ϲ|-xqʑ÷yEͶ%,n X.M }%ghxt]-`ho4v n_ ^ҿ-3 x7wd=Yq2:}3[pˆAV6]IV׫Mgedܚ˥Tgq0]5)e9r.ȝܾ>4x2N@LB6V+pqLB1˱0l٢ 7xVx嗕/ϔg#wߡC]NIǦ`"tUv .reeejΗuhOj] l,]O6BD@{^Ow>dOіaXi   ,,Z5{rF?=ـ_V6)k7ɢv|K}x# x}0sLHgyĹaZ0!zL G`jTJņB,`VfUZ sx( &E[In0#, ~WYs~dz"KQ I#,wEЈ.`~á28ˑI>b6#޽{rBWW˳tg0lzx#CxBA@A@XRlFB8<~ڛp5ᕳWD>G4gHz[=si>J|zM/l8]SSfmqqqpk+M:3?m)b2H-g -Oux̏ FwT;]c{:toǛ *7& 3Z_H2/6'ВHS10Ypg\ ۷oj32]`L׭[M} 7ˈU:Gc@"rjXZ6]bB*''G6_H9bހu(k " 2  JB,{kpՂ[74o=SÇKD>- F)Xػv xa2Ɵݶx[5ks| g ZSxq5z45Us #N`-߂ ?Z w2I%WSC(H=id, W Z&DGwY<9̛9剘0`rq0 8g,h$k׮ {.N |JbNOc' qh OhڥC`!3Ä/ScrS!Hm=5]trLA@A@A`#i2bJu[u-:t#Y_v R3S1֐Gx <ѐXsM4IUKc0%9{/-# bN/ toDP #+琱2e+ 7š'Έ,]ōknnVL0!3Gඡ^N46Ֆyi-'ep5 >NRK|]PRR !pi76ejX Ȧ_SƎ<;rq2G^vsODᆀ#A@A@A` "R <#g-&<‹ٻ/gjuxtj|ngyP,;y2_*GUSGq ey i}`_)ynK3.y59p99=W3kutk рňQ]?]hClb[qOLf%#&ʿCdgg1bBQ80zcu]ǡix{M''UVۇkE5eVnBgE%RdR 4(֌R M({ro`E̤qosgh8 Qx*l 6&Nm$DaM{ZlfhiAaZ`N i}X:‹uő#G† IjmAcL0l޼Ye+}ZK"#66 _&xL>hY g.|jk1d{ #3!1!1!r%f =& $1qN !]׋SU+?ޠG\\_=ϊ1Q`!#/]57\H`f&oaܧpM{Ĩk#[p<'ڵKe+hw?6p`;vlӧ>vc |+k^1Ԁw2<I5$^cftCQE|je4E %q"f!$V*uZsuчIA@A@A ,`锔={{qʫPS4QݘǼB {\ca~$Zgԃ v/dL"E4pf-8ѣʇ?bL_,B6bf% ɤ;b‚=tX,p`AͳmۦHxݮʳ3Z9Α Tq ,mye2QnO"$`?g$9l=<1)/n+SDCzi*t@Blթ|&>X#p:t7*gU9 }KI&^".=0Ijժ6iuMvwto ֦ơ") o[g׮G.)"WI\5rA`E 2`4P3D4⧰s@Lȝ'NØ8QM6m~),, n/&ehh111h&i/Za*T;lU>Oߛ|_"Y %6T6u xlr[B4im}ӄtOtڂ   0'p]]] gN|䕆Nvg`| ` r%s{ I,sH2OӂZqyQZ@* DJoXg؞ܝ߯X2f3$$$zLY򨶶Ve2h; :sua0QT2L:z xwayHH&,ܐBkáf4<ږe$뗾oڱ-ۚ=m_xF=~ZK,>^l31=   &iM7݄iNܕ_uMY0x DpzI%kӌhkF|a&G`,<\d3>yDϫ*N;#vXM#!z粏eAzl&&gϰ?Cѵ'fٷ倘H8s wڵkQ\\ U AJj -uq0h* 5i16KF|KM Ir# Fs*%_8Usm=:l==}`k tr%A@A@A@X8 x+֯vHoz|- 1 frC@|$'sAi~ʰk҇O!jO#387׋Qe;DBBn5̾le0{iT!ķ3r )~T*_d4,&3ǝ9@"5ۿrJW9\R Ìop !¥'B0,0R  !PL.KrczdZjx^9/~p9Չ@,enOI wa9Iӵ:#3nVKn[]j}uՇS,X Y2 Cv1^4C {jw[٘=0/%!3#5   @(ayVάx$c$ C~!+^l¯NGϡ4)\G6 1$$BƐ]D2OBeH.qIbDoS?^8j2n=y$I&& NƄ}q/ݻUI'տ\@l`` Q|^bcc㖮Εd$}U@Z#>>^yApCWc #v| QI+7Z !#t{09DbQax`b߿m/0_ox{ރz ͝h<hy2㋯3񁵹0C!GE* yb@r,>0KzHfU H|6mDAY2~A/g-[(AeٛaEáf4< t^i4V`a&x8@*U\caLqkx:i(,,TDŰ^>ČA> є13DYqՆ;Mp733,66] I$=QVUS``8NeuxHAh/v{\z4x7Ha\ÙF~,vyf?0y!L:B!  W8!I92hV]>֭[*Jhh%OB@b;lT5Ϊf(( #KK<K)I^$%%g/tL+&FFFHO}ydOKKp[oK f"(+&qnAJuظq"=Uc/aܢ93^2ar]ߞ;gy|4ʫԋrae ND5B|gggaoou#CNhXQܛt!Ch9i@Cdd:/B:,~H A@A@A D\| ;ڪNFstE__d>]/υ,?]sr$ʱ3H_Asg;ԃ-ѰGܩG; y;VV3y(AII+*.TY 3ODh5 u13qyG'X{0{al1<?vp1eu$ЬYKZ,WȇUUU {FOajc#TEZ?SsMY@xyЉ^.{<#0va0" o\'NP<@i&G3آnmHvFڗH'e444}MX||v[c~jޚp /696d>`a4Š1)wܩ&0Q# w2#m'+i qBBte]ͪm̩w]n*vgrLp/Qco`1\ê(f,xV>?=LKǓ妞{Ky!:%3>>2222&: Yca:b\XhGqj"KiN9|8㓵sJǁs +X1N% Ѡ"'{ loV~ˠj>w5du4ј[ drƵT !o^J i\OzA506:""=#A}޸gb0Ie]7Aa>s%ϊ[)`2a]D:v"@`r ^vߒˈm16KjH'*ip~ ~?Δ0Z   \!W+۫n`bf=xx)J<Įv\rsC@2OBb0j0Iw &xl``G t;. qy1 _ eB=ش1S^ǚ9"FEEEj3/^@BN-4 |Jy(ydP[A-is[8:2V\I9rD>sO! ݏ;L&#!PPgi!#.ǙNR^!ٜ$:&O|"IzVvU6E5F/'Yz|Yt .Cg?*vz&>H(--^'~|,+^4 4NPz vd%#矖k+/GIe>H#1>-TՈq_0XL9G5_J+NʢЎc.B:\\RXA@A@Pǰ ϊSzf-`Gn¯HJ LJ맱f}`].-]HJ ,Cd˫|O9HO>gp\Jnh&3AǍfF( Lk*!>9wA ~x-&0U&c[IZijID#400/&ϥevC9m*gW,8:`9&8q^ $-KFeHN !B1poqQ`nL]EAAlAz9i8S=Q !?Ƃr^a`ڹDU72>g ? K<0!o"9uݽ0"'2|; Y%Yf He,.u11 R/.\3 _iA2jžaypXv4JA@A@& 8NuTkgh͉&|6v`s>_kVn8)mX\$dqlMIМBsfD׫cc$rTt` z: bDf^6\}, Y([ƺ5$oX^+ ;[-64kH$rE(Yώ 1Vee`ճk]$33S2cwOxS6m -x# Rm%,qƲ?fy.wPK0I,t;4IwCTos")!3ZlP,*`/ܶw")$ܱ   ̧|Q{Ass2Bl=|  8N:ϞwCiR >H3?>ɶ|>#?a<p+7VaM6;);Fa˰Bo"dzvy[Q")BLZ6|Y LΨT{Z|T3xL-YTC+0>i1#aYIB*o{3plذ9Y9MQ_ق2tWWfwxrz(Vk|8\w~nkkivcܢaA@A@A@XNTTT,³e^g}V8sL{?>qܱ:Xr@ +P]]A`͚5G@ F 6~'u>E¦hdߕJ z>hp`@!$]Х%c u?) ic^/ںՇ^ԟBmk|djƘw5m& B6A@A@A@&c02 vZ~hB*i|*aIvZӮ&/ k7CS58ڦ.5k3LQ1j+Pӡk\2mnvуfZxك>xD+b6!#lLp tސ  U!1& jF8sfJ5"F6ƿDe>Py.l->hrAr)X>pرc-f+9Qv#htƁ o`` ĥǠ|tU'ڂSyZ&p"0L8\L,,nW]7>;xiʪ#ꦫ\xӅ{"Qo!3u^TObwUn!VGdYܭEc{7(k8A3d +%Dd`mր?|';sq~8XrA@A@A@;| eeeGss3-=>rqcǗ_şp wg䗖Jy$'S2I p:xgIL&Sа=:@xfFZ=G D4g],3ᡵd8((3HO;$ygOcuѹ!#ŘCq"}V{%u>j}$/LCs~dԲ<ݧ$H։a,8&Pu~ H%>~Fy$xŤ[M={ [n="A@A@+F`eFFZSi5Fˁ ~oăՍHPERo?xKD\1 U9#$Ik tSVFQ.^6YŹ5a6!_Ugj9J =$C"{ =O=erӓ?$C6 =쥶T]ŠDGObƍȣ+B:SoH[A@A@A`#k. SuN{:r=3W^=zIUӜa&_ A̓  @wuua޽'CN&c|?CvL.%XdH+I^.ķhp.Ib5T:Yw͟:T73Og-t# 9^ocy iY Yɔ@DC|e茎ѣ$  aA@A@A@Z|Ltt4xȍ`8+S GV[ ^]ѶH"+. $kDhX8#N%zx^TUUap xK͂   b|jŶmʑLOa9|Ҥe>Ȇ$F=]?rF"4 XTWW^wbԏZϵb8I ٸ y۲aYb#6A6  RxǂV˄`OO}KJJBrr22>YI^qާ,h#eg|&sF\'Z\L%6xN &؏a``@eyٳgq)Ֆo8#6$PTTь/!|ZA@A@Bra#[͑ANchll-y{܀r(9|_w ) /Cg>=#8-Եk 1bcǎьT󑛒G(SMp\ڎIFJ2)gSNrEʴX|df_#%x$:g {fp[`p !©7-   pU͆rYFxC?@_zy}}Xi;}xֶ,j ޿.@4¹Rc![ TVVgAܹ:|&sQOOg5B%A_7aY%i1^ ߵXKkE3HmՓWIkr{UP^b$=F2C mݨSY AkYsXIy.^[-bLr?J'Fkk+>qʠ`ra˖-*zVR9 O#%z(--U 111j_#77WI+t8s:7j2!W,SN!mA@A@A2ݻ҂f| Eu+Z18X82.n+zhihU6a׊o;Vv}^º]a{<þ v֭[ P6h?|[h7ȸoAYA!$̟yn 01B,^~8tЎVn9=4շvH\Ha13{,%> BFe/PQf2N9r;v(28XIP*L#8CXi٪|{GWbejpv`7*h6栚w D&e2    ,X1s3x|<Ԥf0]1A%ReKTo8v%v<$_v4v,K eɖ%RU(${``gx V`tq{)g^4qkONzwQ;k,qhL8lhAt>cUeu׫S׏&ҁw T5/8p`j!gmiX C C$C 9Y0D҇I{^Z[Zh2>ZffHk|+2x&cg}UR^Z;U9  *\œϽj)nK;Hg   TXj1y.o{np;:K'!|,V㣫 (L[=`yy#HJߦu PTHPzccc[z饗&. :g$QAz3aMBɇT4CcI ~$1$F<OtGr{sE04v`xl⒉g?G+ylCz ,<>L]񍢲0Gy&8(,,TdqzC23Gh LH{7H# ƍս&'tbgH>$C4>   b\<6ޕR𕝅PDĦT5idkhU>bMbӡV4n6ss_ Oai׊7xK29;8jȅ<7k:eKw`;ۋ\PÏ3^XarQX"6Þbv1^ܹ׾>9ȯ se:i.I,&Fw o5|HN-v{lI PE/4v{`$! ^GFf4 -#kJsҐsCOv"vڥb1XVWWaĉXֈ7dh pw2EHpba۶m.t}\o׶A@A@A`^+ g;wT\s}oKdO/>|7E@l'kIL8Ӫj=,s]_UHihEŗ -a"=mF6Lkܥ m4Ww]8zPy3T4tF7^"F7ld鮚 3EYd$M2Vg׎&~ԜKH$٣XjgȅE,tP0/L=ڇ!mũXmx3#?= /~{Ő$81 =eL`3roVL&pbL옖GtƧ"cA@A@A Zھv2MlkkÛ0z'kW~wL<>nm?޵{I׫"͸XI\|X3.N+N ]^~_f$e_&)lۃ/Aӳ{56b,(^ʘGw$xåwł;v2&8q'nsrb1NZs!IA@A@n1.~RSSI_7"$61xSXljx"OP ͘7d\\Z-G!9kϋ|/i~0tHz3r㤥 m,2њ?EkmfF&h#gn̟"*37Dn{#c+Gxb9}Y##[#ד|9 M%X>AIZ+O<=igۙKƶ )箆s`S$Awn*T.ۧ GIDϫhDHh|*2&A@A@A@*3ym+|{>d 5$31/.w߽Jc4&ϝj]>ý=+f~?F#&4"? $N2iIU!u0YCzs1hlC{(t!ER˹G@ԓ/'I!_0+Q'bM> #n$d4YnGA}bw5YYY*hcZ~ rYH]:A@A@"0Ȋ67@eАzeeeS7%;R[Ϗ{uUPjZHxIuV{=8e_8J[C&SȋyA@MEϞ=|d{=oP24тP\>rVfa֡p}L95oCО@|VGO#M^''G3U!H5bƦf`e E.ń'H×>HNjEq`A@A@A@C#HOg{ ݩXl(Cu ǎF~wf!;Q8~v`<pg+chy4g{Ḱ[+nl r׬Q#ibpg馛TdCcc#p ]1XL/N%!o-+dR<ĥ >g5E|SТ|$h?P{@IDATzvpky;\("zp;8'HpCmJl@$i'[1r 7uMvLn$YHc#WA@A@A ਆ,{(P+iaqBwWÚ=m~sY Ul cH[cpt " R X:G^1%kԒNك8'a#>7/e\4á IѸxyݭ|bXpʗA̟:7 8̴N TozKr)($Ȳn;R=I@t '0:2A'5aEMy6Mdv@_>>^ 1e8 @Zˣ!ȘA@A@Ah2$\Q"P"r%WpV 0>` YU)h"L8+WM+"`MZn-Z}~mtT]3NQZ/6ī }) vTVaS T׎1I?,-x#^QH" FҳEPA@A@A2$WbpMIh4I4'7@RRH<5s ={6ǣsď 3LD<Ѣ5i4q8BѣJ #Bg Y y*ւ#֯] n"xm!gɀMMH y뫤kB UE^)_ȝ7 pM]%1;,%1 Cm Mcg0 3}l;sSy5d'ڐGwW3Rg씣F}A"@A!fDi~ 51-ޯ7t6   D3ɐtp8\Չ\|?.iQYY:ߏiZ1DM]))'֮@q;,ؘ"L&1;fx<^X( $;)[ XOfb9ۀ0a) wv'u)3}SCޑ zė`N0aigpu{q7?R 7`ok瑕N캳|5/i~#[z=@Ϸة3{'cĩ 9gBAz, DevSy25-hZ>mU[B:Ҏ   ,8Z|/v`?ivRTCΙzgCiI Z <@R@_wF\M5՛gpoA(/GW!FMLqqxsq0 5VQNo:x^cA] $:aPJWo ߎG潡h&'qű(\5G +ZQ!~`Ͳ 48=}k8# y.tu}!{3#>+lJ6)"z٩!oָW)5"o)OQd 9ŀ]NHדf ӫr9Z~z˭8{ ht`eV&&=$O':6}&V`Aj,c{AÏ;a/ B!B`ݍ?l-/u6]P*T1fuXI)} yzʔl%ⴅ̵H3% syDav7az*S׸Ʌ fzW:t -pL8ʢ*!fLʖ%b$]]|8]96R΁ %`}E! ⱦ,'i#?Z3Hh|*2&A@A@A@!d˻d$-)=OBxWoi~h 1:R|<O.lȐK(pSDd`n+,:U&? ?IL> W<;pPOݐ3CI3Yd`ȇ.`? 2老iA֮¾c]E~kFHB=GpB]@8{[c(Z4IcUFQWpn2^6!`6"&΢"Tfn}HK+= 7I;U1 R:)-n8Ht"‚G1+:i:s>ieY ]ΧG6 IXzk酝SXDGYyy>ZĉKɢF@HEd   pEd$L۸ibݴ?I ﺰF(].ڱ?$s4G I@8Qp9x-IfT}@A-R/FĖpɫI`$wa?-uУN~*;ūnv vũ2π HNh(W<4RɌ ܿ^ Auj"vk,$(f:L 0_n (z=4 0555jE0h&L:h:lO/חFh-dCrҷ   ,iaqa5)h8/3 @hqMDO>`_@TT[6sMfh.~$"d@o#iUb-ӂ݈6yIq@MzC#cY/"Lz~HFvp>cgO7^UeV> c}&'c  +1޵%d@=8NP)r%DK4)D"r 5'm/@;/i:Hz^`Np{}8ZD 8vVذ.,_|^NpFNxDrAxIïEk!I8A@A@A`wTjÚ'=yC @{rס.\AjHk'uYȜHR@|'p86ŊrQ`!Y~&"B HzH:ff;mF&|҄[1iĻQ#aBƋ/, xx<ٳG=G }%y$NzNE-92_UGRd|AQ&&8vء E8<=~K(: k+EܝmtSI[-覀LבC$BBy m_]_kġ&V4 806A\~`ᛟ9 "N<ƴ$'-F,tƧ"cA@A@kFϠO <XO 3#i?J. \`1LFc#esvijga=`QC`UQy i `6@,iIPA8\wP +$ /2z^/BeAZ㾇>χ^Ѻ֫TK̂ vEhRW^^"teWVehooG| M/t)7J> Blܸ1d 6L ~^鉨L8xy6'RXip#}{mV],D$ywjX)d9&z۫h3ٖ >81`"~D{Y·Pکdأahdq(OE1 .S<6?:nG"N<DOkQЀ[N/vX}6EyI 5X4@ C4<   \7ll|3_ pVƑ3)5_//uAܴz;:~hyϪ2^@G/K*TC;H gսNEY-B;'wF2^׌/oE2Q {QeʹlH&fX:#%#cXǶ~z%4>.wHn⨉ s;}SӌJ Pdш4ɳDo^/+Rhb9ws/~\-m\z( Ex(>`{LJOT[Gb][Rkh2>Z>"}? J:ƐD'gEyF(z"'UD_4/ȓe>z8YU0C=}6Tu!H_   w'_İ%QsX>d\=${TNFp%^2^$뵅E2^_E}$P.e,KtqҢ˵ˢuqq1E!">ta2N5|\^;VAM8LxΘ8ؾ)K_Ob$=>#&J wbωZByLȐ݃hKPYT8%OIG"B.+;/lY-nԯADk!]>x}e1H/-gF|~iX z'O!u0dm`7xh 639%`M=o`I'Y9׎! ֔#UVrU%D9|6Eh|-}H@v=(Ě14"MG?4̇2xKv(@Y:K Gy|Μ?vA[oXEG(GtzKeb$='9pZ:I=<륲0G BڿPp#i#{aLrw"!I~=0p+{ݔ4"BDPf$2:XRGBF:̠xTfrR3p-GWW2Th%-D˗i>fˤ{kpG>`w/L !# !C4d,  2G p'DVl%y! ؞qƨxIfH)EzC-DI)δ9S !i`ipC4'& $O6ݬd>1:*s Ve!7'V5uHH@~^?ܩ"T$C{Ąs^FʅLTPF=Wl戦IT~3h{n"2.NHLȈ19-b_|%|DƄ".gk2>ZyKjQDe!*+!QPPʬdt6שM aAlQhyG''!-ÿvFE<8p`Q:I"4d,  2E5;d}t ymrҒaX_ ^NI'Ց4)6,*DՈ[vFX&ᥗ^B\\N)6]OwKqKfb 0IzϽ[ i \g1bmY .DAmxU8O¸'T퇐Dd<  F@Q?SQ*\ϳCG 7B@G ^/I(wŁ~D#j[1Dq{>n("MGDhXӚ=u5l٩]T[`͓_:EVg 0 ȟ,# ηv]ŇA7JFN*ο>%ӉG*ٜ:xLkr6S+6[lS2P$\LM"zF·4+F֧j` `6o^B45YfdzLq3ՑptLcɾk>'.ş^h2JKKCzz:Drrue?t"A@A@sW܏;RO`qۑO7?Gb?&?x?3R7XoCޞ3^kO(Mb]?sd I7t!iX#<)ST:h7H*sp$.䘤,5#i|{}j[:qgF+ɃaEna`mРɄIzZ3]O>-[LpQxƑ!ZĚK,S50:lSgeT) ϸ`jax,9# -D˯;1m 7 /N1$)HCIA>_:GhL^Nw@F,GIo4pGL'#LyHՀ_QSA&TC+EbzE~&֖$=MH_ؐ"J~ D\[{/8F=1oE+/º|QnޙQ5nE߸B2L#v&!ȸA@A@Esą?9w=p2LFx2mQƌIII!/2_s 0MSeZ=(?n$} %Ƙbut96'sL$bRtȆދI+KSL^=`%(MB:D郑a    !Q{<=E4E8mvTR͌|[oR&|L,9)I(?Կ "Մ 1( !y|lUkN*yم{/4i-n%t"{t{ yY#Vf '|.HL^TdKpt wV,Ǥ'&>G%p{7,h$>iL*ڵ N^^^Q Eq=d'`˘s`ҁ^{5Uc|衇T{~LR2~|1c%.0t%BO:3t^Y ٦|$ғ^ݜe :<ꂣ)V,3l + ϖ=3^A@!Z::q\=~>mWG}hG.UU+yUZ"|'^~]&"ïEk!I8A@A@E@.[hk@)(lېV1 8NF݇Q69]I!tMCR%ڥ`'_Zʋ7,;b6/vRԿi7kZ`"ͱ|-ψ^76wHۭx'd\?p-@R|7QBI$1Pލŵo$/eyY$D9IGFFiFOOǝw D`諪A8%nݺ)&tׯF8EKNk֬/_eLުUTɉFpߣ'iϓIg|Uo~EBЭު>W8:C#^JJJFL8y^G56Wl bD݃!BIP}$8bf1bK~%?|^䉥H2Z] p7h̎A7< ŦLMMUkK Hk 4hoUl<D$L%B| 1_ϽUWHBZA@A@6Szw12>ӴX FTZU]Yiy=|D:>8%t=J!BHYc\[!n@;ש Umg77>|0YZJ f;wc "wLno#i&:w&h`$^ O{(;`Ru"ݙfҀ;h'9ۑpE9\R-31眮o sss_I/:COݯL0\!Zgy&Q]LX7l0`|8 -_kF39ب`|t`\2&MN'^&('Gvm8v‡UTTg>ausS>~cԌ{."$ZQMDLGD0T0$h$wőaܕ&Quqr>;^?~c=x/Wpddw=UH>gf眴[B:DcAA@A@X2hɗ<KIC.˱[;1%'1gSȸ%+ipW}r @.u__-Rel/Ҋg1`gPy6vtw?Ѝر>>^l}i_(cY*&^yEXX#GTY\\ܼJ񘎞ko硧?rC1Q"$GDXFN HZjÃIA $nOMUx*9$IL 0*R&  pϡ >f(dұ_ɓO)-rz0Ldm$Ecސnzjm^$qs7LV7f2 K@4e@5R/ζ [‚I2ݶm2empz|N/6d@~~vf}Ig^$!J  A`w04!}G"RwÜhQtK툜)3ಅǁe>30Pz*>{JiiiSVHL<\NNV#7rvuʀeāϴߏ7~pmx>|šB2Lb/.D8ieNCgarsU>qڍ[ҥ^hĴX#BB&0d($Ndi^foVE0tUl̉t`}6}m|u4xl\ Oy }C*R%8q=$% )~bbm( jSQ|})kAߏGj^c+WC K qJ ?E.ԶtlK%gSC(͞mVKxSsy':jg2؇%6mihhP}jL&$/HsڮuU?cc:]3i ^`*<g89sgϞUN~% "81 ia |aFq㽲LXu u|H#)w*YϦi~ |~z^t>   h=̡֮Qv}e_! VJ8jA"i<ٔV'v÷o_w;xL >SAE,ɝ'+RۨUH%K@7m̦h+ ADOZtŽ-#n9=DZJ(GB'乱]dd!IB2 IJEH$\HΙ(6ufRy:'MR98aݺuJ"IN,ć$Arǹs甔RI|(*mb#f$- H|G7:Y0ՋW_5"B x+)ŕ4i- OE$  #$]pţ9qϴg>ɴakv)㰤+A@" 秫ވU2wS i 6ѡ<&f ȥFWošoׇO~ <=pAFeӒPJ sQN:$I3 өm8nXf߾} a|J P rH<8eSK4h+oѣ$<"0"ie,H6⩆^cg"}Vے,ؽV&dŚ4i-yT4P$  3"sqc<[j 26&2U ¢Ҍ H p8cRS.窣s̉kZS`aȃ%NNpg RDP&a>gpٌI&4[ QjGӀ[T庲)$/vk̍`)G-8IָnYF/jL: .cB~f*3.}l+szÊXرc\xwTΤʕ+aׂٔF001?4krIs6(iHA0N<~FV!DH5Ս!0N)$9j| wL‚$MW@sdܿ iv[54i-ƩOE$  [ԻgPyA=V=ZIZO\~6zZΤe?4 Ve'Dx]|#w$4D#އl!Ŀt?ǹIm€ 8ȉ F9!4iFwy0p ټ#YVzmWy۪RܶvǏG|LhI&b={=G\.9K"đ`CݻU9&3'R'''OElڴIA Zd|zmmH/F5bb,HA=+ĉf ע嵐$d  #p:l=M=mdQ[Vm@9M[p ᩾Ict:w@IDAT!p|j|zx0"f9\b WVn;xicʈkyfT0Irtf:套ArkD4?~29hdlV˔wGz2L5Mf=̴md4Y(ώEɏ$ܶ@5S;0ȇ7i'ˬCgGzM]hTMȯ\DZgcN#↓|R'm\k*g? 6&4';;I4i-&9D@9lZ-&z Gއ7ɧ!9@QaA 0 IDܱv%>njKf 8U!"To~:Xc;w\s߿o>s$A@A@Ab.=:ƍ!Y dhŊRM%Ř"ׇ~hZZڡ@vJwmk.Օ|n.[~Z~AgA"WC=* ܆RU5;$/ h߫$>|/|&uR|z@mm"",bNhm S'.W 3͓81Vw(""HQD8pAh[֮]䗘d_4wa9--\_ڸv7uSp ?ta[_5ϯeEQQz ---ؾ};V^#G_8>σM<q-^xꩧA@A@XF8ԝC.:(x6u^Yv4jMf}7L$I t\b\! ޥͩZ-hkr%@@Df4*cGx`71M]^=8+.P9~""" L~7u(09Ox.F[nY(Z rIkJ s}T ů8zap0dInC^6سu>“F>E@ٶ6r>R_8|:ۆuMt,h PrZU0^f@Z/[q/!/)}E& ?PRR}kגz-U'RGA@A` rR?\N7r2&w=>Y,4qSnWb\| $sZ L$pi$*]\' sj7=?]3I2iŘgϴ )NX=׆њQ|4݄<ﰚdEEZ`gUG&AdV/'Ĥq MO axxmd|RJUUUJ ye0F5,%$A@ *iPrdaȓ 9tn$>5k`OƵe++Z؉.5i-a /">M k/>co(*H_A@MZtuڜ;G19D:ko.@krְD5͋WgΣ1Ծހ?̃ߋXo>Op2ɸPȾůceK]WJDjLo$0&`D=ED6 сX]0 "&&FPTlq9 TٗObp` N ws1 rjfd`3.?&HhYb" [7yMDËG੖>]bDI/Ex}}c1v*Myi7 |.۞{FKjvd}< o\r] A@A@G }3(t2/B:!4/bc귘M) = oCVt w7q_;"pI >z$ӘLJÝ!_ezMg=A _YT8{8+W"..񫮁a=|Ck`"Q 'N@WW8@RR͝9 u9=62Ju'ʿa&]#_mR-Bh2>ZnkD@8+6?w$GwEuRQJQr(+z%|f s\!\#JꫪKZ/++Set@A  %y,,}TՉ/1p ቉^.>&gW 7;hv!mEH/οTEVg $uu&#'THPZmHuizSzmx mɔd0}dNݏo$A}&d[thoo+cl,̆6kg Yߑ!j;5pJd%Mk/3z``@EGgTP2˷vv%9G?Л p B_ Fz 9+/׮? 0cX SЏ~[ǃy p[goH[[*q׺*9Kr@@H<ЮKZ] jkk/& @4 |X4+iuaKq XH.#0!19"+9E xV}nSȜVe2́>/dN8}\`e8TU_XfթT",Eh:U!;Y_p4 oDF <[z[d8f{7gZLy#բ!p8rqb;@TVwRHuY%˲q['}IIĉ$Nsˎٱ-ɒmJJDb'{wsfq ,9b;wf{yOAB8\*|?G`={WBCC֭[B$FKIKw_Μ'L<ߕL8D(YPdcp㡮~AJíc%:,'de5Ȋ*l*Dak@Hket ڔAY8D@(&sA@A`6 $`;^Fr5K+چRulm8EfɼL m"'3.%kߟʣaahddN@b8!|#(G;&Lb6͋OZ | f_׋E|&\̅q$B@ 㣕կ3u\(c!FY ,0a #:xMB:[x~l#>/\XSDA@F&!uyxoiKqpL [N2YQft1rhuZ;|'"+A{z׆ N>r+,8c80>7o[k>+G5fP  0ER5jm+Շ;JD!EB'DIdž 1cćC.p`g}'`*\L* pp8t$ЫWFeec:pȖ>\'Z-ZriB!űkr쩓Ʉ"x.^kpHO<xZiF(U8GD1;vQ b5pnCT =lcu}gPCQmZr89!~@&t862@Qi9I!ώ5*TrzW{!ʋk" R@ ^kl=2R8 qp0O4Mh*ʁdTߡgPцѨr\bZd6HklRc p)~_%}Yzzؿr{gd$m)" p8a?w;S^8+_²eXM"G-d`_`Y-LuZ+%t09HE3uvA Ž-^T(Ǯن7-(,Jr,HR(+ ?v_H+Ga"B}0jV6]Fy5lZ3)XC̺T^1/4^Gڢ<4lSG7=nkzl09J$FV /;lOo%Q $>y1 ,ϨB_WS޸k](sZǾ'uj\ Gqw^mÉNxQCSl7p/5q (Ο: 1G:^X˭3ir.}!iFi`$ΆZ{ M1+ eV* y)_غ aL@o0ߢ 07|oAI;^ 7n?A|Dnn.x'}ΝjsꫯN/b_K7,#=IsPa(hƒW`Ciuh(\"l ڙ|r_"֮]H믿^Օ_ 1 Ag+dছnRͦzM֟  ,L mD*hCTa3Vj9߄0y1lU`1IC3ͥ9j:8M)9ԟEB~|Sg`+' bH0QnjnSLtW7$ƔHÅ(Lyjޤ\ (LPG !?l\86lsMk}Q1}Ѵd&^f<319uZ9;3RHĚ>#!ݓabc!&""炀 @,PF=D,>r B/VC*', bGS r1<:T(x0_[>:Wݶ˿ly~a5w-Ǫ?[5V{c_[kܷ?Mhh;GQ}>;gĊ߄?چ[T;qM;@O_S5kV#h&e= _K/EC"YK/8 V3)D,ǑӐ&4Ht!L'D0FhS$/7G`o$am 4LJ j\׺rQPu{_]:ngpW$A~(3g"8 w"Ӻ}qivoGc頺sa1b[znGo#oeSaQ6\(A^4Lwݟ(KmU jǞ"f8a k BD>oJy#0)ճ&#'F5\#Vq=Y3ÏqhzPB8\WK4UDR)Y5ñSԠG  $e ﰪ[A֗M=8}G٦Tj$i5SO=h, H-[;_{(((HLJ}ȺF5;žnzq##&CxL+>$#ߩ0(-cdl$JVr&OFA@7: I/!xv.rFwaS[> +JQ T{1S"'Bzjh rjweکřWFE8܁Y|2 W@$!RT(T$s7deJ^VF1eUF%`sbݎ![JY_Lw]TmɇHPP9bb[4 CʻĪqMpFKR!bLQ6 X1R1MBHtL1ԷwR!AaD2"](QEFia:;jP!HHOw鄒α F&%G,s.1Yh ̤p-3ߚNyq/oR{&~5?x?tŅ# t;is;nmnxr>;[TO"Fy9uuqTk6OT?3{z۴O[رf|SNyհ{nCza* l'v`%Z-RذBIB*Pɪ\L&RL̋c֗SȬnZߟ!e 0Gcno>nJXbsAв(DR9yG|πbܔGCI!U!..}?CyT 'cӯOnن>t֬Ddzw_Y2)A@A` Ý<)hwv>iJV?S, Nr5!/F)+pΊxy"cݺuJ ϱY,\W{.>)D{rGq&p| l¹w抸(/{תϙB|G?8?_pI0A^9=8 tHkgt( 6ќA9X'fd=")o kH#H"KB4c XI̟qb?jD:$)vmvnB@SjLG()Qjը Wa׺uXgɓ';peȿ' ʛ,pcsbuD:(_}5(sW=Q6W"OO!IoG+'9 TB$m_:>XfG4YmQ^|ly_\ ä=8|}xv z|J#%S$V;j(dRj]߳uzdN({oᜇruw#)0zG4 k{7Ue^ly6d.':;(EcE sU2>KOGNtrH u #!놉H 4>ȓ͍Zu>Nl HGH2,"X^Zʱ!"&Z͹{TuİuovFXpG#?iOsdZ> ;HkeNDA@YF@S44L2p[;Z5E`P"=j?s+`d/`Ȇʻ a)d9&iO`t' ȥzӠUX?z3(*BGGBgoαF]0u-4fB#xxV2Ң>|¥Nk.ȏ `@N4wFA; hv;%6Y;BB@HzӡTMt8zQI*CAyf\֩|Rdɒ'Ce7c&/ZC>TH隆Dj+Kb^Gu%q {~־HN $H[F#{yP8|%тG1L"1 Z5Րa͊B8Uuc ʙp0OB=TGA8cQTXt& hj(™5>?yfL85#]n"axOS*W`ՀͧUy 7%̎>фtNJA`pD{z(6Ȳ'N"F`>O ]٥KVD}PyrLJ(B Sg~؉'\s 2`W#*<'t&u\(͛2+Yy}0&haK(y)K &4AkygsfzRD# 9!g@:2U+ӯ]lg~A= _ sM+|7 \kp===ȥ[*ÌKЮkA+3%}I- D) ~1>D:ϡ;)EDoD/(ECKc/ H8/54E?8Pfŵw9Q^%A K"9O&@-A`&}oċ}AgBm~,Fa$ ʺ238jZfu =4O%k`Oz[^ݴQձ{r{A`" _'_uI: IA`HO\wfa)4!u\X)')p:va#>@v8m*‰FDF>TeM\+Yl}_ߏʆ Hݮ,&6T,pvڹj ?w^:E>Ub/H"c"f`Q}5Z5S}gC;yy5) !0_B]XhzJU/:E{/y>ЎɠZl&2NNbX,wJ徏{gj6aEUy/ $~ qBt`GZ1%!:<אaGp2t>tK`W(D`b5`%^I+؝ɜ'3kӑHz9ՊGxlI"h\3 Vw9-Gyp*0sO>0/ ͬ=D=>"gD"dj4YסCtRI> !%.fk'xR#I J@f'z\߻ܺv@a} Eh/X*SV<{)+'qNJӭKP_sb; )Q^J[11k Ln;d!<Vi'a&O cϟRun/ZLF,h)BHt H&%@&PBM R'ر{e*hD֭Coo/F'RVV>x9?TG6>d݂ |2 #8707'@w !KF*(Cy>\?MyI"' :<"6burI4.ϙ^a!u?~r:7 k@O!=8lb 2}gK|]h5r\? &Ē:f|X[]N{fbr>VnF y&C~ H:BFٳgq$$ǏWĆ P__?  908\6Th056 p2Ӻ<wa>P @ Ps-H0Fй QQWWǂV\<8q4{ EH-YX)Oa G 3Kt+OaʉrOθI׮lĶuPCaF^|y {s+6@x{ޣ<&' |>D=ǀ_>Ѡ/rItRSB3G&ݰQ. }2]CHA@?N%qO(񿪌v+(\5N(ĕxISrh1ŧOM=`r0m0`rERDcuTvt~Wt ۆZ]ZbhмV9GpSOŚ*l,A ]^ WXS"V4 pN}Ziξ/ 4]Hfq?l9~0+7b-Q8l W6Cd`LA;K~RW,JdG"/qb/ّ6e ^fA<W0"4)2C,]:YQTY;]sy%\; 4Ϭ왑Dnb"{ `v"ψ\pG& T_YkꊐɲŚP -Sb$'"")O_~VބSDXg"N,Ϸc-8]9**@cYzI\{P5\@R奠0k}Ϟ+8*S>oWiDaBw5[`Xɹ(ɽ# f%?AK 8s!LN>=F8Ԩ^|ػwZ@r͉3y*ҝ dxelOn |f t+aշrgA@&A@rLT-x4\gqYxGu}0h,Blڴ a C>! *o;e6LZiξb_ÓW^+A2l#Btw gQcQ2  ^ cS5 |X|38\/D].ǔz ţo :W#]hHs#t2_O}Qx(}tTSk"JͅX8/{QdfD3W+gq%9؇D$D;8,$rQ,"t-[@IDATo$xӇ?׆m.=@X(b=W5ƽc/Esy2Y6?L2g?/}R$ڪzر׻ Hke6b C6iS^^"|>ryJVveҁm.Y?,ׯGcc#=fvQ̹bOA&? ך݂ZF+9O"dU276"ruu m$)=D >!/M(ؒrg~˾0r"YZrY|vB 6Xh֫\ўw\u0!#3`?&+w:i}_'f-B]e*2%jlVHb֫A[A`# H*IeY!Ο*)\ vΤC:uE yv3t|gXCxЉr< RL%FLk+y0WCO8.2( %v^ mmmjȡX F5L~s5L`q}~e-\]QtwR {p=}M^0J a;^Rri_fqQ=jQx[~T6):H1ZwtGuJ YJf c?qQ]轇 Ȼ3:}n"O!;)nOM5C˘B8Iv5, jq8oFUǹ\.I U:P׵0M'NPSܲe &#|ǝbB'?>+ɓjFHqr5%>٘{ S "&&(2q?Y  hnZQX3 ]y156NyAʳ= ػ:tgy")RY @Ii>bNEXr,(i,BÉ@b_PZ%5RlKY(^?"ZEՙGxu> ^c Àvx $fusvk;#UPq} އ  ,lZ"iͻ WD(1&h=±@QB v+`J*J @R(qߕ}YY䝩`Q9u.!ld'+͢a{Dl =EaOuк@&ɻ4Jr7Pb$NJİ< xZE!01tڸ [OP3RRܢ* }AgG9^/S[ Ab/]A+8{yհ #C8sL8hRc3al) IX_C^(_HNRr_W )MK2$utsrx HS^ [U!-xl8PC}?@b)*JP$! #]Km7{&In 2h?z-D "-3:OUs};˞~)Ph&g+$w=M$Σҫ>3hnP:j*-%]cYXE<{10|\WW>| ]|9c(IMLPBdLL8I5o-رcJ@ &5KC:aJޅ1f -5AaʏA gwu_9;uNM(["Bٛ%F>2DC<`v,y!^|OU8$sA+W?fg,|g.S/txהkV`v/--_u20$M1F1 D&0Dq7YMa%<šYpQ\?|STې/L>r S,BYAOsI@,J(N~eu(qVʃI Je$h 6F8RnX0!O3?=Amrhi)'QgD=NC5( K` uY\U0hdcÆ8=Y,d&曅kuZ;\5 @71‰JYHQ `tm i$ غ>Y3p90J"0%Addtuic2Tuu$GӢl@Zyτ@NNڛȑ#Ju֩}۶mSJW^yEMܘɅu} nǤUcp3{sRy&/xĤ{Ųh6B2{*=f5͓3lhu3իWcC3*/ n&5X{G*F.T<뮻N@!I<+V:yZȈܣpPܳq7z]u#Pfѡ;3E8uA@I[nUXbE>/)[%p9r ?|,3ChBPT)ä'8~ΉcԏI~V0D61zI@{jH$?@@nťLRHVR4UأP_Gp-q0D<'}*Q\ԼTȕ#ւW2?2Yr,  !7J R] ^dw֪9H#8L^Vy lyV/]===cN7XlhBқ۳C蚢_}RK #cAYDX4jR`#+":(e#B` `_ y\qxgT˭/ 9{a4g;oً:^3ADχܟFܲ}N~8 ZwL3}BUĽ1sȮW~vMn~oQǓ xlL6* pˆk&Khq`Mֶ\ycoRX8B|x뭷ܢɍ_~YgC1\T77aDrЯBx:F8COFaxF 0yLɝ`6H_MVʡA$Yl3Yf))ǘj0˜K!Qi:ϳ#m"SJnvR`5 wTu6cr|Z ;jjT >NGxavCg/|rg~G;PJs5ƥ~4mXNH51BƄ7lܠ?.H81h@A@:p8r]kUE.sˍ5FC_^|l%I0JWAy`ueמs<̼3of;ͩ+?0QރF?yq{6l%{nՎNE;]ۯכ|۲V͋"  lYш@(T ~)[U /{wR"a gy=Ǥs&81sW3a#&ˢڰ q[^q؞tu)ߣ5ְ p>heXb#:@FLG LE!kry$t1# 0ߠ4%w<j )yIC<}^XBN[?~[#(57׬7yXXg+D!I)R/P /8z~ꆫoMf 8G{|nkk@ȑ x\r]!aaQ}5Jo:~>XÇqGEƕ /0b='ck6rs_;;;U;7፨EMf1 (Ǘ=8~'l 78~EsrfQA@A@3;8+){9p"G3L6Q^ E|7U_F9XxkC.TH6XxDŽ_||/'3N&CUU} b4,3j?nzДZ9KorӋؘ^<(?5"Y\mr! x ϣg#GdBp؛"!xZoOUBK9l._9|5―L'Ra "+-״F0)38~'ќhcd q0w+A@A` ןQIwz;zFIg lLk)^8p@5NDuկyx50mx\_߮]u,ץ '&)N~5<ՅͧѴQs49M& *4u)\&ʷXc‰C@Hy'FH )€I/y%蚗:AO!rp'\bc&\%Nkt!"VTfg ƍUn MJToN(M |-7,Z\ެ= ǵemcul}vUk,*SwIxBhI) s'^=oyZ[۵ mF`"sg1c2Qym;wT\I>f¡&JeeĪ=UboP)"@6# 96fI$=o`/{gW}ZVX1 L:ZJ1z7v?4~H$"(Ug@G:ٟž@Z+6Hz\5dlD)XxPD i%m*zF6{y0JBMuljዴF iÁ vD6IDA@ABc?}~ vn+T"^[)R" ֵ ߯;t*+g*pFl yXjkkQpY deHy22‡A`ДZ9 S!ރV]Y@@rlRI_Y$g9>sNeO#dIOx4awc|ڵL$8 p,tYDv)rI\s-b}.klmǡN<6LB,[L-_y^A@A@2q2/83y$ ~8`3{ˠLjΥpE0Ml DDŽ Z˚)9bkUF"ZkhH"#4XpM'o E@$Dm 962 %DҗHYYzgr򇈇S$OpXQ+!-LF8z^DA@AD@k?%8z"#wbGu"@*@<9X88J'l٢ia &cab_I$} 2{YRBr}!#%ʅE6<$Ά0 z_W4O|O0;<$bV,nB Kq6_r   0D1Á`ZgVU*//]]]\)ҁF]By1i 4 DB22\E@I77{aȥ£V9L8)έ!cA@A@)"E79aǃs/*K/=;lH I<HzvpQ‰q0)VcI"xB]:ffF%wvs-VflZȮ'D>lsa2ǫGP L4,B8\=҃  L!" s>wC<G0Tɟ06"8† Tz9 ѣ,QC!9FHh6 xLMY1< α39[%NլȬ#%RD B:LyF#qOEA@A@lC`LG/ !T_B!KxF~zu]-y睨϶[PD҇)4"E=ԇYJU_\sNku"A@SnkefFQ αW\>Z"i.EA`! ;kDCI}*mzgIA@A@fZiO4@IpsMai/ ?Եt#  \m="Wo> ^rؤ+WDp xrp)H",x 0+Kn.EA`<cc3(@v# Cv   0ox)|O MLyB(DCMMpO*}8CHfBHYpI? pij'6<(˗G$Zi `FD3 \HyZA@A@FGN>zMnj ZHB @lc 8y'{'K|27g2df>y3IK⼀bȀXX!V5JUU{wRU:uϹSM=~LN7oyY.|_/f֭[v8oG< S 4Ef L=Aijn 91?'tɗq+6O=NmZR8I_F| @@@ J/>"޺fdÆK,s XT0go [Kh7gORe:`n;ט%LС(+Ҽ :3FN:$C/r  $O_}G~ܫ_ݵCi-?yNm]WWgg:L+4R^ >s֥^kcý>י LƆJil̖?:!#4$L65kf#5A^@@[Ͻ&?YF';7N{òh"> cQ[@q`[Z9sᯟB WȃnrqԌ$@x  +0(S_&eM{{kk 8h@b^ DbNI"ъn=M5"Ҝ'Зd  G6#vTE!I:@@@WO>/H22ͻd+:22bO{7HMM>`Hb\ P#<SL#  @T'/iwfgɟ|틲neԱ^ 4l߾]֮];C k34O|,KsED-ϖ- 8{k81 `{^Fq'O :$|r  xO`tl\ÿs??axxX~_dggؘdee-DX>f ׹s-Oۍqe˗g$ki{l$H֤%B#i#  $|?YoeGus9e\kpWJ=W?2]"+˟yW}itgA8_:ظ/ 0 @@Dy?>YHw$9gƍeÆ j*?pʲt8JIU@:d :&  :828k֙ Hд$O.o̓qzӁs37FVE} !Ap(  s ?f7 틒i˞={066fg9ѱ 8JY>f~r+ [5MXS -C|f;=k*)由'Tv?)ƆUۮz02#4^ =  $SFd[*OqdfO^pe˖MĔ7,o KمrDv^\{xC~^C'{l$zƿoN  $Gg2b n\#$#=]t薖h%mAtGbx(GPAPA8 GPV*W wV.U-_:%qYMI tH  D&O/W߿6IKɄyo>t#;8J ǺAUou畧CHڽЀ#3 D7V?d6dF@Bn@l<54 @@ AޏM&'rώ-;ngѣGm!33S]i<ǸN ":Vo {,[6@ghY&rsuU<#{c)OB`@ #  s .{cq|d"6lrXT[[k/(Yl8yN9OY Nu  ${M~mT{o۶m!0)vxm}!C+K\@UyrfXmP\_g#rOj֌Uͪ4WyR9{@@.($==MvN EEEax!%yTV~^y;H[AkXCd@@0IVf߼[\B&&& 4뮻S]C!@g@ oG<#4Bӑ-re"rj{3A/mA@@;tTrOEi\Q/cccw^iooLYjdg{l+'|x[WGG 8䟔r :|4/?zͻ<'i7:Hf @@H Xÿ%YUWcO>==]$77Wz,W*A O?+:D LA fC{~t4L~qͫwMyx[!  7Q?D>:"eErikk^Yzl߾.vER˕DA FG#W`Eˤ$nb|H>}Z̬e6O{Dg[jx[!  ><峖V.+lwߵG?ui% G)eT#vUa ů?g=*Tohhʅc@@W:{f 8Vw6ɓ2i6?+**\i_$r%FzOBΠޓ?Z q  $NYR{IYZ̙3k7?s˕$UxNB e@@HBg;[uڥ%'#M#{SN.T__8gr%+@U=vF3<'PgHtރ@@K8~M>lZTm6͖?P:::ƍpdwr%Ϫ ,W3TuV,W3y*?#@r tr'g  E7O?4"W[-ʝ21>fޗ)W\q4zӦMscQ P=ck :pbRfd@=]X=W̯DL#9NmZpP@ 鐌9!  p4ɷ6pFϿy4{;t~  ~/Nk9'@^H,f:$VZ@@.YG/{V'&k߽fij:.=foo]=s˕46C@OJcCC@+3@|L3kә:SK˓@ %@@HX=(d@pV]7'R[[+ +WLj8˕LQxA Ot@7AJb$_啒9C@@xz~?zk8~f} yCZjYjH~@`C t2  O<¯̬/"ׯ_%/~1WHZ"'$gH:a PTq)HąJ@/_7F@@"^tT_I233mݥr7`D\JH:NTNHI -@3bQ@@pM >Ky$3#]o%Uyri 7 999k*fTC@[ݿ  @ LLN9p̐o} wyGz- 8h_\>Y`&CoAAYr$@@\?K^N|wu+ˉ'2J6l\WY$ P`1.N( "v"  =1ʟ|)/̑,ٱc8Z7&!O'FT.@:U"CP@@b(08<*_m@#+*+C'{}@ @b#@!6@@O xԔȟCra{7LJ,W&1  @\:ąJ@@@gZZeIMn&z8@@ig;{[\Z:eu"[7IQQlݺUӧ'\z : -Z @8Z]w@ ^Ԍ  g;Hrٲmk'ۋJlaAf$H:J = A FGt=9 sjˉ{!  0C3ȣ*rE2ߺGӲe˖0zS]^ily@x?h  @X^)z @@ n:%madžrbٵkW,>3Y>R1# /LC@XgrX3l^apUiѴ֭u+$9>8$O?1}Z]Jr5HZٞfo}ծm 3 DOC,9  u 8~ wz0B =xvЊFJSs=PAɖ2ybuٌeumӺW#=+r뮐W^yY䪫Z,W$!DxK v@IDAT$A$XN @C@g.h !4i Bg@}=4|.P=pۛȈ8rtZ_hw~o29_/wܴU [nF{}sD #?@ jFɁ@HV?Œt :V듯5:s1O6@CUYټxәs3ߞ~Y|>k/P}㰐c'{Y$Y{Ah(FG,9 :x?h   2WkkjYSU 2yF^SWU-Յ9vph@t̙ {EIeE<릨䉗ޔ_L߹zjk_F\q02̧ŝ @@:4@o THY.FӺz P{jlY^23<)vmmmn+*%}usM]8 X\^y[J}zy&9}N򤤤dF x:MJq ]@??Z q $@cJi/5 `?3"vܛ]9k;aO6Cٖ666Z{g[rN858@ }|iM wˤvw5S~V$@'4 P  P $`۫C!/*FI@?HФ59WFVNSyn O\=&&'寞a)1*{7deH$A A ou5 QௗQr @X+\;:Mȵ9_qiygR^'[_3Xtׁ@@F)K {b?j]..? Dh?-{f@" @HMT3hcC.% wrXXU-+kJeiudeeI}}2 PjF Eד%|fYDMOsiГloց#Gm!mZ'L@RZCJw?' @x rDXcpxD?M-re"/SFO***RtgMt}?Az.hg.ؘ-Li[$@UCF@`(9?(_SDnz?zDZ)--Mt,r_%A o1A Cg-0s5~*FA8S ( zA#Ouȥ|?:{ ȝ=wbayh    P P9$ /"^3bA@@`A ==~& ō( $@FP,gݹsz_|I?Y;8s,@ӯ'>:*z,ϒN>nWE6Y!_uGF51=1qcѯHx=e24;7uw>+.[9e78<*S.4x3|=qGGeѤO?>I72aޓм`eW3&ddl\3d0Hv޻w4`_/ V65Y渦Nts:4?$K%]wg6X-PcOLL&Od]Md9OdI?w7wȎUq.ﵣ6xsMTK&'EEܬtl4T9b?.| Ty.ؘ=O!^*U%  @ t_x[.UqY @FlGgx_ m6#&gJYM͕zK:f~MyY:>oS?Q}i̖!;<_3mǭ:Ft;+=Mk,/5~ ll߰ցiޣry ȩ?,czL6|^ r-ܤ)7wB~vIQnρ84/xh0ʐ9y;oy\N5⊩7+ɝ28VՅ9SVEyn>YSAbtͫ*ժl`DZJKKO?+ `\Y>&01BT9K ,W3O A0zĉTMMͬ6?ZhF4z<#$pf9xy)uI[wT[Ѵ֭u+$|؞1r澣FMj.3fq33̀XjYt NuJoyfP^ȳ23dh%f)'?ټgGfF);=lV޳>d7+5pq[W9u19n3~/@6jTrB}][*ST:+o<- )7ojB8r;Ρqe}s2 Wk0i>hte:4}&'`nw͒+]%8+B۶cDY;ElfT?saT6|Xؾ׶AS'd|{6nW}%Rh;lgfh_|-wy`\ӥٜGpyS rs5}}-ԩ9ymmmS2듞yfyмLÇM2ק̎ IQN.K/jIA }yCh )3&E*++CFFF$++xs`ݼ1;;ۮY =)ݥNJqf$ % ~ [[H54vٮ\t LY\U&5e%R_!i#vӎA&w\>A]h{A;ny>-//ߣO=ǑX=c#瞳mԥt 7`y,Qp&Ė-[~h۫/r3!~]FHl2;0~i/---{22i@KK+D$G@?YИ/;!>]1Ͻ"5Ǭw4u2+ϋoGG2'UfYʊ$]? -6j` \)>jJ 8OV,]"5%rW4^if5kʲzqJWW ٛdx8pj`<=yMg{Tz\^IYP6m4k֡s~k ;ڵ:73iafںu,ٸqWUvV^$uәz@|}mՀ)~I͛3t)+ 8į+f1M\a5Msӽi$+[ͯ&8ykMtp@d Foз:W3ihc fasklFsWFVټC޴|$ݣKMi@ᤙq>k fyR.%&Yim.þb;_Bۤ/R2M h@dФZ-`렿t ~h@f[nef\s5kϥKzoLN@bfC>? r;:Nz? lϚNRVVr?t3A7ͼ,Iȴ;{hy   a(٠^Wb&SSyyyh8Ƭ$kA30ηHeyTS)$oOÙ;ĜP,bY\S%2!}wu]'饗ge4?`f"L-WnkA4d_ N lù+l}qqvzuVC$cjLO ]1bi-`U}fO MJCc@uZ`kT @J t׮]+fsB]WyfAz4ו1Bc@ Do,#U0W;U.=^<8<*'ζZpB=:{/ς^ɮY\/UEy<\\kk7ސ3gΈȆeF RA%KL4ؠiǎ>:x,,A|+_&7>6{,cە^^)LB5x A0Y׀~ȑ#WǏۧZfcw|^C蘜j8S9XЖW BiqTUIoLC2n4شiXޒ'OWXN2L@F@%tf@UlA{`DԕK9e&Օr0aLrpLX/,stx#AXrL@@ }'<]o +/ev` n0S6CAgzo 08{ ]qe˖iՅV%>W֧HDepDh+cbA( ?/8  ]pl[kF! uyғO>)_җ~#EV"8_Aɀɳf rH澣l<9{g] .Tj7XR'fƂL+e}r9|E ʺjKGte˂.hAotwGb;ԑ|?A@w ԫ핤>_fw:>T9}p%.;-?c8oԍ_9Ol Y.c &A#=uNNYI 2n6Y+eEfk_!@%67]֥6m$~#C&`B4U׬Ycg1BfpGaG{f mjN~z~T  0K,3-Z$o~v IofWmBӤչR54?c8s[oއf  $)k/4ug)$gr2%''岪Lr${B8jAoIV7r尷  AtNfd\2Df#cc5\ *det\WZ3# ;]sd5R&(//[nY2v-3eeeyf^QQ-_ZZ*۷olB)7cř: S&ҥ(}BhzeIN`TMHixFdJɛ,Iɗ !#3a?W.Ǽ/;@fEyŒ/C~Ċ ֥U %/@}2dfKQQr6OJ%l:b4UuuRYϺWKk^ffz̬)I65obb4OmP}ڛG?]GO%`i5Յ6@A}h<+m}mqpMnGN @ApF B0pu6wK=GG,ͯL}~2_V+`4g'(?W G:u[KkL}4_]~O*G wxÆ {?6sG( 0e+2Gha~ y\}sMl7y_-ď" "@!YzrЁ,t HQ$ w膩>\F|[>6W֗JGͭSyk5ϔ=|Z˝\VX`SˬCMgg{tv^[>^Yy̶,$SrgD de tu@N˚\YR\Ӯa9?fdQ~0pҔ9㟐%YR"gM,s'&,7{]:rI@~X\/+o헲rA|3ZRZ"ŅEfgDž3$?556TJcc?l UƆU6Og:<@t # rF}&|R.}Ic&;  >1? &M5%elsCߟ^Qo>sLNh|kHeFFA߿w]W_ ܭ; $ͭrIgf` ˶xb[YA8_W~ĝ| 贈v 22bű@@d 萬=r^eeevlL}?*eyAqIOKn6rP! ifFÐ &g5/)h{Leʫk%7!#eL̞1dbޛ'+L4iMQSm%=Scܨ9lY} 跛40l؄tޡLaI ش\<] 0tt_*RnfxhjWj9mo WTـ ]'&f"|fyWn6is00i簴Ml]8P1JVOJ4:$L33,䛀EqQDΗ 2m2A4[W2f\=4ypMX ` B47Ks "hyM٦/M NnQ[ۣ]&J)A%|>#{v29G-7~.e /ؙ?8ر ;;@}}]Rt7ڠ33HnYtFѺ|;:/>OAYSS XrC+C   tp>~~Ϛ+rY7IzU}K_`O@3x-C&1CΥ;̽.ON}GӚ+<8_l8I4bMȤl dmE4>3l:;B:C 84E9c:C3r].{396(}tL>5y[MjwNtML`4T+ufcgZa'f@;ХrrWf;l䫛s2=K>7;<ΔL[͇dYbG3FK @=2eu.keyoqLߍ+8| O;%, v4\hΫ4BlCݷKueKo |i}^4pvr۟EYm6dny_>}\\3 d27oyAf<iW^y%?.Fv |L9gA(  @,:Bc ALMpЁG}T/1H+~ÔټJ֌F223WL` >gKq^n3%t|)53'4}rSW/+ 01>:i󶙼&ߔg:Cgbԗe{><#-=C6Q^m7Nʀ ,.ɷW|&r-f 䛽92uߌ 84{h?h0CoZ& k~q~%8v߿_JΝkqv]HWXa?#/HAYo?`FGe\oRa?לw(*6KU'7\W+E9M|M0:}H M]Mtÿ{h?oa&LشiBg@ 5&e^۹s]HNstx&5cf2|ԃ@`f×}2q4vUMOÌ7ySveBХteri URlY&A]K7NGgL4Ɯ[u1`/?GPL4ѿS/gg!hv'|b7<˖-KՕTrzӴ}v{4(դ0>t{ܼޔhfVTTw@@ uvw׭4J"K54m6.5nIgͱaakB(͒O:!f?qյfWt9sYz{d q ddI_)6{ 9V-|RܴUuUef zPU Cca5gCNי TUUInn ${,'m0*++`(T r4|?<9LrcE]G^@@@@\v)RΉ @b pe}bG@@@ x}|C> J@@@@@@c^MA@@@@@ 萠G@@@@@AA@@@@@ A:$hl@@@@@&@k=B{@@@@@HP q4@@@@@ tZ@@@@@T #AM(f!#@@@@@qiIt*J`Hd@@@@@ z 啒)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     A7ԩ@@@@@$ 萄)!     @R>oV#<2@@@@@kם_+A𭒪$NN@@@@P`q\"X^) ?     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIK),IDATة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HBIة     ntpC:@@@@@HB:?~\z!2yĉusǸ>|+_Fa@@@@@)A&뤧Gyˎ;̙3aALj6_KkkkX     n&Qus=w^Ϥ6OVZ%;w{MmO]zh'}9i#=FU@@@@@@ %/.lV544ؼW_}uk#u@@@@@DHɠÉ'ljz-4#cDZ>.#     )thkk}{8L6uKӞGzHO'     $@Jmdff"'otttk#u@@@@@DHɠCNN@ 0m^IIɬB3"=FC1      A27~V ټYfDzHˇc@@@@@A %k׮}>:::lƍg1"-Z@@@@@HDhd۸}vyȑ#bŊi?~}eK#|>_41$@D 2J?Qa(AF0G t#JQ: %(dCD 2J?Qa(AF0G S0)tG^zIni{Izz{g>Y_4ϵE4ϱ@@@@@RSgg列_e߾}'HaaoٲEV\)O2<&Y޺u[e     @dӡSNI֭[޽{ݻycǎy}vAhV|Ґ}}>-[T E;r-*s@@@@@F W #     Ԉ@ft4@@@@@:(     [N]~@@@@@ӡj      иthG@@@F+; 64W{" ԦY%W_UfRGV{gɸl{x@W5o\uIM0A{u`H/VM4IHغuꪫWUզMN;}Ws9J>ǘNvBn͘1C 8P >\w}u u6ǿ\||%umm۶UC )4ud5׷.S =%_G?j(ձcGۮvijժUEgᄲz/JXKѷ<Zhc%iZz|-Q"1Sir\=΋o8aʘǏͅ`et暠\y#Ц㡪<|)4@_^|zoٳgksB? l2M;駟iӦ:I&uerʔ)K/͛mf}ӟydڕHiW+ &@_.>.{,wQs=.Zo[_h#N'u]1u$R{ܲ)&wFOO_3+W7nW_}n֬Bv%4x)=z_l.0g|OwuvQG7^a|`@KÓO>Y\d3[_q'_nP'ڕHݬiW*WqMu6ǯl|}]?яl[kqv__P|#M} ec\st:M] I=vt:8 Γ^S>h}IgM.]Y_ozܹ,Kˁy7f^I悘ב@vB~1l0;ŋQN<'<'뮻l]) x@9;J#ɷ..Zn4$ʩkIү8_vWs-`9կJ-M= v6 Yks||#V|iW|㤓NɼJ)@f믷nּmYnWʽ>|÷d#^sSKzXuW1L3!sڌ:,k6D8wOǣڵkgl~]W7w^0*yɓU>}?5zkVWym 7YviwڕE}mNI΂?O;_^T@ںV|}}LҔOY= NyРA 'uwqb[A$+_%-_3}tڥo=o[ە}÷d$N|W,:HR#&'l gl,=QbGl ՗ H~e!c lٲŞ-a }ĉȯx≼L+d- gq׿aJקpYYs<߶/bK/dI7goV_/pԗv3^ѴiS[gWI}Sܔv1ͷ<|+>s,::HZʇwDd$,C՝oiIy] S {eG}480$cQnLgƌvܓ3+ڎoyfRdP$$dL7e])z|-W.yX˹N|WLs|E W2΄@5 <6;)[ԩSՀT߾}3q|mڴQ?CU}GʼQuQ:c9GjС h_M֭[783@f,Do޽{+3f27&yA͞=;!iWSz])IZڜE1_iWZV\NeUf6 /T}yHS؊oxwүt4{Jyveo7r)RżҔ/R>^a~i o.(t3& 'nzRףoyr ϋpZ]O{&:ǑAX6a{q,O>dmx2\#9ғ;QOr5Y~`:gb妛ndq׿U A͍%-[ɾrH𪲌VU|H3vٳ57… O)6NK:BgSmN1dqȣ wE;[ׂYJ>_>N9$ $L+Jb6'Zoyj[3F}ڴidӑ,X͸)>n]L"[\b59N}+&|qTz(]a|G:^|zfdA'IX֟~i~i3Hw}愼nyy 23x``}]y%_c]%Jz]I̚*bgSTqu6'J-yXoTJ2ٗeV 80SׂX((X)|,9j^:$b=TD>7J/p~z=fm޽4i(iܸq..aYR&>LBQ/9VI48ptRHX9M[VMѣGYfE.$e@=6\ꫯj@וI;<,TDYK}AغukAx|1UVKM+t\+>{}6ӊ 9a18Rw}m۶A4B@o8bS89>Zw H=۲gVl*Uhs JyIlHv%Oyv~{{ 6d])z| ##-78J]ž+\iqT ># UqH!CUW]UZ&\]H:ϚOCҥK/~1K+=Ypu؎2ٴiSAyli Py糵bJ1>׻;Is=kORhsHFIgJ)O&a-YN?+q\/Hl1bD6 gI8/9UHIYnWCҹoyHb%iGr*zRʲ{b?I}͍ߘ+us&+6L4_̫c`z @5+m68옛ʼnɆ=yX>}؃P EthѢݷW^EӠ])Jz{j1I]I_DI|Kn:fZ u-({!ʷD-r=),_TQ.N8aIu(}϶Ү$Q"N%Ì-+lW^y2zc ,$kyRi q|Q k87X`ܹS7xc^._uue共R7WV玘݅1;iҥ 3l#~8 {@3h׬Yc (O矷 { ѮDsepƼImN:R_x|g|Z QVf >ܞ… gQwa %qmO.pV$^r>k^v&2eLEx٢r%̧<\sI2c6(iOSCU񑩾Ǹp>uZ컢u qs吻݅M$ A>y2zqڋ-ҽ{֛7oː5>z;={_\ Ϯ>`Hr+s'I&{n007%I'd_Nv%,RJ\IUes]{%1 9׈o?cm~ݪ9-˹S%ZnzY\.Qv8:TwIuգ^Tz$_RN^T̗v%J.z*my[],eqYg'.'YnWʽ]6w<|k1rJ\ž+{8$u ̳# 7z!a/,35Zs6j^lp*9LdÕK&NN򩧞͛7W_zԩ*C {2 4vk3n|ډ7|SbOر}]S]zZQ̫/JZ)/< u;)ɔv%+<[G>ncYbOr(KsMd     %@e3     8:s@@@@@(KN@@@@@N9     %@CY|     NN'@@@@@ӡ,>vF@@@@@'@`     e P;#     I0G@@@@@t(@@@@@@ $#     @Yt:      tp@@@@@@,:cg@@@@@pt:8       Pe3     8:s@@@@@(KN@@4i_.]ƍK;e˖iӦC9ToڴI;VuY5o\C]{ε]} G.\X   PZN>lE@@ t4ȍUVQF۷o͚5N%ʕ+ƭ zR^zZti}Ύ'?^o^UsQ [oSRn[nU˗/WW\q ƏA<@@@@4A6b+  >ժU+K.O^R={_h.&r^[nQcƌQ[lQm۶]v%mۦ;8裏oQ{@@Ӂ@@ ȫzsOoK}[ߊLuP|ǪiӦq3P-Sct2d?9:op׾z,YR@@ht:4ڢ#  ( 7fT-ԓO>:ȬJj_{d0p}Q*R֭[۱!>*mӧO5n8Kŭ1]z@@j\7p| L^yW:ܔGH:=#63gemw琷CJ>zݺu :(mГ&M R;vyg{>Wp0OV$rJ;`~9oӔNkת>`KWJڷo6nhǓiX Gqj׮<:q|)7ݺuSI;ฌWQj1衇Ԑ!CqG+j/;.FnITg@@vxҡv˖3C@"/> ?4g;P?2P^uXɧ6\n.O::\f܉_իms n177~Zz};6$N@@*m8;@@_z=ҫݍ.]C){ k 7_.U^$Sǎ 5doiԔƼG ~ӟڧ^n&$012   @M PI! 4{ Hyx37ojٲ "T[fɍ ' z:;]?yT%:TI2y睟L^$ӀZ!b.c; iq8T/-b#.N]3|# ԦY  @ѬZ{W}Qd:pM6mr:H4g=F B~xm:BO4ɆIM/bb X A%K^z)pY0Oam'Oo6UҦA2y]R^\Y17\d~=eŭwy}=޺u6O<#i|榼o3sLm:7J\|lÆ /s>SRsZ ә]vYd8   @M |񍥦OC@@nroRGܶm۷oAzK>\nZӵy]>_|y; neܠ~vky{졥dҥn9sAwqGA7/?Ys1Jׯ_d'Kc/\n^,n<\zƌ_җbIqG͛k3:ukMrqq\Jӥ@@?8@@@@@@ӡ,>vF@@@@@'@`     e P;#     I0G@@@@@t(@@@@@@ $#     @Y |#f/IENDB`CGNS-3.4.0/src/000077500000000000000000000000001343724673500130555ustar00rootroot00000000000000CGNS-3.4.0/src/CMakeLists.txt000066400000000000000000000475011343724673500156240ustar00rootroot00000000000000 ########## # Global # ########## if (WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif (WIN32) # Include the local directory include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) if (CGNS_ENABLE_HDF5) add_definitions(-DBUILD_HDF5) if (WIN32) if (HDF5_LIBRARY) # file(STRINGS ${HDF5_LIBRARY} HDF5isDLL REGEX "__imp__H5close") # if (HDF5isDLL) # this is only needed when using hdf5 dll libs add_definitions(-DWIN32 -D_HDF5USEDLL_) # endif (HDF5isDLL) endif (HDF5_LIBRARY) endif (WIN32) if(HDF5_NEED_MPI AND MPI_INC) include_directories(${MPI_INC}) endif(HDF5_NEED_MPI AND MPI_INC) if (CGNS_ENABLE_PARALLEL) add_definitions(-DBUILD_PARALLEL) endif (CGNS_ENABLE_PARALLEL) endif (CGNS_ENABLE_HDF5) ################################ # create configed header files # ################################ if ("${SIZE_OF_LONG}" GREATER 4) set(CGLONGT long) else ("${SIZE_OF_LONG}" GREATER 4) set(CGLONGT "long long") endif ("${SIZE_OF_LONG}" GREATER 4) set(BUILDLEGACY 0) set(BUILD64BIT 0) set(BUILDSCOPE 0) set(BUILDFORTRAN 0) set(BUILDBASESCOPE 0) if (CGNS_ENABLE_LEGACY) set(BUILDLEGACY 1) else (CGNS_ENABLE_LEGACY) if (CGNS_ENABLE_64BIT) set(BUILD64BIT 1) else (CGNS_ENABLE_64BIT) endif (CGNS_ENABLE_64BIT) endif (CGNS_ENABLE_LEGACY) if (CGNS_ENABLE_LFS) add_definitions(-DHAVE_LSEEK64) endif (CGNS_ENABLE_LFS) if (CGNS_ENABLE_SCOPING) set(BUILDSCOPE 1) endif (CGNS_ENABLE_SCOPING) if (CGNS_ENABLE_FORTRAN) set(BUILDFORTRAN 1) endif (CGNS_ENABLE_FORTRAN) if (CGNS_ENABLE_BASE_SCOPE) set(BUILDBASESCOPE 1) endif (CGNS_ENABLE_BASE_SCOPE) set(SYSCFLAGS "") set(CFGFLAGS "") set(LIBS "") file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/lib LIBDIR) file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/include INCLUDEDIR) file(TO_NATIVE_PATH ${CMAKE_C_COMPILER} CC) if (WIN32) set(CGNSLIB cgns.lib) else (WIN32) set(CGNSLIB libcgns.a) set(LIBS -lm) endif (WIN32) string(COMPARE EQUAL ${CMAKE_BUILD_TYPE} Debug IS_DEBUG) if (IS_DEBUG) set(BUILDDEBUG 1) set(CFLAGS ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_DEBUG}) set(LDFLAGS ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_DEBUG}) else (IS_DEBUG) set(BUILDDEBUG 0) set(CFLAGS ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_RELEASE}) set(LDFLAGS ${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS_RELEASE}) endif (IS_DEBUG) set(BUILDHDF5 0) set(H5NEEDMPI 0) set(H5NEEDSZIP 0) set(H5NEEDZLIB 0) set(BUILDPARALLEL 0) set(HDF5INC "") set(HDF5LIB "") set(SZIPLIB "") set(ZLIBLIB "") set(MPIINC "") set(MPILIBS "") set(HAVE_FORTRAN_95 0) set(HAVE_FORTRAN_2003 0) set(HAVE_FORTRAN_2008 0) set(HAVE_FORTRAN_2008TS 0) set(HDF5_HAVE_MULTI_DATASETS 0) set(HDF5_HAVE_COLL_METADATA 0) set(FORTRAN_DEFAULT_INTEGER_C_INT64_T 0) set(HAVE_STAT64_STRUCT 0) if (BUILDFORTRAN) #----------- Determine if the Fortran compiler pgi ------------------------ # The PGI compiler segfaults wehn va_start is called, so we need to add # a special compiler flag, see CGNS-40. #-------------------------------------------------------------------------- IF (CMAKE_Fortran_COMPILER_ID MATCHES "PGI") SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Mx,125,0x200") ENDIF() #----------- Determine if the Fortran compiler NAG ------------------------ # The NAG compiler needs an additional flag for Fortran calls to C APIs. #-------------------------------------------------------------------------- IF (CMAKE_Fortran_COMPILER_ID MATCHES "NAG") SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -mismatch_all") ENDIF() ENABLE_LANGUAGE(Fortran) #----------------------------------------------------------------------------- # The provided CMake Fortran macros don't provide a general check function # so use this one. #----------------------------------------------------------------------------- MACRO (CHECK_FORTRAN_FEATURE FUNCTION CODE VARIABLE) IF (NOT DEFINED ${VARIABLE}) IF (CMAKE_REQUIRED_LIBRARIES) SET (CHECK_FUNCTION_EXISTS_ADD_LIBRARIES "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") ELSE (CMAKE_REQUIRED_LIBRARIES) SET (CHECK_FUNCTION_EXISTS_ADD_LIBRARIES) ENDIF (CMAKE_REQUIRED_LIBRARIES) FILE (WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.F90 "${CODE}" ) TRY_COMPILE (${VARIABLE} ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.F90 CMAKE_FLAGS "${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}" OUTPUT_VARIABLE OUTPUT ) # MESSAGE ( "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ") # MESSAGE ( "Test result ${OUTPUT}") # MESSAGE ( "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ") IF (${VARIABLE}) SET (${VARIABLE} 1 CACHE INTERNAL "Have Fortran function ${FUNCTION}") MESSAGE (STATUS "Testing Fortran ${FUNCTION} - OK") FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the Fortran ${FUNCTION} exists passed with the following output:\n" "${OUTPUT}\n\n" ) ELSE (${VARIABLE}) MESSAGE (STATUS "Testing Fortran ${FUNCTION} - Fail") SET (${VARIABLE} "" CACHE INTERNAL "Have Fortran function ${FUNCTION}") FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the Fortran ${FUNCTION} exists failed with the following output:\n" "${OUTPUT}\n\n") ENDIF (${VARIABLE}) ENDIF (NOT DEFINED ${VARIABLE}) ENDMACRO (CHECK_FORTRAN_FEATURE) #----------------------------------------------------------------------------- # Configure Checks which require Fortran compilation must go in here # not in the main ConfigureChecks.cmake files, because if the user has # no Fortran compiler, problems arise. # #----------------------------------------------------------------------------- CHECK_FORTRAN_FEATURE(Fortran2003 " PROGRAM testf03 USE iso_c_binding IMPLICIT NONE INTEGER(C_INT) :: a INTEGER(C_INT32_T) :: b INTEGER(C_INT64_T) :: c REAL(C_FLOAT) :: d REAL(C_DOUBLE) :: e CHARACTER(LEN=1,KIND=C_CHAR), TARGET :: f TYPE(C_PTR) :: g INTERFACE INTEGER(C_INT) FUNCTION test(A, UserDataName1) BIND(C, name='cg_goto') USE ISO_C_BINDING INTEGER(C_INT) , INTENT(IN), VALUE :: A CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: UserDataName1 END FUNCTION test END INTERFACE g = C_LOC(f(1:1)) END PROGRAM testf03 " CHECK_FORTRAN_2003 ) if (CHECK_FORTRAN_2003) set(HAVE_FORTRAN_2003 1) endif (CHECK_FORTRAN_2003) if (HAVE_FORTRAN_2003) CHECK_FORTRAN_FEATURE(Fortran2008TS " PROGRAM testf03 USE ISO_C_BINDING INTERFACE INTEGER(C_INT) FUNCTION test(A) BIND(C, name='test') USE ISO_C_BINDING INTEGER(C_INT), OPTIONAL :: A END FUNCTION test END INTERFACE END PROGRAM testf03 " CHECK_FORTRAN_2008TS ) if (CHECK_FORTRAN_2008TS) set(HAVE_FORTRAN_2008TS 1) endif (CHECK_FORTRAN_2008TS) CHECK_FORTRAN_FEATURE(Fortran2008 " MODULE test USE ISO_C_BINDING INTERFACE binding FUNCTION bind1(x) BIND(C, name='Cfunc') IMPORT :: C_FLOAT REAL(C_FLOAT) :: x END FUNCTION bind1 FUNCTION bind2(x) BIND(C, name='Cfunc') IMPORT :: C_DOUBLE REAL(C_DOUBLE) :: x END FUNCTION bind2 END INTERFACE END MODULE test PROGRAM main USE test IMPLICIT NONE END PROGRAM " CHECK_FORTRAN_2008 ) if (CHECK_FORTRAN_2008) set(HAVE_FORTRAN_2008 1) endif (CHECK_FORTRAN_2008) CHECK_FORTRAN_FEATURE(Sizeof_int " MODULE mod INTERFACE test_integer MODULE PROCEDURE test_int MODULE PROCEDURE test_c_int64 END INTERFACE CONTAINS SUBROUTINE test_c_int64(a) USE ISO_C_BINDING INTEGER(C_INT64_T) :: a END SUBROUTINE test_c_int64 SUBROUTINE test_int(a) USE ISO_C_BINDING INTEGER :: a END SUBROUTINE test_int END MODULE mod PROGRAM main USE mod INTEGER :: a CALL test_integer(a) END PROGRAM main " CHECK_FORTRAN_DEFAULT_INTEGER_C_INT32_T ) if (NOT CHECK_FORTRAN_DEFAULT_INTEGER_C_INT32_T) set(FORTRAN_DEFAULT_INTEGER_C_INT64_T 1) endif (NOT CHECK_FORTRAN_DEFAULT_INTEGER_C_INT32_T) else (HAVE_FORTRAN_2003) CHECK_FORTRAN_FEATURE(Fortran95 " PROGRAM testf95 IMPLICIT NONE INTEGER, PARAMETER :: cgint_kind = SELECTED_INT_KIND(5) END PROGRAM testf95 " CHECK_FORTRAN_95 ) if (CHECK_FORTRAN_95) set(HAVE_FORTRAN_95 1) endif (CHECK_FORTRAN_95) endif (HAVE_FORTRAN_2003) CHECK_FORTRAN_FEATURE(FortranConcat " # define CONCATENATE(a,b) a##b CONCATENATE(PRO,GRAM) testconcat IMPLICIT NONE integer a a = 10 END PROGRAM testconcat " CHECK_FORTRAN_CONCAT ) if (NOT CHECK_FORTRAN_CONCAT) SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DNO_CONCATENATION") endif (NOT CHECK_FORTRAN_CONCAT) endif (BUILDFORTRAN) macro(native_paths INPUT_PATH_VARIABLE RESULT_VARIABLE) set(${RESULT_VARIABLE} "") foreach(PATH ${${INPUT_PATH_VARIABLE}}) file(TO_NATIVE_PATH ${PATH} NATIVE_PATH) list(APPEND ${RESULT_VARIABLE} ${NATIVE_PATH}) endforeach(PATH ${${INPUT_PATH_VARIABLE}}) endmacro(native_paths) #----------------------------------------------------------------------------- # The provided CMake macros don't provide a general HDF5 check function # so use this one. #----------------------------------------------------------------------------- MACRO (CHECK_HDF5_FEATURE FUNCTION CODE VARIABLE) IF (NOT DEFINED ${VARIABLE}) FILE (WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_HDF.c "${CODE}" ) IF (HDF5_LIBRARIES) SET (CHECK_FUNCTION_EXISTS_ADD_LIBRARIES "-DLINK_LIBRARIES:STRING=${HDF5_LIBRARIES}") ELSE (HDF5_LIBRARIES) SET (CHECK_FUNCTION_EXISTS_ADD_LIBRARIES) ENDIF (HDF5_LIBRARIES) SET (CHECK_FUNCTION_EXISTS_ADD_INCLUDE "-DINCLUDE_DIRECTORIES:STRING=${HDF5_INCLUDE_DIR}") TRY_COMPILE (${VARIABLE} ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/test_HDF.c CMAKE_FLAGS "${CHECK_FUNCTION_EXISTS_ADD_INCLUDE}" "${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}" OUTPUT_VARIABLE OUTPUT ) # MESSAGE ( "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ") # MESSAGE ( "Test result ${OUTPUT}") # MESSAGE ( "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ") IF (${VARIABLE}) SET (${VARIABLE} 1 CACHE INTERNAL "Have HDF5 function ${FUNCTION}") MESSAGE (STATUS "Testing HDF5 ${FUNCTION} - OK") FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Determining if the HDF5 ${FUNCTION} exists passed with the following output:\n" "${OUTPUT}\n\n" ) ELSE (${VARIABLE}) MESSAGE (STATUS "Testing HDF5 ${FUNCTION} - NOT FOUND") SET (${VARIABLE} "" CACHE INTERNAL "Have HDF5 function ${FUNCTION}") FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if the HDF5 ${FUNCTION} exists failed with the following output:\n" "${OUTPUT}\n\n") ENDIF (${VARIABLE}) ENDIF (NOT DEFINED ${VARIABLE}) ENDMACRO (CHECK_HDF5_FEATURE) if (CGNS_ENABLE_HDF5) set(BUILDHDF5 1) if (HDF5_INCLUDE_PATH) native_paths(HDF5_INCLUDE_PATH HDF5INC) include_directories(${HDF5INC}) endif (HDF5_INCLUDE_PATH) if (HDF5_LIBRARY) native_paths(HDF5_LIBRARY HDF5LIB) endif (HDF5_LIBRARY) if (HDF5_NEED_SZIP) set(H5NEEDSZIP 1) if (SZIP_LIBRARY) native_paths(SZIP_LIBRARY SZIPLIB) endif (SZIP_LIBRARY) endif (HDF5_NEED_SZIP) if (HDF5_NEED_ZLIB) set(H5NEEDZLIB 1) if (ZLIB_LIBRARY) native_paths(ZLIB_LIBRARY ZLIBLIB) endif (ZLIB_LIBRARY) endif (HDF5_NEED_ZLIB) if (HDF5_NEED_MPI) set(H5NEEDMPI 1) if (MPI_INC) native_paths(MPI_INC MPIINC) endif (MPI_INC) if (MPI_LIBS) native_paths(MPI_LIBS MPILIBS) endif (MPI_LIBS) if (CGNS_ENABLE_PARALLEL) set(BUILDPARALLEL 1) endif (CGNS_ENABLE_PARALLEL) endif (HDF5_NEED_MPI) set(cgns_C_FILES ${cgns_C_FILES} adfh/ADFH.c) if (CGNS_ENABLE_PARALLEL) set(cgns_C_FILES ${cgns_C_FILES} pcgnslib.c) endif (CGNS_ENABLE_PARALLEL) # Check if HDF5 library has multi-dataset read/write APIs # -------------------------------------------------------------------- CHECK_HDF5_FEATURE(Multi_Dataset " #include \"hdf5.h\" void main(void) { H5D_rw_multi_t *multi_info; return; } " CHECK_HDF5_HAVE_MULTI_DATASETS ) if (CHECK_HDF5_HAVE_MULTI_DATASETS) set(HDF5_HAVE_MULTI_DATASETS 1) endif (CHECK_HDF5_HAVE_MULTI_DATASETS) # Check if HDF5 library has collective metadata APIs, HDF5 >= 1.10.0 # -------------------------------------------------------------------- CHECK_HDF5_FEATURE(Collective_metadata " #include \"hdf5.h\" void main(void) { hid_t foo; H5Pset_coll_metadata_write(foo, 1); H5Pset_all_coll_metadata_ops(foo, 1); return; } " CHECK_HDF5_HAVE_COLL_METADATA ) if (CHECK_HDF5_HAVE_COLL_METADATA) set(HDF5_HAVE_COLL_METADATA 1) endif (CHECK_HDF5_HAVE_COLL_METADATA) endif (CGNS_ENABLE_HDF5) # Check for stat64 struct ## -------------------------------------------------------------------- # stat64 is deprecated for OS X if (NOT APPLE) include(CheckStructHasMember) if ( WIN32 ) CHECK_STRUCT_HAS_MEMBER("struct _stat64" st_atime sys/stat.h CHECK_HAVE_STAT64_STRUCT LANGUAGE C) else ( WIN32 ) CHECK_STRUCT_HAS_MEMBER("struct stat64" st_atime sys/stat.h CHECK_HAVE_STAT64_STRUCT LANGUAGE C) endif( WIN32) if (CHECK_HAVE_STAT64_STRUCT) set(HAVE_STAT64_STRUCT 1) endif (CHECK_HAVE_STAT64_STRUCT) endif(NOT APPLE) #create these in build directory so it doesn't mess up the #source directory, then add the path to them configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cgnstypes.h.in ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cgnstypes_f.h.in ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes_f.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cgnstypes_f03.h.in ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes_f03.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cgnsconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/cgnsconfig.h ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cgnsBuild.defs.in ${CMAKE_CURRENT_BINARY_DIR}/cgnsBuild.defs ) include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) ########### # Library # ########### # All the C files needed by the cgns library set(cgns_C_FILES cgns_error.c cgns_internals.c cgns_io.c cgnslib.c adf/ADF_interface.c adf/ADF_internals.c) if (CGNS_ENABLE_MEM_DEBUG) set(cgns_C_FILES ${cgns_C_FILES} cg_malloc.c) add_definitions("-DMEM_DEBUG") endif(CGNS_ENABLE_MEM_DEBUG) if (CGNS_ENABLE_HDF5) set(cgns_C_FILES ${cgns_C_FILES} adfh/ADFH.c) if (CGNS_ENABLE_PARALLEL) set(cgns_C_FILES ${cgns_C_FILES} pcgnslib.c) endif (CGNS_ENABLE_PARALLEL) endif (CGNS_ENABLE_HDF5) # All the Fortran files need by the cgns library (if enabled) set(cgns_F_FILES cg_ftoc.c cgio_ftoc.c) # Only build those files that are needed if (CGNS_ENABLE_FORTRAN) if (FORTRAN_NAMING) set_property(SOURCE ${cgns_F_FILES} PROPERTY COMPILE_DEFINITIONS ${FORTRAN_NAMING}) endif (FORTRAN_NAMING) set(cgns_FILES ${cgns_C_FILES} ${cgns_F_FILES}) add_library(cgns_f2c OBJECT cgns_f.F90) else (CGNS_ENABLE_FORTRAN) set(cgns_FILES ${cgns_C_FILES}) endif (CGNS_ENABLE_FORTRAN) set(CGNS_BUILD_SHARED "ON" CACHE BOOL "Build a shared version of the library") option(CGNS_USE_SHARED "Link programs to the CGNS shared library" "ON") # Build a static version of the library if (CGNS_ENABLE_FORTRAN) add_library(cgns_static STATIC ${cgns_FILES} $) else (CGNS_ENABLE_FORTRAN) add_library(cgns_static STATIC ${cgns_FILES}) endif (CGNS_ENABLE_FORTRAN) # Needed to work around a CMake > 3.8 bug on Windows with MSVS and Intel Fortran set_property(TARGET cgns_static PROPERTY LINKER_LANGUAGE C) # Build a shared version of the library if(CGNS_BUILD_SHARED) mark_as_advanced(CLEAR CGNS_USE_SHARED) add_library(cgns_shared SHARED ${cgns_FILES}) # under windows we need to define BUILD_DLL # and link with the HDF5 libraries to build a dll if (WIN32 OR CYGWIN) add_definitions(-DBUILD_DLL) endif (WIN32 OR CYGWIN) if (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) target_link_libraries(cgns_shared ${HDF5_LIBRARY} ${CMAKE_DL_LIBS}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) target_link_libraries(cgns_shared ${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) target_link_libraries(cgns_shared ${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) target_link_libraries(cgns_shared ${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) else(CGNS_BUILD_SHARED) set(CGNS_USE_SHARED "OFF") mark_as_advanced(FORCE CGNS_USE_SHARED) endif(CGNS_BUILD_SHARED) # Change the output name of the library to be libcgns set_target_properties(cgns_static PROPERTIES OUTPUT_NAME cgns) set_target_properties(cgns_static PROPERTIES CLEAN_DIRECT_OUTPUT 1) if(CGNS_BUILD_SHARED) # for windows we need to change the name of the shared library # for both static and shared version to exist if (WIN32 OR CYGWIN) set_target_properties(cgns_shared PROPERTIES OUTPUT_NAME cgnsdll) else (WIN32 OR CYGWIN) set_target_properties(cgns_shared PROPERTIES OUTPUT_NAME cgns) endif (WIN32 OR CYGWIN) set_target_properties(cgns_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1) endif(CGNS_BUILD_SHARED) # Set the version numbers set_target_properties(cgns_static PROPERTIES VERSION "${CGNS_VERSION}") set_target_properties(cgns_static PROPERTIES SOVERSION "${CGNS_VERSION}") if(CGNS_BUILD_SHARED) set_target_properties(cgns_shared PROPERTIES VERSION "${CGNS_VERSION}") set_target_properties(cgns_shared PROPERTIES SOVERSION "${CGNS_VERSION}") endif(CGNS_BUILD_SHARED) # Set the install path of the static library install(TARGETS cgns_static ARCHIVE DESTINATION lib) # Set the install path of the shared library if(CGNS_BUILD_SHARED) # for windows, need to install both cgnsdll.dll and cgnsdll.lib install (TARGETS cgns_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin) endif(CGNS_BUILD_SHARED) # Set the install path of the header files set(headers cgnslib.h cgns_io.h cgnswin_f.h ${CMAKE_CURRENT_BINARY_DIR}/cgnsconfig.h ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes.h ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes_f.h ${CMAKE_CURRENT_BINARY_DIR}/cgnstypes_f03.h ${CMAKE_CURRENT_BINARY_DIR}/cgnsBuild.defs) if (CGNS_ENABLE_FORTRAN) if(DEFINED CMAKE_Fortran_MODULE_DIRECTORY) list(APPEND headers ${CMAKE_Fortran_MODULE_DIRECTORY}/cgns.mod) else() list(APPEND headers $/cgns.mod) endif() endif (CGNS_ENABLE_FORTRAN) if (CGNS_ENABLE_PARALLEL) list(APPEND headers pcgnslib.h) endif (CGNS_ENABLE_PARALLEL) if (CGNS_ENABLE_LEGACY) list(APPEND headers adf/ADF.h) if (CGNS_ENABLE_HDF5) list(APPEND headers adfh/ADFH.h) endif (CGNS_ENABLE_HDF5) endif (CGNS_ENABLE_LEGACY) # Set the install path of the header files install(FILES ${headers} DESTINATION include) ######### # Tools # ######### add_subdirectory(tools) ######### # Tests # ######### if (CGNS_ENABLE_TESTS) add_subdirectory(tests) add_subdirectory(Test_UserGuideCode/C_code) if (CGNS_ENABLE_PARALLEL) add_subdirectory(ptests) add_subdirectory(Test_UserGuideCode/C_code_parallel) endif (CGNS_ENABLE_PARALLEL) endif (CGNS_ENABLE_TESTS) ############## # CGNS Tools # ############## set(CGNS_BUILD_CGNSTOOLS "OFF" CACHE BOOL "Build the CGNSTools package") if(CGNS_BUILD_CGNSTOOLS) add_subdirectory(cgnstools) endif(CGNS_BUILD_CGNSTOOLS) CGNS-3.4.0/src/LICENSE000066400000000000000000000026461343724673500140720ustar00rootroot00000000000000The distribution and use of the CGNS software is covered by the following license: ----------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ----------------------------------------------------------------------- This license is borrowed from the zlib/libpng License: http://www.opensource.org/licenses/zlib-license.php and supercedes the GNU Lesser General Public License (LGPL) which previously governed the use and distribution of the software. For details on the policy governing the distribution of the CGNS standard and software see: http://www.grc.nasa.gov/www/cgns/charter/principles.html CGNS-3.4.0/src/Makefile.in000066400000000000000000000154251343724673500151310ustar00rootroot00000000000000# makefile for the CGNS Library include make.defs CGNSVER = @CGNSVERS@ .SUFFIXES : .SUFFIXES : .c .F90 .$(O) $(EXE) OBJDIR = @BUILDDIR@ COPTS = $(CFLAGS) $(CFGFLAGS) -I. @BUILDOPTS@ FOPTS = $(FFLAGS) -I. @BUILDOPTS@ D_PRE = @FC_D_PRE@ CGNSLIB = $(LIBCGNS) INSTLIB = @CGNSLIB@ # Prepend to "-D" if necessary (xlf compilers) FOPTS_MOD=$(subst -D,$(D_PRE)-D,$(FOPTS)) #---------- CGNSOBJS=\ $(OBJDIR)/cgns_error.$(O) \ $(OBJDIR)/cgns_internals.$(O) \ $(OBJDIR)/cgns_io.$(O) \ $(OBJDIR)/cgnslib.$(O) # ADF/ADFH routines ADFOBJS=@ADFOBJS@ \ $(OBJDIR)/ADF_interface.$(O) \ $(OBJDIR)/ADF_internals.$(O) # Fortran interface routines @FGNSOBJS@=$(OBJDIR)/cgns_f.$(O) @F2COBJS@=$(OBJDIR)/cg_ftoc.$(O) $(OBJDIR)/cgio_ftoc.$(O) #---------- FORTRAN_TESTS= ifeq ("$(BUILDFORTRAN)" , "1") FORTRAN_TESTS=cd examples/fortran && $(MAKE) test && cd ../../Test_UserGuideCode/Fortran_code && $(MAKE) test endif MakeTests = runtests @PTESTS@ all : $(CGNSLIB) tools @CGNSTOOLS@ cgns : $(CGNSLIB) test : $(MakeTests) check : $(MakeTests) install : install-cgns @INSTALLCGNSTOOLS@ #---------- $(CGNSLIB) : $(OBJDIR) $(CGNSOBJS) $(FGNSOBJS) $(ADFOBJS) $(F2COBJS) -@$(RM) $@ @AR_LIB@ $@ $(CGNSOBJS) $(FGNSOBJS) $(ADFOBJS) $(F2COBJS) @RAN_LIB@ $@ $(OBJDIR) : -$(MKDIR) $(OBJDIR) #---------- tools : $(CGNSLIB) cd tools && $(MAKE) cgnstools : $(CGNSLIB) cd cgnstools && $(MAKE) tests : $(CGNSLIB) cd tests && $(MAKE) ptests : $(CGNSLIB) cd ptests && $(MAKE) runtests : $(CGNSLIB) cd tests && $(MAKE) test cd Test_UserGuideCode/C_code && $(MAKE) test $(FORTRAN_TESTS) runptests : $(CGNSLIB) cd ptests && $(MAKE) test #---------- clean : -$(RM) $(OBJDIR)/*.$(O) -cd tools && $(MAKE) clean -cd tests && $(MAKE) clean -cd examples/fortran && $(MAKE) clean -cd Test_UserGuideCode/C_code && $(MAKE) clean -cd Test_UserGuideCode/Fortran_code && $(MAKE) clean -cd ptests && $(MAKE) clean -cd cgnstools && $(MAKE) clean allclean : distclean distclean : -cd tools && $(MAKE) allclean -$(RM) tools/Makefile -cd tests && $(MAKE) allclean -cd examples/fortran && $(MAKE) clean -cd Test_UserGuideCode/C_code && $(MAKE) clean -cd Test_UserGuideCode/Fortran_code && $(MAKE) clean -$(RM) tests/Makefile -cd ptests && $(MAKE) allclean -$(RM) ptests/Makefile -cd cgnstools && $(MAKE) allclean -$(RM) $(CGNSLIB) -$(RM) $(OBJDIR)/*.$(O) -$(RMDIR) $(OBJDIR) -$(RM) cgnsconfig.h cgnstypes.h cgnstypes_f.h cgnstypes_f03.h -$(RM) config.log config.status -$(RM) make.defs cgnsBuild.defs Makefile -$(RM) *~ *.bak *.mod install-all : install install-cgns : $(CGNSLIB) $(INCLUDEDIR) $(LIBDIR) @INSTALLPCGNS@ @INSTALLADF@ $(INSTALL_DATA) cgnstypes.h $(INCLUDEDIR)/cgnstypes.h $(INSTALL_DATA) cgnstypes_f.h $(INCLUDEDIR)/cgnstypes_f.h $(INSTALL_DATA) cgnstypes_f03.h $(INCLUDEDIR)/cgnstypes_f03.h $(INSTALL_DATA) cgnslib.h $(INCLUDEDIR)/cgnslib.h $(INSTALL_DATA) cgnswin_f.h $(INCLUDEDIR)/cgnswin_f.h $(INSTALL_DATA) cgns_io.h $(INCLUDEDIR)/cgns_io.h $(INSTALL_DATA) cgnsconfig.h $(INCLUDEDIR)/cgnsconfig.h $(INSTALL_DATA) cgnsBuild.defs $(INCLUDEDIR)/cgnsBuild.defs $(INSTALL_DATA) $(CGNSLIB) $(LIBDIR)/$(INSTLIB) @if test -f cgns.mod; then \ $(INSTALL_DATA) cgns.mod $(INCLUDEDIR)/cgns.mod; \ fi install-tools : -cd tools && $(MAKE) install install-cgnstools : install-tools -cd cgnstools && $(MAKE) install install-adf : $(INCLUDEDIR)/adf $(INSTALL_DATA) adf/ADF.h $(INCLUDEDIR)/adf/ADF.h install-adfh : $(INCLUDEDIR)/adfh $(INSTALL_DATA) adfh/ADFH.h $(INCLUDEDIR)/adfh/ADFH.h install-pcgns : $(INCLUDEDIR) $(INSTALL_DATA) pcgnslib.h $(INCLUDEDIR)/pcgnslib.h $(INCLUDEDIR) : @if [ ! -d $(INCLUDEDIR) ] ; then \ echo "Making directory $(INCLUDEDIR)"; \ mkdir -p $(INCLUDEDIR); \ chmod 755 $(INCLUDEDIR); \ fi; $(LIBDIR) : @if [ ! -d $(LIBDIR) ] ; then \ echo "Making directory $(LIBDIR)"; \ mkdir -p $(LIBDIR); \ chmod 755 $(LIBDIR); \ fi; $(INCLUDEDIR)/adf : $(INCLUDEDIR) @if [ ! -d $(INCLUDEDIR)/adf ] ; then \ echo "Making directory $(INCLUDEDIR)/adf"; \ mkdir -p $(INCLUDEDIR)/adf; \ chmod 755 $(INCLUDEDIR)/adf; \ fi; $(INCLUDEDIR)/adfh : $(INCLUDEDIR) @if [ ! -d $(INCLUDEDIR)/adfh ] ; then \ echo "Making directory $(INCLUDEDIR)/adfh"; \ mkdir -p $(INCLUDEDIR)/adfh; \ chmod 755 $(INCLUDEDIR)/adfh; \ fi; uninstall : -cd tools && $(MAKE) uninstall -cd cgnstools && $(MAKE) uninstall -$(RM) $(INCLUDEDIR)/cgnstypes.h -$(RM) $(INCLUDEDIR)/cgnstypes_f.h -$(RM) $(INCLUDEDIR)/cgnslib.h -$(RM) $(INCLUDEDIR)/cgnswin_f.h -$(RM) $(INCLUDEDIR)/cgns_io.h -$(RM) $(INCLUDEDIR)/cgnsconfig.h -$(RM) $(INCLUDEDIR)/cgnsBuild.defs @if [ -f $(INCLUDEDIR)/cgns.mod ] ; then \ $(RM) $(INCLUDEDIR)/cgns.mod \ fi; -$(RM) $(INCLUDEDIR)/cgns.mod -$(RM) $(LIBDIR)/$(INSTLIB) @if [ -f $(INCLUDEDIR)/adf/ADF.h ] ; then \ $(RM) $(INCLUDEDIR)/adf/ADF.h; \ $(RMDIR) $(INCLUDEDIR)/adf; \ fi; \ if [ -f $(INCLUDEDIR)/adfh/ADFH.h ] ; then \ $(RM) $(INCLUDEDIR)/adfh/ADFH.h; \ $(RMDIR) $(INCLUDEDIR)/adfh; \ fi; \ if [ -f $(INCLUDEDIR)/pcgnslib.h ] ; then \ $(RM) $(INCLUDEDIR)/pcgnslib.h; \ fi; #---------- mid-level library $(OBJDIR)/cgns_error.$(O) : cgns_error.c cgnslib.h cgns_header.h cgns_io.h $(CC) $(COPTS) $(COOUT)$@ -c cgns_error.c $(OBJDIR)/cgns_internals.$(O) : cgns_internals.c cgnslib.h cgns_header.h \ cgns_io.h $(CC) $(COPTS) $(HDF5INC) $(COOUT)$@ -c cgns_internals.c $(OBJDIR)/cgnslib.$(O) : cgnslib.c cgnslib.h cgns_header.h cgns_io.h $(CC) $(COPTS) $(HDF5INC) $(MPIINC) $(COOUT)$@ -c cgnslib.c $(OBJDIR)/cgns_io.$(O) : cgns_io.c cgnslib.h cgns_io.h \ adf/ADF.h @ADFINCS@ $(CC) $(COPTS) $(COOUT)$@ -c cgns_io.c $(OBJDIR)/cg_ftoc.$(O) : cg_ftoc.c fortran_macros.h cgnslib.h \ cgns_header.h cgns_io.h $(CC) $(COPTS) $(HDF5INC) $(F2CFLAGS) $(COOUT)$@ -c cg_ftoc.c $(OBJDIR)/cgio_ftoc.$(O) : cgio_ftoc.c fortran_macros.h cgns_io.h $(CC) $(COPTS) $(HDF5INC) $(F2CFLAGS) $(COOUT)$@ -c cgio_ftoc.c $(OBJDIR)/cg_malloc.$(O) : cg_malloc.c cg_malloc.h $(CC) $(COPTS) $(COOUT)$@ -c cg_malloc.c $(OBJDIR)/cgns_f.$(O) : cgns_f.F90 cgnstypes_f.h $(F77) $(FOPTS_MOD) $(COOUT)$@ -c cgns_f.F90 cgnslib.h : cgnstypes.h cgns_header.h : cgnstypes.h cgns_io.h : cgnstypes.h #---------- ADF $(OBJDIR)/ADF_interface.$(O) : adf/ADF_interface.c \ adf/ADF.h adf/ADF_internals.h $(CC) $(COPTS) -Iadf $(COOUT)$@ -c adf/ADF_interface.c $(OBJDIR)/ADF_internals.$(O) : adf/ADF_internals.c \ adf/ADF.h adf/ADF_internals.h $(CC) $(COPTS) -Iadf $(COOUT)$@ -c adf/ADF_internals.c adf/ADF.h : cgnstypes.h adf/ADF_internals.h : cgnstypes.h #---------- HDF5 $(OBJDIR)/ADFH.$(O) : adfh/ADFH.c adfh/ADFH.h $(CC) $(COPTS) -Iadfh $(HDF5INC) $(MPIINC) $(COOUT)$@ -c adfh/ADFH.c adfh/ADFH.h : cgnstypes.h #---------- PCGNS $(OBJDIR)/pcgnslib.$(O) : pcgnslib.c pcgnslib.h $(CC) $(COPTS) $(HDF5INC) $(MPIINC) $(COOUT)$@ -c pcgnslib.c pcgnslib.h : cgnslib.h CGNS-3.4.0/src/README.config000066400000000000000000000346171343724673500152140ustar00rootroot00000000000000================================================================= To compile the CGNS library under Unix, Linux, Cygwin, Mac, .etc: ================================================================= chmod +x configure ./configure [options] make [target] The arguments in [] are optional, and if given should be specified without the []. The recognized options to configure are: ***** basic options ***** --enable-gcc Normally, the configure script will search for the native C compiler (cc) before trying to find gcc. This option reverses this order. --enable-debug[=OPTS] This enables a debug version of the library. Normally, this just sets the -g option for compiling, and prevents stripping the library and executables. If 'OPTS' is given, this is taken as the compile options to be used instead. i.e. --enable-debug=-g gives the default. --with-system=XXX overrides the default system type (see below) and sets the system type to 'XXX'. If not given, the system type will be determined from the 'cgsystem' script. --enable-legacy build the code using legacy settings. Defines cgsize_t as int and turns of enumeration value scoping (CGNS_ENUM in cgnslib.h) --enable-scope enables scoping of all enumeration values in cgnslib.h by prefixing them with a CG_. For example, ZoneType_t becomes CG_ZoneType_t and Structured becomes CG_Structured. --enable-64bit This option turns on 64-bit compilation, where applicable. If legacy is turned off, then cgsize_t will be a 64-bit integer typedef, otherwise it will be typedef'd as an int. --enable-lfs This enables large file support (files larger than 2 Gb), where applicable. Your kernel must also be capable of LFS for this to make a difference. --with-fortran[=F2C] By default the Fortran interface is enabled, and the configure script trys to determine the proper Fortran to C interface. If you specify --without-fortran or --with-fortran=no, the Fortran interface will not be built. To change the Fortran to C interface, specify 'F2C' as one of LOWERCASE, LOWERCASE_, LOWERCASE__, UPPERCASE, UPPERCASE_, or UPPERCASE__. *** NOTE *** If you are using g77, and want to use the compiler without the -fno-second-underscore flag, then use --with-fortran=LOWERCASE__. This should work fine with the MLL routines, but you will NOT be able to use the ADF routines, since you will get unresolved external references when you try to link. The reason is that g77 appends 2 underscores to names which have an underscore in them (the cg_* routines), but only 1 underscore to names that don't (the adf* routines). I don't know why - but that what's happening (at least with my version of g77). You may play around with the test case in the f2c subdirectory and see if you can come up with a solution - if so, let me know. ************ --enable-shared[=all] This enables the building of a shared library. Currently, only Linux, HP, SGI and SUN OS's are supported. If you specify --enable-shared=all, then the script will also attempt to use shared libraries for HDF5, zlib, and sziplib if HDF5 support is being built. ***** HDF5 options ***** --with-hdf5[=DIR] This enables the CGNS interface to HDF5. If 'DIR' is specified, then it should be the top-level directory of the HDF5 distribution. If not given, the script will check if HDF5 is installed and use that. If not installed, then the script will search for a local distribution. --with-zlib[=LIB] This specifies that zlib is to be used with HDF5. This is only needed if HDF5 was built with zlib support. If 'LIB' is given,it should be the pathname to the zlib library. If not given, the script will check for first an installed version, and then a local distribution. --with-szip[=LIB] This specifies that szip is to be used with HDF5. This is only needed if HDF5 was built with szip support. If 'LIB' is given,it should be the pathname to the szip library. If not given, the script will check for first an installed version, and then a local distribution. ***** cgnstools options ***** --enable-cgnstools This enables the building of CGNStools. If built, a Tcl/Tk installation is required. --with-tcl=TCLdir --with-tk=TKdir This sets the path to the Tcl and/or Tk source distribution. If not given, 'configure' will try first to find an installed version to use, then locally for a source distribution. If only one of these are given, the other will be set from that value. For example: "--with-tcl=$HOME/tcl8.3.1" will automatically set "--with-tk=$HOME/tk8.3.1". The "tkConfig.sh" file from either the installed or source distribution version is used to set the link options to be used in linking the cgiowish, plotwish, and calcwish executable. --disable-cut This sets the NO_CUTTING_PLANE compiler flag to disable a cutting plane is cgnsplot. A cutting plane results in more memory being used by the program since the entire volume mesh is saved rather than just the boundary mesh. --disable-mesh This sets the NO_MESH_BOUNDARIES compiler flag to disable the generation of imin,imax,jmin,jmax,kmin and kmax boundary regions for structured zones. ***** installation options ***** --prefix=PREFIX --exec_prefix=EPREFIX --libdir=LIBDIR --includedir=INCLUDEDIR These set the installation directories for the CGNS library, headers and modules. By default, the library will be installed as: /usr/local/lib/libcgns.a and the headers as: /usr/local/include/cgnslib.h /usr/local/include/cgnswin_f.h and the modules as: /usr/local/include/cgns.mod See the autoconf documentation for a description of these options, or run './configure --help' for a brief overview. Use absolute paths or shell environment variables when specifying a directory, since the 'configure' is interpreted by 'sh' not 'csh'. i.e: use --prefix=$HOME instead of --prefix=~ . In addition to creating the required Makefiles, the configure script will create the file 'make.defs', which contains all the system specific information for building the library. If problems are encountered, this is the file to edit. Make will build put all the object modules in the subdirectory 'lib' along with the CGNS library. The main make targets are: all This is the default target (if target is not given). This builds the CGNS library, the executables in the 'tools' subdirectory, and CGNStools if the --enable-cgnstools option to the script was given. cgns Builds just the CGNS library test Builds and runs the executables in the 'tests' subdirectory install Installs the CGNS library and header files. If the --enable-cgnstools option was given, this will also install the executables in the 'tools' subdirectory and CGNStools. You will need write permission to the installation directories. clean This removes all the object files. The library is not affected. allclean distclean Removes the object files, library and files generated by 'configure' and any generated,object or execuatble files in the subdirectories uninstall Uninstalls the library and headers and CGNStools if installed. You will need write permission to the installation directories. Additional targets: tools builds the code in the tools subdirectory tests builds the code in the tests subdirectory cgnstools builds the code in the cgnstools subdirectory install-cgns Installs library and headers install-tools Installs the executables in the 'tools' subdirectory install-cgnstools Installs CGNStools ---------------------------------------------------------------------- The system type is determined by executing the 'cgsystem' script. ./cgsystem [[-][enable-]64[bit]] [[-]cur[rent]] [[-]conf[igure]] Again, everything in [] are optional, and the [] are not included. If no arguments are given, then 'cgsystem' returns the default system type. The '[-][enable-]64[bit]' option enables 64-bit as for the 'configure' script. The '[-]cur[rent]' option returns the current system type, which is that defined in 'make.system', and the '[-]conf[igure]' option will update the 'make.system' file. Currently defined system types are: ALPHA DEC Alpha/OSF APOLLO HP 300 running Domain/OS BSD386 80[345]86 running BSD BSDM68K Motorola 68K running NetBSD BSDMIPS Mips running NetBSD CONVEX Convex CRAY Cray, Cray-2, Cray XMP CYGWIN POSIX emulation on top of Windows DARWIN Macintosh running Darwin DEC DEC FREEBSD FreeBSD HPPA HP 9000 PA-Risc HPPA10 HP 9000 PA-Risc running OS 10.x HPPA11 HP 9000 PA-Risc running OS 11.x (32-bit) HPPA64 HP 9000 PA-Risc running OS 11.x (64-bit) HPIT HP with 64-bit Intel processor (32-bit) HPIT64 HP with 64-bit Intel processor (64-bit) HP HP I860 Intel Hypercube IBM IBM running AIX IBM64 IBM with AIX 4.3 or above (64-bit) LINUX Linux LINUX64 64-bit Linux M88K Motorola M88100 running Real/IX MACOSX Power Macintosh runing OSx NETBSD NetBSD not defined elseware NEXT NeXT OS2 OS/2 PGON Intel Paragon SGI5 Silicon Graphics running OS 5.x SGI6 Silicon Graphics running OS 6.x SGI64 Silicon Graphics (64-bit) SGI Silicon Graphics SUN3 Sun 3 SUN4 Sun 4, 4c, sparc, .etc SUN64 Sun 4 (64-bit) SUN Sun VAX DEC/Microvax UNKNOWN couldn't determine system type Executing './cgsystem [-]help', will display the above information. ================================================================= To compile under MS Windows: ================================================================= configure.bat [options] nmake [target] The make targets are the same as above. NOTE: This assumes that the cl compiler is in your path, and that the INCLUDE and LIB environment variables are set to include the directories containing the MSC include files and libraries. If not, you will need to use full path names to cl and link, and define INCLUDE and LIB in make.win32. You may also execute VCVARS32.BAT in the BIN directory of your VC installation to set these up prior to running nmake. VC7 USERS: I have added code to cgnslib.c to handle the unresolved reference to __ftol2. You will need to add -DNEED_FTOL2 to your compile options for cgnslib.c to enable this, or add ftol2.obj to your link line. see http://www.manusoft.com/Resources/ARXTips/Main.stm The options to configure are: -MT Build library as multi-threaded using libcmt.lib (default) -MD Build library as multi-threaded using run-time library mscvrt.lib -debug Enable debug (-Zi) option for compiler and (/debug) for linker -lfs Enable large file support (files larger then 2 Gb) -legacy build the code using legacy settings. Defines cgsize_t as int and turns of enumeration value scoping (CGNS_ENUM in cgnslib.h) -64 This option turns on 64-bit compilation, where applicable. If legacy is turned off, then cgsize_t will be a 64-bit integer typedef, otherwise it will be typedef'd as an int. -cgnstools Build cgnstools. This requires the Tcl/Tk to be available. -scope enables scoping of all enumeration values in cgnslib.h by prefixing them with a CG_. For example, ZoneType_t becomes CG_ZoneType_t and Structured becomes CG_Structured. -dll build the CGNS library as a DLL, instead of static -f2c [type] Allows you to override the default Fortran to C interface, which is compatible with Visual Fortran. I you are using a Fortran compiler which uses Unix-type interfaces (i.e. Absoft Fortran), then specify the Fortran to C interface with 'type' as one of LOWERCASE, LOWERCASE_, LOWERCASE__, UPPERCASE, UPPERCASE_, or UPPERCASE__. If 'type' is not given, it defaults to LOWERCASE_, which is the most common. You may also disable the Fortran to C interface completely by setting 'type' to none. -ifort Configure to use the Intel Fortran compiler, ifort. This option will set the UPPERCASE Fortran to C interface option, and replace the F77=f77 with F77=ifort in the make.WIN32 file. -absoft Configure to use the absoft Fortran compiler. This option will set the LOWERCASE Fortran to C interface option. Since the absoft compiler is case-sensitive, you should use lowercase to call the CGNS routines from your Fortran code. If you want to use uppercase calls, then use the -f2c UPPERCASE option. -hdf5 [hdf5dir] This enables CGNS interface to HDF5. If 'hdf5dir' is specified, then it should be the top-level directory of the HDF5 distribution. If not given, the script will search the current drive for a local distribution. -zlib [zliblib] This specifies that zlib is to be used with HDF5. This is only needed if HDF5 was built with zlib support. If 'zliblib' is given,it should be the pathname to the zlib library. If not given, the script will search the current drive for the library. -szip [sziplib] This specifies that szip is to be used with HDF5. This is only needed if HDF5 was built with szip support. If 'sziplib' is given,it should be the pathname to the szip library. If not given, the script will search the current drive for the library. -mpi [mpidir] Defines the MPI location when building HDF5 with MPI support. If 'mpidir' is specified, then it should be the top-level directory of the MPI distribution. If not given, the script will search the current drive for a local distribution. -tcl [TCLdir] -tk [TKdir] This sets the path to the Tcl and/or Tk source distribution. If not given, the script will search the current driver a local distribution. If only one of these are given, the other will be set from that value. These are used only to build cgnstools. -nocut This sets the NO_CUTTING_PLANE compiler flag to disable a cutting plane is cgnsplot. A cutting plane results in more memory being used by the program since the entire volume mesh is saved rather than just the boundary mesh. -nomesh This sets the NO_MESH_BOUNDARIES compiler flag to disable the generation of imin,imax,jmin,jmax,kmin and kmax boundary regions for structured zones. -install instdir Sets the installation directory to 'instdir'. The directory should be specified without spaces, i.e. use c:\Progra~1\CGNS instead of c:\Program Files\CGNS. The default is the root directory of the current drive. The library will be installed as: %installdir%\lib\libcgns.lib and the headers %installdir%\include\cgnslib.h %installdir%\include\cgnswin_f.h and the modules %installdir%\include\cgns.mod ---------------------------------------------------------------------- If you have any additions or corrections to make, please report them at: CGNS-3.4.0/src/SampleScripts/000077500000000000000000000000001343724673500156465ustar00rootroot00000000000000CGNS-3.4.0/src/SampleScripts/CRAY_BlueWaters/000077500000000000000000000000001343724673500205415ustar00rootroot00000000000000CGNS-3.4.0/src/SampleScripts/CRAY_BlueWaters/build_cgns000077500000000000000000000022661343724673500226060ustar00rootroot00000000000000#!/bin/csh # ___ __ _ __ __ # / _ )/ /_ _____ | | /| / /__ _/ /____ _______ # / _ / / // / -_) | |/ |/ / _ `/ __/ -_) __(_-< #/____/_/\_,_/\__/ |__/|__/\_,_/\__/\__/_/ /___/ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Build script for CGNS on Blue Waters (Cray XE/XK) # using cray compilers. # NCSA, University of Illinois Urbana-Champaign # Note: I created a bin directory which contains # mpi links (mpif90, mpicc) to the system compilers # since configure expects only those names (need to fix # this in configure) module swap cce cce/8.3.9 module unload cray-libsci atp module load xpmem dmapp ugni udreg module swap cray-mpich/7.0.3 cray-mpich/7.1.3 module list # use the system zlib set ZLIB=/usr/lib64 # location of the installed HDF5 library set HDF5=$HOME/packages/phdf5_trunk_cray setenv LD_LIBRARY_PATH "$ZLIB" setenv CFLAGS "-O3 " setenv CC "cc" setenv FC "ftn" setenv F77 "ftn" setenv FFLAGS "-O3 " setenv FLIBS "-lz -ldl -I../lib" setenv CLIBS "-lz" setenv LIBS "-lz -ldl" ./configure --verbose \ --enable-parallel \ --with-fortran \ --with-hdf5=$HDF5 \ --with-mpi=$HOME/bin \ --enable-64bit \ --enable-lfs \ --disable-cgnstools \ --disable-x CGNS-3.4.0/src/SampleScripts/IBM_BlueGene_xl/000077500000000000000000000000001343724673500205265ustar00rootroot00000000000000CGNS-3.4.0/src/SampleScripts/IBM_BlueGene_xl/README.txt000066400000000000000000000025731343724673500222330ustar00rootroot00000000000000This example assumes all the needed packages are in ${HOME}/packages and the all the scripts are placed in ${HOME}/packages. NOTE (1): If the system already has HDF5 installed then you can use it instead, as long as it was build with --enable-parallel. (1) Building zlib from source: Download and extract the zlib source: http://www.zlib.net/ (a) cd into the top level zlib source directory. (b) modify and run the script: ../build_zlib (2) Building hdf5 from source: (a) From the top level of the hdf5 library, change the ${HOME}/packages to where zlib was installed in STEP 1. ../build_hdf5 --without-pthread --disable-shared --enable-parallel --enable-production \ --enable-fortran --enable-fortran2003 \ --disable-stream-vfd --disable-direct-vfd \ --with-zlib=${HOME}/packages/zlib-1.2.8/lib --prefix=${HOME}/packages/phdf5-trunk where prefix is set for where the hdf5 library will get installed. There should be no need to modify in the script. (3) Building cgns from source: (a) cd into the cgns/src directory (b) modify and run: /build_cgns (c) make (d) To make the tests: cd ptests make (4) IMPORTANT PARAMETERS FOR GOOD PERFORMANCE (i) The environment variable BGLOCKLESSMPIO_F_TYPE=0x47504653 should be set. * Set using qsub --env BGLOCKLESSMPIO_F_TYPE=0x47504653 (ii) does CGNS_FILETYPE need to be set ???? CGNS-3.4.0/src/SampleScripts/IBM_BlueGene_xl/build_cgns000077500000000000000000000012401343724673500225620ustar00rootroot00000000000000#!/bin/tcsh set HDF5=$HOME/packages/phdf5-1_8 setenv LD_LIBRARY_PATH "HOME/packages/zlib-1.2.8/lib" setenv CFLAGS "-O2 " setenv CC "mpixlc" setenv FC "mpixlf2003" setenv F77 "mpixlf2003" setenv FFLAGS "-O2 " setenv LDFLAGS "-I$HOME/packages/zlib-1.2.8/lib/include" setenv FLIBS "-L$HOME/packages/zlib-1.2.8/lib/lib -lz" setenv CLIBS "-I$HOME/packages/zlib-1.2.8/lib/include -L$HOME/packages/zlib-1.2.8/lib/lib -lz" ./configure --verbose \ --enable-parallel \ --with-fortran \ --with-hdf5=$HDF5 \ --with-mpi="/soft/compilers/wrappers/xl" \ --with-zlib="$HOME/packages/zlib-1.2.8/lib" \ --enable-64bit \ --enable-lfs \ --disable-cgnstools \ --disable-x # --enable-debug CGNS-3.4.0/src/SampleScripts/IBM_BlueGene_xl/build_hdf5000077500000000000000000000143751343724673500224730ustar00rootroot00000000000000#!/bin/sh # Do the HDF5 library configure, make, and tests for Blue Gene/P # Usage: bgmakeh5 USAGE() { cat <> "$resultfile" 2>&1 if [ $? -ne 0 ]; then echo "error in '$banner'. makeh5 aborted." exit 1 fi } # Main body # Setup exit steps and print starting time trap TIMESTAMP 0 TIMESTAMP # Make sure we are at the library root level # by checking couple typical files. Not bullet-proof. if [ ! \( -d $SRCDIR/src -a -d $SRCDIR/config -a -f $SRCDIR/configure \) ] then echo "Could not find the source dir or configure script. Abort." exit 1 fi # no configure if already done. if [ ! -f config.status ]; then echo "$CONFIGURE $@ ..." (TIMESTAMP; nerror=0; $CONFIGURE $@ < /dev/null || nerror=1; TIMESTAMP; exit $nerror) > '#config' 2>&1 if [ $? -ne 0 ]; then echo "error in Configure. Aborted." exit 1 fi else echo configure.status already exists. Skip configure. fi # need to edit the src/H5pubconf.h file. # fork() compile okay but does not exec. xfile=src/H5pubconf.h for macro in H5_HAVE_FORK; do echo comment out $macro from $xfile ed -s $xfile <> '#make' 2>&1 # Compile the library # Okay to use parallel gmake for compiling gmake -i -j 8 >> '#make' 2>&1 gmake -i install #test_log="#test.$$" # Do make check #env HDF5_Make_Ignore=yes gmake check > $test_log 2>&1 #if grep FAILED $test_log; then # echo "***FAILED detected in " $test_log #fi CGNS-3.4.0/src/SampleScripts/IBM_BlueGene_xl/build_zlib000077500000000000000000000002511343724673500225710ustar00rootroot00000000000000#!/bin/tcsh setenv CC mpixlc setenv CFLAGS "-O3 -qsimd=auto -qhot=level=1 -qprefetch -qunroll=yes" ./configure --prefix=$PROJECTS_DIR/zlib-1.2.8/lib make make install CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/000077500000000000000000000000001343724673500200765ustar00rootroot00000000000000CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/000077500000000000000000000000001343724673500211515ustar00rootroot00000000000000CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/README.txt000066400000000000000000000036761343724673500226630ustar00rootroot000000000000002.2 Building on SGI (Lustre) 0. Module Enviromnment: 1) comp-intel/2015.0.090 2) mpi-intel/5.0.1.035 (mpi-sgi/mpt.2.11r13 generates strange error messages at run time) 1. Building zlib from source: Download and extract the zlib source: http://www.zlib.net/ (a) cd into the top level zlib source directory. (b) modify and run the script: ../build_zlib (c) Note: if you get errors in steps 2 or 3 below because it cannot find the zlib.h or zlib.a files, it may be necessary to do the following: cd $HOME/packages/zlib-1.2.8 ln -s lib/include/zlib.h . ln -s lib/lib/libz.a . 2. Building hdf5 from source (version 1.8.14) (a) From the top level of the hdf5 library, change the ${HOME}/packages to where zlib was installed in STEP 1. (b) ../build_hdf5 3. Building cgns from source: Note before compiling: CGNS expects the compilers to be mpicc and mpif90. Therefore, create a directory 'bin' in your home directory and add symbolic links to the mpi/intel wrappers: mpicc -> /nasa/intel/impi/5.0.1.035/bin64/mpiicc* mpif90 -> /nasa/intel/impi/5.0.1.035/bin64/mpiifort* The script will point to these symbolic links. (a) cd into the cgns/src directory (b) modify and run: /build_cgns (need to point to your own bin directory as noted above) (c) make (d) To make the tests: cd ptests; make 4. Running: (a) tests need to be submitted as a job; see, e.g.: run_cgns.sh 5. IMPORTANT PARAMETERS FOR GOOD PERFORMANCE (a) The Lustre parameters have not been fully tested. (b) It is best to create a directory with the lustre file parameters, for example: On Pleiades, cd to /nobackupp8/: mkdir 2M lfs setstripe -c 64 -s 2m 2M Then run in subdirectory 2M, using example submit script run_cgns.sh (appropriately modified) This will use a count of 64 and a strip size of 2M, which has shown good performance. CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/build_cgns000077500000000000000000000015771343724673500232220ustar00rootroot00000000000000#!/bin/csh set HDF5=$HOME/packages/phdf5-1_8_14 setenv LD_LIBRARY_PATH "$HOME/packages/zlib-1.2.8/lib" setenv CFLAGS "-O2 " #setenv CC "mpicc" #setenv FC "mpif90" #setenv F77 "mpif90" setenv CC "/nasa/intel/impi/5.0.1.035/bin64/mpiicc" setenv FC "/nasa/intel/impi/5.0.1.035/bin64/mpiifort" setenv F77 "/nasa/intel/impi/5.0.1.035/bin64/mpiifort" setenv FFLAGS "-O2 " setenv LDFLAGS "-I$HOME/packages/zlib-1.2.8/lib/include" setenv FLIBS "-lmpi -L$HOME/packages/zlib-1.2.8/lib/lib -lz" setenv CLIBS "-lmpi -I$HOME/packages/zlib-1.2.8/lib/include -L$HOME/packages/zlib-1.2.8/lib/lib -lz" ./configure --verbose \ --enable-parallel \ --with-fortran \ --with-hdf5=$HDF5 \ --with-mpi="/home1/mbreiten/bin" \ --with-zlib="$LD_LIBRARY_PATH" \ --enable-64bit \ --enable-lfs \ --disable-cgnstools \ --disable-x # --enable-debug # --enable-64bit \ # --with-mpi="/nasa/intel/impi/5.0.1.035/intel64/bin/" \ CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/build_hdf5000077500000000000000000000007111343724673500231030ustar00rootroot00000000000000#!/bin/csh #setenv CC mpicc #setenv FC mpif90 setenv CC /nasa/intel/impi/5.0.1.035/bin64/mpiicc setenv FC /nasa/intel/impi/5.0.1.035/bin64/mpiifort setenv CFLAGS "-O3" setenv FCFLAGS "-O3" ./configure --without-pthread --disable-shared --enable-parallel --enable-production --enable-fortran --enable-fortran2003 --disable-stream-vfd --disable-direct-vfd --with-zlib=${HOME}/packages/zlib-1.2.8/lib --prefix=${HOME}/packages/phdf5-1_8_14 make make install CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/build_zlib000077500000000000000000000002311343724673500232120ustar00rootroot00000000000000#!/bin/csh setenv CC /nasa/intel/impi/5.0.1.035/bin64/mpiicc setenv CFLAGS "-O2 " ./configure --prefix=$HOME/packages/zlib-1.2.8/lib make make install CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/Intel/run_cgns.sh000077500000000000000000000011441343724673500233260ustar00rootroot00000000000000#PBS -S /bin/csh #PBS -l select=4:ncpus=16:mpiprocs=16:model=san #PBS -l walltime=01:00:00 #PBS -j oe #PBS -q debug #PBS -W group_list=a1519 module purge module load comp-intel/2015.0.090 module load mpi-intel/5.0.1.035 # By default, PBS executes your job from your home directory. # However, you can use the environment variable # PBS_O_WORKDIR to change to the directory where # you submitted your job. cd $PBS_O_WORKDIR #mpiexec_mpt ./benchmark_hdf5 /nasa/intel/impi/5.0.1.035/bin64/mpiexec.hydra -env I_MPI_EXTRA_FILESYSTEM on -env I_MPI_EXTRA_FILESYSTEM_LIST lustre ./benchmark_hdf5 # -end of script- CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/README.txt000066400000000000000000000021231343724673500215720ustar00rootroot000000000000002.2 Building on SGI (Lustre) 1. Building zlib from source: Download and extract the zlib source: http://www.zlib.net/ (a) cd into the top level zlib source directory. (b) modify and run the script: ../build_zlib (c) Note: if you get errors in steps 2 or 3 below because it cannot find the zlib.h or zlib.a files, it may be necessary to do the following: cd $HOME/packages/zlib-1.2.8 ln -s lib/include/zlib.h . ln -s lib/lib/libz.a . 2. Building hdf5 from source (a) From the top level of the hdf5 library, change the ${HOME}/packages to where zlib was installed in STEP 1. (b) ../build_hdf5 3. Building cgns from source: (a) cd into the cgns/src directory (b) modify and run: /build_cgns (c) make (d) To make the tests: cd ptests; make 4. Running: (a) tests need to be submitted as a job; see, e.g.: run_cgns.sh 5. IMPORTANT PARAMETERS FOR GOOD PERFORMANCE (a) The Lustre parameters have not been fully tested. (b) On Pleiades, lfs setstripe -c 64 -s 0 /nobackupp8/

, has shown good performance. CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/build_cgns000077500000000000000000000012021343724673500221300ustar00rootroot00000000000000#!/bin/csh set HDF5=$HOME/packages/phdf5-1_8 setenv LD_LIBRARY_PATH "$HOME/packages/zlib-1.2.8/lib:/nasa/sgi/mpt/2.12r26/lib" setenv CFLAGS "-O2 " setenv CC "mpicc" setenv FC "mpif90" setenv F77 "mpif90" setenv FFLAGS "-O2 " setenv FLIBS "-lmpi -L$HOME/packages/zlib-1.2.8/lib/lib -lz" setenv CLIBS "-lmpi -I$HOME/packages/zlib-1.2.8/lib/include -L$HOME/packages/zlib-1.2.8/lib/lib -lz" ./configure --verbose \ --prefix="$HOME/scratch/cgns_1_8" \ --enable-parallel \ --with-fortran \ --with-hdf5=$HDF5 \ --with-mpi="/nasa/sgi/mpt/2.12r26" \ --with-zlib="$HOME/packages/zlib-1.2.8/lib" \ --enable-64bit \ --enable-lfs \ --disable-cgnstools CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/build_hdf5000077500000000000000000000011661343724673500220350ustar00rootroot00000000000000#!/bin/csh # modules loaded (Pleiades) # # module load comp-intel/2016.2.181 # module load mpi-sgi/mpt.2.12r26 setenv CC mpicc setenv FC mpif90 setenv CFLAGS "-O3" setenv FCFLAGS "-O3" grep -q "1.10" ./configure.ac if ( $? == 0 ) then set CONFIG_OPT = "--enable-build-mode=production --enable-fortran" set VERS = "1_10" else set CONFIG_OPT = "--enable-production --enable-fortran --enable-fortran2003" set VERS = "1_8" endif ./configure --without-pthread --disable-shared --enable-parallel $CONFIG_OPT --disable-direct-vfd --with-zlib=$HOME/packages/zlib-1.2.8/lib --prefix=$HOME/packages/phdf5-$VERS make make install CGNS-3.4.0/src/SampleScripts/SGI_Pleiades/build_zlib000077500000000000000000000001661343724673500221460ustar00rootroot00000000000000#!/bin/csh setenv CC mpicc setenv CFLAGS "-O2 " ./configure --prefix=$HOME/packages/zlib-1.2.8/lib make make installCGNS-3.4.0/src/SampleScripts/SGI_Pleiades/run_cgns.sh000066400000000000000000000007441343724673500222550ustar00rootroot00000000000000#PBS -S /bin/csh #PBS -l select=1024:ncpus=16:mpiprocs=16:model=san #PBS -l walltime=00:15:00 #PBS -j oe #PBS -q low #PBS -W group_list=a1519 module load mpi-sgi/mpt.2.12r26 module load comp-intel/2016.2.181 # By default, PBS executes your job from your home directory. # However, you can use the environment variable # PBS_O_WORKDIR to change to the directory where # you submitted your job. cd $PBS_O_WORKDIR mpiexec_mpt ./benchmark_hdf5 # -end of script- CGNS-3.4.0/src/SampleScripts/cmake.xl.mpich.sh000077500000000000000000000025551343724673500210150ustar00rootroot00000000000000#!/bin/tcsh # # This script uses cmake to build cgns, parallel build, # it should be executed some place other then in the # source directory. # Note: # Does szip support # set to where hdf5 is installed. set HDF5=/mnt/scr1/trunk/hdf5 # set to where the mpi compilers are set MPI=/mnt/hdf/packages/mpich/3.1.3_xl15.1.0/ppc64/bin # set to where the source is located set CGNS=/mnt/scr1/HDF5_Parallel cmake \ -D CMAKE_C_COMPILER:PATH=$MPI/mpicc \ -D CMAKE_Fortran_COMPILER:PATH=$MPI/mpif90 \ $CGNS ccmake \ -D CGNS_BUILD_SHARED:BOOL=OFF \ -D CGNS_USE_SHARED:BOOL=OFF \ -D HDF5_NEED_ZLIB:BOOL=ON \ -D CMAKE_EXE_LINKER_FLAGS:STRING="" \ -D CMAKE_STATIC_LINKER_FLAGS:STRING="" \ -D MPIEXEC:STRING=$MPI/mpiexec \ -D MPI_C_COMPILER:STRING=$MPI/mpicc \ -D MPI_Fortran_COMPILER:STRING=$MPI/mpif90 \ -D CGNS_ENABLE_HDF5:BOOL=ON \ -D CGNS_ENABLE_TESTS:BOOL=ON \ -D CGNS_BUILD_CGNSTOOLS:BOOL=OFF \ -D HDF5_LIBRARY_DIR:PATH=$HDF5/lib \ -D HDF5_LIBRARY:STRING=$HDF5/lib/libhdf5.a \ -D HDF5_INCLUDE_DIR:PATH=$HDF5/include \ -D HDF5_INCLUDE_PATH:PATH=$HDF5/include \ -D HDF5_NEED_MPI:BOOL=ON \ -D CGNS_ENABLE_FORTRAN:BOOL=ON \ -D CGNS_ENABLE_64BIT:BOOL=ON \ -D CMAKE_C_COMPILER:PATH=$MPI/mpicc \ -D CMAKE_Fortran_COMPILER:PATH=$MPI/mpif90 \ -D CGNS_ENABLE_PARALLEL:BOOL=ON \ -D CMAKE_INSTALL_PREFIX:PATH="./" \ . # then do: # make # make install CGNS-3.4.0/src/Test_UserGuideCode/000077500000000000000000000000001343724673500165435ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/000077500000000000000000000000001343724673500177175ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/CMakeLists.txt000066400000000000000000000042611343724673500224620ustar00rootroot00000000000000######### # Tests # ######### # Link all the executables to cgns and hdf5 link_directories(.) link_libraries(cgns_static) if (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) link_libraries(${HDF5_LIBRARY}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) link_libraries(${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) link_libraries(${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) link_libraries(${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) if (NOT WIN32) link_libraries(m) endif (NOT WIN32) # Set the files needed by each test set (examples write_grid_str write_bc_str write_bcpnts_str write_bcpnts_unst write_con2zn_str write_con2zn_genrl_str write_convergence write_descriptor write_dimensional write_flowcent_str write_flowcentrind_str write_discreteface_str write_floweqn_str write_flowvert_str write_flowvert_unst write_grid2zn_str write_grid_unst write_nondimensional write_timevert_str read_bc_str read_bcpnts_str read_bcpnts_unst read_con2zn_genrl_str read_con2zn_str read_convergence read_descriptor read_dimensional read_flowcent_str read_flowcentrind_str read_discreteface_str read_floweqn_str read_flowvert_str read_flowvert_unst read_grid2zn_str read_grid_str read_grid_unst read_nondimensional read_timevert_str ) # Build each test foreach (example ${examples}) add_executable (${example} ${example}.c) endforeach (example ${examples}) # Add the tests so that ctest can find them #if (CGNS_ENABLE_TESTS) # foreach (example ${examples}) # add_test (${example} ${example}) # endforeach (example ${examples}) #endif (CGNS_ENABLE_TESTS) # write_grid_str # write_flowvert_str # write_nondimensional # write_descriptor # write_convergence # write_floweqn_str # write_bcpnts_str # write_grid_unst # write_flowvert_unst # write_dimensional # write_descriptor # write_convergence # write_bcpnts_unst # write_grid_str # write_timevert_str # write_grid_str # write_flowcent_str # write_bc_str # write_grid_str # write_flowcentrind_str # write_discreteface_str # write_grid2zn_str # write_con2zn_str # write_grid2zn_str # write_con2zn_genrl_str CGNS-3.4.0/src/Test_UserGuideCode/C_code/Makefile000066400000000000000000000012331343724673500213560ustar00rootroot00000000000000 DIRS = \ Test_Grid_Str \ Test_Grid_Unstr \ Test_Grid_Str_Timeacc \ Test_Grid_Str_FlowCent \ Test_Grid_Str_FlowCentRind \ Test_Grid_Str_2zn \ Test_Grid_Str_2zngenrl #---------- all : @status=0;for d in $(DIRS) ; do \ cd $$d && $(MAKE); \ status=`expr $$status + $$?`; \ cd ..; \ done;\ if [ $$status -ne 0 ]; then \ exit $$status; \ fi test : $(TESTS) @status=0;for d in $(DIRS) ; do \ cd $$d && $(MAKE); \ status=`expr $$status + $$?`; \ cd ..; \ done;\ if [ $$status -ne 0 ]; then \ exit $$status; \ fi;\ ./test.sh; \ exit $$?; clean : $(CLEAN) -@for d in $(DIRS) ; do \ cd $$d && $(MAKE) clean; \ cd ..; \ done; CGNS-3.4.0/src/Test_UserGuideCode/C_code/README000066400000000000000000000021251343724673500205770ustar00rootroot00000000000000This contains a set of C test cases from UserGuideCode. (modified for use with V3.3) If CGNS is compiled with --enable-64bit, then the created "grid_c.cgns" file will use 64-bit integers as appropriate Currently, the testing (make test) only compares output files of some of the variables written to and read from the grid_c.cgns file. It does not check whether the 64-bit integers were necessarily written as I8 or not. To check this, one could use "cgnsview" to look at the grid_c.cgns file(s) directly. For example, with 64-bit integers, in the cgns file under Test_Grid_Str, the PointList data type under the BC_t nodes (under ZoneBC_t) should be I8 rather than I4. ***** NOTE ***** You will first have to edit the Makefile include to set up your CGNS location and compiler and options Edit 'make.defs' for Linux/Unix Not checked for Windows yet. To just build the code, use make on linux/Unix To build and run the tests, use make test Note: executables, output files, and the resulting CGNS file are put in each Subdirectory/build/ directory To clean everything up, use make clean CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/000077500000000000000000000000001343724673500224335ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/Makefile000066400000000000000000000052221343724673500240740ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowvert_str$(EXE) WRITE3 = write_nondimensional$(EXE) WRITE4 = write_descriptor$(EXE) WRITE5 = write_convergence$(EXE) WRITE6 = write_floweqn_str$(EXE) WRITE7 = write_bcpnts_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowvert_str$(EXE) READ3 = read_nondimensional$(EXE) READ4 = read_descriptor$(EXE) READ5 = read_convergence$(EXE) READ6 = read_floweqn_str$(EXE) READ7 = read_bcpnts_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) $(WRITE4) $(WRITE5) $(WRITE6) $(WRITE7) READ_PROGS = $(READ1) $(READ2) $(READ3) $(READ4) $(READ5) $(READ6) $(READ7) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(WRITE4) $(READ4) > $(OUTDIR)/output4 -$(DIFF) OUTPUT4 $(OUTDIR)/output4 $(WRITE4) $(READ4) > $(OUTDIR)/output5 -$(DIFF) OUTPUT5 $(OUTDIR)/output5 $(WRITE6) $(READ6) > $(OUTDIR)/output6 -$(DIFF) OUTPUT6 $(OUTDIR)/output6 $(WRITE7) $(READ7) > $(OUTDIR)/output7 -$(DIFF) OUTPUT7 $(OUTDIR)/output7 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid_str.c $(LIBS) $(WRITE2) : ../write_flowvert_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_flowvert_str.c $(LIBS) $(WRITE3) : ../write_nondimensional.c $(CC) $(COPTS) $(FEOUT)$@ ../write_nondimensional.c $(LIBS) $(WRITE4) : ../write_descriptor.c $(CC) $(COPTS) $(FEOUT)$@ ../write_descriptor.c $(LIBS) $(WRITE5) : ../write_convergence.c $(CC) $(COPTS) $(FEOUT)$@ ../write_convergence.c $(LIBS) $(WRITE6) : ../write_floweqn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_floweqn_str.c $(LIBS) $(WRITE7) : ../write_bcpnts_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_bcpnts_str.c $(LIBS) $(READ1) : ../read_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid_str.c $(LIBS) $(READ2) : ../read_flowvert_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_flowvert_str.c $(LIBS) $(READ3) : ../read_nondimensional.c $(CC) $(COPTS) $(FEOUT)$@ ../read_nondimensional.c $(LIBS) $(READ4) : ../read_descriptor.c $(CC) $(COPTS) $(FEOUT)$@ ../read_descriptor.c $(LIBS) $(READ5) : ../read_convergence.c $(CC) $(COPTS) $(FEOUT)$@ ../read_convergence.c $(LIBS) $(READ6) : ../read_floweqn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_floweqn_str.c $(LIBS) $(READ7) : ../read_bcpnts_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_bcpnts_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT1000066400000000000000000000002271343724673500235000ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT2000066400000000000000000000002151343724673500234760ustar00rootroot00000000000000 Successfully read flow solution from file grid_c.cgns For example, r,p[8][16][20]= 20.000000, 16.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT3000066400000000000000000000016071343724673500235050ustar00rootroot00000000000000 DataClass = NormalizedByUnknownDimensional ReferenceState = ReferenceQuantities Variable=Mach data= 4.60000000 Variable=Reynolds data= 6000000.00000000 Variable=Mach_Velocity data= 4.60000000 Variable=Mach_VelocitySound data= 1.00000000 Variable=Reynolds_Velocity data= 4.60000000 Variable=Reynolds_Length data= 1.00000000 Variable=Reynolds_ViscosityKinematic data= 0.00000077 Variable=Density data= 1.00000000 Variable=Pressure data= 0.71428571 Variable=VelocitySound data= 1.00000000 Variable=ViscosityMolecular data= 0.00000077 Variable=LengthReference data= 1.00000000 Variable=VelocityX data= 4.60000000 Variable=VelocityY data= 0.00000000 Variable=VelocityZ data= 0.00000000 Successfully read nondimensional info from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT4000066400000000000000000000002031343724673500234750ustar00rootroot00000000000000 The descriptor is: Supersonic vehicle with landing gear M=4.6, Re=6 million Successfully read descriptors from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT5000066400000000000000000000002651343724673500235060ustar00rootroot00000000000000 Successfully read cl history from file grid_c.cgns values are: 1.000000, 2.000000, 3.000000, 4.000000, 5.000000 6.000000, 7.000000, 8.000000, 9.000000, 10.000000 CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT6000066400000000000000000000004661343724673500235120ustar00rootroot00000000000000 Eqn dimension = 3 Gov eqn = NSTurbulent diffusion= 0, 1, 0, 0, 0, 0 Gas model type = Ideal gamma = 1.400000 Turbulence closure type = EddyViscosity turb prandtl number = 0.900000 Turbulence model type = OneEquation_SpalartAllmaras Successfully read equation set info from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str/OUTPUT7000066400000000000000000000060751343724673500235150ustar00rootroot00000000000000 BC number: 1 name= Ilo type= BCTunnelInflow no of pts= 153 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=1,1,1 ipnts[1][0], [1][1], [1][2]=1,1,2 ipnts[2][0], [2][1], [2][2]=1,1,3 ipnts[3][0], [3][1], [3][2]=1,1,4 ipnts[4][0], [4][1], [4][2]=1,1,5 ipnts[5][0], [5][1], [5][2]=1,1,6 ipnts[6][0], [6][1], [6][2]=1,1,7 ipnts[7][0], [7][1], [7][2]=1,1,8 ipnts[8][0], [8][1], [8][2]=1,1,9 ipnts[9][0], [9][1], [9][2]=1,2,1 BC number: 2 name= Ihi type= BCExtrapolate no of pts= 153 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=21,1,1 ipnts[1][0], [1][1], [1][2]=21,1,2 ipnts[2][0], [2][1], [2][2]=21,1,3 ipnts[3][0], [3][1], [3][2]=21,1,4 ipnts[4][0], [4][1], [4][2]=21,1,5 ipnts[5][0], [5][1], [5][2]=21,1,6 ipnts[6][0], [6][1], [6][2]=21,1,7 ipnts[7][0], [7][1], [7][2]=21,1,8 ipnts[8][0], [8][1], [8][2]=21,1,9 ipnts[9][0], [9][1], [9][2]=21,2,1 BC number: 3 name= Jlo type= BCWallInviscid no of pts= 189 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=1,1,1 ipnts[1][0], [1][1], [1][2]=1,1,2 ipnts[2][0], [2][1], [2][2]=1,1,3 ipnts[3][0], [3][1], [3][2]=1,1,4 ipnts[4][0], [4][1], [4][2]=1,1,5 ipnts[5][0], [5][1], [5][2]=1,1,6 ipnts[6][0], [6][1], [6][2]=1,1,7 ipnts[7][0], [7][1], [7][2]=1,1,8 ipnts[8][0], [8][1], [8][2]=1,1,9 ipnts[9][0], [9][1], [9][2]=2,1,1 BC number: 4 name= Jhi type= BCWallInviscid no of pts= 189 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=1,17,1 ipnts[1][0], [1][1], [1][2]=1,17,2 ipnts[2][0], [2][1], [2][2]=1,17,3 ipnts[3][0], [3][1], [3][2]=1,17,4 ipnts[4][0], [4][1], [4][2]=1,17,5 ipnts[5][0], [5][1], [5][2]=1,17,6 ipnts[6][0], [6][1], [6][2]=1,17,7 ipnts[7][0], [7][1], [7][2]=1,17,8 ipnts[8][0], [8][1], [8][2]=1,17,9 ipnts[9][0], [9][1], [9][2]=2,17,1 BC number: 5 name= Klo type= BCWallInviscid no of pts= 357 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=1,1,1 ipnts[1][0], [1][1], [1][2]=1,2,1 ipnts[2][0], [2][1], [2][2]=1,3,1 ipnts[3][0], [3][1], [3][2]=1,4,1 ipnts[4][0], [4][1], [4][2]=1,5,1 ipnts[5][0], [5][1], [5][2]=1,6,1 ipnts[6][0], [6][1], [6][2]=1,7,1 ipnts[7][0], [7][1], [7][2]=1,8,1 ipnts[8][0], [8][1], [8][2]=1,9,1 ipnts[9][0], [9][1], [9][2]=1,10,1 BC number: 6 name= Khi type= BCWallInviscid no of pts= 357 (these points read here, but only some printed out:) ipnts[0][0], [0][1], [0][2]=1,1,9 ipnts[1][0], [1][1], [1][2]=1,2,9 ipnts[2][0], [2][1], [2][2]=1,3,9 ipnts[3][0], [3][1], [3][2]=1,4,9 ipnts[4][0], [4][1], [4][2]=1,5,9 ipnts[5][0], [5][1], [5][2]=1,6,9 ipnts[6][0], [6][1], [6][2]=1,7,9 ipnts[7][0], [7][1], [7][2]=1,8,9 ipnts[8][0], [8][1], [8][2]=1,9,9 ipnts[9][0], [9][1], [9][2]=1,10,9 Successfully read BCs (PointList format) from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zn/000077500000000000000000000000001343724673500232245ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zn/Makefile000066400000000000000000000017201343724673500246640ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid2zn_str$(EXE) WRITE2 = write_con2zn_str$(EXE) READ1 = read_grid2zn_str$(EXE) READ2 = read_con2zn_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid2zn_str.c $(LIBS) $(WRITE2) : ../write_con2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_con2zn_str.c $(LIBS) $(READ1) : ../read_grid2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid2zn_str.c $(LIBS) $(READ2) : ../read_con2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_con2zn_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zn/OUTPUT1000066400000000000000000000003361343724673500242720ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 zone 2 x,y,z[8][16][20]= 40.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zn/OUTPUT2000066400000000000000000000004721343724673500242740ustar00rootroot00000000000000 In zone 1: donor name=Zone 2 range (this zone)=21,1,1,21,17,9 range (donor zone)=1,1,1,1,17,9 transform=1,2,3 In zone 2: donor name=Zone 1 range (this zone)=1,1,1,1,17,9 range (donor zone)=21,1,1,21,17,9 transform=1,2,3 Successfully read 1-to-1 connectivity info from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zngenrl/000077500000000000000000000000001343724673500242545ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zngenrl/Makefile000066400000000000000000000017651343724673500257250ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid2zn_str$(EXE) WRITE2 = write_con2zn_genrl_str$(EXE) READ1 = read_grid2zn_str$(EXE) READ2 = read_con2zn_genrl_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid2zn_str.c $(LIBS) $(WRITE2) : ../write_con2zn_genrl_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_con2zn_genrl_str.c $(LIBS) $(READ1) : ../read_grid2zn_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid2zn_str.c $(LIBS) $(READ2) : ../read_con2zn_genrl_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_con2zn_genrl_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zngenrl/OUTPUT1000066400000000000000000000003361343724673500253220ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 zone 2 x,y,z[8][16][20]= 40.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_2zngenrl/OUTPUT2000066400000000000000000000043301343724673500253210ustar00rootroot00000000000000 In zone 1: donor name=Zone 2 number of connectivity pts=153 grid location=Vertex connectivity type=Abutting1to1 pointset type=PointList donor zonetype=Structured donor pointset type=PointListDonor ipnts and ipntsdonor arrays read, only some written out here: ipnts[0][0], [0][1], [0][2]=21,1,1 ipntsdonor[0][0], [0][1], [0][2]=1,1,1 ipnts[1][0], [1][1], [1][2]=21,1,2 ipntsdonor[1][0], [1][1], [1][2]=1,1,2 ipnts[2][0], [2][1], [2][2]=21,1,3 ipntsdonor[2][0], [2][1], [2][2]=1,1,3 ipnts[3][0], [3][1], [3][2]=21,1,4 ipntsdonor[3][0], [3][1], [3][2]=1,1,4 ipnts[4][0], [4][1], [4][2]=21,1,5 ipntsdonor[4][0], [4][1], [4][2]=1,1,5 ipnts[5][0], [5][1], [5][2]=21,1,6 ipntsdonor[5][0], [5][1], [5][2]=1,1,6 ipnts[6][0], [6][1], [6][2]=21,1,7 ipntsdonor[6][0], [6][1], [6][2]=1,1,7 ipnts[7][0], [7][1], [7][2]=21,1,8 ipntsdonor[7][0], [7][1], [7][2]=1,1,8 ipnts[8][0], [8][1], [8][2]=21,1,9 ipntsdonor[8][0], [8][1], [8][2]=1,1,9 ipnts[9][0], [9][1], [9][2]=21,2,1 ipntsdonor[9][0], [9][1], [9][2]=1,2,1 In zone 2: donor name=Zone 1 number of connectivity pts=153 grid location=Vertex connectivity type=Abutting1to1 pointset type=PointList donor zonetype=Structured donor pointset type=PointListDonor ipnts and ipntsdonor arrays read, only some written out here: ipnts[0][0], [0][1], [0][2]=1,1,1 ipntsdonor[0][0], [0][1], [0][2]=21,1,1 ipnts[1][0], [1][1], [1][2]=1,1,2 ipntsdonor[1][0], [1][1], [1][2]=21,1,2 ipnts[2][0], [2][1], [2][2]=1,1,3 ipntsdonor[2][0], [2][1], [2][2]=21,1,3 ipnts[3][0], [3][1], [3][2]=1,1,4 ipntsdonor[3][0], [3][1], [3][2]=21,1,4 ipnts[4][0], [4][1], [4][2]=1,1,5 ipntsdonor[4][0], [4][1], [4][2]=21,1,5 ipnts[5][0], [5][1], [5][2]=1,1,6 ipntsdonor[5][0], [5][1], [5][2]=21,1,6 ipnts[6][0], [6][1], [6][2]=1,1,7 ipntsdonor[6][0], [6][1], [6][2]=21,1,7 ipnts[7][0], [7][1], [7][2]=1,1,8 ipntsdonor[7][0], [7][1], [7][2]=21,1,8 ipnts[8][0], [8][1], [8][2]=1,1,9 ipntsdonor[8][0], [8][1], [8][2]=21,1,9 ipnts[9][0], [9][1], [9][2]=1,2,1 ipntsdonor[9][0], [9][1], [9][2]=21,2,1 Successfully read general 1-to-1 connectivity info from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCent/000077500000000000000000000000001343724673500242345ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCent/Makefile000066400000000000000000000024061343724673500256760ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowcent_str$(EXE) WRITE3 = write_bc_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowcent_str$(EXE) READ3 = read_bc_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) READ_PROGS = $(READ1) $(READ2) $(READ3) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid_str.c $(LIBS) $(WRITE2) : ../write_flowcent_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_flowcent_str.c $(LIBS) $(WRITE3) : ../write_bc_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_bc_str.c $(LIBS) $(READ1) : ../read_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid_str.c $(LIBS) $(READ2) : ../read_flowcent_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_flowcent_str.c $(LIBS) $(READ3) : ../read_bc_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_bc_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCent/OUTPUT1000066400000000000000000000002271343724673500253010ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCent/OUTPUT2000066400000000000000000000002151343724673500252770ustar00rootroot00000000000000 Successfully read flow solution from file grid_c.cgns For example, r,p[7][15][19]= 19.000000, 15.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCent/OUTPUT3000066400000000000000000000012361343724673500253040ustar00rootroot00000000000000 BC number: 1 name= Ilo type= BCTunnelInflow i-range= 1,1 j-range= 1,17 k-range= 1,9 BC number: 2 name= Ihi type= BCExtrapolate i-range= 21,21 j-range= 1,17 k-range= 1,9 BC number: 3 name= Jlo type= BCWallInviscid i-range= 1,21 j-range= 1,1 k-range= 1,9 BC number: 4 name= Jhi type= BCWallInviscid i-range= 1,21 j-range= 17,17 k-range= 1,9 BC number: 5 name= Klo type= BCWallInviscid i-range= 1,21 j-range= 1,17 k-range= 1,1 BC number: 6 name= Khi type= BCWallInviscid i-range= 1,21 j-range= 1,17 k-range= 9,9 Successfully read BCs (PointRange format) from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCentRind/000077500000000000000000000000001343724673500250515ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCentRind/Makefile000066400000000000000000000017421343724673500265150ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowcentrind_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowcentrind_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid_str.c $(LIBS) $(WRITE2) : ../write_flowcentrind_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_flowcentrind_str.c $(LIBS) $(READ1) : ../read_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid_str.c $(LIBS) $(READ2) : ../read_flowcentrind_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_flowcentrind_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCentRind/OUTPUT1000066400000000000000000000002271343724673500261160ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_FlowCentRind/OUTPUT2000066400000000000000000000003761343724673500261240ustar00rootroot00000000000000 Successfully read flow solution from file grid_c.cgns For example, r,p[7][16][20]= 19.000000, 15.000000 rind: r,p[7][16][0]= 1055.000000, 1056.000000 rind: r,p[7][16][21]= -1055.000000, -1056.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_Timeacc/000077500000000000000000000000001343724673500240605ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_Timeacc/Makefile000066400000000000000000000017121343724673500255210ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_timevert_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_timevert_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid_str.c $(LIBS) $(WRITE2) : ../write_timevert_str.c $(CC) $(COPTS) $(FEOUT)$@ ../write_timevert_str.c $(LIBS) $(READ1) : ../read_grid_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid_str.c $(LIBS) $(READ2) : ../read_timevert_str.c $(CC) $(COPTS) $(FEOUT)$@ ../read_timevert_str.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_Timeacc/OUTPUT1000066400000000000000000000002271343724673500251250ustar00rootroot00000000000000 Successfully read grid from file grid_c.cgns For example, zone 1 x,y,z[8][16][20]= 20.000000, 16.000000, 8.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Str_Timeacc/OUTPUT2000066400000000000000000000012411343724673500251230ustar00rootroot00000000000000 number of time steps stored = 3 Times stored are: 10.000000 20.000000 50.000000 Flow solution names corresponding to each are: FlowSolution1 FlowSolution2 FlowSolution3 Simulation type is: TimeAccurate Successfully read 3 flow solutions from file grid_c.cgns For example, r1,p1[0][0][0]=0.000000, 0.000000 r2,p2[0][0][0]=1.000000, 1.000000 r3,p3[0][0][0]=2.000000, 2.000000 For example, r1,p1[8][16][20]=20.000000, 16.000000 r2,p2[8][16][20]=21.000000, 17.000000 r3,p3[8][16][20]=22.000000, 18.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/000077500000000000000000000000001343724673500227765ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/Makefile000066400000000000000000000045041343724673500244410ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_unst$(EXE) WRITE2 = write_flowvert_unst$(EXE) WRITE3 = write_dimensional$(EXE) WRITE4 = write_descriptor$(EXE) WRITE5 = write_convergence$(EXE) WRITE6 = write_bcpnts_unst$(EXE) READ1 = read_grid_unst$(EXE) READ2 = read_flowvert_unst$(EXE) READ3 = read_dimensional$(EXE) READ4 = read_descriptor$(EXE) READ5 = read_convergence$(EXE) READ6 = read_bcpnts_unst$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) $(WRITE4) $(WRITE5) $(WRITE6) READ_PROGS = $(READ1) $(READ2) $(READ3) $(READ4) $(READ5) $(READ6) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(WRITE4) $(READ4) > $(OUTDIR)/output4 -$(DIFF) OUTPUT4 $(OUTDIR)/output4 $(WRITE5) $(READ5) > $(OUTDIR)/output5 -$(DIFF) OUTPUT5 $(OUTDIR)/output5 $(WRITE6) $(READ6) > $(OUTDIR)/output6 -$(DIFF) OUTPUT6 $(OUTDIR)/output6 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../write_grid_unst.c $(LIBS) $(WRITE2) : ../write_flowvert_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../write_flowvert_unst.c $(LIBS) $(WRITE3) : ../write_dimensional.c $(CC) $(COPTS) $(FEOUT)$@ ../write_dimensional.c $(LIBS) $(WRITE4) : ../write_descriptor.c $(CC) $(COPTS) $(FEOUT)$@ ../write_descriptor.c $(LIBS) $(WRITE5) : ../write_convergence.c $(CC) $(COPTS) $(FEOUT)$@ ../write_convergence.c $(LIBS) $(WRITE6) : ../write_bcpnts_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../write_bcpnts_unst.c $(LIBS) $(READ1) : ../read_grid_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../read_grid_unst.c $(LIBS) $(READ2) : ../read_flowvert_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../read_flowvert_unst.c $(LIBS) $(READ3) : ../read_dimensional.c $(CC) $(COPTS) $(FEOUT)$@ ../read_dimensional.c $(LIBS) $(READ4) : ../read_descriptor.c $(CC) $(COPTS) $(FEOUT)$@ ../read_descriptor.c $(LIBS) $(READ5) : ../read_convergence.c $(CC) $(COPTS) $(FEOUT)$@ ../read_convergence.c $(LIBS) $(READ6) : ../read_bcpnts_unst.c $(CC) $(COPTS) $(FEOUT)$@ ../read_bcpnts_unst.c $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT1000066400000000000000000000015201343724673500240400ustar00rootroot00000000000000 number of sections=4 Reading section data... section name=Elem section type=HEXA_8 istart,iend=1, 2560 reading element data for this element Reading section data... section name=InflowElem section type=QUAD_4 istart,iend=2561, 2688 not reading element data for this element Reading section data... section name=OutflowElem section type=QUAD_4 istart,iend=2689, 2816 not reading element data for this element Reading section data... section name=SidewallElem section type=QUAD_4 istart,iend=2817, 3776 not reading element data for this element Successfully read unstructured grid from file grid_c.cgns for example, element 1 is made up of nodes: 1, 2, 23, 22, 358, 359, 380, 379 x,y,z of node 357 are: 0.000000, 0.000000, 1.000000 x,y,z of node 1357 are: 13.000000, 13.000000, 3.000000 CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT2000066400000000000000000000002651343724673500240460ustar00rootroot00000000000000 Successfully read flow solution from file grid_c.cgns For example, r,p[379] = 1.000000, 1.000000 r,p[3212]= 20.000000, 16.000000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT3000066400000000000000000000011711343724673500240440ustar00rootroot00000000000000 DataClass = Dimensional Units= Kilogram Meter Second Kelvin Degree For Density, exponents are: 1.000000 -3.000000 0.000000 0.000000 0.000000 For Pressure, exponents are: 1.000000 -1.000000 -2.000000 0.000000 0.000000 For CoordinateX, exponents are: 0.000000 1.000000 0.000000 0.000000 0.000000 For CoordinateY, exponents are: 0.000000 1.000000 0.000000 0.000000 0.000000 For CoordinateZ, exponents are: 0.000000 1.000000 0.000000 0.000000 0.000000 Successfully read dimensional data from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT4000066400000000000000000000002031343724673500240400ustar00rootroot00000000000000 The descriptor is: Supersonic vehicle with landing gear M=4.6, Re=6 million Successfully read descriptors from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT5000066400000000000000000000002651343724673500240510ustar00rootroot00000000000000 Successfully read cl history from file grid_c.cgns values are: 1.000000, 2.000000, 3.000000, 4.000000, 5.000000 6.000000, 7.000000, 8.000000, 9.000000, 10.000000 CGNS-3.4.0/src/Test_UserGuideCode/C_code/Test_Grid_Unstr/OUTPUT6000066400000000000000000000023011343724673500240430ustar00rootroot00000000000000 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 1 name= Ilo type= BCTunnelInflow no of elements= 128 (these elements read here, but only some printed out:) ipnts[0]=2561 ipnts[1]=2562 ipnts[2]=2563 ipnts[3]=2564 ipnts[4]=2565 ipnts[5]=2566 ipnts[6]=2567 ipnts[7]=2568 ipnts[8]=2569 ipnts[9]=2570 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 2 name= Ihi type= BCExtrapolate no of elements= 128 (these elements read here, but only some printed out:) ipnts[0]=2689 ipnts[1]=2690 ipnts[2]=2691 ipnts[3]=2692 ipnts[4]=2693 ipnts[5]=2694 ipnts[6]=2695 ipnts[7]=2696 ipnts[8]=2697 ipnts[9]=2698 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 3 name= Walls type= BCWallInviscid no of elements= 960 (these elements read here, but only some printed out:) ipnts[0]=2817 ipnts[1]=2818 ipnts[2]=2819 ipnts[3]=2820 ipnts[4]=2821 ipnts[5]=2822 ipnts[6]=2823 ipnts[7]=2824 ipnts[8]=2825 ipnts[9]=2826 Successfully read BCs (PointList format) from file grid_c.cgns CGNS-3.4.0/src/Test_UserGuideCode/C_code/make.defs000066400000000000000000000010161343724673500214750ustar00rootroot00000000000000# location for the CGNS includes and required libraries CGNSDIR = ../../.. include $(CGNSDIR)/make.defs include $(CGNSDIR)/cgnsBuild.defs CGNSLIB = $(CGNSDIR)/$(LIBCGNS) CGNSinclude = ../../../ CGNSlibs = $(CGNSLIB) $(HDF5LIB) # C compiler and options COPTS = -I$(CGNSinclude) $(CFLAGS) LIBS = $(CGNSlibs) $(SZIPLIB) $(ZLIBLIB) $(HDF5LIB_DEP) -lm $(CLIBS) # how to name output executable and extension FEOUT = -o EXE = # working directory for output OUTDIR = build # additional commands MKDIR = mkdir DIFF = diff -w CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_bc_str.c000066400000000000000000000051531343724673500223360ustar00rootroot00000000000000/* Program read_bc_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid + BCs (in PointRange format), and reads the BCs The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c), and the BCs must also already have been written (using write_bc_str.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_bc_str.c cc -o read_bc_str_c read_bc_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int index_file,index_base,index_zone,nbocos,ib; int normalindex[3],ndataset; int normallist; char boconame[33]; CGNS_ENUMT(BCType_t) ibocotype; CGNS_ENUMT(PointSetType_t) iptset; CGNS_ENUMT(DataType_t) normaldatatype; cgsize_t ipnts[2][3]; cgsize_t npts,normallistflag; /* READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* find out number of BCs that exist under this zone */ cg_nbocos(index_file,index_base,index_zone,&nbocos); /* do loop over the total number of BCs */ for (ib=1; ib <= nbocos; ib++) { /* get BC info */ cg_boco_info(index_file,index_base,index_zone,ib,boconame,&ibocotype, &iptset,&npts,normalindex,&normallistflag,&normaldatatype,&ndataset); if (iptset != CGNS_ENUMV(PointRange)) { printf("\nError. For this program, BCs must be set up as PointRange type %s\n", PointSetTypeName[iptset]); return 1; } printf("\nBC number: %i\n",ib); printf(" name= %s\n",boconame); printf(" type= %s\n",BCTypeName[ibocotype]); /* read point range in here */ cg_boco_read(index_file,index_base,index_zone,ib,ipnts[0],&normallist); printf(" i-range= %i,%i\n",(int)ipnts[0][0],(int)ipnts[1][0]); printf(" j-range= %i,%i\n",(int)ipnts[0][1],(int)ipnts[1][1]); printf(" k-range= %i,%i\n",(int)ipnts[0][2],(int)ipnts[1][2]); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read BCs (PointRange format) from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_bcpnts_str.c000066400000000000000000000056501343724673500232450ustar00rootroot00000000000000/* Program read_bcpnts_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid + BCs (in PointList format), and reads the BCs The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c), and the BCs must also already have been written (using write_bcpnts_str.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_bcpnts_str.c cc -o read_bcpnts_str_c read_bcpnts_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxpnts 400 int main() { int index_file,index_base,index_zone,nbocos,ib; int normalindex[3],ndataset; int i,normallist; char boconame[33]; CGNS_ENUMT(BCType_t) ibocotype; CGNS_ENUMT(PointSetType_t) iptset; CGNS_ENUMT(DataType_t) normaldatatype; cgsize_t npts,normallistflag; cgsize_t ipnts[maxpnts][3]; /* READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* find out number of BCs that exist under this zone */ cg_nbocos(index_file,index_base,index_zone,&nbocos); /* do loop over the total number of BCs */ for (ib=1; ib <= nbocos; ib++) { /* get BC info */ cg_boco_info(index_file,index_base,index_zone,ib,boconame,&ibocotype, &iptset,&npts,normalindex,&normallistflag,&normaldatatype,&ndataset); if (iptset != CGNS_ENUMV(PointList)) { printf("\nError. For this program, BCs must be set up as PointList type %s\n", PointSetTypeName[iptset]); return 1; } printf("\nBC number: %i\n",ib); printf(" name= %s\n",boconame); printf(" type= %s\n",BCTypeName[ibocotype]); printf(" no of pts= %i\n",(int)npts); if (npts > maxpnts) { printf("\nError. Must increase maxpnts to at least %i\n",(int)npts); return 1; } /* read point list in here (nothing done with them in this program) */ cg_boco_read(index_file,index_base,index_zone,ib,ipnts[0],&normallist); printf(" (these points read here, but only some printed out:)\n"); for (i=0; i < 10; i++) { printf(" ipnts[%i][0], [%i][1], [%i][2]=%i,%i,%i\n", i,i,i,(int)ipnts[i][0],(int)ipnts[i][1],(int)ipnts[i][2]); } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read BCs (PointList format) from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_bcpnts_unst.c000066400000000000000000000063341343724673500234260ustar00rootroot00000000000000/* Program read_bcpnts_unst */ /* Opens an existing CGNS file that contains a simple 3-D unstructured grid + BCs (in PointList+GridLocation=FaceCenter format), and reads the BCs The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_unst.c), and the BCs must also already have been written (using write_bcpnts_unst.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_bcpnts_unst.c cc -o read_bcpnts_unst_c read_bcpnts_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxpnts 960 int main() { int index_file,index_base,index_zone,nbocos,ib; int normalindex[3],ndataset; int i,normallist; char boconame[33]; CGNS_ENUMT(BCType_t) ibocotype; CGNS_ENUMT(PointSetType_t) iptset; CGNS_ENUMT(DataType_t) normaldatatype; CGNS_ENUMT(GridLocation_t) igr; cgsize_t npts,normallistflag; cgsize_t ipnts[maxpnts]; /* READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* find out number of BCs that exist under this zone */ cg_nbocos(index_file,index_base,index_zone,&nbocos); /* do loop over the total number of BCs */ for (ib=1; ib <= nbocos; ib++) { /* find out what BC grid location is (expecting FaceCenter) */ cg_goto(index_file,index_base,"Zone_t",1,"ZoneBC_t",1,"BC_t",ib,"end"); cg_gridlocation_read(&igr); if (igr == CGNS_ENUMV(FaceCenter)) { printf("\nGridLocation=FaceCenter means BC data refers to elements, not nodes\n"); } /* get BC info */ cg_boco_info(index_file,index_base,index_zone,ib,boconame,&ibocotype, &iptset,&npts,normalindex,&normallistflag,&normaldatatype,&ndataset); if (iptset != CGNS_ENUMV(PointList)) { printf("\nError. For this program, BCs must be set up as PointList type %s\n", PointSetTypeName[iptset]); return 1; } printf("\nBC number: %i\n",ib); printf(" name= %s\n",boconame); printf(" type= %s\n",BCTypeName[ibocotype]); printf(" no of elements= %i\n",(int)npts); if (npts > maxpnts) { printf("\nError. Must increase maxpnts to at least %i\n",(int)npts); return 1; } /* read point list in here (nothing done with them in this program) */ cg_boco_read(index_file,index_base,index_zone,ib,ipnts,&normallist); printf(" (these elements read here, but only some printed out:)\n"); for (i=0; i < 10; i++) { printf(" ipnts[%i]=%i\n",i,(int)ipnts[i]); } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read BCs (PointList format) from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_con2zn_genrl_str.c000066400000000000000000000074371343724673500243610ustar00rootroot00000000000000/* Program read_con2zn_genrl_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid (2 zones) plus 1-to-1 connectivity information (written in GENERAL form), and reads the connectivity info. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid2zn_str.c plus write_con2zn_genrl_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_con2zn_genrl_str.c cc -o read_con2zn_genrl_str_c read_con2zn_genrl_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxpnts 400 int main() { int i,index_file,index_base,nzone,index_zone,nconns,index_conn; char donorname[33],connectname[33]; CGNS_ENUMT(GridLocation_t) location; CGNS_ENUMT(GridConnectivityType_t) iconnect_type; CGNS_ENUMT(PointSetType_t) iptset_type,idonor_ptset_type; CGNS_ENUMT(ZoneType_t) idonor_zonetype; CGNS_ENUMT(DataType_t) idonor_datatype; cgsize_t npts,ndata_donor; cgsize_t ipnts[maxpnts][3],ipntsdonor[maxpnts][3]; /* READ GENERAL CONNECTIVITY INFORMATION FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* get number of zones (should be 2 for our case) */ cg_nzones(index_file,index_base,&nzone); if (nzone != 2) { printf("\nError. This program expects 2 zones. %d read.\n",nzone); return 1; } /* loop over zones */ for (index_zone=1; index_zone <= nzone; ++index_zone) { /* find out how many general interfaces there are in this zone */ /* (for this program, there should only be one) */ cg_nconns(index_file,index_base,index_zone,&nconns); if (nconns != 1) { printf("\nError. Expecting one general interface. %i read\n",nconns); return 1; } index_conn=nconns; /* read general connectivity info */ cg_conn_info(index_file,index_base,index_zone,index_conn,connectname,&location, &iconnect_type,&iptset_type,&npts,donorname,&idonor_zonetype, &idonor_ptset_type,&idonor_datatype,&ndata_donor); if (npts > maxpnts) { printf("\nError. Must increase maxpnts to at least %i\n",(int)npts); return 1; } cg_conn_read(index_file,index_base,index_zone,index_conn,ipnts[0], idonor_datatype,ipntsdonor[0]); printf("\nIn zone %i:\n",index_zone); printf(" donor name=%s\n",donorname); printf(" number of connectivity pts=%i\n",(int)npts); printf(" grid location=%s\n",GridLocationName[location]); printf(" connectivity type=%s\n",GridConnectivityTypeName[iconnect_type]); printf(" pointset type=%s\n",PointSetTypeName[iptset_type]); printf(" donor zonetype=%s\n",ZoneTypeName[idonor_zonetype]); printf(" donor pointset type=%s\n",PointSetTypeName[idonor_ptset_type]); /* printf(" data type=%s\n",DataTypeName[idonor_datatype]); */ printf(" ipnts and ipntsdonor arrays read, only some written out here:\n"); for (i=0; i < 10; i++) { printf(" ipnts[%i][0], [%i][1], [%i][2]=%i,%i,%i", i,i,i,(int)ipnts[i][0],(int)ipnts[i][1],(int)ipnts[i][2]); printf(" ipntsdonor[%i][0], [%i][1], [%i][2]=%i,%i,%i\n", i,i,i,(int)ipntsdonor[i][0],(int)ipntsdonor[i][1],(int)ipntsdonor[i][2]); } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read general 1-to-1 connectivity info from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_con2zn_str.c000066400000000000000000000052141343724673500231610ustar00rootroot00000000000000/* Program read_con2zn_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid (2 zones) plus 1-to-1 connectivity information, and reads the connectivity info. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid2zn_str.c plus write_con2zn_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_con2zn_str.c cc -o read_con2zn_str_c read_con2zn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int itranfrm[3]; int index_file,index_base,nzone,index_zone,n1to1,index_conn; char donorname[33],connectname[33]; cgsize_t ipnts[2][3],ipntsdonor[2][3]; /* READ 1-TO-1 CONNECTIVITY INFORMATION FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* get number of zones (should be 2 for our case) */ cg_nzones(index_file,index_base,&nzone); if (nzone != 2) { printf("\nError. This program expects 2 zones. %d read.\n",nzone); return 1; } /* loop over zones */ for (index_zone=1; index_zone <= nzone; ++index_zone) { /* find out how many 1-to-1 interfaces there are in this zone */ /* (for this program, there should only be one) */ cg_n1to1(index_file,index_base,index_zone,&n1to1); if (n1to1 != 1) { printf("\nError. Expecting one 1-to-1 interface. %i read\n",n1to1); return 1; } index_conn=n1to1; /* read 1-to-1 info */ cg_1to1_read(index_file,index_base,index_zone,index_conn,connectname,donorname, ipnts[0],ipntsdonor[0],itranfrm); printf("\nIn zone %i:\n",index_zone); printf(" donor name=%s\n",donorname); printf(" range (this zone)=%i,%i,%i,%i,%i,%i\n",(int)ipnts[0][0], (int)ipnts[0][1],(int)ipnts[0][2],(int)ipnts[1][0], (int)ipnts[1][1],(int)ipnts[1][2]); printf(" range (donor zone)=%i,%i,%i,%i,%i,%i\n",(int)ipntsdonor[0][0], (int)ipntsdonor[0][1],(int)ipntsdonor[0][2],(int)ipntsdonor[1][0], (int)ipntsdonor[1][1],(int)ipntsdonor[1][2]); printf(" transform=%i,%i,%i\n",itranfrm[0],itranfrm[1],itranfrm[2]); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read 1-to-1 connectivity info from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_convergence.c000066400000000000000000000044211343724673500233550ustar00rootroot00000000000000/* Program read_convergence */ /* Reads convergence history from an existing CGNS file. The CGNS grid file 'grid_c.cgns' must already exist and a convergence history should be in it (using write_convergence.c). Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_convergence.c cc -o read_convergence_c read_convergence.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define ntt 20 int main() { float cl[ntt]; int index_file,index_base,narrays,index_array,ndim; char arrayname[33]; CGNS_ENUMT(DataType_t) itype; cgsize_t idim; /* READ CONVERGENCE HISTORY INFORMATION FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* go to base node */ cg_goto(index_file,index_base,"end"); /* go to history node (we assume it exists and that there is only one - */ /* real working code would check!) */ cg_goto(index_file,index_base,"ConvergenceHistory_t",1,"end"); /* find out how many arrays are here (there should be only one!): */ cg_narrays(&narrays); index_array=narrays; /* some checks: */ if (narrays != 1) { printf("\nError! Expecting only one array, read %i\n",narrays); return 1; } cg_array_info(index_array,arrayname,&itype,&ndim,&idim); if (idim > ntt) { printf("\nError! must increase ntt to at least %i\n",(int)idim); return 1; } if (strcmp(arrayname,"CoefLift") != 0) { printf("\nError! expecting CoefLift, read %s\n",arrayname); return 1; } /* read lift coefficient array */ cg_array_read_as(index_array,CGNS_ENUMV(RealSingle),cl); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read cl history from file grid_c.cgns\n"); printf(" values are: %f, %f, %f, %f, %f\n",cl[0],cl[1],cl[2],cl[3],cl[4]); printf(" %f, %f, %f, %f, %f\n",cl[5],cl[6],cl[7],cl[8],cl[9]); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_descriptor.c000066400000000000000000000026141343724673500232370ustar00rootroot00000000000000/* Program read_descriptor */ /* Reads descriptor node (under CGNSBase_t) from an existing CGNS file. The CGNS grid file 'grid_c.cgns' must already exist. and a descriptor node should be in it (using write_descriptor.c). Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_descriptor.c cc -o read_descriptor_c read_descriptor.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int index_file,index_base,ndescriptors,n; char *text,name[33]; /* READ DESCRIPTOR FROM EXISTING CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* go to base node */ cg_goto(index_file,index_base,"end"); /* find out how many descriptors are here: */ cg_ndescriptors(&ndescriptors); for (n=1; n <= ndescriptors; n++) { /* read descriptor */ cg_descriptor_read(n,name,&text); printf("\nThe descriptor is:\n\n%s\n",text); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read descriptors from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_dimensional.c000066400000000000000000000074211343724673500233640ustar00rootroot00000000000000/* Program read_dimensional */ /* Opens an existing CGNS file that contains a simple 3-D grid plus a flow solution WITH DIMENSIONALITY, and reads the dimensionality. The CGNS grid file 'grid_c.cgns' must already exist (for example, created using write_grid_str.f followed by write_flowcent_str.f or write_grid_str.f followed by write_flowvert_str.f or write_grid_str.f followed by write_flowcentrind_str.f or write_grid_unst.f followed by write_flowvert_unst.f followed by write_dimensional.f) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_dimensional.c cc -o read_dimensional_c read_dimensional.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib_f.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int index_file,index_base,index_zone,index_flow,index_grid,nfields,ncoords; int iff,ic; float exponents[5]; char fieldname[33],coordname[33]; CGNS_ENUMT(DataClass_t) id; CGNS_ENUMT(MassUnits_t) im; CGNS_ENUMT(LengthUnits_t) il; CGNS_ENUMT(TimeUnits_t) it; CGNS_ENUMT(TemperatureUnits_t) ix; CGNS_ENUMT(AngleUnits_t) ia; CGNS_ENUMT(DataType_t) idatatype; /* READ DIMENSIONAL INFO FOR GRID AND FLOW SOLN */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* we know there is only one GridCoordinates_t (real working code would check!) */ index_grid=1; /* read DataClass and DimensionalUnits under Base */ cg_goto(index_file,index_base,"end"); cg_dataclass_read(&id); printf("\nDataClass = %s\n",DataClassName[id]); if (strcmp(DataClassName[id],"Dimensional") != 0) { printf("\nError! Expecting Dimensional\n"); return 1; } cg_units_read(&im,&il,&it,&ix,&ia); printf("\nUnits=\n %s\n %s\n %s\n %s\n %s\n", MassUnitsName[im],LengthUnitsName[il],TimeUnitsName[it], TemperatureUnitsName[ix],AngleUnitsName[ia]); /* read fields */ cg_nfields(index_file,index_base,index_zone,index_flow,&nfields); if (nfields != 2) { printf("\nError! expecting 2 fields, read %i\n",nfields); return 1; } for (iff=1; iff <= nfields; iff++) { /* read DimensionalExponents */ cg_goto(index_file,index_base,"Zone_t",1,"FlowSolution_t",1,"DataArray_t",iff,"end"); cg_exponents_read(exponents); /* get field name */ cg_field_info(index_file,index_base,index_zone,index_flow,iff,&idatatype,fieldname); printf("\nFor %s, exponents are:\n %f\n %f\n %f\n %f\n %f\n", fieldname,exponents[0],exponents[1],exponents[2],exponents[3],exponents[4]); } /* read grid */ cg_ncoords(index_file,index_base,index_zone,&ncoords); for (ic=1; ic <=ncoords; ic++) { /* read DimensionalExponents */ cg_goto(index_file,index_base,"Zone_t",1,"GridCoordinates_t",1, "DataArray_t",ic,"end"); cg_exponents_read(&exponents); /* get coord name */ cg_coord_info(index_file,index_base,index_zone,ic,&idatatype,coordname); printf("\nFor %s, exponents are:\n %f\n %f\n %f\n %f\n %f\n", coordname,exponents[0],exponents[1],exponents[2],exponents[3],exponents[4]); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read dimensional data from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_discreteface_str.c000066400000000000000000000074241343724673500243760ustar00rootroot00000000000000/* Program read_discreteface_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus discrete data (at K-DIR FACE CENTERS PLUS RIND CELLS IN THE I AND J DIRECTIONS), and reads it. In memory, rind cells also exist in the K direction, necessitating use of cg_array_general_read. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_discreteface_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_discreteface_str.c cc -o read_discreteface_str_c read_discreteface_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that there are no restrictions on tri-dimensional array f because because a general write interface is used). In the file, rind cells are stored in array locations [k][0][i], [k][17][i], [k][j][0], [k][j][21] In memory, rind cells are stored in array locations [0][j][i], [10][j][i], [k][0][i], [k][17][i], [k][j][0], [k][j][21] */ float f[9+2][16+2][20+2]; int irinddata[3][2]; int n,index_file,index_base,index_zone,index_discrete; char zonename[33]; cgsize_t isize[3][3],irmin[3],irmax[3],m_dims[3],m_rmin[3],m_rmax[3]; /* clear f since only partial read */ for (n=0; n<(9+2)*(16+2)*(20+2); n++) { f[0][0][n] = -0.123456f; } /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one DiscreteData_t (real working code would check!) */ index_discrete=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* go to position within tree at DiscreteData_t node */ cg_goto(index_file,index_base,"Zone_t",index_zone,"DiscreteData_t",index_discrete,"end"); /* read rind data */ cg_rind_read(irinddata[0]); /* dimensions of array in memory */ m_dims[0] = 20+2; m_dims[1] = 16+2; m_dims[2] = 9+2; /* in file space the core cells ALWAYS start at index 1 */ /* lower range index in file */ irmin[0]=1-irinddata[0][0]; irmin[1]=1-irinddata[1][0]; irmin[2]=1-irinddata[2][0]; /* upper range index in file - use vertex dimensions for k */ irmax[0]=isize[1][0]+irinddata[0][1]; irmax[1]=isize[1][1]+irinddata[1][1]; irmax[2]=isize[0][2]+irinddata[2][1]; /* in memory space, the lower bound ALWAYS starts at index 1 (in this example, * core cells start at 2) */ /* lower range index in memory */ m_rmin[0] = 2-irinddata[0][0]; m_rmin[1] = 2-irinddata[1][0]; m_rmin[2] = 2-irinddata[2][0]; /* upper range index in memory */ m_rmax[0] = 1+20+irinddata[0][1]; m_rmax[1] = 1+16+irinddata[1][1]; m_rmax[2] = 1+ 9+irinddata[2][1]; /* read discrete data */ if (cg_array_general_read(1, irmin, irmax, CGNS_ENUMV(RealSingle), 3, m_dims, m_rmin, m_rmax, f[0][0])) cg_error_exit(); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read discrete data from file grid_c.cgns\n"); printf(" For example, f[ 9][16][20]= %f\n",f[ 9][16][20]); printf(" rind: f[ 9][16][ 0]= %f\n",f[ 9][16][ 0]); printf(" rind: f[ 9][16][21]= %f\n",f[ 9][16][21]); printf(" unmodified: f[10][16][ 0]= %f\n",f[10][16][ 0]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_flowcent_str.c000066400000000000000000000057001343724673500235710ustar00rootroot00000000000000/* Program read_flowcent_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus a flow solution (at CELL CENTERS), and reads it. (Compare this program with read_flowvert_str) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_flowcent_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_flowcent_str.c cc -o read_flowcent_str_c read_flowcent_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N-1][17-1][21-1] (N>=9) for this particular case or else they will be read from the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double r[8][16][20],p[8][16][20]; cgsize_t isize[3][3],irmin[3],irmax[3]; int index_file,index_base,index_zone,index_flow; char zonename[33],solname[33]; CGNS_ENUMT(GridLocation_t) loc; /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin[0]=1; irmin[1]=1; irmin[2]=1; /* upper range index - use cell dimensions */ /* checking GridLocation first (real working code would check */ /* to make sure there are no Rind cells also!): */ cg_sol_info(index_file,index_base,index_zone,index_flow,solname,&loc); if (loc != CGNS_ENUMV(CellCenter)) { printf("\nError, GridLocation must be CellCenter! Currently: %s\n", GridLocationName[loc]); return 1; } irmax[0]=isize[1][0]; irmax[1]=isize[1][1]; irmax[2]=isize[1][2]; /* read flow solution */ cg_field_read(index_file,index_base,index_zone,index_flow,"Density", \ CGNS_ENUMV(RealDouble),irmin,irmax,r[0][0]); cg_field_read(index_file,index_base,index_zone,index_flow,"Pressure", \ CGNS_ENUMV(RealDouble),irmin,irmax,p[0][0]); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read flow solution from file grid_c.cgns\n"); printf(" For example, r,p[7][15][19]= %f, %f\n",r[7][15][19],p[7][15][19]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_flowcentrind_str.c000066400000000000000000000066661343724673500244620ustar00rootroot00000000000000/* Program read_flowcentrind_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus a flow solution (at CELL CENTERS PLUS RIND CELLS IN THE I AND J DIRECTIONS), and reads it. (Compare this program with read_flowcent_str) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_flowcentrind_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_flowcentrind_str.c cc -o read_flowcentrind_str_c read_flowcentrind_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N-1][17-1+2][21-1+2] (N>=9) for this particular case or else they will be read from the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): Rind cells are stored in array locations [k][0][i], [k][17][i], [k][j][0], [k][j][21] */ float r[8][18][22],p[8][18][22]; int irinddata[6]; int index_file,index_base,index_zone,index_flow; char zonename[33],solname[33]; CGNS_ENUMT(GridLocation_t) loc; cgsize_t isize[3][3],irmin[3],irmax[3]; /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ cg_open("grid_c.cgns",CG_MODE_READ,&index_file); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* go to position within tree at FlowSolution\_t node */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowSolution_t",index_flow,"end"); /* read rind data */ cg_rind_read(irinddata); /* lower range index */ irmin[0]=1-irinddata[0]; irmin[1]=1-irinddata[2]; irmin[2]=1-irinddata[4]; /* upper range index - use cell dimensions */ /* checking GridLocation first: */ cg_sol_info(index_file,index_base,index_zone,index_flow,solname,&loc); if (loc != CGNS_ENUMV(CellCenter)) { printf("\nError, GridLocation must be CellCenter! Currently: %s\n", GridLocationName[loc]); return 1; } irmax[0]=isize[1][0]+irinddata[1]; irmax[1]=isize[1][1]+irinddata[3]; irmax[2]=isize[1][2]+irinddata[5]; /* read flow solution */ cg_field_read(index_file,index_base,index_zone,index_flow,"Density", CGNS_ENUMV(RealSingle),irmin,irmax,r[0][0]); cg_field_read(index_file,index_base,index_zone,index_flow,"Pressure", CGNS_ENUMV(RealSingle),irmin,irmax,p[0][0]); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read flow solution from file grid_c.cgns\n"); printf(" For example, r,p[7][16][20]= %f, %f\n",r[7][16][20],p[7][16][20]); printf(" rind: r,p[7][16][0]= %f, %f\n",r[7][16][0],p[7][16][0]); printf(" rind: r,p[7][16][21]= %f, %f\n",r[7][16][21],p[7][16][21]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_floweqn_str.c000066400000000000000000000066361343724673500234340ustar00rootroot00000000000000/* Program read_floweqn_str */ /* Opens an existing CGNS file and reads flow equation info The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_floweqn_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_floweqn_str.c cc -o read_floweqn_str_c read_floweqn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int idata[6]; int index_file,index_base,index_zone; int id,ige,igm,ivm,itcm,itc,itm; float gamma,prandtl; CGNS_ENUMT(GoverningEquationsType_t) itype; CGNS_ENUMT(ModelType_t) mtype; /* READ FLOW EQUATION SET INFO */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* existing file must be 3D structured (real working code would check!) */ /* Read info from 'FlowEquationSet' node under 'Zone_t' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"end"); if (cg_equationset_read(&id,&ige,&igm,&ivm,&itcm,&itc,&itm)) { printf("\nError! FlowEquationSet node does not exist.\n"); return 1; } printf("\nEqn dimension = %i\n",id); /* Read 'GoverningEquations' node */ if (ige == 1) { cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_governing_read(&itype); printf(" Gov eqn = %s\n",GoverningEquationsTypeName[itype]); /* Read 'DiffusionModel' node */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, \ "GoverningEquations_t",1,"end"); cg_diffusion_read(idata); printf(" diffusion= %i, %i, %i, %i, %i, %i\n",idata[0],idata[1], \ idata[2],idata[3],idata[4],idata[5]); } /* Read gas model */ if (igm == 1) { cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_read("GasModel_t",&mtype); printf(" Gas model type = %s\n",ModelTypeName[mtype]); cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, \ "GasModel_t",1,"end"); cg_array_read_as(1,CGNS_ENUMV(RealSingle),&gamma); printf(" gamma = %f\n",gamma); } /* Read turbulence closure */ if (itc == 1) { cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_read("TurbulenceClosure_t",&mtype); printf(" Turbulence closure type = %s\n",ModelTypeName[mtype]); cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, \ "TurbulenceClosure_t",1,"end"); cg_array_read_as(1,CGNS_ENUMV(RealSingle),&prandtl); printf(" turb prandtl number = %f\n",prandtl); } if (itm == 1) { cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_read("TurbulenceModel_t",&mtype); printf(" Turbulence model type = %s\n",ModelTypeName[mtype]); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read equation set info from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_flowvert_str.c000066400000000000000000000055741343724673500236310ustar00rootroot00000000000000/* Program read_flowvert_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus a flow solution (at VERTICES), and reads it. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_flowvert_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_flowvert_str.c cc -o read_flowvert_str_c read_flowvert_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be read from the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ float r[9][17][21],p[9][17][21]; cgsize_t isize[3][3],irmin[3],irmax[3]; int index_file,index_base,index_zone,index_flow; char zonename[33],solname[33]; CGNS_ENUMT(GridLocation_t) loc; /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin[0]=1; irmin[1]=1; irmin[2]=1; /* upper range index - use vertex dimensions */ /* checking GridLocation first (real working code would check */ /* to make sure there are no Rind cells also!): */ cg_sol_info(index_file,index_base,index_zone,index_flow,solname,&loc); if (loc != CGNS_ENUMV(Vertex)) { printf("\nError, GridLocation must be Vertex! Currently: %s\n", GridLocationName[loc]); return 1; } irmax[0]=isize[0][0]; irmax[1]=isize[0][1]; irmax[2]=isize[0][2]; /* read flow solution */ cg_field_read(index_file,index_base,index_zone,index_flow,"Density", CGNS_ENUMV(RealSingle),irmin,irmax,r[0][0]); cg_field_read(index_file,index_base,index_zone,index_flow,"Pressure", CGNS_ENUMV(RealSingle),irmin,irmax,p[0][0]); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read flow solution from file grid_c.cgns\n"); printf(" For example, r,p[8][16][20]= %f, %f\n",r[8][16][20],p[8][16][20]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_flowvert_unst.c000066400000000000000000000052451343724673500240050ustar00rootroot00000000000000/* Program read_flowvert_unst */ /* Opens an existing CGNS file that contains a simple 3-D unstructured grid plus a flow solution (at VERTICES), and reads it. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_unst.c followed by write_flowvert_unst.c) Note that, other than the dimensions of the variables r and p, this program is very similar to that for reading flow solutions from a structured zone: read_flowvert_str.c Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_flowvert_unst.c cc -o read_flowvert_unst_c read_flowvert_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { float r[9*17*21],p[9*17*21]; cgsize_t isize[3][1],irmin,irmax; int index_file,index_base,index_zone,index_flow; char zonename[33],solname[33]; CGNS_ENUMT(GridLocation_t) loc; /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin=1; /* upper range index - use vertex dimensions */ /* checking GridLocation first (real working code would check */ /* to make sure there are no Rind cells also!): */ cg_sol_info(index_file,index_base,index_zone,index_flow,solname,&loc); if (loc != CGNS_ENUMV(Vertex)) { printf("\nError, GridLocation must be Vertex! Currently: %s\n", GridLocationName[loc]); return 1; } irmax=isize[0][0]; /* read flow solution */ cg_field_read(index_file,index_base,index_zone,index_flow,"Density", \ CGNS_ENUMV(RealSingle),&irmin,&irmax,r); cg_field_read(index_file,index_base,index_zone,index_flow,"Pressure", \ CGNS_ENUMV(RealSingle),&irmin,&irmax,p); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read flow solution from file grid_c.cgns\n"); printf(" For example, r,p[379] = %f, %f\n",r[379],p[379]); printf(" r,p[3212]= %f, %f\n",r[3212],p[3212]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_grid2zn_str.c000066400000000000000000000064571343724673500233410ustar00rootroot00000000000000/* Program read_grid2zn_str */ /* Reads simple 3-D structured 2-zone grid from CGNS file (companion program to write_grid2zn_str.c) The CGNS grid file 'grid_c.cgns' must already exist. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_grid2zn_str.c cc -o read_grid2zn_str_c read_grid2zn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays x,y,z must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be read from the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ float x[9][17][21],y[9][17][21],z[9][17][21]; float xsav[2][9][17][21],ysav[2][9][17][21],zsav[2][9][17][21]; cgsize_t isize[3][3],irmin[3],irmax[3]; int index_file,index_base,nzone,index_zone,i,j,k; char zonename[33]; /* READ X, Y, Z GRID POINTS FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* get number of zones (should be 2 for our case) */ cg_nzones(index_file,index_base,&nzone); if (nzone != 2) { printf("\nError. This program expects 2 zones. %i read\n",nzone); return 1; } /* do loop over the zones */ for (index_zone=1; index_zone <= nzone; index_zone++) { /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin[0]=1; irmin[1]=1; irmin[2]=1; /* upper range index of vertices */ irmax[0]=isize[0][0]; irmax[1]=isize[0][1]; irmax[2]=isize[0][2]; /* read grid coordinates */ cg_coord_read(index_file,index_base,index_zone,"CoordinateX", \ CGNS_ENUMV(RealSingle),irmin,irmax,x[0][0]); cg_coord_read(index_file,index_base,index_zone,"CoordinateY", \ CGNS_ENUMV(RealSingle),irmin,irmax,y[0][0]); cg_coord_read(index_file,index_base,index_zone,"CoordinateZ", \ CGNS_ENUMV(RealSingle),irmin,irmax,z[0][0]); /* store grid coordinates in xsav,ysav,zsav array: */ for (i=0; i < isize[0][0]; i++) { for (j=0; j < isize[0][1]; j++) { for (k=0; k < isize[0][2]; k++) { xsav[index_zone-1][k][j][i]=x[k][j][i]; ysav[index_zone-1][k][j][i]=y[k][j][i]; zsav[index_zone-1][k][j][i]=z[k][j][i]; } } } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read grid from file grid_c.cgns\n"); printf(" For example, zone 1 x,y,z[8][16][20]= %f, %f, %f\n", \ xsav[0][8][16][20],ysav[0][8][16][20],zsav[0][8][16][20]); printf(" zone 2 x,y,z[8][16][20]= %f, %f, %f\n", \ xsav[1][8][16][20],ysav[1][8][16][20],zsav[1][8][16][20]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_grid_str.c000066400000000000000000000046401343724673500226770ustar00rootroot00000000000000/* Program read_grid_str */ /* Reads simple 3-D structured grid from CGNS file (companion program to write_grid_str.c) The CGNS grid file 'grid_c.cgns' must already exist. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_grid_str.c cc -o read_grid_str_c read_grid_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays x,y,z must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be read from the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ float x[9][17][21],y[9][17][21],z[9][17][21]; cgsize_t isize[3][3],irmin[3],irmax[3]; int index_file,index_base,index_zone; char zonename[33]; /* READ X, Y, Z GRID POINTS FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin[0]=1; irmin[1]=1; irmin[2]=1; /* upper range index of vertices */ irmax[0]=isize[0][0]; irmax[1]=isize[0][1]; irmax[2]=isize[0][2]; /* read grid coordinates */ cg_coord_read(index_file,index_base,index_zone,"CoordinateX", CGNS_ENUMV(RealSingle),irmin,irmax,x[0][0]); cg_coord_read(index_file,index_base,index_zone,"CoordinateY", CGNS_ENUMV(RealSingle),irmin,irmax,y[0][0]); cg_coord_read(index_file,index_base,index_zone,"CoordinateZ", CGNS_ENUMV(RealSingle),irmin,irmax,z[0][0]); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read grid from file grid_c.cgns\n"); printf(" For example, zone 1 x,y,z[8][16][20]= %f, %f, %f\n", \ x[8][16][20],y[8][16][20],z[8][16][20]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_grid_unst.c000066400000000000000000000064751343724673500230700ustar00rootroot00000000000000/* Program read_grid_unst */ /* Reads simple 3-D unstructured grid from a CGNS file (created using write_grid_unst.c). The CGNS grid file 'grid_c.cgns' must already exist. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_grid_unst.c cc -o read_grid_unst_c read_grid_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { float x[21*17*9],y[21*17*9],z[21*17*9]; cgsize_t isize[3][1],ielem[20*16*8][8]; int index_file,index_base,index_zone; cgsize_t irmin,irmax,istart,iend; int nsections,index_sect,nbndry,iparent_flag; cgsize_t iparentdata; char zonename[33],sectionname[33]; CGNS_ENUMT(ElementType_t) itype; /* READ X, Y, Z GRID POINTS FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin=1; /* upper range index of vertices */ irmax=isize[0][0]; /* read grid coordinates */ cg_coord_read(index_file,index_base,index_zone,"CoordinateX", CGNS_ENUMV(RealSingle),&irmin,&irmax,x); cg_coord_read(index_file,index_base,index_zone,"CoordinateY", CGNS_ENUMV(RealSingle),&irmin,&irmax,y); cg_coord_read(index_file,index_base,index_zone,"CoordinateZ", CGNS_ENUMV(RealSingle),&irmin,&irmax,z); /* find out how many sections */ cg_nsections(index_file,index_base,index_zone,&nsections); printf("\nnumber of sections=%i\n",nsections); /* read element connectivity */ for (index_sect=1; index_sect <= nsections; index_sect++) { cg_section_read(index_file,index_base,index_zone,index_sect,sectionname, &itype,&istart,&iend,&nbndry,&iparent_flag); printf("\nReading section data...\n"); printf(" section name=%s\n",sectionname); printf(" section type=%s\n",ElementTypeName[itype]); printf(" istart,iend=%i, %i\n",(int)istart,(int)iend); if (itype == CGNS_ENUMV(HEXA_8)) { printf(" reading element data for this element\n"); cg_elements_read(index_file,index_base,index_zone,index_sect,ielem[0], \ &iparentdata); } else { printf(" not reading element data for this element\n"); } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read unstructured grid from file grid_c.cgns\n"); printf(" for example, element 1 is made up of nodes: %i, %i, %i, %i, %i, %i, %i, %i\n", (int)ielem[0][0],(int)ielem[0][1],(int)ielem[0][2],(int)ielem[0][3], (int)ielem[0][4],(int)ielem[0][5],(int)ielem[0][6],(int)ielem[0][7]); printf(" x,y,z of node 357 are: %f, %f, %f\n",x[357],y[357],z[357]); printf(" x,y,z of node 1357 are: %f, %f, %f\n",x[1357],y[1357],z[1357]); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_nondimensional.c000066400000000000000000000044161343724673500241000ustar00rootroot00000000000000/* Program read_nondimensional */ /* Opens an existing CGNS file and reads the DataClass and ReferenceState appropriate for a completely NONDIMENSIONAL data set. The CGNS grid file 'grid_c.cgns' must already exist, processed further using write_nondimensional.c. Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_nondimensional.c cc -o read_nondimensional_c read_nondimensional.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { double data; int index_file,index_base,narrays,n,idim; char *state,arrayname[33]; CGNS_ENUMT(DataClass_t) id; CGNS_ENUMT(DataType_t) idata; cgsize_t idimvec; /* READ NONDIMENSIONAL INFO */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* read DataClass under Base */ cg_goto(index_file,index_base,"end"); cg_dataclass_read(&id); printf("\nDataClass = %s\n",DataClassName[id]); if (id != CGNS_ENUMV(NormalizedByUnknownDimensional)) { printf("\nError! Expecting NormalizedByUnknownDimensional\n"); return 1; } /* read ReferenceState under Base */ cg_state_read(&state); printf("\nReferenceState = %s\n",state); /* Go to ReferenceState node, read Mach array and its dataclass */ cg_goto(index_file,index_base,"ReferenceState_t",1,"end"); /* find out how many data arrays */ cg_narrays(&narrays); for (n=1; n <= narrays; n++) { cg_array_info(n,arrayname,&idata,&idim,&idimvec); if (idim != 1 || idimvec != 1) { printf("\nError! expecting idim,idimvec=1,1\n"); printf(" they are idim,idimvec= %i, %i\n",idim,(int)idimvec); return 1; } cg_array_read_as(n,CGNS_ENUMV(RealDouble),&data); printf("Variable=%s\n",arrayname); printf(" data=%18.8f\n",data); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read nondimensional info from file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/read_timevert_str.c000066400000000000000000000147141343724673500236140ustar00rootroot00000000000000/* Program read_timevert_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus 3 different flow solutions (at VERTICES), along with time-accurate info, and reads it. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c followed by write_timevert_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c read_timevert_str.c cc -o read_timevert_str_c read_timevert_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r1, r2, r3 and p1, p2, p3 must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ float r1[9][17][21],p1[9][17][21]; float r2[9][17][21],p2[9][17][21]; float r3[9][17][21],p3[9][17][21]; float time[3]; cgsize_t isize[3][3],irmin[3],irmax[3]; int index_file,index_base,index_zone,nsteps,narrays; int id1,n; cgsize_t idims[2],id2; char zonename[33],bitername[33],zitername[33]; char arrayname[33]; char solname[97],solname2[33]; char sn[3][33]; CGNS_ENUMT(DataType_t) idatatype; CGNS_ENUMT(SimulationType_t) isim; CGNS_ENUMT(GridLocation_t) loc; /* READ FLOW SOLUTION FROM CGNS FILE */ /* open CGNS file for read-only */ if (cg_open("grid_c.cgns",CG_MODE_READ,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); /* lower range index */ irmin[0]=1; irmin[1]=1; irmin[2]=1; /* upper range index - use vertex dimensions */ irmax[0]=isize[0][0]; irmax[1]=isize[0][1]; irmax[2]=isize[0][2]; /* read BaseIterativeData */ cg_biter_read(index_file,index_base,bitername,&nsteps); printf("\nnumber of time steps stored = %i\n",nsteps); if (nsteps != 3) { printf("\nError, expecting nsteps=3!\n"); return 1; } cg_goto(index_file,index_base,"BaseIterativeData_t",1,"end"); cg_narrays(&narrays); if (narrays != 1) { printf("\nError, expecting 1 array in BaseIterativeData... there are %i\n",narrays); return 1; } cg_array_info(1,arrayname,&idatatype,&id1,&id2); if (id1 != 1 || id2 != 3) { printf("\nError, expecting data dimension and vector to be 1 and 3 in " "BaseIterativeData... read %i, %i\n",id1,(int)id2); return 1; } cg_array_read_as(1,CGNS_ENUMV(RealSingle),time); printf("\nTimes stored are:\n"); for (n=0; n < nsteps; n++) { printf(" %f\n",time[n]); } /* read ZoneIterativeData */ cg_ziter_read(index_file,index_base,index_zone,zitername); cg_goto(index_file,index_base,"Zone_t",index_zone,"ZoneIterativeData_t",1,"end"); cg_narrays(&narrays); if (narrays != 1) { printf("\nError, expecting 1 array in ZoneIterativeData... there are %i\n",narrays); return 1; } cg_array_info(1,arrayname,&idatatype,&id1,idims); if (id1 != 2 || idims[0] != 32) { printf("\nError, expecting data dimension and vector to be 2 and 32 in " "ZoneIterativeData... read %i, %i\n",id1,(int)idims[0]); return 1; } cg_array_read_as(1,CGNS_ENUMV(Character),solname); strncpy(sn[0],&solname[0],32); strncpy(sn[1],&solname[32],32); strncpy(sn[2],&solname[64],32); printf("\nFlow solution names corresponding to each are:\n"); for (n=0; n < nsteps; n++) { printf(" %.32s\n",sn[n]); } /* read SimulationType */ cg_simulation_type_read(index_file,index_base,&isim); printf("\nSimulation type is: %s\n",SimulationTypeName[isim]); /* do loop to read flow solutions */ for (n=1; n <= nsteps; n++) { /* check that soln names match, and also check GridLocation (real */ /* working code would check to make sure there are no Rind cells */ /* also!): */ cg_sol_info(index_file,index_base,index_zone,n,solname2,&loc); if (strncmp(solname2,sn[n-1],strlen(solname2)) != 0) { printf("\nError, soln names do not match\n"); printf(" solname2=%s\n",solname2); printf(" sn[%i]=%s\n",n-1,sn[n-1]); return 1; } if (loc != CGNS_ENUMV(Vertex)) { printf("\nError, GridLocation must be Vertex! Currently: %s\n", GridLocationName[loc]); return 1; } if (n == 1) { cg_field_read(index_file,index_base,index_zone,n,"Density", CGNS_ENUMV(RealSingle),irmin,irmax,r1[0][0]); cg_field_read(index_file,index_base,index_zone,n,"Pressure", CGNS_ENUMV(RealSingle),irmin,irmax,p1[0][0]); } else if (n == 2) { cg_field_read(index_file,index_base,index_zone,n,"Density", CGNS_ENUMV(RealSingle),irmin,irmax,r2[0][0]); cg_field_read(index_file,index_base,index_zone,n,"Pressure", CGNS_ENUMV(RealSingle),irmin,irmax,p2[0][0]); } else { cg_field_read(index_file,index_base,index_zone,n,"Density", CGNS_ENUMV(RealSingle),irmin,irmax,r3[0][0]); cg_field_read(index_file,index_base,index_zone,n,"Pressure", CGNS_ENUMV(RealSingle),irmin,irmax,p3[0][0]); } } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully read 3 flow solutions from file grid_c.cgns\n"); printf(" For example, r1,p1[0][0][0]=%f, %f\n",r1[0][0][0],p1[0][0][0]); printf(" r2,p2[0][0][0]=%f, %f\n",r2[0][0][0],p2[0][0][0]); printf(" r3,p3[0][0][0]=%f, %f\n",r3[0][0][0],p3[0][0][0]); printf(" For example, r1,p1[8][16][20]=%f, %f\n",r1[8][16][20],p1[8][16][20]); printf(" r2,p2[8][16][20]=%f, %f\n",r2[8][16][20],p2[8][16][20]); printf(" r3,p3[8][16][20]=%f, %f\n",r3[8][16][20],p3[8][16][20]); printf("\nProgram successful... ending now\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/test.sh000077500000000000000000000120241343724673500212340ustar00rootroot00000000000000#! /bin/bash NO_COLOR="\033[0m" OK_COLOR="\033[32;01m" ERROR_COLOR="\033[31;01m" echoresults() { if test $* -ne 0 then printf "$ERROR_COLOR *** FAILED *** $NO_COLOR \n" else printf "$OK_COLOR passed $NO_COLOR \n" fi } DIRS=" \ Test_Grid_Str" return_val=0 ############################### # Special cases ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowvert_str" "write_nondimensional" "write_descriptor" \ "write_convergence" "write_floweqn_str" "write_bcpnts_str") declare -a r_arr=("read_grid_str" "read_flowvert_str" "read_nondimensional" "read_descriptor" \ "read_convergence" "read_floweqn_str" "read_bcpnts_str") dir=Test_Grid_Str printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_unst" "write_flowvert_unst" "write_dimensional" "write_descriptor" "write_convergence" "write_bcpnts_unst") declare -a r_arr=("read_grid_unst" "read_flowvert_unst" "read_dimensional" "read_descriptor" "read_convergence" "read_bcpnts_unst") dir=Test_Grid_Unstr printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_timevert_str") declare -a r_arr=("read_grid_str" "read_timevert_str") dir=Test_Grid_Str_Timeacc printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowcent_str" "write_bc_str") declare -a r_arr=("read_grid_str" "read_flowcent_str" "read_bc_str") dir=Test_Grid_Str_FlowCent printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowcentrind_str") declare -a r_arr=("read_grid_str" "read_flowcentrind_str") dir=Test_Grid_Str_FlowCentRind printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid2zn_str" "write_con2zn_str") declare -a r_arr=("read_grid2zn_str" "read_con2zn_str") dir=Test_Grid_Str_2zn printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid2zn_str" "write_con2zn_genrl_str") declare -a r_arr=("read_grid2zn_str" "read_con2zn_genrl_str") dir=Test_Grid_Str_2zngenrl printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### echo "=== finished ===" if test $return_val != 0; then printf "$ERROR_COLOR" else printf "$OK_COLOR" fi printf "$return_val tests failed $NO_COLOR \n" exit $return_val CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_bc_str.c000066400000000000000000000101621343724673500225510ustar00rootroot00000000000000/* Program write_bc_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds BC definitions (defined over a range of points = PointRange) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_bc_str.c cc -o write_bc_str_c write_bc_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { cgsize_t isize[3][3],ipnts[2][3]; int index_file,index_base,index_zone,index_bc; int ilo,ihi,jlo,jhi,klo,khi; char zonename[33]; printf("\nProgram write_bc_str\n"); /* WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); printf("zonename=%s\n",zonename); ilo=1; ihi=isize[0][0]; jlo=1; jhi=isize[0][1]; klo=1; khi=isize[0][2]; /* write boundary conditions for ilo face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ilo; ipnts[0][1]=jlo; ipnts[0][2]=klo; /* upper point of range */ ipnts[1][0]=ilo; ipnts[1][1]=jhi; ipnts[1][2]=khi; cg_boco_write(index_file,index_base,index_zone,"Ilo",CGNS_ENUMV(BCTunnelInflow), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* write boundary conditions for ihi face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ihi; ipnts[0][1]=jlo; ipnts[0][2]=klo; /* upper point of range */ ipnts[1][0]=ihi; ipnts[1][1]=jhi; ipnts[1][2]=khi; cg_boco_write(index_file,index_base,index_zone,"Ihi",CGNS_ENUMV(BCExtrapolate), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* write boundary conditions for jlo face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ilo; ipnts[0][1]=jlo; ipnts[0][2]=klo; /* upper point of range */ ipnts[1][0]=ihi; ipnts[1][1]=jlo; ipnts[1][2]=khi; cg_boco_write(index_file,index_base,index_zone,"Jlo",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* write boundary conditions for jhi face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ilo; ipnts[0][1]=jhi; ipnts[0][2]=klo; /* upper point of range */ ipnts[1][0]=ihi; ipnts[1][1]=jhi; ipnts[1][2]=khi; cg_boco_write(index_file,index_base,index_zone,"Jhi",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* write boundary conditions for klo face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ilo; ipnts[0][1]=jlo; ipnts[0][2]=klo; /* upper point of range */ ipnts[1][0]=ihi; ipnts[1][1]=jhi; ipnts[1][2]=klo; cg_boco_write(index_file,index_base,index_zone,"Klo",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* write boundary conditions for khi face, defining range first */ /* (user can give any name) */ /* lower point of range */ ipnts[0][0]=ilo; ipnts[0][1]=jlo; ipnts[0][2]=khi; /* upper point of range */ ipnts[1][0]=ihi; ipnts[1][1]=jhi; ipnts[1][2]=khi; cg_boco_write(index_file,index_base,index_zone,"Khi",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointRange),2,ipnts[0],&index_bc); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added BCs (PointRange) to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_bcpnts_str.c000066400000000000000000000125331343724673500234620ustar00rootroot00000000000000/* Program write_bcpnts_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds BC definitions (defined as individual points = PointList) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_bcpnts_str.c cc -o write_bcpnts_str_c write_bcpnts_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxcount 400 int main() { cgsize_t isize[3][3],ipnts[maxcount][3],icounts; int index_file,index_base,index_zone,index_bc; int ilo,ihi,jlo,jhi,klo,khi; int icount,i,j,k; char zonename[33]; printf("\nProgram write_bcpnts_str\n"); /* WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* get zone size (and name - although not needed here) */ cg_zone_read(index_file,index_base,index_zone,zonename,isize[0]); printf("zonename=%s\n",zonename); ilo=1; ihi=isize[0][0]; jlo=1; jhi=isize[0][1]; klo=1; khi=isize[0][2]; /* write boundary conditions for ilo face, defining pointlist first */ /* (user can give any name) */ icount=0; for (j=jlo; j <= jhi; j++) { for (k=klo; k <= khi; k++) { ipnts[icount][0]=ilo; ipnts[icount][1]=j; ipnts[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Ilo",CGNS_ENUMV(BCTunnelInflow), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* write boundary conditions for ihi face, defining pointlist first */ /* (user can give any name) */ icount=0; for (j=jlo; j <= jhi; j++) { for (k=klo; k <= khi; k++) { ipnts[icount][0]=ihi; ipnts[icount][1]=j; ipnts[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Ihi",CGNS_ENUMV(BCExtrapolate), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* write boundary conditions for jlo face, defining pointlist first */ /* (user can give any name) */ icount=0; for (i=ilo; i <= ihi; i++) { for (k=klo; k <= khi; k++) { ipnts[icount][0]=i; ipnts[icount][1]=jlo; ipnts[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Jlo",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* write boundary conditions for jhi face, defining pointlist first */ /* (user can give any name) */ icount=0; for (i=ilo; i <= ihi; i++) { for (k=klo; k <= khi; k++) { ipnts[icount][0]=i; ipnts[icount][1]=jhi; ipnts[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Jhi",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* write boundary conditions for klo face, defining pointlist first */ /* (user can give any name) */ icount=0; for (i=ilo; i <= ihi; i++) { for (j=jlo; j <= jhi; j++) { ipnts[icount][0]=i; ipnts[icount][1]=j; ipnts[icount][2]=klo; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Klo",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* write boundary conditions for khi face, defining pointlist first */ /* (user can give any name) */ icount=0; for (i=ilo; i <= ihi; i++) { for (j=jlo; j <= jhi; j++) { ipnts[icount][0]=i; ipnts[icount][1]=j; ipnts[icount][2]=khi; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Khi",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointList),icounts,ipnts[0],&index_bc); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added BCs (PointList) to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_bcpnts_unst.c000066400000000000000000000100221343724673500236320ustar00rootroot00000000000000/* Program write_bcpnts_unst */ /* Opens an existing CGNS file that contains a simple 3-D unstructured grid, and adds BC definitions (defined as individual FaceCenter "points" = PointList+GridLocation=FaceCenter) The BCs are added as FaceCenter points, associated with face elements (QUAD_4), rather than associated to nodes For the following, be sure you are using Version 2.0 or later release of the API The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_unst.c). Note: whether the existing CGNS file has a flow solution in it already or not is irrelevant. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_bcpnts_unst.c cc -o write_bcpnts_unst_c write_bcpnts_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxcount 960 int main() { int index_file,index_base,index_zone; int nelem_start,nelem_end,icount,index_bc,ibc,n; cgsize_t ipnts[maxcount],icounts; printf("\nProgram write_bcpnts_unst\n"); /* WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know that for the unstructured zone, the following face elements */ /* have been defined as inflow (real working code would check!): */ nelem_start=2561; nelem_end=2688; icount=0; for (n=nelem_start; n <= nelem_end; n++) { ipnts[icount]=n; icount=icount+1; } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } /* write boundary conditions for ilo face */ icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Ilo",CGNS_ENUMV(BCTunnelInflow), CGNS_ENUMV(PointList),icounts,ipnts,&index_bc); /* we know that for the unstructured zone, the following face elements */ /* have been defined as outflow (real working code would check!): */ nelem_start=2689; nelem_end=2816; icount=0; for (n=nelem_start; n <= nelem_end; n++) { ipnts[icount]=n; icount=icount+1; } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } /* write boundary conditions for ihi face */ icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Ihi",CGNS_ENUMV(BCExtrapolate), CGNS_ENUMV(PointList),icounts,ipnts,&index_bc); /* we know that for the unstructured zone, the following face elements */ /* have been defined as walls (real working code would check!): */ nelem_start=2817; nelem_end=3776; icount=0; for (n=nelem_start; n <= nelem_end; n++) { ipnts[icount]=n; icount=icount+1; } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } /* write boundary conditions for wall faces */ icounts=icount; cg_boco_write(index_file,index_base,index_zone,"Walls",CGNS_ENUMV(BCWallInviscid), CGNS_ENUMV(PointList),icounts,ipnts,&index_bc); /* the above are all face-center locations for the BCs - must indicate this, */ /* otherwise Vertices will be assumed! */ for (ibc=1; ibc <= index_bc; ibc++) { /* (the following call positions you in BC_t - it assumes there */ /* is only one Zone_t and one ZoneBC_t - real working code would check!) */ cg_goto(index_file,index_base,"Zone_t",1,"ZoneBC_t",1,"BC_t",ibc,"end"); cg_gridlocation_write(CGNS_ENUMV(FaceCenter)); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added FaceCenter BCs (PointList) to unstructured grid file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_con2zn_genrl_str.c000066400000000000000000000107711343724673500245730ustar00rootroot00000000000000/* Program write_con2zn_genrl_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid (2 zones), and adds 1-to-1 connectivity information to it (using GENERAL method, as opposed to specific 1-to-1 method). The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid2zn_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_con2zn_genrl_str.c cc -o write_con2zn_genrl_str_c write_con2zn_genrl_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxcount 400 int main() { int ilo[2],ihi[2],jlo[2],jhi[2],klo[2],khi[2]; int icount,j,k; int index_file,index_base,nzone,index_zone,nconns,n1to1,index_conn,iz; char donorname[33],zonename0[33],zonename1[33],zn[33]; cgsize_t isize[3][3],ipnts[maxcount][3],ipntsdonor[maxcount][3]; cgsize_t icounts; printf("\nProgram write_con2zn_genrl_str\n"); /* WRITE GENERAL CONNECTIVITY INFORMATION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* get number of zones (should be 2 for our case) */ cg_nzones(index_file,index_base,&nzone); if (nzone != 2) { printf("\nError. This program expects 2 zones. %d read.\n",nzone); return 1; } /* loop over zones to get zone sizes and names */ for (index_zone=0; index_zone < nzone; ++index_zone) { iz=index_zone+1; cg_zone_read(index_file,index_base,iz,zn,isize[0]); if (index_zone == 0) { strcpy(zonename0,zn); } else { strcpy(zonename1,zn); } ilo[index_zone]=1; ihi[index_zone]=isize[0][0]; jlo[index_zone]=1; jhi[index_zone]=isize[0][1]; klo[index_zone]=1; khi[index_zone]=isize[0][2]; } /* loop over zones again */ for (index_zone=0; index_zone < nzone; ++index_zone) { iz=index_zone+1; /* for this program, there should be no existing connectivity info: */ cg_nconns(index_file,index_base,iz,&nconns); if (nconns != 0) { printf("\nError. This program expects no interfaces yet. %d read.\n",nconns); return 1; } cg_n1to1(index_file,index_base,iz,&n1to1); if (n1to1 != 0) { printf("\nError. This program expects no interfaces yet. %d read.\n",n1to1); return 1; } /* set up point lists */ if (index_zone == 0) { strcpy(donorname,zonename1); icount=0; for (j=jlo[index_zone]; j <= jhi[index_zone]; j++) { for (k=klo[index_zone]; k <= khi[index_zone]; k++) { ipnts[icount][0]=ihi[0]; ipnts[icount][1]=j; ipnts[icount][2]=k; ipntsdonor[icount][0]=ilo[1]; ipntsdonor[icount][1]=j; ipntsdonor[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } } else { strcpy(donorname,zonename0); icount=0; for (j=jlo[index_zone]; j <= jhi[index_zone]; j++) { for (k=klo[index_zone]; k <= khi[index_zone]; k++) { ipnts[icount][0]=ilo[1]; ipnts[icount][1]=j; ipnts[icount][2]=k; ipntsdonor[icount][0]=ihi[0]; ipntsdonor[icount][1]=j; ipntsdonor[icount][2]=k; icount=icount+1; } } if (icount > maxcount) { printf("\nError. Need to increase maxcount to at least %i\n",icount); return 1; } } /* write integer connectivity info (user can give any name) */ icounts=icount; cg_conn_write(index_file,index_base,iz,"GenInterface",CGNS_ENUMV(Vertex),CGNS_ENUMV(Abutting1to1), CGNS_ENUMV(PointList),icounts,ipnts[0],donorname,CGNS_ENUMV(Structured), CGNS_ENUMV(PointListDonor),CGNS_ENUMV(Integer),icounts,ipntsdonor[0],&index_conn); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added 1-to-1 connectivity info to file grid_c.cgns (using GENERAL method)\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_con2zn_str.c000066400000000000000000000101221343724673500233720ustar00rootroot00000000000000/* Program write_con2zn_str.c */ /* Opens an existing CGNS file that contains a simple 3-D structured grid (2 zones), and adds 1-to-1 connectivity information to it. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid2zn_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_con2zn_str.c cc -o write_con2zn_str_c write_con2zn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int ilo[2],ihi[2],jlo[2],jhi[2],klo[2],khi[2]; int itranfrm[3]; int index_file,index_base,nzone,index_zone,nconns,n1to1,index_conn,iz; char donorname[33],zonename0[33],zonename1[33],zn[33]; cgsize_t isize[3][3],ipnts[2][3],ipntsdonor[2][3]; printf("\nProgram write_con2zn_str\n"); /* WRITE 1-TO-1 CONNECTIVITY INFORMATION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* get number of zones (should be 2 for our case) */ cg_nzones(index_file,index_base,&nzone); if (nzone != 2) { printf("\nError. This program expects 2 zones. %d read.\n",nzone); return 1; } /* loop over zones to get zone sizes and names */ for (index_zone=0; index_zone < nzone; ++index_zone) { iz=index_zone+1; cg_zone_read(index_file,index_base,iz,zn,isize[0]); if (index_zone == 0) { strcpy(zonename0,zn); } else { strcpy(zonename1,zn); } ilo[index_zone]=1; ihi[index_zone]=isize[0][0]; jlo[index_zone]=1; jhi[index_zone]=isize[0][1]; klo[index_zone]=1; khi[index_zone]=isize[0][2]; } /* loop over zones again */ for (index_zone=0; index_zone < nzone; ++index_zone) { iz=index_zone+1; /* for this program, there should be no existing connectivity info: */ cg_nconns(index_file,index_base,iz,&nconns); if (nconns != 0) { printf("\nError. This program expects no interfaces yet. %d read.\n",nconns); return 1; } cg_n1to1(index_file,index_base,iz,&n1to1); if (n1to1 != 0) { printf("\nError. This program expects no interfaces yet. %d read.\n",n1to1); return 1; } /* set up index ranges */ if (index_zone == 0) { strcpy(donorname,zonename1); /* lower point of receiver range */ ipnts[0][0]=ihi[0]; ipnts[0][1]=jlo[0]; ipnts[0][2]=klo[0]; /* upper point of receiver range */ ipnts[1][0]=ihi[0]; ipnts[1][1]=jhi[0]; ipnts[1][2]=khi[0]; /* lower point of donor range */ ipntsdonor[0][0]=ilo[1]; ipntsdonor[0][1]=jlo[1]; ipntsdonor[0][2]=klo[1]; /* upper point of donor range */ ipntsdonor[1][0]=ilo[1]; ipntsdonor[1][1]=jhi[1]; ipntsdonor[1][2]=khi[1]; } else { strcpy(donorname,zonename0); /* lower point of receiver range */ ipnts[0][0]=ilo[1]; ipnts[0][1]=jlo[1]; ipnts[0][2]=klo[1]; /* upper point of receiver range */ ipnts[1][0]=ilo[1]; ipnts[1][1]=jhi[1]; ipnts[1][2]=khi[1]; /* lower point of donor range */ ipntsdonor[0][0]=ihi[0]; ipntsdonor[0][1]=jlo[0]; ipntsdonor[0][2]=klo[0]; /* upper point of donor range */ ipntsdonor[1][0]=ihi[0]; ipntsdonor[1][1]=jhi[0]; ipntsdonor[1][2]=khi[0]; } /* set up Transform */ itranfrm[0]=1; itranfrm[1]=2; itranfrm[2]=3; /* write 1-to-1 info (user can give any name) */ cg_1to1_write(index_file,index_base,iz,"Interface",donorname, ipnts[0],ipntsdonor[0],itranfrm,&index_conn); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added 1-to-1 connectivity info to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_convergence.c000066400000000000000000000032441343724673500235760ustar00rootroot00000000000000/* Program write_convergence */ /* Adds convergence history to an existing CGNS file. The CGNS grid file 'grid_c.cgns' must already exist. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_convergence.c cc -o write_convergence_c write_convergence.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define ntt 20 int main() { double cl[ntt]; int n,index_file,index_base; cgsize_t nuse; printf("\nProgram write_convergence\n"); /* create history array simple example: */ for (n=0; n < ntt; n++) { cl[n]=(float)n+1.; } printf("\ncreated simple cl history\n"); /* WRITE CONVERGENCE HISTORY INFORMATION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* go to base node */ cg_goto(index_file,index_base,"end"); /* create history node (SIDS names it GlobalConvergenceHistory at base level) */ cg_convergence_write(ntt,""); /* go to new history node */ cg_goto(index_file,index_base,"ConvergenceHistory_t",1,"end"); /* write lift coefficient array (user must use SIDS-standard name here) */ nuse=ntt; cg_array_write("CoefLift",CGNS_ENUMV(RealDouble),1,&nuse,&cl); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote cl history to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_descriptor.c000066400000000000000000000025461343724673500234620ustar00rootroot00000000000000/* Program write_descriptor */ /* Adds descriptor node to an existing CGNS file (under the CGNSBase_t node). The CGNS grid file 'grid_c.cgns' must already exist. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_descriptor.c cc -o write_descriptor_c write_descriptor.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int index_file,index_base; char textstring[74]; printf("\nProgram write_descriptor\n"); /* WRITE DESCRIPTOR NODE AT BASE LEVEL */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* go to base node */ cg_goto(index_file,index_base,"end"); /* write descriptor node (user can give any name) */ strcpy(textstring,"Supersonic vehicle with landing gear\n"); strcat(textstring,"M=4.6, Re=6 million"); cg_descriptor_write("Information",textstring); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote descriptor node to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_dimensional.c000066400000000000000000000070111343724673500235760ustar00rootroot00000000000000/* Program write_dimensional */ /* Opens an existing CGNS file that contains a simple 3-D grid plus a flow solution and adds its dimensionality (dimensional data). The CGNS grid file 'grid_c.cgns' must already exist (for example, created using write_grid_str.c followed by write_flowcent_str.c or write_grid_str.c followed by write_flowvert_str.c or write_grid_str.c followed by write_flowcentrind_str.c or write_grid_unst.c followed by write_flowvert_unst.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_dimensional.c cc -o write_dimensional_c write_dimensional.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { float exponents[5]; int index_file,index_base,index_zone,index_flow,index_grid; int nfields,iff,icc,ncoords; char fieldname[33]; CGNS_ENUMT(DataType_t) idatatype; printf("\nProgram write_dimensional\n"); /* WRITE DIMENSIONAL INFO FOR GRID AND FLOW SOLN */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* we know there is only one GridCoordinates_t (real working code would check!) */ index_grid=1; /* put DataClass and DimensionalUnits under Base */ cg_goto(index_file,index_base,"end"); cg_dataclass_write(CGNS_ENUMV(Dimensional)); cg_units_write(CGNS_ENUMV(Kilogram),CGNS_ENUMV(Meter),CGNS_ENUMV(Second),CGNS_ENUMV(Kelvin),CGNS_ENUMV(Degree)); /* read fields */ cg_nfields(index_file,index_base,index_zone,index_flow,&nfields); if (nfields != 2) { printf("\nError! expecting 2 fields, read %d\n",nfields); return 1; } for (iff=1; iff <= nfields; iff++) { cg_field_info(index_file,index_base,index_zone,index_flow,iff,&idatatype,fieldname); printf("fieldname=%s\n",fieldname); if (strcmp(fieldname,"Density") == 0) { exponents[0]=1.; exponents[1]=-3.; exponents[2]=0.; exponents[3]=0.; exponents[4]=0.; } else if (strcmp(fieldname,"Pressure") == 0) { exponents[0]=1.; exponents[1]=-1.; exponents[2]=-2.; exponents[3]=0.; exponents[4]=0.; } else { printf("\nError! this fieldname not expected: %s\n",fieldname); return 1; } /* write DimensionalExponents */ cg_goto(index_file,index_base,"Zone_t",1,"FlowSolution_t",1,"DataArray_t",iff,"end"); cg_exponents_write(CGNS_ENUMV(RealSingle),exponents); } /* read grid */ cg_ncoords(index_file,index_base,index_zone,&ncoords); exponents[0]=0.; exponents[1]=1.; exponents[2]=0.; exponents[3]=0.; exponents[4]=0.; for (icc=1; icc <= ncoords; icc++) { /* write DimensionalExponents */ cg_goto(index_file,index_base,"Zone_t",1,"GridCoordinates_t",1,"DataArray_t",icc,"end"); cg_exponents_write(CGNS_ENUMV(RealSingle),exponents); } /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote dimensional data to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_discreteface_str.c000066400000000000000000000116221343724673500246100ustar00rootroot00000000000000/* Program write_discreteface_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds discrete data (at K-DIR FACE CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) to it. In memory, rind cells also exist in the K direction, necessitating use of cg_array_general_write. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_discreteface_str.c cc -o write_discreteface_str_c write_discreteface_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that there are no restrictions on tri-dimensional array f because because a general write interface is used). Rind cells are stored in array locations [0][j][i], [10][j][i], [k][0][i], [k][17][i], [k][j][0], [k][j][21] */ double f[9+2][16+2][20+2]; int ni,nj,nk,i,j,k,kk,index_file,index_base,index_zone,index_discrete; int irinddata[3][2]; cgsize_t dims[3], rmin[3], rmax[3], m_dims[3], m_rmin[3], m_rmax[3]; printf("\nProgram write_discreteface_str\n"); /* create fake discrete data AT I-DIR CELL FACES for simple example: */ ni=20; nj=16; nk=9; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { f[k+1][j+1][i+1]=(double)i; } } } /* create rind cell data: */ for (j=0; j < nj+2; j++) { for (i=0; i < ni+2; i++) { f[0 ][j][i]= 999.; f[nk+1][j][i]=-999.; } } for (k=0; k < nk+2; k++) { kk=k+1; for (j=0; j < nj+2; j++) { f[k][j][0 ]= 999.+(float)j+(5.*(float)kk); f[k][j][ni+1]=-999.-(float)j-(5.*(float)kk); } } for (k=0; k < nk+2; k++) { kk=k+1; for (i=0; i < ni+2; i++) { f[k][0 ][i]= 888.+(float)i+(5.*(float)kk); f[k][nj+1][i]=-888.-(float)i-(5.*(float)kk); } } printf("\ncreated simple 3-D flux with rind data\n"); /* WRITE DISCRETE DATA TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* create discrete data node */ cg_discrete_write(index_file,index_base,index_zone,"DiscreteData",&index_discrete); /* go to position within tree at DiscreteData_t node */ cg_goto(index_file,index_base,"Zone_t",index_zone,"DiscreteData_t",index_discrete,"end"); /* write data location under DiscreteData_t node */ cg_gridlocation_write(CGNS_ENUMV(KFaceCenter)); /* write rind information under DiscreteData_t node (ilo,ihi,jlo,jhi,klo,khi) */ irinddata[0][0]=1; irinddata[0][1]=1; irinddata[1][0]=1; irinddata[1][1]=1; irinddata[2][0]=0; /* note that we are not writing k-direction rind */ irinddata[2][1]=0; /* planes */ cg_rind_write(irinddata[0]); /* write array data (use of cg_array_general_write allows for defining a hyperslab in memory that excludes the k-direction rind planes) */ /* dimensions of array in file */ dims[0] = ni+2; dims[1] = nj+2; dims[2] = nk; /* no k-direction rind planes in file */ /* dimensions of array in memory */ m_dims[0] = ni+2; m_dims[1] = nj+2; m_dims[2] = nk+2; /* in file space the core cells ALWAYS start at index 1 */ /* lower range index in file */ rmin[0] = 1-irinddata[0][0]; rmin[1] = 1-irinddata[1][0]; rmin[2] = 1-irinddata[2][0]; /* upper range index in file */ rmax[0] = ni+irinddata[0][1]; rmax[1] = nj+irinddata[1][1]; rmax[2] = nk+irinddata[2][1]; /* in memory space, the lower bound ALWAYS starts at index 1 (in this example, * core cells start at 2) */ /* lower range index in memory */ m_rmin[0] = 2-irinddata[0][0]; m_rmin[1] = 2-irinddata[1][0]; m_rmin[2] = 2-irinddata[2][0]; /* upper range index in memory */ m_rmax[0] = 1+ni+irinddata[0][0]; m_rmax[1] = 1+nj+irinddata[1][0]; m_rmax[2] = 1+nk+irinddata[2][0]; if (cg_array_general_write("K-Flux", CGNS_ENUMV(RealDouble), 3, dims, rmin, rmax, CGNS_ENUMV(RealDouble), 3, m_dims, m_rmin, m_rmax, f)) cg_error_exit(); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added discrete data to file grid_c.cgns\n"); printf("\nNote: if the original CGNS file already had a DiscreteData_t node,"); printf("\n it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_flowcent_str.c000066400000000000000000000055201343724673500240100ustar00rootroot00000000000000/* Program write_flowcent_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds a flow solution (at CELL CENTERS) to it. (Compare this program with write_flowvert_str) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_flowcent_str.c cc -o write_flowcent_str_c write_flowcent_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N-1][17-1][21-1] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use cg_field_general_write, use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double r[8][16][20],p[8][16][20]; int ni,nj,nk,i,j,k,index_file,index_base,index_zone,index_flow,index_field; char solname[33]; printf("\nProgram write_flowcent_str\n"); /* create fake flow solution AT CELL CENTERS for simple example: */ ni=20; nj=16; nk=8; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { r[k][j][i]=(float)i; p[k][j][i]=(float)j; } } } printf("\ncreated simple 3-D rho and p flow solution\n"); /* WRITE FLOW SOLUTION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* define flow solution node name (user can give any name) */ strcpy(solname,"FlowSolution"); /* create flow solution node (NOTE USE OF CGNS_ENUMV(CellCenter) HERE) */ cg_sol_write(index_file,index_base,index_zone,solname,CGNS_ENUMV(CellCenter),&index_flow); /* write flow solution (user must use SIDS-standard names here) */ cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Density",r[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Pressure",p[0][0],&index_field); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added CellCenter flow solution data to file grid_c.cgns\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t node,"); printf("\n it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_flowcentrind_str.c000066400000000000000000000100161343724673500246610ustar00rootroot00000000000000/* Program write_flowcentrind_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds a flow solution (at CELL CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) to it. (Compare this program with write_flowcent_str) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_flowcentrind_str.c cc -o write_flowcentrind_str_c write_flowcentrind_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N-1][17-1+2][21-1+2] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use cg_field_general_write, use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): Rind cells are stored in array locations [k][0][i], [k][17][i], [k][j][0], [k][j][21] */ double r[8][18][22],p[8][18][22]; int ni,nj,nk,i,j,k,kk,index_file,index_base,index_zone,index_flow,index_field; int irinddata[6]; char solname[33]; printf("\nProgram write_flowcentrind_str\n"); /* create fake flow solution AT CELL CENTERS for simple example: */ ni=20; nj=16; nk=8; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { r[k][j+1][i+1]=(float)i; p[k][j+1][i+1]=(float)j; } } } /* create rind cell data: */ for (k=0; k < nk; k++) { kk=k+1; for (j=0; j <= nj+1; j++) { r[k][j][0]=999.+(float)j+(5.*(float)kk); p[k][j][0]=999.+(float)j+(5.*(float)kk)+1.; r[k][j][ni+1]=-999.-(float)j-(5.*(float)kk); p[k][j][ni+1]=-999.-(float)j-(5.*(float)kk)-1.; } } for (k=0; k < nk; k++) { kk=k+1; for (i=0; i <= ni+1; i++) { r[k][0][i]=888.+(float)i+(5.*(float)kk); p[k][0][i]=888.+(float)i+(5.*(float)kk)+1.; r[k][nj+1][i]=-888.-(float)i-(5.*(float)kk); p[k][nj+1][i]=-888.-(float)i-(5.*(float)kk)-1.; } } printf("\ncreated simple 3-D rho and p flow solution with rind data\n"); /* WRITE FLOW SOLUTION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* define flow solution node name (user can give any name) */ strcpy(solname,"FlowSolution"); /* create flow solution node (NOTE USE OF CGNS_ENUMV(CellCenter) HERE) */ cg_sol_write(index_file,index_base,index_zone,solname,CGNS_ENUMV(CellCenter),&index_flow); /* go to position within tree at FlowSolution_t node */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowSolution_t",index_flow,"end"); /* write rind information under FlowSolution_t node (ilo,ihi,jlo,jhi,klo,khi) */ irinddata[0]=1; irinddata[1]=1; irinddata[2]=1; irinddata[3]=1; irinddata[4]=0; irinddata[5]=0; cg_rind_write(irinddata); /* write flow solution (user must use SIDS-standard names here) */ cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Density",r[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Pressure",p[0][0],&index_field); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added flow solution data to file grid_c.cgns\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t node,"); printf("\n it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_floweqn_str.c000066400000000000000000000071071343724673500236450ustar00rootroot00000000000000/* Program write_floweqn_str */ /* Opens an existing CGNS file and writes flow eqn info The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.f) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_floweqn_str.c cc -o write_floweqn_str_c write_floweqn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { int idata[6],index_file,index_base,index_zone,ieq_dim; float gamma,prandtl; cgsize_t nuse; printf("\nProgram write_floweqn_str\n"); /* data for writing */ gamma=1.4; prandtl=0.90; /* WRITE FLOW EQUATION SET INFO */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* existing file must be 3D structured (real working code would check!) */ /* Create 'FlowEquationSet' node under 'Zone_t' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"end"); /* equation dimension = 3 */ ieq_dim=3; cg_equationset_write(ieq_dim); /* Create 'GoverningEquations' node under 'FlowEquationSet' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_governing_write(CGNS_ENUMV(NSTurbulent)); /* Create 'DiffusionModel' node under 'GoverningEquations' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, "GoverningEquations_t",1,"end"); idata[0]=0; idata[1]=1; idata[2]=0; idata[3]=0; idata[4]=0; idata[5]=0; cg_diffusion_write(idata); nuse=1; /* Create 'GasModel' under 'FlowEquationSet' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_write("GasModel_t",CGNS_ENUMV(Ideal)); /* Create 'SpecificHeatRatio' under GasModel */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, "GasModel_t",1,"end"); cg_array_write("SpecificHeatRatio",CGNS_ENUMV(RealSingle),1,&nuse,&gamma); /* Create 'DataClass' under 'SpecificHeatRatio' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, "GasModel_t",1,"DataArray_t",1,"end"); cg_dataclass_write(CGNS_ENUMV(NondimensionalParameter)); /* Create 'TurbulenceClosure' under 'FlowEquationSet' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_write("TurbulenceClosure_t",CGNS_ENUMV(EddyViscosity)); /* Create 'PrandtlTurbulent' under 'TurbulenceClosure' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, "TurbulenceClosure_t",1,"end"); cg_array_write("PrandtlTurbulent",CGNS_ENUMV(RealSingle),1,&nuse,&prandtl); /* Create 'DataClass' under 'PrandtlTurbulent' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1, "TurbulenceClosure_t",1,"DataArray_t",1,"end"); cg_dataclass_write(CGNS_ENUMV(NondimensionalParameter)); /* Create 'TurbulenceModel' under 'FlowEquationSet' */ cg_goto(index_file,index_base,"Zone_t",index_zone,"FlowEquationSet_t",1,"end"); cg_model_write("TurbulenceModel_t",CGNS_ENUMV(OneEquation_SpalartAllmaras)); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote equation set info to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_flowvert_str.c000066400000000000000000000053701343724673500240420ustar00rootroot00000000000000/* Program write_flowvert_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds a flow solution (at VERTICES) to it. (Compare this program with write_flowcent_str) The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_flowvert_str.c cc -o write_flowvert_str_c write_flowvert_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r and p must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double r[9][17][21],p[9][17][21]; int ni,nj,nk,i,j,k,index_file,index_base,index_zone,index_flow,index_field; char solname[33]; printf("\nProgram write_flowvert_str\n"); /* create fake flow solution AT CELL CENTERS for simple example: */ ni=21; nj=17; nk=9; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { r[k][j][i]=(float)i; p[k][j][i]=(float)j; } } } printf("\ncreated simple 3-D rho and p flow solution\n"); /* WRITE FLOW SOLUTION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* define flow solution node name (user can give any name) */ strcpy(solname,"FlowSolution"); /* create flow solution node */ cg_sol_write(index_file,index_base,index_zone,solname,CGNS_ENUMV(Vertex),&index_flow); /* write flow solution (user must use SIDS-standard names here) */ cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Density",r[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Pressure",p[0][0],&index_field); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added Vertex flow solution data to file grid_c.cgns\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t node,"); printf("\n it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_flowvert_unst.c000066400000000000000000000051201343724673500242140ustar00rootroot00000000000000/* Program write_flowvert_unst */ /* Opens an existing CGNS file that contains a simple 3-D unstructured grid, and adds a flow solution (at VERTICES) to it. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_unst.c) Note that, other than the dimensions of the variables r and p, this program is essentially identical to that for writing flow solutions to a structured zone: write_flowvert_str.c Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_flowvert_unst.c cc -o write_flowvert_unst_c write_flowvert_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { double r[9*17*21],p[9*17*21]; int ni,nj,nk,i,j,k,index_file,index_base,index_zone,index_flow,index_field,iset; char solname[33]; printf("\nProgram write_flowvert_unst\n"); /* create fake flow solution AT CELL CENTERS for simple example: */ ni=21; nj=17; nk=9; iset=0; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { r[iset]=(float)i; p[iset]=(float)j; iset=iset+1; } } } printf("\ncreated simple 3-D rho and p flow solution\n"); /* WRITE FLOW SOLUTION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* define flow solution node name (user can give any name) */ strcpy(solname,"FlowSolution"); /* create flow solution node */ cg_sol_write(index_file,index_base,index_zone,solname,CGNS_ENUMV(Vertex),&index_flow); /* write flow solution (user must use SIDS-standard names here) */ cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Density",r,&index_field); cg_field_write(index_file,index_base,index_zone,index_flow, CGNS_ENUMV(RealDouble),"Pressure",p,&index_field); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added Vertex flow solution data to file grid_c.cgns (unstructured)\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t node,"); printf("\n it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_grid2zn_str.c000066400000000000000000000071631343724673500235530ustar00rootroot00000000000000/* Program write_grid2zn_str.c */ /* Creates simple 3-D structured grid WITH 2 ZONES and writes it to a CGNS file. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_grid2zn_str.c cc -o write_grid2zn_str_c write_grid2zn_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays x,y,z must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double x1[9][17][21],y1[9][17][21],z1[9][17][21]; double x2[9][17][21],y2[9][17][21],z2[9][17][21]; cgsize_t isize[3][3]; int ni,nj,nk,i,j,k; int index_file,icelldim,iphysdim,index_base; int index_zone,index_coord; char basename[33],zonename[33]; printf("\nProgram write_grid2zn_str\n"); /* create gridpoints for simple example: */ ni=21; nj=17; nk=9; for (k=0; k < nk; ++k) { for (j=0; j < nj; ++j) { for (i=0; i < ni; ++i) { x1[k][j][i]=i; y1[k][j][i]=j; z1[k][j][i]=k; x2[k][j][i]=x1[k][j][i]+20.; y2[k][j][i]=y1[k][j][i]; z2[k][j][i]=z1[k][j][i]; } } } printf("\ncreated simple 3-D grid points (2 zones)"); /* WRITE X, Y, Z GRID POINTS TO CGNS FILE */ /* open CGNS file for write */ if (cg_open("grid_c.cgns",CG_MODE_WRITE,&index_file)) cg_error_exit(); /* create base (user can give any name) */ strcpy(basename,"Base"); icelldim=3; iphysdim=3; cg_base_write(index_file,basename,icelldim,iphysdim,&index_base); /* vertex size */ isize[0][0]=21; isize[0][1]=17; isize[0][2]=9; /* cell size */ isize[1][0]=isize[0][0]-1; isize[1][1]=isize[0][1]-1; isize[1][2]=isize[0][2]-1; /* boundary vertex size (always zero for structured grids) */ isize[2][0]=0; isize[2][1]=0; isize[2][2]=0; /* define zone 1 name (user can give any name) */ strcpy(zonename,"Zone 1"); /* create zone */ cg_zone_write(index_file,index_base,zonename,*isize,CGNS_ENUMV(Structured),&index_zone); /* write grid coordinates (user must use SIDS-standard names here) */ cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateX", x1,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateY", y1,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateZ", z1,&index_coord); /* define zone 2 name (user can give any name) */ strcpy(zonename,"Zone 2"); /* create zone */ cg_zone_write(index_file,index_base,zonename,*isize,CGNS_ENUMV(Structured),&index_zone); /* write grid coordinates (user must use SIDS-standard names here) */ cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateX", x2,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateY", y2,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateZ", z2,&index_coord); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote grid to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_grid_str.c000066400000000000000000000054241343724673500231170ustar00rootroot00000000000000/* Program write_grid_str.c */ /* Creates simple 3-D structured grid and writes it to a CGNS file. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_grid_str.c cc -o write_grid_str_c write_grid_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays x,y,z must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use cg_coord_general_write, 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double x[9][17][21],y[9][17][21],z[9][17][21]; cgsize_t isize[3][3]; int ni,nj,nk,i,j,k; int index_file,icelldim,iphysdim,index_base; int index_zone,index_coord; char basename[33],zonename[33]; printf("\nProgram write_grid_str\n"); /* create gridpoints for simple example: */ ni=21; nj=17; nk=9; for (k=0; k < nk; ++k) { for (j=0; j < nj; ++j) { for (i=0; i < ni; ++i) { x[k][j][i]=i; y[k][j][i]=j; z[k][j][i]=k; } } } printf("\ncreated simple 3-D grid points"); /* WRITE X, Y, Z GRID POINTS TO CGNS FILE */ /* open CGNS file for write */ if (cg_open("grid_c.cgns",CG_MODE_WRITE,&index_file)) cg_error_exit(); /* create base (user can give any name) */ strcpy(basename,"Base"); icelldim=3; iphysdim=3; cg_base_write(index_file,basename,icelldim,iphysdim,&index_base); /* define zone name (user can give any name) */ strcpy(zonename,"Zone 1"); /* vertex size */ isize[0][0]=21; isize[0][1]=17; isize[0][2]=9; /* cell size */ isize[1][0]=isize[0][0]-1; isize[1][1]=isize[0][1]-1; isize[1][2]=isize[0][2]-1; /* boundary vertex size (always zero for structured grids) */ isize[2][0]=0; isize[2][1]=0; isize[2][2]=0; /* create zone */ cg_zone_write(index_file,index_base,zonename,*isize,CGNS_ENUMV(Structured),&index_zone); /* write grid coordinates (user must use SIDS-standard names here) */ cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateX", x,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateY", y,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateZ", z,&index_coord); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote grid to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_grid_unst.c000066400000000000000000000176421343724673500233050ustar00rootroot00000000000000/* Program write_grid_unst */ /* Creates simple 3-D unstructured grid and writes it to a CGNS file. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_grid_unst.c cc -o write_grid_unst_c write_grid_unst.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif #define maxelemi 20*16*8 #define maxelemj 1216 int main() { double x[21*17*9],y[21*17*9],z[21*17*9]; cgsize_t isize[3][1],ielem[maxelemi][8],jelem[maxelemj][4]; cgsize_t nelem_start,nelem_end; int ni,nj,nk,iset,i,j,k,index_file,icelldim,iphysdim; int index_base,index_zone,index_coord,ielem_no; int ifirstnode,nbdyelem,index_section; char basename[33],zonename[33]; printf("\nProgram write_grid_unst\n"); /* create gridpoints for simple example: */ ni=21; nj=17; nk=9; iset=0; for (k=1; k <= nk; k++) { for (j=1; j <=nj; j++) { for (i=1; i <= ni; i++) { x[iset]=(float)i-1.; y[iset]=(float)j-1.; z[iset]=(float)k-1.; iset=iset+1; } } } printf("\ncreated simple 3-D grid points\n"); /* WRITE X, Y, Z GRID POINTS TO CGNS FILE */ /* open CGNS file for write */ if (cg_open("grid_c.cgns",CG_MODE_WRITE,&index_file)) cg_error_exit(); /* create base (user can give any name) */ strcpy(basename,"Base"); icelldim=3; iphysdim=3; cg_base_write(index_file,basename,icelldim,iphysdim,&index_base); /* define zone name (user can give any name) */ strcpy(zonename,"Zone 1"); /* vertex size */ isize[0][0]=ni*nj*nk; /* cell size */ isize[1][0]=(ni-1)*(nj-1)*(nk-1); /* boundary vertex size (zero if elements not sorted) */ isize[2][0]=0; /* create zone */ cg_zone_write(index_file,index_base,zonename,isize[0],CGNS_ENUMV(Unstructured),&index_zone); /* write grid coordinates (user must use SIDS-standard names here) */ cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateX", x,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateY", y,&index_coord); cg_coord_write(index_file,index_base,index_zone,CGNS_ENUMV(RealDouble),"CoordinateZ", z,&index_coord); /* set element connectivity: */ /* ---------------------------------------------------------- */ /* do all the HEXA_8 elements (this part is mandatory): */ /* maintain SIDS-standard ordering */ ielem_no=0; /* index no of first element */ nelem_start=1; for (k=1; k < nk; k++) { for (j=1; j < nj; j++) { for (i=1; i < ni; i++) { /* in this example, due to the order in the node numbering, the hexahedral elements can be reconstructed using the following relationships: */ ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; ielem[ielem_no][0]=ifirstnode; ielem[ielem_no][1]=ifirstnode+1; ielem[ielem_no][2]=ifirstnode+1+ni; ielem[ielem_no][3]=ifirstnode+ni; ielem[ielem_no][4]=ifirstnode+ni*nj; ielem[ielem_no][5]=ifirstnode+ni*nj+1; ielem[ielem_no][6]=ifirstnode+ni*nj+1+ni; ielem[ielem_no][7]=ifirstnode+ni*nj+ni; ielem_no=ielem_no+1; } } } /* index no of last element (=2560) */ nelem_end=ielem_no; if (nelem_end > maxelemi) { printf("\nError, must increase maxelemi to at least %d\n",nelem_end); return 1; } /* unsorted boundary elements */ nbdyelem=0; /* write CGNS_ENUMV(HEXA_8) element connectivity (user can give any name) */ cg_section_write(index_file,index_base,index_zone,"Elem",CGNS_ENUMV(HEXA_8),nelem_start, nelem_end,nbdyelem,ielem[0],&index_section); /* ---------------------------------------------------------- */ /* do boundary (QUAD) elements (this part is optional, but you must do it if you eventually want to define BCs at element faces rather than at nodes): maintain SIDS-standard ordering */ /* INFLOW: */ ielem_no=0; /* index no of first element */ nelem_start=nelem_end+1; i=1; for (k=1; k < nk; k++) { for (j=1; j < nj; j++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode; jelem[ielem_no][1]=ifirstnode+ni*nj; jelem[ielem_no][2]=ifirstnode+ni*nj+ni; jelem[ielem_no][3]=ifirstnode+ni; ielem_no=ielem_no+1; } } /* index no of last element */ nelem_end=nelem_start+ielem_no-1; if (ielem_no > maxelemj) { printf("\nError, must increase maxelemj to at least %d\n",ielem_no); return 1; } /* write QUAD element connectivity for inflow face (user can give any name) */ cg_section_write(index_file,index_base,index_zone,"InflowElem",CGNS_ENUMV(QUAD_4),nelem_start, nelem_end,nbdyelem,jelem[0],&index_section); /* OUTFLOW: */ ielem_no=0; /* index no of first element */ nelem_start=nelem_end+1; i=ni-1; for (k=1; k < nk; k++) { for (j=1; j < nj; j++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode+1; jelem[ielem_no][1]=ifirstnode+1+ni; jelem[ielem_no][2]=ifirstnode+ni*nj+1+ni; jelem[ielem_no][3]=ifirstnode+ni*nj+1; ielem_no=ielem_no+1; } } /* index no of last element */ nelem_end=nelem_start+ielem_no-1; if (ielem_no > maxelemj) { printf("\nError, must increase maxelemj to at least %d\n",ielem_no); return 1; } /* write QUAD element connectivity for outflow face (user can give any name) */ cg_section_write(index_file,index_base,index_zone,"OutflowElem",CGNS_ENUMV(QUAD_4),nelem_start, nelem_end,nbdyelem,jelem[0],&index_section); /* SIDEWALLS: */ ielem_no=0; /* index no of first element */ nelem_start=nelem_end+1; j=1; for (k=1; k < nk; k++) { for (i=1; i < ni; i++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode; jelem[ielem_no][1]=ifirstnode+ni*nj; jelem[ielem_no][2]=ifirstnode+ni*nj+1; jelem[ielem_no][3]=ifirstnode+1; ielem_no=ielem_no+1; } } j=nj-1; for (k=1; k < nk; k++) { for (i=1; i < ni; i++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode+1+ni; jelem[ielem_no][1]=ifirstnode+ni; jelem[ielem_no][2]=ifirstnode+ni*nj+ni; jelem[ielem_no][3]=ifirstnode+ni*nj+1+ni; ielem_no=ielem_no+1; } } k=1; for (j=1; j < nj; j++) { for (i=1; i < ni; i++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode; jelem[ielem_no][1]=ifirstnode+1; jelem[ielem_no][2]=ifirstnode+1+ni; jelem[ielem_no][3]=ifirstnode+ni; ielem_no=ielem_no+1; } } k=nk-1; for (j=1; j < nj; j++) { for (i=1; i < ni; i++) { ifirstnode=i+(j-1)*ni+(k-1)*ni*nj; jelem[ielem_no][0]=ifirstnode+ni*nj; jelem[ielem_no][1]=ifirstnode+ni*nj+ni; jelem[ielem_no][2]=ifirstnode+ni*nj+1+ni; jelem[ielem_no][3]=ifirstnode+ni*nj+1; ielem_no=ielem_no+1; } } /* index no of last element */ nelem_end=nelem_start+ielem_no-1; if (ielem_no > maxelemj) { printf("\nError, must increase maxelemj to at least %d\n",ielem_no); return 1; } /* write QUAD element connectivity for sidewall face (user can give any name) */ cg_section_write(index_file,index_base,index_zone,"SidewallElem",CGNS_ENUMV(QUAD_4),nelem_start, nelem_end,nbdyelem,jelem[0],&index_section); /* ---------------------------------------------------------- */ /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote unstructured grid to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_nondimensional.c000066400000000000000000000103731343724673500243160ustar00rootroot00000000000000/* Program write_nondimensional */ /* Opens an existing CGNS file and adds the DataClass and ReferenceState appropriate for a completely NONDIMENSIONAL data set. The CGNS grid file 'grid_c.cgns' must already exist (for example, created using write_grid_str.c or write_grid_unst.c). In this case, the flow solution does not need to be present. Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_nondimensional.c cc -o write_nondimensional_c write_nondimensional.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { double xmach,reue,xmv,xmc,rev,rel,renu,rho0; double p0,c0,vm0,xlength0,vx,vy,vz; double gamma; int index_file,index_base; CGNS_ENUMT(DataClass_t) idata; cgsize_t nuse; printf("\nProgram write_nondimensional\n"); /* define nondimensional parameters */ xmach=4.6; reue=6000000.; xmv=xmach; xmc=1.; rev=xmach; rel=1.; renu=xmach/reue; rho0=1.; gamma=1.4; p0=1./gamma; c0=1.; vm0=xmach/reue; xlength0=1.; vx=xmach; vy=0.; vz=0.; nuse=1; /* WRITE NONDIMENSIONAL INFO */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* put DataClass under Base */ cg_goto(index_file,index_base,"end"); /* check first if a dataclass has already been written */ if (CG_OK == cg_dataclass_read(&idata)) { printf("\nError! DataClass already exists!\n"); printf(" Re-make CGNS file without it and related info, then try again\n"); return 1; } cg_dataclass_write(CGNS_ENUMV(NormalizedByUnknownDimensional)); /* put ReferenceState under Base */ cg_state_write("ReferenceQuantities"); /* Go to ReferenceState node, write Mach array and its dataclass */ cg_goto(index_file,index_base,"ReferenceState_t",1,"end"); cg_array_write("Mach",CGNS_ENUMV(RealDouble),1,&nuse,&xmach); cg_goto(index_file,index_base,"ReferenceState_t",1,"DataArray_t",1,"end"); cg_dataclass_write(CGNS_ENUMV(NondimensionalParameter)); /* Go to ReferenceState node, write Reynolds array and its dataclass */ cg_goto(index_file,index_base,"ReferenceState_t",1,"end"); cg_array_write("Reynolds",CGNS_ENUMV(RealDouble),1,&nuse,&reue); cg_goto(index_file,index_base,"ReferenceState_t",1,"DataArray_t",2,"end"); cg_dataclass_write(CGNS_ENUMV(NondimensionalParameter)); /* Go to ReferenceState node to write reference quantities: */ cg_goto(index_file,index_base,"ReferenceState_t",1,"end"); /* First, write reference quantities that make up Mach and Reynolds: */ /* Mach_Velocity */ cg_array_write("Mach_Velocity",CGNS_ENUMV(RealDouble),1,&nuse,&xmv); /* Mach_VelocitySound */ cg_array_write("Mach_VelocitySound",CGNS_ENUMV(RealDouble),1,&nuse,&xmc); /* Reynolds_Velocity */ cg_array_write("Reynolds_Velocity",CGNS_ENUMV(RealDouble),1,&nuse,&rev); /* Reynolds_Length */ cg_array_write("Reynolds_Length",CGNS_ENUMV(RealDouble),1,&nuse,&rel); /* Reynolds_ViscosityKinematic */ cg_array_write("Reynolds_ViscosityKinematic",CGNS_ENUMV(RealDouble),1,&nuse,&renu); /* Next, write flow field reference quantities: */ /* Density */ cg_array_write("Density",CGNS_ENUMV(RealDouble),1,&nuse,&rho0); /* Pressure */ cg_array_write("Pressure",CGNS_ENUMV(RealDouble),1,&nuse,&p0); /* VelocitySound */ cg_array_write("VelocitySound",CGNS_ENUMV(RealDouble),1,&nuse,&c0); /* ViscosityMolecular */ cg_array_write("ViscosityMolecular",CGNS_ENUMV(RealDouble),1,&nuse,&vm0); /* LengthReference */ cg_array_write("LengthReference",CGNS_ENUMV(RealDouble),1,&nuse,&xlength0); /* VelocityX */ cg_array_write("VelocityX",CGNS_ENUMV(RealDouble),1,&nuse,&vx); /* VelocityY */ cg_array_write("VelocityY",CGNS_ENUMV(RealDouble),1,&nuse,&vy); /* VelocityZ */ cg_array_write("VelocityZ",CGNS_ENUMV(RealDouble),1,&nuse,&vz); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully wrote nondimensional info to file grid_c.cgns\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code/write_timevert_str.c000066400000000000000000000126341343724673500240320ustar00rootroot00000000000000/* Program write_timevert_str */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds 3 different flow solutions (at VERTICES) to it, along with time-accurate info. In this example, r1 & p1, r2 & p2, r3 & p3 correspond with solutions at 3 different time steps. The CGNS grid file 'grid_c.cgns' must already exist (created using write_grid_str.c) Example compilation for this program is (change paths if needed!): cc -I ../.. -c write_timevert_str.c cc -o write_timevert_str_c write_timevert_str.o -L ../../lib -lcgns (../../lib is the location where the compiled library libcgns.a is located) */ #include #include /* cgnslib.h file must be located in directory specified by -I during compile: */ #include "cgnslib.h" #if CGNS_VERSION < 3100 # define cgsize_t int #endif int main() { /* dimension statements (note that tri-dimensional arrays r1, r2, r3 and p1, p2, p3 must be dimensioned exactly as [N][17][21] (N>=9) for this particular case or else they will be written to the CGNS file incorrectly! Other options are to use 1-D arrays, use dynamic memory, or pass index values to a subroutine and dimension exactly there): */ double r1[9][17][21],p1[9][17][21]; double r2[9][17][21],p2[9][17][21]; double r3[9][17][21],p3[9][17][21]; double time[3]; int ni,nj,nk,i,j,k,index_file,index_base,index_zone; cgsize_t idata[2],nuse; int index_flow,index_field,nsteps,n; char sn[3][33]; char solname[97]; /* need an extra byte for the terminating 0 */ printf("\nProgram write_timevert_str\n"); /* set up the times corresponding to the 3 solutions to be stored: */ time[0]=10.; time[1]=20.; time[2]=50.; /* create fake flow solution AT VERTICES for simple example: */ ni=21; nj=17; nk=9; for (k=0; k < nk; k++) { for (j=0; j < nj; j++) { for (i=0; i < ni; i++) { /* soln at time 1: */ r1[k][j][i]=(float)i; p1[k][j][i]=(float)j; /* soln at time 2: */ r2[k][j][i]=r1[k][j][i]+1.; p2[k][j][i]=p1[k][j][i]+1.; /* soln at time 3: */ r3[k][j][i]=r2[k][j][i]+1.; p3[k][j][i]=p2[k][j][i]+1.; } } } printf("\ncreated simple 3-D rho and p flow solution\n"); /* WRITE FLOW SOLUTION TO EXISTING CGNS FILE */ /* open CGNS file for modify */ if (cg_open("grid_c.cgns",CG_MODE_MODIFY,&index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base=1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* define 3 different solution names (user can give any names) */ strcpy(sn[0],"FlowSolution1"); strcpy(sn[1],"FlowSolution2"); strcpy(sn[2],"FlowSolution3"); /* sprintf(solname, "%-32s%-32s%-32s", "FlowSolution1", "FlowSolution2", "FlowSolution3"); */ sprintf(solname,"%-32s%-32s%-32s",sn[0],sn[1],sn[2]); /* do loop for the 3 solutions: */ for (n=0; n < 3; n++) { /* create flow solution node */ cg_sol_write(index_file,index_base,index_zone,sn[n],CGNS_ENUMV(Vertex),&index_flow); printf("\n ...writing solution number %d\n",index_flow); /* write flow solution (user must use SIDS-standard names here) */ if (n == 0) { cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Density", r1[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Pressure", p1[0][0],&index_field); } else if (n == 1) { cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Density", r2[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Pressure", p2[0][0],&index_field); } else { cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Density", r3[0][0],&index_field); cg_field_write(index_file,index_base,index_zone,index_flow,CGNS_ENUMV(RealDouble),"Pressure", p3[0][0],&index_field); } } /* create BaseIterativeData */ nsteps=3; cg_biter_write(index_file,index_base,"TimeIterValues",nsteps); /* go to BaseIterativeData level and write time values */ cg_goto(index_file,index_base,"BaseIterativeData_t",1,"end"); nuse=3; cg_array_write("TimeValues",CGNS_ENUMV(RealDouble),1,&nuse,&time); /* create ZoneIterativeData */ cg_ziter_write(index_file,index_base,index_zone,"ZoneIterativeData"); /* go to ZoneIterativeData level and give info telling which */ /* flow solution corresponds with which time (solname(1) corresponds */ /* with time(1), solname(2) with time(2), and solname(3) with time(3)) */ cg_goto(index_file,index_base,"Zone_t",index_zone,"ZoneIterativeData_t",1,"end"); idata[0]=32; idata[1]=3; cg_array_write("FlowSolutionPointers",CGNS_ENUMV(Character),2,idata,solname); /* add SimulationType */ cg_simulation_type_write(index_file,index_base,CGNS_ENUMV(TimeAccurate)); /* close CGNS file */ cg_close(index_file); printf("\nSuccessfully added 3 times of flow solution data and time info to file grid_c.cgns\n"); printf(" Note: if the original CGNS file already had a FlowSolution_t node,\n"); printf(" it has been overwritten\n"); return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/000077500000000000000000000000001343724673500215735ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/CMakeLists.txt000066400000000000000000000020261343724673500243330ustar00rootroot00000000000000######### # Tests # ######### # Link all the executables to cgns and hdf5 link_directories(.) link_libraries(cgns_static) if (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) link_libraries(${HDF5_LIBRARY}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) link_libraries(${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) link_libraries(${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) link_libraries(${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) if (NOT WIN32) link_libraries(m) endif (NOT WIN32) # Set the files needed by each test set (examples write_grid_str_parinzone write_grid_str_paroverzone write_flowcentrind_str_parinzone write_flowcentrind_str_paroverzone read_grid_str_parinzone read_grid_str_paroverzone read_flowcentrind_str_parinzone read_flowcentrind_str_paroverzone ) # Build each test foreach (example ${examples}) add_executable (${example} ${example}.c) endforeach (example ${examples}) CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/read_flowcentrind_str_parinzone.c000066400000000000000000000120761343724673500304130ustar00rootroot00000000000000/* Program read_flowcentrind_str_parinzone */ /* Opens an existing CGNS file that contains a simple 3-D structured grid plus a flow solution (at CELL CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) and reads it. Each processor reads a slab of data from one zone (parallelism within a zone). The CGNS grid file 'grid_piz_c.cgns' must already exist (created using write_grid_str_parinzone.c followed by write_flowcentrind_str_parinzone.c)) Example compilation for this program is (change paths!): mpicxx read_flowcentrind_str_parinzone.c -lcgns -lhdf5 -lsz -lz -o read_flowcentrind_str_parinzone mpirun -np 2 read_flowcentrind_str_parinzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { int n, comm_size, comm_rank; int index_file, index_base, index_zone, index_flow; char zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for read-only */ if (cgp_open("grid_piz_c.cgns", CG_MODE_READ, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* COLLECTIVE READING OF FILE DATA -- each processor reads a part of the zone */ /* get zone size (and name - although not needed here) */ cgsize_t zoneSize[3][3]; if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* partition the k-index of the zone among the processes. Note that the partitions do not include the k-direction rind planes. */ int kIdxBeg; /* beginning k-index for this processor */ int numLocalkIdx = zoneSize[1][2]/comm_size; /* the number of k-indices local to this process */ { int numUnevenkIdx = zoneSize[1][2] - numLocalkIdx*comm_size; if (comm_rank < numUnevenkIdx) { ++numLocalkIdx; kIdxBeg = comm_rank*numLocalkIdx; } else { kIdxBeg = numUnevenkIdx*(numLocalkIdx + 1); kIdxBeg += (comm_rank - numUnevenkIdx)*numLocalkIdx; } } int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *r = NULL; double *p = NULL; int ni, nj, nk; if (numLocalkIdx > 0) { /* create fake flow solution AT CELL CENTERS for simple example. In memory, there are two rind cells in each direction: */ ni = zoneSize[1][0] + 2; nj = zoneSize[1][1] + 2; nk = numLocalkIdx; const int num_vertex = ni*nj*nk; r = (double*)malloc(2*num_vertex*sizeof(double)); p = r + num_vertex; /* shape in file space (core cells start at 1) */ for (n = 0; n < 2; ++n) { s_rmin[n] = 0; s_rmax[n] = zoneSize[1][n] + 1; } s_rmin[2] = kIdxBeg + 1; /* but no rind cells in k-direction */ s_rmax[2] = kIdxBeg + numLocalkIdx; /* shape in memory (array starts at 1)*/ for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[1][n] + 2; m_rmin[n] = 1; m_rmax[n] = zoneSize[1][n] + 2; } m_dimvals[2] = numLocalkIdx; m_rmin[2] = 1; m_rmax[2] = numLocalkIdx; } /* if there is nothing for this process to write, a valid zone index must be provided and data array = NULL */ if (cgp_field_general_read_data(index_file, index_base, index_zone, index_flow, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, r)) cgp_error_exit(); if (cgp_field_general_read_data(index_file, index_base, index_zone, index_flow, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, p)) cgp_error_exit(); if (7 >= kIdxBeg && 7 < kIdxBeg + numLocalkIdx) { printf("\nSuccessfully read flow solution from file grid_piz_c.cgns\n"); printf(" For example, r,p[7][18][20]= %f, %f\n", r[((7 - kIdxBeg)*nj + 18)*ni + 20], p[((7 - kIdxBeg)*nj + 18)*ni + 20]); printf(" rind: r,p[7][18][ 0]= %f, %f\n", r[((7 - kIdxBeg)*nj + 18)*ni + 0], p[((7 - kIdxBeg)*nj + 18)*ni + 0]); printf(" rind: r,p[7][18][21]= %f, %f\n", r[((7 - kIdxBeg)*nj + 18)*ni + 21], p[((7 - kIdxBeg)*nj + 18)*ni + 21]); } if (numLocalkIdx > 0) { free(r); } /* close CGNS file */ cg_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nProgram successful... ending now\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/read_flowcentrind_str_paroverzone.c000066400000000000000000000141231343724673500307530ustar00rootroot00000000000000/* Program read_flowcentrind_str_paroverzone */ /* Opens an existing CGNS file that contains a simple two-zone 3-D structured grid plus a flow solution (at CELL CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) and reads it. Each processor reads data from one zone (parallelism over zones). The CGNS grid file 'grid_poz_c.cgns' must already exist (created using write_grid_str_paroverzone.c followed by write_flowcentrind_str_paroverzone.c) Example compilation for this program is (change paths!): mpicxx read_flowcentrind_str_paroverzone.c -lcgns -lhdf5 -lsz -lz -o read_flowcentrind_str_paroverzone mpirun -np 2 read_flowcentrind_str_paroverzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { int n, comm_size, comm_rank; int index_file, index_base, index_zone, index_flow; char zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for read-only */ if (cgp_open("grid_poz_c.cgns", CG_MODE_READ, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* get the number of zones (should be 2) */ int numZone; if (cg_nzones(index_file, index_base, &numZone)) cg_error_exit(); /* we know there is only one FlowSolution_t (real working code would check!) */ index_flow=1; /* COLLECTIVE READING OF FILE DATA -- each processor reads from a separate zone */ /* partition the zones among the processes */ int maxLocalZone; /* the maximum number of zones on any process */ int idxGlobalZoneBeg; /* the global index of the first zone on this process */ int numLocalZone = numZone/comm_size; /* the number of zones local to this process */ { int numUnevenZone = numZone - numLocalZone*comm_size; maxLocalZone = numLocalZone + (numUnevenZone > 0); if (comm_rank < numUnevenZone) { ++numLocalZone; idxGlobalZoneBeg = comm_rank*numLocalZone; } else { idxGlobalZoneBeg = numUnevenZone*(numLocalZone + 1); idxGlobalZoneBeg += (comm_rank - numUnevenZone)*numLocalZone; } } int idxLocalZone; for (idxLocalZone = 0; idxLocalZone < maxLocalZone; ++idxLocalZone) { const int idxGlobalZone = idxGlobalZoneBeg + idxLocalZone; cgsize_t zoneSize[3][3]; int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *r = NULL; double *p = NULL; int ni, nj, nk; /* if there is nothing for this process to read, a valid zone index must be provided and data array = NULL */ index_zone = (idxGlobalZone < numZone) ? idxGlobalZone + 1 : 1; if (idxGlobalZone < numZone) { /* get zone size (and name - although not needed here) */ if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* allocate memory for reading (all rind planes) */ ni = zoneSize[1][0] + 2; nj = zoneSize[1][1] + 2; nk = zoneSize[1][2] + 2; const int num_vertex = ni*nj*nk; r = (double*)malloc(2*num_vertex*sizeof(double)); p = r + num_vertex; /* shape in file space (core cells start at 1) */ for (n = 0; n < 2; ++n) { s_rmin[n] = 0; s_rmax[n] = zoneSize[1][n] + 1; } s_rmin[2] = 1; /* but no rind cells in k-direction */ s_rmax[2] = zoneSize[1][n]; /* shape in memory (array starts at 1)*/ for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[1][n] + 2; m_rmin[n] = 1; m_rmax[n] = zoneSize[1][n] + 2; } m_dimvals[2] = zoneSize[1][n] + 2; m_rmin[2] = 2; /* but no rind cells in k-direction */ m_rmax[2] = zoneSize[1][n] + 1; } if (cgp_field_general_read_data(index_file, index_base, index_zone, index_flow, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, r)) cgp_error_exit(); if (cgp_field_general_read_data(index_file, index_base, index_zone, index_flow, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, p)) cgp_error_exit(); for (n = 0; n < comm_size; ++n) { if (n == comm_rank) { if (idxGlobalZone < numZone) { int imax = zoneSize[1][0]; printf("\nProcess %d successfully read flow solution from " "zone %d in file grid_poz_c.cgns\n", comm_rank, index_zone); printf(" For example, r,p[8][18][%d]= %f, %f\n", imax, r[(8*nj + 18)*ni + imax], p[(8*nj + 18)*ni + imax]); printf(" rind: r,p[8][18][ 0]= %f, %f\n", r[(8*nj + 18)*ni + 0], p[(8*nj + 18)*ni + 0]); printf(" rind: r,p[8][18][%d]= %f, %f\n", imax+1, r[(8*nj + 18)*ni + imax+1], p[(8*nj + 18)*ni + imax+1]); fflush(stdout); } } /* this does not guarantee output is written in order but may help */ MPI_Barrier(MPI_COMM_WORLD); } if (idxGlobalZone < numZone) { free(r); } } /* close CGNS file */ cg_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nProgram successful... ending now\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/read_grid_str_parinzone.c000066400000000000000000000105611343724673500266370ustar00rootroot00000000000000/* Program read_grid_str_parinzone.c */ /* Reads a simple 3-D structured grid from a CGNS file. Each processor reads a slab of data from one zone (parallelism within a zone). The CGNS grid file 'grid_piz_c.cgns' must already exist. mpicxx read_grid_str_parinzone.c -lcgns -lhdf5 -lsz -lz -o read_grid_str_parinzone mpirun -np 2 write_grid_str_parinzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { cgsize_t zoneSize[3][3]; int n, comm_size, comm_rank; int index_file, index_base, index_zone; char zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for read-only */ if (cgp_open("grid_piz_c.cgns", CG_MODE_READ, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* we know there is only one zone (real working code would check!) */ index_zone = 1; /* get zone size (and name - although not needed here) */ if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* COLLECTIVE READING OF FILE DATA -- each processor reads a part of the zone */ /* partition the k-index of the zone among the processes */ int kIdxBeg; /* beginning k-index for this processor */ int numLocalkIdx = zoneSize[0][2]/comm_size; /* the number of k-indices local to this process */ { int numUnevenkIdx = zoneSize[0][2] - numLocalkIdx*comm_size; if (comm_rank < numUnevenkIdx) { ++numLocalkIdx; kIdxBeg = comm_rank*numLocalkIdx; } else { kIdxBeg = numUnevenkIdx*(numLocalkIdx + 1); kIdxBeg += (comm_rank - numUnevenkIdx)*numLocalkIdx; } } int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *x = NULL; double *y = NULL; double *z = NULL; int ni, nj, nk; if (numLocalkIdx > 0) { /* allocate memory for reading */ ni = zoneSize[0][0]; nj = zoneSize[0][1]; nk = numLocalkIdx; const int num_vertex = ni*nj*nk; x = (double*)malloc(3*num_vertex*sizeof(double)); y = x + num_vertex; z = y + num_vertex; // shape in file space for (n = 0; n < 2; ++n) { s_rmin[n] = 1; s_rmax[n] = zoneSize[0][n]; } s_rmin[2] = kIdxBeg + 1; s_rmax[2] = kIdxBeg + numLocalkIdx; // shape in memory for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[0][n]; m_rmin[n] = 1; m_rmax[n] = zoneSize[0][n]; } m_dimvals[2] = numLocalkIdx; m_rmin[2] = 1; m_rmax[2] = numLocalkIdx; } /* the file data is defined as single but will be read as double */ if (cgp_coord_general_read_data(index_file, index_base, index_zone, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, x)) cgp_error_exit(); if (cgp_coord_general_read_data(index_file, index_base, index_zone, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, y)) cgp_error_exit(); if (cgp_coord_general_read_data(index_file, index_base, index_zone, 3, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, z)) cgp_error_exit(); if (8 >= kIdxBeg && 8 < kIdxBeg + numLocalkIdx) { printf("\nSuccessfully read grid from file grid_piz_c.cgns\n"); printf(" For example, from process %d, zone 1 x,y,z[8][18][16]= " "%f, %f, %f\n", comm_rank, x[((8 - kIdxBeg)*nj + 18)*ni + 16], y[((8 - kIdxBeg)*nj + 18)*ni + 16], z[((8 - kIdxBeg)*nj + 18)*ni + 16]); } if (numLocalkIdx > 0) { free(x); } /* close CGNS file */ cgp_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nProgram successful... ending now\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/read_grid_str_paroverzone.c000066400000000000000000000125501343724673500272040ustar00rootroot00000000000000/* Program read_grid_str_paroverzone.c */ /* Reads a simple 3-D structured grid from a CGNS file. Each processor reads data from one zone (parallelism over zones). The CGNS grid file 'grid_poz_c.cgns' must already exist. mpicxx read_grid_str_paroverzone.c -lcgns -lhdf5 -lsz -lz -o read_grid_str_paroverzone mpirun -np 2 write_grid_str_paroverzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { int n, comm_size, comm_rank; int index_file, index_base, index_zone; char zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for read-only */ if (cgp_open("grid_poz_c.cgns", CG_MODE_READ, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* get the number of zones (should be 2) */ int numZone; if (cg_nzones(index_file, index_base, &numZone)) cg_error_exit(); /* COLLECTIVE READING OF FILE DATA -- each processor reads from a separate zone */ /* partition the zones among the processes */ int maxLocalZone; /* the maximum number of zones on any process */ int idxGlobalZoneBeg; /* the global index of the first zone on this process */ int numLocalZone = numZone/comm_size; /* the number of zones local to this process */ { int numUnevenZone = numZone - numLocalZone*comm_size; maxLocalZone = numLocalZone + (numUnevenZone > 0); if (comm_rank < numUnevenZone) { ++numLocalZone; idxGlobalZoneBeg = comm_rank*numLocalZone; } else { idxGlobalZoneBeg = numUnevenZone*(numLocalZone + 1); idxGlobalZoneBeg += (comm_rank - numUnevenZone)*numLocalZone; } } int idxLocalZone; for (idxLocalZone = 0; idxLocalZone < maxLocalZone; ++idxLocalZone) { const int idxGlobalZone = idxGlobalZoneBeg + idxLocalZone; cgsize_t zoneSize[3][3]; cgsize_t s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *x = NULL; double *y = NULL; double *z = NULL; int ni, nj, nk; /* if there is nothing for this process to read, a valid zone index must be provided and data array = NULL */ index_zone = (idxGlobalZone < numZone) ? idxGlobalZone + 1 : 1; if (idxGlobalZone < numZone) { /* get zone size (and name - although not needed here) */ if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* allocate memory for reading */ ni = zoneSize[0][0]; nj = zoneSize[0][1]; nk = zoneSize[0][2]; const int num_vertex = ni*nj*nk; x = (double*)malloc(3*num_vertex*sizeof(double)); y = x + num_vertex; z = y + num_vertex; /* shape in file space */ for (n = 0; n < 3; ++n) { s_rmin[n] = 1; s_rmax[n] = zoneSize[0][n]; } /* shape in memory */ for (n = 0; n < 3; ++n) { m_dimvals[n] = zoneSize[0][n]; m_rmin[n] = 1; m_rmax[n] = zoneSize[0][n]; } } /* the file data is defined as single but will be read as double */ if (cgp_coord_general_read_data(index_file, index_base, index_zone, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, x)) cgp_error_exit(); if (cgp_coord_general_read_data(index_file, index_base, index_zone, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, y)) cgp_error_exit(); if (cgp_coord_general_read_data(index_file, index_base, index_zone, 3, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, z)) cgp_error_exit(); for (n = 0; n < comm_size; ++n) { if (n == comm_rank) { if (idxGlobalZone < numZone) { printf("\nProcess %d successfully read grid from file " "grid_poz_c.cgns\n", comm_rank); printf(" For example, zone %d x,y,z[8][18][16]= " "%f, %f, %f\n", index_zone, x[(8*nj + 18)*ni + 16], y[(8*nj + 18)*ni + 16], z[(8*nj + 18)*ni + 16]); fflush(stdout); } } /* this does not guarantee output is written in order but may help */ MPI_Barrier(MPI_COMM_WORLD); } if (idxGlobalZone < numZone) { free(x); } } /* close CGNS file */ cgp_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nProgram successful... ending now\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/write_flowcentrind_str_parinzone.c000066400000000000000000000160461343724673500306330ustar00rootroot00000000000000/* Program write_flowcentrind_str_parinzone */ /* Opens an existing CGNS file that contains a simple 3-D structured grid, and adds a flow solution (at CELL CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) to it. The CGNS grid file 'grid_piz_c.cgns' must already exist (created using write_grid_str_parinzone.c) Example compilation for this program is (change paths!): mpicxx write_flowcentrind_str_parinzone.c -lcgns -lhdf5 -lsz -lz -o write_flowcentrind_str_parinzone mpirun -np 2 write_flowcentrind_str_parinzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { int i, j, k, n, comm_size, comm_rank; int index_file, index_base, index_zone, index_flow, index_field; char solname[33], zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for modify */ if (cgp_open("grid_piz_c.cgns", CG_MODE_MODIFY, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* we know there is only one zone (real working code would check!) */ index_zone=1; /* CREATION OF FILE STRUCTURE -- all processors write the same information. Only meta-data is written to the library at this stage */ /* define flow solution node name (user can give any name) */ strcpy(solname, "FlowSolution"); /* create flow solution node (NOTE USE OF CGNS_ENUMV(CellCenter) HERE) */ cg_sol_write(index_file, index_base, index_zone, solname, CGNS_ENUMV(CellCenter), &index_flow); /* go to position within tree at FlowSolution_t node */ cg_goto(index_file, index_base, "Zone_t", index_zone, "FlowSolution_t", index_flow, "end"); /* write rind information under FlowSolution_t node (ilo,ihi,jlo,jhi,klo,khi) */ int irinddata[6] = { 1, 1, 1, 1, 0, 0 }; cg_rind_write(irinddata); if (cgp_field_write(index_file, index_base, index_zone, index_flow, CGNS_ENUMV(RealDouble), "Density", &index_field)) cgp_error_exit(); if (cgp_field_write(index_file, index_base, index_zone, index_flow, CGNS_ENUMV(RealDouble), "Pressure", &index_field)) cgp_error_exit(); /* COLLECTIVE WRITING OF FILE DATA -- each processor writes to a separate zone */ /* get zone size (and name - although not needed here) */ cgsize_t zoneSize[3][3]; if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* partition the k-index of the zone among the processes. Note that the partitions do not include the k-direction rind planes. */ int kIdxBeg; /* beginning k-index for this processor */ int numLocalkIdx = zoneSize[1][2]/comm_size; /* the number of k-indices local to this process */ { int numUnevenkIdx = zoneSize[1][2] - numLocalkIdx*comm_size; if (comm_rank < numUnevenkIdx) { ++numLocalkIdx; kIdxBeg = comm_rank*numLocalkIdx; } else { kIdxBeg = numUnevenkIdx*(numLocalkIdx + 1); kIdxBeg += (comm_rank - numUnevenkIdx)*numLocalkIdx; } } int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *r = NULL; double *p = NULL; int ni, nj, nk; if (numLocalkIdx > 0) { /* create fake flow solution AT CELL CENTERS for simple example. In memory, there are two rind cells in each direction: */ ni = zoneSize[1][0] + 2; nj = zoneSize[1][1] + 2; nk = numLocalkIdx; const int num_vertex = ni*nj*nk; r = (double*)malloc(2*num_vertex*sizeof(double)); p = r + num_vertex; for (k = kIdxBeg; k < kIdxBeg + numLocalkIdx; ++k) { for (j = 1; j < nj-1; ++j) { for (i = 1; i < ni-1; ++i) { int idx = ((k - kIdxBeg)*nj + j)*ni + i; r[idx] = (float)(i - 1); p[idx] = (float)(j - 1); } } } /* create rind cell data: */ /* k rind planes are not even allocated */ for (k = kIdxBeg; k < kIdxBeg + numLocalkIdx; ++k) /* i planes */ { for (j = 0; j < nj; ++j) { int idx = ((k - kIdxBeg)*nj + j)*ni + 0; r[idx] = 999. + (float)j + (5.*(float)k); p[idx] = 999. + (float)j + (5.*(float)k) + 1.; idx = ((k - kIdxBeg)*nj + j)*ni + (ni-1); r[idx] = -999. - (float)j - (5.*(float)k); p[idx] = -999. - (float)j - (5.*(float)k) - 1.; } } for (k = kIdxBeg; k < kIdxBeg + numLocalkIdx; ++k) /* j planes */ { for (i = 0; i < ni; ++i) { int idx = ((k - kIdxBeg)*nj + 0)*ni + i; r[idx] = 888. + (float)i + (5.*(float)k); p[idx] = 888. + (float)i + (5.*(float)k) + 1.; idx = ((k - kIdxBeg)*nj + (nj-1))*ni + i; r[idx] = -888. - (float)i - (5.*(float)k); p[idx] = -888. - (float)i - (5.*(float)k) - 1.; } } /* shape in file space (core cells start at 1) */ for (n = 0; n < 2; ++n) { s_rmin[n] = 0; s_rmax[n] = zoneSize[1][n] + 1; } s_rmin[2] = kIdxBeg + 1; /* but no rind cells in k-direction */ s_rmax[2] = kIdxBeg + numLocalkIdx; /* shape in memory (array starts at 1)*/ for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[1][n] + 2; m_rmin[n] = 1; m_rmax[n] = zoneSize[1][n] + 2; } m_dimvals[2] = numLocalkIdx; m_rmin[2] = 1; m_rmax[2] = numLocalkIdx; } /* if there is nothing for this process to write, a valid zone index must be provided and data array = NULL */ if (cgp_field_general_write_data(index_file, index_base, index_zone, index_flow, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, r)) cgp_error_exit(); if (cgp_field_general_write_data(index_file, index_base, index_zone, index_flow, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, p)) cgp_error_exit(); if (numLocalkIdx > 0) { free(r); } /* close CGNS file */ cg_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nSuccessfully added flow solution data to file " "grid_piz_c.cgns\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t " "node,"); printf("\n it has been overwritten\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/write_flowcentrind_str_paroverzone.c000066400000000000000000000205631343724673500311770ustar00rootroot00000000000000/* Program write_flowcentrind_str_paroverzone */ /* Opens an existing CGNS file that contains a simple two-zone 3-D structured grid, and adds a flow solution (at CELL CENTERS PLUS RIND CELLS IN I AND J DIRECTIONS) to it. The CGNS grid file 'grid_poz_c.cgns' must already exist (created using write_grid_str_paroverzone.c) Example compilation for this program is (change paths!): mpicxx write_flowcentrind_str_paroverzone.c -lcgns -lhdf5 -lsz -lz -o write_flowcentrind_str_paroverzone mpirun -np 2 write_flowcentrind_str_paroverzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { int i, j, k, n, comm_size, comm_rank; int index_file, index_base, index_zone, index_flow, index_field; char solname[33], zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for modify */ if (cgp_open("grid_poz_c.cgns", CG_MODE_MODIFY, &index_file)) cg_error_exit(); /* we know there is only one base (real working code would check!) */ index_base = 1; /* set the number of zones (should be 2, real working code would check!) */ int numZone = 2; /* CREATION OF FILE STRUCTURE -- all processors write the same information. Only meta-data is written to the library at this stage */ int idxZone; for (idxZone = 0; idxZone != numZone; ++idxZone) { index_zone = idxZone + 1; /* define flow solution node name (user can give any name) */ strcpy(solname, "FlowSolution"); /* create flow solution node (NOTE USE OF CGNS_ENUMV(CellCenter) HERE) */ cg_sol_write(index_file, index_base, index_zone, solname, CGNS_ENUMV(CellCenter), &index_flow); /* go to position within tree at FlowSolution_t node */ cg_goto(index_file, index_base, "Zone_t", index_zone, "FlowSolution_t", index_flow, "end"); /* write rind information under FlowSolution_t node (ilo,ihi,jlo,jhi,klo,khi) */ int irinddata[6] = { 1, 1, 1, 1, 0, 0 }; cg_rind_write(irinddata); if (cgp_field_write(index_file, index_base, index_zone, index_flow, CGNS_ENUMV(RealDouble), "Density", &index_field)) cgp_error_exit(); if (cgp_field_write(index_file, index_base, index_zone, index_flow, CGNS_ENUMV(RealDouble), "Pressure", &index_field)) cgp_error_exit(); } /* COLLECTIVE WRITING OF FILE DATA -- each processor writes to a separate zone */ /* partition the zones among the processes */ int maxLocalZone; /* the maximum number of zones on any process */ int idxGlobalZoneBeg; /* the global index of the first zone on this process */ int numLocalZone = numZone/comm_size; /* the number of zones local to this process */ { int numUnevenZone = numZone - numLocalZone*comm_size; maxLocalZone = numLocalZone + (numUnevenZone > 0); if (comm_rank < numUnevenZone) { ++numLocalZone; idxGlobalZoneBeg = comm_rank*numLocalZone; } else { idxGlobalZoneBeg = numUnevenZone*(numLocalZone + 1); idxGlobalZoneBeg += (comm_rank - numUnevenZone)*numLocalZone; } } int idxLocalZone; for (idxLocalZone = 0; idxLocalZone < maxLocalZone; ++idxLocalZone) { const int idxGlobalZone = idxGlobalZoneBeg + idxLocalZone; cgsize_t zoneSize[3][3]; int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *r = NULL; double *p = NULL; int ni, nj, nk; /* if there is nothing for this process to read, a valid zone index must be provided and data array = NULL */ index_zone = (idxGlobalZone < numZone) ? idxGlobalZone + 1 : 1; if (idxGlobalZone < numZone) { /* get zone size (and name - although not needed here) */ if (cg_zone_read(index_file, index_base, index_zone, zonename, (cgsize_t*)zoneSize)) cg_error_exit(); /* create fake flow solution AT CELL CENTERS for simple example. In memory, there are two rind cells in each direction: */ ni = zoneSize[1][0] + 2; nj = zoneSize[1][1] + 2; nk = zoneSize[1][2] + 2; const int num_vertex = ni*nj*nk; const int iOffset = idxGlobalZone*20; r = (double*)malloc(2*num_vertex*sizeof(double)); p = r + num_vertex; for (k = 1; k < nk-1; ++k) { for (j = 1; j < nj-1; ++j) { for (i = 1; i < ni-1; ++i) { int idx = (k*nj + j)*ni + i; r[idx] = (float)(i - 1 + iOffset); p[idx] = (float)(j - 1); } } } /* create rind cell data: */ for (j = 0; j < nj; ++j) /* k planes */ { for (i = 0; i < ni; ++i) { int idx = (0*nj + j)*ni + i; r[idx] = 777.; p[idx] = 777.; idx = ((nk-1)*nj + j)*ni + i; r[idx] = 777.; p[idx] = 777.; } } for (k = 1; k < nk-1; ++k) /* i planes */ { for (j = 0; j < nj; ++j) { int idx = (k*nj + j)*ni + 0; r[idx] = 999. + (float)j + (5.*(float)k); p[idx] = 999. + (float)j + (5.*(float)k) + 1.; idx = (k*nj + j)*ni + (ni-1); r[idx] = -999. - (float)j - (5.*(float)k); p[idx] = -999. - (float)j - (5.*(float)k) - 1.; } } for (k = 1; k < nk-1; ++k) /* j planes */ { for (i = 0; i < ni; ++i) { int idx = (k*nj + 0)*ni + i; r[idx] = 888. + (float)i + (5.*(float)k); p[idx] = 888. + (float)i + (5.*(float)k) + 1.; idx = (k*nj + (nj-1))*ni + i; r[idx] = -888. - (float)i - (5.*(float)k); p[idx] = -888. - (float)i - (5.*(float)k) - 1.; } } /* shape in file space (core cells start at 1) */ for (n = 0; n < 2; ++n) { s_rmin[n] = 0; s_rmax[n] = zoneSize[1][n] + 1; } s_rmin[2] = 1; /* but no rind cells in k-direction */ s_rmax[2] = zoneSize[1][n]; /* shape in memory (array starts at 1)*/ for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[1][n] + 2; m_rmin[n] = 1; m_rmax[n] = zoneSize[1][n] + 2; } m_dimvals[2] = zoneSize[1][n] + 2; m_rmin[2] = 2; /* but no rind cells in k-direction */ m_rmax[2] = zoneSize[1][n] + 1; } /* if there is nothing for this process to write, a valid zone index must be provided and data array = NULL */ if (cgp_field_general_write_data(index_file, index_base, index_zone, index_flow, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, r)) cgp_error_exit(); if (cgp_field_general_write_data(index_file, index_base, index_zone, index_flow, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, p)) cgp_error_exit(); if (idxGlobalZone < numZone) { free(r); } } /* close CGNS file */ cg_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nSuccessfully added flow solution data to file " "grid_poz_c.cgns\n"); printf("\nNote: if the original CGNS file already had a FlowSolution_t " "node,"); printf("\n it has been overwritten\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/write_grid_str_parinzone.c000066400000000000000000000132121343724673500270520ustar00rootroot00000000000000/* Program write_grid_str_parinzone.c */ /* Creates simple 3-D structured grid and writes it to a CGNS file. Each processor writes a slab of data to one zone (parallelism within a zone) mpicxx write_grid_str_parinzone.c -lcgns -lhdf5 -lsz -lz -o write_grid_str_parinzone mpirun -np 2 write_grid_str_parinzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { /* dimension statements for the zone are given here */ const cgsize_t zoneSize[3][3] = /* vertices cells boundary vertex */ { {21, 19, 9}, {20, 18, 8}, {0, 0, 0} }; int i, j, k, n, comm_size, comm_rank; int index_file, index_base; int index_zone, index_grid, index_coordx, index_coordy, index_coordz; char basename[33], zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for write */ if (cgp_open("grid_piz_c.cgns", CG_MODE_WRITE, &index_file)) cg_error_exit(); /* create base (user can give any name) */ strcpy(basename, "Base"); int icelldim = 3; int iphysdim = 3; cg_base_write(index_file, basename, icelldim, iphysdim, &index_base); /* CREATION OF FILE STRUCTURE -- all processors write the same information. Only zone meta-data is written to the library at this stage */ /* define zone name (user can give any name) */ sprintf(zonename, "Zone %d", 1); /* create zone */ if (cg_zone_write(index_file, index_base, zonename, (cgsize_t*)zoneSize, Structured, &index_zone)) cg_error_exit(); if (cg_grid_write(index_file, index_base, index_zone, "GridCoordinates", &index_grid)) cg_error_exit(); /* construct the grid coordinates nodes (user must use SIDS-standard names here) */ if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateX", &index_coordx)) cgp_error_exit(); if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateY", &index_coordy)) cgp_error_exit(); if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateZ", &index_coordz)) cgp_error_exit(); /* COLLECTIVE WRITING OF FILE DATA -- each processor writes a part of the zone */ /* partition the k-index of the zone among the processes */ int kIdxBeg; /* beginning k-index for this processor */ int numLocalkIdx = zoneSize[0][2]/comm_size; /* the number of k-indices local to this process */ { int numUnevenkIdx = zoneSize[0][2] - numLocalkIdx*comm_size; if (comm_rank < numUnevenkIdx) { ++numLocalkIdx; kIdxBeg = comm_rank*numLocalkIdx; } else { kIdxBeg = numUnevenkIdx*(numLocalkIdx + 1); kIdxBeg += (comm_rank - numUnevenkIdx)*numLocalkIdx; } } cgsize_t s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *x = NULL; double *y = NULL; double *z = NULL; if (numLocalkIdx > 0) { /* create gridpoints for simple example: */ const int ni = zoneSize[0][0]; const int nj = zoneSize[0][1]; const int nk = numLocalkIdx; const int num_vertex = ni*nj*nk; x = (double*)malloc(3*num_vertex*sizeof(double)); y = x + num_vertex; z = y + num_vertex; for (k = kIdxBeg; k < kIdxBeg + numLocalkIdx; ++k) { for (j = 0; j < nj; ++j) { for (i = 0; i < ni; ++i) { int idx = ((k - kIdxBeg)*nj + j)*ni + i; x[idx] = i; y[idx] = j; z[idx] = k; } } } // shape in file space for (n = 0; n < 2; ++n) { s_rmin[n] = 1; s_rmax[n] = zoneSize[0][n]; } s_rmin[2] = kIdxBeg + 1; s_rmax[2] = kIdxBeg + numLocalkIdx; // shape in memory for (n = 0; n < 2; ++n) { m_dimvals[n] = zoneSize[0][n]; m_rmin[n] = 1; m_rmax[n] = zoneSize[0][n]; } m_dimvals[2] = numLocalkIdx; m_rmin[2] = 1; m_rmax[2] = numLocalkIdx; } /* if there is nothing for this process to write, a valid zone index must be provided and data array = NULL */ /* the data is defined as double but will be written as single */ if (cgp_coord_general_write_data(index_file, index_base, index_zone, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, x)) cgp_error_exit(); if (cgp_coord_general_write_data(index_file, index_base, index_zone, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, y)) cgp_error_exit(); if (cgp_coord_general_write_data(index_file, index_base, index_zone, 3, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, z)) cgp_error_exit(); if (numLocalkIdx > 0) { free(x); } /* close CGNS file */ cgp_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nSuccessfully wrote grid to file grid_piz_c.cgns\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/C_code_parallel/write_grid_str_paroverzone.c000066400000000000000000000151361343724673500274260ustar00rootroot00000000000000/* Program write_grid_str_paroverzone.c */ /* Creates simple 3-D structured grid and writes it to a CGNS file. Each processor writes data to one zone (parallelism over zones) mpicxx write_grid_str_paroverzone.c -lcgns -lhdf5 -lsz -lz -o write_grid_str_paroverzone mpirun -np 2 write_grid_str_paroverzone */ #include #include #include #include "pcgnslib.h" #include "mpi.h" int main(int argc, const char* argv[]) { /* dimension statements for the zones are given here */ const int numZone = 2; const cgsize_t zoneSize[2][3][3] = { /* zone 1 */ /* vertices cells boundary vertex */ { {21, 19, 9}, {20, 18, 8}, {0, 0, 0} }, /* zone 2 */ /* vertices cells boundary vertex */ { {17, 19, 9}, {16, 18, 8}, {0, 0, 0} } }; int i, j, k, n, comm_size, comm_rank; int index_file, index_base; int index_zone, index_grid, index_coordx, index_coordy, index_coordz; char basename[33], zonename[33]; MPI_Init(&argc, (char***)(&argv)); MPI_Comm_size(MPI_COMM_WORLD, &comm_size); MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); cgp_mpi_comm(MPI_COMM_WORLD); /* open CGNS file for writing */ if (cgp_open("grid_poz_c.cgns", CG_MODE_WRITE, &index_file)) cg_error_exit(); /* create base (user can give any name) */ strcpy(basename, "Base"); int icelldim = 3; int iphysdim = 3; cg_base_write(index_file, basename, icelldim, iphysdim, &index_base); /* CREATION OF FILE STRUCTURE -- all processors write the same information. Only zone meta-data is written to the library at this stage */ int idxZone; for (idxZone = 0; idxZone != numZone; ++idxZone) { /* define zone name (user can give any name) */ sprintf(zonename, "Zone %d", idxZone + 1); /* create zone */ if (cg_zone_write(index_file, index_base, zonename, (cgsize_t*)zoneSize[idxZone], Structured, &index_zone)) cg_error_exit(); if (cg_grid_write(index_file, index_base, index_zone, "GridCoordinates", &index_grid)) cg_error_exit(); /* construct the grid coordinates nodes (user must use SIDS-standard names here) */ if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateX", &index_coordx)) cgp_error_exit(); if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateY", &index_coordy)) cgp_error_exit(); if (cgp_coord_write(index_file, index_base, index_zone, CGNS_ENUMV(RealSingle), "CoordinateZ", &index_coordz)) cgp_error_exit(); } /* COLLECTIVE WRITING OF FILE DATA -- each processor writes to a separate zone */ /* partition the zones among the processes */ int maxLocalZone; /* the maximum number of zones on any process */ int idxGlobalZoneBeg; /* the global index of the first zone on this process */ int numLocalZone = numZone/comm_size; /* the number of zones local to this process */ { int numUnevenZone = numZone - numLocalZone*comm_size; maxLocalZone = numLocalZone + (numUnevenZone > 0); if (comm_rank < numUnevenZone) { ++numLocalZone; idxGlobalZoneBeg = comm_rank*numLocalZone; } else { idxGlobalZoneBeg = numUnevenZone*(numLocalZone + 1); idxGlobalZoneBeg += (comm_rank - numUnevenZone)*numLocalZone; } } int idxLocalZone; for (idxLocalZone = 0; idxLocalZone < maxLocalZone; ++idxLocalZone) { const int idxGlobalZone = idxGlobalZoneBeg + idxLocalZone; int s_rmin[3], s_rmax[3], m_dimvals[3], m_rmin[3], m_rmax[3]; double *x = NULL; double *y = NULL; double *z = NULL; if (idxGlobalZone < numZone) { /* create gridpoints for simple example: */ const int ni = zoneSize[idxGlobalZone][0][0]; const int nj = zoneSize[idxGlobalZone][0][1]; const int nk = zoneSize[idxGlobalZone][0][2]; const int num_vertex = ni*nj*nk; const double xOffset = idxGlobalZone*zoneSize[0][1][0]; x = (double*)malloc(3*num_vertex*sizeof(double)); y = x + num_vertex; z = y + num_vertex; for (k = 0; k < nk; ++k) { for (j = 0; j < nj; ++j) { for (i = 0; i < ni; ++i) { int idx = (k*nj + j)*ni + i; x[idx] = i + xOffset; y[idx] = j; z[idx] = k; } } } /* shape in file space */ for (n = 0; n < 3; ++n) { s_rmin[n] = 1; s_rmax[n] = zoneSize[idxGlobalZone][0][n]; } /* shape in memory */ for (n = 0; n < 3; ++n) { m_dimvals[n] = zoneSize[idxGlobalZone][0][n]; m_rmin[n] = 1; m_rmax[n] = zoneSize[idxGlobalZone][0][n]; } } /* if there is nothing for this process to write, a valid zone index must be provided and data array = NULL */ index_zone = (idxGlobalZone < numZone) ? idxGlobalZone + 1 : 1; /* the data is defined as double but will be written as single */ if (cgp_coord_general_write_data(index_file, index_base, index_zone, 1, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, x)) cgp_error_exit(); if (cgp_coord_general_write_data(index_file, index_base, index_zone, 2, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, y)) cgp_error_exit(); if (cgp_coord_general_write_data(index_file, index_base, index_zone, 3, s_rmin, s_rmax, CGNS_ENUMV(RealDouble), 3, m_dimvals, m_rmin, m_rmax, z)) cgp_error_exit(); if (idxGlobalZone < numZone) { free(x); } } /* close CGNS file */ cgp_close(index_file); MPI_Finalize(); if (comm_rank == 0) { printf("\nSuccessfully wrote grid to file grid_poz_c.cgns\n"); } return 0; } CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/000077500000000000000000000000001343724673500211505ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Makefile000066400000000000000000000012331343724673500226070ustar00rootroot00000000000000 DIRS = \ Test_Grid_Str \ Test_Grid_Unstr \ Test_Grid_Str_Timeacc \ Test_Grid_Str_FlowCent \ Test_Grid_Str_FlowCentRind \ Test_Grid_Str_2zn \ Test_Grid_Str_2zngenrl #---------- all : @status=0;for d in $(DIRS) ; do \ cd $$d && $(MAKE); \ status=`expr $$status + $$?`; \ cd ..; \ done;\ if [ $$status -ne 0 ]; then \ exit $$status; \ fi test : $(TESTS) @status=0;for d in $(DIRS) ; do \ cd $$d && $(MAKE); \ status=`expr $$status + $$?`; \ cd ..; \ done;\ if [ $$status -ne 0 ]; then \ exit $$status; \ fi;\ ./test.sh; \ exit $$?; clean : $(CLEAN) -@for d in $(DIRS) ; do \ cd $$d && $(MAKE) clean; \ cd ..; \ done; CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/README000066400000000000000000000021271343724673500220320ustar00rootroot00000000000000This contains a set of Fortran90 test cases from UserGuideCode. (modified for use with V3.3) If CGNS is compiled with --enable-64bit, then the created "grid.cgns" file will use 64-bit integers as appropriate Currently, the testing (make test) only compares output files of some of the variables written to and read from the grid.cgns file. It does not check whether the 64-bit integers were necessarily written as I8 or not. To check this, one could use "cgnsview" to look at the grid.cgns file(s) directly. For example, with 64-bit integers, in the cgns file under Test_Grid_Str, the PointList data type under the BC_t nodes (under ZoneBC_t) should be I8 rather than I4. ***** NOTE ***** You will first have to edit the Makefile include to set up your CGNS location and compiler and options Edit 'make.defs' for Linux/Unix Not checked for Windows yet. To just build the code, use make on linux/Unix To build and run the tests, use make test Note: executables, output files, and the resulting CGNS file are put in each Subdirectory/build/ directory To clean everything up, use make clean CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/000077500000000000000000000000001343724673500236645ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/Makefile000066400000000000000000000053461343724673500253340ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowvert_str$(EXE) WRITE3 = write_nondimensional$(EXE) WRITE4 = write_descriptor$(EXE) WRITE5 = write_convergence$(EXE) WRITE6 = write_floweqn_str$(EXE) WRITE7 = write_bcpnts_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowvert_str$(EXE) READ3 = read_nondimensional$(EXE) READ4 = read_descriptor$(EXE) READ5 = read_convergence$(EXE) READ6 = read_floweqn_str$(EXE) READ7 = read_bcpnts_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) $(WRITE4) $(WRITE5) $(WRITE6) $(WRITE7) READ_PROGS = $(READ1) $(READ2) $(READ3) $(READ4) $(READ5) $(READ6) $(READ7) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(WRITE4) $(READ4) > $(OUTDIR)/output4 -$(DIFF) OUTPUT4 $(OUTDIR)/output4 $(WRITE4) $(READ4) > $(OUTDIR)/output5 -$(DIFF) OUTPUT5 $(OUTDIR)/output5 $(WRITE6) $(READ6) > $(OUTDIR)/output6 -$(DIFF) OUTPUT6 $(OUTDIR)/output6 $(WRITE7) $(READ7) > $(OUTDIR)/output7 -$(DIFF) OUTPUT7 $(OUTDIR)/output7 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid_str.F90 $(LIBS) $(WRITE2) : ../write_flowvert_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_flowvert_str.F90 $(LIBS) $(WRITE3) : ../write_nondimensional.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_nondimensional.F90 $(LIBS) $(WRITE4) : ../write_descriptor.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_descriptor.F90 $(LIBS) $(WRITE5) : ../write_convergence.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_convergence.F90 $(LIBS) $(WRITE6) : ../write_floweqn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_floweqn_str.F90 $(LIBS) $(WRITE7) : ../write_bcpnts_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_bcpnts_str.F90 $(LIBS) $(READ1) : ../read_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid_str.F90 $(LIBS) $(READ2) : ../read_flowvert_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_flowvert_str.F90 $(LIBS) $(READ3) : ../read_nondimensional.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_nondimensional.F90 $(LIBS) $(READ4) : ../read_descriptor.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_descriptor.F90 $(LIBS) $(READ5) : ../read_convergence.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_convergence.F90 $(LIBS) $(READ6) : ../read_floweqn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_floweqn_str.F90 $(LIBS) $(READ7) : ../read_bcpnts_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_bcpnts_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT1000066400000000000000000000002221343724673500247240ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, x,y,z(21,17,9)= 20.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT2000066400000000000000000000002151343724673500247270ustar00rootroot00000000000000 Successfully read flow solution from file grid.cgns For example, r,p(21,17,9)= 20.00000 16.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT3000066400000000000000000000023241343724673500247330ustar00rootroot00000000000000 DataClass = NormalizedByUnknownDimensional ReferenceState = ReferenceQuantities Variable=Mach data= 4.60000000 Variable=Reynolds data= 6000000.00000000 Variable=Mach_Velocity data= 4.60000000 Variable=Mach_VelocitySound data= 1.00000000 Variable=Reynolds_Velocity data= 4.60000000 Variable=Reynolds_Length data= 1.00000000 Variable=Reynolds_ViscosityKinematic data= 0.00000077 Variable=Density data= 1.00000000 Variable=Pressure data= 0.71428571 Variable=VelocitySound data= 1.00000000 Variable=ViscosityMolecular data= 0.00000077 Variable=LengthReference data= 1.00000000 Variable=VelocityX data= 4.60000000 Variable=VelocityY data= 0.00000000 Variable=VelocityZ data= 0.00000000 Successfully read nondimensional info from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT4000066400000000000000000000002201343724673500247250ustar00rootroot00000000000000 The descriptor is: Supersonic vehicle with landing gear M=4.6, Re=6 million Successfully read descriptors from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT5000066400000000000000000000003141343724673500247320ustar00rootroot00000000000000 Successfully read cl history from file grid.cgns values are: 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000 10.00000 CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT6000066400000000000000000000006201343724673500247330ustar00rootroot00000000000000 Eqn dimension = 3 Gov eqn = NSTurbulent diffusion= 0 1 0 0 0 0 Gas model type = Ideal gamma= 1.40000 Turbulence closure type = EddyViscosity turb prandtl number = 0.90000 Turbulence model type = OneEquation_SpalartAllmaras Successfully read equation set info from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str/OUTPUT7000066400000000000000000000071241343724673500247420ustar00rootroot00000000000000 BC number: 1 name=Ilo type=BCTunnelInflow no of pts= 153 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 1 1 1 ipnts(1, 2), (2, 2), (3, 2)= 1 1 2 ipnts(1, 3), (2, 3), (3, 3)= 1 1 3 ipnts(1, 4), (2, 4), (3, 4)= 1 1 4 ipnts(1, 5), (2, 5), (3, 5)= 1 1 5 ipnts(1, 6), (2, 6), (3, 6)= 1 1 6 ipnts(1, 7), (2, 7), (3, 7)= 1 1 7 ipnts(1, 8), (2, 8), (3, 8)= 1 1 8 ipnts(1, 9), (2, 9), (3, 9)= 1 1 9 ipnts(1,10), (2,10), (3,10)= 1 2 1 BC number: 2 name=Ihi type=BCExtrapolate no of pts= 153 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 21 1 1 ipnts(1, 2), (2, 2), (3, 2)= 21 1 2 ipnts(1, 3), (2, 3), (3, 3)= 21 1 3 ipnts(1, 4), (2, 4), (3, 4)= 21 1 4 ipnts(1, 5), (2, 5), (3, 5)= 21 1 5 ipnts(1, 6), (2, 6), (3, 6)= 21 1 6 ipnts(1, 7), (2, 7), (3, 7)= 21 1 7 ipnts(1, 8), (2, 8), (3, 8)= 21 1 8 ipnts(1, 9), (2, 9), (3, 9)= 21 1 9 ipnts(1,10), (2,10), (3,10)= 21 2 1 BC number: 3 name=Jlo type=BCWallInviscid no of pts= 189 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 1 1 1 ipnts(1, 2), (2, 2), (3, 2)= 1 1 2 ipnts(1, 3), (2, 3), (3, 3)= 1 1 3 ipnts(1, 4), (2, 4), (3, 4)= 1 1 4 ipnts(1, 5), (2, 5), (3, 5)= 1 1 5 ipnts(1, 6), (2, 6), (3, 6)= 1 1 6 ipnts(1, 7), (2, 7), (3, 7)= 1 1 7 ipnts(1, 8), (2, 8), (3, 8)= 1 1 8 ipnts(1, 9), (2, 9), (3, 9)= 1 1 9 ipnts(1,10), (2,10), (3,10)= 2 1 1 BC number: 4 name=Jhi type=BCWallInviscid no of pts= 189 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 1 17 1 ipnts(1, 2), (2, 2), (3, 2)= 1 17 2 ipnts(1, 3), (2, 3), (3, 3)= 1 17 3 ipnts(1, 4), (2, 4), (3, 4)= 1 17 4 ipnts(1, 5), (2, 5), (3, 5)= 1 17 5 ipnts(1, 6), (2, 6), (3, 6)= 1 17 6 ipnts(1, 7), (2, 7), (3, 7)= 1 17 7 ipnts(1, 8), (2, 8), (3, 8)= 1 17 8 ipnts(1, 9), (2, 9), (3, 9)= 1 17 9 ipnts(1,10), (2,10), (3,10)= 2 17 1 BC number: 5 name=Klo type=BCWallInviscid no of pts= 357 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 1 1 1 ipnts(1, 2), (2, 2), (3, 2)= 1 2 1 ipnts(1, 3), (2, 3), (3, 3)= 1 3 1 ipnts(1, 4), (2, 4), (3, 4)= 1 4 1 ipnts(1, 5), (2, 5), (3, 5)= 1 5 1 ipnts(1, 6), (2, 6), (3, 6)= 1 6 1 ipnts(1, 7), (2, 7), (3, 7)= 1 7 1 ipnts(1, 8), (2, 8), (3, 8)= 1 8 1 ipnts(1, 9), (2, 9), (3, 9)= 1 9 1 ipnts(1,10), (2,10), (3,10)= 1 10 1 BC number: 6 name=Khi type=BCWallInviscid no of pts= 357 (these points read here, but only some printed out:) ipnts(1, 1), (2, 1), (3, 1)= 1 1 9 ipnts(1, 2), (2, 2), (3, 2)= 1 2 9 ipnts(1, 3), (2, 3), (3, 3)= 1 3 9 ipnts(1, 4), (2, 4), (3, 4)= 1 4 9 ipnts(1, 5), (2, 5), (3, 5)= 1 5 9 ipnts(1, 6), (2, 6), (3, 6)= 1 6 9 ipnts(1, 7), (2, 7), (3, 7)= 1 7 9 ipnts(1, 8), (2, 8), (3, 8)= 1 8 9 ipnts(1, 9), (2, 9), (3, 9)= 1 9 9 ipnts(1,10), (2,10), (3,10)= 1 10 9 Successfully read BCs (PointList format) from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zn/000077500000000000000000000000001343724673500244555ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zn/Makefile000066400000000000000000000017511343724673500261210ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid2zn_str$(EXE) WRITE2 = write_con2zn_str$(EXE) READ1 = read_grid2zn_str$(EXE) READ2 = read_con2zn_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid2zn_str.F90 $(LIBS) $(WRITE2) : ../write_con2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_con2zn_str.F90 $(LIBS) $(READ1) : ../read_grid2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid2zn_str.F90 $(LIBS) $(READ2) : ../read_con2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_con2zn_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zn/OUTPUT1000066400000000000000000000003441343724673500255220ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, zone 1 x,y,z(21,17,9)= 20.00000 16.00000 8.00000 zone 2 x,y,z(21,17,9)= 40.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zn/OUTPUT2000066400000000000000000000007241343724673500255250ustar00rootroot00000000000000 In zone 1: donor name=Zone 2 range (this zone)= 21 1 1 21 17 9 range (donor zone)= 1 1 1 1 17 9 transform= 1 2 3 In zone 2: donor name=Zone 1 range (this zone)= 1 1 1 1 17 9 range (donor zone)= 21 1 1 21 17 9 transform= 1 2 3 Successfully read 1-to-1 connectivity info from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zngenrl/000077500000000000000000000000001343724673500255055ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zngenrl/Makefile000066400000000000000000000020151343724673500271430ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid2zn_str$(EXE) WRITE2 = write_con2zn_genrl_str$(EXE) READ1 = read_grid2zn_str$(EXE) READ2 = read_con2zn_genrl_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid2zn_str.F90 $(LIBS) $(WRITE2) : ../write_con2zn_genrl_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_con2zn_genrl_str.F90 $(LIBS) $(READ1) : ../read_grid2zn_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid2zn_str.F90 $(LIBS) $(READ2) : ../read_con2zn_genrl_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_con2zn_genrl_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zngenrl/OUTPUT1000066400000000000000000000003441343724673500265520ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, zone 1 x,y,z(21,17,9)= 20.00000 16.00000 8.00000 zone 2 x,y,z(21,17,9)= 40.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_2zngenrl/OUTPUT2000066400000000000000000000052641343724673500265610ustar00rootroot00000000000000 In zone 1: donor name=Zone 2 number of connectivity pts= 153 grid location=Vertex connectivity type=Abutting1to1 pointset type=PointList donor zonetype=Structured donor pointset type=PointListDonor ipnts and ipntsdonor arrays read, only some written out here: ipnts(1, 1), (2, 1), (3, 1)= 21 1 1 ipntsdonor(1, 1), (2, 1), (3, 1)= 1 1 1 ipnts(1, 2), (2, 2), (3, 2)= 21 1 2 ipntsdonor(1, 2), (2, 2), (3, 2)= 1 1 2 ipnts(1, 3), (2, 3), (3, 3)= 21 1 3 ipntsdonor(1, 3), (2, 3), (3, 3)= 1 1 3 ipnts(1, 4), (2, 4), (3, 4)= 21 1 4 ipntsdonor(1, 4), (2, 4), (3, 4)= 1 1 4 ipnts(1, 5), (2, 5), (3, 5)= 21 1 5 ipntsdonor(1, 5), (2, 5), (3, 5)= 1 1 5 ipnts(1, 6), (2, 6), (3, 6)= 21 1 6 ipntsdonor(1, 6), (2, 6), (3, 6)= 1 1 6 ipnts(1, 7), (2, 7), (3, 7)= 21 1 7 ipntsdonor(1, 7), (2, 7), (3, 7)= 1 1 7 ipnts(1, 8), (2, 8), (3, 8)= 21 1 8 ipntsdonor(1, 8), (2, 8), (3, 8)= 1 1 8 ipnts(1, 9), (2, 9), (3, 9)= 21 1 9 ipntsdonor(1, 9), (2, 9), (3, 9)= 1 1 9 ipnts(1,10), (2,10), (3,10)= 21 2 1 ipntsdonor(1,10), (2,10), (3,10)= 1 2 1 In zone 2: donor name=Zone 1 number of connectivity pts= 153 grid location=Vertex connectivity type=Abutting1to1 pointset type=PointList donor zonetype=Structured donor pointset type=PointListDonor ipnts and ipntsdonor arrays read, only some written out here: ipnts(1, 1), (2, 1), (3, 1)= 1 1 1 ipntsdonor(1, 1), (2, 1), (3, 1)= 21 1 1 ipnts(1, 2), (2, 2), (3, 2)= 1 1 2 ipntsdonor(1, 2), (2, 2), (3, 2)= 21 1 2 ipnts(1, 3), (2, 3), (3, 3)= 1 1 3 ipntsdonor(1, 3), (2, 3), (3, 3)= 21 1 3 ipnts(1, 4), (2, 4), (3, 4)= 1 1 4 ipntsdonor(1, 4), (2, 4), (3, 4)= 21 1 4 ipnts(1, 5), (2, 5), (3, 5)= 1 1 5 ipntsdonor(1, 5), (2, 5), (3, 5)= 21 1 5 ipnts(1, 6), (2, 6), (3, 6)= 1 1 6 ipntsdonor(1, 6), (2, 6), (3, 6)= 21 1 6 ipnts(1, 7), (2, 7), (3, 7)= 1 1 7 ipntsdonor(1, 7), (2, 7), (3, 7)= 21 1 7 ipnts(1, 8), (2, 8), (3, 8)= 1 1 8 ipntsdonor(1, 8), (2, 8), (3, 8)= 21 1 8 ipnts(1, 9), (2, 9), (3, 9)= 1 1 9 ipntsdonor(1, 9), (2, 9), (3, 9)= 21 1 9 ipnts(1,10), (2,10), (3,10)= 1 2 1 ipntsdonor(1,10), (2,10), (3,10)= 21 2 1 Successfully read general 1-to-1 connectivity info from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCent/000077500000000000000000000000001343724673500254655ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCent/Makefile000066400000000000000000000024521343724673500271300ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowcent_str$(EXE) WRITE3 = write_bc_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowcent_str$(EXE) READ3 = read_bc_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) READ_PROGS = $(READ1) $(READ2) $(READ3) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid_str.F90 $(LIBS) $(WRITE2) : ../write_flowcent_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_flowcent_str.F90 $(LIBS) $(WRITE3) : ../write_bc_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_bc_str.F90 $(LIBS) $(READ1) : ../read_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid_str.F90 $(LIBS) $(READ2) : ../read_flowcent_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_flowcent_str.F90 $(LIBS) $(READ3) : ../read_bc_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_bc_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCent/OUTPUT1000066400000000000000000000002221343724673500265250ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, x,y,z(21,17,9)= 20.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCent/OUTPUT2000066400000000000000000000002151343724673500265300ustar00rootroot00000000000000 Successfully read flow solution from file grid.cgns For example, r,p(20,16,8)= 19.00000 15.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCent/OUTPUT3000066400000000000000000000021011343724673500265250ustar00rootroot00000000000000 BC number: 1 name=Ilo type=BCTunnelInflow i-range= 1 1 j-range= 1 17 k-range= 1 9 BC number: 2 name=Ihi type=BCExtrapolate i-range= 21 21 j-range= 1 17 k-range= 1 9 BC number: 3 name=Jlo type=BCWallInviscid i-range= 1 21 j-range= 1 1 k-range= 1 9 BC number: 4 name=Jhi type=BCWallInviscid i-range= 1 21 j-range= 17 17 k-range= 1 9 BC number: 5 name=Klo type=BCWallInviscid i-range= 1 21 j-range= 1 17 k-range= 1 1 BC number: 6 name=Khi type=BCWallInviscid i-range= 1 21 j-range= 1 17 k-range= 9 9 Successfully read BCs (PointRange format) from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCentRind/000077500000000000000000000000001343724673500263025ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCentRind/Makefile000066400000000000000000000017721343724673500277510ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_flowcentrind_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_flowcentrind_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid_str.F90 $(LIBS) $(WRITE2) : ../write_flowcentrind_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_flowcentrind_str.F90 $(LIBS) $(READ1) : ../read_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid_str.F90 $(LIBS) $(READ2) : ../read_flowcentrind_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_flowcentrind_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCentRind/OUTPUT1000066400000000000000000000002221343724673500273420ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, x,y,z(21,17,9)= 20.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_FlowCentRind/OUTPUT2000066400000000000000000000003701343724673500273470ustar00rootroot00000000000000 Successfully read flow solution from file grid.cgns For example, r,p(21,17,8)= 19.00000 15.00000 rind: r,p(1,17,8)= 1055.00000 1056.00000 rind: r,p(22,17,8)= -1055.00000 -1056.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_Timeacc/000077500000000000000000000000001343724673500253115ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_Timeacc/Makefile000066400000000000000000000017421343724673500267550ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_str$(EXE) WRITE2 = write_timevert_str$(EXE) READ1 = read_grid_str$(EXE) READ2 = read_timevert_str$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) READ_PROGS = $(READ1) $(READ2) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid_str.F90 $(LIBS) $(WRITE2) : ../write_timevert_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_timevert_str.F90 $(LIBS) $(READ1) : ../read_grid_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid_str.F90 $(LIBS) $(READ2) : ../read_timevert_str.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_timevert_str.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_Timeacc/OUTPUT1000066400000000000000000000002221343724673500263510ustar00rootroot00000000000000 Successfully read grid from file grid.cgns For example, x,y,z(21,17,9)= 20.00000 16.00000 8.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Str_Timeacc/OUTPUT2000066400000000000000000000013141343724673500263550ustar00rootroot00000000000000 number of time steps stored = 3 Times stored are: 10.000 20.000 50.000 Flow solution names corresponding to each are: FlowSolution1 FlowSolution2 FlowSolution3 Simulation type is: TimeAccurate Successfully read 3 flow solutions from file grid.cgns For example, r1,p1(1,1,1)= 0.00000 0.00000 r2,p2(1,1,1)= 1.00000 1.00000 r3,p3(1,1,1)= 2.00000 2.00000 For example, r1,p1(21,17,9)= 20.00000 16.00000 r2,p2(21,17,9)= 21.00000 17.00000 r3,p3(21,17,9)= 22.00000 18.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/000077500000000000000000000000001343724673500242275ustar00rootroot00000000000000CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/Makefile000066400000000000000000000046151343724673500256750ustar00rootroot00000000000000include ../make.defs WRITE1 = write_grid_unst$(EXE) WRITE2 = write_flowvert_unst$(EXE) WRITE3 = write_dimensional$(EXE) WRITE4 = write_descriptor$(EXE) WRITE5 = write_convergence$(EXE) WRITE6 = write_bcpnts_unst$(EXE) READ1 = read_grid_unst$(EXE) READ2 = read_flowvert_unst$(EXE) READ3 = read_dimensional$(EXE) READ4 = read_descriptor$(EXE) READ5 = read_convergence$(EXE) READ6 = read_bcpnts_unst$(EXE) WRITE_PROGS = $(WRITE1) $(WRITE2) $(WRITE3) $(WRITE4) $(WRITE5) $(WRITE6) READ_PROGS = $(READ1) $(READ2) $(READ3) $(READ4) $(READ5) $(READ6) all : write read write : $(OUTDIR) $(WRITE_PROGS) read : $(OUTDIR) $(READ_PROGS) test : write read -@$(RM) grid.cgns $(WRITE1) $(READ1) > $(OUTDIR)/output1 -$(DIFF) OUTPUT1 $(OUTDIR)/output1 $(WRITE2) $(READ2) > $(OUTDIR)/output2 -$(DIFF) OUTPUT2 $(OUTDIR)/output2 $(WRITE3) $(READ3) > $(OUTDIR)/output3 -$(DIFF) OUTPUT3 $(OUTDIR)/output3 $(WRITE4) $(READ4) > $(OUTDIR)/output4 -$(DIFF) OUTPUT4 $(OUTDIR)/output4 $(WRITE5) $(READ5) > $(OUTDIR)/output5 -$(DIFF) OUTPUT5 $(OUTDIR)/output5 $(WRITE6) $(READ6) > $(OUTDIR)/output6 -$(DIFF) OUTPUT6 $(OUTDIR)/output6 $(OUTDIR) : -@$(MKDIR) $(OUTDIR) $(WRITE1) : ../write_grid_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_grid_unst.F90 $(LIBS) $(WRITE2) : ../write_flowvert_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_flowvert_unst.F90 $(LIBS) $(WRITE3) : ../write_dimensional.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_dimensional.F90 $(LIBS) $(WRITE4) : ../write_descriptor.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_descriptor.F90 $(LIBS) $(WRITE5) : ../write_convergence.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_convergence.F90 $(LIBS) $(WRITE6) : ../write_bcpnts_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../write_bcpnts_unst.F90 $(LIBS) $(READ1) : ../read_grid_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_grid_unst.F90 $(LIBS) $(READ2) : ../read_flowvert_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_flowvert_unst.F90 $(LIBS) $(READ3) : ../read_dimensional.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_dimensional.F90 $(LIBS) $(READ4) : ../read_descriptor.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_descriptor.F90 $(LIBS) $(READ5) : ../read_convergence.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_convergence.F90 $(LIBS) $(READ6) : ../read_bcpnts_unst.F90 $(F77) $(FOPTS) $(FEOUT) $@ ../read_bcpnts_unst.F90 $(LIBS) clean : -$(RM) grid.cgns $(WRITE_PROGS) $(READ_PROGS) -$(RMDIR) $(OUTDIR) CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT1000066400000000000000000000021051343724673500252710ustar00rootroot00000000000000 number of sections= 4 Reading section data... section name=Elem section type=HEXA_8 istart,iend= 1 2560 reading element data for this element Reading section data... section name=InflowElem section type=QUAD_4 istart,iend= 2561 2688 not reading element data for this element Reading section data... section name=OutflowElem section type=QUAD_4 istart,iend= 2689 2816 not reading element data for this element Reading section data... section name=SidewallElem section type=QUAD_4 istart,iend= 2817 3776 not reading element data for this element Successfully read unstructured grid from file grid.cgns for example, element 1 is made up of nodes: 1 2 23 22 358 359 380 379 x,y,z of node 358 are: 0.00000 0.00000 1.00000 x,y,z of node 1358 are: 13.00000 13.00000 3.00000 CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT2000066400000000000000000000002751343724673500253000ustar00rootroot00000000000000 Successfully read flow solution from file grid.cgns For example, r,p(380) = 1.00000 1.00000 r,p(3213)= 20.00000 16.00000 Program successful... ending now CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT3000066400000000000000000000015651343724673500253040ustar00rootroot00000000000000 DataClass = Dimensional Units= Kilogram Meter Second Kelvin Degree For Density , exponents are: 1.0 -3.0 0.0 0.0 0.0 For Pressure , exponents are: 1.0 -1.0 -2.0 0.0 0.0 For CoordinateX , exponents are: 0.0 1.0 0.0 0.0 0.0 For CoordinateY , exponents are: 0.0 1.0 0.0 0.0 0.0 For CoordinateZ , exponents are: 0.0 1.0 0.0 0.0 0.0 Successfully read dimensional data from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT4000066400000000000000000000002201343724673500252700ustar00rootroot00000000000000 The descriptor is: Supersonic vehicle with landing gear M=4.6, Re=6 million Successfully read descriptors from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT5000066400000000000000000000003141343724673500252750ustar00rootroot00000000000000 Successfully read cl history from file grid.cgns values are: 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000 10.00000 CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/Test_Grid_Unstr/OUTPUT6000066400000000000000000000024411343724673500253010ustar00rootroot00000000000000 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 1 name=Ilo type=BCTunnelInflow no of elements= 128 (these elements read here, but only some printed out:) ipnts( 1)=2561 ipnts( 2)=2562 ipnts( 3)=2563 ipnts( 4)=2564 ipnts( 5)=2565 ipnts( 6)=2566 ipnts( 7)=2567 ipnts( 8)=2568 ipnts( 9)=2569 ipnts(10)=2570 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 2 name=Ihi type=BCExtrapolate no of elements= 128 (these elements read here, but only some printed out:) ipnts( 1)=2689 ipnts( 2)=2690 ipnts( 3)=2691 ipnts( 4)=2692 ipnts( 5)=2693 ipnts( 6)=2694 ipnts( 7)=2695 ipnts( 8)=2696 ipnts( 9)=2697 ipnts(10)=2698 GridLocation=FaceCenter means BC data refers to elements, not nodes BC number: 3 name=Walls type=BCWallInviscid no of elements= 960 (these elements read here, but only some printed out:) ipnts( 1)=2817 ipnts( 2)=2818 ipnts( 3)=2819 ipnts( 4)=2820 ipnts( 5)=2821 ipnts( 6)=2822 ipnts( 7)=2823 ipnts( 8)=2824 ipnts( 9)=2825 ipnts(10)=2826 Successfully read BCs (PointList format) from file grid.cgns CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/make.defs000066400000000000000000000010241343724673500227250ustar00rootroot00000000000000# location for the CGNS includes and required libraries CGNSDIR = ../../.. include $(CGNSDIR)/make.defs include $(CGNSDIR)/cgnsBuild.defs CGNSLIB = $(CGNSDIR)/$(LIBCGNS) CGNSinclude = ../../../ CGNSlibs = $(CGNSLIB) $(HDF5LIB) # Fortran compiler and options FOPTS = -I$(CGNSinclude) $(FFLAGS) LIBS = $(CGNSlibs) $(SZIPLIB) $(ZLIBLIB) $(HDF5LIB_DEP) -lm $(FLIBS) # how to name output executable and extension FEOUT = -o EXE = # working directory for output OUTDIR = build # additional commands MKDIR = mkdir DIFF = diff -w CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_bc_str.F90000066400000000000000000000056631343724673500237110ustar00rootroot00000000000000 program read_bc_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid + BCs (in PointRange format), and reads the BCs ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f), and the BCs must also ! already have been written (using write_bc_str.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_bc_str.F90 ! ifort -o read_bc_str read_bc_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer(cgsize_t) ipnts(3,2),npts,normallistflag integer normalindex(3) integer normallist,ndataset,normaldatatype,iptset,ibocotype,ib,nbocos integer index_zone,index_base,index_file,ier character boconame*32 ! ! READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! find out number of BCs that exist under this zone call cg_nbocos_f(index_file,index_base,index_zone,nbocos,ier) ! do loop over the total number of BCs do ib=1,nbocos ! get BC info call cg_boco_info_f(index_file,index_base,index_zone,ib, & boconame,ibocotype,iptset,npts,normalindex,normallistflag, & normaldatatype,ndataset,ier) if (iptset .ne. PointRange) then write(6,'('' Error. For this program, BCs must be set'', & '' up as PointRange type'',a32)') PointSetTypeName(iptset) stop end if write(6,'('' BC number: '',i5)') ib write(6,'('' name='',a32)') boconame write(6,'('' type='',a32)') BCTypeName(ibocotype) ! read point range in here call cg_boco_read_f(index_file,index_base,index_zone,ib, & ipnts,normallist,ier) write(6,'('' i-range='',2i5)') ipnts(1,1),ipnts(1,2) write(6,'('' j-range='',2i5)') ipnts(2,1),ipnts(2,2) write(6,'('' k-range='',2i5)') ipnts(3,1),ipnts(3,2) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read BCs (PointRange format)'', & '' from file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_bcpnts_str.F90000066400000000000000000000065101343724673500246060ustar00rootroot00000000000000 program read_bcpnts_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid + BCs (in PointList format), and reads the BCs ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f), and the BCs must also ! already have been written (using write_bcpnts_str.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_bcpnts_str.F90 ! ifort -o read_bcpnts_str read_bcpnts_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxpnts=400 integer(cgsize_t) ipnts(3,maxpnts),npts,normallistflag integer normalindex(3) integer i,normallist,ndataset,normaldatatype,iptset,ibocotype integer ib,nbocos integer index_zone,index_base,index_file,ier character boconame*32 ! ! READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! find out number of BCs that exist under this zone call cg_nbocos_f(index_file,index_base,index_zone,nbocos,ier) ! do loop over the total number of BCs do ib=1,nbocos ! get BC info call cg_boco_info_f(index_file,index_base,index_zone,ib, & boconame,ibocotype,iptset,npts,normalindex,normallistflag, & normaldatatype,ndataset,ier) if (iptset .ne. PointList) then write(6,'('' Error. For this program, BCs must be set'', & '' up as PointList type'',a32)') PointSetTypeName(iptset) stop end if write(6,'('' BC number: '',i5)') ib write(6,'('' name='',a32)') boconame write(6,'('' type='',a32)') BCTypeName(ibocotype) write(6,'('' no of pts='',i5)') npts if (npts .gt. maxpnts) then write(6,'('' Error. Must increase maxpnts to at least '',i5)') npts stop end if ! read point list in here (nothing done with them in this program) call cg_boco_read_f(index_file,index_base,index_zone,ib, & ipnts,normallist,ier) write(6,'('' (these points read here, but only some'', & '' printed out:)'')') do i=1,10 write(6,'('' ipnts(1,'',i2,''), (2,'',i2,''), (3,'',i2,'')='', & 3i4)') i,i,i,ipnts(1,i),ipnts(2,i),ipnts(3,i) enddo enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read BCs (PointList format)'', & '' from file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_bcpnts_unst.F90000066400000000000000000000073211343724673500247700ustar00rootroot00000000000000 program read_bcpnts_unst use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! unstructured grid + BCs (in PointList+GridLocation=FaceCenter ! format), and reads the BCs ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_unst.f), and the BCs must also ! already have been written (using write_bcpnts_unst.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_bcpnts_unst.F90 ! ifort -o read_bcpnts_unst read_bcpnts_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxpnts=960 integer(cgsize_t) ipnts(maxpnts),npts,normallistflag integer normalindex(3) integer i,normallist,ndataset,normaldatatype,iptset,ibocotype integer igr,ib,nbocos integer index_zone,index_base,index_file,ier character boconame*32 ! ! READ BOUNDARY CONDITIONS FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! find out number of BCs that exist under this zone call cg_nbocos_f(index_file,index_base,index_zone,nbocos,ier) ! do loop over the total number of BCs do ib=1,nbocos ! find out what BC grid location is (expecting FaceCenter) call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'ZoneBC_t',1,'BC_t',ib,'end') call cg_gridlocation_read_f(igr,ier) if (igr .eq. FaceCenter) then write(6,'('' GridLocation=FaceCenter means BC data refers'', & '' to elements, not nodes'')') end if ! get BC info call cg_boco_info_f(index_file,index_base,index_zone,ib, & boconame,ibocotype,iptset,npts,normalindex,normallistflag, & normaldatatype,ndataset,ier) if (iptset .ne. PointList) then write(6,'('' Error. For this program, BCs must be set'', & '' up as PointList type'',a32)') PointSetTypeName(iptset) stop end if write(6,'('' BC number: '',i5)') ib write(6,'('' name='',a32)') boconame write(6,'('' type='',a32)') BCTypeName(ibocotype) write(6,'('' no of elements='',i5)') npts if (npts .gt. maxpnts) then write(6,'('' Error. Must increase maxpnts to at least '', & i5)') npts stop end if ! read point list in here (nothing done with them in this program) call cg_boco_read_f(index_file,index_base,index_zone,ib, & ipnts,normallist,ier) write(6,'('' (these elements read here, but only some'', & '' printed out:)'')') do i=1,10 write(6,'('' ipnts('',i2,'')='',i4)') i,ipnts(i) enddo enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read BCs (PointList format)'', & '' from file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_con2zn_genrl_str.F90000066400000000000000000000106571343724673500257240ustar00rootroot00000000000000 program read_con2zn_genrl_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid (2 zones) plus 1-to-1 connectivity ! information (written in GENERAL form), and reads the ! connectivity info. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid2zn_str.f plus write_con2zn_genrl_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_con2zn_genrl_str.F90 ! ifort -o read_con2zn_genrl_str read_con2zn_genrl_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxpnts=400 integer(cgsize_t) npts,ndata_donor integer(cgsize_t) ipnts(3,maxpnts),ipntsdonor(3,maxpnts) integer i,idonor_datatype,idonor_ptset_type,idonor_zonetype,iptset_type integer iconnect_type,location,nconns,nzone integer index_conn,index_zone,index_base,index_file,ier character donorname*32,connectname*32 ! ! READ GENERAL CONNECTIVITY INFORMATION FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! get number of zones (should be 2 for our case) call cg_nzones_f(index_file,index_base,nzone,ier) if (nzone .ne. 2) then write(6,'('' Error. This program expects 2 zones. '',i5, & '' read'')') nzone stop end if ! loop over zones do index_zone=1,nzone ! find out how many general interfaces there are in this zone ! (for this program, there should only be one) call cg_nconns_f(index_file,index_base,index_zone,nconns,ier) if (nconns .ne. 1) then write(6,'('' Error. Expecting one general interface.'', & i6,'' read'')') nconns stop end if index_conn=nconns ! read general connectivity info call cg_conn_info_f(index_file,index_base,index_zone,index_conn, & connectname,location,iconnect_type,iptset_type,npts, & donorname,idonor_zonetype,idonor_ptset_type,idonor_datatype, & ndata_donor,ier) if (npts .gt. maxpnts) then write(6,'('' Error. Must increase maxpnts to at least '',i5)') npts stop end if call cg_conn_read_f(index_file,index_base,index_zone,index_conn, & ipnts,idonor_datatype,ipntsdonor,ier) write(6,'('' In zone '',i5,'':'')') index_zone write(6,'('' donor name='',a32)') donorname write(6,'('' number of connectivity pts='',i6)') npts write(6,'('' grid location='',a32)') & GridLocationName(location) write(6,'('' connectivity type='',a32)') & GridConnectivityTypeName(iconnect_type) write(6,'('' pointset type='',a32)') & PointSetTypeName(iptset_type) write(6,'('' donor zonetype='',a32)') & ZoneTypeName(idonor_zonetype) write(6,'('' donor pointset type='',a32)') & PointSetTypeName(idonor_ptset_type) ! write(6,'('' data type='',a32)') DataTypeName(idonor_datatype) write(6,'('' ipnts and ipntsdonor arrays read, only some'', & '' written out here:'')') do i=1,10 write(6,'('' ipnts(1,'',i2,''), (2,'',i2,''), (3,'',i2,'')='', & 3i4,'' ipntsdonor(1,'',i2,''), (2,'',i2,''), (3,'',i2, & '')='',3i4)') i,i,i,ipnts(1,i),ipnts(2,i),ipnts(3,i), & i,i,i,ipntsdonor(1,i),ipntsdonor(2,i),ipntsdonor(3,i) enddo enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read general 1-to-1 connectivity'', & '' info from file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_con2zn_str.F90000066400000000000000000000060411343724673500245250ustar00rootroot00000000000000 program read_con2zn_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid (2 zones) plus 1-to-1 connectivity ! information, and reads the connectivity info. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid2zn_str.f plus write_con2zn_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_con2zn_str.F90 ! ifort -o read_con2zn_str read_con2zn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer(cgsize_t) ipnts(3,2),ipntsdonor(3,2) integer itranfrm(3) integer nzone,n1to1 integer index_conn,index_zone,index_base,index_file,ier character donorname*32,connectname*32 ! ! READ 1-TO-1 CONNECTIVITY INFORMATION FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! get number of zones (should be 2 for our case) call cg_nzones_f(index_file,index_base,nzone,ier) if (nzone .ne. 2) then write(6,'('' Error. This program expects 2 zones. '',i5, & '' read'')') nzone stop end if ! loop over zones do index_zone=1,nzone ! find out how many 1-to-1 interfaces there are in this zone ! (for this program, there should only be one) call cg_n1to1_f(index_file,index_base,index_zone,n1to1,ier) if (n1to1 .ne. 1) then write(6,'('' Error. Expecting one 1-to-1 interface.'', & i6,'' read'')') n1to1 stop end if index_conn=n1to1 ! read 1-to-1 info call cg_1to1_read_f(index_file,index_base,index_zone,index_conn, & connectname,donorname,ipnts,ipntsdonor,itranfrm,ier) write(6,'('' In zone '',i5,'':'')') index_zone write(6,'('' donor name='',a32)') donorname write(6,'('' range (this zone)='',6i5)') ipnts(1,1), & ipnts(2,1),ipnts(3,1),ipnts(1,2),ipnts(2,2),ipnts(3,2) write(6,'('' range (donor zone)='',6i5)') ipntsdonor(1,1), & ipntsdonor(2,1),ipntsdonor(3,1),ipntsdonor(1,2), & ipntsdonor(2,2),ipntsdonor(3,2) write(6,'('' transform='',3i5)') itranfrm(1),itranfrm(2), & itranfrm(3) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read 1-to-1 connectivity info from'', & '' file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_convergence.F90000066400000000000000000000052551343724673500247300ustar00rootroot00000000000000 program read_convergence use cgns implicit none ! ! Reads convergence history from an existing CGNS file. ! ! The CGNS grid file 'grid.cgns' must already exist ! and a convergence history should be in it (using write_convergence.f). ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_convergence.F90 ! ifort -o read_convergence read_convergence.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: ntt=20 real*4 cl(ntt) integer(cgsize_t) idim(1) integer ndim,itype,index_array,narrays integer index_base,index_file,ier character arrayname*32 ! ! READ CONVERGENCE HISTORY INFORMATION FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! go to base node call cg_goto_f(index_file,index_base,ier,'end') ! go to history node (we assume it exists and that there is only one - ! real working code would check!) call cg_goto_f(index_file,index_base,ier,'ConvergenceHistory_t', & 1,'end') ! find out how many arrays are here (there should be only one!): call cg_narrays_f(narrays,ier) index_array=narrays ! some checks: if (narrays .ne. 1) then write(6,'('' Error! Expecting only one array, read'',i5)') narrays stop end if call cg_array_info_f(index_array,arrayname,itype,ndim,idim,ier) if (idim(1) .gt. ntt) then write(6,'('' Error! must increase ntt to at least '',i5)') idim(1) stop end if if (arrayname .ne. 'CoefLift') then write(6,'('' Error! expecting CoefLift, read'',a32)') arrayname stop end if ! read lift coefficient array call cg_array_read_as_f(index_array,RealSingle,cl,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read cl history from file grid.cgns'')') write(6,'('' values are: '',5f12.5)') cl(1),cl(2),cl(3), & cl(4),cl(5) write(6,'('' '',5f12.5)') cl(6),cl(7),cl(8), & cl(9),cl(10) stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_descriptor.F90000066400000000000000000000040301343724673500245760ustar00rootroot00000000000000 program read_descriptor use cgns implicit none ! ! Reads descriptor node (under CGNSBase_t) from an existing CGNS file. ! ! The CGNS grid file 'grid.cgns' must already exist ! and a descriptor node should be in it (using write_descriptor.f). ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_descriptor.F90 ! ifort -o read_descriptor read_descriptor.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! maxsize should match the length of 'text': integer, parameter :: maxsize=70 integer isize,n,ndescriptors,index_base,index_file,ier character text*70,name*32 ! ! READ DESCRIPTOR FROM EXISTING CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! go to base node call cg_goto_f(index_file,index_base,ier,'end') ! find out how many descriptors are here: call cg_ndescriptors_f(ndescriptors,ier) do n=1,ndescriptors call cg_descriptor_size_f(n,isize,ier) if (isize .gt. maxsize) then write(6,'('' Error! must increase maxsize to at least '', & i5)') isize stop end if ! read descriptor call cg_descriptor_read_f(n,name,text,ier) write(6,'('' The descriptor is:'',/,/,a)') text enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'(/,'' Successfully read descriptors from file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_dimensional.F90000066400000000000000000000102401343724673500247220ustar00rootroot00000000000000 program read_dimensional use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! grid plus a flow solution WITH DIMENSIONALITY, and reads ! the dimensionality. ! ! The CGNS grid file 'grid.cgns' must already exist ! (for example, created using ! write_grid_str.f followed by write_flowcent_str.f or ! write_grid_str.f followed by write_flowvert_str.f or ! write_grid_str.f followed by write_flowcentrind_str.f or ! write_grid_unst.f followed by write_flowvert_unst.f ! followed by write_dimensional.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_dimensional.F90 ! ifort -o read_dimensional read_dimensional.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 exponents(5) integer ic,ncoords,idatatype,iff,nfields,ia,ix,it,il,im,id integer index_grid,index_flow,index_zone,index_base,index_file,ier character fieldname*32,coordname*32 ! ! READ DIMENSIONAL INFO FOR GRID AND FLOW SOLN ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! we know there is only one GridCoordinates_t (real working code would check!) index_grid=1 ! read DataClass and DimensionalUnits under Base call cg_goto_f(index_file,index_base,ier,'end') call cg_dataclass_read_f(id,ier) write(6,'('' DataClass = '',a32)') DataClassName(id) if (DataClassName(id) .ne. 'Dimensional') then write(6,'('' Error! Expecting Dimensional'')') stop end if call cg_units_read_f(im,il,it,ix,ia,ier) write(6,'('' Units='',5(/,8x,a32))') MassUnitsName(im), & LengthUnitsName(il),TimeUnitsName(it), & TemperatureUnitsName(ix),AngleUnitsName(ia) ! read fields call cg_nfields_f(index_file,index_base,index_zone,index_flow, & nfields,ier) if (nfields .ne. 2) then write(6,'('' Error! expecting 2 fields, read '',i5)') nfields stop end if do iff=1,nfields ! read DimensionalExponents call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'FlowSolution_t',1,'DataArray_t',iff,'end') call cg_exponents_read_f(exponents,ier) ! get field name call cg_field_info_f(index_file,index_base,index_zone, & index_flow,iff,idatatype,fieldname,ier) write(6,'('' For '',a32,'', exponents are:'',5(/,6x,f5.1))') & fieldname,exponents(1),exponents(2),exponents(3),exponents(4), & exponents(5) enddo ! read grid call cg_ncoords_f(index_file,index_base,index_zone,ncoords,ier) do ic=1,ncoords ! read DimensionalExponents call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'GridCoordinates_t',1,'DataArray_t',ic,'end') call cg_exponents_read_f(exponents,ier) ! get coord name call cg_coord_info_f(index_file,index_base,index_zone, & ic,idatatype,coordname,ier) write(6,'('' For '',a32,'', exponents are:'',5(/,6x,f5.1))') & coordname,exponents(1),exponents(2),exponents(3),exponents(4), & exponents(5) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read dimensional data from file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_flowcent_str.F90000066400000000000000000000064771343724673500251520ustar00rootroot00000000000000 program read_flowcent_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid plus a flow solution (at CELL CENTERS), ! and reads it. (Compare this program with read_flowvert_str) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f followed by ! write_flowcent_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_flowcent_str.F90 ! ifort -o read_flowcent_str read_flowcent_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21-1,17-1,N-1) (N>=9) ! for this particular case or else they will be read from ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 r(20,16,8),p(20,16,8) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer loc,index_flow,index_zone,index_base,index_file,ier character*32 zonename,solname ! ! READ FLOW SOLUTION FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename,isize,ier) ! lower range index irmin(1)=1 irmin(2)=1 irmin(3)=1 ! upper range index - use cell dimensions ! checking GridLocation first (real working code would check ! to make sure there are no Rind cells also!): call cg_sol_info_f(index_file,index_base,index_zone,index_flow, & solname,loc,ier) if (loc .ne. CellCenter) then write(6,'('' Error, GridLocation must be CellCenter!'', & '' Currently:'',a32)') GridLocationName(loc) stop end if irmax(1)=isize(1,2) irmax(2)=isize(2,2) irmax(3)=isize(3,2) ! read flow solution call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Density',RealDouble,irmin,irmax,r,ier) call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Pressure',RealDouble,irmin,irmax,p,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read flow solution from file'', & '' grid.cgns'')') write(6,'('' For example, r,p(20,16,8)='',2f12.5)') & r(20,16,8),p(20,16,8) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_flowcentrind_str.F90000066400000000000000000000077101343724673500260160ustar00rootroot00000000000000 program read_flowcentrind_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid plus a flow solution (at CELL CENTERS PLUS ! RIND CELLS IN THE I AND J DIRECTIONS), and reads it. ! (Compare this program with read_flowcent_str) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f followed by ! write_flowcentrind_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_flowcentrind_str.F90 ! ifort -o read_flowcentrind_str read_flowcentrind_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21-1+2,17-1+2,N-1) (N>=9) ! for this particular case or else they will be read from ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): ! Rind cells are stored in array locations (i,1,k), (i,18,k), (1,j,k), (22,j,k) real*4 r(22,18,8),p(22,18,8) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer irinddata(6) integer loc,index_flow,index_zone,index_base,index_file,ier character*32 zonename,solname ! ! READ FLOW SOLUTION FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename,isize,ier) ! go to position within tree at FlowSolution\_t node call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowSolution_t',index_flow,'end') ! read rind data call cg_rind_read_f(irinddata,ier) ! lower range index irmin(1)=1-irinddata(1) irmin(2)=1-irinddata(3) irmin(3)=1-irinddata(5) ! upper range index - use cell dimensions and rind info ! checking GridLocation first: call cg_sol_info_f(index_file,index_base,index_zone,index_flow, & solname,loc,ier) if (loc .ne. CellCenter) then write(6,'('' Error, GridLocation must be CellCenter!'', & '' Currently:'',a32)') GridLocationName(loc) stop end if irmax(1)=isize(1,2)+irinddata(2) irmax(2)=isize(2,2)+irinddata(4) irmax(3)=isize(3,2)+irinddata(6) ! read flow solution call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Density',RealSingle,irmin,irmax,r,ier) call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Pressure',RealSingle,irmin,irmax,p,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read flow solution from file'', & '' grid.cgns'')') write(6,'('' For example, r,p(21,17,8)='',2f12.5)') & r(21,17,8),p(21,17,8) write(6,'('' rind: r,p(1,17,8)='',2f12.5)') & r(1,17,8),p(1,17,8) write(6,'('' rind: r,p(22,17,8)='',2f12.5)') & r(22,17,8),p(22,17,8) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_floweqn_str.F90000066400000000000000000000101201343724673500247600ustar00rootroot00000000000000 program read_floweqn_str use cgns implicit none ! ! Opens an existing CGNS file and reads flow equation info ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f followed by write_floweqn_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_floweqn_str.F90 ! ifort -o read_floweqn_str read_floweqn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 prandtl,gamma integer idata(6) integer itype,itm,itc,itcm,ivm,igm,ige,id integer index_zone,index_base,index_file,ier ! ! READ FLOW EQUATION SET INFO ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! existing file must be 3D structured (real working code would check!) ! Read info from 'FlowEquationSet' node under 'Zone_t' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone,'end') call cg_equationset_read_f(id,ige,igm,ivm,itcm,itc,itm,ier) if (ier .gt. 0) then write(6,'('' Error! FlowEquationSet node does not exist.'')') stop end if write(6,'('' Eqn dimension = '',i5)') id ! Read 'GoverningEquations' node if (ige .eq. 1) then call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_governing_read_f(itype,ier) write(6,'('' Gov eqn = '',a32)') GoverningEquationsTypeName(itype) ! Read 'DiffusionModel' node call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'GoverningEquations_t',1,'end') call cg_diffusion_read_f(idata,ier) write(6,'('' diffusion='',6i5)') idata(1),idata(2), & idata(3),idata(4),idata(5),idata(6) end if ! Read gas model if (igm .eq. 1) then call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_read_f('GasModel_t',itype,ier) write(6,'('' Gas model type = '',a32)') ModelTypeName(itype) call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'GasModel_t',1,'end') call cg_array_read_as_f(1,RealSingle,gamma,ier) write(6,'('' gamma='',f12.5)') gamma end if ! Read turbulence closure if (itc .eq. 1) then call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_read_f('TurbulenceClosure_t',itype,ier) write(6,'('' Turbulence closure type = '',a32)') & ModelTypeName(itype) call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'TurbulenceClosure_t',1,'end') call cg_array_read_as_f(1,RealSingle,prandtl,ier) write(6,'('' turb prandtl number = '',f12.5)') prandtl end if if (itm .eq. 1) then call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_read_f('TurbulenceModel_t',itype,ier) write(6,'('' Turbulence model type = '',a32)') & ModelTypeName(itype) end if ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read equation set info from file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_flowvert_str.F90000066400000000000000000000063631343724673500251730ustar00rootroot00000000000000 program read_flowvert_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid plus a flow solution (at VERTICES), ! and reads it. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f followed by ! write_flowvert_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_flowvert_str.F90 ! ifort -o read_flowvert_str read_flowvert_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be read from ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*4 r(21,17,9),p(21,17,9) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer loc,index_flow,index_zone,index_base,index_file,ier character*32 zonename,solname ! ! READ FLOW SOLUTION FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename,isize,ier) ! lower range index irmin(1)=1 irmin(2)=1 irmin(3)=1 ! upper range index - use vertex dimensions ! checking GridLocation first (real working code would check ! to make sure there are no Rind cells also!): call cg_sol_info_f(index_file,index_base,index_zone,index_flow, & solname,loc,ier) if (loc .ne. Vertex) then write(6,'('' Error, GridLocation must be Vertex! Currently:'', & a32)') GridLocationName(loc) stop end if irmax(1)=isize(1,1) irmax(2)=isize(2,1) irmax(3)=isize(3,1) ! read flow solution call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Density',RealSingle,irmin,irmax,r,ier) call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Pressure',RealSingle,irmin,irmax,p,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read flow solution from file'', & '' grid.cgns'')') write(6,'('' For example, r,p(21,17,9)='',2f12.5)') & r(21,17,9),p(21,17,9) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_flowvert_unst.F90000066400000000000000000000061351343724673500253510ustar00rootroot00000000000000 program read_flowvert_unst use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! unstructured grid plus a flow solution (at VERTICES), ! and reads it. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_unst.f followed by ! write_flowvert_unst.f) ! Note that, other than the dimensions of the variables ! r and p, this program is very similar to that for ! reading flow solutions from a structured zone: ! read_flowvert_str.f ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_flowvert_unst.F90 ! ifort -o read_flowvert_unst read_flowvert_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 r(21*17*9),p(21*17*9) integer(cgsize_t) isize(1,3),irmin,irmax integer loc,index_flow,index_zone,index_base,index_file,ier character*32 zonename,solname ! ! READ FLOW SOLUTION FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename,isize,ier) ! lower range index irmin=1 ! upper range index - use vertex dimensions ! checking GridLocation first (real working code would check ! to make sure there are no Rind cells also!): call cg_sol_info_f(index_file,index_base,index_zone,index_flow, & solname,loc,ier) if (loc .ne. Vertex) then write(6,'('' Error, GridLocation must be Vertex! Currently:'', & a32)') GridLocationName(loc) stop end if irmax=isize(1,1) ! read flow solution call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Density',RealSingle,irmin,irmax,r,ier) call cg_field_read_f(index_file,index_base,index_zone,index_flow, & 'Pressure',RealSingle,irmin,irmax,p,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read flow solution from file'', & '' grid.cgns'')') write(6,'('' For example, r,p(380) ='',2f12.5)') & r(380),p(380) write(6,'('' r,p(3213)='',2f12.5)') & r(3213),p(3213) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_grid2zn_str.F90000066400000000000000000000071221343724673500246740ustar00rootroot00000000000000 program read_grid2zn_str use cgns implicit none ! ! Reads simple 3-D structured 2-zone grid from CGNS file ! (companion program to write_grid2zn_str.f) ! ! The CGNS grid file 'grid.cgns' must already exist. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_grid2zn_str.F90 ! ifort -o read_grid2zn_str read_grid2zn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! x,y,z must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be read from ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*4 x(21,17,9),y(21,17,9),z(21,17,9) real*4 xsav(21,17,9,2),ysav(21,17,9,2),zsav(21,17,9,2) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer nzone,i,j,k,index_zone,index_base,index_file,ier character zonename*32 ! ! READ X, Y, Z GRID POINTS FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! get number of zones (should be 2 for our case) call cg_nzones_f(index_file,index_base,nzone,ier) if (nzone .ne. 2) then write(6,'('' Error. This program expects 2 zones. '',i5, & '' read'')') nzone stop end if ! do loop over the zones do index_zone=1,nzone ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone, & zonename,isize,ier) ! lower range index irmin(1)=1 irmin(2)=1 irmin(3)=1 ! upper range index of vertices irmax(1)=isize(1,1) irmax(2)=isize(2,1) irmax(3)=isize(3,1) ! read grid coordinates call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateX',RealSingle,irmin,irmax,x,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateY',RealSingle,irmin,irmax,y,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateZ',RealSingle,irmin,irmax,z,ier) ! store grid coordinates in xsav,ysav,zsav array: do i=1,isize(1,1) do j=1,isize(2,1) do k=1,isize(3,1) xsav(i,j,k,index_zone)=x(i,j,k) ysav(i,j,k,index_zone)=y(i,j,k) zsav(i,j,k,index_zone)=z(i,j,k) enddo enddo enddo enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read grid from file grid.cgns'')') write(6,'('' For example, zone 1 x,y,z(21,17,9)='',3f12.5)') & xsav(21,17,9,1),ysav(21,17,9,1),zsav(21,17,9,1) write(6,'('' zone 2 x,y,z(21,17,9)='',3f12.5)') & xsav(21,17,9,2),ysav(21,17,9,2),zsav(21,17,9,2) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_grid_str.F90000066400000000000000000000054001343724673500242370ustar00rootroot00000000000000 program read_grid_str use cgns implicit none ! ! Reads simple 3-D structured grid from CGNS file ! (companion program to write_grid_str.f) ! ! The CGNS grid file 'grid.cgns' must already exist. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_grid_str.F90 ! ifort -o read_grid_str read_grid_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! x,y,z must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be read from ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*4 x(21,17,9),y(21,17,9),z(21,17,9) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer index_zone,index_base,index_file,ier character zonename*32 ! ! READ X, Y, Z GRID POINTS FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename, & isize,ier) ! lower range index irmin(1)=1 irmin(2)=1 irmin(3)=1 ! upper range index of vertices irmax(1)=isize(1,1) irmax(2)=isize(2,1) irmax(3)=isize(3,1) ! read grid coordinates call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateX',RealSingle,irmin,irmax,x,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateY',RealSingle,irmin,irmax,y,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateZ',RealSingle,irmin,irmax,z,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read grid from file grid.cgns'')') write(6,'('' For example, x,y,z(21,17,9)='',3f12.5)') & x(21,17,9),y(21,17,9),z(21,17,9) write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_grid_unst.F90000066400000000000000000000073771343724673500244370ustar00rootroot00000000000000 program read_grid_unst use cgns implicit none ! ! Reads simple 3-D unstructured grid from a CGNS file ! (created using write_grid_unst.f). ! ! The CGNS grid file 'grid.cgns' must already exist. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_grid_unst.F90 ! ifort -o read_grid_unst read_grid_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 x(21*17*9),y(21*17*9),z(21*17*9) integer(cgsize_t) isize(1,3),ielem(8,20*16*8) integer(cgsize_t) irmin,irmax,istart,iend,iparentdata integer iparent_flag,nbndry,itype,index_sect,nsections integer index_zone,index_base,index_file,ier character zonename*32,sectionname*32 ! ! READ X, Y, Z GRID POINTS FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename, & isize,ier) ! lower range index irmin=1 ! upper range index of vertices irmax=isize(1,1) ! read grid coordinates call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateX',RealSingle,irmin,irmax,x,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateY',RealSingle,irmin,irmax,y,ier) call cg_coord_read_f(index_file,index_base,index_zone, & 'CoordinateZ',RealSingle,irmin,irmax,z,ier) ! find out how many sections call cg_nsections_f(index_file,index_base,index_zone,nsections,ier) write(6,'('' number of sections='',i7)') nsections ! read element connectivity do index_sect=1,nsections call cg_section_read_f(index_file,index_base,index_zone, & index_sect,sectionname,itype,istart,iend,nbndry, & iparent_flag,ier) write(6,'('' Reading section data...'')') write(6,'('' section name='',a32)') sectionname write(6,'('' section type='',a32)') ElementTypeName(itype) write(6,'('' istart,iend='',2i6)') istart,iend if (ElementTypeName(itype) .eq. 'HEXA_8') then write(6,'('' reading element data for this element'')') call cg_elements_read_f(index_file,index_base,index_zone, & index_sect,ielem,iparentdata,ier) else write(6,'('' not reading element data for this element'')') end if enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read unstructured grid from file'', & '' grid.cgns'')') write(6,'('' for example, element 1 is made up of nodes:'', & 8i5)') ielem(1,1),ielem(2,1),ielem(3,1),ielem(4,1), & ielem(5,1),ielem(6,1),ielem(7,1),ielem(8,1) write(6,'('' x,y,z of node 358 are:'',3f12.5)') & x(358),y(358),z(358) write(6,'('' x,y,z of node 1358 are:'',3f12.5)') & x(1358),y(1358),z(1358) stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_nondimensional.F90000066400000000000000000000052251343724673500254440ustar00rootroot00000000000000 program read_nondimensional use cgns implicit none ! ! Opens an existing CGNS file and reads the DataClass and ! ReferenceState appropriate for a completely ! NONDIMENSIONAL data set. ! ! The CGNS grid file 'grid.cgns' must already exist, ! processed further using write_nondimensional.f. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_nondimensional.F90 ! ifort -o read_nondimensional read_nondimensional.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*8 data integer(cgsize_t) idimvec(1) integer n,idim,idata,narrays,id,index_base,index_file,ier character state*32,arrayname*32 ! ! READ NONDIMENSIONAL INFO ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! read DataClass under Base call cg_goto_f(index_file,index_base,ier,'end') call cg_dataclass_read_f(id,ier) write(6,'('' DataClass = '',a32)') DataClassName(id) if (DataClassName(id) .ne. 'NormalizedByUnknownDimensional') then write(6,'('' Error! Expecting NormalizedByUnknownDimensional'')') stop end if ! read ReferenceState under Base call cg_state_read_f(state,ier) write(6,'('' ReferenceState = '',a32)') state ! Go to ReferenceState node, read Mach array and its dataclass call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1,'end') ! find out how many data arrays call cg_narrays_f(narrays,ier) do n=1,narrays call cg_array_info_f(n,arrayname,idata,idim,idimvec,ier) if (idim .ne. 1 .or. idimvec(1) .ne. 1) then write(6,'('' Error! expecting idim,idimvec=1,1'')') write(6,'('' they are idim,idimvec='',2i5)')idim,idimvec(1) stop end if call cg_array_read_as_f(n,RealDouble,data,ier) write(6,'('' Variable='',a32)') arrayname write(6,'('' data='',f18.8)') data enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read nondimensional info from file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/read_timevert_str.F90000066400000000000000000000156631343724673500251650ustar00rootroot00000000000000 program read_timevert_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid plus 3 different flow solutions (at VERTICES), ! along with time-accurate info, and reads it. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f followed by ! write_timevert_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c read_timevert_str.F90 ! ifort -o read_timevert_str read_timevert_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r1, r2, r3 and p1, p2, p3 ! must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*4 r1(21,17,9),p1(21,17,9) real*4 r2(21,17,9),p2(21,17,9) real*4 r3(21,17,9),p3(21,17,9) real*4 time(3) integer(cgsize_t) isize(3,3),irmin(3),irmax(3) integer(cgsize_t) idims(2),id2(1) integer n,idatatype,id1,nsteps,narrays,isim,loc integer index_zone,index_base,index_file,ier character zonename*32,bitername*32,zitername*32 character arrayname*32 character solname(3)*32,solname2*32 ! ! READ FLOW SOLUTION FROM CGNS FILE ! open CGNS file for read-only call cg_open_f('grid.cgns',CG_MODE_READ,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename, & isize,ier) ! lower range index irmin(1)=1 irmin(2)=1 irmin(3)=1 ! upper range index - use vertex dimensions irmax(1)=isize(1,1) irmax(2)=isize(2,1) irmax(3)=isize(3,1) ! read BaseIterativeData call cg_biter_read_f(index_file,index_base,bitername,nsteps,ier) write(6,'('' number of time steps stored = '',i5)') nsteps if (nsteps .ne. 3) then write(6,'('' Error, expecting nsteps=3!'')') stop end if call cg_goto_f(index_file,index_base,ier,'BaseIterativeData_t',1,'end') call cg_narrays_f(narrays,ier) if (narrays .ne. 1) then write(6,'('' Error, expecting 1 array in BaseIterativeData'', & ''... there are '',i5)') narrays stop end if call cg_array_info_f(1,arrayname,idatatype,id1,id2,ier) if (id1 .ne. 1 .or. id2(1) .ne. 3) then write(6,'('' Error, expecting data dimension and vector to'', & '' be 1 and 3 in BaseIterativeData... read '',2i5)') id1,id2(1) stop end if call cg_array_read_as_f(1,RealSingle,time,ier) write(6,'('' Times stored are:'')') do n=1,nsteps write(6,'(f12.3)') time(n) enddo ! read ZoneIterativeData call cg_ziter_read_f(index_file,index_base,index_zone,zitername,ier) call cg_goto_f(index_file,index_base,ier,'Zone_t', & index_zone,'ZoneIterativeData_t',1,'end') call cg_narrays_f(narrays,ier) if (narrays .ne. 1) then write(6,'('' Error, expecting 1 array in ZoneIterativeData'', & ''... there are '',i5)') narrays stop end if call cg_array_info_f(1,arrayname,idatatype,id1,idims,ier) if (id1 .ne. 2 .or. idims(1) .ne. 32) then write(6,'('' Error, expecting data dimension and vector to'', & '' be 2 and 32 in ZoneIterativeData... read '',2i5)') id1, & idims(1) stop end if call cg_array_read_as_f(1,Character,solname,ier) write(6,'('' Flow solution names corresponding to each are:'')') do n=1,nsteps write(6,'(a32)') solname(n) enddo ! read SimulationType call cg_simulation_type_read_f(index_file,index_base,isim,ier) write(6,'('' Simulation type is: '',a32)') SimulationTypeName(isim) ! do loop to read flow solutions do n=1,nsteps ! check that soln names match, and also check GridLocation (real ! working code would check to make sure there are no Rind cells ! also!): call cg_sol_info_f(index_file,index_base,index_zone,n, & solname2,loc,ier) if (solname2 .ne. solname(n)) then write(6,'('' Error, soln names do not match'')') stop end if if (loc .ne. Vertex) then write(6,'('' Error, GridLocation must be Vertex! Currently:'', & a32)') GridLocationName(loc) stop end if if (n .eq. 1) then call cg_field_read_f(index_file,index_base,index_zone,n, & 'Density',RealSingle,irmin,irmax,r1,ier) call cg_field_read_f(index_file,index_base,index_zone,n, & 'Pressure',RealSingle,irmin,irmax,p1,ier) else if (n .eq. 2) then call cg_field_read_f(index_file,index_base,index_zone,n, & 'Density',RealSingle,irmin,irmax,r2,ier) call cg_field_read_f(index_file,index_base,index_zone,n, & 'Pressure',RealSingle,irmin,irmax,p2,ier) else call cg_field_read_f(index_file,index_base,index_zone,n, & 'Density',RealSingle,irmin,irmax,r3,ier) call cg_field_read_f(index_file,index_base,index_zone,n, & 'Pressure',RealSingle,irmin,irmax,p3,ier) end if enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully read 3 flow solutions from file'', & '' grid.cgns'')') write(6,'('' For example, r1,p1(1,1,1)='',2f12.5)') & r1(1,1,1),p1(1,1,1) write(6,'('' r2,p2(1,1,1)='',2f12.5)') & r2(1,1,1),p2(1,1,1) write(6,'('' r3,p3(1,1,1)='',2f12.5)') & r3(1,1,1),p3(1,1,1) write(6,'('' For example, r1,p1(21,17,9)='',2f12.5)') & r1(21,17,9),p1(21,17,9) write(6,'('' r2,p2(21,17,9)='',2f12.5)') & r2(21,17,9),p2(21,17,9) write(6,'('' r3,p3(21,17,9)='',2f12.5)') & r3(21,17,9),p3(21,17,9) ! write(6,'('' Program successful... ending now'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/test.sh000077500000000000000000000120241343724673500224650ustar00rootroot00000000000000#! /bin/bash NO_COLOR="\033[0m" OK_COLOR="\033[32;01m" ERROR_COLOR="\033[31;01m" echoresults() { if test $* -ne 0 then printf "$ERROR_COLOR *** FAILED *** $NO_COLOR \n" else printf "$OK_COLOR passed $NO_COLOR \n" fi } DIRS=" \ Test_Grid_Str" return_val=0 ############################### # Special cases ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowvert_str" "write_nondimensional" "write_descriptor" \ "write_convergence" "write_floweqn_str" "write_bcpnts_str") declare -a r_arr=("read_grid_str" "read_flowvert_str" "read_nondimensional" "read_descriptor" \ "read_convergence" "read_floweqn_str" "read_bcpnts_str") dir=Test_Grid_Str printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_unst" "write_flowvert_unst" "write_dimensional" "write_descriptor" "write_convergence" "write_bcpnts_unst") declare -a r_arr=("read_grid_unst" "read_flowvert_unst" "read_dimensional" "read_descriptor" "read_convergence" "read_bcpnts_unst") dir=Test_Grid_Unstr printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_timevert_str") declare -a r_arr=("read_grid_str" "read_timevert_str") dir=Test_Grid_Str_Timeacc printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowcent_str" "write_bc_str") declare -a r_arr=("read_grid_str" "read_flowcent_str" "read_bc_str") dir=Test_Grid_Str_FlowCent printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid_str" "write_flowcentrind_str") declare -a r_arr=("read_grid_str" "read_flowcentrind_str") dir=Test_Grid_Str_FlowCentRind printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid2zn_str" "write_con2zn_str") declare -a r_arr=("read_grid2zn_str" "read_con2zn_str") dir=Test_Grid_Str_2zn printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### ## declare an array of tests declare -a w_arr=("write_grid2zn_str" "write_con2zn_genrl_str") declare -a r_arr=("read_grid2zn_str" "read_con2zn_genrl_str") dir=Test_Grid_Str_2zngenrl printf "%-40s" "Testing $dir..." cd $dir # loop through tests size_arr=${#w_arr[@]} #Number of elements in the array for i in $(seq 1 $size_arr);do ./${w_arr[$i-1]} ./${r_arr[$i-1]} > build/output$i diff <( sed '/Library/ d' build/output$i) <( sed '/Library/ d' ./OUTPUT$i) > build/results$i.txt status=$? echoresults $status return_val=`expr $status + $return_val` done cd .. ############################### echo "=== finished ===" if test $return_val != 0; then printf "$ERROR_COLOR" else printf "$OK_COLOR" fi printf "$return_val tests failed $NO_COLOR \n" exit $return_val CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_bc_str.F90000066400000000000000000000111401343724673500241130ustar00rootroot00000000000000 program write_bc_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds BC definitions (defined ! over a range of points = PointRange) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_bc_str.F90 ! ifort -o write_bc_str write_bc_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer ilo,ihi,jlo,jhi,klo,khi integer index_zone,index_base,index_file,index_bc,ier integer(cgsize_t) isize(3,3),ipnts(3,2) character zonename*32 ! write(6,'('' Program write_bc_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename, & isize,ier) write(6,'('' zonename='',a32)') zonename ilo=1 ihi=isize(1,1) jlo=1 jhi=isize(2,1) klo=1 khi=isize(3,1) ! write boundary conditions for ilo face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ilo ipnts(2,1)=jlo ipnts(3,1)=klo ! upper point of range ipnts(1,2)=ilo ipnts(2,2)=jhi ipnts(3,2)=khi call cg_boco_write_f(index_file,index_base,index_zone,'Ilo', & BCTunnelInflow,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! write boundary conditions for ihi face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ihi ipnts(2,1)=jlo ipnts(3,1)=klo ! upper point of range ipnts(1,2)=ihi ipnts(2,2)=jhi ipnts(3,2)=khi call cg_boco_write_f(index_file,index_base,index_zone,'Ihi', & BCExtrapolate,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! write boundary conditions for jlo face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ilo ipnts(2,1)=jlo ipnts(3,1)=klo ! upper point of range ipnts(1,2)=ihi ipnts(2,2)=jlo ipnts(3,2)=khi call cg_boco_write_f(index_file,index_base,index_zone,'Jlo', & BCWallInviscid,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! write boundary conditions for jhi face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ilo ipnts(2,1)=jhi ipnts(3,1)=klo ! upper point of range ipnts(1,2)=ihi ipnts(2,2)=jhi ipnts(3,2)=khi call cg_boco_write_f(index_file,index_base,index_zone,'Jhi', & BCWallInviscid,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! write boundary conditions for klo face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ilo ipnts(2,1)=jlo ipnts(3,1)=klo ! upper point of range ipnts(1,2)=ihi ipnts(2,2)=jhi ipnts(3,2)=klo call cg_boco_write_f(index_file,index_base,index_zone,'Klo', & BCWallInviscid,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! write boundary conditions for khi face, defining range first ! (user can give any name) ! lower point of range ipnts(1,1)=ilo ipnts(2,1)=jlo ipnts(3,1)=khi ! upper point of range ipnts(1,2)=ihi ipnts(2,2)=jhi ipnts(3,2)=khi call cg_boco_write_f(index_file,index_base,index_zone,'Khi', & BCWallInviscid,PointRange,2_cgsize_t,ipnts,index_bc,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added BCs (PointRange) to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_bcpnts_str.F90000066400000000000000000000135701343724673500250310ustar00rootroot00000000000000 program write_bcpnts_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds BC definitions (defined ! as individual points = PointList) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_bcpnts_str.F90 ! ifort -o write_bcpnts_str write_bcpnts_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxcount=400 integer(cgsize_t) isize(3,3),ipnts(3,maxcount),icounts integer i,j,k,ilo,ihi,jlo,jhi,klo,khi,icount integer index_bc,index_zone,index_base,index_file,ier character zonename*32 ! write(6,'('' Program write_bcpnts_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! get zone size (and name - although not needed here) call cg_zone_read_f(index_file,index_base,index_zone,zonename,isize,ier) write(6,'('' zonename='',a32)') zonename ilo=1 ihi=isize(1,1) jlo=1 jhi=isize(2,1) klo=1 khi=isize(3,1) ! write boundary conditions for ilo face, defining pointlist first ! (user can give any name) icount=0 do j=jlo,jhi do k=klo,khi icount=icount+1 ipnts(1,icount)=ilo ipnts(2,icount)=j ipnts(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Ilo', & BCTunnelInflow,PointList,icounts,ipnts,index_bc,ier) ! write boundary conditions for ihi face, defining pointlist first ! (user can give any name) icount=0 do j=jlo,jhi do k=klo,khi icount=icount+1 ipnts(1,icount)=ihi ipnts(2,icount)=j ipnts(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Ihi', & BCExtrapolate,PointList,icounts,ipnts,index_bc,ier) ! write boundary conditions for jlo face, defining pointlist first ! (user can give any name) icount=0 do i=ilo,ihi do k=klo,khi icount=icount+1 ipnts(1,icount)=i ipnts(2,icount)=jlo ipnts(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Jlo', & BCWallInviscid,PointList,icounts,ipnts,index_bc,ier) ! write boundary conditions for jhi face, defining pointlist first ! (user can give any name) icount=0 do i=ilo,ihi do k=klo,khi icount=icount+1 ipnts(1,icount)=i ipnts(2,icount)=jhi ipnts(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Jhi', & BCWallInviscid,PointList,icounts,ipnts,index_bc,ier) ! write boundary conditions for klo face, defining pointlist first ! (user can give any name) icount=0 do i=ilo,ihi do j=jlo,jhi icount=icount+1 ipnts(1,icount)=i ipnts(2,icount)=j ipnts(3,icount)=klo enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Klo', & BCWallInviscid,PointList,icounts,ipnts,index_bc,ier) ! write boundary conditions for khi face, defining pointlist first ! (user can give any name) icount=0 do i=ilo,ihi do j=jlo,jhi icount=icount+1 ipnts(1,icount)=i ipnts(2,icount)=j ipnts(3,icount)=khi enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Khi', & BCWallInviscid,PointList,icounts,ipnts,index_bc,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added BCs (PointList) to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_bcpnts_unst.F90000066400000000000000000000111201343724673500251770ustar00rootroot00000000000000 program write_bcpnts_unst use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! unstructured grid, and adds BC definitions (defined ! as individual FaceCenter "points" = PointList+GridLocation=FaceCenter) ! The BCs are added as FaceCenter points, associated with ! face elements (QUAD_4), rather than associated to nodes ! ! For the following, be sure you are using Version 2.0 or ! later release of the API ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_unst.f). Note: whether the ! existing CGNS file has a flow solution in it already or ! not is irrelevant. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_bcpnts_unst.F90 ! ifort -o write_bcpnts_unst write_bcpnts_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxcount=960 integer n,ibc,icount,nelem_start,nelem_end integer index_zone,index_base,index_file,index_bc,ier integer(cgsize_t) ipnts(maxcount),icounts ! write(6,'('' Program write_bcpnts_unst'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! WRITE BOUNDARY CONDITIONS TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know that for the unstructured zone, the following face elements ! have been defined as inflow (real working code would check!): nelem_start=2561 nelem_end=2688 icount=0 do n=nelem_start,nelem_end icount=icount+1 ipnts(icount)=n enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if ! write boundary conditions for ilo face icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Ilo', & BCTunnelInflow,PointList,icounts,ipnts,index_bc,ier) ! we know that for the unstructured zone, the following face elements ! have been defined as outflow (real working code would check!): nelem_start=2689 nelem_end=2816 icount=0 do n=nelem_start,nelem_end icount=icount+1 ipnts(icount)=n enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if ! write boundary conditions for ihi face icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Ihi', & BCExtrapolate,PointList,icounts,ipnts,index_bc,ier) ! we know that for the unstructured zone, the following face elements ! have been defined as walls (real working code would check!): nelem_start=2817 nelem_end=3776 icount=0 do n=nelem_start,nelem_end icount=icount+1 ipnts(icount)=n enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if ! write boundary conditions for wall faces icounts=icount call cg_boco_write_f(index_file,index_base,index_zone,'Walls', & BCWallInviscid,PointList,icounts,ipnts,index_bc,ier) ! ! the above are all face-center locations for the BCs - must indicate this, ! otherwise Vertices will be assumed! do ibc=1,index_bc ! (the following call positions you in BC_t - it assumes there ! is only one Zone_t and one ZoneBC_t - real working code would check!) call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'ZoneBC_t',1,'BC_t',ibc,'end') call cg_gridlocation_write_f(FaceCenter,ier) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added FaceCenter BCs (PointList) to'', & '' unstructured grid file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_con2zn_genrl_str.F90000066400000000000000000000116631343724673500261410ustar00rootroot00000000000000 program write_con2zn_genrl_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid (2 zones), and adds 1-to-1 ! connectivity information to it (using GENERAL ! method, as opposed to specific 1-to-1 method). ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid2zn_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_con2zn_genrl_str.F90 ! ifort -o write_con2zn_genrl_str write_con2zn_genrl_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxcount=400 integer ilo(2),ihi(2),jlo(2),jhi(2),klo(2),khi(2) integer(cgsize_t) isize(3,3),ipnts(3,maxcount) integer(cgsize_t) ipntsdonor(3,maxcount),icounts integer index_conn,index_zone,index_base,index_file,ier integer nconns,n1to1,icount,nzone,j,k character donorname*32,zonename(2)*32 ! write(6,'('' Program write_con2zn_genrl_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! WRITE GENERAL CONNECTIVITY INFORMATION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! get number of zones (should be 2 for our case) call cg_nzones_f(index_file,index_base,nzone,ier) if (nzone .ne. 2) then write(6,'('' Error. This program expects 2 zones. '',i5, & '' read'')') nzone stop end if ! loop over zones to get zone sizes and names do index_zone=1,nzone call cg_zone_read_f(index_file,index_base,index_zone, & zonename(index_zone),isize,ier) ilo(index_zone)=1 ihi(index_zone)=isize(1,1) jlo(index_zone)=1 jhi(index_zone)=isize(2,1) klo(index_zone)=1 khi(index_zone)=isize(3,1) enddo ! loop over zones again do index_zone=1,nzone ! for this program, there should be no existing connectivity info: call cg_nconns_f(index_file,index_base,index_zone,nconns,ier) if (nconns .ne. 0) then write(6,'('' Error. This program expects no interfaces'', & '' yet.'',i5,'' read'')') nconns stop end if call cg_n1to1_f(index_file,index_base,index_zone,n1to1,ier) if (n1to1 .ne. 0) then write(6,'('' Error. This program expects no interfaces'', & '' yet.'',i5,'' read'')') n1to1 stop end if ! set up point lists if (index_zone .eq. 1) then icount=0 do j=jlo(index_zone),jhi(index_zone) do k=klo(index_zone),khi(index_zone) icount=icount+1 ipnts(1,icount)=ihi(1) ipnts(2,icount)=j ipnts(3,icount)=k ipntsdonor(1,icount)=ilo(2) ipntsdonor(2,icount)=j ipntsdonor(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if donorname=zonename(2) else icount=0 do j=jlo(index_zone),jhi(index_zone) do k=klo(index_zone),khi(index_zone) icount=icount+1 ipnts(1,icount)=ilo(2) ipnts(2,icount)=j ipnts(3,icount)=k ipntsdonor(1,icount)=ihi(1) ipntsdonor(2,icount)=j ipntsdonor(3,icount)=k enddo enddo if (icount .gt. maxcount) then write(6,'('' Error. Need to increase maxcount to at least'', & i5)') icount stop end if donorname=zonename(1) end if ! write integer connectivity info (user can give any name) icounts=icount call cg_conn_write_f(index_file,index_base,index_zone, & 'GenInterface',Vertex,Abutting1to1,PointList,icounts,ipnts, & donorname,Structured,PointListDonor,Integer,icounts, & ipntsdonor,index_conn,ier) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added 1-to-1 connectivity info to'', & '' file grid.cgns (using GENERAL method)'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_con2zn_str.F90000066400000000000000000000110451343724673500247440ustar00rootroot00000000000000 program write_con2zn_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid (2 zones), and adds 1-to-1 ! connectivity information to it. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid2zn_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_con2zn_str.F90 ! ifort -o write_con2zn_str write_con2zn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer ilo(2),ihi(2),jlo(2),jhi(2),klo(2),khi(2) integer itranfrm(3) integer index_conn,n1to1,nconns,nzone integer index_zone,index_base,index_file,ier integer(cgsize_t) isize(3,3),ipnts(3,2),ipntsdonor(3,2) character donorname*32,zonename(2)*32 ! write(6,'('' Program write_con2zn_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! WRITE 1-TO-1 CONNECTIVITY INFORMATION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! get number of zones (should be 2 for our case) call cg_nzones_f(index_file,index_base,nzone,ier) if (nzone .ne. 2) then write(6,'('' Error. This program expects 2 zones. '',i5, & '' read'')') nzone stop end if ! loop over zones to get zone sizes and names do index_zone=1,nzone call cg_zone_read_f(index_file,index_base,index_zone, & zonename(index_zone),isize,ier) ilo(index_zone)=1 ihi(index_zone)=isize(1,1) jlo(index_zone)=1 jhi(index_zone)=isize(2,1) klo(index_zone)=1 khi(index_zone)=isize(3,1) enddo ! loop over zones again do index_zone=1,nzone ! for this program, there should be no existing connectivity info: call cg_nconns_f(index_file,index_base,index_zone,nconns,ier) if (nconns .ne. 0) then write(6,'('' Error. This program expects no interfaces'', & '' yet.'',i5,'' read'')') nconns stop end if call cg_n1to1_f(index_file,index_base,index_zone,n1to1,ier) if (n1to1 .ne. 0) then write(6,'('' Error. This program expects no interfaces'', & '' yet.'',i5,'' read'')') n1to1 stop end if ! set up index ranges if (index_zone .eq. 1) then donorname=zonename(2) ! lower point of receiver range ipnts(1,1)=ihi(1) ipnts(2,1)=jlo(1) ipnts(3,1)=klo(1) ! upper point of receiver range ipnts(1,2)=ihi(1) ipnts(2,2)=jhi(1) ipnts(3,2)=khi(1) ! lower point of donor range ipntsdonor(1,1)=ilo(2) ipntsdonor(2,1)=jlo(2) ipntsdonor(3,1)=klo(2) ! upper point of donor range ipntsdonor(1,2)=ilo(2) ipntsdonor(2,2)=jhi(2) ipntsdonor(3,2)=khi(2) else donorname=zonename(1) ! lower point of receiver range ipnts(1,1)=ilo(2) ipnts(2,1)=jlo(2) ipnts(3,1)=klo(2) ! upper point of receiver range ipnts(1,2)=ilo(2) ipnts(2,2)=jhi(2) ipnts(3,2)=khi(2) ! lower point of donor range ipntsdonor(1,1)=ihi(1) ipntsdonor(2,1)=jlo(1) ipntsdonor(3,1)=klo(1) ! upper point of donor range ipntsdonor(1,2)=ihi(1) ipntsdonor(2,2)=jhi(1) ipntsdonor(3,2)=khi(1) end if ! set up Transform itranfrm(1)=1 itranfrm(2)=2 itranfrm(3)=3 ! write 1-to-1 info (user can give any name) call cg_1to1_write_f(index_file,index_base,index_zone, & 'Interface',donorname,ipnts,ipntsdonor,itranfrm, & index_conn,ier) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added 1-to-1 connectivity info to'', & '' file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_convergence.F90000066400000000000000000000041471343724673500251460ustar00rootroot00000000000000 program write_convergence use cgns implicit none ! ! Adds convergence history to an existing CGNS file. ! ! The CGNS grid file 'grid.cgns' must already exist. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_convergence.F90 ! ifort -o write_convergence write_convergence.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: ntt=20 real*8 cl(ntt) integer index_base,index_file,ier,n integer(cgsize_t) nuse ! write(6,'('' Program write_convergence'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! create history array simple example: do n=1,ntt cl(n)=float(n) enddo write(6,'('' created simple cl history'')') ! ! WRITE CONVERGENCE HISTORY INFORMATION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! go to base node call cg_goto_f(index_file,index_base,ier,'end') ! create history node (SIDS names it GlobalConvergenceHistory at base level) call cg_convergence_write_f(ntt,CHAR(0),ier) ! go to new history node call cg_goto_f(index_file,index_base,ier,'ConvergenceHistory_t',1,'end') ! write lift coefficient array (user must use SIDS-standard name here) nuse=ntt call cg_array_write_f('CoefLift',RealDouble,1,nuse,cl,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote cl history to file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_descriptor.F90000066400000000000000000000034711343724673500250250ustar00rootroot00000000000000 program write_descriptor use cgns implicit none ! ! Adds descriptor node to an existing CGNS file (under the ! CGNSBase_t node). ! ! The CGNS grid file 'grid.cgns' must already exist. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_descriptor.F90 ! ifort -o write_descriptor write_descriptor.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer index_base,index_file,ier character text1*36,text2*36,textstring*73 ! write(6,'('' Program write_descriptor'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! WRITE DESCRIPTOR NODE AT BASE LEVEL ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! go to base node call cg_goto_f(index_file,index_base,ier,'end') ! write descriptor node (user can give any name) text1='Supersonic vehicle with landing gear' text2='M=4.6, Re=6 million' textstring=text1//char(10)//text2 call cg_descriptor_write_f('Information',textstring,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote descriptor node to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_dimensional.F90000066400000000000000000000100301343724673500251360ustar00rootroot00000000000000 program write_dimensional use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! grid plus a flow solution and adds its dimensionality ! (dimensional data). ! ! The CGNS grid file 'grid.cgns' must already exist ! (for example, created using ! write_grid_str.f followed by write_flowcent_str.f or ! write_grid_str.f followed by write_flowvert_str.f or ! write_grid_str.f followed by write_flowcentrind_str.f or ! write_grid_unst.f followed by write_flowvert_unst.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_dimensional.F90 ! ifort -o write_dimensional write_dimensional.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 exponents(5) integer icc,iff,nfields,index_grid,index_flow,index_zone integer index_base,index_file,ier,ncoords,idatatype character fieldname*32 ! write(6,'('' Program write_dimensional'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! WRITE DIMENSIONAL INFO FOR GRID AND FLOW SOLN ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! we know there is only one FlowSolution_t (real working code would check!) index_flow=1 ! we know there is only one GridCoordinates_t (real working code would check!) index_grid=1 ! put DataClass and DimensionalUnits under Base call cg_goto_f(index_file,index_base,ier,'end') call cg_dataclass_write_f(Dimensional,ier) call cg_units_write_f(Kilogram,Meter,Second,Kelvin,Degree,ier) ! read fields call cg_nfields_f(index_file,index_base,index_zone,index_flow, & nfields,ier) if (nfields .ne. 2) then write(6,'('' Error! expecting 2 fields, read '',i5)') nfields stop end if do iff=1,nfields call cg_field_info_f(index_file,index_base,index_zone, & index_flow,iff,idatatype,fieldname,ier) write(6,'('' fieldname='',a32)') fieldname if (fieldname .eq. 'Density') then exponents(1)=1. exponents(2)=-3. exponents(3)=0. exponents(4)=0. exponents(5)=0. else if (fieldname .eq. 'Pressure') then exponents(1)=1. exponents(2)=-1. exponents(3)=-2. exponents(4)=0. exponents(5)=0. else write(6,'('' Error! this fieldname not expected: '',a32)') fieldname stop end if ! write DimensionalExponents call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'FlowSolution_t',1,'DataArray_t',iff,'end') call cg_exponents_write_f(RealSingle,exponents,ier) enddo ! read grid call cg_ncoords_f(index_file,index_base,index_zone,ncoords,ier) exponents(1)=0. exponents(2)=1. exponents(3)=0. exponents(4)=0. exponents(5)=0. do icc=1,ncoords ! write DimensionalExponents call cg_goto_f(index_file,index_base,ier,'Zone_t',1, & 'GridCoordinates_t',1,'DataArray_t',icc,'end') call cg_exponents_write_f(RealSingle,exponents,ier) enddo ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote dimensional data to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_flowcent_str.F90000066400000000000000000000063661343724673500253660ustar00rootroot00000000000000 program write_flowcent_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds a flow solution (at CELL CENTERS) ! to it. (Compare this program with write_flowvert_str) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_flowcent_str.F90 ! ifort -o write_flowcent_str write_flowcent_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21-1,17-1,N-1) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 r(20,16,8),p(20,16,8) integer index_field,index_flow,index_zone,index_base,index_file,ier integer i,j,k,ni,nj,nk character solname*32 ! write(6,'('' Program write_flowcent_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! create fake flow solution AT CELL CENTERS for simple example: ni=20 nj=16 nk=8 do k=1,nk do j=1,nj do i=1,ni r(i,j,k)=float(i-1) p(i,j,k)=float(j-1) enddo enddo enddo write(6,'('' created simple 3-D rho and p flow solution'')') ! ! WRITE FLOW SOLUTION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! define flow solution node name (user can give any name) solname = 'FlowSolution' ! create flow solution node (NOTE USE OF CellCenter HERE) call cg_sol_write_f(index_file,index_base,index_zone,solname, & CellCenter,index_flow,ier) ! write flow solution (user must use SIDS-standard names here) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p,index_field,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added CellCenter flow solution data'', & '' to file grid.cgns'')') write(6,'('' Note: if the original CGNS file already had'', & '' a FlowSolution_t node,'')') write(6,'('' it has been overwritten'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_flowcentrind_str.F90000066400000000000000000000107161343724673500262350ustar00rootroot00000000000000 program write_flowcentrind_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds a flow solution (at CELL CENTERS ! PLUS RIND CELLS IN I AND J DIRECTIONS) to it. ! (Compare this program with write_flowcent_str) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_flowcentrind_str.F90 ! ifort -o write_flowcentrind_str write_flowcentrind_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21-1+2,17-1+2,N-1) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): ! Rind cells are stored in array locations (i,1,k), (i,18,k), (1,j,k), (22,j,k) real*8 r(22,18,8),p(22,18,8) integer index_file,index_base,index_zone,index_flow,index_field,ier integer i,j,k,ni,nj,nk integer irinddata(6) character solname*32 ! write(6,'('' Program write_flowcentrind_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! create fake flow solution AT CELL CENTERS for simple example: ni=20 nj=16 nk=8 do k=1,nk do j=1,nj do i=1,ni r(i+1,j+1,k)=float(i-1) p(i+1,j+1,k)=float(j-1) enddo enddo enddo ! create rind cell data: do k=1,nk do j=0,nj+1 r(1,j+1,k)=999.d0+float(j)+5.d0*float(k) p(1,j+1,k)=999.d0+float(j)+5.d0*float(k)+1.d0 r(ni+2,j+1,k)=-999.d0-float(j)-5.d0*float(k) p(ni+2,j+1,k)=-999.d0-float(j)-5.d0*float(k)-1.d0 enddo enddo do k=1,nk do i=0,ni+1 r(i+1,1,k)=888.d0+float(i)+5.d0*float(k) p(i+1,1,k)=888.d0+float(i)+5.d0*float(k)+1.d0 r(i+1,nj+2,k)=-888.d0-float(i)-5.d0*float(k) p(i+1,nj+2,k)=-888.d0-float(i)-5.d0*float(k)-1.d0 enddo enddo write(6,'('' created simple 3-D rho and p flow solution'', & '' with rind data'')') ! ! WRITE FLOW SOLUTION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! define flow solution node name (user can give any name) solname = 'FlowSolution' ! create flow solution node (NOTE USE OF CellCenter HERE) call cg_sol_write_f(index_file,index_base,index_zone,solname, & CellCenter,index_flow,ier) ! go to position within tree at FlowSolution_t node call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowSolution_t',index_flow,'end') ! write rind information under FlowSolution_t node (ilo,ihi,jlo,jhi,klo,khi) irinddata(1)=1 irinddata(2)=1 irinddata(3)=1 irinddata(4)=1 irinddata(5)=0 irinddata(6)=0 call cg_rind_write_f(irinddata,ier) ! write flow solution (user must use SIDS-standard names here) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p,index_field,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added flow solution data to file'', & '' grid.cgns'')') write(6,'('' Note: if the original CGNS file already had'', & '' a FlowSolution_t node,'')') write(6,'('' it has been overwritten'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_floweqn_str.F90000066400000000000000000000106231343724673500252070ustar00rootroot00000000000000 program write_floweqn_str use cgns implicit none ! ! Opens an existing CGNS file and writes flow eqn info ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_floweqn_str.F90 ! ifort -o write_floweqn_str write_floweqn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*4 gamma,prandtl integer idata(6) integer ieq_dim,index_zone,index_base,index_file,ier integer(cgsize_t) nuse ! write(6,'('' Program write_floweqn_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! data for writing gamma=1.4 prandtl=0.90 ! WRITE FLOW EQUATION SET INFO ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! existing file must be 3D structured (real working code would check!) ! Create 'FlowEquationSet' node under 'Zone_t' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone,'end') ! equation dimension = 3 ieq_dim=3 call cg_equationset_write_f(ieq_dim,ier) ! ! Create 'GoverningEquations' node under 'FlowEquationSet' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_governing_write_f(NSTurbulent,ier) ! Create 'DiffusionModel' node under 'GoverningEquations' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'GoverningEquations_t',1,'end') idata(1)=0 idata(2)=1 idata(3)=0 idata(4)=0 idata(5)=0 idata(6)=0 call cg_diffusion_write_f(idata,ier) ! nuse=1 ! Create 'GasModel' under 'FlowEquationSet' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_write_f('GasModel_t',Ideal,ier) ! Create 'SpecificHeatRatio' under GasModel call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'GasModel_t',1,'end') call cg_array_write_f('SpecificHeatRatio',RealSingle,1,nuse,gamma,ier) ! Create 'DataClass' under 'SpecificHeatRatio' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'GasModel_t',1,'DataArray_t',1,'end') call cg_dataclass_write_f(NondimensionalParameter,ier) ! ! Create 'TurbulenceClosure' under 'FlowEquationSet' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_write_f('TurbulenceClosure_t',EddyViscosity,ier) ! Create 'PrandtlTurbulent' under 'TurbulenceClosure' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'TurbulenceClosure_t',1,'end') call cg_array_write_f('PrandtlTurbulent',RealSingle,1,nuse,prandtl,ier) ! Create 'DataClass' under 'PrandtlTurbulent' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'TurbulenceClosure_t',1, & 'DataArray_t',1,'end') call cg_dataclass_write_f(NondimensionalParameter,ier) ! ! Create 'TurbulenceModel' under 'FlowEquationSet' call cg_goto_f(index_file,index_base,ier,'Zone_t',index_zone, & 'FlowEquationSet_t',1,'end') call cg_model_write_f('TurbulenceModel_t', & OneEquation_SpalartAllmaras,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote equation set info to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_flowvert_str.F90000066400000000000000000000063061343724673500254070ustar00rootroot00000000000000 program write_flowvert_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds a flow solution (at VERTICES) ! to it. (Compare this program with write_flowcent_str) ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_flowvert_str.F90 ! ifort -o write_flowvert_str write_flowvert_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r and p must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 r(21,17,9),p(21,17,9) integer index_field,index_flow,index_zone,index_base,ier integer index_file,i,j,k,ni,nj,nk character solname*32 ! write(6,'('' Program write_flowvert_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! create fake flow solution AT VERTICES for simple example: ni=21 nj=17 nk=9 do k=1,nk do j=1,nj do i=1,ni r(i,j,k)=float(i-1) p(i,j,k)=float(j-1) enddo enddo enddo write(6,'('' created simple 3-D rho and p flow solution'')') ! ! WRITE FLOW SOLUTION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! define flow solution node name (user can give any name) solname = 'FlowSolution' ! create flow solution node call cg_sol_write_f(index_file,index_base,index_zone,solname, & Vertex,index_flow,ier) ! write flow solution (user must use SIDS-standard names here) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p,index_field,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added Vertex flow solution data'', & '' to file grid.cgns'')') write(6,'('' Note: if the original CGNS file already had'', & '' a FlowSolution_t node,'')') write(6,'('' it has been overwritten'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_flowvert_unst.F90000066400000000000000000000060701343724673500255660ustar00rootroot00000000000000 program write_flowvert_unst use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! unstructured grid, and adds a flow solution (at VERTICES) ! to it. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_unst.f) ! Note that, other than the dimensions of the variables ! r and p, this program is essentially identical to that for ! writing flow solutions to a structured zone: ! write_flowvert_str.f ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_flowvert_unst.F90 ! ifort -o write_flowvert_unst write_flowvert_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*8 r(21*17*9),p(21*17*9) integer index_field,index_flow,index_zone,index_base,ier integer index_file,i,j,k,ni,nj,nk,iset character solname*32 ! write(6,'('' Program write_flowvert_unst'')') if (CG_BUILD_64BIT) then write(6,'('' ...compiled in 64-bit mode, but not needed'')') end if ! ! create fake flow solution AT VERTICES for simple example: ni=21 nj=17 nk=9 iset=0 do k=1,nk do j=1,nj do i=1,ni iset=iset+1 r(iset)=float(i-1) p(iset)=float(j-1) enddo enddo enddo write(6,'('' created simple 3-D rho and p flow solution'')') ! ! WRITE FLOW SOLUTION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! define flow solution node name (user can give any name) solname = 'FlowSolution' ! create flow solution node call cg_sol_write_f(index_file,index_base,index_zone,solname, & Vertex,index_flow,ier) ! write flow solution (user must use SIDS-standard names here) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p,index_field,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added flow solution data to file'', & '' grid.cgns (unstructured)'')') write(6,'('' Note: if the original CGNS file already had'', & '' a FlowSolution_t node,'')') write(6,'('' it has been overwritten'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_grid2zn_str.F90000066400000000000000000000100601343724673500251060ustar00rootroot00000000000000 program write_grid2zn_str use cgns implicit none ! ! Creates simple 3-D structured grid WITH 2 ZONES and writes ! it to a CGNS file. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_grid2zn_str.F90 ! ifort -o write_grid2zn_str write_grid2zn_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! x,y,z must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 x1(21,17,9),y1(21,17,9),z1(21,17,9) real*8 x2(21,17,9),y2(21,17,9),z2(21,17,9) integer index_coord,index_zone,index_base,ier integer iphysdim,icelldim,index_file integer i,j,k,ni,nj,nk integer(cgsize_t) isize(3,3) character basename*32,zonename*32 ! write(6,'('' Program write_grid2zn_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! create gridpoints for simple example: ni=21 nj=17 nk=9 do k=1,nk do j=1,nj do i=1,ni x1(i,j,k)=float(i-1) y1(i,j,k)=float(j-1) z1(i,j,k)=float(k-1) x2(i,j,k)=x1(i,j,k)+20.d0 y2(i,j,k)=y1(i,j,k) z2(i,j,k)=z1(i,j,k) enddo enddo enddo write(6,'('' created simple 3-D grid points (2 zones)'')') ! ! WRITE X, Y, Z GRID POINTS TO CGNS FILE ! open CGNS file for write call cg_open_f('grid.cgns',CG_MODE_WRITE,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! create base (user can give any name) basename='Base' icelldim=3 iphysdim=3 call cg_base_write_f(index_file,basename,icelldim,iphysdim,index_base,ier) ! vertex size isize(1,1)=21 isize(2,1)=17 isize(3,1)=9 ! cell size isize(1,2)=isize(1,1)-1 isize(2,2)=isize(2,1)-1 isize(3,2)=isize(3,1)-1 ! boundary vertex size (always zero for structured grids) isize(1,3)=0 isize(2,3)=0 isize(3,3)=0 ! define zone 1 name (user can give any name) zonename = 'Zone 1' ! create zone call cg_zone_write_f(index_file,index_base,zonename,isize, & Structured,index_zone,ier) ! write grid coordinates (user must use SIDS-standard names here) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateX',x1,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateY',y1,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateZ',z1,index_coord,ier) ! define zone 2 name (user can give any name) zonename = 'Zone 2' ! create zone call cg_zone_write_f(index_file,index_base,zonename,isize, & Structured,index_zone,ier) ! write grid coordinates (user must use SIDS-standard names here) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateX',x2,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateY',y2,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateZ',z2,index_coord,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote grid to file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_grid_str.F90000066400000000000000000000063131343724673500244620ustar00rootroot00000000000000 program write_grid_str use cgns implicit none ! ! Creates simple 3-D structured grid and writes it to a ! CGNS file. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_grid_str.F90 ! ifort -o write_grid_str write_grid_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! ! dimension statements (note that tri-dimensional arrays ! x,y,z must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 x(21,17,9),y(21,17,9),z(21,17,9) integer ni,nj,nk,i,j,k integer icelldim,iphysdim integer index_coord,index_file,ier integer index_base,index_zone integer(cgsize_t) isize(3,3) character basename*32,zonename*32 ! write(6,'('' Program write_grid_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! create gridpoints for simple example: ni=21 nj=17 nk=9 do k=1,nk do j=1,nj do i=1,ni x(i,j,k)=float(i-1) y(i,j,k)=float(j-1) z(i,j,k)=float(k-1) enddo enddo enddo write(6,'('' created simple 3-D grid points'')') ! ! WRITE X, Y, Z GRID POINTS TO CGNS FILE ! open CGNS file for write call cg_open_f('grid.cgns',CG_MODE_WRITE,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! create base (user can give any name) basename='Base' icelldim=3 iphysdim=3 call cg_base_write_f(index_file,basename,icelldim,iphysdim, & index_base,ier) ! define zone name (user can give any name) zonename = 'Zone 1' ! vertex size isize(1,1)=21 isize(2,1)=17 isize(3,1)=9 ! cell size isize(1,2)=isize(1,1)-1 isize(2,2)=isize(2,1)-1 isize(3,2)=isize(3,1)-1 ! boundary vertex size (always zero for structured grids) isize(1,3)=0 isize(2,3)=0 isize(3,3)=0 ! create zone call cg_zone_write_f(index_file,index_base,zonename,isize, & Structured,index_zone,ier) ! write grid coordinates (user must use SIDS-standard names here) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateX',x,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateY',y,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateZ',z,index_coord,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote grid to file grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_grid_unst.F90000066400000000000000000000207671343724673500246540ustar00rootroot00000000000000 program write_grid_unst use cgns implicit none ! ! Creates simple 3-D unstructured grid and writes it to a ! CGNS file. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_grid_unst.F90 ! ifort -o write_grid_unst write_grid_unst.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! integer, parameter :: maxelemi=20*16*8 integer, parameter :: maxelemj=1216 real*8 x(21*17*9),y(21*17*9),z(21*17*9) integer i,j,k,ifirstnode,nbdyelem,ni,nj,nk integer index_file,index_section,ielem_no integer index_base,index_zone,index_coord integer ier,iset,iphysdim,icelldim integer(cgsize_t) isize(1,3),ielem(8,maxelemi),jelem(4,maxelemj) integer(cgsize_t) nelem_start,nelem_end character basename*32,zonename*32 ! write(6,'('' Program write_grid_unst'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! create gridpoints for simple example: ni=21 nj=17 nk=9 iset=0 do k=1,nk do j=1,nj do i=1,ni iset=iset+1 x(iset)=float(i-1) y(iset)=float(j-1) z(iset)=float(k-1) enddo enddo enddo write(6,'('' created simple 3-D grid points'')') ! ! WRITE X, Y, Z GRID POINTS TO CGNS FILE ! open CGNS file for write call cg_open_f('grid.cgns',CG_MODE_WRITE,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! create base (user can give any name) basename='Base' icelldim=3 iphysdim=3 call cg_base_write_f(index_file,basename,icelldim,iphysdim,index_base,ier) ! define zone name (user can give any name) zonename = 'Zone 1' ! vertex size isize(1,1)=ni*nj*nk ! cell size isize(1,2)=(ni-1)*(nj-1)*(nk-1) ! boundary vertex size (zero if elements not sorted) isize(1,3)=0 ! create zone call cg_zone_write_f(index_file,index_base,zonename,isize, & Unstructured,index_zone,ier) ! write grid coordinates (user must use SIDS-standard names here) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateX',x,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateY',y,index_coord,ier) call cg_coord_write_f(index_file,index_base,index_zone,RealDouble, & 'CoordinateZ',z,index_coord,ier) ! set element connectivity: ! ---------------------------------------------------------- ! do all the HEXA_8 elements (this part is mandatory): ! maintain SIDS-standard ordering ielem_no=0 ! index no of first element nelem_start=1 do k=1,nk-1 do j=1,nj-1 do i=1,ni-1 ielem_no=ielem_no+1 ! in this example, due to the order in the node numbering, the ! hexahedral elements can be reconstructed using the following ! relationships: ifirstnode=i+(j-1)*ni+(k-1)*ni*nj ielem(1,ielem_no)=ifirstnode ielem(2,ielem_no)=ifirstnode+1 ielem(3,ielem_no)=ifirstnode+1+ni ielem(4,ielem_no)=ifirstnode+ni ielem(5,ielem_no)=ifirstnode+ni*nj ielem(6,ielem_no)=ifirstnode+ni*nj+1 ielem(7,ielem_no)=ifirstnode+ni*nj+1+ni ielem(8,ielem_no)=ifirstnode+ni*nj+ni enddo enddo enddo ! index no of last element (=2560) nelem_end=ielem_no if (nelem_end .gt. maxelemi) then write(6,'('' Error, must increase maxelemi to at least '', & i7)') nelem_end stop end if ! unsorted boundary elements nbdyelem=0 ! write HEXA_8 element connectivity (user can give any name) call cg_section_write_f(index_file,index_base,index_zone, & 'Elem',HEXA_8,nelem_start,nelem_end,nbdyelem,ielem, & index_section,ier) ! ---------------------------------------------------------- ! do boundary (QUAD) elements (this part is optional, ! but you must do it if you eventually want to define BCs ! at element faces rather than at nodes): ! maintain SIDS-standard ordering ! INFLOW: ielem_no=0 ! index no of first element nelem_start=nelem_end+1 i=1 do k=1,nk-1 do j=1,nj-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode jelem(2,ielem_no)=ifirstnode+ni*nj jelem(3,ielem_no)=ifirstnode+ni*nj+ni jelem(4,ielem_no)=ifirstnode+ni enddo enddo ! index no of last element nelem_end=nelem_start+ielem_no-1 if (ielem_no .gt. maxelemj) then write(6,'('' Error, must increase maxelemj to at least '', & i7)') ielem_no stop end if ! write QUAD element connectivity for inflow face (user can give any name) call cg_section_write_f(index_file,index_base,index_zone, & 'InflowElem',QUAD_4,nelem_start,nelem_end,nbdyelem, & jelem,index_section,ier) ! OUTFLOW: ielem_no=0 ! index no of first element nelem_start=nelem_end+1 i=ni-1 do k=1,nk-1 do j=1,nj-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode+1 jelem(2,ielem_no)=ifirstnode+1+ni jelem(3,ielem_no)=ifirstnode+ni*nj+1+ni jelem(4,ielem_no)=ifirstnode+ni*nj+1 enddo enddo ! index no of last element nelem_end=nelem_start+ielem_no-1 if (ielem_no .gt. maxelemj) then write(6,'('' Error, must increase maxelemj to at least '', & i7)') ielem_no stop end if ! write QUAD element connectivity for outflow face (user can give any name) call cg_section_write_f(index_file,index_base,index_zone, & 'OutflowElem',QUAD_4,nelem_start,nelem_end,nbdyelem, & jelem,index_section,ier) ! SIDEWALLS: ielem_no=0 ! index no of first element nelem_start=nelem_end+1 j=1 do k=1,nk-1 do i=1,ni-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode jelem(2,ielem_no)=ifirstnode+ni*nj jelem(3,ielem_no)=ifirstnode+ni*nj+1 jelem(4,ielem_no)=ifirstnode+1 enddo enddo j=nj-1 do k=1,nk-1 do i=1,ni-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode+1+ni jelem(2,ielem_no)=ifirstnode+ni jelem(3,ielem_no)=ifirstnode+ni*nj+ni jelem(4,ielem_no)=ifirstnode+ni*nj+1+ni enddo enddo k=1 do j=1,nj-1 do i=1,ni-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode jelem(2,ielem_no)=ifirstnode+1 jelem(3,ielem_no)=ifirstnode+1+ni jelem(4,ielem_no)=ifirstnode+ni enddo enddo k=nk-1 do j=1,nj-1 do i=1,ni-1 ielem_no=ielem_no+1 ifirstnode=i+(j-1)*ni+(k-1)*ni*nj jelem(1,ielem_no)=ifirstnode+ni*nj jelem(2,ielem_no)=ifirstnode+ni*nj+ni jelem(3,ielem_no)=ifirstnode+ni*nj+1+ni jelem(4,ielem_no)=ifirstnode+ni*nj+1 enddo enddo ! index no of last element nelem_end=nelem_start+ielem_no-1 if (ielem_no .gt. maxelemj) then write(6,'('' Error, must increase maxelemj to at least '', & i7)') ielem_no stop end if ! write QUAD element connectivity for sidewall face (user can give any name) call cg_section_write_f(index_file,index_base,index_zone, & 'SidewallElem',QUAD_4,nelem_start,nelem_end,nbdyelem, & jelem,index_section,ier) ! ---------------------------------------------------------- ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote unstructured grid to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_nondimensional.F90000066400000000000000000000115501343724673500256610ustar00rootroot00000000000000 program write_nondimensional use cgns implicit none ! ! Opens an existing CGNS file and adds the DataClass and ! ReferenceState appropriate for a completely ! NONDIMENSIONAL data set. ! ! The CGNS grid file 'grid.cgns' must already exist ! (for example, created using write_grid_str.f or ! write_grid_unst.f). In this case, the flow solution does ! not need to be present. ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_nondimensional.F90 ! ifort -o write_nondimensional write_nondimensional.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! real*8 xmach,reue,xmv,xmc,rev,rel,renu,rho0,gamma,p0,c0,vm0 real*8 xlength0,vx,vy,vz integer index_file,ier,index_base,idata integer(cgsize_t) nuse ! write(6,'('' Program write_nondimensional'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! define nondimensional parameters xmach=4.6d0 reue=6000000.d0 xmv=xmach xmc=1.d0 rev=xmach rel=1.d0 renu=xmach/reue rho0=1.d0 gamma=1.4d0 p0=1.d0/gamma c0=1.d0 vm0=xmach/reue xlength0=1.d0 vx=xmach vy=0.d0 vz=0.d0 nuse=1 ! WRITE NONDIMENSIONAL INFO ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! put DataClass under Base call cg_goto_f(index_file,index_base,ier,'end') ! check first if a dataclass has already been written call cg_dataclass_read_f(idata,ier) if (ier .eq. 0) then write(6,'('' Error! DataClass already exists!'')') write(6,'('' Re-make CGNS file without it and related info,'', & '' then try again'')') stop else ier=0 end if call cg_dataclass_write_f(NormalizedByUnknownDimensional,ier) ! put ReferenceState under Base call cg_state_write_f('ReferenceQuantities',ier) ! Go to ReferenceState node, write Mach array and its dataclass call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1,'end') call cg_array_write_f('Mach',RealDouble,1,nuse,xmach,ier) call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1, & 'DataArray_t',1,'end') call cg_dataclass_write_f(NondimensionalParameter,ier) ! Go to ReferenceState node, write Reynolds array and its dataclass call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1,'end') call cg_array_write_f('Reynolds',RealDouble,1,nuse,reue,ier) call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1, & 'DataArray_t',2,'end') call cg_dataclass_write_f(NondimensionalParameter,ier) ! Go to ReferenceState node to write reference quantities: call cg_goto_f(index_file,index_base,ier,'ReferenceState_t',1,'end') ! First, write reference quantities that make up Mach and Reynolds: ! Mach_Velocity call cg_array_write_f('Mach_Velocity',RealDouble,1,nuse,xmv,ier) ! Mach_VelocitySound call cg_array_write_f('Mach_VelocitySound',RealDouble,1,nuse,xmc,ier) ! Reynolds_Velocity call cg_array_write_f('Reynolds_Velocity',RealDouble,1,nuse,rev,ier) ! Reynolds_Length call cg_array_write_f('Reynolds_Length',RealDouble,1,nuse,rel,ier) ! Reynolds_ViscosityKinematic call cg_array_write_f('Reynolds_ViscosityKinematic',RealDouble, & 1,nuse,renu,ier) ! ! Next, write flow field reference quantities: ! Density call cg_array_write_f('Density',RealDouble,1,nuse,rho0,ier) ! Pressure call cg_array_write_f('Pressure',RealDouble,1,nuse,p0,ier) ! VelocitySound call cg_array_write_f('VelocitySound',RealDouble,1,nuse,c0,ier) ! ViscosityMolecular call cg_array_write_f('ViscosityMolecular',RealDouble,1,nuse,vm0,ier) ! LengthReference call cg_array_write_f('LengthReference',RealDouble,1,nuse,xlength0,ier) ! VelocityX call cg_array_write_f('VelocityX',RealDouble,1,nuse,vx,ier) ! VelocityY call cg_array_write_f('VelocityY',RealDouble,1,nuse,vy,ier) ! VelocityZ call cg_array_write_f('VelocityZ',RealDouble,1,nuse,vz,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully wrote nondimensional info to file'', & '' grid.cgns'')') stop end CGNS-3.4.0/src/Test_UserGuideCode/Fortran_code/write_timevert_str.F90000066400000000000000000000132531343724673500253750ustar00rootroot00000000000000 program write_timevert_str use cgns implicit none ! ! Opens an existing CGNS file that contains a simple 3-D ! structured grid, and adds 3 different flow solutions ! (at VERTICES) to it, along with time-accurate info. ! In this example, r1 & p1, r2 & p2, r3 & p3 correspond ! with solutions at 3 different time steps. ! ! The CGNS grid file 'grid.cgns' must already exist ! (created using write_grid_str.f) ! ! Example compilation for this program is (change paths if needed!): ! Note: when using the cgns module file, you must use the SAME fortran compiler ! used to compile CGNS (see make.defs file) ! ...or change, for example, via environment "setenv FC ifort" ! ! ifort -I ../.. -c write_timevert_str.F90 ! ifort -o write_timevert_str write_timevert_str.o -L ../../lib -lcgns ! ! (../../lib is the location where the compiled ! library libcgns.a is located) ! ! The following is no longer supported; now superceded by "use cgns": ! include 'cgnslib_f.h' ! Note Windows machines need to include cgnswin_f.h ! ! dimension statements (note that tri-dimensional arrays ! r1, r2, r3 and p1, p2, p3 ! must be dimensioned exactly as (21,17,N) (N>=9) ! for this particular case or else they will be written to ! the CGNS file incorrectly! Other options are to use 1-D ! arrays, use dynamic memory, or pass index values to a ! subroutine and dimension exactly there): real*8 r1(21,17,9),p1(21,17,9) real*8 r2(21,17,9),p2(21,17,9) real*8 r3(21,17,9),p3(21,17,9) real*8 time(3) integer nsteps,index_field,n,index_zone,ier,index_file integer i,j,k,ni,nj,nk,index_base,index_flow integer(cgsize_t) idata(2),nuse character solname(3)*32 ! write(6,'('' Program write_timevert_str'')') if (CG_BUILD_64BIT) then write(6,'('' ...using 64-bit mode for particular integers'')') end if ! ! set up the times corresponding to the 3 solutions to be ! stored: time(1)=10.d0 time(2)=20.d0 time(3)=50.d0 ! create fake flow solution AT VERTICES for simple example: ni=21 nj=17 nk=9 do k=1,nk do j=1,nj do i=1,ni ! soln at time 1: r1(i,j,k)=float(i-1) p1(i,j,k)=float(j-1) ! soln at time 2: r2(i,j,k)=r1(i,j,k)+1.d0 p2(i,j,k)=p1(i,j,k)+1.d0 ! soln at time 3: r3(i,j,k)=r2(i,j,k)+1.d0 p3(i,j,k)=p2(i,j,k)+1.d0 enddo enddo enddo write(6,'('' created simple 3-D rho and p flow solution'')') ! ! WRITE FLOW SOLUTION TO EXISTING CGNS FILE ! open CGNS file for modify call cg_open_f('grid.cgns',CG_MODE_MODIFY,index_file,ier) if (ier .ne. CG_OK) call cg_error_exit_f ! we know there is only one base (real working code would check!) index_base=1 ! we know there is only one zone (real working code would check!) index_zone=1 ! define 3 different solution names (user can give any names) solname(1) = 'FlowSolution1' solname(2) = 'FlowSolution2' solname(3) = 'FlowSolution3' ! do loop for the 3 solutions: do n=1,3 ! create flow solution node call cg_sol_write_f(index_file,index_base,index_zone,solname(n), & Vertex,index_flow,ier) write(6,'('' ... writing solution number '',i5)') index_flow ! write flow solution (user must use SIDS-standard names here) if (n .eq. 1) then call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r1,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p1,index_field,ier) else if (n .eq. 2) then call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r2,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p2,index_field,ier) else call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Density',r3,index_field,ier) call cg_field_write_f(index_file,index_base,index_zone,index_flow, & RealDouble,'Pressure',p3,index_field,ier) end if enddo ! create BaseIterativeData nsteps=3 call cg_biter_write_f(index_file,index_base,'TimeIterValues',nsteps,ier) ! go to BaseIterativeData level and write time values call cg_goto_f(index_file,index_base,ier,'BaseIterativeData_t',1,'end') nuse=3 call cg_array_write_f('TimeValues',RealDouble,1,nuse,time,ier) ! create ZoneIterativeData call cg_ziter_write_f(index_file,index_base,index_zone, & 'ZoneIterativeData',ier) ! go to ZoneIterativeData level and give info telling which ! flow solution corresponds with which time (solname(1) corresponds ! with time(1), solname(2) with time(2), and solname(3) with time(3)) call cg_goto_f(index_file,index_base,ier,'Zone_t', & index_zone,'ZoneIterativeData_t',1,'end') idata(1)=32 idata(2)=3 call cg_array_write_f('FlowSolutionPointers',Character,2,idata, & solname,ier) ! add SimulationType call cg_simulation_type_write_f(index_file,index_base,TimeAccurate,ier) ! close CGNS file call cg_close_f(index_file,ier) write(6,'('' Successfully added 3 times of flow solution data'', & '' and time info to file grid.cgns'')') write(6,'('' Note: if the original CGNS file already had'', & '' a FlowSolution_t node,'')') write(6,'('' it has been overwritten'')') stop end CGNS-3.4.0/src/adf/000077500000000000000000000000001343724673500136075ustar00rootroot00000000000000CGNS-3.4.0/src/adf/ADF.h000066400000000000000000000254001343724673500143530ustar00rootroot00000000000000/* ------------------------------------------------------------------------- * * CGNS - CFD General Notation System (http://www.cgns.org) * * CGNS/MLL - Mid-Level Library header file * * Please see cgnsconfig.h file for this local installation configuration * * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. * ------------------------------------------------------------------------- */ /** File: ADF.h ---------------------------------------------------------------------- BOEING ---------------------------------------------------------------------- Project: CGNS Author: Tom Dickens 865-6122 tpd6908@yak.ca.boeing.com Date: 3/2/1995 Purpose: Provide prototype declarations for the ADF-Core routines. ---------------------------------------------------------------------- ---------------------------------------------------------------------- **/ #ifndef ADF_INCLUDE #define ADF_INCLUDE #include "cgnstypes.h" #if defined(_WIN32) && defined(BUILD_DLL) # define EXTERN extern __declspec(dllexport) #else # define EXTERN extern #endif /*********************************************************************** Defines: These defines are used within the ADF core routines to specify the size in bytes of varoius items. Caution: Simply changing a define here may not correctly adjust the ADF core code. These sizes are provided for reference only! ***********************************************************************/ #define ADF_DATA_TYPE_LENGTH 32 #define ADF_DATE_LENGTH 32 #define ADF_FILENAME_LENGTH 1024 #define ADF_FORMAT_LENGTH 20 #define ADF_LABEL_LENGTH 32 #define ADF_MAXIMUM_LINK_DEPTH 100 #define ADF_MAX_DIMENSIONS 12 #define ADF_MAX_ERROR_STR_LENGTH 80 #define ADF_MAX_LINK_DATA_SIZE 4096 #define ADF_NAME_LENGTH 32 #define ADF_STATUS_LENGTH 32 #define ADF_VERSION_LENGTH 32 /*********************************************************************** Prototypes for Interface Routines ***********************************************************************/ #if defined (__cplusplus) extern "C" { #endif EXTERN void ADF_Children_Names( const double PID, const int istart, const int ilen, const int name_length, int *ilen_ret, char *names, int *error_return ) ; EXTERN void ADF_Children_IDs( const double PID, const int istart, const int ilen, int *ilen_ret, double *IDs, int *error_return ) ; EXTERN void ADF_Create( const double PID, const char *name, double *ID, int *error_return ) ; EXTERN void ADF_Database_Close( const double ID, int *error_return ) ; EXTERN void ADF_Database_Delete( const char *filename, int *error_return ) ; EXTERN void ADF_Database_Garbage_Collection( const double ID, int *error_return ) ; EXTERN void ADF_Database_Get_Format( const double Root_ID, char *format, int *error_return ) ; EXTERN void ADF_Database_Open( const char *filename, const char *status, const char *format, double *root_ID, int *error_return ) ; EXTERN void ADF_Database_Valid( const char *filename, int *error_return ) ; EXTERN void ADF_Database_Set_Format( const double Root_ID, const char *format, int *error_return ) ; EXTERN void ADF_Database_Version( const double Root_ID, char *version, char *creation_date, char *modification_date, int *error_return ) ; EXTERN void ADF_Delete( const double PID, const double ID, int *error_return ) ; EXTERN void ADF_Error_Message( const int error_return_input, char *error_string ) ; EXTERN void ADF_Flush_to_Disk( const double ID, int *error_return ) ; EXTERN void ADF_Get_Data_Type( const double ID, char *data_type, int *error_return ) ; EXTERN void ADF_Get_Dimension_Values( const double ID, cgsize_t dim_vals[], int *error_return ) ; EXTERN void ADF_Get_Error_State( int *error_state, int *error_return ) ; EXTERN void ADF_Get_Label( const double ID, char *label, int *error_return ) ; EXTERN void ADF_Get_Link_Path( const double ID, char *filename, char *link_path, int *error_return ) ; EXTERN void ADF_Get_Name( const double ID, char *name, int *error_return ) ; EXTERN void ADF_Get_Node_ID( const double PID, const char *name, double *ID, int *error_return ) ; EXTERN void ADF_Get_Number_of_Dimensions( const double ID, int *num_dims, int *error_return ) ; EXTERN void ADF_Get_Root_ID( const double ID, double *Root_ID, int *error_return ) ; EXTERN void ADF_Is_Link( const double ID, int *link_path_length, int *error_return ) ; EXTERN void ADF_Library_Version( char *version, int *error_return ) ; EXTERN void ADF_Link( const double PID, const char *name, const char *file, const char *name_in_file, double *ID, int *error_return ) ; EXTERN void ADF_Link_Size( const double ID, int *len_file, int *len_name, int *error_return ) ; EXTERN void ADF_Move_Child( const double PID, const double ID, const double NPID, int *error_return ) ; EXTERN void ADF_Number_of_Children( const double ID, int *num_children, int *error_return ) ; EXTERN void ADF_Put_Dimension_Information( const double ID, const char *data_type, const int dims, const cgsize_t dim_vals[], int *error_return ) ; EXTERN void ADF_Put_Name( const double PID, const double ID, const char *name, int *error_return ) ; EXTERN void ADF_Read_All_Data( const double ID, char *data, int *error_return ) ; EXTERN void ADF_Read_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) ; EXTERN void ADF_Read_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], char *data, int *error_return ) ; EXTERN void ADF_Set_Error_State( const int error_state, int *error_return ) ; EXTERN void ADF_Set_Label( const double ID, const char *label, int *error_return ) ; EXTERN void ADF_Write_All_Data( const double ID, const char *data, int *error_return ) ; EXTERN void ADF_Write_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) ; EXTERN void ADF_Write_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], const char *data, int *error_return ) ; #if defined (__cplusplus) } #endif #undef EXTERN /*********************************************************************** Error-return values These values need to be kept in sync with the error strings in file ADF_interface.c ***********************************************************************/ /** Don't use zero since you can assign zero to a pointer **/ #define NO_ERROR -1 #define NUMBER_LESS_THAN_MINIMUM 1 #define NUMBER_GREATER_THAN_MAXIMUM 2 #define STRING_LENGTH_ZERO 3 #define STRING_LENGTH_TOO_BIG 4 #define STRING_NOT_A_HEX_STRING 5 #define TOO_MANY_ADF_FILES_OPENED 6 #define ADF_FILE_STATUS_NOT_RECOGNIZED 7 #define FILE_OPEN_ERROR 8 #define ADF_FILE_NOT_OPENED 9 #define FILE_INDEX_OUT_OF_RANGE 10 #define BLOCK_OFFSET_OUT_OF_RANGE 11 #define NULL_STRING_POINTER 12 #define FSEEK_ERROR 13 #define FWRITE_ERROR 14 #define FREAD_ERROR 15 #define ADF_MEMORY_TAG_ERROR 16 #define ADF_DISK_TAG_ERROR 17 #define REQUESTED_NEW_FILE_EXISTS 18 #define ADF_FILE_FORMAT_NOT_RECOGNIZED 19 #define FREE_OF_ROOT_NODE 20 #define FREE_OF_FREE_CHUNK_TABLE 21 #define REQUESTED_OLD_FILE_NOT_FOUND 22 #define UNIMPLEMENTED_CODE 23 #define SUB_NODE_TABLE_ENTRIES_BAD 24 #define MEMORY_ALLOCATION_FAILED 25 #define DUPLICATE_CHILD_NAME 26 #define ZERO_DIMENSIONS 27 #define BAD_NUMBER_OF_DIMENSIONS 28 #define CHILD_NOT_OF_GIVEN_PARENT 29 #define DATA_TYPE_TOO_LONG 30 #define INVALID_DATA_TYPE 31 #define NULL_POINTER 32 #define NO_DATA 33 #define ERROR_ZEROING_OUT_MEMORY 34 #define REQUESTED_DATA_TOO_LONG 35 #define END_OUT_OF_DEFINED_RANGE 36 #define BAD_STRIDE_VALUE 37 #define MINIMUM_GT_MAXIMUM 38 #define MACHINE_FORMAT_NOT_RECOGNIZED 39 #define CANNOT_CONVERT_NATIVE_FORMAT 40 #define CONVERSION_FORMATS_EQUAL 41 #define DATA_TYPE_NOT_SUPPORTED 42 #define FILE_CLOSE_ERROR 43 #define NUMERIC_OVERFLOW 44 #define START_OUT_OF_DEFINED_RANGE 45 #define ZERO_LENGTH_VALUE 46 #define BAD_DIMENSION_VALUE 47 #define BAD_ERROR_STATE 48 #define UNEQUAL_MEMORY_AND_DISK_DIMS 49 #define LINKS_TOO_DEEP 50 #define NODE_IS_NOT_A_LINK 51 #define LINK_TARGET_NOT_THERE 52 #define LINKED_TO_FILE_NOT_THERE 53 #define NODE_ID_ZERO 54 #define INCOMPLETE_DATA 55 #define INVALID_NODE_NAME 56 #define INVALID_VERSION 57 #define NODES_NOT_IN_SAME_FILE 58 #define PRISTK_NOT_FOUND 59 #define MACHINE_FILE_INCOMPATABLE 60 #define FFLUSH_ERROR 61 #define NULL_NODEID_POINTER 62 #define MAX_FILE_SIZE_EXCEEDED 63 #define MAX_INT32_SIZE_EXCEEDED 64 #endif CGNS-3.4.0/src/adf/ADF.inc000066400000000000000000000205051343724673500146760ustar00rootroot00000000000000C C File: ADF.inc C ---------------------------------------------------------------------- C BOEING C ---------------------------------------------------------------------- C Project: CGNS C Authors: Tom Dickens 865-6122 tpd6908@yak.ca.boeing.com C Chuck Keagle 234-0990 keagle@cfdd38.cfd.ca.boeing.com C Date: 2/7/96 C Purpose: Provide FORTRAN definitions for the ADF-Core routines. C ---------------------------------------------------------------------- C ---------------------------------------------------------------------- implicit none C*********************************************************************** C Defines: These defines are used within the ADF core routines C to specify the size in bytes of varoius items. C Caution: Simply changing a define here may not correctly adjust the C ADF core code. These sizes are provided for reference only! C***********************************************************************/ integer ADF_DATA_TYPE_LENGTH integer ADF_DATE_LENGTH integer ADF_FILENAME_LENGTH integer ADF_FORMAT_LENGTH integer ADF_LABEL_LENGTH integer ADF_MAXIMUM_LINK_DEPTH integer ADF_MAX_DIMENSIONS integer ADF_MAX_ERROR_STR_LENGTH integer ADF_MAX_LINK_DATA_SIZE integer ADF_NAME_LENGTH integer ADF_STATUS_LENGTH integer ADF_VERSION_LENGTH parameter (ADF_DATA_TYPE_LENGTH = 32) parameter (ADF_DATE_LENGTH = 32 ) parameter (ADF_FILENAME_LENGTH = 1024) parameter (ADF_FORMAT_LENGTH = 20) parameter (ADF_LABEL_LENGTH = 32) parameter (ADF_MAXIMUM_LINK_DEPTH = 100) parameter (ADF_MAX_DIMENSIONS = 12) parameter (ADF_MAX_ERROR_STR_LENGTH = 80) parameter (ADF_MAX_LINK_DATA_SIZE = 4096) parameter (ADF_NAME_LENGTH = 32) parameter (ADF_STATUS_LENGTH = 32) parameter (ADF_VERSION_LENGTH = 32 ) !*********************************************************************** ! Error-return values ! These values need to be kept in sync with the error strings in ! file ADF_interface.c !*********************************************************************** ! Don't use zero since you can assign zero to a pointer integer NO_ERROR integer NUMBER_LESS_THAN_MINIMUM integer NUMBER_GREATER_THAN_MAXIMUM integer STRING_LENGTH_ZERO integer STRING_LENGTH_TOO_BIG integer STRING_NOT_A_HEX_STRING integer TOO_MANY_ADF_FILES_OPENED integer ADF_FILE_STATUS_NOT_RECOGNIZED integer FILE_OPEN_ERROR integer ADF_FILE_NOT_OPENED integer FILE_INDEX_OUT_OF_RANGE integer BLOCK_OFFSET_OUT_OF_RANGE integer NULL_STRING_POINTER integer FSEEK_ERROR integer FWRITE_ERROR integer FREAD_ERROR integer ADF_MEMORY_TAG_ERROR integer ADF_DISK_TAG_ERROR integer REQUESTED_NEW_FILE_EXISTS integer ADF_FILE_FORMAT_NOT_RECOGNIZED integer FREE_OF_ROOT_NODE integer FREE_OF_FREE_CHUNK_TABLE integer REQUESTED_OLD_FILE_NOT_FOUND integer UNIMPLEMENTED_CODE integer SUB_NODE_TABLE_ENTRIES_BAD integer MEMORY_ALLOCATION_FAILED integer DUPLICATE_CHILD_NAME integer ZERO_DIMENSIONS integer BAD_NUMBER_OF_DIMENSIONS integer CHILD_NOT_OF_GIVEN_PARENT integer DATA_TYPE_TOO_LONG integer INVALID_DATA_TYPE integer NULL_POINTER integer NO_DATA integer ERROR_ZEROING_OUT_MEMORY integer REQUESTED_DATA_TOO_LONG integer END_OUT_OF_DEFINED_RANGE integer BAD_STRIDE_VALUE integer MINIMUM_GT_MAXIMUM integer MACHINE_FORMAT_NOT_RECOGNIZED integer CANNOT_CONVERT_NATIVE_FORMAT integer CONVERSION_FORMATS_EQUAL integer DATA_TYPE_NOT_SUPPORTED integer FILE_CLOSE_ERROR integer NUMERIC_OVERFLOW integer START_OUT_OF_DEFINED_RANGE integer ZERO_LENGTH_VALUE integer BAD_DIMENSION_VALUE integer BAD_ERROR_STATE integer UNEQUAL_MEMORY_AND_DISK_DIMS integer LINKS_TOO_DEEP integer NODE_IS_NOT_A_LINK integer LINK_TARGET_NOT_THERE integer LINKED_TO_FILE_NOT_THERE integer NODE_ID_ZERO integer INCOMPLETE_DATA integer INVALID_NODE_NAME integer INVALID_VERSION integer NODES_NOT_IN_SAME_FILE integer PRISTK_NOT_FOUND integer MACHINE_FILE_INCOMPATABLE integer FFLUSH_ERROR integer NULL_NODEID_POINTER integer MAX_FILE_SIZE_EXCEEDED parameter (NO_ERROR = -1) parameter (NUMBER_LESS_THAN_MINIMUM = 1) parameter (NUMBER_GREATER_THAN_MAXIMUM = 2) parameter (STRING_LENGTH_ZERO = 3) parameter (STRING_LENGTH_TOO_BIG = 4) parameter (STRING_NOT_A_HEX_STRING = 5) parameter (TOO_MANY_ADF_FILES_OPENED = 6) parameter (ADF_FILE_STATUS_NOT_RECOGNIZED= 7) parameter (FILE_OPEN_ERROR = 8) parameter (ADF_FILE_NOT_OPENED = 9) parameter (FILE_INDEX_OUT_OF_RANGE = 10) parameter (BLOCK_OFFSET_OUT_OF_RANGE = 11) parameter (NULL_STRING_POINTER = 12) parameter (FSEEK_ERROR = 13) parameter (FWRITE_ERROR = 14) parameter (FREAD_ERROR = 15) parameter (ADF_MEMORY_TAG_ERROR = 16) parameter (ADF_DISK_TAG_ERROR = 17) parameter (REQUESTED_NEW_FILE_EXISTS = 18) parameter (ADF_FILE_FORMAT_NOT_RECOGNIZED= 19) parameter (FREE_OF_ROOT_NODE = 20) parameter (FREE_OF_FREE_CHUNK_TABLE = 21) parameter (REQUESTED_OLD_FILE_NOT_FOUND = 22) parameter (UNIMPLEMENTED_CODE = 23) parameter (SUB_NODE_TABLE_ENTRIES_BAD = 24) parameter (MEMORY_ALLOCATION_FAILED = 25) parameter (DUPLICATE_CHILD_NAME = 26) parameter (ZERO_DIMENSIONS = 27) parameter (BAD_NUMBER_OF_DIMENSIONS = 28) parameter (CHILD_NOT_OF_GIVEN_PARENT = 29) parameter (DATA_TYPE_TOO_LONG = 30) parameter (INVALID_DATA_TYPE = 31) parameter (NULL_POINTER = 32) parameter (NO_DATA = 33) parameter (ERROR_ZEROING_OUT_MEMORY = 34) parameter (REQUESTED_DATA_TOO_LONG = 35) parameter (END_OUT_OF_DEFINED_RANGE = 36) parameter (BAD_STRIDE_VALUE = 37) parameter (MINIMUM_GT_MAXIMUM = 38) parameter (MACHINE_FORMAT_NOT_RECOGNIZED = 39) parameter (CANNOT_CONVERT_NATIVE_FORMAT = 40) parameter (CONVERSION_FORMATS_EQUAL = 41) parameter (DATA_TYPE_NOT_SUPPORTED = 42) parameter (FILE_CLOSE_ERROR = 43) parameter (NUMERIC_OVERFLOW = 44) parameter (START_OUT_OF_DEFINED_RANGE = 45) parameter (ZERO_LENGTH_VALUE = 46) parameter (BAD_DIMENSION_VALUE = 47) parameter (BAD_ERROR_STATE = 48) parameter (UNEQUAL_MEMORY_AND_DISK_DIMS = 49) parameter (LINKS_TOO_DEEP = 50) parameter (NODE_IS_NOT_A_LINK = 51) parameter (LINK_TARGET_NOT_THERE = 52) parameter (LINKED_TO_FILE_NOT_THERE = 53) parameter (NODE_ID_ZERO = 54) parameter (INCOMPLETE_DATA = 55) parameter (INVALID_NODE_NAME = 56) parameter (INVALID_VERSION = 57) parameter (NODES_NOT_IN_SAME_FILE = 58) parameter (PRISTK_NOT_FOUND = 59) parameter (MACHINE_FILE_INCOMPATABLE = 60) parameter (FFLUSH_ERROR = 61) parameter (NULL_NODEID_POINTER = 62) parameter (MAX_FILE_SIZE_EXCEEDED = 63) CGNS-3.4.0/src/adf/ADF_fbind.h000066400000000000000000000075701343724673500155250ustar00rootroot00000000000000/*****************************************************************************/ /* McDonnell Douglas Corporation */ /*****************************************************************************/ /* */ /*****************************************************************************/ /* 'typedefs' and macro definitions for interfacing FORTRAN and C */ /*****************************************************************************/ #if defined(SYSTYPE) #undef SYSTYPE #endif #ifndef USE_ADF_MACROS /* use the CGNS Fortran macros */ #include "fortran_macros.h" #define SYSTYPE typedef VINTEGER Fint; typedef VFLOAT Freal; typedef VREAL Fdouble; typedef VCHARACTER *Fchar; #define F2CP(FCHAR) STR_PTR(FCHAR) #define FNAME(A,B) FMNAME(A,B) #else #if defined(__convexc__) /* Convex */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(cray) /* Cray */ #define SYSTYPE #include typedef int Fint; typedef float Freal; typedef double Fdouble; typedef _fcd Fchar; #define F2CP(FCHAR) (_fcdtocp(FCHAR)) #define FNAME(A,B) B #elif defined(__hpux) /* Hewlett Packard HP-UX */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A #elif defined(_AIX) /* IBM RS/6000 */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A #elif defined(__PARAGON__) /* Intel Paragon */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(sgi) /* Silicon Graphics */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(VMS) /* DEC VAX/VMS */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef struct dsc$descriptor_s *Fchar; #define F2CP(FCHAR) ((FCHAR)->dsc$a_pointer) #define FNAME(A,B) A #include #elif defined(__alpha) /* DEC ALPHA OSF/1 */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(PPRO) /* Pentium Pro (P6) using the Intel Reference Compiler */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A #elif defined(sun) /* Sun */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(_WIN32) /* WIN32 */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) B #elif defined(_CX_UX) /* Harris Nighthawk */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #elif defined(m88k) #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A/**/_ #elif defined(__linux__) /* LINUX on Intel */ #define SYSTYPE typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A ## _ #else typedef int Fint; typedef float Freal; typedef double Fdouble; typedef char *Fchar; #define F2CP(FCHAR) (FCHAR) #define FNAME(A,B) A #endif #endif CGNS-3.4.0/src/adf/ADF_fortran.f000066400000000000000000000637231343724673500161160ustar00rootroot00000000000000c c*********************************************************************** c R1: Get Children names of a Node. Return the name of children nodes c directly associated with a parent node. The names of the children c are NOT guaranteed to be returned in any particular order. If a c new child is added, it is NOT guaranteed to be returned as the last c child. Note: To start with the first child, use an istart value of 1. c c f77: ADFCNAM( ID, istart, inum, inamlen, inumret, names, ierr ) c input: real*8 ID. The ID of the Node to use. c input: integer istart. The Nth child's name to start with (first=1). c input: integer inum. Maximum number of names to return. c input: integer inamlen. Length of names. c output: integer inumret. The number of names returned. c output: character*(*) names Array of names. c output: integer ierr. c*********************************************************************** subroutine ADFCNAM( ID, istart, inum, inamlen, inumret, names, 1 ierr ) IMPLICIT NONE real*8 ID integer istart integer inum integer inamlen integer inumret character*(*) names integer ierr call ADFCNA2( ID, istart, inum, inamlen, len(names), inumret, 1 names, ierr ) return end c*********************************************************************** c R1: Create a Node. Create a new node (not a link-node) as a child c of a given parent. Default values in this new node are: label=blank, c number of sub-nodes = 0, data-type = "MT", number of dimensions c = 0, data = NULL. c c f77: ADFCRE( PID, name, ID, ierr ) c input: real*8 PID. The ID of the parent node, to whom we are c creating a new child node. c input: character*(*) name. c output: real*8 ID. The ID of the newly created node. c output: integer ierr. c*********************************************************************** subroutine ADFCRE( PID, name, ID, ierr ) IMPLICIT NONE real*8 PID character*(*) name real*8 ID integer ierr call ADFCRE2( PID, name, LEN( name ), ID, ierr ) return end c*********************************************************************** c R1: Close an opened database. If the ADF database spans multiple c files then all files used will also be closed. If an ADF file which c is linked to by this database is also opened through another c database, only the opened file stream associated with this database c will be closed. c c f77: ADFDCLO( RootID, ierr ) c input: real*8 RootID Root ID of the database. c output: integer ierr. c*********************************************************************** subroutine ADFDCLO( RootID, ierr ) IMPLICIT NONE real*8 RootID integer ierr call ADFDCL2( RootID, ierr ) return end c*********************************************************************** c Rn: Delete an existing database. This will delete one or more ADF c files which are linked together under file top ADF file named c "filename". c c f77: ADFDDEL( filename, ierr ) c input: character*(*) filename c output: integer ierr. c*********************************************************************** subroutine ADFDDEL( filename, ierr ) IMPLICIT NONE character*(*) filename integer ierr call ADFDDE2( filename, LEN( filename ), ierr ) return end c*********************************************************************** c R2: Delete a Node. If the node is NOT a link, then the specified c node and all c sub-nodes anywhere under it are also deleted. For a link, and also c for links farther down in the tree, the link-node will be deleted, c but the node which the link is linked to is not affected. When a c node is deleted, other link-nodes which point to it are left c dangling. For example, if N13 is deleted, then L1 and L2 point to a c non-existing node. This is OK until L1 and L2 are used. c c f77: ADFDEL( PID, ID, ierr ) c input: real*8 PID. The ID of the node's parent. c input: real*8 ID. The ID of the node to use. c output: integer ierr. c*********************************************************************** subroutine ADFDEL( PID, ID, ierr ) IMPLICIT NONE real*8 PID real*8 ID integer ierr call ADFDEL2( PID, ID, ierr ) return end c*********************************************************************** c Rn: Garbage Collection. Redistribute data in the file to use free- c space which is not located at the end of the file. Neighboring free c spaces will be merged. Note: For better file compaction a utility c could be written to copy an ADF file, creating a new ADF file c without any wasted space. c c f77: ADFDGC( ID, ierr ) c input: real*8 ID. The ID of a node in the ADF file in which to do c garbage collection. c output: integer ierr. c*********************************************************************** subroutine ADFDGC( ID, ierr ) IMPLICIT NONE real*8 ID integer ierr call ADFDGC2( ID, ierr ) return end c*********************************************************************** c R1: Get the data format used in an existing database. c c f77: ADFDGF( RootID, format, ierr ) c input: real*8 RootID The rootID of the ADF file. c output: character*20 format. See format for ADFDOPN. c output: integer ierr. c*********************************************************************** subroutine ADFDGF( RootID, format, ierr ) IMPLICIT NONE real*8 RootID character*(*) format integer ierr call ADFDGF2( RootID, format, LEN( format ), ierr ) return end c*********************************************************************** c R1: Open a database. Open either a new or an existing ADF file. c If links to other ADF files are used, these additional files will be c opened automatically as required. c c f77: ADFDOPN( filename, status, format, rootID, ierr) c input: character*(*) filename. Not used if status SCRATCH is c used. Filename must be a legal name and may c include a relative or absolute path. It must be c directly usable by the C fopen() system c routine (no environment expansion is done). c input: character*(*) status. Like FORTRAN OPEN() status. c This field is required. Allowable values are: c READ_ONLY - File must exist. Writing NOT allowed. c OLD - File must exist. Reading and writing allowed. c NEW - File must not exist. c SCRATCH - New file. Filename is ignored. c UNKNOWN - OLD if file exists, else NEW is used. c input: character*(*) format. Specifies the numeric format for c the file. If blank, the machine's native c format is used. This field is only used when a c file is created. c NATIVE - Determine the format on the machine. If the c native format is not one of the formats c supported, the created file cannot be used on c other machines. c IEEE_BIG - Use the IEEE big ENDIAN format. c IEEE_LITTLE - Use the IEEE little ENDIAN format. c CRAY - Use the native Cray format. c output: real*8 rootID c output: integer ierr. c*********************************************************************** subroutine ADFDOPN( filename, status, format, rootID, ierr) IMPLICIT NONE character*(*) filename character*(*) status character*(*) format real*8 rootID integer ierr call ADFDOP2( filename, len( filename ), status, len( status ), 1 format, len( format ), rootID, ierr ) return end c*********************************************************************** c R1: Set the data format used in an existing database. c Note: Use with extreme caution. Needed only c for data conversion utilities and NOT intended c for the general user!!! c c f77: ADFDSF( RootID, format, ierr ) c input: real*8 RootID The rootID if the ADF file. c input: character*(*) format. See format for ADFDOPN. c output: integer ierr. c*********************************************************************** subroutine ADFDSF( RootID, format, ierr ) IMPLICIT NONE real*8 RootID character*(*) format integer ierr call ADFDSF2( RootID, format, len( format ), ierr ) return end c*********************************************************************** c R1: Get ADF File Version ID. This is the version number of the ADF c library routines which created an ADF database. Modified ADF databases c will take on the version ID of the current ADF library version if c it is higher than the version indicated in the file. c The format of the version ID is: "ADF Database Version 000.01" c c f77: ADFDVER( RootID, version, cdate, mdate, ierr ) c input: real*8 RootID. The ID of the root node in the ADF file. c output: character(32) version. A 32-byte character string c containing the version ID. c output: character(32) cdate. A 32-byte character string c containing the creation date of the file. c output: character(32) mdate. A 32-byte character c string containing the last modification date of the file. c output: integer ierr. c*********************************************************************** subroutine ADFDVER( RootID, version, cdate, mdate, ierr ) IMPLICIT NONE real*8 RootID character*(*) version character*(*) cdate character*(*) mdate integer ierr call ADFDVE2( RootID, version, cdate, mdate, 1 len( version ), len( cdate ), len( mdate ), ierr ) return end c*********************************************************************** c R1: Return Error Message. Given an ierr from an ADF routine, c get a textual description of the error. c c f77: ADFERR( ierr, errstr ) c input: integer ierr. c output: character(80) errstr. An 80-byte description of c the specified error. If the number is bad, the c string "Unknown error #nnn" is returned. c*********************************************************************** subroutine ADFERR( ierr, errstr ) IMPLICIT NONE integer ierr character*(*) errstr call ADFERR2( ierr, errstr, len( errstr ) ) return end c*********************************************************************** c R1: Flush data to disk. This routine is used to force any modified c information to be flushed to the physical disk. This ensures that c data will not be lost if a program aborts. This control of when to c flush all data to disk is provided to the user rather than to flush c the data every time it is modified, which would result in reduced c performance. c c f77: ADFFTD( ID, ierr ) c input: real*8 ID. The ID of a node in the ADF file in which to flush. c output: integer ierr. c*********************************************************************** subroutine ADFFTD( ID, ierr ) IMPLICIT NONE real*8 ID integer ierr call ADFFTD2( ID, ierr ) return end c*********************************************************************** c R1: Get Data Type. Return the 32 character string in a node's data- c type field. In C, the data-type will be null terminated after the last c non-blank character. A maximum of 33 characters may be used c (32 for the data-type plus 1 for the null). c c f77: ADFGDT( ID, dtype, ierr ) c input: real*8 ID. The ID of the node to use. c output: character*(*) dtype. The 32-character data-type of the node. c output: integer ierr. c*********************************************************************** subroutine ADFGDT( ID, dtype, ierr ) IMPLICIT NONE real*8 ID character*(*) dtype integer ierr call ADFGDT2( ID, dtype, len( dtype ), ierr ) return end c*********************************************************************** c R1: Get Dimension Values. Return the dimension values for a node. c Values will only be returned for the number of dimensions defined in c the node. If the number of dimensions for the node is zero, an c error is returned. c c f77: ADFGDV( ID, dvals, ierr ) c input: real*8 ID. The ID of the node to use. c output: integer dvals(12). c output: integer ierr. c*********************************************************************** subroutine ADFGDV( ID, dvals, ierr ) IMPLICIT NONE real*8 ID integer dvals(12) integer ierr call ADFGDV2( ID, dvals, ierr ) return end c*********************************************************************** c R1 Get Error State. Return the active error state. c c f77: ADFGES( estate, ierr ) c output: integer estate. Flag for ABORT on error (1) or return c error status (0). Set on a per database basis. c output: integer ierr. c*********************************************************************** subroutine ADFGES( estate, ierr ) IMPLICIT NONE integer estate integer ierr call ADFGES2( estate, ierr ) return end c*********************************************************************** c R1: Get Label. Return the 32 character string in a node's label field. c In C, the label will be null terminated after the last non-blank c character. A maximum of 33 characters may be used (32 for the c label plus 1 for the null). c c f77: ADFGLB( ID, label, ierr ) c input: real*8 ID. The ID of the node to use. c output: character*(*) label. The 32-character label of the node. c output: integer ierr. c*********************************************************************** subroutine ADFGLB( ID, label, ierr ) IMPLICIT NONE real*8 ID character*(*) label integer ierr call ADFGLB2( ID, label, len( label ), ierr ) return end c*********************************************************************** c R1: Get path information from a link. If the node is a link-node, c return the path information. Else, return an error. c If the link is in the same file, then a blank filename is returned. c c f77: ADFGLKP( ID, file, name, ierr ) c input: real*8 ID. The ID of the node to use. c output: character*(*) file. The filename. c output: character*(*) name. The name of node. c output: integer ierr. c*********************************************************************** subroutine ADFGLKP( ID, file, name, ierr ) IMPLICIT NONE real*8 ID character*(*) file character*(*) name integer ierr call ADFGLK2( ID, file, len( file ), name, len( name ), ierr ) return end c*********************************************************************** c R1: Get Name of a Node. Given a node's ID, return the 32 character c name of that node. In C, the name will be null terminated after the c last non-blank character. A maximum of 33 characters may be used c (32 for the name plus 1 for the null). c c f77: ADFGNAM( ID, name, ierr ) c input: real*8 ID. The ID of the node to use. c output: character*(*) name. The simple name of the node. c output: integer ierr. c*********************************************************************** subroutine ADFGNAM( ID, name, ierr ) IMPLICIT NONE real*8 ID character*(*) name integer ierr call ADFGNA2( ID, name, len( name ), ierr ) return end c*********************************************************************** c R1: Get Number of Dimensions. Return the number of data dimensions c used in a node. Valid values are from 0 to 12. c c f77: ADFGND( ID, ndims, ierr ) c input: real*8 ID. The ID of the node to use. c output: integer ndims. c output: integer ierr. c*********************************************************************** subroutine ADFGND( ID, ndims, ierr ) IMPLICIT NONE real*8 ID integer ndims integer ierr call ADFGND2( ID, ndims, ierr ) return end c*********************************************************************** c R1: Get Unique-Identifier of a Node. Given a parent node ID and a c a name of child node, return the ID of the child. To return the ID c of the root-node in an ADF file, use any known ID in the ADF file c and a name of "/". c c f77: ADFGNID( PID, name, ID, ierr ) c input: real*8 PID. The ID of the Node's parent. c input: character*(*) name. The name of the node. Compound c names including path information use a slash c "/" notation between node names. If a c leading slash is used, then PID can be any c valid node ID in the ADF database. c output: real*8 ID. The ID of the named node. c output: integer ierr. c*********************************************************************** subroutine ADFGNID( PID, name, ID, ierr ) IMPLICIT NONE real*8 PID character*(*) name real*8 ID integer ierr call ADFGNI2( PID, name, len( name ), ID, ierr ) return end c*********************************************************************** c R1: Get root-ID for an ADF system from any ID in the system. c c f77: ADFGRID( ID, RootID, ierr ) c input: real*8 ID. The ID of the node to use. c output: real*8 RootID. The ID of the root node. c output: integer ierr. c*********************************************************************** subroutine ADFGRID( ID, RootID, ierr ) IMPLICIT NONE real*8 ID real*8 RootID integer ierr call ADFGRI2( ID, RootID, ierr ) return end c*********************************************************************** c R1: Test if a Node is a link. If the actual data-type of the node c is "LK" (created with ADF_Link), return the link path length. c Otherwise, return 0. c c f77: ADFISLK( ID, lplen, ierr ) c input: real*8 ID. The ID of the node to use. c input: integer lplen. 0 if the node is NOT a link. If c the node is a link, the length of the path string is returned. c output: integer ierr. c*********************************************************************** subroutine ADFISLK( ID, lplen, ierr ) IMPLICIT NONE real*8 ID integer lplen integer ierr call ADFISL2( ID, lplen, ierr ) return end c*********************************************************************** c R1: Create a link. Note: The Node linked to does not have to exist c when the link is created (but it may exist and that is OK). However, c when the link is used, an error will occur if the linked to node does c not exist. c c f77: ADFLINK( PID, name, file, nfile, ID, ierr ) c input: real*8 PID. The ID of the Node's parent. c input: character*(*) name. The name of the link node. c input: character*(*) file. The filename to use for the link c (directly usable by a C open() routine). If c blank (null), the link will be within the same file. c input: character*(*) nfile. The name of the node which c the link will point to. This can be a simple or c compound name. c output: real*8 ID. The ID of the link-node. c output: integer ierr. c*********************************************************************** subroutine ADFLINK( PID, name, file, nfile, ID, ierr ) IMPLICIT NONE real*8 PID character*(*) name character*(*) file character*(*) nfile real*8 ID integer ierr call ADFLIN2( PID, name, file, nfile, len( name ), 1 len( file ), len( nfile ), ID, ierr ) return end c*********************************************************************** c R1: Get ADF Library Version ID. This is the version number of the c ADF library routines which your program is currently using. c The format of the version ID is: "ADF Library Version 000.01" c Note: There is a double space between Library and Version. This c lines up the number with the Database Version string. c c f77: ADFLVER( version, ierr ) c output: character(32) version. A 32-byte character string c containing the ADF Library version ID information. c output: integer ierr. c*********************************************************************** subroutine ADFLVER( version, ierr ) IMPLICIT NONE character*(*) version integer ierr call ADFLVE2( version, len( version ), ierr ) return end c*********************************************************************** c R2: Change Parent (move a Child Node). The node and the 2 parents c must all exist within a single ADF file. If the node is pointed to c by a link-node, changing the node's parent will break the link. c c f77: ADFMOVE( PID, ID, NPID, ierr ) c input: real*8 PID. The ID of the Node's parent. c input: real*8 ID. The ID of the node to use. c input: real*8 NPID. The ID of the Node's New Parent c output: integer ierr. c*********************************************************************** subroutine ADFMOVE( PID, ID, NPID, ierr ) IMPLICIT NONE real*8 PID real*8 ID real*8 NPID integer ierr call ADFMOV2( PID, ID, NPID, ierr ) return end c*********************************************************************** c R1: Get Number of Children of a Node. Return the number of children c nodes directly associated with a parent node. c c f77: ADFNCLD( ID, numcld, ierr ) c input: real*8 ID. The ID of the node to use. c output: integer numcld. The number of children directly c associated with this node. c output: integer ierr. c*********************************************************************** subroutine ADFNCLD( ID, numcld, ierr ) IMPLICIT NONE real*8 ID integer numcld integer ierr call ADFNCL2( ID, numcld, ierr ) return end c*********************************************************************** c R1: Set/change the data-type and Dimension Information of a Node. c Valid user-definable data-types are: c c No data MT c Integer 32 I4 c Integer 64 I8 c Unsigned Int 32 U4 c Unsigned Int 64 U8 c Real 32 R4 c Real 64 R8 c Complex 64 X4 c Complex 128 X8 c Character (unsigned byte) C1 c Byte (unsigned byte) B1 c Compound data-types can be used which combine types c ("I4,I4,R8"), define an array ("I4[25]"), or a combination of these c ("I4,C1[20],R8[3]"). c dims can be a number from 0 to 12. c dim_vals is an array of integers. The number of integers used is c determined by the dims argument. If dims is zero, the dim_values c are not used. Valid range for dim_values are from 1 to c 2,147,483,648. The total data size, calculated by the data-type-size c times the dimension value(s), cannot exceed 2,147,483,648. c Note: When this routine is called and the data-type or the c number of dimensions changes, any data currently associated c with the node is lost!! The dimension values can be changed and c the data space will be extended as needed. c- c f77: ADFPDIM( ID, dtype, dims, dvals, ierr) c input: real*8 ID. The ID of the node. c input: character*(*) dtype. c input: integer dims. The number of dimensions this node has. c input: integer dvals(12). The dimension values for this node. c output: integer ierr. c*********************************************************************** subroutine ADFPDIM( ID, dtype, dims, dvals, ierr) IMPLICIT NONE real*8 ID character*(*) dtype integer dims integer dvals(12) integer ierr call ADFPDI2( ID, dtype, len( dtype ), dims, dvals, ierr) return end c*********************************************************************** c R2: Put (change) Name of a Node. Warning: If the node is pointed c to by a link-node, changing the node's name will break the link. c c f77: ADFPNAM( PID, ID, name, ierr ) c input: real*8 PID. The ID of the Node's parent. c input: real*8 ID. The ID of the node to use. c input: character*(*) name. The new name of the node. c output: integer ierr. c*********************************************************************** subroutine ADFPNAM( PID, ID, name, ierr ) IMPLICIT NONE real*8 PID real*8 ID character*(*) name integer ierr call ADFPNA2( PID, ID, name, len( name ), ierr ) return end c*********************************************************************** c R1 Set Error State. For all ADF calls, set the error handling c convention; either return error codes, or abort the program on an error. c The default state for the ADF interface is to return error codes and NOT c abort. c c f77: ADFSES( estate, ierr ) c input: integer estate. Flag for ABORT on error (1) or return c error status (0). Set on a per database basis. c output: integer ierr. c*********************************************************************** subroutine ADFSES( estate, ierr ) IMPLICIT NONE integer estate integer ierr call ADFSES2( estate, ierr ) return end c*********************************************************************** c R1: Set Label. Set the 32 character string in a node's label field. c c f77: ADFSLB( ID, label, ierr ) c input: real*8 ID. The ID of the node to use. c input: character*(*) label. The 32-character label of the node. c output: integer ierr. c*********************************************************************** subroutine ADFSLB( ID, label, ierr ) IMPLICIT NONE real*8 ID character*(*) label integer ierr call ADFSLB2( ID, label, len( label ), ierr ) return end CGNS-3.4.0/src/adf/ADF_fortran_2_c.c000066400000000000000000001104331343724673500166250ustar00rootroot00000000000000/* created by combine 2.0 */ /* file ADFAAA2.c */ /*********************************************************************** ADF Core: Glue routines between the FORTRAN interface and the C interface. ***********************************************************************/ #include #include #include #include "ADF.h" #include "ADF_internals.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif /* end of file ADFAAA2.c */ /* file ADFCNA2.c */ /*********************************************************************** ADFCNAM ADF_Children_Names: ***********************************************************************/ void FNAME(adfcna2,ADFCNA2)( const Fdouble *PID, const Fint *istart, const Fint *imaxnum, const Fint *idim, const Fint *name_length, Fint *inum_ret, Fchar names, Fint *error_return ) { int i; char *pstr, *tmp_names; if( *idim != *name_length ) { /** inconsistency **/ *error_return = BAD_DIMENSION_VALUE ; /** not really what this error code was meant for but it might do **/ return ; } /* end if */ pstr = F2CP(names); tmp_names = (char *) malloc( (*imaxnum) * (*name_length + 1) * (sizeof(char)) ) ; if( tmp_names == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ ADF_Children_Names( *PID, *istart, *imaxnum, *name_length, inum_ret, tmp_names, error_return ) ; if( *error_return != NO_ERROR ) { free( tmp_names ) ; return ; } /* end if */ for( i=0; i<*inum_ret; i++ ) { /* Blank-fill the names */ if( strlen( &tmp_names[ i * (*name_length+1) ]) == *name_length ) { /** string is maximum length, do not null terminate or blank fill **/ strncpy( &pstr[ i * (*name_length) ], &tmp_names[ i * (*name_length+1) ], *name_length ) ; } else { /** string is short enough, blank fill remainder **/ strcpy( &pstr[ i * (*name_length) ], &tmp_names[ i * (*name_length+1) ] ) ; ADFI_blank_fill_string( &pstr[ i * (*name_length) ], *name_length ) ; } /* end if */ } /* end for */ free( tmp_names ) ; } /* end of file ADFCNA2.c */ /* file ADFCID2.c */ /*********************************************************************** ADFCNAM ADF_Children_IDs: ***********************************************************************/ void FNAME(adfcid2,ADFCID2)( const Fdouble *PID, const Fint *istart, const Fint *imaxnum, Fint *inum_ret, Fdouble *CIDs, Fint *error_return ) { ADF_Children_IDs( *PID, *istart, *imaxnum, inum_ret, CIDs, error_return ) ; } /* end of file ADFCID2.c */ /* file ADFCRE2.c */ /*********************************************************************** ADFCRE ADF_Create: ***********************************************************************/ void FNAME(adfcre2,ADFCRE2)( const Fdouble *PID, const Fchar name, const Fint *name_length, Fdouble *ID, Fint *error_return ) { char c_name[ ADF_NAME_LENGTH + 1 ] ; ADFI_string_2_C_string( F2CP(name), MIN(ADF_NAME_LENGTH, *name_length), c_name, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Create( *PID, c_name, ID, error_return ) ; } /* end of file ADFCRE2.c */ /* file ADFDCL2.c */ /*********************************************************************** ADFDCLO ADF_Database_Close: ***********************************************************************/ void FNAME(adfdcl2,ADFDCL2)( const Fdouble *Root_ID, Fint *error_return ) { ADF_Database_Close( *Root_ID, error_return ) ; } /* end of file ADFDCL2.c */ /* file ADFDDE2.c */ /*********************************************************************** ADFDDEL ADF_Database_Delete: ***********************************************************************/ void FNAME(adfdde2,ADFDDE2)( const Fchar filename, const Fint *name_length, Fint *error_return ) { char c_name[ ADF_FILENAME_LENGTH + 1 ] ; ADFI_string_2_C_string( F2CP(filename), MIN(ADF_FILENAME_LENGTH, *name_length), c_name, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Database_Delete( c_name, error_return ) ; } /* end of file ADFDDE2.c */ /* file ADFDEL2.c */ /*********************************************************************** ADFDEL ADF_Delete: ***********************************************************************/ void FNAME(adfdel2,ADFDEL2)( const Fdouble *PID, const Fdouble *ID, Fint *error_return ) { ADF_Delete( *PID, *ID, error_return ) ; } /* end of file ADFDEL2.c */ /* file ADFDGC2.c */ /*********************************************************************** ADFDGC ADF_Database_Garbage_Collection: ***********************************************************************/ void FNAME(adfdgc2,ADFDGC2)( const Fdouble *ID, Fint *error_return ) { ADF_Database_Garbage_Collection( *ID, error_return ) ; } /* end of file ADFDGC2.c */ /* file ADFDGF2.c */ /*********************************************************************** ADFDGF ADF_Database_Get_Format: ***********************************************************************/ void FNAME(adfdgf2,ADFDGF2)( const Fdouble *Root_ID, Fchar format, const Fint *format_length, Fint *error_return ) { ADF_Database_Get_Format( *Root_ID, F2CP(format), error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_blank_fill_string( F2CP(format), *format_length ) ; } /* end of file ADFDGF2.c */ /* file ADFDOP2.c */ /*********************************************************************** ADFDOPN ADF_Database_Open: ***********************************************************************/ void FNAME(adfdop2,ADFDOP2)( const Fchar filename, const Fint *filename_length, Fchar status_in, const Fint *status_length, const Fchar format, const Fint *format_length, Fdouble *Root_ID, Fint *error_return ) { char c_filename[ ADF_FILENAME_LENGTH + 1 ], c_status[ ADF_NAME_LENGTH+1 ], c_format[ ADF_NAME_LENGTH+1 ] ; ADFI_string_2_C_string( F2CP(filename), MIN(ADF_FILENAME_LENGTH, *filename_length), c_filename, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_string_2_C_string( F2CP(status_in), MIN(ADF_NAME_LENGTH, *status_length), c_status, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_string_2_C_string( F2CP(format), MIN(ADF_NAME_LENGTH, *format_length), c_format, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Database_Open( c_filename, c_status, c_format, Root_ID, error_return ) ; } /* end of file ADFDOP2.c */ /* file ADFDSF2.c */ /*********************************************************************** ADFDSF ADF_Database_Set_Format: ***********************************************************************/ void FNAME(adfdsf2,ADFDSF2)( const Fdouble *Root_ID, const Fchar format, const Fint *format_length, Fint *error_return ) { char c_format[ ADF_NAME_LENGTH + 1 ] ; ADFI_string_2_C_string( F2CP(format), MIN(ADF_NAME_LENGTH, *format_length), c_format, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Database_Set_Format( *Root_ID, c_format, error_return ) ; } /* end of file ADFDSF2.c */ /* file ADFDVE2.c */ /*********************************************************************** ADVDVER ADF_Database_Version: ***********************************************************************/ void FNAME(adfdve2,ADFDVE2)( const Fdouble *Root_ID, Fchar version, Fchar creation_date, Fchar modification_date, const Fint *v_length, const Fint *c_length, const Fint *m_length, Fint *error_return ) { ADF_Database_Version( *Root_ID, F2CP(version), F2CP(creation_date), F2CP(modification_date), error_return ) ; ADFI_blank_fill_string( F2CP(version), *v_length ) ; ADFI_blank_fill_string( F2CP(creation_date), *c_length ) ; ADFI_blank_fill_string( F2CP(modification_date), *m_length ) ; } /* end of file ADFDVE2.c */ /* file ADFERR2.c */ /*********************************************************************** ADFERR ADF_Error_Message: ***********************************************************************/ void FNAME(adferr2,ADFERR2)( const Fint *error_return_input, Fchar error_string, const Fint *str_length ) { char msg_buf[ADF_MAX_ERROR_STR_LENGTH+1] ; ADF_Error_Message( *error_return_input, msg_buf ) ; strncpy( F2CP(error_string), msg_buf, *str_length ) ; ADFI_blank_fill_string( F2CP(error_string), *str_length ) ; } /* end of file ADFERR2.c */ /* file ADFFTD2.c */ /*********************************************************************** ADFFTD ADF_Flush_to_Disk: ***********************************************************************/ void FNAME(adfftd2,ADFFTD2)( const Fdouble *ID, Fint *error_return ) { ADF_Flush_to_Disk( *ID, error_return ) ; } /* end of file ADFFTD2.c */ /* file ADFGDT2.c */ /*********************************************************************** ADFGDT ADF_Get_Data_Type: ***********************************************************************/ void FNAME(adfgdt2,ADFGDT2)( const Fdouble *ID, Fchar data_type, const Fint *data_type_length, Fint *error_return ) { char ctype[ ADF_DATA_TYPE_LENGTH + 1 ] ; ADF_Get_Data_Type( *ID, ctype, error_return ) ; if( *error_return == NO_ERROR ) { if( strlen( ctype ) < *data_type_length ) { strcpy( F2CP(data_type), ctype ) ; ADFI_blank_fill_string( F2CP(data_type), *data_type_length ) ; } else { strncpy( F2CP(data_type), ctype, *data_type_length ) ; } /* end if */ } /* end if */ } /* end of file ADFGDT2.c */ /* file ADFGDV2.c */ /*********************************************************************** ADFGDV ADF_Get_Dimension_Values: ***********************************************************************/ void FNAME(adfgdv2,ADFGDV2)( const Fdouble *ID, Fint dim_vals[], Fint *error_return ) { ADF_Get_Dimension_Values( *ID, dim_vals, error_return ) ; } /* end of file ADFGDV2.c */ /* file ADFGES2.c */ /*********************************************************************** ADFGES ADF_Get_Error_State: ***********************************************************************/ void FNAME(adfges2,ADFGES2)( Fint *error_state, Fint *error_return ) { ADF_Get_Error_State( error_state, error_return ) ; } /* end of file ADFGES2.c */ /* file ADFGLB2.c */ /*********************************************************************** ADFGLB ADF_Get_Label: ***********************************************************************/ void FNAME(adfglb2,ADFGLB2)( const Fdouble *ID, Fchar label, const Fint *label_length, Fint *error_return ) { char clabel[ ADF_LABEL_LENGTH + 1 ] ; ADF_Get_Label( *ID, clabel, error_return ) ; if( *error_return == NO_ERROR ) { if( strlen( clabel ) < *label_length ) { strcpy( F2CP(label), clabel ) ; ADFI_blank_fill_string( F2CP(label), *label_length ) ; } else { strncpy( F2CP(label), clabel, *label_length ) ; } /* end if */ } /* end if */ } /* end of file ADFGLB2.c */ /* file ADFGLK2.c */ /*********************************************************************** ADFGLKP ADF_Get_Link_Path: ***********************************************************************/ void FNAME(adfglk2,ADFGLK2)( const Fdouble *ID, Fchar filename, const Fint *filename_length, Fchar link_path, const Fint *link_path_length, Fint *error_return ) { char cpath[ ADF_MAX_LINK_DATA_SIZE + 1 ], cfilename[ ADF_FILENAME_LENGTH + 1 ] ; ADF_Get_Link_Path( *ID, cfilename, cpath, error_return ) ; if( *error_return == NO_ERROR ) { if( strlen(cfilename) < *filename_length ) { strcpy( F2CP(filename), cfilename ) ; ADFI_blank_fill_string( F2CP(filename), *filename_length ) ; } else { strncpy( F2CP(filename), cfilename, *filename_length ) ; } /* end if */ if( strlen(cpath) < *link_path_length ) { strcpy( F2CP(link_path), cpath ) ; ADFI_blank_fill_string( F2CP(link_path), *link_path_length ) ; } else { strncpy( F2CP(link_path), cpath, *link_path_length ) ; } /* end if */ } /* end if */ } /* end of file ADFGLK2.c */ /* file ADFGNA2.c */ /*********************************************************************** ADFGNAM ADF_Get_Name: ***********************************************************************/ void FNAME(adfgna2,ADFGNA2)( const Fdouble *ID, Fchar name, const Fint *name_length, Fint *error_return ) { char cname[ ADF_NAME_LENGTH + 1 ] ; ADF_Get_Name( *ID, cname, error_return ) ; if( *error_return == NO_ERROR ) { if( strlen( cname ) < *name_length ) { strcpy( F2CP(name), cname ) ; ADFI_blank_fill_string( F2CP(name), *name_length ) ; } else { strncpy( F2CP(name), cname, *name_length ) ; } /* end if */ } /* end if */ } /* end of file ADFGNA2.c */ /* file ADFGND2.c */ /*********************************************************************** ADFGND ADF_Get_Number_of_Dimensions: ***********************************************************************/ void FNAME(adfgnd2,ADFGND2)( const Fdouble *ID, Fint *num_dims, Fint *error_return ) { ADF_Get_Number_of_Dimensions( *ID, num_dims, error_return ) ; } /* end of file ADFGND2.c */ /* file ADFGNI2.c */ /*********************************************************************** ADFGNID ADF_Get_Node_ID: ***********************************************************************/ void FNAME(adfgni2,ADFGNI2)( const Fdouble *PID, const Fchar name, const Fint *name_length, Fdouble *ID, Fint *error_return ) { char c_name[ ADF_FILENAME_LENGTH + 1 ] ; ADFI_string_2_C_string( F2CP(name), MIN(ADF_FILENAME_LENGTH, *name_length), c_name, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Get_Node_ID( *PID, c_name, ID, error_return ) ; } /* end of file ADFGNI2.c */ /* file ADFGRI2.c */ /*********************************************************************** ADFGRID ADF_Get_Root_ID: ***********************************************************************/ void FNAME(adfgri2,ADFGRI2)( const Fdouble *ID, Fdouble *Root_ID, Fint *error_return ) { ADF_Get_Root_ID( *ID, Root_ID, error_return ) ; } /* end of file ADFGRI2.c */ /* file ADFISL2.c */ /*********************************************************************** ADFISLK ADF_Is_Link: ***********************************************************************/ void FNAME(adfisl2,ADFISL2)( const Fdouble *ID, Fint *link_path_length, Fint *error_return ) { ADF_Is_Link( *ID, link_path_length, error_return ) ; } /* end of file ADFISL2.c */ /* file ADFLIN2.c */ /*********************************************************************** ADFLINK ADF_Link: ***********************************************************************/ void FNAME(adflin2,ADFLIN2)( const Fdouble *PID, const Fchar name, const Fchar file, const Fchar name_in_file, const Fint *name_length, const Fint *file_length, const Fint *nfile_length, Fdouble *ID, Fint *error_return ) { char c_name[ ADF_FILENAME_LENGTH + 1 ], c_file[ ADF_FILENAME_LENGTH + 1 ], c_nfile[ ADF_MAX_LINK_DATA_SIZE + 1 ] ; ADFI_string_2_C_string( F2CP(name), MIN(ADF_FILENAME_LENGTH, *name_length), c_name, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_string_2_C_string( F2CP(file), MIN(ADF_FILENAME_LENGTH, *file_length), c_file, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_string_2_C_string( F2CP(name_in_file), MIN(ADF_MAX_LINK_DATA_SIZE, *nfile_length), c_nfile, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Link( *PID, c_name, c_file, c_nfile, ID, error_return ) ; } /* end of file ADFLIN2.c */ /* file ADFLVE2.c */ /*********************************************************************** ADFLVER ADF_Library_Version: ***********************************************************************/ void FNAME(adflve2,ADFLVE2)( Fchar version, const Fint *version_length, Fint *error_return ) { ADF_Library_Version( F2CP(version), error_return ) ; ADFI_blank_fill_string ( F2CP(version), *version_length ); } /* end of file ADFLVE2.c */ /* file ADFMOV2.c */ /*********************************************************************** ADFMOVE ADF_Move_Child: ***********************************************************************/ void FNAME(adfmov2,ADFMOV2)( const Fdouble *PID, const Fdouble *ID, const Fdouble *NPID, Fint *error_return ) { ADF_Move_Child( *PID, *ID, *NPID, error_return ) ; } /* end of file ADFMOV2.c */ /* file ADFNCL2.c */ /*********************************************************************** ADFNCLD ADF_Number_of_Children: ***********************************************************************/ void FNAME(adfncl2,ADFNCL2)( const Fdouble *ID, Fint *num_children, Fint *error_return ) { ADF_Number_of_Children( *ID, num_children, error_return ) ; } /* end of file ADFNCL2.c */ /* file ADFPDI2.c */ /*********************************************************************** ADFPDIM ADF_Put_Dimension_Information: ***********************************************************************/ void FNAME(adfpdi2,ADFPDI2)( const Fdouble *ID, const Fchar data_type, const Fint *data_type_length, const Fint *dims, const Fint dim_vals[], Fint *error_return ) { char c_data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; /* CMLU */ int i; for (i=0;i= 0 ) { /** expecting character data type **/ ADF_Read_All_Data( *ID, F2CP(data), error_return ) ; } else { /** expecting non-character data type **/ ADF_Read_All_Data( *ID, data.c_pointer, (int *)data.fcd_len ) ; } #else ADF_Read_All_Data( *ID, F2CP(data), error_return ) ; #endif } /* end of file ADFRALL.c */ /* file ADFRBLK.c */ /*********************************************************************** ADFRBLK ADF_Read_Block_Data: Read block of data from a Node. Reads a block of the node's data and returns it into a contiguous memory space. input: real*8 ID The ID of the node to use. input: const int b_start The starting point in block in token space input: const int b_end The ending point in block in token space output: character *(*) data The start of the data in memory. output: integer error_return Error flag. ***********************************************************************/ void FNAME(adfrblk,ADFRBLK)( const Fdouble *ID, const Fint *b_start, const Fint *b_end, Fchar data, Fint *error_return ) { #if defined(cray) && defined(_ADDR64) int local_error ; char data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; char errmsg[ ADF_MAX_ERROR_STR_LENGTH + 1 ] ; /** see ADFWALL() for more details **/ ADF_Get_Data_Type( *ID, data_type, &local_error ) ; if( local_error != NO_ERROR ) { ADF_Error_Message( local_error, errmsg ) ; fprintf(stderr,"%s\n", errmsg ) ; fprintf(stderr,"Unrecoverable ADF error. ADFRBLK\n" ) ; fprintf(stderr,"Cannot determine data type, so cannot determine function\n" ) ; fprintf(stderr,"argument list (character arrays are different than other\n" ) ; fprintf(stderr,"types in this environemnt), so cannot set error_return.\n" ) ; abort () ; } /* end if */ if ( ADFI_stridx_c( data_type, "C1" ) >= 0 ) { /** expecting character data type **/ ADF_Read_Block_Data( *ID, (long) *b_start, (long) *b_end, F2CP(data), error_return ) ; } else { /** expecting non-character data type **/ ADF_Read_Block_Data( *ID, (long) *b_start, (long) *b_end, data.c_pointer, (int *)data.fcd_len ) ; } #else ADF_Read_Block_Data( *ID, (long) *b_start, (long) *b_end, F2CP(data), error_return ) ; #endif } /* end of file ADFRBLK.c */ /* file ADFREA2.c */ /* end of file ADFREA2.c */ /* file ADFREAD.c */ /*********************************************************************** ADFREAD ADF_Read_Data: A 1-based system is used with all index values (the first element has an index of 1, not 0). R1: Read data from a node, with partial capabilities. The partial capabilities are both in the node's data and also in memory. Vectors of integers are used to indicate the data to be accessed from the node, and another set of integer vectors is used to describe the memory location for the data. Note: If the data-type of the node is a compound data-type ("I4[3],R8") for example, the partial capabilities will access one or more of these 20-byte data entities. You cannot access a subset of an occurrence of the data-type. f77: ADFREAD( ID, sstart[], send[], sstrid[], mnumd, mdims[], mstart[], mend[], mstrid[], data, ierr ) input: real*8 ID The ID of the node to use. input: integer sstart(12) The starting dimension values to use in the database (node). input: integer send(12) The ending dimension values to use in the database (node). input: integer sstrid(12) The stride values to use in the database (node). input: integer mnumd The number of dimensions to use in memory. input: integer mdims(mnumd) The dimensionality to use in memory. input: integer mstart(mnumd) The starting dimension values to use in memory. input: integer mend(mnumd) The ending dimension values to use in memory. input: integer mstrid(mnumd) The stride values to use in memory. output: character*(*) data The start of the data in memory. output: integer ierr ***********************************************************************/ void FNAME(adfread,ADFREAD)( const Fdouble *ID, const Fint s_start[], const Fint s_end[], const Fint s_stride[], const Fint *m_num_dims, const Fint m_dims[], const Fint m_start[], const Fint m_end[], const Fint m_stride[], Fchar data, Fint *error_return ) { #if defined(cray) && defined(_ADDR64) int local_error ; char data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; char errmsg[ ADF_MAX_ERROR_STR_LENGTH + 1 ] ; /** see ADFWALL() for more details **/ ADF_Get_Data_Type( *ID, data_type, &local_error ) ; if( local_error != NO_ERROR ) { ADF_Error_Message( local_error, errmsg ) ; fprintf(stderr,"%s\n", errmsg ) ; fprintf(stderr,"Unrecoverable ADF error. ADFREAD\n" ) ; fprintf(stderr,"Cannot determine data type, so cannot determine function\n" ) ; fprintf(stderr,"argument list (character arrays are different than other\n" ) ; fprintf(stderr,"types in this environemnt), so cannot set error_return.\n" ) ; abort () ; } /* end if */ if ( ADFI_stridx_c( data_type, "C1" ) >= 0 ) { /** expecting character data type **/ ADF_Read_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, F2CP(data), error_return ) ; } else { /** expecting non-character data type **/ ADF_Read_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, data.c_pointer, (int *)data.fcd_len ) ; } #else ADF_Read_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, F2CP(data), error_return ) ; #endif } /* end of file ADFREAD.c */ /* file ADFSES2.c */ /*********************************************************************** ADFSES ADF_Set_Error_State: ***********************************************************************/ void FNAME(adfses2,ADFSES2)( const Fint *error_state, Fint *error_return ) { ADF_Set_Error_State( *error_state, error_return ) ; } /* end of file ADFSES2.c */ /* file ADFSLB2.c */ /*********************************************************************** ADFSLB ADF_Set_Label: ***********************************************************************/ void FNAME(adfslb2,ADFSLB2)( const Fdouble *ID, const Fchar label, const Fint *label_length, Fint *error_return ) { char c_label[ ADF_LABEL_LENGTH + 1 ] ; ADFI_string_2_C_string( F2CP(label), MIN(ADF_LABEL_LENGTH, *label_length), c_label, error_return ) ; if( *error_return != NO_ERROR ) return ; ADF_Set_Label( *ID, c_label, error_return ) ; } /* end of file ADFSLB2.c */ /* file ADFWAL2.c */ /* end of file ADFWAL2.c */ /* file ADFWALL.c */ /*********************************************************************** ADFWALL ADF_Write_All_Data: Write all data to a Node. Writes all the node's data from a contiguous memory space. input: real*8 ID The node's id. input: character *(*) data The start of data in memory. output: integer error_return Error flag. ***********************************************************************/ void FNAME(adfwall,ADFWALL)( const Fdouble *ID, const Fchar data, Fint *error_return ) { #if defined(cray) && defined(_ADDR64) int local_error ; char data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; char errmsg[ ADF_MAX_ERROR_STR_LENGTH + 1 ] ; /** On Crays with 64 bit addresses (like Tritons), Fortran character arrays occupy two 64 bit words on argument stacks (see ). Other data (INTEGER, REAL, etc) occupy one word. To accommodate both situations with one function, some tricks need to be employed... **/ /** First, find the data type that ADF is expecting and assume the function is being called with that kind of argument. This function is defined with character data in mind and deviates from that if necessary. **/ ADF_Get_Data_Type( *ID, data_type, &local_error ) ; if( local_error != NO_ERROR ) { ADF_Error_Message( local_error, errmsg ) ; fprintf(stderr,"%s\n", errmsg ) ; fprintf(stderr,"Unrecoverable ADF error. ADFWALL\n" ) ; fprintf(stderr,"Cannot determine data type, so cannot determine function\n" ) ; fprintf(stderr,"argument list (character arrays are different than other\n" ) ; fprintf(stderr,"types in this environemnt), so cannot set error_return.\n" ) ; abort () ; } /* end if */ if ( ADFI_stridx_c( data_type, "C1" ) >= 0 ) { /** expecting character data type **/ ADF_Write_All_Data( *ID, F2CP(data), error_return ) ; } else { /** expecting data type other than character - the stack is not as long as is with character data and so "error_return" does not correspond to anything valid. Since "data" is declared Fchar but the actual argument is not, the second half of "data" contains the error flag argument (the stack is assumed to be contiguous). **/ ADF_Write_All_Data( *ID, data.c_pointer, (int *)data.fcd_len ) ; } #else /** In other CRAY environments the declared length is encoded in unused portions of pointers and the F2CP macro handles its conversion. In other environments, the character array declared length mystery argument is assumed to be on the end of the stack and is ignored here (F2CP macro does nothing). **/ ADF_Write_All_Data( *ID, F2CP(data), error_return ) ; #endif } /* end of file ADFWALL.c */ /* file ADFWBLK.c */ /*********************************************************************** ADFWBLK ADF_Write_Block_Data: Write block of data from a Node. Writes a block of the node's data and returns it into a contiguous memory space. input: real*8 ID The ID of the node to use. input: const int b_start The starting point in block in token space input: const int b_end The ending point in block in token space output: character *(*) data The start of the data in memory. output: integer error_return Error flag. ***********************************************************************/ void FNAME(adfwblk,ADFWBLK)( const Fdouble *ID, const Fint *b_start, const Fint *b_end, Fchar data, Fint *error_return ) { #if defined(cray) && defined(_ADDR64) int local_error ; char data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; char errmsg[ ADF_MAX_ERROR_STR_LENGTH + 1 ] ; /** see ADFWALL() for more details **/ ADF_Get_Data_Type( *ID, data_type, &local_error ) ; if( local_error != NO_ERROR ) { ADF_Error_Message( local_error, errmsg ) ; fprintf(stderr,"%s\n", errmsg ) ; fprintf(stderr,"Unrecoverable ADF error. ADFWBLK\n" ) ; fprintf(stderr,"Cannot determine data type, so cannot determine function\n" ) ; fprintf(stderr,"argument list (character arrays are different than other\n" ) ; fprintf(stderr,"types in this environemnt), so cannot set error_return.\n" ) ; abort () ; } /* end if */ if ( ADFI_stridx_c( data_type, "C1" ) >= 0 ) { /** expecting character data type **/ ADF_Write_Block_Data( *ID, (long) *b_start, (long) *b_end, F2CP(data), error_return ) ; } else { /** expecting non-character data type **/ ADF_Write_Block_Data( *ID, (long) *b_start, (long) *b_end, data.c_pointer, (int *)data.fcd_len ) ; } #else ADF_Write_Block_Data( *ID, (long) *b_start, (long) *b_end, F2CP(data), error_return ) ; #endif } /* end of file ADFWBLK.c */ /* file ADFWRI2.c */ /* end of file ADFWRI2.c */ /* file ADFWRIT.c */ /*********************************************************************** ADFWRIT ADF_Write_Data: Write data to a Node, with partial capabilities. See ADF_Read_Data for description. f77: ADFWRIT( ID, sstart[], send[], sstrid[], mnumd, mdims[], mstart[], mend[], mstrid[], data, ierr ) input: real*8 ID The ID of the node to use. input: integer sstart(12) The starting dimension values to use in the database (node). input: integer send(12) The ending dimension values to use in the database (node). input: integer sstrid(12) The stride values to use in the database (node). input: integer mnumd The number of dimensions to use in memory. input: integer mdims(mnumd) The dimensionality to use in memory. input: integer mstart(mnumd) The starting dimension values to use in memory. input: integer mend(mnumd) The ending dimension values to use in memory. input: integer mstrid(mnumd) The stride values to use in memory. input: character*(*) data The start of the data in memory. output: integer ierr ***********************************************************************/ void FNAME(adfwrit,ADFWRIT)( const Fdouble *ID, const Fint s_start[], const Fint s_end[], const Fint s_stride[], const Fint *m_num_dims, const Fint m_dims[], const Fint m_start[], const Fint m_end[], const Fint m_stride[], const Fchar data, Fint *error_return ) { #if defined(cray) && defined(_ADDR64) int local_error ; char data_type[ ADF_DATA_TYPE_LENGTH + 1 ] ; char errmsg[ ADF_MAX_ERROR_STR_LENGTH + 1 ] ; /** see ADFWALL() for more details **/ ADF_Get_Data_Type( *ID, data_type, &local_error ) ; if( local_error != NO_ERROR ) { ADF_Error_Message( local_error, errmsg ) ; fprintf(stderr,"%s\n", errmsg ) ; fprintf(stderr,"Unrecoverable ADF error. ADFWRIT\n" ) ; fprintf(stderr,"Cannot determine data type, so cannot determine function\n" ) ; fprintf(stderr,"argument list (character arrays are different than other\n" ) ; fprintf(stderr,"types in this environemnt), so cannot set error_return.\n" ) ; abort () ; } /* end if */ if ( ADFI_stridx_c( data_type, "C1" ) >= 0 ) { /** expecting character data type **/ ADF_Write_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, F2CP(data), error_return ) ; } else { /** expecting non-character data type **/ ADF_Write_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, data.c_pointer, (int *)data.fcd_len ) ; } #else ADF_Write_Data( *ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, F2CP(data), error_return ) ; #endif } /* end of file ADFWRIT.c */ /* end of combine 2.0 */ CGNS-3.4.0/src/adf/ADF_interface.c000066400000000000000000004736311343724673500164030ustar00rootroot00000000000000/* created by combine 2.0 */ /* file ADF_AAA_var.c */ /* file ADF_AAA_var.c */ /*** File: ADF_interface.c ---------------------------------------------------------------------- BOEING ---------------------------------------------------------------------- Project: CGNS Author: Tom Dickens 234-1024 tpd6908@yak.ca.boeing.com Date: 3/2/1995 Purpose: The code which implements the ADF-Core capabilities. ---------------------------------------------------------------------- ---------------------------------------------------------------------- ***/ /*********************************************************************** Library and Database "what" strings. ***********************************************************************/ /** Change the major revision letter in the Library Version for changes to the API (new public functions, changes to public header files, changes to existings functions or their defined behavior) and/or changes to the internal file format resulting in incompatibilites with previous library versions. Change the internal revision number for internal changes and bug fixes; reset to zero for major revision letter changes. **/ static char ADF_L_identification[] = "@(#)ADF Library Version F01>" ; /* 01234567890123456789012345678901 = 32 */ /** Change version database version number every time the library version changes according to the following philosophy. The format: AXXxxx where: A Major revision number. Major internal structure changes. This number is not expected to change very often if at all because backward compatibility is only available by explicit policy decision. One alphabetic character. Range of values: A-Za-z In unlikely event of reaching z, then can use any other unused printable ASCII character except blank or symbols used by "what" command: @, (, #, ), ~, >, \. XX Minor revision number. New features and minor changes and bug fixes. Files are backward but NOT forward compatible. Two digit hexadecimal number (uppercase letters). Range of values: 00 - FF Reset to 00 with changes in major revision number. xxx Incremental number. Incremented with every new version of library (even if no changes are made to file format). Files are forward AND backward compatible. Three digit hexadecimal number (lowercase letters) Range of values: 000 to fff Does not reset. Definitions: forward compatible Older versions of libraries can read and write to files created by newer versions of libraries. backward compatible Newer versions of libraries can read and write to files created by older versions of libraries. **/ /** change suggested by Kevin Mack of Adapco With the original ADF library, there is no binary data for at least the first 560 bytes, which causes a lot of programs (mailers, WinZip) to think that the file is text and try to do a \n -> \n\r conversion. Since this string is only used for the 'what' command, I am deciding that we don't need this functionality and am putting binary characters here. Specifically, I am putting control characters, because while some programs (Evolution/gnome-vfs) look for unprintable characters, some look for a ratio (Mozilla). **/ /** modification by Bruce Wedan I'm modifying the 1st 4 bytes of the header, @(#), by turning on the high bit. This makes these bytes non-ASCII and should not effect the check/reporting of version number **/ /* AXXxxx */ static char ADF_D_identification[] = "\300\250\243\251ADF Database Version B02012>" ; /* 0 1 2 3 4567890123456789012345678901 = 32 */ static char ADF_A_identification[] = "\300\250\243\251ADF Database Version A02011>" ; /*********************************************************************** Includes ***********************************************************************/ #include #include #include #include #include #if defined(_WIN32) && !defined(__NUTC__) # include # ifndef F_OK # define R_OK 004 /* Test for Read permission */ # define W_OK 002 /* Test for Write permission */ # define X_OK 001 /* Test for eXecute permission */ # define F_OK 000 /* Test for existence of File */ # endif # define ACCESS _access #else # include # define ACCESS access #endif #include "ADF.h" #include "ADF_internals.h" #include "cgnstypes.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif /*********************************************************************** Error strings These strings must be kept in sync with the error defines in ADF.h. ***********************************************************************/ const char *ADF_error_string[] = { "ADF -1: No Error.", "ADF 1: Integer number is less than given minimum value.", "ADF 2: Integer number is greater than given maximum value.", "ADF 3: String length of zero or blank string detected.", "ADF 4: String length longer than maximum allowable length.", "ADF 5: String is not an ASCII-HEX string.", "ADF 6: Too many ADF files opened.", "ADF 7: ADF file status was not recognized.", "ADF 8: ADF file-open error.", "ADF 9: ADF file not currently opened.", "ADF 10: ADF file index out of legal range.", "ADF 11: Block/offset out of legal range.", "ADF 12: A string pointer is NULL.", "ADF 13: FSEEK error.", "ADF 14: FWRITE error.", "ADF 15: FREAD error.", "ADF 16: Internal error: Memory boundary tag bad.", "ADF 17: Internal error: Disk boundary tag bad.", "ADF 18: File Open Error: NEW - File already exists.", "ADF 19: ADF file format was not recognized.", "ADF 20: Attempt to free the RootNode disk information.", "ADF 21: Attempt to free the FreeChunkTable disk information.", "ADF 22: File Open Error: OLD - File does not exist.", "ADF 23: Entered area of Unimplemented Code...", "ADF 24: Sub-Node.entries is bad.", "ADF 25: Memory allocation failed.", "ADF 26: Duplicate child name under a parent node.", "ADF 27: Node has no dimensions.", "ADF 28: Node's number-of-dimensions is not in legal range.", "ADF 29: Specified child is NOT a child of the specified parent.", "ADF 30: Data-Type is too long.", "ADF 31: Invalid Data-Type.", "ADF 32: A pointer is NULL.", "ADF 33: Node has no data associated with it.", "ADF 34: Error zeroing out memory.", "ADF 35: Requested data exceeds actual data available.", "ADF 36: Bad end value.", "ADF 37: Bad stride value.", "ADF 38: Minimum values is greater than the maximum value.", "ADF 39: The format of this machine does not match a known signature.", "ADF 40: Cannot convert to or from an unknown Native format.", "ADF 41: The two conversion formats are equal, no conversion done.", "ADF 42: The data format is not support on a particular machine.", "ADF 43: File Close error.", "ADF 44: Numeric overflow/underflow in data conversion.", "ADF 45: Bad start value.", "ADF 46: A value of zero is not allowable.", "ADF 47: Bad dimension value.", "ADF 48: Error state must be either a 0 (zero) or a 1 (one).", "ADF 49: Dimensional specifications for disk and memory are unequal.", "ADF 50: Too many link level used. May be caused by a recursive link.", "ADF 51: The node is not a link. It was expected to be a link.", "ADF 52: The linked-to node does not exist.", "ADF 53: The ADF file of a linked-node is not accessable.", "ADF 54: A node-id of 0.0 is not valid.", "ADF 55: Incomplete Data when reading multiple data blocks.", "ADF 56: Node name contains invalid characters.", "ADF 57: ADF file version incompatible with this library version.", "ADF 58: Nodes are not from the same file.", "ADF 59: Priority Stack Error.", "ADF 60: Machine format and file format are incompatable.", "ADF 61: FFLUSH error", "ADF 62: The node ID pointer is NULL.", "ADF 63: The maximum size for a file exceeded.", "ADF 64: Dimensions exceed that for a 32-bit integer.", "ADF x: Last error mesage" } ; /*********************************************************************** Global Variables: ***********************************************************************/ int ADF_sys_err = 0; static int ADF_abort_on_error = FALSE ; extern char data_chunk_start_tag[]; #define CHECK_ADF_ABORT( error_flag ) if( error_flag != NO_ERROR ) { \ if( ADF_abort_on_error == TRUE ) { \ ADF_Error_Message( error_flag, 0L );\ ADFI_Abort( error_flag) ; } \ else { return ; } } /* Added to remove memory leaks in ADF_Get_Node_ID */ #define CHECK_ADF_ABORT1( error_flag ) if( error_flag != NO_ERROR ) { \ free (name_tmp); \ if( ADF_abort_on_error == TRUE ) { \ ADF_Error_Message( error_flag, 0L );\ ADFI_Abort( error_flag) ; } \ else { return ; } } /*********************************************************************** Data Query: Note: If the node is a link, the data query will occur on the linked-to node, not the node which is the link. Internal Implementation: A linked node will have a data-type of "LK", dimension of 1 and a dimension value of the length of a data string containing the file-path and the node-path within the file. The routines ADF_Is_Link and ADF_Get_Link_Path allow viewing of a link's data-type and data. ***********************************************************************/ /*********************************************************************** Data I/O: A 1-based system is used with all index values (the first element has an index of 1, not 0). ***********************************************************************/ /* end of file ADF_AAA_var.c */ /* end of file ADF_AAA_var.c */ /* file ADF_Children_Names.c */ /*********************************************************************** ADF Children names: Get Children names of a Node. Return the name of children nodes directly associated with a parent node. The names of the children are NOT guaranteed to be returned in any particular order. If a new child is added, it is NOT guaranteed to be returned as the last child. Null-terminated names will be written into the names array and thus there needs to be room for the null character. As an example, the array can be defined as: char names[IMAX_NUM][IMAX_NAME_LENGTH+1]; where IMAX_NUM and IMAX_NAME_LENGTH are defined by the using application and correspond to this function's "imax_num" and "imax_name_len" parameters respectively. "imax_name_len" is the maximum length of a name to be copied into the names array. This value can be equal to ADF_NAME_LENGTH but does not have to be. However, the name dimension of the array MUST be declared to be "imax_name_len" + 1. The name will be returned truncated (but still null-terminated) if the actual name is longer than "imax_name_len" and if "imax_name_len" is less than ADF_NAME_LENGTH. Note that the names array parameter is declared as a single dimension character array inside this function. Therefore, use a (char *) cast to cast a two dimensional array argument. ADF_Children_Names( PID, istart, imax_num, imax_name_len, inum_ret, names, error_return ) input: const double PID The ID of the Node to use. input: const int istart The Nth child's name to start with (first is 1). input: const int imax_num Maximum number of names to return. input: const int imax_name_len Maximum Length of a name to return. output: int *inum_ret The number of names returned. output: char *names The returned names (cast with (char *)). output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER NUMBER_LESS_THAN_MINIMUM ***********************************************************************/ void ADF_Children_Names( const double PID, const int istart, const int imax_num, const int imax_name_len, int *inum_ret, char *names, int *error_return ) { int i ; unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; struct SUB_NODE_TABLE_ENTRY sub_node_table_entry ; double LID ; *error_return = NO_ERROR ; if( inum_ret == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *inum_ret = 0 ; if( names == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( (istart <=0) || (imax_num <= 0) || (imax_name_len <= 0) ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_chase_link( PID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Check for zero children, return if 0 **/ if( node.num_sub_nodes == 0 ) { return ; } /* end if */ /** point to the first child wanted **/ block_offset.block = node.sub_node_table.block ; block_offset.offset = node.sub_node_table.offset + (TAG_SIZE + DISK_POINTER_SIZE + (ADF_NAME_LENGTH + DISK_POINTER_SIZE) * (istart-1)) ; /** Return the data for the requested children **/ for( i=(istart-1); i< MIN(istart-1+imax_num, (int) node.num_sub_nodes); i++ ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Read the sun-node entry table **/ ADFI_read_sub_node_table_entry( file_index, &block_offset, &sub_node_table_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Convert the child's name from blank-filled into a C string **/ ADFI_string_2_C_string( sub_node_table_entry.child_name, MIN(imax_name_len,ADF_NAME_LENGTH), &names[(i-(istart-1))*(imax_name_len+1)], error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Increment the disk-pointer and the number of names returned **/ block_offset.offset += (ADF_NAME_LENGTH + DISK_POINTER_SIZE) ; *inum_ret = *inum_ret + 1 ; } /* end for */ } /* end of ADF_Children_Names */ /* end of file ADF_Children_Names.c */ /* file ADF_Children_IDs.c */ /*********************************************************************** ADF Children IDs: Get Children node IDs of a Node. Return the node IDs of children nodes directly associated with a parent node. ADF_Children_IDs( PID, istart, imax_num, inum_ret, IDs, error_return) input: const double PID The ID of the Node to use. input: const int istart The Nth child's name to start with (first is 1). input: const int imax_num Maximum number of names to return. output: int *inum_ret The number of names returned. output: double *IDs The returned node IDs output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER NUMBER_LESS_THAN_MINIMUM ***********************************************************************/ void ADF_Children_IDs ( const double PID, const int istart, const int imax_num, int *inum_ret, double *IDs, int *error_return ) { int i ; unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; struct SUB_NODE_TABLE_ENTRY sub_node_table_entry ; double LID ; *error_return = NO_ERROR ; if( inum_ret == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *inum_ret = 0 ; if( IDs == NULL ) { *error_return = NULL_NODEID_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( (istart <=0) || (imax_num <= 0) ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_chase_link( PID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Check for zero children, return if 0 **/ if( node.num_sub_nodes == 0 ) { return ; } /* end if */ /** point to the first child wanted **/ block_offset.block = node.sub_node_table.block ; block_offset.offset = node.sub_node_table.offset + (TAG_SIZE + DISK_POINTER_SIZE + (ADF_NAME_LENGTH + DISK_POINTER_SIZE) * (istart-1)) ; /** Return the data for the requested children **/ for( i=(istart-1); i< MIN(istart-1+imax_num, (int) node.num_sub_nodes); i++ ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Read the sub-node entry table **/ ADFI_read_sub_node_table_entry( file_index, &block_offset, &sub_node_table_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get the ID from the sub-node table **/ ADFI_file_block_offset_2_ID( file_index, sub_node_table_entry.child_location.block, sub_node_table_entry.child_location.offset, &IDs[i-(istart-1)], error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Increment the disk-pointer and the number of IDs returned **/ block_offset.offset += (ADF_NAME_LENGTH + DISK_POINTER_SIZE) ; *inum_ret = *inum_ret + 1 ; } /* end for */ } /* end of ADF_Children_IDs */ /* end of file ADF_Children_IDs.c */ /* file ADF_Create.c */ /*********************************************************************** ADF Create: Create a Node. Create a new node (not a link-node) as a child of a given parent. Default values in this new node are: label=blank, number of sub-nodes = 0, data-type = "MT", number of dimensions = 0, data = NULL. ADF_Create( PID, name, ID, error_return ) input: const double PID The ID of the parent node, to whom we are creating a new child node. input: const char *name The name of the new child. output: double *ID The ID of the newly created node. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADF_Create( const double PID, const char *name, double *ID, int *error_return ) { unsigned int file_index ; struct DISK_POINTER parent_block_offset, child_block_offset ; struct DISK_POINTER sub_node_entry_location ; struct NODE_HEADER parent_node, child_node ; struct SUB_NODE_TABLE_ENTRY sub_node_entry ; int i, name_length, name_start, found ; double LID ; ADFI_check_string_length( name, ADF_NAME_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( ID == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( PID, &LID, &file_index, &parent_block_offset, &parent_node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Initialize node header **/ ADFI_fill_initial_node_header( &child_node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Skip any leading blanks in the name **/ name_start = 0 ; while( name[ name_start ] == ' ' ) { name_start++ ; } /* end while */ name_length = (int)strlen( &name[ name_start ] ) ; if( name_length > ADF_NAME_LENGTH ) { *error_return = STRING_LENGTH_TOO_BIG ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Check for uniqueness and legality of the name **/ ADFI_check_4_child_name( file_index, &parent_block_offset, &name[ name_start ], &found, &sub_node_entry_location, &sub_node_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( found == 1 ) { *error_return = DUPLICATE_CHILD_NAME ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ for ( i=0; i < name_length; i++ ) { if ( ! isprint ( name[ name_start + i ] ) || name[ name_start + i ] == '/' ) { *error_return = INVALID_NODE_NAME; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end for */ /** Assign the name to the new node **/ strncpy( child_node.name, &name[ name_start ], name_length ) ; /** Allocate disk space for the new node **/ ADFI_file_malloc( file_index, NODE_HEADER_SIZE, &child_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write out the new node header **/ ADFI_write_node_header( file_index, &child_block_offset, &child_node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** OK, new node is on disk. Now, update the list of children for the parent... **/ ADFI_add_2_sub_node_table( file_index, &parent_block_offset, &child_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Return the ID of the new child **/ ADFI_file_block_offset_2_ID( file_index, child_block_offset.block, child_block_offset.offset, ID, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Create */ /* end of file ADF_Create.c */ /* file ADF_Database_Close.c */ /*********************************************************************** ADF Database Close: Close an opened database. If the ADF database spans multiple files, then all files used will also be closed. If an ADF file which is linked to by this database is also opened through another database, only the opened file stream associated with this database will be closed. ADF_Database_Close( Root_ID, error_return ) input: const double Root_ID Root-ID of the ADF database. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Close( const double Root_ID, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; *error_return = NO_ERROR ; /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( Root_ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Close the ADF file (which may close other sub-files) **/ ADFI_close_file( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Close */ /* end of file ADF_Database_Close.c */ /* file ADF_Database_Delete.c */ /*********************************************************************** ADF Database Delete: Delete an existing database. This will delete one or more ADF files which are linked together under file top ADF file named "filename". ADF_Database_Delete( filename, error_return ) input: char *filename Filename of the ADF database to delete. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Delete( const char *filename, int *error_return ) { ADFI_check_string_length( filename, ADF_FILENAME_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; fprintf(stderr,"Subroutine ADF_Database_Delete is not yet implemented...\n" ) ; *error_return = UNIMPLEMENTED_CODE ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Delete */ /* end of file ADF_Database_Delete.c */ /* file ADF_Database_Garbage_Collection.c */ /*********************************************************************** ADF Database Garbage Collection: Garbage Collection. This capability will most likely be implemented internally and will not be user-callable. ADF_Database_Garbage_Collection( ID, error_return ) input: const double ID The ID of a node in the ADF file in which to do garbage collection. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Garbage_Collection( const double ID, int *error_return ) { fprintf(stderr, "Subroutine ADF_Database_Garbage_Collection is not yet implemented...\n" ) ; *error_return = UNIMPLEMENTED_CODE ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Garbage_Collection */ /* end of file ADF_Database_Garbage_Collection.c */ /* file ADF_Database_Get_Format.c */ /*********************************************************************** ADF Database Get Format: Get the data format used in an existing database. ADF_Database_Get_Format( Root_ID, format, error_return ) input: const double Root_ID The root_ID of the ADF file. output: char *format See format for ADFDOPN. Maximum of 20 characters returned. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Get_Format( const double Root_ID, char *format, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct FILE_HEADER file_header ; if( format == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( Root_ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; #define EVAL_2_BYTES( C0, C1 ) (((C0)<<8)+((C1))) switch( EVAL_2_BYTES( file_header.numeric_format, file_header.os_size ) ) { case EVAL_2_BYTES( 'B', 'L' ) : strcpy( format, IEEE_BIG_32_FORMAT_STRING ) ; break ; case EVAL_2_BYTES( 'L', 'L' ) : strcpy( format, IEEE_LITTLE_32_FORMAT_STRING ) ; break ; case EVAL_2_BYTES( 'B', 'B' ) : strcpy( format, IEEE_BIG_64_FORMAT_STRING ) ; break ; case EVAL_2_BYTES( 'L', 'B' ) : strcpy( format, IEEE_LITTLE_64_FORMAT_STRING ) ; break ; case EVAL_2_BYTES( 'C', 'B' ) : strcpy( format, CRAY_FORMAT_STRING ) ; break ; case EVAL_2_BYTES( 'N', 'L' ) : case EVAL_2_BYTES( 'N', 'B' ) : strcpy( format, NATIVE_FORMAT_STRING ) ; break ; default: *error_return = ADF_FILE_FORMAT_NOT_RECOGNIZED ; return ; } /* end switch */ } /* end of ADF_Database_Get_Format */ /* end of file ADF_Database_Get_Format.c */ /* file ADF_Database_Open.c */ /*********************************************************************** ADF Database Open: Open a database. Open either a new or an existing ADF file. If links to other ADF files are used, these additional file will be opened automatically as required. ADF_Database_Open( filename, status, format, root_ID, error_return) input: const char *filename Not used if status SCRATCH is used. Filename must be a legal name and may include a relative or absolute path. It must be directly usable by the C fopen() system routine. input: const char *status_in Like FORTRAN OPEN() status. Allowable values are: READ_ONLY - File must exist. Writing NOT allowed. OLD - File must exist. Reading and writing allowed. NEW - File must not exist. SCRATCH - New file. Filename is ignored. UNKNOWN - OLD if file exists, else NEW is used. input: const char *format Specifies the numeric format for the file. If blank or NULL, the machine's native format is used. This field is only used when a file is created. NATIVE - Determine the format on the machine. If the native format is not one of the formats supported, the created file cannot be used on other machines. IEEE_BIG - Use the IEEE big ENDIAN format. IEEE_LITTLE - Use the IEEE little ENDIAN format. CRAY - Use the native Cray format. output: double *root_ID Root-ID of the opened ADF database. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER ADF_FILE_STATUS_NOT_RECOGNIZED REQUESTED_NEW_FILE_EXISTS FILE_OPEN_ERROR ***********************************************************************/ void ADF_Database_Open( const char *filename, const char *status_in, const char *format, double *Root_ID, int *error_return ) { int iret, legacy = 0 ; int error_dummy ; char machine_format, format_to_use, os_to_use ; char *status ; int formats_compare ; unsigned int file_index ; unsigned int file_minor_version, lib_minor_version ; struct FILE_HEADER file_header ; struct NODE_HEADER node_header ; struct FREE_CHUNK_TABLE free_chunk_table ; file_header.tag0[0] = '\0' ; status = (char *)status_in ; if( status == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( Root_ID == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** DO NOT Check filename for NULL here, it may NOT be used... **/ *error_return = NO_ERROR ; /** Get this machine's numeric format **/ ADFI_figure_machine_format( format, &machine_format, &format_to_use, &os_to_use, error_return ) ; if( ADFI_stridx_c( status, "SCRATCH" ) != 0 ) { ADFI_check_string_length( filename, ADF_FILENAME_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_check_string_length( status, ADF_STATUS_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Determine the requested STATUS **/ if( ADFI_stridx_c( status, "UNKNOWN" ) == 0 ) { /** Determine the assessability of the filename **/ iret = ACCESS( filename, F_OK ) ; if( iret != 0 ) /* File does not exist, set status to NEW */ status = "NEW" ; else status = "OLD" ; } /* end else if */ if( (ADFI_stridx_c( status, "READ_ONLY" ) == 0) || (ADFI_stridx_c( status, "OLD" ) == 0) ) { /** Determine the assessability of the filename **/ iret = ACCESS( filename, F_OK ) ; if( iret != 0 ) { /* File does not exist, this is BAD for OLD */ *error_return = REQUESTED_OLD_FILE_NOT_FOUND ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** open the file **/ ADFI_open_file( filename, status, &file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else if */ else if( (ADFI_stridx_c( status, "NEW" ) == 0) || (ADFI_stridx_c( status, "SCRATCH" ) == 0) ) { /** Determine the assessability of the filename **/ if( ADFI_stridx_c( status, "NEW" ) == 0 ) { iret = ACCESS( filename, F_OK ) ; if( iret == 0 ) { /* File exists, this is BAD for NEW */ *error_return = REQUESTED_NEW_FILE_EXISTS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( errno != ENOENT ) { *error_return = FILE_OPEN_ERROR ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end if */ if (ADFI_stridx_c(format, "LEGACY") == 0) legacy = 1; /** Compose the file header **/ ADFI_fill_initial_file_header( format_to_use, os_to_use, legacy ? ADF_A_identification : ADF_D_identification, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Open the new file **/ ADFI_open_file( filename, status, &file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /* need this to write header */ ADF_file[file_index].old_version = (char)legacy; ADF_file[file_index].format = format_to_use; ADF_file[file_index].os_size = os_to_use; /** write out the file header **/ ADFI_write_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Compose Initial root-node header **/ ADFI_fill_initial_node_header( &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; strncpy( node_header.name, ROOT_NODE_NAME, strlen( ROOT_NODE_NAME )) ; strncpy( node_header.label, ROOT_NODE_LABEL, strlen( ROOT_NODE_LABEL ) ) ; /** Write out the root-node header **/ ADFI_write_node_header( file_index, &file_header.root_node, &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Compose Initial Free-Chunk Table **/ ADFI_fill_initial_free_chunk_table( &free_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write out Free-Chunk Table **/ ADFI_write_free_chunk_table( file_index, &free_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else if */ else { *error_return = ADF_FILE_STATUS_NOT_RECOGNIZED ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Read the header of the ADF file **/ if( file_header.tag0[0] == '\0' ) { ADFI_read_file_header( file_index, &file_header, error_return ) ; if ( *error_return != NO_ERROR ) goto Open_Error ; /** Check Database version numbers for compatibility **/ if( file_header.what[25] != ADF_D_identification[25] ) { /* Look at major revision letter: version in file must equal what this library would write unless there is a policy decision to support both versions. */ if (file_header.what[25] == 'A') ADF_file[file_index].old_version = 1 ; else { *error_return = INVALID_VERSION ; goto Open_Error ; } } /* end if */ if( file_header.what[28] == '>' ) { /* we have an old file created before this version numbering scheme was instituted - probably will not work */ *error_return = INVALID_VERSION ; if ( *error_return != NO_ERROR ) goto Open_Error ; } else /* check version number for file format compatibility */ { /* Look at minor revision number: version in file must be less than or equal to what this library would write. */ ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &file_header.what[26], &file_minor_version, error_return) ; if ( *error_return != NO_ERROR ) goto Open_Error ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &ADF_D_identification[26], &lib_minor_version, error_return) ; if ( *error_return != NO_ERROR ) goto Open_Error ; if( file_minor_version > lib_minor_version ) { *error_return = INVALID_VERSION ; if ( *error_return != NO_ERROR ) goto Open_Error ; } /* end if */ if( file_minor_version < lib_minor_version ) { /** If a new feature is added which requires that the file version be changed then it is done here. Care must be take not to break forward compatibility by changing the file version. Thus new features may not be available for older file versions. For instance version A1 files cannot be upgraded to version A2 and above since a change was made to how links were store and the file version is used to decide how to treat links. **/ if ( ADF_D_identification[25] == 'A' && file_minor_version > 1 ) { ADFI_remember_version_update( file_index, ADF_D_identification, error_return ) ; if ( *error_return != NO_ERROR ) goto Open_Error ; } /* end if */ /** The link separator was changed from " " to ">" in order to support blanks in filenames under Windows. This change is for version A02 and higher **/ if ( ADF_D_identification[25] == 'A' && file_minor_version < 2 ) { ADF_file[file_index].link_separator = ' ' ; } /* end if */ } /* end if */ } /* end if */ } /* end if */ /** get the root ID for the user **/ ADFI_file_block_offset_2_ID( file_index, file_header.root_node.block, file_header.root_node.offset, Root_ID, error_return ) ; if ( *error_return != NO_ERROR ) goto Open_Error ; /** Remember the file's data format **/ ADFI_remember_file_format( file_index, file_header.numeric_format, file_header.os_size, error_return ) ; if ( *error_return != NO_ERROR ) goto Open_Error ; /** check machine modes, if machine is native the file must be !! **/ ADFI_file_and_machine_compare( file_index, NULL, &formats_compare, error_return ) ; if ( *error_return != NO_ERROR ) goto Open_Error ; return ; Open_Error: /** Close the ADF file and free its index **/ ADFI_close_file( file_index, &error_dummy ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Open */ /* end of file ADF_Database_Open.c */ /*********************************************************************** ADF Database Valid: Checks if a file is a valid ADF file. If status if given, then check if the file can be opened in that mode. ADF_Database_Valid( filename, status, error_return) input: const char *filename Filename must be a legal name and may include a relative or absolute path. It must be directly usable by the C fopen() system routine. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER FILE_OPEN_ERROR ADF_FILE_FORMAT_NOT_RECOGNIZED ***********************************************************************/ void ADF_Database_Valid( const char *filename, int *error_return ) { FILE *fp; char header[33]; if (NULL == filename || 0 == *filename) { *error_return = NULL_STRING_POINTER; return; } if (ACCESS(filename, F_OK)) { *error_return = REQUESTED_OLD_FILE_NOT_FOUND; return; } if ((fp = fopen(filename, "rb")) == NULL) { if (errno == EMFILE) *error_return = TOO_MANY_ADF_FILES_OPENED; else *error_return = FILE_OPEN_ERROR; return; } fread (header, sizeof(char), 32, fp); fclose (fp); header[32] = 0; if (strncmp (&header[4], "ADF Database Version", 20)) *error_return = ADF_FILE_FORMAT_NOT_RECOGNIZED; else *error_return = NO_ERROR; } /* file ADF_Database_Set_Format.c */ /*********************************************************************** ADF Database Set Format: Set the data format used in an existing database. Note: Use with extreme caution. Needed only for data conversion utilities and NOT intended for the general user!!! ADF_Database_Set_Format( Root_ID, format, error_return ) input: const double Root_ID The root_ID if the ADF file. input: const char *format See format for ADFDOPN. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Set_Format( const double Root_ID, const char *format, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct FILE_HEADER file_header ; char machine_format, format_to_use, os_to_use ; ADFI_check_string_length( format, ADF_FORMAT_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( Root_ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_figure_machine_format( format, &machine_format, &format_to_use, &os_to_use, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; file_header.numeric_format = format_to_use ; file_header.os_size = os_to_use ; /** Get modification date to be updated with the header **/ ADFI_get_current_date ( file_header.modification_date ); /** Now write the disk header out... **/ ADFI_write_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_remember_file_format( file_index, format_to_use, os_to_use, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Set_Format */ /* end of file ADF_Database_Set_Format.c */ /* file ADF_Database_Version.c */ /*********************************************************************** ADF Database Version: Get ADF File Version ID. This is the version number of the ADF library routines which created an ADF database. Modified ADF databases will take on the version ID of the current ADF library version if it is higher than the version indicated in the file. The format of the version ID is: "ADF Database Version 000.01" ADF_Database_Version( Root_ID, version, creation_date, modification_date, error_return ) input: const double Root_ID The ID of the root node in the ADF file. output: char *version A 32-byte character string containing the version ID. output: char *creation_date A 32-byte character string containing the creation date of the file. output: char *modification_date A 32-byte character string containing the last modification date of the file. output: int *error_return Error return. ***********************************************************************/ void ADF_Database_Version( const double Root_ID, char *version, char *creation_date, char *modification_date, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct FILE_HEADER file_header ; if( (version == NULL) || (creation_date == NULL) || (modification_date == NULL) ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( Root_ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; *error_return = NO_ERROR ; /** Convert the "what" string into a C string **/ ADFI_string_2_C_string( &file_header.what[4], (int)strcspn ( file_header.what, ">" ) - 4, version, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Convert the creation date string into a C string **/ ADFI_string_2_C_string( file_header.creation_date, 28, creation_date, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Convert the modification date string into a C string **/ ADFI_string_2_C_string( file_header.modification_date, 28, modification_date, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Database_Version */ /* end of file ADF_Database_Version.c */ /* file ADF_Delete.c */ /*********************************************************************** ADF Delete: Delete a Node. If the node is NOT a link, then the specified node and all sub-nodes anywhere under it are also deleted. For a link, and also for links farther down in the tree, the link-node will be deleted, but the node which the link is linked to is not affected. When a node is deleted, other link-nodes which point to it are left dangling. For example, if N13 is deleted, then L1 and L2 point to a non-existing node. This is OK until L1 and L2 are used. ADF_Delete( PID, ID, error_return ) input: const double PID The ID of the node's parent. input: const double ID The ID of the node to use. output: int *error_return Error return. ***********************************************************************/ void ADF_Delete( const double PID, const double ID, int *error_return ) { int num_ids , i, link_path_length ; double *ids ; unsigned int file_index ; struct DISK_POINTER parent ; struct DISK_POINTER child ; struct NODE_HEADER node_header ; /** Don't use ADFI_chase_link() - delete link nodes but NOT the nodes they are linked too **/ ADFI_ID_2_file_block_offset( ID, &file_index, &child.block, &child.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADF_Is_Link( ID, &link_path_length, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_read_node_header( file_index, &child, &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Delete node data **/ if( link_path_length > 0 ) { /** this node IS a link **/ /** Delete the link path data for this node **/ ADFI_delete_data( file_index, &node_header, error_return ) ; } else { /** this node is NOT a link **/ /** Recursively delete all sub-nodes (children) of this node **/ ADFI_get_direct_children_ids( file_index, &child, &num_ids, &ids, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; for( i=0; i 0 ) { free( ids ) ; } /* end if */ /** Delete all data for this node **/ ADF_Put_Dimension_Information( ID, "MT", 0, (cgsize_t *)0, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if-else */ /** Disassociate node from parent **/ ADFI_ID_2_file_block_offset( PID, &file_index, &parent.block, &parent.offset, error_return ) ; /* file_index should be same as before since parent and child should be in the same file */ CHECK_ADF_ABORT( *error_return ) ; ADFI_delete_from_sub_node_table( file_index, &parent, &child, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Delete this node's sub node table **/ if( node_header.entries_for_sub_nodes > 0 ) { ADFI_delete_sub_node_table( file_index, &node_header.sub_node_table, node_header.entries_for_sub_nodes, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Delete node header from disk **/ ADFI_file_free( file_index, &child, 0, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Delete */ /* end of file ADF_Delete.c */ /* file ADF_Error_Message.c */ /*********************************************************************** ADF Error message: Return Error Message. Given an error_return from an ADF routine, get a textual description of the error. ADF_Error_Message( error_return, error_string ) input: const int error_return An ADF-generated error code. output: char *error_string An 80-byte description of the specified error. If the number is NULL, then print out error message. ***********************************************************************/ void ADF_Error_Message( const int error_return_input, char *error_string ) { char err_msg_str[ADF_MAX_ERROR_STR_LENGTH+1] ; /** If return pointer is NULL, print message to stdout **/ if( error_string == NULL ) { ADF_Error_Message( error_return_input, err_msg_str ) ; fprintf(stderr,"%s\n", err_msg_str ) ; return ; } /* end if */ /** NO_ERROR is NOT zero for pointer-assignment checking **/ if( error_return_input == NO_ERROR ) { strcpy( error_string, ADF_error_string[ 0 ] ) ; } /* end if */ /** Check range of error code **/ else if( (error_return_input <= 0) || (error_return_input >= sizeof( ADF_error_string )/sizeof(char *) - 1 ) ) { sprintf( error_string, "ADF: Unrecognized error number %d.", error_return_input ) ; } /* end else if */ /** Error-code good, copy it for the user **/ else if (ADF_sys_err && (FILE_OPEN_ERROR == error_return_input || FILE_CLOSE_ERROR == error_return_input || FSEEK_ERROR == error_return_input || FREAD_ERROR == error_return_input || FWRITE_ERROR == error_return_input || FFLUSH_ERROR == error_return_input)) { char *p; strncpy (err_msg_str, strerror(ADF_sys_err), ADF_MAX_ERROR_STR_LENGTH-8); err_msg_str[ADF_MAX_ERROR_STR_LENGTH-8] = 0; p = err_msg_str + strlen(err_msg_str) - 1; if (*p == '\n') *p = 0; sprintf (error_string, "ADF %d: %s", error_return_input, err_msg_str); } else { strcpy( error_string, ADF_error_string[error_return_input] ) ; } /* end else */ } /* end of ADF_Error_Message */ /* end of file ADF_Error_Message.c */ /* file ADF_Flush_to_Disk.c */ /*********************************************************************** ADF Flush to Disk: Flush data to disk. This routine is used force any modified information to be flushed to the physical disk. This ensures that data will not be lost if a program aborts. This control of when to flush all data to disk is provided to the user rather than to flush the data every time it is modified, which would result in reduced performance. ADF_Flush_to_Disk( ID, error_return ) input: const double ID The ID of a node in the ADF file to flush. output: int *error_return Error return. ***********************************************************************/ void ADF_Flush_to_Disk( const double ID, int *error_return ) { double LID ; unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_fflush_file( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Flush_to_Disk */ /* end of file ADF_Flush_to_Disk.c */ /* file ADF_Get_Data_Type.c */ /*********************************************************************** ADF Get Data Type: Get Data Type. Return the 32 character string in a node's data-type field. In C, the name will be null terminated after the last non-blank character. A maximum of 33 characters may be used (32 for the name plus 1 for the null). ADF_Get_Data_Type( ID, data_type, error_return ) input: const double ID The ID of the node to use. output: char *data_type The 32-character data-type of the node. output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Data_Type( const double ID, char *data_type, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; double LID ; if( data_type == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Copy the blank-filled data-type into a C string **/ ADFI_string_2_C_string( node.data_type, ADF_DATA_TYPE_LENGTH, data_type, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Get_Data_Type */ /* end of file ADF_Get_Data_Type.c */ /* file ADF_Get_Dimension_Values.c */ /*********************************************************************** ADF Get Dimension Values: Get Dimension Values. Return the dimension values for a node. Values will be in the range of 1 to 100,000. Values will only be returned for the number of dimensions defined in the node. If the number of dimensions for the node is zero, an error is returned. ADF_Get_Dimension_Values( ID, dim_vals, error_return ) input: const double ID The ID of the node to use. output: int dim_vals[] Array for returned dimension values. output: int *error_return Error return. Possible errors: NO_ERROR ZERO_DIMENSIONS BAD_NUMBER_OF_DIMENSIONS BAD_DIMENSION_VALUE NULL_POINTER FILE_INDEX_OUT_OF_RANGE BLOCK_OFFSET_OUT_OF_RANGE ***********************************************************************/ void ADF_Get_Dimension_Values( const double ID, cgsize_t dim_vals[], int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; int i ; double LID ; if( dim_vals == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Check for zero dimensions **/ if( node.number_of_dimensions == 0 ) { *error_return = ZERO_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Check for too-large-of dimensions **/ if( node.number_of_dimensions > ADF_MAX_DIMENSIONS ) { *error_return = BAD_NUMBER_OF_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Copy the dimension information **/ for( i=0; i<(int)node.number_of_dimensions; i++ ) { #if CG_SIZEOF_SIZE == 32 if (node.dimension_values[i] > CG_MAX_INT32) { *error_return = MAX_INT32_SIZE_EXCEEDED; CHECK_ADF_ABORT( *error_return ) ; } #endif dim_vals[i] = (cgsize_t)node.dimension_values[i] ; } } /* end of ADF_Get_Dimension_Values */ /* end of file ADF_Get_Dimension_Values.c */ /* file ADF_Get_Error_State.c */ /*********************************************************************** ADF Get Error State: Get Error State. Return the current error state. ADF_Get_Error_State( error_state, error_return ) output: int *error_state Flag for ABORT on error (1) or return error status (0). output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Error_State( int *error_state, int *error_return ) { if( error_state == 0L ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; if( ADF_abort_on_error == TRUE ) *error_state = 1 ; else *error_state = 0 ; } /* end of ADF_Get_Error_State */ /* end of file ADF_Get_Error_State.c */ /* file ADF_Get_Label.c */ /*********************************************************************** ADF Get Label: Return the 32 character string in a node's label field. ADF_Get_Label( ID, label, error_return ) input: const double ID The ID of the node to use. output: char *label The 32-character label of the node. output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Label( const double ID, char *label, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; double LID ; if( label == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Copy the blank-filled label type into a C string **/ ADFI_string_2_C_string( node.label, ADF_LABEL_LENGTH, label, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Get_Label */ /* end of file ADF_Get_Label.c */ /* file ADF_Get_Link_Path.c */ /*********************************************************************** ADF Get Link path: Get path information from a link. If the node is a link-node, return the path information. Else, return an error. If the link is in the same file, then the filename returned is zero length. ADF_Get_Link_Path( ID, file, name_in_file, error_return ) input: const double ID The ID of the node to use. output: char *file The returned filename output: char *name_in_file The returned name of node. output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Link_Path( const double ID, char *file, char *name_in_file, int *error_return ) { unsigned int file_index ; int file_bytes, machine_bytes, total_bytes ; char file_format, machine_format ; struct DISK_POINTER block_offset ; struct NODE_HEADER node_header ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 2 ] ; char link_data[ADF_FILENAME_LENGTH + ADF_MAX_LINK_DATA_SIZE + 1 + 1] ; size_t lenfilename ; char *separator; if( file == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( name_in_file == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_node_header( file_index, &block_offset, &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( (node_header.data_type[0] != 'L') || (node_header.data_type[1] != 'K')) { *error_return = NODE_IS_NOT_A_LINK ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get tokenized datatype **/ ADFI_evaluate_datatype( file_index, node_header.data_type, &file_bytes, &machine_bytes, tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; total_bytes = file_bytes * (int)node_header.dimension_values[0] ; ADFI_read_data_chunk( file_index, &node_header.data_chunks, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, link_data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /* NULL terminate the string */ link_data[ node_header.dimension_values[0] ] = '\0' ; file[0] = '\0' ; name_in_file[0] = '\0' ; /** look for file/link delimiter **/ separator = strchr (link_data, ADF_file[file_index].link_separator); if (separator == NULL) { lenfilename = 0; } else { lenfilename = (size_t)(separator - link_data); } if ( lenfilename == 0 ) /** no filename **/ { strcpy( name_in_file, &link_data[1] ); } else if ( lenfilename > 0 && lenfilename == strlen( link_data ) ) { strcpy( file, link_data) ; /** no link ? **/ } else { strncpy( file, link_data, lenfilename) ; file[lenfilename] = '\0'; strcpy( name_in_file, &link_data[lenfilename+1] ); } /* end if */ } /* end of ADF_Get_Link_Path */ /* end of file ADF_Get_Link_Path.c */ /*********************************************************************** ADF Get size of Link path: Get path information from a link. If the node is a link-node, return the path information. Else, return an error. If the link is in the same file, then the filename returned is zero length. ADF_Link_Size( ID, len_name, len_file, error_return ) input: const double ID The ID of the node to use. output: int *len_file The length of the filename output: int *len_name The length of the node path output: int *error_return Error return. ***********************************************************************/ void ADF_Link_Size( const double ID, int *len_file, int *len_name, int *error_return ) { unsigned int file_index ; int file_bytes, machine_bytes, total_bytes ; char file_format, machine_format ; struct DISK_POINTER block_offset ; struct NODE_HEADER node_header ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 2 ] ; char link_data[ADF_FILENAME_LENGTH + ADF_MAX_LINK_DATA_SIZE + 1 + 1] ; size_t lenfilename ; char *separator; if( len_name == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( len_file == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_node_header( file_index, &block_offset, &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; *len_name = *len_file = 0; if( (node_header.data_type[0] != 'L') || (node_header.data_type[1] != 'K')) { return ; } /* end if */ /** Get tokenized datatype **/ ADFI_evaluate_datatype( file_index, node_header.data_type, &file_bytes, &machine_bytes, tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; total_bytes = file_bytes * (int)node_header.dimension_values[0] ; ADFI_read_data_chunk( file_index, &node_header.data_chunks, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, link_data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /* NULL terminate the string */ link_data[ node_header.dimension_values[0] ] = '\0' ; /** look for file/link delimiter **/ separator = strchr (link_data, ADF_file[file_index].link_separator); if (separator == NULL) { lenfilename = 0; } else { lenfilename = (size_t)(separator - link_data); } if ( lenfilename == 0 ) /** no filename **/ { *len_name = (int)strlen(link_data) - 1; } else if ( lenfilename > 0 && lenfilename == strlen( link_data ) ) { *len_file = (int)lenfilename; } else { *len_file = (int)lenfilename; *len_name = (int)(strlen(link_data) - lenfilename - 1); } /* end if */ } /* end of ADF_Get_Link_Path */ /* file ADF_Get_Name.c */ /*********************************************************************** ADF get name: Get Name of a Node. Given a node's ID, return the 32 character name of that node. ADF_Get_Name( ID, name, error_return ) input: const double ID The ID of the node to use. output: char *name The simple name of the node (no path info). output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Name( const double ID, char *name, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; if( name == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Copy the blank-filled name into a C string **/ ADFI_string_2_C_string( node.name, ADF_NAME_LENGTH, name, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Get_Name */ /* end of file ADF_Get_Name.c */ /* file ADF_Get_Node_ID.c */ /*********************************************************************** ADF get Node ID: Get Unique-Identifier of a Node. Given a parent node ID and a name of a child node, this routine returns the ID of the child. If the child node is a link, the ID of the link node is returned (not the ID of the linked-to node) - otherwise there would be no way to obtain the ID of a link node. The child name may be a simple name or a compound path name. If the name is a compound path name and it begins with a '/', then the parent node ID may be any valid ID in the same database as the first node in the path. If the name is only "/" and the parent ID is any valid ID in the database, the root ID is returned. If the name is a compound path name and does not begin with a '/', then the parent node ID is the ID of the parent of the first node in the path. If the path name contains a link node (except for the ending leaf node), then the link is followed. ADF_Get_Node_ID( PID, name, ID, error_return ) input: const double PID The ID of name's parent. input: const char *name The name of the node. Compound names including path information use a slash "/" notation between node names. If a leading slash is used, then PID can be any valid node ID in the ADF database of the first name in the path. output: double *ID The ID of the named node. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADF_Get_Node_ID( const double PID, const char *name, double *ID, int *error_return ) { double LID ; int found ; int name_length ; unsigned int file_index ; struct DISK_POINTER parent_block_offset, sub_node_entry_location ; struct SUB_NODE_TABLE_ENTRY sub_node_entry ; struct NODE_HEADER node_header ; char *name_tmp, *name_ptr, *name_pos ; if( name == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ name_length = (int)strlen( name ) ; if( name_length == 0 ) { *error_return = STRING_LENGTH_ZERO ; return ; } /* end if */ if( ID == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; *ID = PID ; /** initialize the ID variable to use in intermediate steps **/ if( name[0] == '/' ) { /** start at the root node **/ /** according to user documentation, PID can be any valid node in the database, but we need to use it to get the root ID in order to start at the top **/ ADF_Get_Root_ID( PID, ID, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** This is the root-node, return the Root-ID **/ if( name[ 1 ] == '\0' ) { return ; /** NOT an error, just done and need to get out **/ } /* end if */ } /* end if */ name_tmp = (char *) malloc( (name_length + 1) * sizeof( char ) ) ; if( name_tmp == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ strcpy( name_tmp, name ) ; /** start search for tokens (names separated by '/') **/ name_pos = name_tmp ; name_ptr = ADFI_strtok( name_tmp, &name_pos, "/" ) ; if( name_ptr == NULL ) { /** this should never happen but check anyway **/ *error_return = INVALID_NODE_NAME ; CHECK_ADF_ABORT1( *error_return ) ; } /* end if */ /** Get file-index, etc. to start. Note: Parent ID may be a link **/ ADFI_chase_link( *ID, &LID, &file_index, &parent_block_offset, &node_header, error_return ) ; CHECK_ADF_ABORT1( *error_return ) ; *ID = LID ; /** Track through the possible compound name string **/ while( name_ptr ) { /** Find this child under the current parent **/ ADFI_check_4_child_name( file_index, &parent_block_offset, name_ptr, &found, &sub_node_entry_location, &sub_node_entry, error_return ) ; CHECK_ADF_ABORT1( *error_return ) ; if( found == 0 ) { /** Child NOT found **/ *error_return = CHILD_NOT_OF_GIVEN_PARENT ; CHECK_ADF_ABORT1( *error_return ) ; } /* end if */ /** create the child ID **/ ADFI_file_block_offset_2_ID( file_index, sub_node_entry.child_location.block, sub_node_entry.child_location.offset, ID, error_return ) ; /** Get the next node-name token (NULL if no more). This is needed for the while-loop check and normally would be done at the end of the loop, but it is useful in the next step to see if there are any more branches in the path. **/ name_ptr = ADFI_strtok( name_tmp, &name_pos, "/" ) ; /** If this node is the last in the path it may be a link, but there needs to be a mechanism by which a link's ID can be determined and so we cannot follow the link at this time. **/ if( name_ptr != NULL ) { /* Make sure we have a real ID so we can continue the search */ ADFI_chase_link( *ID, &LID, &file_index, &parent_block_offset, &node_header, error_return ) ; CHECK_ADF_ABORT1( *error_return ) ; *ID = LID ; /** This child now becomes the parent. Do it again... **/ ADFI_ID_2_file_block_offset( *ID, &file_index, &parent_block_offset.block, &parent_block_offset.offset, error_return ) ; CHECK_ADF_ABORT1( *error_return ) ; } /* end if */ } /* end while */ free( name_tmp ) ; } /* end of ADF_Get_Node_ID */ /* end of file ADF_Get_Node_ID.c */ /* file ADF_Get_Number_of_Dimensions.c */ /*********************************************************************** ADF Get Number of Dimensions: Get Number of Dimensions. Return the number of data dimensions used in a node. Valid values are from 0 to 12. ADF_Get_Number_of_Dimensions( ID, num_dims, error_return) input: const double ID The ID of the node to use. output: int *num_dims The returned number of dimensions. output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Number_of_Dimensions( const double ID, int *num_dims, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; double LID ; if( num_dims == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Return the number of dimensions **/ *num_dims = node.number_of_dimensions ; } /* end of ADF_Get_Number_of_Dimensions */ /* end of file ADF_Get_Number_of_Dimensions.c */ /* file ADF_Get_Root_ID.c */ /*********************************************************************** ADF_Get_Root_ID: Get root-ID for an ADF system from any ID in the system. input: const double ID The ID of the node to use. output: *double Root_ID The returned ID of the root node. output: int *error_return Error return. ***********************************************************************/ void ADF_Get_Root_ID( const double ID, double *Root_ID, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct FILE_HEADER file_header ; if( Root_ID == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; /** Get the file ID **/ ADFI_ID_2_file_block_offset( ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Use the file header to find the root ID **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Format the root ID **/ ADFI_file_block_offset_2_ID( file_index, file_header.root_node.block, file_header.root_node.offset, Root_ID, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Get_Root_ID */ /* end of file ADF_Get_Root_ID.c */ /* file ADF_Is_Link.c */ /*********************************************************************** ADF Is Link: Test if a Node is a link. If the actual data-type of the node is "LK" (created with ADF_Link), return the link path length. Otherwise, return 0. ADF_Is_Link( ID, link_path_length, error_return ) input: const double ID The ID of the node to use. output: int *link_path_length 0 if the node is NOT a link. If the node is a link, the length of the path string is returned. output: int *error_return Error return. ***********************************************************************/ void ADF_Is_Link( const double ID, int *link_path_length, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node_header ; if( link_path_length == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get node_header for the node **/ ADFI_read_node_header( file_index, &block_offset, &node_header, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( (node_header.data_type[0] == 'L') && (node_header.data_type[1] == 'K')) *link_path_length = (int)node_header.dimension_values[0] ; else *link_path_length = 0 ; } /* end of ADF_Is_Link */ /* end of file ADF_Is_Link.c */ /* file ADF_Library_Version.c */ /*********************************************************************** ADF Library Version: Get ADF Library Version ID. This is the version number of the ADF library routines which your program is currently using. The format of the version ID is: "ADF Library Version 000.01" ADF_Library_Version( version, error_return ) output: char *version A 32-byte character string containing the ADF Library version ID information. output: int *error_return Error return. ***********************************************************************/ void ADF_Library_Version( char *version, int *error_return ) { int lversion; if( version == NULL ) { *error_return = NULL_STRING_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; /** Copy the proper portion of the "what" string **/ strcpy ( version, &ADF_L_identification[4] ) ; lversion = (int)strlen ( version ) ; version[lversion-1] = '\0' ; /** remove trailing "what" delimiter ('>') **/ } /* end of ADF_Library_Version */ /* end of file ADF_Library_Version.c */ /* file ADF_Link.c */ /*********************************************************************** ADF Link: Create a link. Note: The Node linked to does not have to exist when the link is created (but it may exist and that is OK). However, when the link is used, an error will occur if the linked to node does not exist. ADF_Link( PID, name, file, name_in_file, ID, error_return ) input: const double PID The ID of the Node's parent. input: const char *name The name of the link node. input: const char *file The filename to use for the link (directly usable by a C open() routine). If blank (null), the link will be within the same file. input: const char *name_in_file The name of the node which the link will point to. This can be a simple or compound name. output: double ID The returned ID of the link-node. output: int *error_return Error return. ***********************************************************************/ void ADF_Link( const double PID, const char *name, const char *file_name, const char *name_in_file, double *ID, int *error_return ) { char link_data[ADF_FILENAME_LENGTH + ADF_MAX_LINK_DATA_SIZE + 2] ; int null_filename = FALSE ; int filename_length, linked_to_length, data_length ; cgsize_t dim_vals[1] ; unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node_header ; /** Don't check file since it can be a NULL pointer **/ ADFI_check_string_length( name, ADF_NAME_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_check_string_length( name_in_file, ADF_MAX_LINK_DATA_SIZE, error_return ); CHECK_ADF_ABORT( *error_return ) ; ADF_Is_Link( PID, &linked_to_length, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if ( linked_to_length > 0 ) { *error_return = LINKS_TOO_DEEP ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Create the node in the normal way **/ ADF_Create( PID, name, ID, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( *ID, &file_index, &block_offset.block, &block_offset.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Add the file and linked-to name as data in the child **/ ADFI_check_string_length( file_name, ADF_FILENAME_LENGTH, error_return ) ; if( *error_return != NO_ERROR ) { null_filename = TRUE ; filename_length = 0 ; } /* end if */ else { filename_length = (int)strlen( file_name) ; } /* end else */ linked_to_length = (int)strlen( name_in_file ) ; data_length = filename_length + linked_to_length + 1 ; if( data_length > ADF_FILENAME_LENGTH + ADF_MAX_LINK_DATA_SIZE + 1 ) { *error_return = STRING_LENGTH_TOO_BIG ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( null_filename == TRUE ) { sprintf( link_data, "%c%s", ADF_file[file_index].link_separator, name_in_file ) ; } /* end if */ else { sprintf( link_data, "%s%c%s", file_name, ADF_file[file_index].link_separator, name_in_file ) ; } /* end else */ /** We must use a datatype of "C1" to put the data into this node. With a datatype of "Lk" (a link), the written data will go into the linked-to node (that's the whole point). To set this up we must be careful... **/ dim_vals[0] = data_length ; ADF_Put_Dimension_Information( *ID, "C1", 1, dim_vals, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADF_Write_All_Data( *ID, link_data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Change the datatype to be LK, without deleting the data. We can't use ADF_Put_Dimension_Information since the change of datatype will delete the data. We must do this manually. **/ ADFI_read_node_header( file_index, &block_offset, &node_header, error_return ); CHECK_ADF_ABORT( *error_return ) ; if( (node_header.data_type[0] != 'C') || (node_header.data_type[1] != '1') || (node_header.data_type[2] != ' ') ) { *error_return = INVALID_DATA_TYPE ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ node_header.data_type[0] = 'L' ; node_header.data_type[1] = 'K' ; ADFI_write_node_header( file_index, &block_offset, &node_header, error_return ); CHECK_ADF_ABORT( *error_return ) ; /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Link */ /* end of file ADF_Link.c */ /* file ADF_Move_Child.c */ /*********************************************************************** ADF Move Child: Change Parent (move a Child Node). The node and the 2 parents must all exist within a single ADF file. If the node is pointed to by a link-node, changing the node's parent will break the link. ADF_Move_Child( PID, ID, NPID, error_return ) input: double PID The ID of the Node's parent. input: double ID The ID of the node to use. input: double NPID The ID of the Node's New Parent output: int *error_return Error return. ***********************************************************************/ void ADF_Move_Child( const double PID, const double ID, const double NPID, int *error_return ) { unsigned int parent_file_index, child_file_index, new_parent_file_index, file_index ; char child_name[ ADF_NAME_LENGTH ] ; int found ; struct DISK_POINTER parent, child, new_parent, sub_node_entry_location ; struct SUB_NODE_TABLE_ENTRY sub_node_entry ; *error_return = NO_ERROR ; ADFI_ID_2_file_block_offset( PID, &parent_file_index, &parent.block, &parent.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_ID_2_file_block_offset( ID, &child_file_index, &child.block, &child.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( child_file_index != parent_file_index ) { *error_return = NODES_NOT_IN_SAME_FILE ; CHECK_ADF_ABORT( *error_return ) ; } ADFI_ID_2_file_block_offset( NPID, &new_parent_file_index, &new_parent.block, &new_parent.offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( new_parent_file_index != parent_file_index ) { *error_return = NODES_NOT_IN_SAME_FILE ; CHECK_ADF_ABORT( *error_return ) ; } file_index = parent_file_index ; /* use a shorter, more generic name - file indices should now be the same for all 3 nodes */ /** check that child is really a child of parent **/ ADF_Get_Name( ID, child_name, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_check_4_child_name( file_index, &parent, child_name, &found, &sub_node_entry_location, &sub_node_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( found == 0 ) { /* child not found */ *error_return = CHILD_NOT_OF_GIVEN_PARENT ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** add child to its new parent's sub node table **/ ADFI_add_2_sub_node_table( file_index, &new_parent, &child, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** remove child from its old parent's sub node table **/ ADFI_delete_from_sub_node_table( file_index, &parent, &child, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Move_Child */ /* end of file ADF_Move_Child.c */ /* file ADF_Number_of_Children.c */ /*********************************************************************** ADF Number of Children; Get Number of Children of a Node. Return the number of children nodes directly associated with a parent node. ADF_Number_of_Children( ID, num_children, error_return ) input: const double ID The ID of the node to use. output: int *num_children The number of children directly associated with this node. output: int *error_return Error return. ***********************************************************************/ void ADF_Number_of_Children( const double ID, int *num_children, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; double LID ; if( num_children == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Return the number of children **/ *num_children = node.num_sub_nodes ; } /* end of ADF_Number_of_Children */ /* end of file ADF_Number_of_Children.c */ /* file ADF_Put_Dimension_Information.c */ /*********************************************************************** ADF Put Dimension Information: Set/change the data-type and Dimension Information of a Node. Valid user-definable data-types are: No data MT Integer 32 I4 Integer 64 I8 Unsigned Int 32 U4 Unsigned Int 64 U8 Real 32 R4 Real 64 R8 Complex 64 X4 Complex 128 X8 Character (unsigned byte) C1 Byte (unsigned byte) B1 Compound data-types can be used which combine types ("I4,I4,R8"), define an array ("I4[25]"), or a combination of these ("I4,C1[20],R8[3]"). dims can be a number from 0 to 12. dim_vals is an array of integers. The number of integers used is determined by the dims argument. If dims is zero, the dim_values are not used. Valid range for dim_values are from 1 to 2,147,483,648. The total data size, calculated by the data-type-size times the dimension value(s), cannot exceed 2,147,483,648. Note: When this routine is called and the data-type or the number of dimensions changes, any data currently associated with the node is lost!! The dimension values can be changed and the data space will be extended as needed. ADF_Put_Dimension_Information( ID, data_type, dims, dim_vals, error_return ) input: const double ID The ID of the node. input: const char *data-type The data-type to use. input: const int dims The number of dimensions this node has. input: const int dim_vals[] The dimension values for this node. output: int *error_return Error return. ***********************************************************************/ void ADF_Put_Dimension_Information( const double ID, const char *data_type, const int dims, const cgsize_t dim_vals[], int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 1 + (ADF_DATA_TYPE_LENGTH + 1)/3 ] ; char file_format, machine_format ; int file_bytes[2], machine_bytes[2] ; cgulong_t data_bytes, old_data_bytes ; int i, datatype_length ; int preserve_data = FALSE ; double LID ; ADFI_check_string_length( data_type, ADF_DATA_TYPE_LENGTH, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( dim_vals == NULL && dims > 0 ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Check new datatype **/ ADFI_evaluate_datatype( file_index, data_type, &file_bytes[0], &machine_bytes[0], tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Look at old datatype **/ ADFI_evaluate_datatype( file_index, node.data_type, &file_bytes[1], &machine_bytes[1], tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Calculate new data-size **/ if( dims < 0 ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( dims > ADF_MAX_DIMENSIONS) { *error_return = BAD_NUMBER_OF_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** If the number of dimensions is zero, set data-bytes to zero **/ if( dims == 0 ) data_bytes = 0 ; else { /** Calculate the total number of bytes in the data **/ for( data_bytes=file_bytes[0], i=0; i ADF_NAME_LENGTH ) { *error_return = STRING_LENGTH_TOO_BIG ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( name_length == 0 ) { *error_return = STRING_LENGTH_ZERO ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Need to check for uniqueness and legality of the name **/ ADFI_check_4_child_name( file_index, &parent_block_offset, &name[ name_start ], &found, &sub_node_entry_location, &sub_node_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( found == 1 ) { *error_return = DUPLICATE_CHILD_NAME ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ for ( i=0; i < name_length; i++ ) { if ( ! isprint ( name[ name_start + i ] ) || name[ name_start + i ] == '/' ) { *error_return = INVALID_NODE_NAME; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end for */ /** Confirm that child is from the parent **/ ADFI_check_4_child_name( file_index, &parent_block_offset, child_node.name, &found, &sub_node_entry_location, &sub_node_entry, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( found == 0 ) { *error_return = CHILD_NOT_OF_GIVEN_PARENT ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( (child_block_offset.block != sub_node_entry.child_location.block) || (child_block_offset.offset != sub_node_entry.child_location.offset) ) { *error_return = CHILD_NOT_OF_GIVEN_PARENT ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Copy the name **/ name_length = (int)strlen( name ) ; for( i=0; i total_bytes ) { bytes_to_read = total_bytes - bytes_read ; } /* end if */ if( bytes_to_read == 0 ) break ; ADFI_read_data_chunk( file_index, &data_chunk_table[i].start, tokenized_data_type, file_bytes, bytes_to_read, 0, bytes_to_read, data_pointer, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data_pointer += (bytes_to_read * memory_bytes) / file_bytes ; bytes_read += bytes_to_read ; } /* end for */ free( data_chunk_table ) ; if( bytes_read < total_bytes ) { *error_return = INCOMPLETE_DATA ; memset( data_pointer, 0, (size_t)(total_bytes - bytes_read) ) ; } /* end if */ } /* end else */ } /* end of ADF_Read_All_Data */ /* end of file ADF_Read_All_Data.c */ /* file ADF_Read_Block_Data.c */ /*********************************************************************** ADF Read Block Data: Read a continous block of data from a Node. Reads a block the node's data and returns it into a contiguous memory space. ADF_Read_Block_Data( ID, data, error_return ) input: const double ID The ID of the node to use. input: const long b_start The starting point in block in token space input: const long b_end The ending point in block in token space output: char *data The start of the data in memory. output: int *error_return Error return. ***********************************************************************/ void ADF_Read_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 1 + (ADF_DATA_TYPE_LENGTH + 1)/3 ] ; struct DATA_CHUNK_TABLE_ENTRY *data_chunk_table ; char *data_pointer ; char file_format, machine_format ; int file_bytes, memory_bytes ; cglong_t bytes_to_read ; cglong_t total_bytes, bytes_read, start_offset ; cglong_t chunk_size, chunk_end_byte ; cglong_t start_byte, end_byte, block_bytes ; int i, j ; double LID ; if( data == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get datatype size **/ ADFI_evaluate_datatype( file_index, node.data_type, &file_bytes, &memory_bytes, tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( (file_bytes == 0) || (node.number_of_dimensions == 0) ) { *error_return = NO_DATA ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Calculate total number of bytes in the data **/ total_bytes = file_bytes ; for( j=0; j<(int)node.number_of_dimensions; j++ ) total_bytes *= node.dimension_values[j] ; if( total_bytes == 0 ) { *error_return = ZERO_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Calculate the starting and ending range in the file **/ start_byte = file_bytes * (b_start-1) ; end_byte = file_bytes * b_end ; if ( start_byte < 0 || start_byte > end_byte || end_byte > total_bytes ) { *error_return = START_OUT_OF_DEFINED_RANGE ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ block_bytes = end_byte - start_byte ; /** If there is NO DATA, fill data space with zeros, return error **/ if( node.number_of_data_chunks == 0 ) { memset( data, 0, (size_t)(block_bytes*memory_bytes/file_bytes) ) ; *error_return = NO_DATA ; return ; /** NO_DATA is really a warning, so don't check & abort... **/ } /* end if */ /** Read the data from disk **/ else if( node.number_of_data_chunks == 1 ) { ADFI_read_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, total_bytes, start_byte, block_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else if */ else { /** Allocate memory for the required table space in memory **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( node.number_of_data_chunks * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node.data_chunks, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Read data from each entry in the table **/ bytes_read = 0 ; chunk_end_byte = 0 ; data_pointer = data ; for( i=0; i<(int)node.number_of_data_chunks; i++ ) { chunk_size = (data_chunk_table[i].end.block - data_chunk_table[i].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[i].end.offset - data_chunk_table[i].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; /** Check to be sure we don't think the chunk is bigger than it is (shrinking a data block can cause this) **/ if( chunk_end_byte + chunk_size > total_bytes ) { chunk_size = total_bytes - chunk_end_byte ; } /* end if */ if( chunk_size == 0 ) break ; chunk_end_byte += chunk_size ; /** If start of block not in this chunk then continue **/ if ( start_byte >= chunk_end_byte ) continue ; /** Set offset into the current chunk **/ if ( start_byte > (chunk_end_byte - chunk_size) ) /** The start of the block is inside the current chunk so adjust the offset to the beginning of the block **/ start_offset = ( start_byte - (chunk_end_byte-chunk_size) ) ; else start_offset = 0 ; /** Calculate the number of bytes needed in this chunk **/ bytes_to_read = chunk_size - start_offset ; if( bytes_read + bytes_to_read > block_bytes ) { bytes_to_read = block_bytes - bytes_read ; } /* end if */ if( bytes_to_read == 0 || (chunk_end_byte-chunk_size) > end_byte ) break ; ADFI_read_data_chunk( file_index, &data_chunk_table[i].start, tokenized_data_type, file_bytes, chunk_size, start_offset, bytes_to_read, data_pointer, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data_pointer += (bytes_to_read * memory_bytes) / file_bytes ; bytes_read += bytes_to_read ; } /* end for */ free( data_chunk_table ) ; if( bytes_read < block_bytes ) { *error_return = INCOMPLETE_DATA ; memset( data_pointer, 0, (size_t)(total_bytes - bytes_read) ) ; } /* end if */ } /* end else */ } /* end of ADF_Read_Block_Data */ /* end of file ADF_Read_Block_Data.c */ /* file ADF_Read_Data.c */ /*********************************************************************** ADF Read Data: Read data from a node, with partial capabilities. The partial capabilities are both in the node's data and also in memory. Vectors of integers are used to indicate the data to be accessed from the node, and another set of integer vectors is used to describe the memory location for the data. Note: If the data-type of the node is a compound data-type ("I4[3],R8") for example, the partial capabilities will access one or more of these 20-byte data entities. You cannot access a subset of an occurrence of the data-type. ADF_Read_Data( ID, s_start[], s_end[], s_stride[], m_num_dims, m_dims[], m_start[], m_end[], m_stride[], data, error_return ) input: const double ID The ID of the node to use. input: const int s_start[] The starting dimension values to use in the database (node). input: const int s_end[] The ending dimension values to use in the database (node). input: const int s_stride[] The stride values to use in the database (node). input: const int m_num_dims The number of dimensions to use in memory. input: const int m_dims[] The dimensionality to use in memory. input: const int m_start[] The starting dimension values to use in memory. input: const int m_end[] The ending dimension values to use in memory. input: const int m_stride[] The stride values to use in memory. output: char *data The start of the data in memory. output: int *error_return Error return. ***********************************************************************/ void ADF_Read_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], char *data, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset, relative_block ; struct NODE_HEADER node ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 1 + (ADF_DATA_TYPE_LENGTH + 1)/3 ] ; cglong_t current_disk[ADF_MAX_DIMENSIONS] ; cglong_t current_memory[ADF_MAX_DIMENSIONS] ; cgulong_t total_disk_elements, total_memory_elements ; cgulong_t disk_offset, memory_offset ; cgulong_t memory_dims[ADF_MAX_DIMENSIONS] ; char disk_format, machine_format ; int formats_compare ; int i ; int file_bytes = 0 ; int memory_bytes = 0 ; int no_data = FALSE ; double LID ; cgulong_t relative_offset = 0, current_chunk_size = 0, past_chunk_sizes = 0, current_chunk = 0, disk_elem ; struct DATA_CHUNK_TABLE_ENTRY *data_chunk_table = NULL; if( (s_start == NULL) || (s_end == NULL) || (s_stride == NULL) || (m_dims == NULL) || (m_start == NULL) || (m_end == NULL) || (m_stride == NULL) || (data == NULL) ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get datatype length **/ ADFI_evaluate_datatype( file_index, node.data_type, &file_bytes, &memory_bytes, tokenized_data_type, &disk_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( (file_bytes == 0) || (node.number_of_dimensions == 0) ) { *error_return = NO_DATA ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_count_total_array_points( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, &total_disk_elements, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; for (i = 0; i < m_num_dims; i++) memory_dims[i] = m_dims[i]; ADFI_count_total_array_points( (unsigned int)m_num_dims, memory_dims, m_start, m_end, m_stride, &total_memory_elements, &memory_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( total_disk_elements != total_memory_elements ) { *error_return = UNEQUAL_MEMORY_AND_DISK_DIMS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_file_and_machine_compare( file_index, tokenized_data_type, &formats_compare, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Check to see if there is actual data to use **/ if( node.number_of_data_chunks == 0 ) { no_data = TRUE ; } /* end if */ /** Check for multiple data-chunks **/ else if( node.number_of_data_chunks == 1 ) { /** A single data chunk **/ /** Point to the start of the data **/ block_offset.block = node.data_chunks.block ; block_offset.offset = node.data_chunks.offset + TAG_SIZE + DISK_POINTER_SIZE + disk_offset * file_bytes ; ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else if */ else if( node.number_of_data_chunks > 1 ) { /** Multiple data chunks **/ current_chunk = 0 ; past_chunk_sizes = 0 ; relative_offset = disk_offset * file_bytes ; /** Allocate memory for the required table space in memory **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( node.number_of_data_chunks * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node.data_chunks, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; current_chunk_size = (data_chunk_table[ current_chunk ].end.block - data_chunk_table[ current_chunk ].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[ current_chunk ].end.offset - data_chunk_table[ current_chunk ].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; } /* end else if */ /** Setup initial indexing **/ for( i=0; i<(int)node.number_of_dimensions; i++ ) current_disk[i] = s_start[i] ; for( i=0; i DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ if( formats_compare ) { /** Read the data off of disk directly **/ ADFI_read_file( file_index, block_offset.block, block_offset.offset, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /** Read and translate data **/ ADFI_read_data_translated( file_index, block_offset.block, block_offset.offset, tokenized_data_type, file_bytes, file_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Increment disk pointers, for the special case of one dimensional data we will a simple increment to maximize the throught. Thus for block reads you can temporarily change to 1D for the read to improve efficiency. Note total size shouldn't change!! **/ if( disk_elem < total_disk_elements - 1 ) { if ( node.number_of_dimensions == 1 ) { disk_offset = s_stride[0]; current_disk[0] += disk_offset; if ( current_disk[0] > s_end[0] ) current_disk[0] = s_end[0] ; } /* end if */ else { ADFI_increment_array( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, current_disk, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ block_offset.offset += disk_offset * file_bytes ; if ( block_offset.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end if */ } /* end else if */ else if( node.number_of_data_chunks > 1 ) { /** Multiple data chunks **/ while( relative_offset >= past_chunk_sizes + current_chunk_size ) { if( ++current_chunk >= node.number_of_data_chunks ) { *error_return = INCOMPLETE_DATA ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { past_chunk_sizes += current_chunk_size ; current_chunk_size = (data_chunk_table[ current_chunk ].end.block - data_chunk_table[ current_chunk ].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[ current_chunk ].end.offset - data_chunk_table[ current_chunk ].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; } /* end else */ } /* end while */ /** Get the data off of disk **/ relative_block.block = data_chunk_table[ current_chunk ].start.block ; relative_block.offset = data_chunk_table[ current_chunk ].start.offset + (TAG_SIZE + DISK_POINTER_SIZE) + (relative_offset - past_chunk_sizes) ; if ( relative_block.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &relative_block, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } if( formats_compare ) { /** Read the data off of disk directly **/ ADFI_read_file( file_index, relative_block.block, relative_block.offset, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /** Read and translate data **/ ADFI_read_data_translated( file_index, relative_block.block, relative_block.offset, tokenized_data_type, file_bytes, file_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Increment disk pointers **/ if( disk_elem < total_disk_elements - 1 ) { if ( node.number_of_dimensions == 1 ) { disk_offset = s_stride[0]; current_disk[0] += disk_offset; if ( current_disk[0] > s_end[0] ) current_disk[0] = s_end[0] ; } /* end if */ else { ADFI_increment_array( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, current_disk, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ relative_offset += disk_offset * file_bytes ; } /* end if */ } /* end else if */ if( disk_elem < total_disk_elements - 1 ) { /** Increment memory pointers **/ if ( m_num_dims == 1 ) { memory_offset = m_stride[0]; current_memory[0] += disk_offset; if ( current_memory[0] > m_end[0] ) current_memory[0] = m_end[0] ; } /* end if */ else { ADFI_increment_array( (unsigned int)m_num_dims, memory_dims, m_start, m_end, m_stride, current_memory, &memory_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Adjust data pointer **/ data += memory_offset * memory_bytes ; } /* end if */ } /* end for */ if( node.number_of_data_chunks > 1 ) /** Multiple data chunks **/ free( data_chunk_table ) ; } /* end of ADF_Read_Data */ /* end of file ADF_Read_Data.c */ /* file ADF_Set_Error_State.c */ /*********************************************************************** ADF Set Error State: Set Error State. For all ADF calls, set the error handling convention; either return error codes, or abort the program on an error. The default state for the ADF interface is to return error codes and NOT abort. ADF_Set_Error_State( error_state, error_return ) input: const int error_state Flag for ABORT on error (1) or return error status (0). output: int *error_return Error return. ***********************************************************************/ void ADF_Set_Error_State( const int error_state, int *error_return ) { *error_return = NO_ERROR ; if( error_state == 0 ) ADF_abort_on_error = FALSE ; else if( error_state == 1 ) ADF_abort_on_error = TRUE ; else { *error_return = BAD_ERROR_STATE ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ } /* end of ADF_Set_Error_State */ /* end of file ADF_Set_Error_State.c */ /* file ADF_Set_Label.c */ /*********************************************************************** ADF Set Label: Set Label. Set the 32 character string in a node's label field. ADF_Set_Label( ID, label, error_return ) input: const double ID The ID of the node to use. input: const char *label The 32-character label of the node. output: int *error_return Error return. ***********************************************************************/ void ADF_Set_Label( const double ID, const char *label, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset ; struct NODE_HEADER node ; int i, label_length ; double LID ; /** Don't check for NULL or BLANK label, these are OK **/ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Copy the label **/ if( label == NULL ) label_length = 0 ; /* copy none, then blank fill */ else label_length = (int)strlen( label ) ; if( label_length > ADF_LABEL_LENGTH ) { *error_return = STRING_LENGTH_TOO_BIG ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ for( i=0; i chunk_total_bytes ) { /** Write the part of the new data to existing data-chunk **/ ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, chunk_total_bytes, 0, chunk_total_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Allocate a second data chunk **/ total_bytes -= chunk_total_bytes ; ADFI_file_malloc( file_index, total_bytes + TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE, &new_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write the rest of the data **/ /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data += (chunk_total_bytes * memory_bytes ) / file_bytes ; ADFI_write_data_chunk( file_index, &new_block_offset, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Allocate a data-chunk-table for two entries **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + 5 * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write data-chunk-table to disk **/ data_chunk_entry_table[0].start.block = node.data_chunks.block ; data_chunk_entry_table[0].start.offset = node.data_chunks.offset ; chunk_start.block = node.data_chunks.block ; chunk_start.offset = node.data_chunks.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** get the size of the data_chunk for the table end pointer **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_entry_table[0].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_entry_table[1].start.block = new_block_offset.block ; data_chunk_entry_table[1].start.offset = new_block_offset.offset ; chunk_start.block = new_block_offset.block ; chunk_start.offset = new_block_offset.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** get the size of the data_chunk for the table end pointer **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_entry_table[1].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, 2, data_chunk_entry_table, error_return ) ; /** Update node header with number of data-chunks = 2 and the pointer to the data-chunk-table **/ node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; node.number_of_data_chunks = 2 ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /** Write the new data to existing data-chunk **/ ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ } /* end else if */ else { /** Multiple data chunks **/ /** Allocate memory for the data-chunk-table, with an additional entry in case we need to grow it **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( (node.number_of_data_chunks + 1 ) * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node.data_chunks, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** looping on the data-chunks, write the size of the current chunk **/ for( i=0; i<(int)node.number_of_data_chunks; i++ ) { current_bytes = (data_chunk_table[i].end.block - data_chunk_table[i].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[i].end.offset - data_chunk_table[i].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; /** Limit the number of bytes written by whats left to write. **/ current_bytes = MIN( current_bytes, total_bytes ) ; ADFI_write_data_chunk( file_index, &data_chunk_table[i].start, tokenized_data_type, file_bytes, current_bytes, 0, current_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data += (current_bytes * memory_bytes ) / file_bytes ; total_bytes -= current_bytes ; if( total_bytes <= 0 ) break ; } /* end for */ /** If we are out of data-chunks and have data left, allocate a new data-chunk in the file. **/ if( total_bytes > 0 ) { /** Write data-chunk-table to disk **/ /** allocate data space in the file **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + DISK_POINTER_SIZE + total_bytes, &data_chunk_table[ node.number_of_data_chunks ].start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_table[ node.number_of_data_chunks ].end.block = data_chunk_table[ node.number_of_data_chunks ].start.block ; data_chunk_table[ node.number_of_data_chunks ].end.offset = data_chunk_table[ node.number_of_data_chunks ].start.offset + TAG_SIZE + DISK_POINTER_SIZE + total_bytes ; ADFI_adjust_disk_pointer( &data_chunk_table[ node.number_of_data_chunks ].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** allocate space for the new data-chunk-entry-table **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + (2 * (node.number_of_data_chunks + 1) + 1) * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, node.number_of_data_chunks+1, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk( file_index, &data_chunk_table[node.number_of_data_chunks ].start, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Free the old data-chunk-table **/ ADFI_file_free( file_index, &node.data_chunks, 0, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Update node header with number of data-chunks++ and the pointer to the data-chunk-table **/ node.number_of_data_chunks++ ; node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ free( data_chunk_table ) ; } /* end else */ /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Write_All_Data */ /* end of file ADF_Write_All_Data.c */ /* end of file ADF_Write_All_Data.c */ /* file ADF_Write_Block_Data.c */ /*********************************************************************** ADF Write Block Data: Write all data to a Node. Writes all the node's data from a contiguous memory space. ADF_Write_All_Data( ID, data, error_return ) input: const double ID The ID of the node to use. input: const long b_start The starting point in block in token space input: const long b_end The ending point in block in token space input: const char *data The start of the data in memory. output: int *error_return Error return. ***********************************************************************/ void ADF_Write_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset, new_block_offset, dct_block_offset ; struct NODE_HEADER node ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 1 + (ADF_DATA_TYPE_LENGTH + 1)/3 ] ; struct DATA_CHUNK_TABLE_ENTRY data_chunk_entry_table[2], *data_chunk_table ; char file_format, machine_format ; int file_bytes, memory_bytes ; cglong_t total_bytes, bytes_written, bytes_to_write = 0; int i, j ; char tag[TAG_SIZE+1] ; struct DISK_POINTER data_start, chunk_start, end_of_chunk_tag ; cglong_t start_offset ; cglong_t chunk_size, chunk_end_byte ; cglong_t start_byte, end_byte, block_bytes ; double LID ; if( data == NULL ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get the datatype length **/ ADFI_evaluate_datatype( file_index, node.data_type, &file_bytes, &memory_bytes, tokenized_data_type, &file_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Calculate the total number of data bytes **/ total_bytes = file_bytes ; for( j=0; j<(int)node.number_of_dimensions; j++ ) total_bytes *= node.dimension_values[j] ; if( total_bytes == 0 ) { *error_return = ZERO_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Calculate the starting and ending range in the file **/ start_byte = file_bytes * (b_start-1) ; end_byte = file_bytes * b_end ; if ( start_byte < 0 || start_byte > end_byte || end_byte > total_bytes ) { *error_return = START_OUT_OF_DEFINED_RANGE ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ block_bytes = end_byte - start_byte ; /** If there currently is NO data, allocate disk space for it **/ if( node.number_of_data_chunks == 0 ) { ADFI_file_malloc( file_index, total_bytes + TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE, &node.data_chunks, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write the new data **/ ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, total_bytes, start_byte, block_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Record the modified the node-header **/ node.number_of_data_chunks = 1 ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else if( node.number_of_data_chunks == 1 ) { /** Get the data length **/ ADFI_read_chunk_length( file_index, &node.data_chunks, tag, &end_of_chunk_tag, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; tag[TAG_SIZE] = '\0' ; /** Check start-of-chunk tag **/ if( ADFI_stridx_c( tag, data_chunk_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Point to the start of the data **/ data_start.block = node.data_chunks.block ; data_start.offset = node.data_chunks.offset + TAG_SIZE + DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( &data_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** See if the new data exceedes the existing data space **/ chunk_size = end_of_chunk_tag.offset - data_start.offset + (end_of_chunk_tag.block - data_start.block) * DISK_BLOCK_SIZE ; /** If Data grew: Write old size, then allocate more data-space and write the rest **/ if( total_bytes > chunk_size ) { /** Write the part of the new data to existing data-chunk **/ bytes_written = 0 ; if ( start_byte <= chunk_size ) { bytes_to_write = MIN ( block_bytes, (chunk_size-start_byte) ) ; ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, chunk_size, start_byte, bytes_to_write, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; bytes_written += bytes_to_write ; } /* end if */ /** Allocate a second data chunk **/ total_bytes -= chunk_size ; ADFI_file_malloc( file_index, total_bytes + TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE, &new_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write the rest of the data **/ /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data += (bytes_to_write * memory_bytes ) / file_bytes ; if ( bytes_written < block_bytes ) { bytes_to_write = block_bytes - bytes_written ; start_offset = MAX ( 0L, (start_byte - chunk_size) ) ; ADFI_write_data_chunk( file_index, &new_block_offset, tokenized_data_type, file_bytes, total_bytes, start_offset, bytes_to_write, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { ADFI_write_data_chunk( file_index, &new_block_offset, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, NULL, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Allocate a data-chunk-table for two entries **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + 5 * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write data-chunk-table to disk **/ data_chunk_entry_table[0].start.block = node.data_chunks.block ; data_chunk_entry_table[0].start.offset = node.data_chunks.offset ; /** get the size of the data_chunk for the table end pointer **/ chunk_start.block = node.data_chunks.block ; chunk_start.offset = node.data_chunks.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_entry_table[0].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_entry_table[1].start.block = new_block_offset.block ; data_chunk_entry_table[1].start.offset = new_block_offset.offset ; chunk_start.block = new_block_offset.block ; chunk_start.offset = new_block_offset.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** get the size of the data_chunk for the table end pointer **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_entry_table[1].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, 2, data_chunk_entry_table, error_return ) ; /** Update node header with number of data-chunks = 2 and the pointer to the data-chunk-table **/ node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; node.number_of_data_chunks = 2 ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ); CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /** Write the new data to existing data-chunk **/ ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, chunk_size, start_byte, block_bytes, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ } /* end else if */ else { /** Multiple data chunks **/ /** Allocate memory for the data-chunk-table, with an additional entry in case we need to grow it **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( (node.number_of_data_chunks + 1 ) * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node.data_chunks, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** looping on the data-chunks, write the size of the current chunk **/ chunk_end_byte = 0 ; bytes_written = 0 ; for( i=0; i<(int)node.number_of_data_chunks; i++ ) { chunk_size = (data_chunk_table[i].end.block - data_chunk_table[i].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[i].end.offset - data_chunk_table[i].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; chunk_end_byte += chunk_size ; /** If start of block not in this chunk then continue **/ if ( start_byte > chunk_end_byte ) continue ; /** Set offset into the current chunk **/ if ( start_byte > (chunk_end_byte - chunk_size) ) /** The start of the block is inside the current chunk so adjust the offset to the beginning of the block **/ start_offset = ( start_byte - (chunk_end_byte-chunk_size) ) ; else start_offset = 0 ; /** Check to be sure we aren't writing too much data **/ bytes_to_write = chunk_size - start_offset ; if( bytes_written + bytes_to_write > block_bytes ) { bytes_to_write = block_bytes - bytes_written ; } /* end if */ if( bytes_to_write == 0 || (chunk_end_byte-chunk_size) > end_byte ) continue ; /** Write the chunk **/ ADFI_write_data_chunk( file_index, &data_chunk_table[i].start, tokenized_data_type, file_bytes, chunk_size, start_offset, bytes_to_write, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** note: memory_bytes and file_bytes might be different (e.g., if machine is "IEEE_BIG" and file is "CRAY") in which case data pointer advances at a different rate from file pointer. **/ data += (bytes_to_write * memory_bytes ) / file_bytes ; bytes_written += bytes_to_write ; } /* end for */ /** If we are out of data-chunks and have data left, allocate a new data-chunk in the file. **/ total_bytes -= chunk_end_byte ; if( total_bytes > 0 ) { /** Write data-chunk-table to disk **/ /** allocate data space in the file **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + DISK_POINTER_SIZE + total_bytes, &data_chunk_table[ node.number_of_data_chunks ].start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_table[ node.number_of_data_chunks ].end.block = data_chunk_table[ node.number_of_data_chunks ].start.block ; data_chunk_table[ node.number_of_data_chunks ].end.offset = data_chunk_table[ node.number_of_data_chunks ].start.offset + TAG_SIZE + DISK_POINTER_SIZE + total_bytes ; ADFI_adjust_disk_pointer( &data_chunk_table[ node.number_of_data_chunks ].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** allocate space for the new data-chunk-entry-table **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + (2 * (node.number_of_data_chunks + 1) + 1) * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, node.number_of_data_chunks+1, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if ( bytes_written < block_bytes ) { bytes_to_write = block_bytes - bytes_written ; start_offset = MAX ( 0L, (start_byte - total_bytes) ) ; ADFI_write_data_chunk( file_index, &data_chunk_table[node.number_of_data_chunks ].start, tokenized_data_type, file_bytes, total_bytes, start_offset, bytes_to_write, data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { ADFI_write_data_chunk( file_index, &data_chunk_table[node.number_of_data_chunks ].start, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, NULL, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Free the old data-chunk-table **/ ADFI_file_free( file_index, &node.data_chunks, 0, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Update node header with number of data-chunks++ and the pointer to the data-chunk-table **/ node.number_of_data_chunks++ ; node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ free( data_chunk_table ) ; } /* end else */ /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Write_Block_Data */ /* end of file ADF_Write_Block_Data.c */ /* file ADF_Write_Data.c */ /*********************************************************************** ADF Write Data: Write data to a Node, with partial capabilities. See ADF_Read_Data for description. ADF_Write_Data( ID, s_start[], s_end[], s_stride[], m_num_dims, m_dims[], m_start[], m_end[], m_stride[], data, error_return ) input: const double ID The ID of the node to use. input: const int s_start[] The starting dimension values to use in the database (node). input: const int s_end[] The ending dimension values to use in the database (node). input: const int s_stride[] The stride values to use in the database (node). input: const int m_num_dims The number of dimensions to use in memory. input: const int m_dims[] The dimensionality to use in memory. input: const int m_start[] The starting dimension values to use in memory. input: const int m_end[] The ending dimension values to use in memory. input: const int m_stride[] The stride values to use in memory. input: const char *data The start of the data in memory. output: int *error_return Error return. ***********************************************************************/ void ADF_Write_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], const char *data, int *error_return ) { unsigned int file_index ; struct DISK_POINTER block_offset, dct_block_offset, relative_block ; struct DISK_POINTER data_start, new_block_offset ; struct DISK_POINTER chunk_start, end_of_chunk_tag ; struct NODE_HEADER node ; struct DATA_CHUNK_TABLE_ENTRY *data_chunk_table ; struct TOKENIZED_DATA_TYPE tokenized_data_type[ 1 + (ADF_DATA_TYPE_LENGTH + 1)/3 ] ; cglong_t current_disk[ADF_MAX_DIMENSIONS] ; cglong_t current_memory[ADF_MAX_DIMENSIONS] ; cgulong_t total_disk_elements, total_memory_elements ; cgulong_t disk_offset, memory_offset ; cgulong_t memory_dims[ADF_MAX_DIMENSIONS]; int formats_compare ; char disk_format, machine_format ; int i ; int file_bytes = 0 ; int memory_bytes = 0 ; char tag[TAG_SIZE+1] ; cgulong_t total_bytes, disk_elem ; cglong_t current_bytes, chunk_total_bytes ; double LID ; cgulong_t relative_offset, current_chunk, current_chunk_size, past_chunk_sizes ; if( (s_start == NULL) || (s_end == NULL) || (s_stride == NULL) || (m_dims == NULL) || (m_start == NULL) || (m_end == NULL) || (m_stride == NULL) || (data == NULL) ) { *error_return = NULL_POINTER ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ *error_return = NO_ERROR ; data_chunk_table = 0L ; ADFI_chase_link( ID, &LID, &file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Get datatype length **/ ADFI_evaluate_datatype( file_index, node.data_type, &file_bytes, &memory_bytes, tokenized_data_type, &disk_format, &machine_format, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( (file_bytes == 0) || (node.number_of_dimensions == 0) ) { *error_return = NO_DATA ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ ADFI_count_total_array_points( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, &total_disk_elements, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; for (i = 0; i < m_num_dims; i++) memory_dims[i] = m_dims[i]; ADFI_count_total_array_points( (unsigned int)m_num_dims, memory_dims, m_start, m_end, m_stride, &total_memory_elements, &memory_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; if( total_disk_elements != total_memory_elements ) { *error_return = UNEQUAL_MEMORY_AND_DISK_DIMS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Calculate the total number of data bytes **/ total_bytes = file_bytes ; for( i=0; i<(int)node.number_of_dimensions; i++ ) total_bytes *= node.dimension_values[i] ; if( total_bytes == 0 ) { *error_return = ZERO_DIMENSIONS ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** check for need of data translation **/ ADFI_file_and_machine_compare( file_index, tokenized_data_type, &formats_compare, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** If there currently is NO data, allocate disk space for it **/ if( node.number_of_data_chunks == 0 ) { ADFI_file_malloc( file_index, total_bytes + TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE, &node.data_chunks, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** initialize the new disk_space with zero's, then we'll write the partial data **/ ADFI_write_data_chunk( file_index, &node.data_chunks, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, 0L, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Record the modified the node-header **/ node.number_of_data_chunks = 1 ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** If one data chunk, check to see if we need to add a second **/ else if( node.number_of_data_chunks == 1 ) { /** Get the data length **/ ADFI_read_chunk_length( file_index, &node.data_chunks, tag, &end_of_chunk_tag, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; tag[TAG_SIZE] = '\0' ; /** Check start-of-chunk tag **/ if( ADFI_stridx_c( tag, data_chunk_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Point to the start of the data **/ data_start.block = node.data_chunks.block ; data_start.offset = node.data_chunks.offset + TAG_SIZE + DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( &data_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** See if the new data exceedes the existing data space **/ chunk_total_bytes = end_of_chunk_tag.offset - data_start.offset + (end_of_chunk_tag.block - data_start.block) * DISK_BLOCK_SIZE ; /** If Data grew: Allocate more data-space and initialize to zero**/ if( (cglong_t) total_bytes > chunk_total_bytes ) { /** Allocate memory for the data-chunk-table, with an additional entry in case we need to grow it **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( (node.number_of_data_chunks + 1 ) * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Allocate a second data chunk **/ total_bytes -= chunk_total_bytes ; ADFI_file_malloc( file_index, total_bytes + TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE, &new_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Initialize the new data with zeros **/ ADFI_write_data_chunk( file_index, &new_block_offset, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, 0L, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Allocate a data-chunk-table for two entries **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + 5 * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Write data-chunk-table to disk **/ data_chunk_table[0].start.block = node.data_chunks.block ; data_chunk_table[0].start.offset = node.data_chunks.offset ; chunk_start.block = node.data_chunks.block ; chunk_start.offset = node.data_chunks.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** get the size of the data_chunk for the table end pointer **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_table[0].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_table[1].start.block = new_block_offset.block ; data_chunk_table[1].start.offset = new_block_offset.offset ; chunk_start.block = new_block_offset.block ; chunk_start.offset = new_block_offset.offset + TAG_SIZE ; ADFI_adjust_disk_pointer( &chunk_start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** get the size of the data_chunk for the table end pointer **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_start.block, chunk_start.offset, &data_chunk_table[1].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, 2, data_chunk_table, error_return ) ; /** Update node header with number of data-chunks = 2 and the pointer to the data-chunk-table **/ node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; node.number_of_data_chunks = 2 ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end else if */ else { /** Multiple data chunks, check to see if we need to add one mode **/ /** Allocate memory for the data-chunk-table, with an additional entry in case we need to grow it **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( (node.number_of_data_chunks + 1 ) * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node.data_chunks, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** looping on the data-chunks, look at the size of the chunks **/ for( i=0; i<(int)node.number_of_data_chunks; i++ ) { current_bytes = (data_chunk_table[i].end.block - data_chunk_table[i].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[i].end.offset - data_chunk_table[i].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; total_bytes -= current_bytes ; if( total_bytes <= 0 ) break ; } /* end for */ /** If we are out of data-chunks and have data left, allocate a new data-chunk in the file. **/ if( total_bytes > 0 ) { /** Write data-chunk-table to disk **/ /** allocate data space in the file **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + DISK_POINTER_SIZE + total_bytes, &data_chunk_table[ node.number_of_data_chunks ].start, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; data_chunk_table[ node.number_of_data_chunks ].end.block = data_chunk_table[ node.number_of_data_chunks ].start.block ; data_chunk_table[ node.number_of_data_chunks ].end.offset = data_chunk_table[ node.number_of_data_chunks ].start.offset + TAG_SIZE + DISK_POINTER_SIZE + total_bytes ; ADFI_adjust_disk_pointer( &data_chunk_table[ node.number_of_data_chunks ].end, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** allocate space for the new data-chunk-entry-table **/ ADFI_file_malloc( file_index, 2 * TAG_SIZE + (2 * (node.number_of_data_chunks + 1) + 1) * DISK_POINTER_SIZE, &dct_block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; ADFI_write_data_chunk_table( file_index, &dct_block_offset, node.number_of_data_chunks+1, data_chunk_table, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Initialize the new data chunk to zeros **/ ADFI_write_data_chunk( file_index, &data_chunk_table[node.number_of_data_chunks ].start, tokenized_data_type, file_bytes, total_bytes, 0, total_bytes, 0L, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Free the old data-chunk-table **/ ADFI_file_free( file_index, &node.data_chunks, 0, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Update node header with number of data-chunks++ and the pointer to the data-chunk-table **/ node.number_of_data_chunks++ ; node.data_chunks.block = dct_block_offset.block ; node.data_chunks.offset = dct_block_offset.offset ; ADFI_write_node_header( file_index, &block_offset, &node, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ } /* end else */ /** Do single data-chunks here... **/ if( node.number_of_data_chunks == 1 ) { /** Point to the start of the data **/ block_offset.block = node.data_chunks.block ; block_offset.offset = node.data_chunks.offset + TAG_SIZE + DISK_POINTER_SIZE + disk_offset * file_bytes ; ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; /** Setup initial indexing **/ for( i=0; i<(int)node.number_of_dimensions; i++ ) current_disk[i] = s_start[i] ; for( i=0; i DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /** Here is where we need to check for spanning multiple data-chunks **/ /** Put the data out to disk **/ if( formats_compare ) { /* directly */ ADFI_write_file( file_index, block_offset.block, block_offset.offset, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /* translated */ ADFI_write_data_translated( file_index, block_offset.block, block_offset.offset, tokenized_data_type, file_bytes, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Increment disk/memory pointers, for the special case of one dimensional data we will a simple increment to maximize the throught. Thus for block writes you can temporarily change to 1D for the read to improve efficiency. Note total size shouldn't change!! **/ if( disk_elem < total_disk_elements - 1 ) { if ( node.number_of_dimensions == 1 ) { disk_offset = s_stride[0]; current_disk[0] += disk_offset; if ( current_disk[0] > s_end[0] ) current_disk[0] = s_end[0] ; } /* end if */ else { ADFI_increment_array( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, current_disk, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ if ( m_num_dims == 1 ) { memory_offset = m_stride[0]; current_memory[0] += disk_offset; if ( current_memory[0] > m_end[0] ) current_memory[0] = m_end[0] ; } /* end if */ else { ADFI_increment_array( (unsigned int)m_num_dims, memory_dims, m_start, m_end, m_stride, current_memory, &memory_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ block_offset.offset += disk_offset * file_bytes ; if ( block_offset.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &block_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Adjust data pointer **/ data += memory_offset * memory_bytes ; } /* end if */ } /* end for */ } /* end if */ else { /** Point to the start of the data **/ current_chunk = 0 ; past_chunk_sizes = 0 ; relative_offset = disk_offset * file_bytes ; current_chunk_size = (data_chunk_table[ current_chunk ].end.block - data_chunk_table[ current_chunk ].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[ current_chunk ].end.offset - data_chunk_table[ current_chunk ].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; /** Setup initial indexing **/ for( i=0; i<(int)node.number_of_dimensions; i++ ) current_disk[i] = s_start[i] ; for( i=0; i= past_chunk_sizes + current_chunk_size ) { if( ++current_chunk >= node.number_of_data_chunks ) { *error_return = INCOMPLETE_DATA ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { past_chunk_sizes += current_chunk_size ; current_chunk_size = (data_chunk_table[ current_chunk ].end.block - data_chunk_table[ current_chunk ].start.block) * DISK_BLOCK_SIZE + (data_chunk_table[ current_chunk ].end.offset - data_chunk_table[ current_chunk ].start.offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; } /* end else */ } /* end while */ /** Put the data to disk **/ relative_block.block = data_chunk_table[ current_chunk ].start.block ; relative_block.offset = data_chunk_table[ current_chunk ].start.offset + (TAG_SIZE + DISK_POINTER_SIZE) + (relative_offset - past_chunk_sizes) ; if ( relative_block.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &relative_block, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Put the data out to disk **/ if( formats_compare ) { /* directly */ ADFI_write_file( file_index, relative_block.block, relative_block.offset, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ else { /* translated */ ADFI_write_data_translated( file_index, relative_block.block, relative_block.offset, tokenized_data_type, file_bytes, file_bytes, (char *)data, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end if */ /** Increment disk and memory pointers **/ if( disk_elem < total_disk_elements - 1 ) { if ( node.number_of_dimensions == 1 ) { disk_offset = s_stride[0]; current_disk[0] += disk_offset; if ( current_disk[0] > s_end[0] ) current_disk[0] = s_end[0] ; } /* end if */ else { ADFI_increment_array( node.number_of_dimensions, node.dimension_values, s_start, s_end, s_stride, current_disk, &disk_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ relative_offset += disk_offset * file_bytes ; if ( m_num_dims == 1 ) { memory_offset = m_stride[0]; current_memory[0] += disk_offset; if ( current_memory[0] > m_end[0] ) current_memory[0] = m_end[0] ; } /* end if */ else { ADFI_increment_array( (unsigned int)m_num_dims, memory_dims, m_start, m_end, m_stride, current_memory, &memory_offset, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end else */ /** Adjust data pointer **/ data += memory_offset * memory_bytes ; } /* end if */ } /* end for */ } /* end else */ if( data_chunk_table != 0L ) free( data_chunk_table ) ; /** Finally, update modification date **/ ADFI_write_modification_date( file_index, error_return ) ; CHECK_ADF_ABORT( *error_return ) ; } /* end of ADF_Write_Data */ /* end of file ADF_Write_Data.c */ /* end of combine 2.0 */ CGNS-3.4.0/src/adf/ADF_internals.c000066400000000000000000011315071343724673500164340ustar00rootroot00000000000000/* created by combine 2.0 */ /* file ADFI_AAA_var.c */ /*** File: ADF_internals.c ---------------------------------------------------------------------- BOEING ---------------------------------------------------------------------- Project: CGNS Author: Tom Dickens 234-1024 tpd6908@yak.ca.boeing.com Date: 3/2/1995 Purpose: Provide the underlying support for the ADF-Core. ---------------------------------------------------------------------- ---------------------------------------------------------------------- Notes: Integer numbers are stored on disk as ASCII-hex numbers. 2 bytes gives a number from 0 to 255, 4 bytes 0 to 65,535, 8 bytes 0 to 4,294,967,295, and 12 bytes from 0 to 281,474,976,710,655. Pointers are 12 bytes. 8 bytes pointing to a 4096-byte chunk on disk, and 4 bytes is an offset into that chunk. This gives a maximum file size of 17,592,186,048,512 bytes (17.5 Tera bytes). ---------------------------------------------------------------------- The tables below detail the format of the information which makes up the ADF file. There are 7 different, unique types of data "chunks" used. Three of these are of fixed length, and the other four are variable in length. With the exception of numeric data (user's data), all information in an ADF file is written in ASCII. Uniquely-defined boundary-tags are used to surround all "chunks" of information. These tags are checked to confirm "chunk" type and also to ensure data integrity. ---------------------------------------------------------------------- 186 Physical disk-First block bytes start end description range / format 32 0 31 "what" description "@(#)ADF Database Version AXXxxx>" 4 32 35 "AdF0" boundary tag Tag 28 36 63 Creation date/time "Wed Apr 19 09:33:25 1995 " 4 64 67 "AdF1" boundary tag Tag 28 68 95 Modification date/time "Wed Apr 19 09:33:29 1995 " 4 96 99 "AdF2" boundary tag Tag 1 100 100 Numeric format ['B', 'L', 'C', 'N'] 1 101 101 Duplicate of numeric format ['B', 'L', 'C', 'N'] 4 102 105 "AdF3" boundary tag Tag 2 106 107 sizeof( char ) 0 to 255 2 108 109 sizeof( short ) 0 to 255 2 110 111 sizeof( int ) 0 to 255 2 112 113 sizeof( long ) 0 to 255 2 114 115 sizeof( float ) 0 to 255 2 116 117 sizeof( double ) 0 to 255 2 118 119 sizeof( char * ) 0 to 255 2 120 121 sizeof( short * ) 0 to 255 2 122 123 sizeof( int *) 0 to 255 2 124 125 sizeof( long * ) 0 to 255 2 126 127 sizeof( float *) 0 to 255 2 128 129 sizeof( double *) 0 to 255 4 130 133 "AdF4" boundary tag Tag 12 134 145 Root-node header pointer Disk chunk, chunk offset. 12 146 157 End-of-File pointer Disk chunk, chunk offset. 12 158 169 Free-Chunk table pointer Disk chunk, chunk offset. 12 170 181 Extra pointer Disk chunk, chunk offset. 4 182 185 "AdF5" boundary tag Tag 80 Free-Chunk table bytes start end description range / format 4 0 3 "fCbt" boundary tag Tag 12 4 15 First small block pointer Disk chunk, chunk offset. 12 16 27 Last small block pointer Disk chunk, chunk offset. 12 28 39 First medium block pointer Disk chunk, chunk offset. 12 40 51 Last medium block pointer Disk chunk, chunk offset. 12 52 63 First large block pointer Disk chunk, chunk offset. 12 64 75 Last large block pointer Disk chunk, chunk offset. 4 76 79 "fcte" boundarg tag Tag Variable: min 32 Free Chunk bytes start end description range / format 4 0 3 "FreE" boundary tag Tag 12 4 15 Pointer to End-of-Chunk-Tag 12 16 27 Pointer to Next-Chunk in list 0 28 - more free space 4 28 31 "EndC" boundarg tag Tag Note: There can occur other free space "gas" in the file which are smaller than the 32-bytes needed to have tags and pointers. The convention in these cases is to just fill the entire free space with the letter z, lower-case. 246 Node header bytes start end description range / format 4 0 3 "NoDe" boundary tag Tag 32 4 35 Name Text: Blank filled 32 36 67 Label Text: Blank filled 8 68 75 Number of sub-nodes 0 to 4,294,967,295 8 76 83 Entries for sub-nodes 0 to 4,294,967,295 12 84 95 Pointer to sub-node table Disk chunk, chunk offset. 32 96 127 Data-type Text: Blank filled 2 128 129 Number of dimensions 0 to 12 8 130 137 Dimension value 0 0 to 4,294,967,295 8 138 145 Dimension value 1 0 to 4,294,967,295 8 146 153 Dimension value 2 0 to 4,294,967,295 8 154 161 Dimension value 3 0 to 4,294,967,295 8 162 169 Dimension value 4 0 to 4,294,967,295 8 170 177 Dimension value 5 0 to 4,294,967,295 8 178 185 Dimension value 6 0 to 4,294,967,295 8 186 193 Dimension value 7 0 to 4,294,967,295 8 194 201 Dimension value 8 0 to 4,294,967,295 8 202 209 Dimension value 9 0 to 4,294,967,295 8 210 217 Dimension value 10 0 to 4,294,967,295 8 218 225 Dimension value 11 0 to 4,294,967,295 4 226 229 Number of data chunks 0 to 65,535 12 230 241 Pointer to data chunk (or table) Disk chunk, chunk offset. 4 242 245 "TaiL" boundary tag Tag Variable: min 64 Sub-node table bytes start end description range / format 4 0 3 "SNTb" boundary tag Tag 12 4 15 Pointer to End-of-Table-Tag 32 16 47 Child's name Text: Blank filled 12 48 59 Pointer to child Disk chunk, chunk offset. 32 - - Child's name Text: Blank filled 12 - - Pointer to child Disk chunk, chunk offset. 32 - - Child's name Text: Blank filled 12 - - Pointer to child Disk chunk, chunk offset. 32 - - Child's name Text: Blank filled 12 - - Pointer to child Disk chunk, chunk offset. 32 - - Child's name Text: Blank filled 12 - - Pointer to child Disk chunk, chunk offset. 32 - - Child's name Text: Blank filled 12 - - Pointer to child Disk chunk, chunk offset. 4 60 63 "snTE" boundary tag Tag Variable: min 44 Data-chunk table bytes start end description range / format 4 0 3 "DCtb" boundary tag Tag 12 4 15 Pointer to End-of-Table-Tag 12 16 27 Pointer to data start Disk chunk, chunk offset. 12 28 39 Pointer to data end Disk chunk, chunk offset. 12 - - Pointer to data start Disk chunk, chunk offset. 12 - - Pointer to data end Disk chunk, chunk offset. 12 - - Pointer to data start Disk chunk, chunk offset. 12 - - Pointer to data end Disk chunk, chunk offset. 12 - - Pointer to data start Disk chunk, chunk offset. 12 - - Pointer to data end Disk chunk, chunk offset. 4 40 43 "dcTE" boundarg tag Tag Variable: min 32 Data-chunks (Minimum is 32 bytes, which cooresponds to the size required for a free-chunk) bytes start end description range / format 4 0 3 "DaTa" boundary tag Tag 12 4 15 Pointer to End-of-Data-Tag 16 16 27 The data 4 28 31 "dEnD" boundarg tag Tag **/ /*********************************************************************** Includes ***********************************************************************/ #include #include #include #include #include #include #include #include #if defined(_WIN32) && !defined(__NUTC__) # include # define ACCESS _access # define OPEN _open # define CLOSE _close # define FILENO _fileno # define READ _read # define WRITE _write # define LSEEK _lseek #else # include # include # include # define ACCESS access # define OPEN open # define CLOSE close # define FILENO fileno # define READ read # define WRITE write # define LSEEK lseek #endif #include "ADF.h" #include "ADF_internals.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #include "cgns_io.h" /* for cgio_find_file */ #if 0 #define CHECK_ABORT(E) if(E!=NO_ERROR){int a=0;int b=1/a;} #else #define CHECK_ABORT(E) if(E!=NO_ERROR)return; #endif /*********************************************************************** Large File Support - files > 2Gb on 32-bit machines ***********************************************************************/ #ifdef HAVE_OPEN64 # define file_open open64 #else # define file_open OPEN #endif #ifdef HAVE_LSEEK64 # ifdef _WIN32 typedef __int64 file_offset_t; # define file_seek _lseeki64 # else typedef off64_t file_offset_t; # define file_seek lseek64 # endif #else typedef off_t file_offset_t; # define file_seek LSEEK #endif extern int ADF_sys_err; /* how many file data structures to add when increasing */ #define ADF_FILE_INC 5 /* open file data structure */ ADF_FILE *ADF_file; int maximum_files = 0; /** Track the format of this machine as well as the format of eack of the files. This is used for reading and writing numeric data associated with the nodes, which may include numeric-format translations. **/ static char ADF_this_machine_format = UNDEFINED_FORMAT_CHAR ; static char ADF_this_machine_os_size = UNDEFINED_FORMAT_CHAR ; /** we need a block of "zz"-bytes for dead-space **/ static char block_of_ZZ[ SMALLEST_CHUNK_SIZE ] ; static int block_of_ZZ_initialized = FALSE ; /** we need a block of "xx"-bytes for free-blocks **/ static char block_of_XX[ DISK_BLOCK_SIZE ] ; static int block_of_XX_initialized = FALSE ; /** we need a block of null-bytes for disk conditioning **/ static char block_of_00[ DISK_BLOCK_SIZE ] ; static int block_of_00_initialized = FALSE ; /** read/write conversion buffer **/ #define CONVERSION_BUFF_SIZE 100000 static unsigned char from_to_data[ CONVERSION_BUFF_SIZE ] ; /** read/write buffering variables **/ static char rd_block_buffer[DISK_BLOCK_SIZE] ; static cglong_t last_rd_block = -1 ; static int last_rd_file = -1 ; static int num_in_rd_block = -1 ; static char wr_block_buffer[DISK_BLOCK_SIZE] ; static cglong_t last_wr_block = -2 ; static int last_wr_file = -2 ; static int flush_wr_block = -2 ; static double last_link_ID = 0.0; static double last_link_LID = 0.0; enum { FLUSH, FLUSH_CLOSE }; /** Assumed machine variable sizes for the currently supported machines. For ordering of data see the Figure_Machine_Format function. Note that when openning a new file not in the machine format these are the sizes used!! **/ enum { TO_FILE_FORMAT, FROM_FILE_FORMAT } ; #define NUMBER_KNOWN_MACHINES 5 static size_t machine_sizes[NUMBER_KNOWN_MACHINES][16] = { /* IEEE BIG 32 */ { 1, 1, 1, 2, 2, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4 }, /* IEEE SML 32 */ { 1, 1, 1, 2, 2, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4 }, /* IEEE BIG 64 */ { 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8, 8, 8, 8, 8 }, /* IEEE SML 64 */ { 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8, 8, 8, 8, 8 }, /* CRAY 64 */ { 1, 1, 1, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } } ; /*********************************************************************** pows: Powers of 16, from 16^0 to 16^7 ASCII_Hex: Hex numbers from 0 to 15. ***********************************************************************/ static const unsigned int pows[8] = { /** Powers of 16 **/ 1, 16, 256, 4096, 65536, 1048576, 16777216, 268435456 } ; static const char ASCII_Hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' } ; /*********************************************************************** Character string defining the data tags: ***********************************************************************/ static char *file_header_tags[] = { "AdF0", "AdF1", "AdF2", "AdF3", "AdF4", "AdF5" } ; static char node_start_tag[] = "NoDe" ; static char node_end_tag[] = "TaiL" ; static char free_chunk_table_start_tag[] = "fCbt" ; static char free_chunk_table_end_tag[] = "Fcte" ; static char free_chunk_start_tag[] = "FreE" ; static char free_chunk_end_tag[] = "EndC" ; static char sub_node_start_tag[] = "SNTb" ; static char sub_node_end_tag[] = "snTE" ; static char data_chunk_table_start_tag[] = "DCtb" ; static char data_chunk_table_end_tag[] = "dcTE" ; char data_chunk_start_tag[] = "DaTa" ; /* needed in ADF_interface.c */ static char data_chunk_end_tag[] = "dEnD" ; /*********************************************************************** Priority Stack Buffer is used to buffer some of the overhead of reading small blocks of file control information like the node header by saving the data into a memory buffer. The buffer has a priority value associated with it and is used to determine which entry to replace when the stack is full!! Each stack entry could be as large as 274 bytes since the stack data could be for a node where NODE_HEADER_SIZE = 246. ***********************************************************************/ #define MAX_STACK 50 static struct { int file_index; cgulong_t file_block; unsigned int block_offset; int stack_type; char *stack_data; int priority_level; } PRISTK[MAX_STACK] ; /* Define stack types */ enum { FILE_STK=1, NODE_STK, DISK_PTR_STK, FREE_CHUNK_STK, SUBNODE_STK }; /* Define stack control modes */ enum { INIT_STK, CLEAR_STK, CLEAR_STK_TYPE, DEL_STK_ENTRY, GET_STK, SET_STK }; /*********************************************************************** Defined macros ***********************************************************************/ #define EVAL_2_BYTES( C0, C1 ) (((C0)<<8)+((C1))) #define EVAL_4_BYTES( C0, C1, C2, C3 ) (((C0)<<24)+((C1)<<16)+((C2)<<8)+((C3))) /* end of file ADFI_AAA_var.c */ /* file ADFI_ASCII_Hex_2_unsigned_int.c */ /*********************************************************************** ADFI ASCII Hex to unsigned int: Convert a number of ASCII-HEX into an unsigned integer. input: const unsigned int minimum Expected minimum number. input: const unsigned int maximum Expected maximum number. input: const unsigned int string_length Length (bytes) of the input string. input: const char string[] The input string. output: unsigned int *number The resulting number. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER STRING_LENGTH_ZERO STRING_LENGTH_TOO_BIG STRING_NOT_A_HEX_STRING NUMBER_LESS_THAN_MINIMUM NUMBER_GREATER_THAN_MAXIMUM ***********************************************************************/ void ADFI_ASCII_Hex_2_unsigned_int( const unsigned int minimum, const unsigned int maximum, const unsigned int string_length, const char string[], unsigned int *number, int *error_return ) { unsigned int i, /** Index from 0 to string_length - 1 **/ ir, /** Index from string_length - 1 to 0 **/ j, /** Temoprary integer variable **/ num ; /** Working value of ther number **/ if( string == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( string_length == 0 ) { *error_return = STRING_LENGTH_ZERO ; return ; } /* end if */ if( number == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( string_length > 8 ) { *error_return = STRING_LENGTH_TOO_BIG ; return ; } /* end if */ if( minimum > maximum ) { *error_return = MINIMUM_GT_MAXIMUM ; return ; } /* end if */ *error_return = NO_ERROR ; /** Convert the ASCII-Hex string into decimal **/ num = 0 ; ir = (string_length - 1) << 2; for( i=0; i= '0' && string[i] <= '9') j = string[i] - 48; else if (string[i] >= 'A' && string[i] <= 'F') j = string[i] - 55; else if (string[i] >= 'a' && string[i] <= 'f') j = string[i] - 87; else { *error_return = STRING_NOT_A_HEX_STRING ; return ; } num += (j << ir); ir -= 4; } if( num < minimum ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; return ; } /* end if */ if( num > maximum ) { *error_return = NUMBER_GREATER_THAN_MAXIMUM ; return ; } /* end if */ /** Return the number **/ *number = num ; } /* end of ADFI_ASCII_Hex_2_unsigned_int */ /* end of file ADFI_ASCII_Hex_2_unsigned_int.c */ /*------------------------------------------------------------------------------------*/ static void ADFI_convert_integers( const int size, const int count, const char from_format, const char to_format, const char *from_data, char *to_data, int *error_return) { int do_swap = 0; if (from_format == 'N' || to_format == 'N') { *error_return = CANNOT_CONVERT_NATIVE_FORMAT; return; } if (from_format != to_format) { switch (EVAL_2_BYTES(from_format, to_format)) { case EVAL_2_BYTES('L', 'B'): case EVAL_2_BYTES('B', 'L'): case EVAL_2_BYTES('L', 'C'): case EVAL_2_BYTES('C', 'L'): do_swap = 1; break; case EVAL_2_BYTES('B', 'C'): case EVAL_2_BYTES('C', 'B'): break; default: *error_return = ADF_FILE_FORMAT_NOT_RECOGNIZED; return; } } *error_return = NO_ERROR; if (do_swap) { int n, i; for (n = 0; n < count; n++) { for (i = 0; i < size; i++) { to_data[i] = from_data[size-i-1]; } to_data += size; from_data += size; } } else { memcpy(to_data, from_data, size * count); } } /*------------------------------------------------------------------------------------*/ /* file ADFI_Abort.c */ /*********************************************************************** ADFI Abort: Do any cleanup and then shut the application down. input: const int error_code Error which caused the Abort. output: -none- Hey, we ain't coming back... ***********************************************************************/ void ADFI_Abort( const int error_code ) { fprintf(stderr,"ADF Aborted: Exiting\n" ) ; exit( error_code ) ; } /* end of ADFI_Abort */ /* end of file ADFI_Abort.c */ /* file ADFI_ID_2_file_block_offset.c */ /*********************************************************************** ADFI ID to file block and offset: The ID is a combination of the file-index, the block within the file, and an offset within the block. the file index is an unsigned 16-bit int. block pointer is a 32-bit unsigned int. block offset is a 16-bit unsigned int. input: const double ID Given ADF ID. output: unsigned int *file_index File index from the ID. output: unsigned long *file_block File block from the ID. output: unsigned long *block_offset Block offset from the ID. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER FILE_INDEX_OUT_OF_RANGE BLOCK_OFFSET_OUT_OF_RANGE ***********************************************************************/ void ADFI_ID_2_file_block_offset( const double ID, unsigned int *file_index, cgulong_t *file_block, cgulong_t *block_offset, int *error_return ) { unsigned char * cc; if( (file_index == NULL) || (file_block == NULL) || (block_offset == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( ID == 0.0 ) { *error_return = NODE_ID_ZERO ; return ; } /* end if */ *error_return = NO_ERROR ; cc = (unsigned char *) &ID; #ifdef PRINT_STUFF printf("In ADFI_ID_2_file_block_offset: ID=%lf\n",ID); printf("cc[0-7] = %02X %02X %02X %02X %02X %02X %02X %02X \n", cc[0], cc[1], cc[2], cc[3], cc[4], cc[5], cc[6], cc[7] ) ; #endif /** Unmap the bytes from the character **/ #ifdef NEW_ID_MAPPING if (ADF_this_machine_format == IEEE_LITTLE_FORMAT_CHAR) { *file_index = (((unsigned int)(cc[7] & 0x3F)) << 6) + (((unsigned int)(cc[6] & 0xFC)) >> 2); *file_block = (((cgulong_t)(cc[6] & 0x03)) << 36) + (((cgulong_t)(cc[5] & 0xFF)) << 28) + (((cgulong_t)(cc[4] & 0xFF)) << 20) + (((cgulong_t)(cc[3] & 0xFF)) << 12) + (((cgulong_t)(cc[2] & 0xFF)) << 4) + (((cgulong_t)(cc[1] & 0xF0)) >> 4); *block_offset = (((unsigned int)(cc[1] & 0x0F)) << 8) + (((unsigned int)(cc[0] & 0xFF))); } else { *file_index = (((unsigned int)(cc[0] & 0x3F)) << 6) + (((unsigned int)(cc[1] & 0xFC)) >> 2); *file_block = (((cgulong_t)(cc[1] & 0x03)) << 36) + (((cgulong_t)(cc[2] & 0xFF)) << 28) + (((cgulong_t)(cc[3] & 0xFF)) << 20) + (((cgulong_t)(cc[4] & 0xFF)) << 12) + (((cgulong_t)(cc[5] & 0xFF)) << 4) + (((cgulong_t)(cc[6] & 0xF0)) >> 4); *block_offset = (((unsigned int)(cc[6] & 0x0F)) << 8) + (((unsigned int)(cc[7] & 0xFF))); } #if 0 assert(*file_index <= 0xfff); assert(*file_block <= 0x3fffffffff); assert(*block_offset <= 0xfff); #endif #else if ( ADF_this_machine_format == IEEE_BIG_FORMAT_CHAR ) { *file_index = cc[1] + ((cc[0] & 0x3f) << 8) ; *file_block = cc[2] + (cc[3]<<8) + (cc[4]<<16) + (cc[5]<<24) ; *block_offset = cc[6] + (cc[7]<<8) ; } /* end if */ else if ( ADF_this_machine_format == IEEE_LITTLE_FORMAT_CHAR ) { *file_index = cc[6] + ((cc[7] & 0x3f) << 8) ; *file_block = cc[2] + (cc[3]<<8) + (cc[4]<<16) + (cc[5]<<24) ; *block_offset = cc[0] + (cc[1]<<8) ; } /* end else if */ else { *file_index = cc[0] + (cc[1]<<8) ; *file_block = cc[2] + (cc[3]<<8) + (cc[4]<<16) + (cc[5]<<24) ; *block_offset = cc[6] + (cc[7]<<8) ; } /* end else */ #endif #ifdef PRINT_STUFF printf("*file_index=%d, *file_block=%d, *block_offset=%d\n", *file_index, *file_block, *block_offset); #endif if( (int)(*file_index) >= maximum_files ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } /* end if */ if( *block_offset >= DISK_BLOCK_SIZE ) { *error_return = BLOCK_OFFSET_OUT_OF_RANGE ; return ; } /* end if */ } /* end of ADFI_ID_2_file_block_offset */ /* end of file ADFI_ID_2_file_block_offset.c */ /* file ADFI_add_2_sub_node_table.c */ /*********************************************************************** ADFI add 2 sub node table: Add a child to a parent's sub-node table. input: const int file_index Index of ADF file. input: const struct DISK_POINTER *parent Location of the parent input: const struct DISK_POINTER *child Location of the child. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED SUB_NODE_TABLE_ENTRIES_BAD MEMORY_ALLOCATION_FAILED ***********************************************************************/ void ADFI_add_2_sub_node_table( const int file_index, const struct DISK_POINTER *parent, const struct DISK_POINTER *child, int *error_return ) { struct NODE_HEADER parent_node, child_node ; struct SUB_NODE_TABLE_ENTRY *sub_node_table ; struct DISK_POINTER tmp_disk_ptr ; unsigned int old_num_entries ; int i ; if( (parent == NULL) || (child == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Get node_header for the node (parent) **/ ADFI_read_node_header( file_index, parent, &parent_node, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Get node_header for the node (child) **/ ADFI_read_node_header( file_index, child, &child_node, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check current length of sub-node_table, add space if needed **/ if( parent_node.entries_for_sub_nodes <= parent_node.num_sub_nodes ) { old_num_entries = parent_node.entries_for_sub_nodes ; /** Increase the table space (double it) **/ if( parent_node.entries_for_sub_nodes == 0 ) parent_node.entries_for_sub_nodes = LIST_CHUNK ; else parent_node.entries_for_sub_nodes = (unsigned int) ( (float) parent_node.entries_for_sub_nodes * LIST_CHUNK_GROW_FACTOR ) ; if( parent_node.entries_for_sub_nodes <= parent_node.num_sub_nodes ) { *error_return = SUB_NODE_TABLE_ENTRIES_BAD ; return ; } /* end if */ /** Allocate memory for the required table space in memory **/ sub_node_table = (struct SUB_NODE_TABLE_ENTRY *) malloc( parent_node.entries_for_sub_nodes * sizeof( *sub_node_table ) ) ; if( sub_node_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ /** If sub-node table exists, get it **/ if( old_num_entries > 0 ) { ADFI_read_sub_node_table( file_index, &parent_node.sub_node_table, sub_node_table, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ /** Blank out the new part of the sub-node_table **/ for( i=parent_node.num_sub_nodes; i<(int) parent_node.entries_for_sub_nodes; i++ ) { strncpy( sub_node_table[i].child_name, /* " ", ADF_NAME_LENGTH ) ; */ "unused entry in sub-node-table ", ADF_NAME_LENGTH ) ; sub_node_table[i].child_location.block = 0 ; sub_node_table[i].child_location.offset = DISK_BLOCK_SIZE ; } /* end for */ /** Allocate memory for the required table space on disk **/ if( parent_node.num_sub_nodes > 0 ) { /* delete old table from file */ ADFI_delete_sub_node_table( file_index, &parent_node.sub_node_table, old_num_entries, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ ADFI_file_malloc( file_index, TAG_SIZE + DISK_POINTER_SIZE + TAG_SIZE + parent_node.entries_for_sub_nodes * (ADF_NAME_LENGTH + DISK_POINTER_SIZE), &tmp_disk_ptr, error_return ) ; if( *error_return != NO_ERROR ) return ; parent_node.sub_node_table.block = tmp_disk_ptr.block ; parent_node.sub_node_table.offset = tmp_disk_ptr.offset ; /** Write out modified sub_node_table **/ ADFI_write_sub_node_table( file_index, &parent_node.sub_node_table, parent_node.entries_for_sub_nodes, (struct SUB_NODE_TABLE_ENTRY *)sub_node_table, error_return ) ; free( sub_node_table ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ /** Insert new entry in sub-node table **/ tmp_disk_ptr.block = parent_node.sub_node_table.block ; tmp_disk_ptr.offset = parent_node.sub_node_table.offset + TAG_SIZE + DISK_POINTER_SIZE + parent_node.num_sub_nodes * (ADF_NAME_LENGTH + DISK_POINTER_SIZE) ; ADFI_adjust_disk_pointer( &tmp_disk_ptr, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write the child's name **/ ADFI_write_file( file_index, tmp_disk_ptr.block, tmp_disk_ptr.offset, ADF_NAME_LENGTH, child_node.name, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write out new sub_node_table entry **/ tmp_disk_ptr.offset += ADF_NAME_LENGTH ; ADFI_adjust_disk_pointer( &tmp_disk_ptr, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, tmp_disk_ptr.block, tmp_disk_ptr.offset, child, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write out modified parent node-header **/ parent_node.num_sub_nodes++ ; ADFI_write_node_header( file_index, parent, &parent_node, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end of ADFI_add_2_sub_node_table */ /* end of file ADFI_add_2_sub_node_table.c */ /* file ADFI_adjust_disk_pointer.c */ /*********************************************************************** ADFI adjust disk pointer: Adjust the disk pointer so that the offset is in a legal range; from 0 and < DISK_BLOCK_SIZE. input: const struct DISK_POINTER *block_offset output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER BLOCK_OFFSET_OUT_OF_RANGE ***********************************************************************/ void ADFI_adjust_disk_pointer( struct DISK_POINTER *block_offset, int *error_return ) { cgulong_t oblock ; cgulong_t nblock ; if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; if ( block_offset->offset < DISK_BLOCK_SIZE ) return ; /** Calculate the number of blocks in the current offset **/ nblock = (cgulong_t) (block_offset->offset / DISK_BLOCK_SIZE) ; /** Adjust block/offset checking for block roll-over **/ oblock = block_offset->block ; block_offset->block += nblock ; block_offset->offset -= nblock * DISK_BLOCK_SIZE ; if ( block_offset->block < oblock ) { *error_return = BLOCK_OFFSET_OUT_OF_RANGE ; return ; } /* end if */ } /* end of ADFI_adjust_disk_pointer */ /* end of file ADFI_adjust_disk_pointer.c */ /* file ADFI_big_endian_32_swap_64.c */ /*********************************************************************** ADFI big endian 32 swap 64: input: const char from_format Format to convert from. 'B','L','C','N' input: const char from_os_size Format to convert from. 'B','L' input: const char to_format Format to convert to. input: const char to_os_size Format to convert to. 'B','L' input: const char data_type[2] The type of data to convert. MT I4 I8 U4 U8 R4 R8 X4 X8 C1 B1 input: const unsigned long delta_from_bytes Number of from_bytes used. input: const unsigned long delta_to_bytes Number of to_bytes used. input: const char *from_data The data to convert from. output: char *to_data The resulting data. output: int *error_return Error return. Recognized data types: Machine representations Type Notation IEEE_BIG IEEE_LITTLE Cray 32 64 32 64 No data MT Integer 32 I4 I4 I4 I4 I4 I8 Integer 64 I8 -- I8 -- I8 I8 Unsigned 32 U4 I4 I4 I4 I4 I8 Unsigned 64 U8 -- I8 -- I8 I8 Real 32 R4 R4 R4 R4 R4 R8 Real 64 R8 R8 R8 R8 R8 R8 Complex 64 X4 R4R4 R4R4 R4R4 R4R4 R8R8 Complex 128 X8 R8R8 R8R8 R8R8 R8R8 R8R8 Character (unsigned byte) C1 C1 C1 C1 C1 C1 Byte (unsigned byte) B1 C1 C1 C1 C1 C1 Machine Numeric Formats: ***IEEE_BIG (SGI-Iris Assembly Language Programmer's Guide, pages 1-2, 6-3) I4: Byte0 Byte1 Byte2 Byte3 MSB---------------------LSB R4: Byte0 Byte1 Byte2 Byte3 Bits: sign-bit, 8-bit exponent, 23-bit mantissa The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa Machine Numeric Formats: ***IEEE_LITTLE ( The backwards Big Endian ) I4: Byte0 Byte1 Byte2 Byte3 LSB---------------------MSB R4: Byte0 Byte1 Byte2 Byte3 Bits: 23-bit mantissa, 8-bit exponent, sign-bit The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: 52-bit mantissa, 11-bit exponent, sign-bit Note: To convert between these two formats the order of the bytes is reversed since by definition the Big endian starts at the LSB and goes to the MSB where the little goes form the MSB to the LSB of the word. *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_big_endian_32_swap_64( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; if ( delta_to_bytes == delta_from_bytes ) { memcpy( to_data, from_data, (size_t)delta_from_bytes ) ; } /* end if */ else if ( delta_from_bytes < delta_to_bytes ) { switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'I', '8' ): if( (from_data[0] & 0x80) == 0x80 ) { /* Negative number */ to_data[0] = 0xff ; to_data[1] = 0xff ; to_data[2] = 0xff ; to_data[3] = 0xff ; } /* end if */ else { to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; } /* end else */ to_data[4] = from_data[0] ; to_data[5] = from_data[1] ; to_data[6] = from_data[2] ; to_data[7] = from_data[3] ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end else if */ else { switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'I', '8' ): to_data[0] = from_data[4] ; to_data[1] = from_data[5] ; to_data[2] = from_data[6] ; to_data[3] = from_data[7] ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end else */ } /* end of ADFI_big_endian_32_swap_64 */ /* end of file ADFI_big_endian_32_swap_64.c */ /* file ADFI_big_endian_to_cray.c */ /*********************************************************************** ADFI big endian to cray: input: const char from_format Format to convert from. 'B','L','C','N' input: const char from_os_size Format to convert from. 'B','L' input: const char to_format Format to convert to. input: const char to_os_size Format to convert to. 'B','L' input: const char data_type[2] The type of data to convert. MT I4 I8 U4 U8 R4 R8 X4 X8 C1 B1 input: const unsigned long delta_from_bytes Number of from_bytes used. input: const unsigned long delta_to_bytes Number of to_bytes used. input: const char *from_data The data to convert from. output: char *to_data The resulting data. output: int *error_return Error return. Recognized data types: Machine representations Type Notation IEEE_BIG IEEE_LITTLE Cray 32 64 32 64 No data MT Integer 32 I4 I4 I4 I4 I4 I8 Integer 64 I8 -- I8 -- I8 I8 Unsigned 32 U4 I4 I4 I4 I4 I8 Unsigned 64 U8 -- I8 -- I8 I8 Real 32 R4 R4 R4 R4 R4 R8 Real 64 R8 R8 R8 R8 R8 R8 Complex 64 X4 R4R4 R4R4 R4R4 R4R4 R8R8 Complex 128 X8 R8R8 R8R8 R8R8 R8R8 R8R8 Character (unsigned byte) C1 C1 C1 C1 C1 C1 Byte (unsigned byte) B1 C1 C1 C1 C1 C1 Machine Numeric Formats: ***IEEE_BIG (SGI-Iris Assembly Language Programmer's Guide, pages 1-2, 6-3) I4: Byte0 Byte1 Byte2 Byte3 MSB---------------------LSB R4: Byte0 Byte1 Byte2 Byte3 Bits: sign-bit, 8-bit exponent, 23-bit mantissa The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa ***Cray (Cray CFT77 Reference Manual, pages G-1 G-2) I8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 MSB-----------------------------------------------------LSB R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, exponent-sign, 14-bit exponent, 48-bit mantissa Note: Exponent sign: 1 in this bits indicates a positive exponent sign, thus bit 62 is the inverse of bit 61 (the sign in the exponent). The exception to this is a zero, in which all 64 bits are zero! The interpreation of the floating-point number is: >>> .mantissia(fraction) X 2^exponent. <<< The mantissia is left justified (the leftmost bit is a 1). This MUST be done! *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_big_endian_to_cray( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { int i, exp ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'M', 'T' ): *error_return = NO_DATA ; return ; case EVAL_2_BYTES( 'C', '1' ): case EVAL_2_BYTES( 'B', '1' ): to_data[0] = from_data[0] ; break ; case EVAL_2_BYTES( 'I', '4' ): if( (from_data[0] & 0x80) == 0x80 ) { /* Negative number */ to_data[0] = 0xff ; to_data[1] = 0xff ; to_data[2] = 0xff ; to_data[3] = 0xff ; } /* end if */ else { to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; } /* end else */ to_data[4] = from_data[0] ; to_data[5] = from_data[1] ; to_data[6] = from_data[2] ; to_data[7] = from_data[3] ; break ; case EVAL_2_BYTES( 'U', '4' ): to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; to_data[4] = from_data[0] ; to_data[5] = from_data[1] ; to_data[6] = from_data[2] ; to_data[7] = from_data[3] ; break ; case EVAL_2_BYTES( 'I', '8' ): if( (from_data[0] & 0x80) == 0x80 ) { /* Negative number */ to_data[0] = 0xff ; to_data[1] = 0xff ; to_data[2] = 0xff ; to_data[3] = 0xff ; } /* end if */ else { to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; } /* end else */ for( i=0; i<(int)delta_from_bytes; i++ ) to_data[8-delta_from_bytes+i] = from_data[i] ; break ; case EVAL_2_BYTES( 'U', '8' ): to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; for( i=0; i<(int)delta_from_bytes; i++ ) to_data[8-delta_from_bytes+i] = from_data[i] ; break ; case EVAL_2_BYTES( 'R', '4' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 8 bits to 14 bits. Sign extent from 8 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = (from_data[0] & 0x3f) << 1 ; if( (from_data[1] & 0x80) == 0x80 ) exp += 1 ; if( (from_data[0] & 0x40) == 0x00 ) /* set sign */ exp -= 128 ; exp += 2 ; to_data[1] = exp & 0xff ; if( exp < 0 ) to_data[0] |= 0x3f ; /* exponent sign 0, sign extend exponent */ else to_data[0] |= 0x40 ; /* exponent sign 1 */ /** Convert the mantissia **/ /** 23 bits to 48 bits. Left shift 25 bits, zero fill **/ to_data[2] = from_data[1] | 0x80 ; to_data[3] = from_data[2] ; to_data[4] = from_data[3] ; break ; case EVAL_2_BYTES( 'R', '8' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 11 bits to 14 bits. Sign extent from 11 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = ((from_data[0] & 0x3f) << 4) + ((from_data[1]>>4)&0x0f) ; if( (from_data[0] & 0x40) == 0x00 ) /* set sign */ exp -= 1024 ; exp += 2 ; to_data[1] = (unsigned int)(exp & 0xff) ; to_data[0] |= ((exp>>8) & 0x03) ; if( exp < 0 ) to_data[0] |= 0x3c ; /* exponent sign 0, sign extend exponent */ else to_data[0] |= 0x40 ; /* exponent sign 1 */ /** Convert the mantissia **/ /** 52 bits to 48 bits. Use 48, drop last 4 bits **/ to_data[2] = 0x80 | ((from_data[1]<<3)&0x78) | ((from_data[2]>>5)&0x07) ; for( i=3; i<8; i++ ) to_data[i] = ((from_data[i-1]<<3)&0xF8) | ((from_data[i]>>5)&0x07) ; #ifdef PRINT_STUFF printf("from:" ) ; for( i=0; i<8; i++ ) printf("%02x ", from_data[i] ) ; printf("to:" ) ; for( i=0; i<8; i++ ) printf("%02x ", to_data[i] ) ; printf("\n" ) ; #endif break ; case EVAL_2_BYTES( 'X', '4' ): ADFI_big_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_big_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, &from_data[4], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; case EVAL_2_BYTES( 'X', '8' ): ADFI_big_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_big_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end of ADFI_big_endian_to_cray */ /* end of file ADFI_big_endian_to_cray.c */ /* file ADFI_big_little_endian_swap.c */ /*********************************************************************** ADFI big little endian swap: input: const char from_format Format to convert from. 'B','L','C','N' input: const char from_os_size Format to convert from. 'B','L' input: const char to_format Format to convert to. input: const char to_os_size Format to convert to. 'B','L' input: const char data_type[2] The type of data to convert. MT I4 I8 U4 U8 R4 R8 X4 X8 C1 B1 input: const unsigned long delta_from_bytes Number of from_bytes used. input: const unsigned long delta_to_bytes Number of to_bytes used. input: const char *from_data The data to convert from. output: char *to_data The resulting data. output: int *error_return Error return. Recognized data types: Machine representations Type Notation IEEE_BIG IEEE_LITTLE Cray 32 64 32 64 No data MT Integer 32 I4 I4 I4 I4 I4 I8 Integer 64 I8 -- I8 -- I8 I8 Unsigned 32 U4 I4 I4 I4 I4 I8 Unsigned 64 U8 -- I8 -- I8 I8 Real 32 R4 R4 R4 R4 R4 R8 Real 64 R8 R8 R8 R8 R8 R8 Complex 64 X4 R4R4 R4R4 R4R4 R4R4 R8R8 Complex 128 X8 R8R8 R8R8 R8R8 R8R8 R8R8 Character (unsigned byte) C1 C1 C1 C1 C1 C1 Byte (unsigned byte) B1 C1 C1 C1 C1 C1 Machine Numeric Formats: ***IEEE_BIG (SGI-Iris Assembly Language Programmer's Guide, pages 1-2, 6-3) I4: Byte0 Byte1 Byte2 Byte3 MSB---------------------LSB R4: Byte0 Byte1 Byte2 Byte3 Bits: sign-bit, 8-bit exponent, 23-bit mantissa The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa Machine Numeric Formats: ***IEEE_LITTLE ( The backwards Big Endian ) I4: Byte0 Byte1 Byte2 Byte3 LSB---------------------MSB R4: Byte0 Byte1 Byte2 Byte3 Bits: 23-bit mantissa, 8-bit exponent, sign-bit The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: 52-bit mantissa, 11-bit exponent, sign-bit Note: To convert between these two formats the order of the bytes is reversed since by definition the Big endian starts at the LSB and goes to the MSB where the little goes form the MSB to the LSB of the word. *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_big_little_endian_swap( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { int i ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ if ( from_os_size != to_os_size || delta_to_bytes != delta_from_bytes ) { *error_return = DATA_TYPE_NOT_SUPPORTED ; return ; } /** end if **/ *error_return = NO_ERROR ; for ( i=0; i<(int)delta_from_bytes; i++ ) to_data[i] = from_data[delta_from_bytes-1-i] ; } /* end of ADFI_big_little_endian_swap */ /* end of file ADFI_big_little_endian_swap.c */ /* file ADFI_blank_fill_string.c */ /*********************************************************************** ADFI blank fill string: input/output: char *str The string to fill with blanks. input: const int length The total length of the string to fill. ***********************************************************************/ void ADFI_blank_fill_string( char *str, const int length ) { int i ; for( i=(int)strlen( str ); iblock, &block_offset->offset, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_read_node_header( *file_index, block_offset, node_header, error_return ) ; return ; } Link_ID = ID ; while( done == FALSE ) { /** Get the file, block, and offset numbers from the ID **/ ADFI_ID_2_file_block_offset( Link_ID, file_index, &block_offset->block, &block_offset->offset, error_return ) ; CHECK_ABORT(*error_return); /** Get node_header for the node **/ ADFI_read_node_header( *file_index, block_offset, node_header, error_return ) ; CHECK_ABORT(*error_return); if( (node_header->data_type[0] == 'L') && (node_header->data_type[1] == 'K')) { /** node is a link get file and path data **/ ADF_Get_Link_Path( Link_ID, link_file, link_path, error_return ) ; CHECK_ABORT(*error_return); if( link_file[0] != '\0' ) { /* A filename is specified, open it. **/ /* locate the file */ ADFI_find_file(ADF_file[*file_index].file_name, link_file, error_return); CHECK_ABORT(*error_return); /** Link_ID = root-node of the new file. note: the file could already be opened, and may be the current file! **/ ADFI_get_file_index_from_name( link_file, &found, &link_file_index, &Link_ID, error_return ) ; if( ! found ) { /** Not found; try to open it **/ if (ACCESS(link_file,2)) /* check for read-only mode */ strcpy (status, "READ_ONLY"); else /* open in same mode as current file */ strcpy (status, ADF_file[*file_index].open_mode) ; if ( ADFI_stridx_c(status, "READ_ONLY" ) != 0 ) strcpy (status, "OLD") ; ADFI_link_open( link_file, status, &Link_ID, &link_file_index, error_return ); CHECK_ABORT(*error_return); } /* end else */ ADFI_link_add( *file_index, link_file_index, found ); } /* end if */ else { /* filename NOT specified, file must be root of link */ ADF_Get_Node_ID( Link_ID, "/", &temp_ID, error_return ) ; CHECK_ABORT(*error_return); Link_ID = temp_ID ; } /* end else */ /** Get the node ID of the link to node (may be other links) **/ ADF_Get_Node_ID( Link_ID, link_path, &temp_ID, error_return ) ; if( *error_return == CHILD_NOT_OF_GIVEN_PARENT ) *error_return = LINK_TARGET_NOT_THERE ; /* A better error message */ CHECK_ABORT(*error_return); Link_ID = temp_ID ; if( ++link_depth > ADF_MAXIMUM_LINK_DEPTH ) { *error_return = LINKS_TOO_DEEP ; return ; } /* end if */ } /* end if */ else { /** node is NOT a link **/ done = TRUE ; } /* end else */ } /* end while */ *LID = Link_ID ; if (Link_ID != ID) { last_link_ID = ID; last_link_LID = Link_ID; } } /* end of ADFI_chase_link */ /* end of file ADFI_chase_link.c */ /* file ADFI_check_4_child_name.c */ /*********************************************************************** ADFI check 4 child name: input: const int file_index Index of ADF file. input: const struct DISK_POINTER *parent Location of the parent input: const char *name The name of the new child. output: int *found 0 if NOT found, else 1. output: struct DISK_POINTER *sub_node_entry_location output: struct SUB_NODE_TABLE_ENTRY *sub_node_entry output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ADF_FILE_NOT_OPENED MEMORY_ALLOCATION_FAILED ***********************************************************************/ void ADFI_check_4_child_name( const int file_index, const struct DISK_POINTER *parent, const char *name, int *found, struct DISK_POINTER *sub_node_entry_location, struct SUB_NODE_TABLE_ENTRY *sub_node_entry, int *error_return ) { struct NODE_HEADER parent_node ; struct SUB_NODE_TABLE_ENTRY *sub_node_table ; int i ; if( (parent == NULL) || (found == NULL) || (sub_node_entry_location == NULL) || (sub_node_entry == NULL ) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( name == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; *found = 0 ; /* default to NOT found */ /** Get node_header for the node **/ ADFI_read_node_header( file_index, parent, &parent_node, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check for valid node name **/ /** If parent has no children, the new name MUST be NOT found **/ if( parent_node.num_sub_nodes == 0 ) { *found = 0 ; return ; } /* end if */ /** Allocate memory for the required table space in memory **/ sub_node_table = (struct SUB_NODE_TABLE_ENTRY *) malloc( parent_node.entries_for_sub_nodes * sizeof( *sub_node_table ) ) ; if( sub_node_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ if( parent_node.entries_for_sub_nodes > 0 ) { ADFI_read_sub_node_table( file_index, &parent_node.sub_node_table, sub_node_table, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ /** Check all names for our new name **/ for( i=0; i<(int)parent_node.num_sub_nodes; i++ ) { ADFI_compare_node_names( sub_node_table[i].child_name, name, found, error_return ) ; if( *error_return != NO_ERROR ) break ; if( *found == 1 ) { /* name was found, save off addresses */ sub_node_entry_location->block = parent_node.sub_node_table.block ; sub_node_entry_location->offset = parent_node.sub_node_table.offset + TAG_SIZE + DISK_POINTER_SIZE + (ADF_NAME_LENGTH + DISK_POINTER_SIZE) * i ; ADFI_adjust_disk_pointer( sub_node_entry_location, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Also save off the child's name **/ strncpy( sub_node_entry->child_name, sub_node_table[i].child_name, ADF_NAME_LENGTH ) ; sub_node_entry->child_location.block = sub_node_table[i].child_location.block ; sub_node_entry->child_location.offset = sub_node_table[i].child_location.offset ; /** Get out of the for loop **/ break ; } /* end if */ } /* end for */ free( sub_node_table ) ; } /* end of ADFI_check_4_child_name */ /* end of file ADFI_check_4_child_name.c */ /* file ADFI_check_string_length.c */ /*********************************************************************** ADFI check string length: Check a character string for: being a NULL pointer, being too long, being zero length. input: const char *str The input string. input: const int max_length Maximum allowable length of the string. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER STRING_LENGTH_ZERO STRING_LENGTH_TOO_BIG ***********************************************************************/ void ADFI_check_string_length( const char *str, const int max_length, int *error_return ) { int str_length, i ; if( str == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ str_length = (int)strlen( str ) ; if( str_length == 0 ) { *error_return = STRING_LENGTH_ZERO ; return ; } /* end if */ if( (int) strlen( str ) > max_length ) { *error_return = STRING_LENGTH_TOO_BIG ; return ; } /* end if */ /** Check for blank string **/ *error_return = STRING_LENGTH_ZERO ; for( i=0; i= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /* close files that his file links to */ for (index = 0; index < ADF_file[file_index].nlinks; index++) { ADFI_close_file( ADF_file[file_index].links[index], error_return); } /* don't close until in_use is 0 */ index = ADF_file[file_index].in_use - 1; if ( index == 0) { ADF_sys_err = 0; if( ADF_file[file_index].file >= 0 ) { ADFI_flush_buffers( file_index, FLUSH_CLOSE, error_return ); if( CLOSE( ADF_file[file_index].file ) < 0 ) { ADF_sys_err = errno; *error_return = FILE_CLOSE_ERROR ; } } /* end if */ ADF_file[file_index].file = -1 ; /** Clear this file's entry **/ ADFI_stack_control(file_index,0,0,CLEAR_STK,0,0,NULL); if (ADF_file[file_index].nlinks) { free (ADF_file[file_index].links); ADF_file[file_index].nlinks = 0; } if (ADF_file[file_index].file_name != NULL) { free (ADF_file[file_index].file_name); ADF_file[file_index].file_name = NULL; } } ADF_file[file_index].in_use = index; /* if no more files open, free data structure */ for (index = 0; index < maximum_files; index++) { if (ADF_file[index].in_use) return; } free (ADF_file); maximum_files = 0; } /* end of ADFI_close_file */ /* end of file ADFI_close_file.c */ /* file ADFI_compare_node_names.c */ /*********************************************************************** ADFI compare node names: input: const char *name Existing node name. input: const char *new_name New node name. output: int *names_match 0 if name do NOT match, else 1. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_compare_node_names( const char *name, const char *new_name, int *names_match, int *error_return ) { int i, new_length ; if( (name == NULL) || (new_name == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( names_match == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; *names_match = 0 ; /* Default to NO match */ new_length = (int)strlen( new_name ) ; for( i=0; i>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa Machine Numeric Formats: ***IEEE_LITTLE ( The backwards Big Endian ) I4: Byte0 Byte1 Byte2 Byte3 LSB---------------------MSB R4: Byte0 Byte1 Byte2 Byte3 Bits: 23-bit mantissa, 8-bit exponent, sign-bit The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: 52-bit mantissa, 11-bit exponent, sign-bit ***Cray (Cray CFT77 Reference Manual, pages G-1 G-2) I8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 MSB-----------------------------------------------------LSB R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, exponent-sign, 14-bit exponent, 48-bit mantissa Note: Exponent sign: 1 in this bits indicates a positive exponent sign, thus bit 62 is the inverse of bit 61 (the sign in the exponent). The exception to this is a zero, in which all 64 bits are zero! The interpreation of the floating-point number is: >>> .mantissia(fraction) X 2^exponent. <<< The mantissia is left justified (the leftmost bit is a 1). This MUST be done! *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_convert_number_format( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const int convert_dir, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const unsigned int length, unsigned char *from_data, unsigned char *to_data, int *error_return ) { unsigned char temp_data[16] ; char data_type[2] ; int current_token ; int array_size ; int l, s ; cgulong_t delta_from_bytes, delta_to_bytes ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( length == 0 ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ switch( EVAL_4_BYTES( from_format, to_format, from_os_size, to_os_size ) ) { case EVAL_4_BYTES( 'B', 'B', 'B', 'B' ): case EVAL_4_BYTES( 'C', 'C', 'B', 'B' ): case EVAL_4_BYTES( 'L', 'L', 'B', 'B' ): case EVAL_4_BYTES( 'B', 'B', 'L', 'L' ): case EVAL_4_BYTES( 'C', 'C', 'L', 'L' ): case EVAL_4_BYTES( 'L', 'L', 'L', 'L' ): *error_return = CONVERSION_FORMATS_EQUAL ; return ; } /* end switch */ *error_return = NO_ERROR ; /** loop over each element **/ for ( l=0; l<(int)length; l++ ) { current_token = -1 ; while( tokenized_data_type[ ++current_token ].type[0] != 0 ) { data_type[0] = tokenized_data_type[ current_token ].type[0] ; data_type[1] = tokenized_data_type[ current_token ].type[1] ; array_size = tokenized_data_type[ current_token ].length ; if ( convert_dir == FROM_FILE_FORMAT ) { delta_from_bytes=tokenized_data_type[ current_token ].file_type_size ; delta_to_bytes =tokenized_data_type[ current_token ].machine_type_size ; } /** end if **/ else { delta_to_bytes =tokenized_data_type[ current_token ].file_type_size ; delta_from_bytes=tokenized_data_type[ current_token ].machine_type_size ; } /** end else **/ for ( s=0; s 12) ) { *error_return = BAD_NUMBER_OF_DIMENSIONS ; return ; } /* end if */ *error_return = NO_ERROR ; /** Chek the inputs **/ for( i=0; i=1 **/ if( dims[i] < 1 ) { *error_return = BAD_DIMENSION_VALUE ; return ; } /* end if */ /** Check starting values >=1 and <= dims **/ if( (dim_start[i] < 1) || ((cgulong_t)dim_start[i] > dims[i]) ) { *error_return = START_OUT_OF_DEFINED_RANGE ; return ; } /* end if */ /** Check ending values >=1 and <= dims and >= dim_start **/ if( (dim_end[i] < 1) || ((cgulong_t)dim_end[i] > dims[i]) ) { *error_return = END_OUT_OF_DEFINED_RANGE ; return ; } /* end if */ if( dim_end[i] < dim_start[i] ) { *error_return = MINIMUM_GT_MAXIMUM ; return ; } /* end if */ /** Check stride >= 1 **/ if( dim_stride[i] < 1 ) { *error_return = BAD_STRIDE_VALUE ; return ; } /* end if */ } /* end for */ total = 1 ; offset = 0 ; accumlated_size = 1 ; for( i=0; i>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa ***Cray (Cray CFT77 Reference Manual, pages G-1 G-2) I8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 MSB-----------------------------------------------------LSB R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, exponent-sign, 14-bit exponent, 48-bit mantissa Note: Exponent sign: 1 in this bits indicates a positive exponent sign, thus bit 62 is the inverse of bit 61 (the sign in the exponent). The exception to this is a zero, in which all 64 bits are zero! The interpreation of the floating-point number is: >>> .mantissia(fraction) X 2^exponent. <<< The mantissia is left justified (the leftmost bit is a 1). This MUST be done! *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_cray_to_big_endian( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { int i, exp ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'M', 'T' ): *error_return = NO_DATA ; return ; case EVAL_2_BYTES( 'C', '1' ): case EVAL_2_BYTES( 'B', '1' ): to_data[0] = from_data[0] ; break ; case EVAL_2_BYTES( 'I', '4' ): case EVAL_2_BYTES( 'U', '4' ): to_data[0] = from_data[4] ; to_data[1] = from_data[5] ; to_data[2] = from_data[6] ; to_data[3] = from_data[7] ; break ; case EVAL_2_BYTES( 'I', '8' ): case EVAL_2_BYTES( 'U', '8' ): for( i=0; i<(int) delta_to_bytes; i++ ) to_data[i] = from_data[8-delta_to_bytes+i] ; break ; case EVAL_2_BYTES( 'R', '4' ): for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) && (from_data[4] == 0x00) && (from_data[5] == 0x00) && (from_data[6] == 0x00) && (from_data[7] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 14 bits to 8 bits. Sign extent from 8 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = from_data[1] + ((from_data[0]&0x3f)<<8) ; if( (from_data[0] & 0x40) == 0x00 ) /* set sign */ exp -= 16384 ; exp -= 2 ; if( exp >= 128 ) { *error_return = NUMERIC_OVERFLOW ; return ; } /* end if */ else if ( exp < -128 ) { for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /* underflow set to 0 */ break; } /* end else */ to_data[0] |= ((exp&0x7F) >> 1) ; if( (exp & 0x01) == 0x01 ) /* LSBit of the exponent */ to_data[1] |= 0x80 ; if( exp >= 0 ) /* Set exponent sign */ to_data[0] |= 0x40 ; /** Convert the mantissia **/ /** 48 bits to 23 bits, skip the first '1' (2.fract) **/ to_data[1] |= (from_data[2] & 0x7f) ; to_data[2] = from_data[3] ; to_data[3] = from_data[4] ; break ; case EVAL_2_BYTES( 'R', '8' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 14 bits to 11 bits **/ /** Cray exponent is 2 greater than the Iris **/ exp = from_data[1] + ((from_data[0]&0x3f)<<8) ; /* set sign if exponent is non-zero */ if( (exp != 0) && ((from_data[0] & 0x40) == 0x00) ) exp -= 16384 ; exp -= 2 ; if( exp >= 1024 ) { *error_return = NUMERIC_OVERFLOW ; return ; } /* end if */ else if ( exp < -1024 ) { for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /* underflow set to 0 */ break; } /* end else */ to_data[0] |= ((exp & 0x03F0) >> 4) ; to_data[1] |= ((exp & 0x000F) << 4) ; if( exp >= 0 ) /* Set exponent sign */ to_data[0] |= 0x40 ; /** Convert the mantissia **/ /** 48 bits to 52 bits, skip the first '1' (2.fract) **/ to_data[1] |= ((from_data[2] & 0x78) >> 3) ; for( i=2; i<7; i++ ) to_data[i] = ((from_data[i] & 0x07) << 5) | ((from_data[i+1] & 0xf8) >> 3) ; to_data[7] = ((from_data[7] & 0x07) << 5) ; #ifdef PRINT_STUFF printf("from:" ) ; for( i=0; i<8; i++ ) printf("%02x ", from_data[i] ) ; printf("to:" ) ; for( i=0; i<8; i++ ) printf("%02x ", to_data[i] ) ; printf("\n" ) ; #endif break ; case EVAL_2_BYTES( 'X', '4' ): ADFI_cray_to_big_endian( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_cray_to_big_endian( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[4], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; case EVAL_2_BYTES( 'X', '8' ): ADFI_cray_to_big_endian( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_cray_to_big_endian( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end of ADFI_cray_to_big_endian */ /* end of file ADFI_cray_to_big_endian.c */ /* file ADFI_cray_to_little_endian.c */ /*********************************************************************** ADFI cray to little endian: input: const char from_format Format to convert from. 'B','L','C','N' input: const char from_os_size Format to convert from. 'B','L' input: const char to_format Format to convert to. input: const char to_os_size Format to convert to. 'B','L' input: const char data_type[2] The type of data to convert. MT I4 I8 U4 U8 R4 R8 X4 X8 C1 B1 input: const unsigned long delta_from_bytes Number of from_bytes used. input: const unsigned long delta_to_bytes Number of to_bytes used. input: const char *from_data The data to convert from. output: char *to_data The resulting data. output: int *error_return Error return. Recognized data types: Machine representations Type Notation IEEE_BIG IEEE_L Cray No data MT Integer 32 I4 I4 I4 I4 I4 I8 Integer 64 I8 -- I8 -- I8 I8 Unsigned 32 U4 I4 I4 I4 I4 I8 Unsigned 64 U8 -- I8 -- I8 I8 Real 32 R4 R4 R4 R4 R4 R8 Real 64 R8 R8 R8 R8 R8 R8 Complex 64 X4 R4R4 R4R4 R4R4 R4R4 R8R8 Complex 128 X8 R8R8 R8R8 R8R8 R8R8 R8R8 Character (unsigned byte) C1 C1 C1 C1 C1 C1 Byte (unsigned byte) B1 C1 C1 C1 C1 C1 Machine Numeric Formats: ***IEEE_BIG (SGI-Iris Assembly Language Programmer's Guide, pages 1-2, 6-3) I4: Byte0 Byte1 Byte2 Byte3 MSB---------------------LSB R4: Byte0 Byte1 Byte2 Byte3 Bits: sign-bit, 8-bit exponent, 23-bit mantissa The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa ***Cray (Cray CFT77 Reference Manual, pages G-1 G-2) I8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 MSB-----------------------------------------------------LSB R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, exponent-sign, 14-bit exponent, 48-bit mantissa Note: Exponent sign: 1 in this bits indicates a positive exponent sign, thus bit 62 is the inverse of bit 61 (the sign in the exponent). The exception to this is a zero, in which all 64 bits are zero! The interpreation of the floating-point number is: >>> .mantissia(fraction) X 2^exponent. <<< The mantissia is left justified (the leftmost bit is a 1). This MUST be done! *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_cray_to_little_endian( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { int i, exp ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'M', 'T' ): *error_return = NO_DATA ; return ; case EVAL_2_BYTES( 'C', '1' ): case EVAL_2_BYTES( 'B', '1' ): to_data[0] = from_data[0] ; break ; case EVAL_2_BYTES( 'I', '4' ): case EVAL_2_BYTES( 'U', '4' ): to_data[3] = from_data[4] ; to_data[2] = from_data[5] ; to_data[1] = from_data[6] ; to_data[0] = from_data[7] ; break ; case EVAL_2_BYTES( 'I', '8' ): case EVAL_2_BYTES( 'U', '8' ): for( i=0; i<(int) delta_to_bytes; i++ ) to_data[delta_to_bytes-1-i] = from_data[8-delta_to_bytes+i] ; break ; case EVAL_2_BYTES( 'R', '4' ): for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) && (from_data[4] == 0x00) && (from_data[5] == 0x00) && (from_data[6] == 0x00) && (from_data[7] == 0x00) ) break ; /** Convert the sign **/ to_data[3] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 14 bits to 8 bits. Sign extent from 8 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = from_data[1] + ((from_data[0]&0x3f)<<8) ; if( (from_data[0] & 0x40) == 0x00 ) /* set sign */ exp -= 16384 ; exp -= 2 ; if( exp >= 128 ) { *error_return = NUMERIC_OVERFLOW ; return ; } /* end if */ else if ( exp < -128 ) { for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /* underflow set to 0 */ break; } /* end else */ to_data[3] |= ((exp&0x7F) >> 1) ; if( (exp & 0x01) == 0x01 ) /* LSBit of the exponent */ to_data[2] |= 0x80 ; if( exp >= 0 ) /* Set exponent sign */ to_data[3] |= 0x40 ; /** Convert the mantissia **/ /** 48 bits to 23 bits, skip the first '1' (2.fract) **/ to_data[2] |= (from_data[2] & 0x7f) ; to_data[1] = from_data[3] ; to_data[0] = from_data[4] ; break ; case EVAL_2_BYTES( 'R', '8' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[0] == 0x00) && (from_data[1] == 0x00) && (from_data[2] == 0x00) && (from_data[3] == 0x00) ) break ; /** Convert the sign **/ to_data[7] = from_data[0] & 0x80 ; /** Convert the exponent **/ /** 14 bits to 11 bits **/ /** Cray exponent is 2 greater than the Iris **/ exp = from_data[1] + ((from_data[0]&0x3f)<<8) ; /* set sign if exponent is non-zero */ if( (exp != 0) && ((from_data[0] & 0x40) == 0x00) ) exp -= 16384 ; exp -= 2 ; if( exp >= 1024 ) { *error_return = NUMERIC_OVERFLOW ; return ; } /* end if */ else if ( exp < -1024 ) { for( i=0; i<4; i++ ) to_data[i] = 0x00 ; /* underflow set to 0 */ break; } /* end else */ to_data[7] |= ((exp & 0x03F0) >> 4) ; to_data[6] |= ((exp & 0x000F) << 4) ; if( exp >= 0 ) /* Set exponent sign */ to_data[7] |= 0x40 ; /** Convert the mantissia **/ /** 48 bits to 52 bits, skip the first '1' (2.fract) **/ to_data[6] |= ((from_data[2] & 0x78) >> 3) ; for( i=2; i<7; i++ ) to_data[7-i] = ((from_data[i] & 0x07) << 5) | ((from_data[i+1] & 0xf8) >> 3) ; to_data[0] = ((from_data[7] & 0x07) << 5) ; #ifdef PRINT_STUFF printf("from:" ) ; for( i=0; i<8; i++ ) printf("%02x ", from_data[i] ) ; printf("to:" ) ; for( i=0; i<8; i++ ) printf("%02x ", to_data[i] ) ; printf("\n" ) ; #endif break ; case EVAL_2_BYTES( 'X', '4' ): ADFI_cray_to_little_endian( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_cray_to_little_endian( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[4], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; case EVAL_2_BYTES( 'X', '8' ): ADFI_cray_to_little_endian( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_cray_to_little_endian( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end of ADFI_cray_to_little_endian */ /* end of file ADFI_cray_to_little_endian.c */ /* file ADFI_delete_data.c */ /*********************************************************************** ADFI delete data: Deletes all data from the file for a node. input: const int file_index The file index. input: const struct NODE_HEADER Node header information. output: int *error_return Error return. ***********************************************************************/ void ADFI_delete_data( const int file_index, const struct NODE_HEADER *node_header, int *error_return ) { struct DATA_CHUNK_TABLE_ENTRY *data_chunk_table ; int i ; *error_return = NO_ERROR ; if( node_header == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ switch( node_header->number_of_data_chunks ) { case 0 : /** No data to free, do nothing **/ return ; case 1 : /** A single data-chunk to free, so free it **/ ADFI_file_free( file_index, &node_header->data_chunks, 0, error_return ) ; if( *error_return != NO_ERROR ) return ; break ; default : /** Multiple data-chunks to free. Free them, and also the data_chunk table **/ /** Allocate memory for the required table space in memory **/ data_chunk_table = (struct DATA_CHUNK_TABLE_ENTRY *) malloc( node_header->number_of_data_chunks * sizeof( *data_chunk_table ) ) ; if( data_chunk_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ /** Read in the table **/ ADFI_read_data_chunk_table( file_index, &node_header->data_chunks, data_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Free each entry in the table **/ for( i=0; i<(int)node_header->number_of_data_chunks; i++ ) { ADFI_file_free( file_index, &data_chunk_table[i].start, 0, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end for */ free( data_chunk_table ) ; ADFI_file_free( file_index, &node_header->data_chunks, 0, error_return ) ; if( *error_return != NO_ERROR ) return ; break ; }/* end switch */ /** Clear all disk entries off the priority stack for file **/ ADFI_stack_control(file_index, 0, 0, CLEAR_STK_TYPE, DISK_PTR_STK, 0, NULL ) ; } /* end of ADFI_delete_data */ /* end of file ADFI_delete_data.c */ /* file ADFI_delete_from_sub_node_table.c */ /*********************************************************************** ADFI delete from sub node table: Delete a child from a parent's sub-node table. input: const int file_index Index of ADF file. input: const struct DISK_POINTER *parent Location of the parent input: const struct DISK_POINTER *child Location of the child. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_delete_from_sub_node_table( const int file_index, const struct DISK_POINTER *parent, const struct DISK_POINTER *child, int *error_return ) { int i, found ; struct NODE_HEADER parent_node ; struct SUB_NODE_TABLE_ENTRY *sub_node_table ; if( (parent == NULL) || (child == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; ADFI_read_node_header( file_index, parent, &parent_node, error_return ) ; if( *error_return != NO_ERROR ) return ; sub_node_table = (struct SUB_NODE_TABLE_ENTRY *) malloc( parent_node.entries_for_sub_nodes * sizeof( struct SUB_NODE_TABLE_ENTRY ) ) ; if( sub_node_table == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ ADFI_read_sub_node_table( file_index, &parent_node.sub_node_table, sub_node_table, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Find the child in the parent's sub-node table **/ for( i=0, found = -1 ; i<(int)parent_node.num_sub_nodes ; i++ ) { if( child->block == sub_node_table[i].child_location.block && child->offset == sub_node_table[i].child_location.offset ) { found = i ; break ; } /* end if */ } /* end for */ if( found == -1 ) { *error_return = SUB_NODE_TABLE_ENTRIES_BAD ; free(sub_node_table); return ; } /** Move the rest of the table up to fill the hole **/ for( i=found ; i<(int) (parent_node.num_sub_nodes-1) ; i++ ) { sub_node_table[i].child_location.block = sub_node_table[i+1].child_location.block ; sub_node_table[i].child_location.offset = sub_node_table[i+1].child_location.offset ; strncpy ( sub_node_table[i].child_name, sub_node_table[i+1].child_name, ADF_NAME_LENGTH ) ; } /* end for */ i = parent_node.num_sub_nodes - 1 ; sub_node_table[i].child_location.block = 0 ; sub_node_table[i].child_location.offset = 0 ; strncpy ( sub_node_table[i].child_name, "unused entry in sub-node-table ", ADF_NAME_LENGTH ) ; /** Re-write the parent's sub-node table **/ ADFI_write_sub_node_table( file_index, &parent_node.sub_node_table, parent_node.entries_for_sub_nodes, sub_node_table, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Update the sub-node count and write the parent's node-header **/ parent_node.num_sub_nodes -= 1; ADFI_write_node_header( file_index, parent, &parent_node, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Clear all subnode/disk entries off the priority stack for file **/ ADFI_stack_control(file_index, 0, 0, CLEAR_STK_TYPE, SUBNODE_STK, 0, NULL ) ; ADFI_stack_control(file_index, 0, 0, CLEAR_STK_TYPE, DISK_PTR_STK, 0, NULL ) ; free(sub_node_table); } /* end of ADFI_delete_from_sub_node_table */ /* end of file ADFI_delete_from_sub_node_table.c */ /* file ADFI_delete_sub_node_table.c */ /*********************************************************************** ADFI delete sub node table: Deletes a sub-node table from the file. input: const int file_index Index of ADF file. input: const struct DISK_POINTER *block_offset The block & offset of the sub node table. input: const unsigned int size_sub_node_table Current size of the sub node table (usually node_header.entries_for_sub_nodes). If zero, then no action performed. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED FREE_OF_ROOT_NODE ADF_DISK_TAG_ERROR FREE_OF_FREE_CHUNK_TABLE ***********************************************************************/ void ADFI_delete_sub_node_table( const int file_index, const struct DISK_POINTER *block_offset, const unsigned int size_sub_node_table, int *error_return ) { unsigned int num_bytes ; *error_return = NO_ERROR ; if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ if( size_sub_node_table == 0 ) return ; /* assume nothing to delete */ /* calculate size */ num_bytes = TAG_SIZE + TAG_SIZE + DISK_POINTER_SIZE + size_sub_node_table * (ADF_NAME_LENGTH + DISK_POINTER_SIZE); ADFI_file_free( file_index, block_offset, num_bytes, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Clear all subnode/disk entries off the priority stack for file **/ ADFI_stack_control(file_index, 0, 0, CLEAR_STK_TYPE, SUBNODE_STK, 0, NULL ) ; ADFI_stack_control(file_index, 0, 0, CLEAR_STK_TYPE, DISK_PTR_STK, 0, NULL ) ; } /* end of ADFI_delete_sub_node_table */ /* end of file ADFI_delete_sub_node_table.c */ /* file ADFI_disk_pointer_2_ASCII_Hex.c */ /*********************************************************************** ADFI disk pointer to ASCII Hex: Convert a disk pointer into an ASCII-Hex representation (for disk). input: const struct DISK_POINTER *block_offset Disk-pointer struct. output: char block[8] ASCII block number. output: char offset[4] ASCII offset number. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ***********************************************************************/ void ADFI_disk_pointer_2_ASCII_Hex( const struct DISK_POINTER *block_offset, char block[8], char offset[4], int *error_return ) { if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (block == NULL) || (offset == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; /** Convert into ASCII-Hex form **/ ADFI_unsigned_int_2_ASCII_Hex( (unsigned int)block_offset->block, 0, MAXIMUM_32_BITS, 8, block, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( (unsigned int)block_offset->offset, 0, DISK_BLOCK_SIZE, 4, offset, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end of ADFI_disk_pointer_2_ASCII_Hex */ /* end of file ADFI_disk_pointer_2_ASCII_Hex.c */ /* file ADFI_disk_pointer_from_ASCII_Hex.c */ /*********************************************************************** ADFI disk pointer from ASCII Hex: Convert an ASCII-Hex representation into a disk-pointer (for memory). input: const char block[8] ASCII block number. input: const char offset[4] ASCII offset number. output: struct DISK_POINTER *block_offset Disk-pointer struct. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ***********************************************************************/ void ADFI_disk_pointer_from_ASCII_Hex( const char block[8], const char offset[4], struct DISK_POINTER *block_offset, int *error_return ) { unsigned int tmp ; if( (block == NULL) || (offset == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; /** Convert into numeric form **/ ADFI_ASCII_Hex_2_unsigned_int( 0, MAXIMUM_32_BITS, 8, block, &tmp, error_return ) ; if( *error_return != NO_ERROR ) return ; block_offset->block = tmp ; ADFI_ASCII_Hex_2_unsigned_int( 0, DISK_BLOCK_SIZE, 4, offset, &tmp, error_return ) ; if( *error_return != NO_ERROR ) return ; block_offset->offset = tmp ; } /* end of ADFI_disk_pointer_from_ASCII_Hex */ /* end of file ADFI_disk_pointer_from_ASCII_Hex.c */ /*----------------------------------------------------------------------------------*/ void ADFI_write_disk_pointer( const unsigned int file_index, const struct DISK_POINTER *block_offset, char block[8], char offset[4], int *error_return) { if (ADF_file[file_index].old_version) { ADFI_disk_pointer_2_ASCII_Hex(block_offset, block, offset, error_return); } else { unsigned int boff = (unsigned int)block_offset->offset; ADFI_convert_integers(8, 1, ADF_this_machine_format, ADF_file[file_index].format, (char *)&block_offset->block, block, error_return); if (*error_return != NO_ERROR) return; ADFI_convert_integers(4, 1, ADF_this_machine_format, ADF_file[file_index].format, (char *)&boff, offset, error_return); } } /*----------------------------------------------------------------------------------*/ void ADFI_read_disk_pointer( const unsigned int file_index, const char block[8], const char offset[4], struct DISK_POINTER *block_offset, int *error_return ) { if (ADF_file[file_index].old_version) { ADFI_disk_pointer_from_ASCII_Hex(block, offset, block_offset, error_return); } else { unsigned int boff; ADFI_convert_integers(8, 1, ADF_file[file_index].format, ADF_this_machine_format, block, (char *)&block_offset->block, error_return); if (*error_return != NO_ERROR) return; ADFI_convert_integers(4, 1, ADF_file[file_index].format, ADF_this_machine_format, offset, (char *)&boff, error_return); block_offset->offset = boff; } } /*----------------------------------------------------------------------------------*/ /* file ADFI_evaluate_datatype.c */ /*********************************************************************** ADFI evaluate datatype: input: const int file_index The file index (0 to MAXIMUM_FILES). input: const char *data_type. Data-type string. output: int *file_bytes. Number of bytes used by the data type. output: int *machine_ bytes. Number of bytes used by the data type. output: struct TOKENIZED_DATA_TYPE *tokenized_data_type Array. output: char *file_format The format of this file. output: char *machine_format The format of this machine. output: int error_return. Error return. Recognized data types: Type Notation No data MT Integer 32 I4 Integer 64 I8 Unsigned 32 U4 Unsigned 64 U8 Real 32 R4 Real 64 R8 Complex 64 X4 Complex 128 X8 Character (unsigned byte) C1 Link (same as C1) LK Byte (unsigned byte) B1 A structure is represented as the string "I4,I4,R8". An array of 25 integers is "I4[25]". Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER DATA_TYPE_TOO_LONG INVALID_DATA_TYPE ***********************************************************************/ void ADFI_evaluate_datatype( const int file_index, const char data_type[], int *file_bytes, int *machine_bytes, struct TOKENIZED_DATA_TYPE *tokenized_data_type, char *file_format, char *machine_format, int *error_return ) { int str_position = 0 ; int current_token = 0 ; int i, str_len, size_file, size_machine ; char data_type_string[ADF_DATA_TYPE_LENGTH + 1 ] ; struct FILE_HEADER file_header ; if( (file_format == NULL) || (machine_format == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (file_bytes == NULL) || (machine_bytes == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ *file_bytes = 0 ; *machine_bytes = 0 ; *error_return = NO_ERROR ; /** Return the file & machine's format info **/ if( file_index >= maximum_files ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } /* end if */ *file_format = ADF_file[file_index].format ; *machine_format = ADF_this_machine_format ; /** Convert blank-filled datatype into C string **/ ADFI_string_2_C_string( data_type, ADF_DATA_TYPE_LENGTH, data_type_string, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Upper_CASE the data-type string **/ str_len = (int)strlen( data_type_string ) ; if ( str_len == 0 ) { *error_return = STRING_LENGTH_ZERO ; return ; } /** end if **/ for( i=0; i= '0') && (data_type_string[ str_position ] <= '9') ) { array_size = array_size * 10 + (data_type_string[ str_position ] - '0') ; str_position += 1 ; } /* end while */ if( data_type_string[ str_position ] != ']' ) { *error_return = INVALID_DATA_TYPE ; return ; } /* end if */ str_position += 1 ; /** Check for comma between types **/ if( data_type_string[ str_position ] == ',' ) { str_position += 1 ; } /* end if */ *file_bytes = *file_bytes + size_file * array_size ; *machine_bytes = *machine_bytes + size_machine * array_size ; tokenized_data_type[ current_token++ ].length = array_size ; } break ; case ',' : str_position += 1 ; *file_bytes = *file_bytes + size_file ; *machine_bytes = *machine_bytes + size_machine ; break ; default : /** Error condition **/ *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end while */ tokenized_data_type[ current_token ].type[0] = 0x00 ; tokenized_data_type[ current_token ].type[1] = 0x00 ; tokenized_data_type[ current_token ].file_type_size = *file_bytes; tokenized_data_type[ current_token ].machine_type_size = *machine_bytes ; } /* end of ADFI_evaluate_datatype */ /* end of file ADFI_evaluate_datatype.c */ /* file ADFI_fflush_file.c */ /*********************************************************************** ADFI fflush file: To flush the file output stream. input: const unsigned int file_index File to use. output: int *error_return Error return. Possible errors: NO_ERROR ADF_FILE_NOT_OPENED FFLUSH_ERROR ***********************************************************************/ void ADFI_fflush_file( const unsigned int file_index, int *error_return ) { int iret ; if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; ADF_sys_err = 0; # ifdef _WIN32 iret = _commit( ADF_file[file_index].file ) ; # else iret = fsync( ADF_file[file_index].file ) ; # endif if (iret < 0) { ADF_sys_err = errno; *error_return = FFLUSH_ERROR ; } /* end if */ } /* end of ADFI_fflush_file */ /* end of file ADFI_fflush_file.c */ /* file ADFI_figure_machine_format.c */ /* file ADFI_figure_machine_format.c */ /*********************************************************************** ADFI figure machine format: Determine if the host computer is IEEE_BIG, IEEE_LITTLE, CRAY, or NATIVE. Once this machines format if determined, look at the requested format. If NATIVE, use this machines format, otherwise use the requested format. input: const char *format IEEE_BIG, IEEE_LITTLE, CRAY, or NATIVE. output: const char *machine_format 'B', 'L', 'C', 'N' output: const char *format_to_use 'B', 'L', 'C', 'N' output: const char *os_to_use 'B', 'L' output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER ***********************************************************************/ static unsigned char bits[NUMBER_KNOWN_MACHINES][8][8] = { /* IEEE BIG 32 */ /* u.i = 123456789: */ { { 0x07, 0x5B, 0xCD, 0x15, 0x00, 0x00, 0x00, 0x00 }, /* u.i = -123456789: */ { 0xF8, 0xA4, 0x32, 0xEB, 0x00, 0x00, 0x00, 0x00 }, /* u.l = 1234567890L: */ { 0x49, 0x96, 0x02, 0xD2, 0x00, 0x00, 0x00, 0x00 }, /* u.l = -1234567890L: */ { 0xB6, 0x69, 0xFD, 0x2E, 0x00, 0x00, 0x00, 0x00 }, /* u.f = 12345.6789: */ { 0x46, 0x40, 0xE6, 0xB7, 0x00, 0x00, 0x00, 0x00 }, /* u.f = -12345.6789: */ { 0xC6, 0x40, 0xE6, 0xB7, 0x00, 0x00, 0x00, 0x00 }, /* u.d = 12345.6789: */ { 0x40, 0xC8, 0x1C, 0xD6, 0xE6, 0x31, 0xF8, 0xA1 }, /* u.d = -12345.6789: */ { 0xC0, 0xC8, 0x1C, 0xD6, 0xE6, 0x31, 0xF8, 0xA1 } }, /* IEEE LITTLE 32 */ /* u.i = 123456789: */ { { 0x15, 0xCD, 0x5B, 0x07, 0x00, 0x00, 0x00, 0x00 }, /* u.i = -123456789: */ { 0xEB, 0x32, 0xA4, 0xF8, 0x00, 0x00, 0x00, 0x00 }, /* u.l = 1234567890L: */ { 0xD2, 0x02, 0x96, 0x49, 0x00, 0x00, 0x00, 0x00 }, /* u.l = -1234567890L: */ { 0x2E, 0xFD, 0x69, 0xB6, 0x00, 0x00, 0x00, 0x00 }, /* u.f = 12345.6789: */ { 0xB7, 0xE6, 0x40, 0x46, 0x00, 0x00, 0x00, 0x00 }, /* u.f = -12345.6789: */ { 0xB7, 0xE6, 0x40, 0xC6, 0x00, 0x00, 0x00, 0x00 }, /* u.d = 12345.6789: */ { 0xA1, 0xF8, 0x31, 0xE6, 0xD6, 0x1C, 0xC8, 0x40 }, /* u.d = -12345.6789: */ { 0xA1, 0xF8, 0x31, 0xE6, 0xD6, 0x1C, 0xC8, 0xC0 } }, /* IEEE BIG 64 */ /* u.i = 123456789: */ { { 0x07, 0x5B, 0xCD, 0x15, 0x00, 0x00, 0x00, 0x00 }, /* u.i = -123456789: */ { 0xF8, 0xA4, 0x32, 0xEB, 0x00, 0x00, 0x00, 0x00 }, /* u.l = 1234567890L: */ { 0x00, 0x00, 0x00, 0x00, 0x49, 0x96, 0x02, 0xD2 }, /* u.l = -1234567890L: */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x69, 0xFD, 0x2E }, /* u.f = 12345.6789: */ { 0x46, 0x40, 0xE6, 0xB7, 0x00, 0x00, 0x00, 0x00 }, /* u.f = -12345.6789: */ { 0xC6, 0x40, 0xE6, 0xB7, 0x00, 0x00, 0x00, 0x00 }, /* u.d = 12345.6789: */ { 0x40, 0xC8, 0x1C, 0xD6, 0xE6, 0x31, 0xF8, 0xA1 }, /* u.d = -12345.6789: */ { 0xC0, 0xC8, 0x1C, 0xD6, 0xE6, 0x31, 0xF8, 0xA1 } }, /* IEEE LITTLE 64 */ /* u.i = 123456789: */ { { 0x15, 0xCD, 0x5B, 0x07, 0x00, 0x00, 0x00, 0x00 }, /* u.i = -123456789: */ { 0xEB, 0x32, 0xA4, 0xF8, 0x00, 0x00, 0x00, 0x00 }, /* u.l = 1234567890L: */ { 0xD2, 0x02, 0x96, 0x49, 0x00, 0x00, 0x00, 0x00 }, /* u.l = -1234567890L: */ { 0x2E, 0xFD, 0x69, 0xB6, 0xFF, 0xFF, 0xFF, 0xFF }, /* u.f = 12345.6789: */ { 0xB7, 0xE6, 0x40, 0x46, 0x00, 0x00, 0x00, 0x00 }, /* u.f = -12345.6789: */ { 0xB7, 0xE6, 0x40, 0xC6, 0x00, 0x00, 0x00, 0x00 }, /* u.d = 12345.6789: */ { 0xA1, 0xF8, 0x31, 0xE6, 0xD6, 0x1C, 0xC8, 0x40 }, /* u.d = -12345.6789: */ { 0xA1, 0xF8, 0x31, 0xE6, 0xD6, 0x1C, 0xC8, 0xC0 } }, /* CRAY */ /* u.i = 123456789: */ { { 0x00, 0x00, 0x00, 0x00, 0x07, 0x5B, 0xCD, 0x15 }, /* u.i = -123456789: */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xA4, 0x32, 0xEB }, /* u.l = 1234567890L: */ { 0x00, 0x00, 0x00, 0x00, 0x49, 0x96, 0x02, 0xD2 }, /* u.l = -1234567890L: */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x69, 0xFD, 0x2E }, /* u.f = 12345.6789: */ { 0x40, 0x0E, 0xC0, 0xE6, 0xB7, 0x31, 0x8F, 0xC5 }, /* u.f = -12345.6789: */ { 0xC0, 0x0E, 0xC0, 0xE6, 0xB7, 0x31, 0x8F, 0xC5 }, /* u.d = 12345.6789: */ { 0x40, 0x0E, 0xC0, 0xE6, 0xB7, 0x31, 0x8F, 0xC5 }, /* u.d = -12345.6789: */ { 0xC0, 0x0E, 0xC0, 0xE6, 0xB7, 0x31, 0x8F, 0xC5 } } } ; void ADFI_figure_machine_format( const char *format, char *machine_format, char *format_to_use, char *os_to_use, int *error_return ) { char requested_format, requested_os, machine_os_size = OS_32_BIT ; union { int i; long l; float f; double d; unsigned char bytes[8]; } u ; int i, k, OK ; if( (machine_format == NULL) || (format_to_use == NULL) || (os_to_use == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check requested format **/ if( format == NULL ) { requested_format = NATIVE_FORMAT_CHAR ; requested_os = OS_32_BIT ; } /* end if */ else if( (format[0] == '\0') || (format[0] == ' ') ) { requested_format = NATIVE_FORMAT_CHAR ; requested_os = OS_32_BIT ; } /* end else if */ else if( ADFI_stridx_c( IEEE_BIG_32_FORMAT_STRING, format ) == 0 ) { requested_format = IEEE_BIG_FORMAT_CHAR ; requested_os = OS_32_BIT ; } /* end else if */ else if( ADFI_stridx_c( IEEE_LITTLE_32_FORMAT_STRING, format ) == 0 ) { requested_format = IEEE_LITTLE_FORMAT_CHAR ; requested_os = OS_32_BIT ; } /* end else if */ else if( ADFI_stridx_c( IEEE_BIG_64_FORMAT_STRING, format ) == 0 ) { requested_format = IEEE_BIG_FORMAT_CHAR ; requested_os = OS_64_BIT ; } /* end else if */ else if( ADFI_stridx_c( IEEE_LITTLE_64_FORMAT_STRING, format ) == 0 ) { requested_format = IEEE_LITTLE_FORMAT_CHAR ; requested_os = OS_64_BIT ; } /* end else if */ else if( ADFI_stridx_c( CRAY_FORMAT_STRING, format ) == 0 ) { requested_format = CRAY_FORMAT_CHAR ; requested_os = OS_64_BIT ; } /* end else if */ else if( ADFI_stridx_c( NATIVE_FORMAT_STRING, format ) == 0 || ADFI_stridx_c( LEGACY_FORMAT_STRING, format ) == 0 ) { requested_format = NATIVE_FORMAT_CHAR ; requested_os = OS_32_BIT ; } /* end else if */ else { *error_return = ADF_FILE_FORMAT_NOT_RECOGNIZED ; return ; } /* end else */ /***** Determine this machine's numeric format *****/ /** Check for numeric bit patterns **/ #define ZERO_UNION() \ for( k=0; k<8; k++ ) \ u.bytes[k] = '\0' ; #define CHECK_UNION(B) \ if( (u.bytes[0] != B[0]) || (u.bytes[1] != B[1]) || \ (u.bytes[2] != B[2]) || (u.bytes[3] != B[3]) || \ (u.bytes[4] != B[4]) || (u.bytes[5] != B[5]) || \ (u.bytes[6] != B[6]) || (u.bytes[7] != B[7]) ) continue ; OK = FALSE ; *machine_format = NATIVE_FORMAT_CHAR ; for( i=0; i= 8 ) machine_os_size = OS_64_BIT ; else machine_os_size = OS_32_BIT ; } /* end if */ if( ADF_this_machine_format == UNDEFINED_FORMAT_CHAR ) { ADF_this_machine_format = *machine_format ; ADF_this_machine_os_size = machine_os_size ; } /* end if */ if( requested_format == NATIVE_FORMAT_CHAR ) { *format_to_use = *machine_format ; *os_to_use = machine_os_size ; } /* end if */ else { *format_to_use = requested_format ; *os_to_use = requested_os ; } /* end if */ if( *machine_format == NATIVE_FORMAT_CHAR ) *error_return = MACHINE_FORMAT_NOT_RECOGNIZED ; } /* end of ADFI_figure_machine_format */ /* end of file ADFI_figure_machine_format.c */ /* end of file ADFI_figure_machine_format.c */ /* file ADFI_file_and_machine_compare.c */ /*********************************************************************** ADFI file and machine compare: Compares file and machine formats. input: const int file_index The file index (0 to MAXIMUM_FILES). output: int *compare 1 = formats compare, 0 = do not output: int *error_return Error return Possible errors: FILE_INDEX_OUT_OF_RANGE ***********************************************************************/ void ADFI_file_and_machine_compare( const int file_index, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, int *compare, int *error_return ) { int machine_size, file_size, token ; *compare = 0 ; *error_return = NO_ERROR ; if( file_index < 0 || file_index >= maximum_files ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } if( ADF_this_machine_format == NATIVE_FORMAT_CHAR || ADF_file[file_index].format == NATIVE_FORMAT_CHAR ) { unsigned int size_long; struct FILE_HEADER file_header ; /** Get file_header for the file variable sizes **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; if( *error_return != NO_ERROR ) return ; size_long = ADF_file[file_index].old_version ? sizeof(long) : sizeof(cglong_t); /** Make sure the sizes are the same or we are cooked!! **/ if ( ADF_file[file_index].format != NATIVE_FORMAT_CHAR || file_header.sizeof_char != sizeof( char ) || file_header.sizeof_short != sizeof( short ) || file_header.sizeof_int != sizeof( int ) || file_header.sizeof_long != size_long || file_header.sizeof_float != sizeof( float ) || #if 0 file_header.sizeof_double != sizeof( double ) || file_header.sizeof_char_p != sizeof( char * ) || file_header.sizeof_short_p != sizeof( short * ) || file_header.sizeof_int_p != sizeof( int * ) || file_header.sizeof_long_p != sizeof( long * ) || file_header.sizeof_float_p != sizeof( float * ) || file_header.sizeof_double_p != sizeof( double * ) ) { #else file_header.sizeof_double != sizeof( double ) ) { #endif *error_return = MACHINE_FILE_INCOMPATABLE ; return ; } /** end if **/ } /** end if **/ if( ADF_file[file_index].format == ADF_this_machine_format && ADF_file[file_index].os_size == ADF_this_machine_os_size ) { *compare = 1 ; } else if( ADF_file[file_index].format == ADF_this_machine_format ) { /** If the file and machine binary type are the same and only the sizes may be different (like long is 32 or 64), then if all the sizes are the same then no converion is necessary and ws can avoid the conversion overhead and just do direct read/writes. **/ if ( tokenized_data_type == NULL ) return ; token = -1 ; *compare = 1 ; do { token++ ; machine_size = tokenized_data_type[ token ].machine_type_size ; file_size = tokenized_data_type[ token ].file_type_size ; if ( machine_size != file_size ) { *compare = 0 ; break ; } } while( tokenized_data_type[ token ].type[0] != 0 ) ; } } /* end of ADFI_file_and_machine_compare */ /* end of file ADFI_file_and_machine_compare.c */ /* file ADFI_file_block_offset_2_ID.c */ /*********************************************************************** ADFI file block and offset to ID: Convert an ADF file, block, and offset to an ADF ID. input: const int file_index The file index (0 to MAXIMUM_FILES). input: const unsigned long file_block The block within the file. input: const unsigned long block_offset The offset within the block. output: double *ID The resulting ADF ID. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER FILE_INDEX_OUT_OF_RANGE BLOCK_OFFSET_OUT_OF_RANGE ***********************************************************************/ void ADFI_file_block_offset_2_ID( const int file_index, const cgulong_t file_block, const cgulong_t block_offset, double *ID, int *error_return ) { double dd; unsigned char * cc; if( ID == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; if( file_index >= maximum_files ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } /* end if */ if( block_offset >= DISK_BLOCK_SIZE ) { *error_return = BLOCK_OFFSET_OUT_OF_RANGE ; return ; } /* end if */ /** Map the bytes into the character variable **/ /* Note that there were problems with some machines flushing small numbers to zero causing problems with the encoding of ID (which is not in its self a true number). The IEEE standard says that this is not allowed and so should not be a problem except that you get a major performance hit on the machine if you have it enforce the IEEE standard. Thus I force the sign bit on the exponent to always be positive so that the ID is a number greater than |1|. Previously on the IEEE big endian the numbers would look like 3.132313E-311. The new encoding changes the max number of open files to 16K from 64K */ cc = (unsigned char *) ⅆ #ifdef NEW_ID_MAPPING #if 0 assert(file_index <= 0xfff); assert(file_block <= 0x3fffffffff); assert(block_offset <= 0xfff); if (ADF_this_machine_format == IEEE_LITTLE_FORMAT_CHAR) { cc[7] = (unsigned char)((file_index & 0x0FC0) >> 6) + 0x40; cc[6] = (unsigned char)((file_index & 0x003F) << 2) + (unsigned char)((file_block & 0x3000000000) >> 36); cc[5] = (unsigned char)((file_block & 0x0FF0000000) >> 28); cc[4] = (unsigned char)((file_block & 0x000FF00000) >> 20); cc[3] = (unsigned char)((file_block & 0x00000FF000) >> 12); cc[2] = (unsigned char)((file_block & 0x0000000FF0) >> 4); cc[1] = (unsigned char)((file_block & 0x000000000F) << 4) + (unsigned char)((block_offset & 0x0F00) >> 8); cc[0] = (unsigned char) (block_offset & 0x00FF); } else { cc[0] = (unsigned char)((file_index & 0x0FC0) >> 6) + 0x40; cc[1] = (unsigned char)((file_index & 0x003F) << 2) + (unsigned char)((file_block & 0x3000000000) >> 36); cc[2] = (unsigned char)((file_block & 0x0FF0000000) >> 28); cc[3] = (unsigned char)((file_block & 0x000FF00000) >> 20); cc[4] = (unsigned char)((file_block & 0x00000FF000) >> 12); cc[5] = (unsigned char)((file_block & 0x0000000FF0) >> 4); cc[6] = (unsigned char)((file_block & 0x000000000F) << 4) + (unsigned char)((block_offset & 0x0F00) >> 8); cc[7] = (unsigned char) (block_offset & 0x00FF); } #else if (ADF_this_machine_format == IEEE_LITTLE_FORMAT_CHAR) { cc[7] = (unsigned char)((file_index >> 6) & 0x3F) + 0x40; cc[6] = (unsigned char)((file_index << 2) & 0xFC) + (unsigned char)((file_block >> 36) & 0x03); cc[5] = (unsigned char)((file_block >> 28) & 0xFF); cc[4] = (unsigned char)((file_block >> 20) & 0xFF); cc[3] = (unsigned char)((file_block >> 12) & 0xFF); cc[2] = (unsigned char)((file_block >> 4) & 0xFF); cc[1] = (unsigned char)((file_block << 4) & 0xF0) + (unsigned char)((block_offset >> 8) & 0x0F); cc[0] = (unsigned char) (block_offset & 0xFF); } else { cc[0] = (unsigned char)((file_index >> 6) & 0x3F) + 0x40; cc[1] = (unsigned char)((file_index << 2) & 0xFC) + (unsigned char)((file_block >> 36) & 0x03); cc[2] = (unsigned char)((file_block >> 28) & 0xFF); cc[3] = (unsigned char)((file_block >> 20) & 0xFF); cc[4] = (unsigned char)((file_block >> 12) & 0xFF); cc[5] = (unsigned char)((file_block >> 4) & 0xFF); cc[6] = (unsigned char)((file_block << 4) & 0xF0) + (unsigned char)((block_offset >> 8) & 0x0F); cc[7] = (unsigned char) (block_offset & 0xFF); } #endif #else if ( ADF_this_machine_format == IEEE_BIG_FORMAT_CHAR ) { cc[1] = (unsigned char) (file_index & 0x00ff) ; cc[0] = (unsigned char) (64 + (( file_index >> 8) & 0x003f)) ; cc[2] = (unsigned char) (file_block & 0x000000ff) ; cc[3] = (unsigned char) ((file_block >> 8) & 0x000000ff) ; cc[4] = (unsigned char) ((file_block >> 16) & 0x000000ff) ; cc[5] = (unsigned char) ((file_block >> 24) & 0x000000ff) ; cc[6] = (unsigned char) (block_offset & 0x00ff) ; cc[7] = (unsigned char) ((block_offset >> 8) & 0x00ff) ; } /* end if */ else if ( ADF_this_machine_format == IEEE_LITTLE_FORMAT_CHAR ) { cc[6] = (unsigned char) (file_index & 0x00ff) ; cc[7] = (unsigned char) (64 + (( file_index >> 8) & 0x003f)) ; cc[2] = (unsigned char) (file_block & 0x000000ff) ; cc[3] = (unsigned char) ((file_block >> 8) & 0x000000ff) ; cc[4] = (unsigned char) ((file_block >> 16) & 0x000000ff) ; cc[5] = (unsigned char) ((file_block >> 24) & 0x000000ff) ; cc[0] = (unsigned char) (block_offset & 0x00ff) ; cc[1] = (unsigned char) ((block_offset >> 8) & 0x00ff) ; } /* end else if */ else { cc[0] = (unsigned char) (file_index & 0x00ff) ; cc[1] = (unsigned char) ((file_index >> 8) & 0x00ff) ; cc[2] = (unsigned char) (file_block & 0x000000ff) ; cc[3] = (unsigned char) ((file_block >> 8) & 0x000000ff) ; cc[4] = (unsigned char) ((file_block >> 16) & 0x000000ff) ; cc[5] = (unsigned char) ((file_block >> 24) & 0x000000ff) ; cc[6] = (unsigned char) (block_offset & 0x00ff) ; cc[7] = (unsigned char) ((block_offset >> 8) & 0x00ff) ; } /* end else */ #endif *ID = dd; #ifdef PRINT_STUFF printf("cc[0-7] = %02X %02X %02X %02X %02X %02X %02X %02X \n", cc[0], cc[1], cc[2], cc[3], cc[4], cc[5], cc[6], cc[7] ) ; printf("In ADFI_file_block_offset_2_ID: ID=%lf\n",*ID); #endif } /* end of ADFI_file_block_offset_2_ID */ /* end of file ADFI_file_block_offset_2_ID.c */ /* file ADFI_file_free.c */ /*********************************************************************** ADFI file free: To free-up a chunk of file space. input: const int file_index The file index (0 to MAXIMUM_FILES). input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const long number_of_bytes Number of bytes to free. If 0, then look at type of chunk to get size. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED FREE_OF_ROOT_NODE ADF_DISK_TAG_ERROR FREE_OF_FREE_CHUNK_TABLE ***********************************************************************/ void ADFI_file_free( const int file_index, const struct DISK_POINTER *block_offset, const cglong_t in_number_of_bytes, int *error_return ) { char tag[TAG_SIZE + 1] ; struct DISK_POINTER end_of_chunk_tag ; struct DISK_POINTER tmp_blk_ofst ; struct FREE_CHUNK_TABLE free_chunk_table ; struct FREE_CHUNK free_chunk ; int i ; cglong_t number_of_bytes = in_number_of_bytes ; if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ if( number_of_bytes == 0 ) { /** Check the disk tag to see what kind of disk chunk we have. We need this to determine the length of the chunk. **/ ADFI_read_file( file_index, block_offset->block, block_offset->offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; /* Null terminate the string */ end_of_chunk_tag.block = 0 ; end_of_chunk_tag.offset = 0 ; if( ADFI_stridx_c( tag, node_start_tag ) == 0 ) { /** This is a node **/ if( (block_offset->block == ROOT_NODE_BLOCK) && (block_offset->offset == ROOT_NODE_OFFSET) ) { *error_return = FREE_OF_ROOT_NODE ; return ; } /* end if */ end_of_chunk_tag.block = block_offset->block ; end_of_chunk_tag.offset = block_offset->offset + NODE_HEADER_SIZE - TAG_SIZE ; if ( end_of_chunk_tag.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; } /** Check disk boundary-tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; if( ADFI_stridx_c( tag, node_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ } /* end if */ else if( ADFI_stridx_c( tag, free_chunk_table_start_tag ) == 0 ) { /** Trying to free the free-chunk-table. This is BAD. **/ *error_return = FREE_OF_FREE_CHUNK_TABLE ; return ; } /* end else if */ else if( ADFI_stridx_c( tag, free_chunk_start_tag ) == 0 ) { /** Set a temporary block/offset to read disk pointer **/ tmp_blk_ofst.block = block_offset->block ; tmp_blk_ofst.offset = block_offset->offset + TAG_SIZE ; if ( tmp_blk_ofst.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &tmp_blk_ofst, error_return ) ; if( *error_return != NO_ERROR ) return ; } /** Get the end_of_chunk-tag block/offset from disk **/ ADFI_read_disk_pointer_from_disk( file_index, tmp_blk_ofst.block, tmp_blk_ofst.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk boundary-tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; if( ADFI_stridx_c( tag, free_chunk_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ } /* end else if */ else if( ADFI_stridx_c( tag, sub_node_start_tag ) == 0 ) { /** Set a temporary block/offset to read disk pointer **/ tmp_blk_ofst.block = block_offset->block ; tmp_blk_ofst.offset = block_offset->offset + TAG_SIZE ; if ( tmp_blk_ofst.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &tmp_blk_ofst, error_return ) ; if( *error_return != NO_ERROR ) return ; } /** Get the end_of_chunk-tag block/offset from disk **/ ADFI_read_disk_pointer_from_disk( file_index, tmp_blk_ofst.block, tmp_blk_ofst.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk boundary-tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; if( ADFI_stridx_c( tag, sub_node_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ } /* end else if */ else if( ADFI_stridx_c( tag, data_chunk_table_start_tag ) == 0 ) { /** Set a temporary block/offset to read disk pointer **/ tmp_blk_ofst.block = block_offset->block ; tmp_blk_ofst.offset = block_offset->offset + TAG_SIZE ; if ( tmp_blk_ofst.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &tmp_blk_ofst, error_return ) ; if( *error_return != NO_ERROR ) return ; } /** Get the end_of_chunk-tag block/offset from disk **/ ADFI_read_disk_pointer_from_disk( file_index, tmp_blk_ofst.block, tmp_blk_ofst.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk boundary-tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; if( ADFI_stridx_c( tag, data_chunk_table_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ } /* end else if */ else if( ADFI_stridx_c( tag, data_chunk_start_tag ) == 0 ) { /** Set a temporary block/offset to read disk pointer **/ tmp_blk_ofst.block = block_offset->block ; tmp_blk_ofst.offset = block_offset->offset + TAG_SIZE ; if ( tmp_blk_ofst.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &tmp_blk_ofst, error_return ) ; if( *error_return != NO_ERROR ) return ; } /** Get the end_of_chunk-tag block/offset from disk **/ ADFI_read_disk_pointer_from_disk( file_index, tmp_blk_ofst.block, tmp_blk_ofst.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk boundary-tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; if( ADFI_stridx_c( tag, data_chunk_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ } /* end else if */ else { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end else */ number_of_bytes = (end_of_chunk_tag.block - block_offset->block) * DISK_BLOCK_SIZE + (end_of_chunk_tag.offset - block_offset->offset + TAG_SIZE) ; } /* end if */ else { /** Use the number of bytes passed in **/ end_of_chunk_tag.block = block_offset->block ; end_of_chunk_tag.offset = block_offset->offset + number_of_bytes - TAG_SIZE ; ADFI_adjust_disk_pointer( &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ if( number_of_bytes <= SMALLEST_CHUNK_SIZE ) { /** Too small, z-gas **/ /** Initialize the block of 'Z's **/ if( block_of_ZZ_initialized == FALSE ) { for( i=0; ioffset <= 0x1fff); ADFI_write_file( file_index, block_offset->block, block_offset->offset, number_of_bytes, block_of_ZZ, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { /** Add this chunk to the free table **/ /** Get the free-chunk-table **/ ADFI_read_free_chunk_table( file_index, &free_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; if( block_offset->block == end_of_chunk_tag.block ) { /* small or medium */ if( (end_of_chunk_tag.offset + TAG_SIZE - block_offset->offset) <= SMALL_CHUNK_MAXIMUM ) { /** SMALL chunk **/ free_chunk.end_of_chunk_tag.block = end_of_chunk_tag.block ; free_chunk.end_of_chunk_tag.offset = end_of_chunk_tag.offset ; free_chunk.next_chunk.block = free_chunk_table.small_first_block.block; free_chunk.next_chunk.offset = free_chunk_table.small_first_block.offset ; free_chunk_table.small_first_block.block = block_offset->block ; free_chunk_table.small_first_block.offset = block_offset->offset ; /** If linked-list was empty, also point to this as the last. **/ if( free_chunk.next_chunk.offset == BLANK_BLOCK_OFFSET ) { free_chunk_table.small_last_block.block = block_offset->block ; free_chunk_table.small_last_block.offset = block_offset->offset ; } /* end if */ } /* end if */ else { /** MEDIUM chunk **/ free_chunk.end_of_chunk_tag.block = end_of_chunk_tag.block ; free_chunk.end_of_chunk_tag.offset = end_of_chunk_tag.offset ; free_chunk.next_chunk.block = free_chunk_table.medium_first_block.block ; free_chunk.next_chunk.offset = free_chunk_table.medium_first_block.offset; free_chunk_table.medium_first_block.block = block_offset->block ; free_chunk_table.medium_first_block.offset = block_offset->offset ; /** If linked-list was empty, also point to this as the last. **/ if( free_chunk.next_chunk.offset == BLANK_BLOCK_OFFSET ) { free_chunk_table.medium_last_block.block = block_offset->block ; free_chunk_table.medium_last_block.offset = block_offset->offset ; } /* end if */ } /* end else */ } /* end if */ else { /** LARGE chunk **/ free_chunk.end_of_chunk_tag.block = end_of_chunk_tag.block ; free_chunk.end_of_chunk_tag.offset = end_of_chunk_tag.offset ; free_chunk.next_chunk.block = free_chunk_table.large_first_block.block; free_chunk.next_chunk.offset = free_chunk_table.large_first_block.offset ; free_chunk_table.large_first_block.block = block_offset->block ; free_chunk_table.large_first_block.offset = block_offset->offset ; /** If linked-list was empty, also point to this as the last. **/ if( free_chunk.next_chunk.offset == BLANK_BLOCK_OFFSET ) { free_chunk_table.large_last_block.block = block_offset->block ; free_chunk_table.large_last_block.offset = block_offset->offset ; } /* end if */ } /* end else */ /** Put the free-chunk tags in place **/ strncpy( free_chunk.start_tag, free_chunk_start_tag, TAG_SIZE ) ; strncpy( free_chunk.end_tag, free_chunk_end_tag, TAG_SIZE ) ; /** Write out the free chunk **/ ADFI_write_free_chunk( file_index, block_offset, &free_chunk, error_return ); if( *error_return != NO_ERROR ) return ; /** Update the free-chunk-table **/ ADFI_write_free_chunk_table( file_index, &free_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ /** Delete the block/offset off the stack **/ ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, DEL_STK_ENTRY, 0, 0, NULL ) ; } /* end of ADFI_file_free */ /* end of file ADFI_file_free.c */ /* file ADFI_file_malloc.c */ /*********************************************************************** ADFI file malloc: To allocate a chunk of disk space. input: const int file_index The file index (0 to MAXIMUM_FILES). input: size_bytes The size in bytes to allocate. output: const struct DISK_POINTER *block_offset Block & offset in the file. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_file_malloc( const int file_index, const cglong_t size_bytes, struct DISK_POINTER *block_offset, int *error_return ) { struct FILE_HEADER file_header ; int memory_found = FALSE ; #if 0 struct FREE_CHUNK_TABLE free_chunk_table ; struct DISK_POINTER disk_pointer, previous_disk_pointer ; struct DISK_POINTER *first_free_block, *last_free_block ; struct FREE_CHUNK free_chunk, previous_free_chunk ; int i ; unsigned long size ; #endif if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ #if 0 /* skip this, and just write to end of file - this gives a significant speedup with only a small increase in file size. If the file is modified, skipping this will leave large holes in the file, but the entire file is rewritten by cg_close so we can ignore it here */ /** Get the free-chunk_table **/ ADFI_read_free_chunk_table( file_index, &free_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Look for the needed space in the 3 free lists. Note that all file control headers are smaller than the SMALLEST_CHUNK_SIZE and so will be fit later into a block at the end of the file. This greatly improves node creation efficiency. **/ for( i=0; i<3; i++ ) { if( memory_found == TRUE || size_bytes <= SMALLEST_CHUNK_SIZE ) break ; ADFI_set_blank_disk_pointer( &previous_disk_pointer ) ; switch( i ) { case 0: /** SMALL CHUNKS **/ if( size_bytes > SMALL_CHUNK_MAXIMUM ) continue ; /** Next in the for loop **/ first_free_block = &free_chunk_table.small_first_block ; last_free_block = &free_chunk_table.small_last_block ; break ; case 1: /** MEDIUM CHUNKS **/ if( size_bytes > MEDIUM_CHUNK_MAXIMUM ) continue ; /** Next in the for loop **/ first_free_block = &free_chunk_table.medium_first_block ; last_free_block = &free_chunk_table.medium_last_block ; break ; case 2: /** LARGE CHUNKS **/ first_free_block = &free_chunk_table.large_first_block ; last_free_block = &free_chunk_table.large_last_block ; break ; } /* end switch */ disk_pointer = *first_free_block ; while( (memory_found != TRUE) && ((disk_pointer.block != BLANK_FILE_BLOCK) || (disk_pointer.offset != BLANK_BLOCK_OFFSET)) ) { ADFI_read_free_chunk( file_index, &disk_pointer, &free_chunk, error_return ) ; if( *error_return != NO_ERROR ) return ; size = (free_chunk.end_of_chunk_tag.block - disk_pointer.block) * DISK_BLOCK_SIZE + (free_chunk.end_of_chunk_tag.offset - disk_pointer.offset) + TAG_SIZE ; if( (long int) size >= size_bytes ) { *block_offset = disk_pointer ; if( (previous_disk_pointer.block != BLANK_FILE_BLOCK) || (previous_disk_pointer.offset != BLANK_BLOCK_OFFSET) ) { /** Link previous free-chunk to the next free-chunk, removing this free-chunk from the list **/ ADFI_read_free_chunk( file_index, &previous_disk_pointer, &previous_free_chunk, error_return ) ; if( *error_return != NO_ERROR ) return ; previous_free_chunk.next_chunk = free_chunk.next_chunk ; ADFI_write_free_chunk( file_index, &previous_disk_pointer, &previous_free_chunk, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { /** Free-chunk was the first one, change entry in the free-chunk-header **/ *first_free_block = free_chunk.next_chunk ; ADFI_write_free_chunk_table( file_index, &free_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ if((last_free_block->block == disk_pointer.block) && (last_free_block->offset == disk_pointer.offset)){ if( (previous_disk_pointer.block != BLANK_FILE_BLOCK) || (previous_disk_pointer.offset != BLANK_BLOCK_OFFSET) ) { *last_free_block = previous_disk_pointer ; } /* end if */ else { ADFI_set_blank_disk_pointer( last_free_block ) ; } /* end else */ ADFI_write_free_chunk_table( file_index, &free_chunk_table, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ size -= size_bytes ; if ( size > 0 ) { disk_pointer.offset += size_bytes ; ADFI_adjust_disk_pointer( &disk_pointer, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_file_free( file_index, &disk_pointer, size, error_return ) ; if( *error_return != NO_ERROR ) return ; } memory_found = TRUE ; } /* end if */ else { previous_disk_pointer = disk_pointer ; disk_pointer = free_chunk.next_chunk ; } /* end else */ } /* end while */ } /* end if */ #endif /** The end-of_file pointer points to the last byte USED, NOT the next byte TO USE. **/ if( memory_found != TRUE ) { /* Append memory at end of file **/ ADFI_read_file_header( file_index, &file_header, error_return ) ; if( *error_return != NO_ERROR ) return ; /** If the end-of_file is NOT at a block boundary, then see if the new allocated chunk will span a block boundary. If it will, then start at the new block if it will fit within the block. This helps efficiency to have file control headers located within a block boundry. **/ if( file_header.end_of_file.offset != DISK_BLOCK_SIZE - 1 ) { if( (file_header.end_of_file.offset+size_bytes) >= DISK_BLOCK_SIZE && size_bytes <= DISK_BLOCK_SIZE ) { /** Free rest of block, allocate from next block **/ file_header.end_of_file.offset++ ; ADFI_file_free( file_index, &file_header.end_of_file, DISK_BLOCK_SIZE - file_header.end_of_file.offset, error_return ) ; if( *error_return != NO_ERROR ) return ; block_offset->block = file_header.end_of_file.block + 1 ; block_offset->offset = 0 ; file_header.end_of_file.block++ ; file_header.end_of_file.offset = size_bytes - 1 ; ADFI_adjust_disk_pointer( &file_header.end_of_file, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { /** Use the remaining block **/ block_offset->block = file_header.end_of_file.block ; block_offset->offset = file_header.end_of_file.offset + 1 ; file_header.end_of_file.offset += size_bytes ; ADFI_adjust_disk_pointer( &file_header.end_of_file, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ } /* end if */ else { /* already pointing to start of block **/ block_offset->block = file_header.end_of_file.block + 1 ; block_offset->offset = 0 ; file_header.end_of_file.block++ ; file_header.end_of_file.offset = size_bytes - 1 ; ADFI_adjust_disk_pointer( &file_header.end_of_file, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ /** Write out the modified file header **/ ADFI_write_file_header( file_index, &file_header, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ } /* end of ADFI_file_malloc */ /* end of file ADFI_file_malloc.c */ /* file ADFI_fill_initial_file_header.c */ /*********************************************************************** ADFI fill initial file header: To determine the file header information... input: const char format 'B', 'L', 'C', 'N' input: const char os_size 'B', 'L' input: const char *what_string UNIX "what" identifier. output: struct FILE_HEADER *file_header The resulting file header information. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ADF_FILE_FORMAT_NOT_RECOGNIZED ***********************************************************************/ void ADFI_fill_initial_file_header( const char format, const char os_size, const char *what_string, struct FILE_HEADER *file_header, int *error_return ) { int i ; if( what_string == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( file_header == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (format != IEEE_BIG_FORMAT_CHAR) && (format != IEEE_LITTLE_FORMAT_CHAR) && (format != CRAY_FORMAT_CHAR) && (format != NATIVE_FORMAT_CHAR) ) { *error_return = ADF_FILE_FORMAT_NOT_RECOGNIZED ; return ; } /* end if */ /** Put the boundary tags in first. If we then overwrite them, we'll know **/ strncpy( file_header->tag0, file_header_tags[0], TAG_SIZE ) ; strncpy( file_header->tag1, file_header_tags[1], TAG_SIZE ) ; strncpy( file_header->tag2, file_header_tags[2], TAG_SIZE ) ; strncpy( file_header->tag3, file_header_tags[3], TAG_SIZE ) ; strncpy( file_header->tag4, file_header_tags[4], TAG_SIZE ) ; strncpy( file_header->tag5, file_header_tags[5], TAG_SIZE ) ; /** The UNIX "what" string" - blank terminated **/ strncpy( file_header->what, what_string, WHAT_STRING_SIZE ) ; if ( strlen(what_string) < WHAT_STRING_SIZE ) { ADFI_blank_fill_string ( file_header->what, WHAT_STRING_SIZE ) ; } /** File creation date/time - blank terminated **/ ADFI_get_current_date( file_header->creation_date ) ; /** File modification date/time - same as creation time **/ strncpy( file_header->modification_date, file_header->creation_date, DATE_TIME_SIZE ) ; file_header->numeric_format = format ; file_header->os_size = os_size ; /** Set sizeof() information for file data **/ if( (format==ADF_this_machine_format && os_size==ADF_this_machine_os_size) || format==NATIVE_FORMAT_CHAR ) { file_header->sizeof_char = sizeof( char ) ; file_header->sizeof_short = sizeof( short ) ; file_header->sizeof_int = sizeof( int ) ; #if 0 file_header->sizeof_long = sizeof( long ) ; #else file_header->sizeof_long = sizeof( cglong_t ) ; #endif file_header->sizeof_float = sizeof( float ) ; file_header->sizeof_double = sizeof( double ) ; file_header->sizeof_char_p = sizeof( char * ) ; file_header->sizeof_short_p = sizeof( short * ) ; file_header->sizeof_int_p = sizeof( int * ) ; #if 0 file_header->sizeof_long_p = sizeof( long * ) ; #else file_header->sizeof_long_p = sizeof( cglong_t * ) ; #endif file_header->sizeof_float_p = sizeof( float * ) ; file_header->sizeof_double_p = sizeof( double * ) ; } /** end if **/ else { switch( EVAL_2_BYTES( format, os_size ) ) { case EVAL_2_BYTES( 'B', 'L' ): i = IEEE_BIG_32_FORMAT - 1 ; break ; case EVAL_2_BYTES( 'L', 'L' ): i = IEEE_LITTLE_32_FORMAT - 1 ; break ; case EVAL_2_BYTES( 'B', 'B' ): i = IEEE_BIG_64_FORMAT - 1 ; break ; case EVAL_2_BYTES( 'L', 'B' ): i = IEEE_LITTLE_64_FORMAT - 1 ; break ; case EVAL_2_BYTES( 'C', 'B' ): i = CRAY_FORMAT - 1 ; break ; default: *error_return = MACHINE_FORMAT_NOT_RECOGNIZED ; return ; } /* end switch */ file_header->sizeof_char = (unsigned int)machine_sizes[i][ 0] ; file_header->sizeof_short = (unsigned int)machine_sizes[i][ 3] ; file_header->sizeof_int = (unsigned int)machine_sizes[i][ 5] ; #if 0 file_header->sizeof_long = (unsigned int)machine_sizes[i][ 7] ; #else file_header->sizeof_long = (unsigned int)sizeof(cglong_t) ; #endif file_header->sizeof_float = (unsigned int)machine_sizes[i][ 9] ; file_header->sizeof_double = (unsigned int)machine_sizes[i][10] ; file_header->sizeof_char_p = (unsigned int)machine_sizes[i][11] ; file_header->sizeof_short_p = (unsigned int)machine_sizes[i][12] ; file_header->sizeof_int_p = (unsigned int)machine_sizes[i][12] ; #if 0 file_header->sizeof_long_p = (unsigned int)machine_sizes[i][13] ; #else file_header->sizeof_long_p = (unsigned int)sizeof(cglong_t *) ; #endif file_header->sizeof_float_p = (unsigned int)machine_sizes[i][14] ; file_header->sizeof_double_p = (unsigned int)machine_sizes[i][15] ; } /** end else **/ /** Set root node table pointers **/ file_header->root_node.block = ROOT_NODE_BLOCK ; file_header->root_node.offset = ROOT_NODE_OFFSET ; file_header->end_of_file.block = ROOT_NODE_BLOCK ; file_header->end_of_file.offset = ROOT_NODE_OFFSET + NODE_HEADER_SIZE - 1 ; file_header->free_chunks.block = FREE_CHUNKS_BLOCK ; file_header->free_chunks.offset = FREE_CHUNKS_OFFSET ; ADFI_set_blank_disk_pointer( &file_header->extra ) ; } /* end of ADFI_fill_initial_file_header */ /* end of file ADFI_fill_initial_file_header.c */ /* file ADFI_fill_initial_free_chunk_table.c */ /*********************************************************************** ADFI fill initial free chunk header: To fill out a new free chunk header. output: struct FREE_CHUNK_TABLE *free_chunk_table Resulting header info. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ***********************************************************************/ void ADFI_fill_initial_free_chunk_table( struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) { if( free_chunk_table == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ strncpy( free_chunk_table->start_tag, free_chunk_table_start_tag, TAG_SIZE ) ; strncpy( free_chunk_table->end_tag, free_chunk_table_end_tag, TAG_SIZE ) ; /** Small: First and Last Blocks **/ ADFI_set_blank_disk_pointer( &free_chunk_table->small_first_block ) ; ADFI_set_blank_disk_pointer( &free_chunk_table->small_last_block ) ; /** Medium: First and Last Blocks **/ ADFI_set_blank_disk_pointer( &free_chunk_table->medium_first_block ) ; ADFI_set_blank_disk_pointer( &free_chunk_table->medium_last_block ) ; /** large: First and Last Blocks **/ ADFI_set_blank_disk_pointer( &free_chunk_table->large_first_block ) ; ADFI_set_blank_disk_pointer( &free_chunk_table->large_last_block ) ; } /* end of ADFI_fill_initial_free_chunk_table */ /* end of file ADFI_fill_initial_free_chunk_table.c */ /* file ADFI_fill_initial_node_header.c */ /*********************************************************************** ADFI fill initial node header: To fill out a new node header. output: struct NODE_HEADER *node_header The resulting node header information. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ***********************************************************************/ void ADFI_fill_initial_node_header( struct NODE_HEADER *node_header, int *error_return ) { int i ; if( node_header == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ strncpy( node_header->node_start_tag, node_start_tag, TAG_SIZE ) ; strncpy( node_header->node_end_tag, node_end_tag, TAG_SIZE ) ; /** Blank out the name **/ for( i=0; iname[i] = ' ' ; /** Blank out the label **/ for( i=0; ilabel[i] = ' ' ; /** Set number of sub nodes to zero **/ node_header->num_sub_nodes = 0 ; node_header->entries_for_sub_nodes = 0 ; ADFI_set_blank_disk_pointer( &node_header->sub_node_table ) ; /** Blank out the Data-Type, then set to eMpTy. **/ for( i=2; idata_type[i] = ' ' ; node_header->data_type[0] = 'M' ; node_header->data_type[1] = 'T' ; /** Zero out number of dimensions & Set dimension values to zero **/ node_header->number_of_dimensions = 0 ; for( i=0; idimension_values[i] = 0 ; /** Set number of data chunks to zero, zero out data chunk pointer **/ node_header->number_of_data_chunks = 0 ; ADFI_set_blank_disk_pointer( &node_header->data_chunks ) ; } /* end of ADFI_fill_initial_node_header */ /* end of file ADFI_fill_initial_node_header.c */ /* file ADFI_flush_buffers.c */ /*********************************************************************** ADFI Flush buffers: input: const unsigned int file_index The file index. output: int *error_return Error return. Possible errors: NO_ERROR ADF_FILE_NOT_OPENED FWRITE_ERROR ***********************************************************************/ void ADFI_flush_buffers( const unsigned int file_index, int flush_mode, int *error_return ) { char data; if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; if ( (int)file_index == last_wr_file ) { /** Flush any active write buffer, file block is set to a nonsense value so that the buffer flags are not reset **/ ADFI_write_file ( file_index, MAXIMUM_32_BITS, 0, 0, &data, error_return ) ; /** Reset control flags **/ if ( flush_mode == FLUSH_CLOSE ) { last_wr_block = -2; last_wr_file = -2; flush_wr_block = -2 ; } } if ( (int) file_index == last_rd_file && flush_mode == FLUSH_CLOSE ) { /** Reset control flags **/ last_rd_block = -1; last_rd_file = -1; num_in_rd_block = -1; } } /* end of ADFI_flush_buffers */ /* end of file ADFI_flush_buffers.c */ /* file ADFI_fseek_file.c */ /*********************************************************************** ADFI_fseek_file: To position the current position for fread() or fwrite(). Need to allow for files larger than what a long int can represent (the offset for fseek). input: const unsigned int file_index File to use. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. output: int *error_return Error return. Possible errors: NO_ERROR ADF_FILE_NOT_OPENED FSEEK_ERROR ***********************************************************************/ void ADFI_fseek_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, int *error_return ) { file_offset_t offset; file_offset_t iret; if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ offset = (file_offset_t)(file_block * DISK_BLOCK_SIZE + block_offset) ; if (offset < 0) { *error_return = MAX_FILE_SIZE_EXCEEDED; return; } *error_return = NO_ERROR ; ADF_sys_err = 0; iret = file_seek( ADF_file[file_index].file, offset, SEEK_SET ) ; if( iret < 0 ) { ADF_sys_err = errno; *error_return = FSEEK_ERROR ; } /* end if */ } /* end of ADFI_fseek_file */ /* end of file ADFI_fseek_file.c */ /* file ADFI_get_current_date.c */ /*********************************************************************** ADFI get current date: Returns the current date and time in a blank-filled character array. output: char date[] Current date/time in an array blank-filled to DATE_TIME_SIZE. Array must be allocated to at least DATE_TIME_SIZE. No null added. ***********************************************************************/ void ADFI_get_current_date( char date[] ) { time_t ct ; int i_len ; char *current_time_p ; /** get the current time **/ ct = time( (time_t *)NULL ) ; current_time_p = ctime( &ct ) ; /** remove '\n' from ctime format **/ i_len = (int)strcspn ( current_time_p, "\n" ) ; strcpy( date, current_time_p ) ; date[i_len] = '\0' ; /** blank fill **/ ADFI_blank_fill_string ( date, DATE_TIME_SIZE ) ; } /* end of ADFI_get_current_date */ /* end of file ADFI_get_current_date.c */ /* file ADFI_get_direct_children_ids.c */ /*********************************************************************** ADFI get direct children ids: Get Children ids of a Node. Return the ids of children nodes directly associated with a parent node (no links are followed). The ids of the children are NOT guaranteed to be returned in any particular order. If it is desired to follow potential links for the node ID, then call ADFI_chase_link() and pass the resultant link ID to this function. NOTE: link nodes do not have direct children. ADFI_get_direct_children_ids( ID, num_ids, ids, error_return ) input: const unsigned int file_index The file index. input: const struct DISK_POINTER *node_block_offset Block & offset in file. output: int *num_ids The number of ids returned. output: double **ids An allocated array of ids (free this space). output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER MEMORY_ALLOCATION_FAILED FILE_INDEX_OUT_OF_RANGE BLOCK_OFFSET_OUT_OF_RANGE ADF_FILE_NOT_OPENED ADF_DISK_TAG_ERROR ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_get_direct_children_ids( const unsigned int file_index, const struct DISK_POINTER *node_block_offset, int *num_ids, double **ids, int *error_return ) { int i ; struct DISK_POINTER sub_node_block_offset ; struct NODE_HEADER node ; struct SUB_NODE_TABLE_ENTRY sub_node_table_entry ; *error_return = NO_ERROR ; if( num_ids == NULL || ids == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *num_ids = 0 ; *ids = NULL ; ADFI_read_node_header( file_index, node_block_offset, &node, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check for zero children, return if 0 **/ if( node.num_sub_nodes == 0 ) { return ; } /* end if */ *ids = (double *) malloc ( node.num_sub_nodes * sizeof(double) ) ; if( *ids == NULL ) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } /* end if */ /** point to the first child **/ sub_node_block_offset.block = node.sub_node_table.block ; sub_node_block_offset.offset = node.sub_node_table.offset + (TAG_SIZE + DISK_POINTER_SIZE ) ; /** Return the ids for all the children **/ *num_ids = node.num_sub_nodes ; for( i=0; i< *num_ids; i++ ) { ADFI_adjust_disk_pointer( &sub_node_block_offset, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Read one sub-node table entry **/ ADFI_read_sub_node_table_entry( file_index, &sub_node_block_offset, &sub_node_table_entry, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Get the ID from the sub-node table **/ ADFI_file_block_offset_2_ID( file_index, sub_node_table_entry.child_location.block, sub_node_table_entry.child_location.offset, &(*ids)[i], error_return ) ; if( *error_return != NO_ERROR ) return ; /** Increment the disk-pointer **/ sub_node_block_offset.offset += (ADF_NAME_LENGTH + DISK_POINTER_SIZE) ; } /* end for */ } /* end of file ADFI_get_direct_children_ids.c */ /* file ADFI_get_file_index_from_name.c */ /*********************************************************************** ADFI get file index from name: Searches file list for given name. Returns file index and Root ID if name is found in list. input: const char *file_name Name of file output: int *found 1 = name found, 0 = not found output: unsigned int *file_index File-index output: double *ID ID of files root node output: int *error_return Error return ***********************************************************************/ void ADFI_get_file_index_from_name( const char *file_name, int *found, unsigned int *file_index, double *ID, int *error_return ) { double root_ID = 0; int i ; *error_return = NO_ERROR ; if( (file_index == NULL) || (ID == NULL) || (found == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_name == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ *found = 0; for( i=0; i 12) ) { *error_return = BAD_NUMBER_OF_DIMENSIONS ; return ; } /* end if */ *error_return = NO_ERROR ; offset = 0 ; accumlated_size = 1 ; for( i=0; i>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa Machine Numeric Formats: ***IEEE_LITTLE ( The backwards Big Endian ) I4: Byte0 Byte1 Byte2 Byte3 LSB---------------------MSB R4: Byte0 Byte1 Byte2 Byte3 Bits: 23-bit mantissa, 8-bit exponent, sign-bit The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: 52-bit mantissa, 11-bit exponent, sign-bit Note: To convert between these two formats the order of the bytes is reversed since by definition the Big endian starts at the LSB and goes to the MSB where the little goes form the MSB to the LSB of the word. *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_little_endian_32_swap_64( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; if ( delta_to_bytes == delta_from_bytes ) { memcpy( to_data, from_data, (size_t)delta_from_bytes ) ; } /* end if */ else if ( delta_from_bytes < delta_to_bytes ) { switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'I', '8' ): if( (from_data[3] & 0x80) == 0x80 ) { /* Negative number */ to_data[7] = 0xff ; to_data[6] = 0xff ; to_data[5] = 0xff ; to_data[4] = 0xff ; } /* end if */ else { to_data[7] = 0x00 ; to_data[6] = 0x00 ; to_data[5] = 0x00 ; to_data[4] = 0x00 ; } /* end else */ to_data[3] = from_data[3] ; to_data[2] = from_data[2] ; to_data[1] = from_data[1] ; to_data[0] = from_data[0] ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end else if */ else { switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'I', '8' ): to_data[3] = from_data[3] ; to_data[2] = from_data[2] ; to_data[1] = from_data[1] ; to_data[0] = from_data[0] ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end else */ } /* end of ADFI_little_endian_32_swap_64 */ /* end of file ADFI_little_endian_32_swap_64.c */ /* file ADFI_little_endian_to_cray.c */ /*********************************************************************** ADFI little endian to cray: input: const char from_format Format to convert from. 'B','L','C','N' input: const char from_os_size Format to convert from. 'B','L' input: const char to_format Format to convert to. input: const char to_os_size Format to convert to. 'B','L' input: const char data_type[2] The type of data to convert. MT I4 I8 U4 U8 R4 R8 X4 X8 C1 B1 input: const unsigned long delta_from_bytes Number of from_bytes used. input: const unsigned long delta_to_bytes Number of to_bytes used. input: const char *from_data The data to convert from. output: char *to_data The resulting data. output: int *error_return Error return. Recognized data types: Machine representations Type Notation IEEE_BIG IEEE_LITTLE Cray 32 64 32 64 No data MT Integer 32 I4 I4 I4 I4 I4 I8 Integer 64 I8 -- I8 -- I8 I8 Unsigned 32 U4 I4 I4 I4 I4 I8 Unsigned 64 U8 -- I8 -- I8 I8 Real 32 R4 R4 R4 R4 R4 R8 Real 64 R8 R8 R8 R8 R8 R8 Complex 64 X4 R4R4 R4R4 R4R4 R4R4 R8R8 Complex 128 X8 R8R8 R8R8 R8R8 R8R8 R8R8 Character (unsigned byte) C1 C1 C1 C1 C1 C1 Byte (unsigned byte) B1 C1 C1 C1 C1 C1 Machine Numeric Formats: ***IEEE_BIG (SGI-Iris Assembly Language Programmer's Guide, pages 1-2, 6-3) I4: Byte0 Byte1 Byte2 Byte3 MSB---------------------LSB R4: Byte0 Byte1 Byte2 Byte3 Bits: sign-bit, 8-bit exponent, 23-bit mantissa The sign of the exponent is: 1=positive, 0=negative (NOT 2's complement) The interpreation of the floating-point number is: >>> 2.mantissia(fraction) X 2^exponent. <<< R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, 11-bit exponent, 52-bit mantissa ***Cray (Cray CFT77 Reference Manual, pages G-1 G-2) I8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 MSB-----------------------------------------------------LSB R8: Byte0 Byte1 Byte2 Byte 3 Byte 4 Byte5 Byte6 Byte7 Bits: sign-bit, exponent-sign, 14-bit exponent, 48-bit mantissa Note: Exponent sign: 1 in this bits indicates a positive exponent sign, thus bit 62 is the inverse of bit 61 (the sign in the exponent). The exception to this is a zero, in which all 64 bits are zero! The interpreation of the floating-point number is: >>> .mantissia(fraction) X 2^exponent. <<< The mantissia is left justified (the leftmost bit is a 1). This MUST be done! *** Possible errors: NO_ERROR NULL_STRING_POINTER NULL_POINTER ***********************************************************************/ void ADFI_little_endian_to_cray( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ) { int i, exp ; if( (from_data == NULL) || (to_data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (delta_from_bytes == 0) || (delta_to_bytes == 0) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (from_format == 'N') || (to_format == 'N') ) { *error_return = CANNOT_CONVERT_NATIVE_FORMAT ; return ; } /* end if */ *error_return = NO_ERROR ; switch( EVAL_2_BYTES( data_type[0], data_type[1] ) ) { case EVAL_2_BYTES( 'M', 'T' ): *error_return = NO_DATA ; return ; case EVAL_2_BYTES( 'C', '1' ): case EVAL_2_BYTES( 'B', '1' ): to_data[0] = from_data[0] ; break ; case EVAL_2_BYTES( 'I', '4' ): if( (from_data[3] & 0x80) == 0x80 ) { /* Negative number */ to_data[0] = 0xff ; to_data[1] = 0xff ; to_data[2] = 0xff ; to_data[3] = 0xff ; } /* end if */ else { to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; } /* end else */ to_data[4] = from_data[3] ; to_data[5] = from_data[2] ; to_data[6] = from_data[1] ; to_data[7] = from_data[0] ; break ; case EVAL_2_BYTES( 'U', '4' ): to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; to_data[4] = from_data[3] ; to_data[5] = from_data[2] ; to_data[6] = from_data[1] ; to_data[7] = from_data[0] ; break ; case EVAL_2_BYTES( 'I', '8' ): if( (from_data[3] & 0x80) == 0x80 ) { /* Negative number */ to_data[0] = 0xff ; to_data[1] = 0xff ; to_data[2] = 0xff ; to_data[3] = 0xff ; } /* end if */ else { to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; } /* end else */ for( i=0; i<(int)delta_from_bytes; i++ ) to_data[8-delta_from_bytes+i] = from_data[delta_from_bytes-1-i] ; break ; case EVAL_2_BYTES( 'U', '8' ): to_data[0] = 0x00 ; to_data[1] = 0x00 ; to_data[2] = 0x00 ; to_data[3] = 0x00 ; for( i=0; i<(int)delta_from_bytes; i++ ) to_data[8-delta_from_bytes+i] = from_data[delta_from_bytes-1-i] ; break ; case EVAL_2_BYTES( 'R', '4' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[3] == 0x00) && (from_data[2] == 0x00) && (from_data[1] == 0x00) && (from_data[0] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[3] & 0x80 ; /** Convert the exponent **/ /** 8 bits to 14 bits. Sign extent from 8 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = (from_data[3] & 0x3f) << 1 ; if( (from_data[2] & 0x80) == 0x80 ) exp += 1 ; if( (from_data[3] & 0x40) == 0x00 ) /* set sign */ exp -= 128 ; exp += 2 ; to_data[1] = exp & 0xff ; if( exp < 0 ) to_data[0] |= 0x3f ; /* exponent sign 0, sign extend exponent */ else to_data[0] |= 0x40 ; /* exponent sign 1 */ /** Convert the mantissia **/ /** 23 bits to 48 bits. Left shift 25 bits, zero fill **/ to_data[2] = from_data[2] | 0x80 ; to_data[3] = from_data[1] ; to_data[4] = from_data[0] ; break ; case EVAL_2_BYTES( 'R', '8' ): for( i=0; i<8; i++ ) to_data[i] = 0x00 ; /** Check for zero: a special case on the Cray (exponent sign) **/ if( (from_data[7] == 0x00) && (from_data[6] == 0x00) && (from_data[5] == 0x00) && (from_data[4] == 0x00) ) break ; /** Convert the sign **/ to_data[0] = from_data[7] & 0x80 ; /** Convert the exponent **/ /** 11 bits to 14 bits. Sign extent from 11 to 14 **/ /** Cray exponent is 2 greater than the Iris **/ exp = ((from_data[7] & 0x3f) << 4) + ((from_data[6]>>4)&0x0f) ; if( (from_data[7] & 0x40) == 0x00 ) /* set sign */ exp -= 1024 ; exp += 2 ; to_data[1] = (unsigned int)(exp & 0xff) ; to_data[0] |= ((exp>>8) & 0x03) ; if( exp < 0 ) to_data[0] |= 0x3c ; /* exponent sign 0, sign extend exponent */ else to_data[0] |= 0x40 ; /* exponent sign 1 */ /** Convert the mantissia **/ /** 52 bits to 48 bits. Use 48, drop last 4 bits **/ to_data[2] = 0x80 | ((from_data[6]<<3)&0x78) | ((from_data[5]>>5)&0x07) ; for( i=3; i<8; i++ ) to_data[i] = ((from_data[7-i+1]<<3)&0xF8) | ((from_data[7-i]>>5)&0x07) ; #ifdef PRINT_STUFF printf("from:" ) ; for( i=0; i<8; i++ ) printf("%02x ", from_data[i] ) ; printf("to:" ) ; for( i=0; i<8; i++ ) printf("%02x ", to_data[i] ) ; printf("\n" ) ; #endif break ; case EVAL_2_BYTES( 'X', '4' ): ADFI_little_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_little_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R4", delta_from_bytes, delta_to_bytes, &from_data[4], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; case EVAL_2_BYTES( 'X', '8' ): ADFI_little_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_little_endian_to_cray( from_format, from_os_size, to_format, to_os_size, "R8", delta_from_bytes, delta_to_bytes, &from_data[8], &to_data[8], error_return ) ; if( *error_return != NO_ERROR ) return ; break ; default: *error_return = INVALID_DATA_TYPE ; return ; } /* end switch */ } /* end of ADFI_little_endian_to_cray */ /* end of file ADFI_little_endian_to_cray.c */ /* file ADFI_open_file.c */ /*********************************************************************** ADFI open file: Track the files used by index. Also track which files are within a given system so a close for the system can close all related files. input: const char *file The filename to open. input: const char *status The status in which to open the file. Allowable values are: READ_ONLY - File must exist. Writing NOT allowed. OLD - File must exist. Reading and writing allowed. NEW - File must not exist. SCRATCH - New file. Filename is ignored. UNKNOWN - OLD if file exists, else NEW is used. input: const int top_file_index -1 if this is the top file. output: unsigned int *file_index Returned index of the file. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER TOO_MANY_ADF_FILES_OPENED ADF_FILE_STATUS_NOT_RECOGNIZED FILE_OPEN_ERROR ***********************************************************************/ void ADFI_open_file( const char *file, const char *status, unsigned int *file_index, int *error_return ) { int index; int f_ret, f_mode; char header_data[102]; if( (status == NULL) || ((file == NULL) && (ADFI_stridx_c( status, "SCRATCH" ) != 0) ) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( file_index == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; for( index=0; index= maximum_files ) { ADF_FILE *files; /* I don't use realloc, because I don't want to lose any currently open file information if it fails */ files = (ADF_FILE *) calloc (maximum_files + ADF_FILE_INC, sizeof(ADF_FILE)); if (files == NULL) { *error_return = MEMORY_ALLOCATION_FAILED ; return ; } if (maximum_files) { memcpy (files, ADF_file, maximum_files * sizeof(ADF_FILE)); free (ADF_file); } else { ADFI_stack_control(0,0,0,INIT_STK,0,0,NULL); } ADF_file = files; index = maximum_files; maximum_files += ADF_FILE_INC; } /* end if */ if (index > MAXIMUM_FILES) { *error_return = TOO_MANY_ADF_FILES_OPENED; return; } ADF_file[index].in_use = 1 ; ADF_file[index].nlinks = 0; ADF_file[index].links = NULL; ADF_file[index].file_name = NULL; ADF_file[index].version_update[0] = '\0' ; ADF_file[index].format = UNDEFINED_FORMAT ; ADF_file[index].os_size = UNDEFINED_FORMAT ; ADF_file[index].link_separator = '>' ; ADF_file[index].old_version = 0 ; /*** READ_ONLY - File must exist. Writing NOT allowed. OLD - File must exist. Reading and writing allowed. NEW - File must not exist. SCRATCH - New file. Filename is ignored. UNKNOWN - OLD if file exists, else NEW is used. ***/ ADF_file[index].file = -1; ADF_sys_err = 0; #ifdef _WIN32 f_mode = O_BINARY ; #else f_mode = 0; #endif if( ADFI_stridx_c( status, "READ_ONLY" ) == 0 ) f_ret = file_open( file, f_mode | O_RDONLY, 0666); else if( ADFI_stridx_c( status, "OLD" ) == 0 ) f_ret = file_open( file, f_mode | O_RDWR, 0666); else if( ADFI_stridx_c( status, "NEW" ) == 0 ) f_ret = file_open( file, f_mode | O_RDWR | O_CREAT, 0666); else if( ADFI_stridx_c( status, "SCRATCH" ) == 0 ) { FILE *ftmp = tmpfile(); f_ret = ftmp == NULL ? -1 : FILENO(ftmp); } else if( ADFI_stridx_c( status, "UNKNOWN" ) == 0 ) f_ret = file_open( file, f_mode | O_RDWR | O_CREAT, 0666); else { *error_return = ADF_FILE_STATUS_NOT_RECOGNIZED ; goto Error_Exit ; } /* end else */ if( f_ret < 0 ) { ADF_sys_err = errno; if (errno == EMFILE) *error_return = TOO_MANY_ADF_FILES_OPENED; else *error_return = FILE_OPEN_ERROR ; goto Error_Exit ; } /* end if */ ADF_file[index].file = f_ret ; *file_index = index ; strcpy( ADF_file[index].open_mode, status); if( ADFI_stridx_c( status, "SCRATCH" ) ) { ADF_file[index].file_name = (char *) malloc (strlen(file) + 1); if (ADF_file[index].file_name == NULL) { *error_return = MEMORY_ALLOCATION_FAILED; goto Error_Exit; } strcpy( ADF_file[index].file_name, file ) ; } /* end else */ /* try to read first part of header to determine version and format */ if (102 == READ(f_ret, header_data, 102)) { if (header_data[25] != 'B') ADF_file[index].old_version = 1; ADF_file[index].format = header_data[100]; ADF_file[index].os_size = header_data[101]; } return ; Error_Exit: /** Clear this file's entry **/ if( ADF_file[index].file >= 0 ) { if( CLOSE( ADF_file[index].file ) < 0 ) { ADF_sys_err = errno; *error_return = FILE_CLOSE_ERROR ; } } /* end if */ ADF_file[index].file = -1 ; ADF_file[index].in_use = 0 ; if (ADF_file[index].file_name != NULL) { free (ADF_file[index].file_name); ADF_file[index].file_name = NULL; } } /* end of ADFI_open_file */ /* end of file ADFI_open_file.c */ /* file ADFI_read_chunk_length.c */ /*********************************************************************** ADFI read chunk length: Read the header of the chunk. If it is a variable sized chunk, then the first 2 things in is are: Tag, and pointer to end_of_chunk-tag If NOT variable, then determine what type of chunk it is and return a pointer to the end_of_chunk-tag: If the incomming pointers are 0 0, then we are looking at the file header. input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. output: char tag[TAG_SIZE] The tag from the chunk. output: struct DISK_POINTER *end_of_chunk_tag End of chunk. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_read_chunk_length( const unsigned int file_index, const struct DISK_POINTER *block_offset, char tag[TAG_SIZE+1], struct DISK_POINTER *end_of_chunk_tag, int *error_return ) { char info[ TAG_SIZE + DISK_POINTER_SIZE ] ; struct DISK_POINTER current_block_offset ; cgulong_t count ; if( (block_offset == NULL) || (end_of_chunk_tag == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( tag == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; end_of_chunk_tag->block = 0 ; end_of_chunk_tag->offset = 0 ; /** File Header **/ if( (block_offset->block == 0) && (block_offset->offset == 0) ) { /** point to end-tag **/ end_of_chunk_tag->offset = FILE_HEADER_SIZE - TAG_SIZE ; tag[0] = file_header_tags[0][0] ; tag[1] = file_header_tags[0][1] ; tag[2] = file_header_tags[0][2] ; tag[3] = file_header_tags[0][3] ; } /* end if */ /** Free-Chunk Table **/ else if( (block_offset->block == 0) && (block_offset->offset == FREE_CHUNKS_OFFSET) ) { /** point to end-tag **/ end_of_chunk_tag->offset = (FREE_CHUNKS_OFFSET + FREE_CHUNK_TABLE_SIZE) - TAG_SIZE ; tag[0] = free_chunk_table_start_tag[0] ; tag[1] = free_chunk_table_start_tag[1] ; tag[2] = free_chunk_table_start_tag[2] ; tag[3] = free_chunk_table_start_tag[3] ; } /* end if */ else { /** Check for 'z's in the file. This is free-data, too small to include tags and pointers **/ count = 0 ; ADFI_read_file( file_index, block_offset->block, block_offset->offset, 1, info, error_return ) ; if( *error_return != NO_ERROR ) return ; if( info[0] == 'z' ) { current_block_offset.block = block_offset->block ; current_block_offset.offset = block_offset->offset ; while( info[0] == 'z' ) { count++ ; current_block_offset.offset++ ; ADFI_adjust_disk_pointer( ¤t_block_offset, error_return ) ; if( *error_return != NO_ERROR ) return ; info[0] = '\0' ; ADFI_read_file( file_index, current_block_offset.block, current_block_offset.offset, 1, info, error_return ) ; if( (*error_return == FSEEK_ERROR) || (*error_return == FREAD_ERROR)){ break ; } /* end if */ if( *error_return != NO_ERROR ) return ; } /* end while */ end_of_chunk_tag->block = block_offset->block ; end_of_chunk_tag->offset = block_offset->offset + count - TAG_SIZE ; ADFI_adjust_disk_pointer( end_of_chunk_tag, error_return ) ; tag[0] = tag[1] = tag[2] = tag[3] = 'z' ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { /** Read TAG and disk_pointer **/ ADFI_read_file( file_index, block_offset->block, block_offset->offset, TAG_SIZE + DISK_POINTER_SIZE, info, error_return ) ; if( *error_return != NO_ERROR ) return ; /* Copy the tag **/ tag[0] = info[0] ; tag[1] = info[1] ; tag[2] = info[2] ; tag[3] = info[3] ; tag[4] = '\0' ; /** Check for known tags **/ if( ADFI_stridx_c( tag, node_start_tag ) == 0 ) { /** Node **/ end_of_chunk_tag->block = block_offset->block ; end_of_chunk_tag->offset = block_offset->offset + NODE_HEADER_SIZE - TAG_SIZE ; ADFI_adjust_disk_pointer( end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { /** Convert pointers into numeric form **/ #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &info[TAG_SIZE], &info[DISK_POINTER_SIZE], end_of_chunk_tag, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &info[TAG_SIZE], &info[DISK_POINTER_SIZE], end_of_chunk_tag, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; } /* end else */ } /* end else */ } /* end else */ } /* end of ADFI_read_chunk_length */ /* end of file ADFI_read_chunk_length.c */ /* file ADFI_read_data_chunk.c */ /*********************************************************************** ADFI read data chunk: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const char *data_type The defined datatype. input: const int data_size Size of data entity in bytes. input: const long chunk_bytes Number of bytes in data chunk. input: const long start_offset Starting offset into the data chunk input: const long total_bytes Number of bytes to read in data chunk. output: char *data Pointer to the resulting data. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_DISK_TAG_ERROR REQUESTED_DATA_TOO_LONG ***********************************************************************/ void ADFI_read_data_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t chunk_bytes, const cglong_t start_offset, const cglong_t total_bytes, char *data, int *error_return ) { int format_compare ; char tag[TAG_SIZE + 1] ; struct DISK_POINTER data_start, end_of_chunk_tag ; cglong_t chunk_total_bytes ; if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (tokenized_data_type == NULL) || (data == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ if( total_bytes+start_offset > chunk_bytes ) { *error_return = REQUESTED_DATA_TOO_LONG ; return ; } /* end if */ *error_return = NO_ERROR ; /** Get tag and chunk length **/ ADFI_read_chunk_length( file_index, block_offset, tag, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; /** Check start-of-chunk tag **/ if( ADFI_stridx_c( tag, data_chunk_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ /** Check end-of-chunk tag **/ ADFI_read_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; if( ADFI_stridx_c( tag, data_chunk_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ /** Point to the start of the data **/ data_start.block = block_offset->block ; data_start.offset = block_offset->offset + start_offset + DISK_POINTER_SIZE + TAG_SIZE ; ADFI_adjust_disk_pointer( &data_start, error_return ) ; if( *error_return != NO_ERROR ) return ; /** calculate the total number of data bytes **/ chunk_total_bytes = end_of_chunk_tag.offset - data_start.offset + start_offset + (end_of_chunk_tag.block - data_start.block) * DISK_BLOCK_SIZE ; if( chunk_bytes > chunk_total_bytes ) { *error_return = REQUESTED_DATA_TOO_LONG ; return ; } /* end if */ else { if( chunk_bytes < chunk_total_bytes ) *error_return = REQUESTED_DATA_TOO_LONG ; /** check for need of data translation **/ ADFI_file_and_machine_compare( file_index, tokenized_data_type, &format_compare, error_return ); if( *error_return != NO_ERROR ) return ; if( format_compare == 1 ) { /** Read the data off of disk **/ assert(data_start.offset <= 0x1fff); ADFI_read_file( file_index, data_start.block, data_start.offset, total_bytes, data, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { ADFI_read_data_translated( file_index, data_start.block, data_start.offset, tokenized_data_type, data_size, total_bytes, data, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ } /* end else */ } /* end of ADFI_read_data_chunk */ /* end of file ADFI_read_data_chunk.c */ /* file ADFI_read_data_chunk_table.c */ /*********************************************************************** ADFI read data chunk table: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. output: struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[] Array of DC entries. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_read_data_chunk_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[], int *error_return ) { char tag[ TAG_SIZE + 1 ] ; struct DISK_POINTER end_of_chunk_tag, tmp_block_offset ; cgulong_t i, number_of_bytes_to_read ; if( (block_offset == NULL) || (data_chunk_table == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Get the tag and the length **/ ADFI_read_chunk_length( file_index, block_offset, tag, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; /** Compare the start tag **/ if( ADFI_stridx_c( tag, data_chunk_table_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ number_of_bytes_to_read = (end_of_chunk_tag.block - block_offset->block) * DISK_BLOCK_SIZE + (end_of_chunk_tag.offset - block_offset->offset) - (TAG_SIZE + DISK_POINTER_SIZE) ; /** Read the data from disk **/ tmp_block_offset.block = block_offset->block ; tmp_block_offset.offset = block_offset->offset + TAG_SIZE ; for( i=0; i number_of_data_elements ) { chunk_size -= (unsigned int)( number_of_elements_read - number_of_data_elements ) ; delta_from_bytes = chunk_size * data_size ; delta_to_bytes = chunk_size * machine_size ; } ADFI_read_file( file_index, disk_pointer.block, disk_pointer.offset, delta_from_bytes, (char *)from_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_convert_number_format( ADF_file[file_index].format, /* from format */ ADF_file[file_index].os_size, /* from os size */ ADF_this_machine_format, /* to format */ ADF_this_machine_os_size, /* to os size */ FROM_FILE_FORMAT, tokenized_data_type, chunk_size, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; to_data += delta_to_bytes ; disk_pointer.offset += delta_from_bytes ; if ( disk_pointer.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &disk_pointer, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ } /* end while */ } /* end of ADFI_read_data_translated */ /* end of file ADFI_read_data_translated.c */ /* file ADFI_read_disk_block.c */ /*********************************************************************** ADFI read disk block: Possible errors: NO_ERROR ***********************************************************************/ void ADFI_read_disk_block() { fprintf(stderr,"Subroutine ADFI_read_disk_block is not yet implemented...\n" ) ; } /* end of ADFI_read_disk_block */ /* end of file ADFI_read_disk_block.c */ /* file ADFI_read_disk_pointer_from_disk.c */ /*********************************************************************** ADFI read disk pointer from disk: Given a pointer to a disk pointer, read it from disk and convert it into numeric form. input: const unsigned int file_index File to read from. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. output: struct DISK_POINTER *block_and_offset Resulting disk pointer. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_read_disk_pointer_from_disk( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, struct DISK_POINTER *block_and_offset, int *error_return ) { char disk_block_offset[DISK_POINTER_SIZE] ; if( block_and_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( block_offset > DISK_BLOCK_SIZE ) { *error_return = BLOCK_OFFSET_OUT_OF_RANGE ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check the stack for block/offset **/ #if 0 if ( ADFI_stack_control(file_index, file_block, (unsigned int)block_offset, GET_STK, DISK_PTR_STK, DISK_POINTER_SIZE, disk_block_offset ) != NO_ERROR ) { #endif /** Get the block/offset from disk **/ ADFI_read_file( file_index, file_block, block_offset, DISK_POINTER_SIZE, disk_block_offset, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Set the block/offset onto the stack **/ #if 0 ADFI_stack_control(file_index, file_block, (unsigned int)block_offset, SET_STK, DISK_PTR_STK, DISK_POINTER_SIZE, disk_block_offset ); } /* end if */ #endif /** Convert into numeric form **/ #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_block_offset[0], &disk_block_offset[8], block_and_offset, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_block_offset[0], &disk_block_offset[8], block_and_offset, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; } /* end of ADFI_read_disk_pointer_from_disk */ /* end of file ADFI_read_disk_pointer_from_disk.c */ /***********************************************************************/ cglong_t ADFI_read ( const unsigned int file_index, const cglong_t data_length, char *data) { char *data_ptr = data; cglong_t bytes_left = data_length; cglong_t bytes_read = 0; int nbytes, to_read; ADF_sys_err = 0; while (bytes_left > 0) { to_read = bytes_left > CG_MAX_INT32 ? CG_MAX_INT32 : (int)bytes_left; nbytes = (int) READ (ADF_file[file_index].file, data_ptr, to_read); if (0 == nbytes) break; if (-1 == nbytes) { if (EINTR != errno) { ADF_sys_err = errno; return -1; } } else { bytes_left -= nbytes; bytes_read += nbytes; data_ptr += nbytes; } } return bytes_read; } /* file ADFI_read_file.c */ /*********************************************************************** ADFI read file: Read a number of bytes from an open ADF file from a given file, block, and offset. Buffering is done in an attempt to improve performance of repeatedly reading small pieces of contiguous data. Note: read buffering also affects the write function, i.e, all writes must reset the read buffer. input: const unsigned int file_index File to read from. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. input: const unsigned int data_length Length of the data to read. input: char *data Address of the data. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER ADF_FILE_NOT_OPENED FREAD_ERROR ***********************************************************************/ void ADFI_read_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const cglong_t data_length, char *data, int *error_return ) { cglong_t iret ; if( data == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** No need to buffer large pieces of data or to take special measures to cross block boundaries **/ if( data_length + block_offset > DISK_BLOCK_SIZE ) { /** Position the file **/ ADFI_fseek_file( file_index, file_block, block_offset, error_return ) ; if( *error_return != NO_ERROR ) { return ; } /* end if */ /** Read the data from disk **/ iret = ADFI_read ( file_index, data_length, data ) ; if( iret != data_length ) { *error_return = FREAD_ERROR ; return ; } /* end if */ return; } /* end if */ /** For smaller pieces of data, read a block at a time. This will improve performance if neighboring data is requested a small piece at a time (strided reads, file overhead). Some assumptions apply to the block size. With some experimenting, 1K blocks do not offer much improvement. 4K blocks (4096 bytes) do improve performance remarkably. This is due to the fact that the file structure is based of 4K blocks with offsets. **/ if( num_in_rd_block < DISK_BLOCK_SIZE || /*- buffer is not full -*/ (cglong_t) file_block != last_rd_block || /*- a different block -*/ (int) file_index != last_rd_file ) { /*- entirely different file -*/ /** buffer is not current, re-read **/ if ( (cglong_t) file_block == last_wr_block && (int) file_index == last_wr_file ) { /* Copy data from write buffer */ memcpy( rd_block_buffer, wr_block_buffer, DISK_BLOCK_SIZE ); iret = DISK_BLOCK_SIZE; } else { /** Position the file **/ ADFI_fseek_file( file_index, file_block, 0, error_return ) ; if( *error_return != NO_ERROR ) { return ; } /* end if */ /** Read the data from disk **/ iret = ADFI_read( file_index, DISK_BLOCK_SIZE, rd_block_buffer ) ; if( iret <= 0 ) { *error_return = FREAD_ERROR ; return ; } /* end if */ } /* end if */ /** Remember buffer information **/ last_rd_block = file_block ; last_rd_file = (int)file_index ; num_in_rd_block = (int)iret ; } /* end if */ /*read from buffer*/ memcpy( data, &rd_block_buffer[block_offset], (size_t)data_length ); } /* end of ADFI_read_file */ /* end of file ADFI_read_file.c */ /* file ADFI_read_file_header.c */ /*********************************************************************** ADFI read file header: input: const unsigned int file_index The file index. output: struct FILE_HEADER *file_header Pointer to a file-header struct. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_read_file_header( const unsigned int file_index, struct FILE_HEADER *file_header, int *error_return ) { char disk_header[ FILE_HEADER_SIZE ] ; if( file_header == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check the stack for header **/ if ( ADFI_stack_control(file_index, 0, 0, GET_STK, FILE_STK, FILE_HEADER_SIZE, disk_header ) != NO_ERROR ) { /** Read in the header into memory **/ ADFI_read_file( file_index, 0, 0, FILE_HEADER_SIZE, disk_header, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check memory tags for proper data **/ if( strncmp( &disk_header[32], file_header_tags[0], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( &disk_header[64], file_header_tags[1], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( &disk_header[96], file_header_tags[2], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( &disk_header[102], file_header_tags[3], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( &disk_header[130], file_header_tags[4], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( &disk_header[182], file_header_tags[5], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ /** Set the header onto the stack **/ ADFI_stack_control(file_index, 0, 0, SET_STK, FILE_STK, FILE_HEADER_SIZE, disk_header ); } /* end if */ /** OK the memory tags look good, let's convert disk-formatted header into memory **/ strncpy( (char *)file_header->what, &disk_header[ 0], 32 ) ; strncpy( (char *)file_header->tag0, &disk_header[ 32], TAG_SIZE ) ; strncpy( (char *)file_header->creation_date, &disk_header[ 36], DATE_TIME_SIZE); strncpy( (char *)file_header->tag1, &disk_header[ 64], TAG_SIZE ) ; strncpy( (char *)file_header->modification_date, &disk_header[ 68], DATE_TIME_SIZE ) ; strncpy( (char *)file_header->tag2, &disk_header[ 96], TAG_SIZE ) ; file_header->numeric_format = disk_header[100] ; file_header->os_size = disk_header[101] ; strncpy( (char *)file_header->tag3, &disk_header[102], TAG_SIZE ) ; #if 0 #ifdef NEW_DISK_POINTER if (ADF_file[file_index].format == UNDEFINED_FORMAT) ADF_file[file_index].format = file_header->numeric_format; if (ADF_file[file_index].os_size == UNDEFINED_FORMAT) ADF_file[file_index].os_size = file_header->os_size; #endif #else assert(ADF_file[file_index].format != UNDEFINED_FORMAT); assert(ADF_file[file_index].os_size != UNDEFINED_FORMAT); #endif ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[106], &file_header->sizeof_char, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[108], &file_header->sizeof_short, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[110], &file_header->sizeof_int, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[112], &file_header->sizeof_long, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[114], &file_header->sizeof_float, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[116], &file_header->sizeof_double, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[118], &file_header->sizeof_char_p, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[120], &file_header->sizeof_short_p, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[122], &file_header->sizeof_int_p, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[124], &file_header->sizeof_long_p, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[126], &file_header->sizeof_float_p, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, 255, 2, &disk_header[128], &file_header->sizeof_double_p, error_return ) ; if( *error_return != NO_ERROR ) return ; strncpy( file_header->tag4, &disk_header[130], TAG_SIZE ) ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_header[134], &disk_header[142], &file_header->root_node, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_header[134], &disk_header[142], &file_header->root_node, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_header[146], &disk_header[154], &file_header->end_of_file, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_header[146], &disk_header[154], &file_header->end_of_file, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_header[158], &disk_header[166], &file_header->free_chunks, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_header[158], &disk_header[166], &file_header->free_chunks, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_header[170], &disk_header[178], &file_header->extra, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_header[170], &disk_header[178], &file_header->extra, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( file_header->tag5, &disk_header[182], TAG_SIZE ) ; /** Check memory tags for proper data **/ if( strncmp( file_header->tag0, file_header_tags[0], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag1, file_header_tags[1], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag2, file_header_tags[2], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag3, file_header_tags[3], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag4, file_header_tags[4], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag5, file_header_tags[5], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ } /* end of ADFI_read_file_header */ /* end of file ADFI_read_file_header.c */ /* file ADFI_read_free_chunk.c */ /*********************************************************************** ADFI read free chunk: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. output: struct DISK_POINTER *end_of_chunk_tag End of free chunk tag. output: struct DISK_POINTER *next_chunk Next free chunk in list. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_DISK_TAG_ERROR ***********************************************************************/ void ADFI_read_free_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct FREE_CHUNK *free_chunk, int *error_return ) { char tag[TAG_SIZE + 1] ; struct DISK_POINTER chunk_block_offset ; if( (block_offset == NULL) || (free_chunk == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Get the tag and the length **/ ADFI_read_chunk_length( file_index, block_offset, tag, &(free_chunk->end_of_chunk_tag), error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; /** Compare the start tag **/ if( ADFI_stridx_c( tag, free_chunk_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ /** Set block offset to the start of the chunk **/ chunk_block_offset = *block_offset ; chunk_block_offset.offset += TAG_SIZE + DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( &chunk_block_offset, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Read the data from disk **/ ADFI_read_disk_pointer_from_disk( file_index, chunk_block_offset.block, chunk_block_offset.offset, &(free_chunk->next_chunk), error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_read_file( file_index, free_chunk->end_of_chunk_tag.block, free_chunk->end_of_chunk_tag.offset, TAG_SIZE, tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Compare the end tag **/ if( ADFI_stridx_c( tag, free_chunk_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ strncpy( free_chunk->start_tag, free_chunk_start_tag, 4 ) ; strncpy( free_chunk->end_tag, free_chunk_end_tag, 4 ) ; } /* end of ADFI_read_free_chunk */ /* end of file ADFI_read_free_chunk.c */ /* file ADFI_read_free_chunk_table.c */ /*********************************************************************** ADFI read free chunk table: input: const unsigned int file_index The file index. output: struct FREE_CHUNK_TABLE *free_chunk_table Pointer to table. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_DISK_TAG_ERROR ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_read_free_chunk_table( const unsigned int file_index, struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) { char disk_free_chunk_data[ FREE_CHUNK_TABLE_SIZE ] ; if( free_chunk_table == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check the stack for free chunk **/ if ( ADFI_stack_control(file_index, FREE_CHUNKS_BLOCK, FREE_CHUNKS_OFFSET, GET_STK, FREE_CHUNK_STK, FREE_CHUNK_TABLE_SIZE, disk_free_chunk_data ) != NO_ERROR ) { /** Read the free-chunk table off of disk **/ ADFI_read_file( file_index, FREE_CHUNKS_BLOCK, FREE_CHUNKS_OFFSET, FREE_CHUNK_TABLE_SIZE, disk_free_chunk_data, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk tags **/ if( ADFI_stridx_c( &disk_free_chunk_data[0], free_chunk_table_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end of */ if( ADFI_stridx_c( &disk_free_chunk_data[FREE_CHUNK_TABLE_SIZE - TAG_SIZE], free_chunk_table_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end of */ /** Set the free chunk onto the stack **/ ADFI_stack_control(file_index, FREE_CHUNKS_BLOCK, FREE_CHUNKS_OFFSET, SET_STK, FREE_CHUNK_STK, FREE_CHUNK_TABLE_SIZE, disk_free_chunk_data ); } /* end if */ /** Convert into memory **/ strncpy( (char *)free_chunk_table->start_tag, &disk_free_chunk_data[ 0], TAG_SIZE ) ; strncpy( (char *)free_chunk_table->end_tag, &disk_free_chunk_data[ FREE_CHUNK_TABLE_SIZE - TAG_SIZE ], TAG_SIZE ) ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[ TAG_SIZE], &disk_free_chunk_data[DISK_POINTER_SIZE], &free_chunk_table->small_first_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[ TAG_SIZE], &disk_free_chunk_data[DISK_POINTER_SIZE], &free_chunk_table->small_first_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[16], &disk_free_chunk_data[24], &free_chunk_table->small_last_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[16], &disk_free_chunk_data[24], &free_chunk_table->small_last_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[28], &disk_free_chunk_data[36], &free_chunk_table->medium_first_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[28], &disk_free_chunk_data[36], &free_chunk_table->medium_first_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[40], &disk_free_chunk_data[48], &free_chunk_table->medium_last_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[40], &disk_free_chunk_data[48], &free_chunk_table->medium_last_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[52], &disk_free_chunk_data[60], &free_chunk_table->large_first_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[52], &disk_free_chunk_data[60], &free_chunk_table->large_first_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_free_chunk_data[64], &disk_free_chunk_data[72], &free_chunk_table->large_last_block, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_free_chunk_data[64], &disk_free_chunk_data[72], &free_chunk_table->large_last_block, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; /** Check memory tags **/ if( ADFI_stridx_c( free_chunk_table->start_tag, free_chunk_table_start_tag ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end of */ if( ADFI_stridx_c( free_chunk_table->end_tag, free_chunk_table_end_tag ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end of */ } /* end of ADFI_read_free_chunk_table */ /* end of file ADFI_read_free_chunk_table.c */ /* file ADFI_read_node_header.c */ /*********************************************************************** ADFI read node header: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. output: struct NODE_HEADER *node_header Pointer to node header. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_DISK_TAG_ERROR ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_read_node_header( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct NODE_HEADER *node_header, int *error_return ) { char disk_node_data[ NODE_HEADER_SIZE ] ; int i ; if( (block_offset == NULL) || (node_header == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check the stack for header **/ if ( ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, GET_STK, NODE_STK, NODE_HEADER_SIZE, disk_node_data ) != NO_ERROR ) { /** Get the node header from disk **/ ADFI_read_file( file_index, block_offset->block, block_offset->offset, NODE_HEADER_SIZE, disk_node_data, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Check disk tags **/ if( ADFI_stridx_c( &disk_node_data[0], node_start_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end of */ if( ADFI_stridx_c( &disk_node_data[ NODE_HEADER_SIZE - TAG_SIZE ], node_end_tag ) != 0 ) { *error_return = ADF_DISK_TAG_ERROR ; return ; } /* end if */ /** Set the header onto the stack **/ ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, SET_STK, NODE_STK, NODE_HEADER_SIZE, disk_node_data ); } /* end if */ /** Convert into memory **/ strncpy( (char *)node_header->node_start_tag, &disk_node_data[ 0], TAG_SIZE ) ; strncpy( (char *)node_header->node_end_tag, &disk_node_data[ NODE_HEADER_SIZE - TAG_SIZE], TAG_SIZE ) ; strncpy( (char *)node_header->name, &disk_node_data[ TAG_SIZE], ADF_NAME_LENGTH ) ; strncpy( (char *)node_header->label, &disk_node_data[ 36], ADF_LABEL_LENGTH ) ; ADFI_ASCII_Hex_2_unsigned_int( 0, MAXIMUM_32_BITS, 8, &disk_node_data[ 68], &node_header->num_sub_nodes, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_ASCII_Hex_2_unsigned_int( 0, MAXIMUM_32_BITS, 8, &disk_node_data[ 76], &node_header->entries_for_sub_nodes, error_return ) ; if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_node_data[84], &disk_node_data[92], &node_header->sub_node_table, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_node_data[84], &disk_node_data[92], &node_header->sub_node_table, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( (char *)node_header->data_type, &disk_node_data[ 96], ADF_DATA_TYPE_LENGTH ) ; ADFI_ASCII_Hex_2_unsigned_int( 0, 12, 2, &disk_node_data[128], &node_header->number_of_dimensions, error_return ) ; if( *error_return != NO_ERROR ) return ; if (ADF_file[file_index].old_version) { unsigned int dim; for( i=0; idimension_values[i] = dim; } /* end for */ } else { ADFI_convert_integers(8, 12, ADF_file[file_index].format, ADF_this_machine_format, &disk_node_data[130], (char *)node_header->dimension_values, error_return); if( *error_return != NO_ERROR ) return ; } ADFI_ASCII_Hex_2_unsigned_int( 0, 65535, 4, &disk_node_data[226], &node_header->number_of_data_chunks, error_return ) ; if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &disk_node_data[230], &disk_node_data[238], &node_header->data_chunks, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &disk_node_data[230], &disk_node_data[238], &node_header->data_chunks, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; /** Check memory tags **/ if( ADFI_stridx_c( node_header->node_start_tag, node_start_tag ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end of */ if( ADFI_stridx_c( node_header->node_end_tag, node_end_tag ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end of */ } /* end of ADFI_read_node_header */ /* end of file ADFI_read_node_header.c */ /* file ADFI_read_sub_node_table.c */ /*********************************************************************** ADFI read sub node table: At this point, reading of the ENTIRE table is required. input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. output: struct SUB_NODE_TABLE_ENTRY sub_node_table[] Array of SN entries. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_read_sub_node_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct SUB_NODE_TABLE_ENTRY sub_node_table[], int *error_return ) { char tag[TAG_SIZE + 1] ; struct DISK_POINTER end_of_chunk_tag, current_child ; unsigned int number_of_children, i ; if( (block_offset == NULL) || (sub_node_table == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Get tag and length **/ ADFI_read_chunk_length( file_index, block_offset, tag, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; tag[TAG_SIZE] = '\0' ; /** calculate the number of chuldren in the sub-node table **/ number_of_children = (unsigned int)( (end_of_chunk_tag.block - block_offset->block) * DISK_BLOCK_SIZE + (end_of_chunk_tag.offset - block_offset->offset) ) / (DISK_POINTER_SIZE + ADF_NAME_LENGTH) ; current_child.block = block_offset->block ; current_child.offset = block_offset->offset + TAG_SIZE + DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( ¤t_child, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Read and convert the variable-length table into memory **/ for( i=0; i= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check the stack for subnode **/ if ( ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, GET_STK, SUBNODE_STK, ADF_NAME_LENGTH + DISK_POINTER_SIZE, sub_node_entry_disk_data ) != NO_ERROR ) { /** Read the entry from disk **/ ADFI_read_file( file_index, block_offset->block, block_offset->offset, ADF_NAME_LENGTH + DISK_POINTER_SIZE, sub_node_entry_disk_data, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Set the subnode onto the stack **/ ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, SET_STK, SUBNODE_STK, ADF_NAME_LENGTH + DISK_POINTER_SIZE, sub_node_entry_disk_data ); } /* end if */ /** Copy the name **/ strncpy( sub_node_table_entry->child_name, &sub_node_entry_disk_data[0], ADF_NAME_LENGTH ) ; /** Convert the disk-pointer **/ #ifdef NEW_DISK_POINTER ADFI_read_disk_pointer( file_index, &sub_node_entry_disk_data[ ADF_NAME_LENGTH ], &sub_node_entry_disk_data[ ADF_NAME_LENGTH + 8 ], &sub_node_table_entry->child_location, error_return ) ; #else ADFI_disk_pointer_from_ASCII_Hex( &sub_node_entry_disk_data[ ADF_NAME_LENGTH ], &sub_node_entry_disk_data[ ADF_NAME_LENGTH + 8 ], &sub_node_table_entry->child_location, error_return ) ; #endif if( *error_return != NO_ERROR ) return ; } /* end of ADFI_read_sub_node_table_entry */ /* end of file ADFI_read_sub_node_table_entry.c */ /* file ADFI_remember_file_format.c */ /********************************************************************** ADFI remember file format: Track the file format used: input: const int file_index Index for the file. input: const char numeric_format Format for the file. input: const char os_size operating system size for the file. output: int *error_return Error return. Possible errors: NO_ERROR FILE_INDEX_OUT_OF_RANGE **********************************************************************/ void ADFI_remember_file_format( const int file_index, const char numeric_format, const char os_size, int *error_return ) { if( (file_index < 0) || (file_index >= maximum_files) ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } /* end if */ *error_return = NO_ERROR ; ADF_file[file_index].format = numeric_format ; ADF_file[file_index].os_size = os_size ; } /* end of file ADFI_remember_file_format.c */ /* file ADFI_remember_version_update.c */ /*********************************************************************** ADFI remember version update: Stores the what-string (which contains the file version number) so that it can be written after the first successful update. After the file has been updated once, the remembered what-string is "forgotten". input: const int file_index File index to write to. input: const char *what_string What string to remember (contains version) output: int *error_return Error return. Possible errors: FILE_INDEX_OUT_OF_RANGE NULL_STRING_POINTER STRING_LENGTH_ZERO ***********************************************************************/ void ADFI_remember_version_update( const int file_index, const char *what_string, int *error_return ) { *error_return = NO_ERROR ; if( (file_index < 0) || (file_index >= maximum_files) ) { *error_return = FILE_INDEX_OUT_OF_RANGE ; return ; } /* end if */ if( what_string == NULL ) { *error_return = NULL_STRING_POINTER ; return; } /* end if */ if( what_string[0] == '\0' ) { *error_return = STRING_LENGTH_ZERO ; return; } /* end if */ if( strlen( what_string ) > WHAT_STRING_SIZE ) { *error_return = STRING_LENGTH_TOO_BIG ; return ; } /* end if */ strcpy( ADF_file[file_index].version_update, what_string ) ; } /* end of ADFI_remember_version_update */ /* end of file ADFI_remember_version_update.c */ /* file ADFI_set_blank_disk_pointer.c */ /********************************************************************** ADFI_set_blank_disk_pointer: Set the block and offset to the defined "blank", or unused values. output: struct DISK_POINTER *block_offset Block & offset in the file. Possible errors: None allowed **********************************************************************/ void ADFI_set_blank_disk_pointer( struct DISK_POINTER *block_offset ) { block_offset->block = BLANK_FILE_BLOCK ; block_offset->offset = BLANK_BLOCK_OFFSET ; } /* end of ADFI_set_blank_disk_pointer */ /* end of file ADFI_set_blank_disk_pointer.c */ /* file ADFI_stack_control.c */ /*********************************************************************** ADFI stack control: input: const unsigned int file_index The file index. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. input: const int stack_mode Control mode: INIT, GET or SET input; const int stack_type Type of stack entry to process: FILE, NODE, etc.. input: const unsigned int data_length Length of the data to buffer. input/output: char *stack_data The character string buffered, is input for mode SET and output for mode GET. Possible errors: NO_ERROR NULL_STRING_POINTER ADF_FILE_NOT_OPENED PRISTK_NOT_FOUND Note: errors are only important for GET mode since you must then go ahead and read the data fom the file. The stack is only meant to speed things up, not stop the process !!! ***********************************************************************/ int ADFI_stack_control( const unsigned int file_index, const cgulong_t file_block, const unsigned int block_offset, const int stack_mode, const int stack_type, const unsigned int data_length, char *stack_data ) { int i; int low_priority; int insert_index = 0; int found; if( stack_data == NULL && (stack_mode == GET_STK || stack_mode == SET_STK) ) { return NULL_STRING_POINTER ; } /* end if */ if( ((int)file_index >= maximum_files || ADF_file[file_index].in_use == 0) && stack_mode != INIT_STK ) { return ADF_FILE_NOT_OPENED ; } /* end if */ /* Process depending on the mode */ switch( stack_mode ) { case INIT_STK: case CLEAR_STK: case CLEAR_STK_TYPE: /* Clear all entries with current file_index and or type, if file_index is 0 then clear all the entries!! */ for (i=0; i 0 ) free(PRISTK[i].stack_data); PRISTK[i].file_index = -1; PRISTK[i].file_block = 0; PRISTK[i].block_offset = 0; PRISTK[i].stack_type = -1; PRISTK[i].priority_level = -1; } /* end for */ /* just in case link or linked-to node deleted */ last_link_ID = 0.0; break ; case GET_STK: /* Try and find the entry in the current stack by matching the file index, block and offset, if found copy data else if not return with an error. */ for (i=0; i= 0 ) { /* Existing entry so lower its priority, if it is the lowest then save its index for possible replacement. */ if ( PRISTK[i].priority_level > low_priority ) { low_priority = PRISTK[i].priority_level; insert_index = i; } /* end if */ PRISTK[i].priority_level++; } /* end else if */ else if ( found == 'f' ) { /* An empty entry set pointer for possible insertion */ low_priority = MAX_STACK * MAX_STACK; insert_index = i; found = 'e'; } /* end else if */ } /* end for */ /* If the item was already on the stack then we are done */ if ( found == 't' ) return NO_ERROR; /* Insert the data onto the stack at the index_insert location. */ i = insert_index; if ( PRISTK[i].priority_level > 0 ) free(PRISTK[i].stack_data); PRISTK[i].stack_data = ( char * ) malloc((size_t)data_length*sizeof(char)); if ( PRISTK[i].stack_data == NULL ) { /* Error allocating memory buffer so clear stack and punt */ PRISTK[i].file_index = -1; PRISTK[i].file_block = 0; PRISTK[i].block_offset = 0; PRISTK[i].stack_type = -1; PRISTK[i].priority_level = -1; return NO_ERROR; } /* end if */ memcpy( PRISTK[i].stack_data, stack_data, (size_t)data_length ); PRISTK[i].file_index = file_index; PRISTK[i].file_block = file_block; PRISTK[i].block_offset = (unsigned int)block_offset; PRISTK[i].stack_type = stack_type; PRISTK[i].priority_level = 1; break ; } /* end switch */ return NO_ERROR; } /* end of ADFI_stack_control */ /* end of file ADFI_stack_control.c */ /* file ADFI_stridx_c.c */ /********************************************************************** ADFI stridx c: To find the location of a substring within a string. This routine is case InSeNsItIvE!!! It is NOT assumed that the substring is already upper-case!!! input: const char *str The string to search in. input: const char *substr The substring to search for. output: int return-value The position in str where substr was found. -1 if substr was not found. Possible errors: none: Errors are not allowed. ***********************************************************************/ int ADFI_stridx_c( const char *str, const char *substr ) { int i, j, k ; if( str == NULL || substr == NULL || substr[0] == '\0' ) { return -1 ; /* not found - nothing to check */ } for( i=0; str[i] != '\0'; i++ ) { for( j=i, k=0; TO_UPPER( str[j] ) == TO_UPPER( substr[k] ); j++ ) { if( substr[++k] == '\0' ) return i ; /* the substring was found */ } /* end for */ } /* end for */ return -1 ; /* the substring was not found */ } /* end of ADFI_stridx_c */ /* end of file ADFI_stridx_c.c */ /* file ADFI_string_2_C_string.c */ /********************************************************************** ADFI string to C string: Create a C string of the maximum length (+1 for null) which is null terminated and has no trailing blanks. input: const char *string Input string. input: const int string_length Length of input string to use. output: char *c_string Returned C string. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER **********************************************************************/ void ADFI_string_2_C_string( const char *string, const int string_length, char *c_string, int *error_return ) { int i, iend ; if( (string == NULL) || (c_string == NULL) ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ *error_return = NO_ERROR ; /** Skip and trailing blanks **/ for( iend=string_length-1; iend>=0; iend-- ) { if( string[ iend ] != ' ' ) { break ; } /* end if */ } /* end for */ /** Copy the non-trailing blank portion of the string **/ for( i=0; i<=iend; i++ ) c_string[i] = string[i] ; /** NULL terminate the C string **/ c_string[i] = '\0' ; } /* end of ADFI_string_2_C_string */ /* end of file ADFI_string_2_C_string.c */ /* file ADFI_unsigned_int_2_ASCII_Hex.c */ /*********************************************************************** ADFI unsigned int to ASCII hex: Convert an unsigned int to an ASCII-Hex string. input: const unsigned int number The integer number to convert to ASCII. input: const unsigned int minimum The expected minimum number in the int. input: const unsigned int maximum The expected maximum number in the int. input: const unsigned int string_length The length of the returned string. output: char string[] The string. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER NUMBER_LESS_THAN_MINIMUM NUMBER_GREATER_THAN_MAXIMUM STRING_LENGTH_ZERO STRING_LENGTH_TOO_BIG ***********************************************************************/ void ADFI_unsigned_int_2_ASCII_Hex( const unsigned int number, const unsigned int minimum, const unsigned int maximum, const unsigned int string_length, char string[], int *error_return ) { unsigned int i, /** Index from 0 to string_length - 1 **/ ir, /** Index from string_length - 1 to 0 **/ j, /** Temoprary integer variable **/ num ; /** Working value of ther number **/ if( string == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( number < minimum ) { *error_return = NUMBER_LESS_THAN_MINIMUM ; return ; } /* end if */ if( number > maximum ) { *error_return = NUMBER_GREATER_THAN_MAXIMUM ; return ; } /* end if */ if( string_length == 0 ) { *error_return = STRING_LENGTH_ZERO ; return ; } /* end if */ if( string_length > 8 ) { *error_return = STRING_LENGTH_TOO_BIG ; return ; } /* end if */ *error_return = NO_ERROR ; /** Convert the number using power-of-2 table **/ num = number ; for( i=0, ir=string_length - 1; i= pows[ ir ] ) { j = num / pows[ ir ] ; num = num - j * pows[ ir ] ; } /* end if */ else j = 0 ; string[i] = ASCII_Hex[ j ] ; } /* end for */ } /* end of ADFI_unsignedlong_2_ASCII_Hex */ /* end of file ADFI_unsigned_int_2_ASCII_Hex.c */ /* file ADFI_write_data_chunk.c */ /*********************************************************************** ADFI write data chunk: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const struct TOKENIZED_DATA_TYPE *tokenized_data_type Array. input: const int data_size Size of data entity in bytes. input: const long chunk_bytes Number of bytes in data chunk. input: const long start_offset Starting offset into the data chunk input: const long total_bytes Number of bytes to write in data chunk. input: const char *data Pointer to the data. If 0, zero data. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER NULL_STRING_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_write_data_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t chunk_bytes, const cglong_t start_offset, const cglong_t total_bytes, const char *data, int *error_return ) { int format_compare ; struct DISK_POINTER current_location, end_of_chunk_tag ; if( block_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( tokenized_data_type == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ if( total_bytes+start_offset > chunk_bytes ) { *error_return = REQUESTED_DATA_TOO_LONG ; return ; } /* end if */ *error_return = NO_ERROR ; /** Write the tag **/ ADFI_write_file( file_index, block_offset->block, block_offset->offset, TAG_SIZE, data_chunk_start_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Calculate the end-of-chunk-tag pointer **/ end_of_chunk_tag.block = block_offset->block ; end_of_chunk_tag.offset = block_offset->offset + TAG_SIZE + DISK_POINTER_SIZE + chunk_bytes ; ADFI_adjust_disk_pointer( &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Adjust location and write end-of-chunk pointer **/ current_location.block = block_offset->block ; current_location.offset = block_offset->offset + TAG_SIZE ; ADFI_adjust_disk_pointer( ¤t_location, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, current_location.block, current_location.offset, &end_of_chunk_tag, error_return ) ; current_location.offset += start_offset + DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( ¤t_location, error_return ) ; if( *error_return != NO_ERROR ) return ; /** write the data **/ if( data == NULL ) { /** Zero out the file data **/ /** If the data-pointer is NULL, write zeros to the file **/ /** Initialize the block of zeros **/ if( block_of_00_initialized == FALSE ) { int i ; for( i=0; i DISK_BLOCK_SIZE ) { cglong_t t_bytes = total_bytes ; /** If the number of bytes to write is larger than the block of zeros we have, write out a series of zero blocks... **/ /** write out the remainder of this block **/ assert(current_location.offset <= 0x1fff); ADFI_write_file( file_index, current_location.block, current_location.offset, DISK_BLOCK_SIZE - current_location.offset + 1, block_of_00, error_return ) ; if( *error_return != NO_ERROR ) return ; current_location.block++ ; current_location.offset = 0 ; t_bytes -= (DISK_BLOCK_SIZE - current_location.offset + 1) ; /** Write blocks of zeros, then a partial block **/ while( t_bytes > 0 ) { assert(current_location.offset <= 0x1fff); ADFI_write_file( file_index, current_location.block, current_location.offset, MIN( DISK_BLOCK_SIZE, t_bytes), block_of_00, error_return ) ; if( *error_return != NO_ERROR ) return ; t_bytes -= (MIN( DISK_BLOCK_SIZE, t_bytes)) ; } /* end while */ } /* end if */ else { /** Write a partial block of zeros to disk **/ assert(current_location.offset <= 0x1fff); ADFI_write_file( file_index, current_location.block, current_location.offset, total_bytes, block_of_00, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ } /* end if */ else { /** check for need of data translation **/ ADFI_file_and_machine_compare( file_index, tokenized_data_type, &format_compare, error_return ); if( *error_return != NO_ERROR ) return ; if( format_compare == 1 ) { /** Write the data to disk **/ assert(current_location.offset <= 0x1fff); ADFI_write_file( file_index, current_location.block, current_location.offset, total_bytes, data, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ else { ADFI_write_data_translated( file_index, current_location.block, current_location.offset, tokenized_data_type, data_size, total_bytes, data, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end else */ } /* end else */ /** Write the ending tag to disk **/ ADFI_write_file( file_index, end_of_chunk_tag.block, end_of_chunk_tag.offset, TAG_SIZE, data_chunk_end_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end of ADFI_write_data_chunk */ /* end of file ADFI_write_data_chunk.c */ /* file ADFI_write_data_chunk_table.c */ /*********************************************************************** ADFI write data chunk table: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const int number_of_data_chunks Number of entries to write. output: struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[] Array of entries. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_write_data_chunk_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, const int number_of_data_chunks, struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[], int *error_return ) { struct DISK_POINTER disk_pointer, end_of_chunk_tag ; int i ; if( (block_offset == NULL) || (data_chunk_table == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Write Starting boundary tag **/ disk_pointer.block = block_offset->block ; disk_pointer.offset = block_offset->offset ; ADFI_write_file( file_index, disk_pointer.block, disk_pointer.offset, TAG_SIZE, data_chunk_table_start_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; disk_pointer.offset += TAG_SIZE ; ADFI_adjust_disk_pointer( &disk_pointer, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Calculate the end-of-chunk-tag location **/ end_of_chunk_tag.block = disk_pointer.block ; end_of_chunk_tag.offset = disk_pointer.offset + DISK_POINTER_SIZE + number_of_data_chunks * 2 * DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, disk_pointer.block, disk_pointer.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write data chunk table entries **/ disk_pointer.offset += DISK_POINTER_SIZE ; for( i=0; i number_of_data_elements ) { chunk_size -= (unsigned int)( number_of_elements_written - number_of_data_elements ) ; delta_to_bytes = chunk_size * data_size ; delta_from_bytes = chunk_size * machine_size ; } ADFI_convert_number_format( ADF_this_machine_format, /* from format */ ADF_this_machine_os_size, /* from os size */ ADF_file[file_index].format, /* to format */ ADF_file[file_index].os_size, /* to os size */ TO_FILE_FORMAT, tokenized_data_type, chunk_size, from_data, to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_file( file_index, disk_pointer.block, disk_pointer.offset, delta_to_bytes, (char *)to_data, error_return ) ; if( *error_return != NO_ERROR ) return ; from_data += delta_from_bytes ; disk_pointer.offset += delta_to_bytes ; if ( disk_pointer.offset > DISK_BLOCK_SIZE ) { ADFI_adjust_disk_pointer( &disk_pointer, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ } /* end while */ } /* end of ADFI_write_data_translated */ /* end of file ADFI_write_data_translated.c */ /* file ADFI_write_disk_block.c */ /*********************************************************************** ADFI write disk block: ***********************************************************************/ void ADFI_write_disk_block() { fprintf(stderr,"Subroutine ADFI_write_disk_block is not yet implemented...\n" ) ; } /* end of ADFI_write_disk_block */ /* end of file ADFI_write_disk_block.c */ /* file ADFI_write_disk_pointer_2_disk.c */ /*********************************************************************** ADFI write disk pointer 2 disk: Given a pointer to a disk pointer, convert it to ASCII Hex and write it to disk. input: const unsigned int file_index File to write to. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. input: const struct DISK_POINTER *block_and_offset Disk pointer. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_write_disk_pointer_2_disk( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const struct DISK_POINTER *block_and_offset, int *error_return ) { char disk_block_offset[DISK_POINTER_SIZE] ; if( block_and_offset == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Convert into ASCII_Hex form **/ #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, block_and_offset, &disk_block_offset[0], &disk_block_offset[8], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( block_and_offset, &disk_block_offset[0], &disk_block_offset[8], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; /** Put the block/offset to disk **/ ADFI_write_file( file_index, file_block, block_offset, DISK_POINTER_SIZE, disk_block_offset, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Set the block/offset onto the stack **/ #if 0 ADFI_stack_control(file_index, file_block, (unsigned int)block_offset, SET_STK, DISK_PTR_STK, DISK_POINTER_SIZE, disk_block_offset ); #endif } /* end of ADFI_write_disk_pointer_2_disk */ /* end of file ADFI_write_disk_pointer_2_disk.c */ /***********************************************************************/ cglong_t ADFI_write ( const unsigned int file_index, const cglong_t data_length, const char *data) { char *data_ptr = (char *)data; cglong_t bytes_left = data_length; cglong_t bytes_out = 0; int nbytes, to_write; ADF_sys_err = 0; while (bytes_left > 0) { to_write = bytes_left > CG_MAX_INT32 ? CG_MAX_INT32 : (int)bytes_left; nbytes = (int) WRITE (ADF_file[file_index].file, data_ptr, to_write); if (-1 == nbytes) { if (EINTR != errno) { ADF_sys_err = errno; return -1; } } else { bytes_left -= nbytes; bytes_out += nbytes; data_ptr += nbytes; } } return bytes_out; } /* file ADFI_write_file.c */ /*********************************************************************** ADFI write file: Write a number of bytes to an ADF file, given the file, block, and block offset. input: const unsigned int file_index File to write to. input: const unsigned long file_block Block within the file. input: const unsigned long block_offset Offset within the block. input: const unsigned int data_length Length of the data to write. input: const char *data Address of the data. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER ADF_FILE_NOT_OPENED FWRITE_ERROR ***********************************************************************/ void ADFI_write_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const cglong_t data_length, const char *data, int *error_return ) { cglong_t iret; cglong_t end_block; if( data == NULL ) { *error_return = NULL_STRING_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** If the read buffer overlaps the buffer then reset it to make sure its currrent **/ end_block = file_block+(block_offset+data_length)/DISK_BLOCK_SIZE+1; if ( last_rd_file == (int) file_index && last_rd_block >= (cglong_t) file_block && last_rd_block <= end_block ) { last_rd_block = -1; last_rd_file = -1; num_in_rd_block = -1 ; } /** Check to see if we need to flush the write buffer. this happens if we are writing a large chunk or the write moves out of the current block. If the data length is zero then just flush the buffer and return. Note that the ADF_modification_date routine will flush the buffer after any write operations !! **/ if( ( (cgulong_t) data_length + block_offset > DISK_BLOCK_SIZE || last_wr_block != (cglong_t) file_block || last_wr_file != (int) file_index || data_length == 0 ) && flush_wr_block > 0 ) { /** Position the file **/ ADFI_fseek_file( last_wr_file, last_wr_block, 0, error_return ) ; if( *error_return != NO_ERROR ) { return ; } /* end if */ /** write the buffer **/ iret= ADFI_write( last_wr_file, DISK_BLOCK_SIZE, wr_block_buffer ); flush_wr_block = -2 ; /** Make sure we don't flush twice due to error **/ if( iret != DISK_BLOCK_SIZE ) { *error_return = FWRITE_ERROR ; return ; } /* end if */ /** If the write buffer overlaps the buffer then reset it to make sure its currrent, set flush buffer flag to false. **/ if ( last_wr_file == (int) file_index && last_wr_block >= (cglong_t) file_block && last_wr_block <= (cglong_t) end_block ) { last_wr_block = -2; last_wr_file = -2; } } /* end if */ if ( data_length == 0 ) return; /** Just a buffer flush **/ /** No need to buffer large pieces of data or to take special measures to cross block boundaries **/ if( data_length + block_offset > DISK_BLOCK_SIZE ) { /** Position the file **/ ADFI_fseek_file( file_index, file_block, block_offset, error_return ) ; if( *error_return != NO_ERROR ) { return ; } /* end if */ /** write the data **/ iret = ADFI_write( file_index, data_length, data ) ; if( iret != data_length ) { *error_return = FWRITE_ERROR ; return ; } /* end if */ return; } /* end if */ /** For smaller pieces of data, write a block at a time. This will improve performance if neighboring data is writen a small piece at a time (strided reads, file overhead). Some assumptions apply to the block size. With some experimenting, 1K blocks do not offer much improvement. 4K blocks (4096 bytes) do improve performance remarkably. This is due to the fact that the file structure is based of 4K blocks with offsets. Also the CRAY loves 4K block writes!! **/ if( (cglong_t) file_block != last_wr_block || /*- a different block -*/ (int) file_index != last_wr_file ) { /*- entirely different file -*/ /** buffer is not current, re-read **/ if ( (cglong_t) file_block == last_rd_block && (int) file_index == last_rd_file ) { /* Copy data from read buffer */ memcpy( wr_block_buffer, rd_block_buffer, DISK_BLOCK_SIZE ); iret = num_in_rd_block; } else { /** Position the file **/ ADFI_fseek_file( file_index, file_block, 0, error_return ) ; if( *error_return != NO_ERROR ) { return ; } /* end if */ /** Read the data from disk **/ iret = ADFI_read( file_index, DISK_BLOCK_SIZE, wr_block_buffer ) ; if( iret < DISK_BLOCK_SIZE ) { if ( iret < 0 ) iret = 0; memset( &wr_block_buffer[iret], (size_t) ' ', (size_t)(DISK_BLOCK_SIZE-iret) ); } /* end if */ } /* end if */ /** Remember buffer information **/ last_wr_block = file_block ; last_wr_file = (int)file_index ; } /* end if */ /** Write into the buffer and set flush buffer flag **/ memcpy( &wr_block_buffer[block_offset], data, (size_t)data_length ); flush_wr_block = 1 ; } /* end of ADFI_write_file */ /* end of file ADFI_write_file.c */ /* file ADFI_write_file_header.c */ /*********************************************************************** ADFI write file header: To take information in the FILE_HEADER structure and format it for disk, and write it out. input: const int file_index File index to write to. input: const FILE_HEADER *file_header The file header structure. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_MEMORY_TAG_ERROR ADF_DISK_TAG_ERROR ***********************************************************************/ void ADFI_write_file_header( const int file_index, const struct FILE_HEADER *file_header, int *error_return ) { char disk_header[ FILE_HEADER_SIZE ] ; if( file_header == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check memory tags for proper data **/ if( strncmp( file_header->tag0, file_header_tags[0], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag1, file_header_tags[1], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag2, file_header_tags[2], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag3, file_header_tags[3], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag4, file_header_tags[4], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( file_header->tag5, file_header_tags[5], TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ /** OK the memory tags look good, let's format the file header information into the disk format and write it out. **/ strncpy( &disk_header[ 0], (char *)file_header->what, WHAT_STRING_SIZE ) ; strncpy( &disk_header[ 32], (char *)file_header->tag0, TAG_SIZE ) ; strncpy( &disk_header[ 36], (char *)file_header->creation_date, DATE_TIME_SIZE); strncpy( &disk_header[ 64], (char *)file_header->tag1, TAG_SIZE ) ; strncpy( &disk_header[ 68], (char *)file_header->modification_date, DATE_TIME_SIZE ) ; strncpy( &disk_header[ 96], (char *)file_header->tag2, TAG_SIZE ) ; disk_header[100] = file_header->numeric_format ; disk_header[101] = file_header->os_size ; strncpy( &disk_header[102], (char *)file_header->tag3, TAG_SIZE ) ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_char, 0, 255, 2, &disk_header[106], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_short, 0, 255, 2, &disk_header[108], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_int, 0, 255, 2, &disk_header[110], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_long, 0, 255, 2, &disk_header[112], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_float, 0, 255, 2, &disk_header[114], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_double, 0, 255, 2, &disk_header[116], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_char_p, 0, 255, 2, &disk_header[118], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_short_p, 0, 255, 2, &disk_header[120], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_int_p, 0, 255, 2, &disk_header[122], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_long_p, 0, 255, 2, &disk_header[124], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_float_p, 0, 255, 2, &disk_header[126], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( file_header->sizeof_double_p, 0, 255, 2, &disk_header[128], error_return ) ; if( *error_return != NO_ERROR ) return ; strncpy( &disk_header[130], file_header->tag4, TAG_SIZE ) ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &file_header->root_node, &disk_header[134], &disk_header[142], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &file_header->root_node, &disk_header[134], &disk_header[142], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &file_header->end_of_file, &disk_header[146], &disk_header[154], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &file_header->end_of_file, &disk_header[146], &disk_header[154], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &file_header->free_chunks, &disk_header[158], &disk_header[166], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &file_header->free_chunks, &disk_header[158], &disk_header[166], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &file_header->extra, &disk_header[170], &disk_header[178], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &file_header->extra, &disk_header[170], &disk_header[178], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( &disk_header[182], file_header->tag5, TAG_SIZE ) ; /** Now write the disk header out... **/ ADFI_write_file( file_index, 0, 0, FILE_HEADER_SIZE, disk_header, error_return ) ; /** Set the header onto the stack **/ ADFI_stack_control(file_index, 0, 0, SET_STK, FILE_STK, FILE_HEADER_SIZE, disk_header ); } /* end of ADFI_write_file_header */ /* end of file ADFI_write_file_header.c */ /* file ADFI_write_free_chunk.c */ /*********************************************************************** ADFI write free chunk: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const struct FREE_CHUNK *free_chunk Pointer to free-chunk. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_write_free_chunk( const int file_index, const struct DISK_POINTER *block_offset, const struct FREE_CHUNK *free_chunk, int *error_return ) { unsigned int i ; struct DISK_POINTER current_location ; if( (block_offset == NULL) || (free_chunk == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Initialize the block of 'X's **/ if( block_of_XX_initialized == FALSE ) { for( i=0; istart_tag, free_chunk_start_tag, TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( free_chunk->end_tag, free_chunk_end_tag, TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ /** Write start TAG **/ ADFI_write_file( file_index, block_offset->block, block_offset->offset, TAG_SIZE, free_chunk->start_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write disk pointers **/ current_location.block = block_offset->block ; current_location.offset = block_offset->offset + TAG_SIZE ; ADFI_adjust_disk_pointer( ¤t_location, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, current_location.block, current_location.offset, &free_chunk->end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; current_location.offset += DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( ¤t_location, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, current_location.block, current_location.offset, &free_chunk->next_chunk, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write out a bunch of 'x's in the free chunk's empty space **/ current_location.offset += DISK_POINTER_SIZE ; ADFI_adjust_disk_pointer( ¤t_location, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Fill in partial end of a block **/ if( (current_location.block != free_chunk->end_of_chunk_tag.block) && (current_location.offset != 0 ) ) { assert(current_location.offset < DISK_BLOCK_SIZE); ADFI_write_file( file_index, current_location.block, current_location.offset, DISK_BLOCK_SIZE - current_location.offset, block_of_XX, error_return ) ; if( *error_return != NO_ERROR ) return ; current_location.block++ ; current_location.offset = 0 ; } /* end if */ /** Fill in intermediate whole blocks **/ while( current_location.block < free_chunk->end_of_chunk_tag.block ) { ADFI_write_file( file_index, current_location.block, 0, DISK_BLOCK_SIZE, block_of_XX, error_return ) ; if( *error_return != NO_ERROR ) return ; current_location.block++ ; } /* end if */ /** Fill in partial block to end-of-free-chunk **/ if( current_location.offset < free_chunk->end_of_chunk_tag.offset ) { ADFI_write_file( file_index, current_location.block, current_location.offset, free_chunk->end_of_chunk_tag.offset - current_location.offset, block_of_XX, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end if */ /** Now (finally) write out the free_chunk-end_tag **/ ADFI_write_file( file_index, current_location.block, free_chunk->end_of_chunk_tag.offset, TAG_SIZE, free_chunk->end_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; } /* end of ADFI_write_free_chunk */ /* end of file ADFI_write_free_chunk.c */ /* file ADFI_write_free_chunk_table.c */ /*********************************************************************** ADFI write free chunk table: To take information in the FREE_CHUNK_TABLE structure and format it for disk, and write it out. input: const int file_index File index to write to. input: const FREE_CHUNK_TABLE *free_chunk_table The free_chunk header struct. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_write_free_chunk_table( const int file_index, const struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) { char disk_free_chunk_data[ FREE_CHUNK_TABLE_SIZE ] ; if( free_chunk_table == NULL ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check memory tags for proper data **/ if( strncmp( free_chunk_table->start_tag, free_chunk_table_start_tag, TAG_SIZE ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( free_chunk_table->end_tag, free_chunk_table_end_tag, TAG_SIZE ) != 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ /** OK the memory tags look good, let's format the free_chunk header information into the disk format and write it out. **/ strncpy( &disk_free_chunk_data[ 0], (char *)free_chunk_table->start_tag, TAG_SIZE ) ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->small_first_block, &disk_free_chunk_data[TAG_SIZE], &disk_free_chunk_data[DISK_POINTER_SIZE], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->small_first_block, &disk_free_chunk_data[TAG_SIZE], &disk_free_chunk_data[DISK_POINTER_SIZE], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->small_last_block, &disk_free_chunk_data[16], &disk_free_chunk_data[24], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->small_last_block, &disk_free_chunk_data[16], &disk_free_chunk_data[24], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->medium_first_block, &disk_free_chunk_data[28], &disk_free_chunk_data[36], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->medium_first_block, &disk_free_chunk_data[28], &disk_free_chunk_data[36], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->medium_last_block, &disk_free_chunk_data[40], &disk_free_chunk_data[48], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->medium_last_block, &disk_free_chunk_data[40], &disk_free_chunk_data[48], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->large_first_block, &disk_free_chunk_data[52], &disk_free_chunk_data[60], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->large_first_block, &disk_free_chunk_data[52], &disk_free_chunk_data[60], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &free_chunk_table->large_last_block, &disk_free_chunk_data[64], &disk_free_chunk_data[72], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &free_chunk_table->large_last_block, &disk_free_chunk_data[64], &disk_free_chunk_data[72], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( &disk_free_chunk_data[ 76], (char *)free_chunk_table->end_tag, TAG_SIZE ) ; /** Now write the free_chunk header out to disk... **/ ADFI_write_file( file_index, FREE_CHUNKS_BLOCK, FREE_CHUNKS_OFFSET, FREE_CHUNK_TABLE_SIZE, disk_free_chunk_data, error_return ) ; /** Set the free chunk onto the stack **/ ADFI_stack_control(file_index, FREE_CHUNKS_BLOCK, FREE_CHUNKS_OFFSET, SET_STK, FREE_CHUNK_STK, FREE_CHUNK_TABLE_SIZE, disk_free_chunk_data ); } /* end of ADFI_write_free_chunk_table */ /* end of file ADFI_write_free_chunk_table.c */ /* file ADFI_write_modification_date.c */ /*********************************************************************** ADFI write modification date: Writes the current date/time into the modification date field of the file header. Also updates the file version (what string) in the header if the file version global variable has been set - after writing, file version global variable is unset so that it is only written once. input: const int file_index File index to write to. output: int *error_return Error return. Possible errors: NO_ERROR NULL_STRING_POINTER ADF_FILE_NOT_OPENED FWRITE_ERROR ***********************************************************************/ void ADFI_write_modification_date( const int file_index, int *error_return ) { int i_block_offset ; char mod_date[DATE_TIME_SIZE] ; *error_return = NO_ERROR ; ADFI_get_current_date( mod_date ) ; /** block offset depends on the location the of modification date in the FILE_HEADER structure **/ i_block_offset = WHAT_STRING_SIZE + TAG_SIZE + DATE_TIME_SIZE + TAG_SIZE ; ADFI_write_file( file_index, 0, i_block_offset, DATE_TIME_SIZE, mod_date, error_return ) ; if( *error_return != NO_ERROR ) { return; } /* end if */ /** Flush the write buffer to ensure the file is current!! **/ ADFI_flush_buffers( file_index, FLUSH, error_return ); if( *error_return != NO_ERROR ) { return; } /* end if */ if( ADF_file[file_index].version_update[0] != '\0' ) { i_block_offset = 0 ; /* what-string is first field in header */ ADFI_write_file( file_index, 0, i_block_offset, WHAT_STRING_SIZE, ADF_file[file_index].version_update, error_return ) ; /** reset the version to default so that it only gets updated once **/ ADF_file[file_index].version_update[0] = '\0' ; if( *error_return != NO_ERROR ) { return; } /* end if */ } /* end if */ } /* end of ADFI_write_modification_date */ /* end of file ADFI_write_modification_date.c */ /* file ADFI_write_node_header.c */ /*********************************************************************** ADFI write node header: To take information in the NODE_HEADER structure and format it for disk, and write it out. input: const int file_index File index to write to. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const NODE_HEADER *node_header The node header structure. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ADF_MEMORY_TAG_ERROR ***********************************************************************/ void ADFI_write_node_header( const int file_index, const struct DISK_POINTER *block_offset, const struct NODE_HEADER *node_header, int *error_return ) { int i ; char disk_node_data[ NODE_HEADER_SIZE ] ; if( (block_offset == NULL) || (node_header == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Check memory tags for proper data **/ if( strncmp( node_header->node_start_tag, node_start_tag, TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ if( strncmp( node_header->node_end_tag, node_end_tag, TAG_SIZE )!= 0 ) { *error_return = ADF_MEMORY_TAG_ERROR ; return ; } /* end if */ /** OK the memory tags look good, let's format the node header information into the disk format and write it out. **/ strncpy( &disk_node_data[ 0], (char *)node_header->node_start_tag, TAG_SIZE ) ; strncpy( &disk_node_data[ TAG_SIZE], (char *)node_header->name, ADF_NAME_LENGTH ); strncpy( &disk_node_data[ 36], (char *)node_header->label, ADF_LABEL_LENGTH ) ; ADFI_unsigned_int_2_ASCII_Hex( node_header->num_sub_nodes, 0, MAXIMUM_32_BITS, 8, &disk_node_data[ 68], error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_unsigned_int_2_ASCII_Hex( node_header->entries_for_sub_nodes, 0, MAXIMUM_32_BITS, 8, &disk_node_data[ 76], error_return ) ; if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer(file_index, &node_header->sub_node_table, &disk_node_data[84], &disk_node_data[92], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &node_header->sub_node_table, &disk_node_data[84], &disk_node_data[92], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( &disk_node_data[ 96], (char *)node_header->data_type, ADF_DATA_TYPE_LENGTH ) ; ADFI_unsigned_int_2_ASCII_Hex( node_header->number_of_dimensions, 0, 12, 2, &disk_node_data[128], error_return ) ; if( *error_return != NO_ERROR ) return ; if (ADF_file[file_index].old_version) { for( i=0; idimension_values[i] > MAXIMUM_32_BITS) { *error_return = NUMBER_GREATER_THAN_MAXIMUM ; } else { ADFI_unsigned_int_2_ASCII_Hex( (unsigned int)node_header->dimension_values[i], 0, MAXIMUM_32_BITS, 8, &disk_node_data[130+(i*8)], error_return ) ; } if( *error_return != NO_ERROR ) return ; } /* end for */ } else { ADFI_convert_integers(8, 12, ADF_this_machine_format, ADF_file[file_index].format, (char *)node_header->dimension_values, &disk_node_data[130], error_return); if( *error_return != NO_ERROR ) return ; } ADFI_unsigned_int_2_ASCII_Hex( node_header->number_of_data_chunks, 0, 65535, 4, &disk_node_data[226], error_return ) ; if( *error_return != NO_ERROR ) return ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer(file_index, &node_header->data_chunks, &disk_node_data[230], &disk_node_data[238], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &node_header->data_chunks, &disk_node_data[230], &disk_node_data[238], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; strncpy( &disk_node_data[242], (char *)node_header->node_end_tag, TAG_SIZE ) ; /** Now write the node-header out to disk... **/ ADFI_write_file( file_index, block_offset->block, block_offset->offset, NODE_HEADER_SIZE, disk_node_data, error_return ) ; /** Set the header onto the stack **/ ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, SET_STK, NODE_STK, NODE_HEADER_SIZE, disk_node_data ); } /* end of ADFI_write_node_header */ /* end of file ADFI_write_node_header.c */ /* file ADFI_write_sub_node_table.c */ /*********************************************************************** ADFI write sub node table: input: const unsigned int file_index The file index. input: const struct DISK_POINTER *block_offset Block & offset in the file. input: const int number_of_sub_nodes Number of sub-node entries. input: struct SUB_NODE_TABLE_ENTRY sub_node_table[] Array of sub-node entries. output: int *error_return Error return. Possible errors: NO_ERROR NULL_POINTER ADF_FILE_NOT_OPENED ***********************************************************************/ void ADFI_write_sub_node_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, const int number_of_sub_nodes, struct SUB_NODE_TABLE_ENTRY sub_node_table[], int *error_return ) { int i ; struct DISK_POINTER end_of_chunk_tag, current_child ; if( (block_offset == NULL) || (sub_node_table == NULL) ) { *error_return = NULL_POINTER ; return ; } /* end if */ if( (int)file_index >= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** calculate the end-of-chunk tag pointer **/ end_of_chunk_tag.block = block_offset->block ; end_of_chunk_tag.offset = block_offset->offset + TAG_SIZE + DISK_POINTER_SIZE + number_of_sub_nodes * (ADF_NAME_LENGTH + DISK_POINTER_SIZE) ; ADFI_adjust_disk_pointer( &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write start TAG **/ ADFI_write_file( file_index, block_offset->block, block_offset->offset, TAG_SIZE, sub_node_start_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Write disk pointer **/ current_child.block = block_offset->block ; current_child.offset = block_offset->offset + TAG_SIZE ; ADFI_adjust_disk_pointer( ¤t_child, error_return ) ; if( *error_return != NO_ERROR ) return ; ADFI_write_disk_pointer_2_disk( file_index, current_child.block, current_child.offset, &end_of_chunk_tag, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Format and write out the table entries **/ current_child.offset += DISK_POINTER_SIZE ; for( i=0; i= maximum_files || ADF_file[file_index].in_use == 0 ) { *error_return = ADF_FILE_NOT_OPENED ; return ; } /* end if */ *error_return = NO_ERROR ; /** Format the tag and disk pointer in memory **/ strncpy( &sub_node_entry_disk_data[0], sub_node_table_entry->child_name, ADF_NAME_LENGTH ) ; #ifdef NEW_DISK_POINTER ADFI_write_disk_pointer( file_index, &sub_node_table_entry->child_location, &sub_node_entry_disk_data[ ADF_NAME_LENGTH ], &sub_node_entry_disk_data[ ADF_NAME_LENGTH + 8 ], error_return ) ; #else ADFI_disk_pointer_2_ASCII_Hex( &sub_node_table_entry->child_location, &sub_node_entry_disk_data[ ADF_NAME_LENGTH ], &sub_node_entry_disk_data[ ADF_NAME_LENGTH + 8 ], error_return ) ; #endif if( *error_return != NO_ERROR ) return ; /** Now write it out to disk **/ ADFI_write_file( file_index, block_offset->block, block_offset->offset, ADF_NAME_LENGTH + DISK_POINTER_SIZE, sub_node_entry_disk_data, error_return ) ; if( *error_return != NO_ERROR ) return ; /** Set the subnode onto the stack **/ ADFI_stack_control(file_index, block_offset->block, (unsigned int)block_offset->offset, SET_STK, SUBNODE_STK, ADF_NAME_LENGTH + DISK_POINTER_SIZE, sub_node_entry_disk_data ); } /* end of ADFI_write_sub_node_table_entry */ /* end of file ADFI_write_sub_node_table_entry.c */ /* file ADFI_strtok.c */ /*********************************************************************** ADFI get string token: This routine simulates strtok except it returns the current postion in the string tobe used later. Thas avoids the problem of trying using strtok in a recrusive subroutine call which does not work! input/output: *string - the string to parse tokens from. returns string with token replaced by nil. input/output: *string_pos - the string position to begin parsing should be placed at the beginning of the string. returns postion after last token to continue string parsing. Token may change from last call. input: *token - The token to search for. function return: - a pointer to the desired substring. A NULL returns indicates the end of the string. ***********************************************************************/ char *ADFI_strtok( char *string, char **string_pos, char *token ) { char *tmp_ptr ; char *sub_string ; int string_len ; if ( string_pos == NULL ) return NULL ; if( token == NULL || string == NULL || *string_pos == NULL ) return NULL ; /* Get the length left in the string */ string_len = (int)strlen ( *string_pos ) ; if ( string_len == 0 ) return NULL ; /* Find the first character in the string which does not match the token */ tmp_ptr = *string_pos ; while ( string_len > 0 ) { if ( tmp_ptr[0] == token[0] ) { tmp_ptr++ ; string_len-- ; } else { break ; } /* end if */ } /* end while */ if ( string_len == 0 ) return NULL ; /* Set the begining fof the sub string */ sub_string = tmp_ptr ; /* Find the next token or the end of the string */ while ( string_len > 0 ) { if ( tmp_ptr[0] != token[0] ) { tmp_ptr++ ; string_len-- ; } else { tmp_ptr[0] = '\0' ; break ; } /* end if */ } /* end while */ /* Set location for the next search */ if ( string_len > 0 ) *string_pos = &tmp_ptr[1] ; else *string_pos = NULL ; return sub_string ; } /* end of ADFI_strtok */ /* end of file ADFI_strtok.c */ /* end of combine 2.0 */ CGNS-3.4.0/src/adf/ADF_internals.h000066400000000000000000001023531343724673500164350ustar00rootroot00000000000000/** File: ADF_internals.h ---------------------------------------------------------------------- BOEING ---------------------------------------------------------------------- Project: CGNS Author: Tom Dickens 865-6122 tpd6908@yak.ca.boeing.com Date: 3/2/1995 Purpose: Provide declarations for the internal ADF-Core routines. ---------------------------------------------------------------------- ---------------------------------------------------------------------- **/ #ifndef ADF_INTERNALS_INCLUDE #define ADF_INTERNALS_INCLUDE #include "ADF.h" #include /* needed for toupper */ #define NEW_ID_MAPPING #define NEW_DISK_POINTER /*********************************************************************** Defines ***********************************************************************/ /* the length of items in a sub_node_list is a multiple of LIST_CHUNK */ #define LIST_CHUNK 8 #define LIST_CHUNK_GROW_FACTOR 1.5 /** File parameters **/ #ifndef DISK_BLOCK_SIZE #define DISK_BLOCK_SIZE 4096 #endif #ifdef NEW_ID_MAPPING # define MAXIMUM_FILES 0xfff #else # define MAXIMUM_FILES 0x3fff #endif #define MAXIMUM_32_BITS (4294967295U) #define BLANK_FILE_BLOCK 0 #define BLANK_BLOCK_OFFSET DISK_BLOCK_SIZE /** Sizes of things on disk **/ #define FILE_HEADER_SIZE 186 #define FREE_CHUNK_TABLE_SIZE 80 #define FREE_CHUNK_ENTRY_SIZE 32 #define NODE_HEADER_SIZE 246 #define DISK_POINTER_SIZE 12 #define TAG_SIZE 4 #define WHAT_STRING_SIZE 32 #define DATE_TIME_SIZE 28 /* smallest amount of data (chunk) to be allocated. Minimum size corresponds to the free-chunk minimum size for the free-chunk linked lists. */ #define SMALLEST_CHUNK_SIZE NODE_HEADER_SIZE #define SMALL_CHUNK_MAXIMUM 1024 #define MEDIUM_CHUNK_MAXIMUM DISK_BLOCK_SIZE #define FREE_CHUNKS_BLOCK 0 #define FREE_CHUNKS_OFFSET FILE_HEADER_SIZE #define ROOT_NODE_BLOCK 0 #define ROOT_NODE_OFFSET (FREE_CHUNKS_OFFSET + FREE_CHUNK_TABLE_SIZE) #define ROOT_NODE_NAME "ADF MotherNode" #define ROOT_NODE_LABEL "Root Node of ADF File" /** Machine formats **/ #define UNDEFINED_FORMAT 0 #define IEEE_BIG_32_FORMAT 1 #define IEEE_LITTLE_32_FORMAT 2 #define IEEE_BIG_64_FORMAT 3 #define IEEE_LITTLE_64_FORMAT 4 #define CRAY_FORMAT 5 #define NATIVE_FORMAT 99 #define UNDEFINED_FORMAT_CHAR 'U' #define IEEE_BIG_FORMAT_CHAR 'B' #define IEEE_LITTLE_FORMAT_CHAR 'L' #define CRAY_FORMAT_CHAR 'C' #define NATIVE_FORMAT_CHAR 'N' #define OS_64_BIT 'B' #define OS_32_BIT 'L' #define IEEE_BIG_32_FORMAT_STRING "IEEE_BIG_32" #define IEEE_LITTLE_32_FORMAT_STRING "IEEE_LITTLE_32" #define IEEE_BIG_64_FORMAT_STRING "IEEE_BIG_64" #define IEEE_LITTLE_64_FORMAT_STRING "IEEE_LITTLE_64" #define CRAY_FORMAT_STRING "CRAY" #define NATIVE_FORMAT_STRING "NATIVE" #define LEGACY_FORMAT_STRING "LEGACY" #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (-1) #endif /*********************************************************************** Defined Marcos ***********************************************************************/ /** Upper case a character **/ /** Need to use the system macros for the Cray optimizer **/ #define TO_UPPER( c ) ((islower(c))?(toupper(c)):(c)) #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) /*********************************************************************** Structures: ***********************************************************************/ /** A DISK_POINTER tracks the block number (from 0) and the offset within a block. **/ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct DISK_POINTER { cgulong_t block ; /* 0 to 4,294,967,295 (8 ASCII-Hex bytes) */ cgulong_t offset ; /* 0 to 4096 (4 ASCII-Hex bytes) */ } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct FILE_HEADER { char what [WHAT_STRING_SIZE] ; char tag0 [TAG_SIZE] ; char creation_date [DATE_TIME_SIZE] ; char tag1 [TAG_SIZE] ; char modification_date [DATE_TIME_SIZE] ; char tag2 [TAG_SIZE] ; char numeric_format ; char os_size ; char tag3 [TAG_SIZE] ; unsigned int sizeof_char ; unsigned int sizeof_short ; unsigned int sizeof_int ; unsigned int sizeof_long ; unsigned int sizeof_float ; unsigned int sizeof_double ; unsigned int sizeof_char_p ; unsigned int sizeof_short_p ; unsigned int sizeof_int_p ; unsigned int sizeof_long_p ; unsigned int sizeof_float_p ; unsigned int sizeof_double_p ; char tag4 [TAG_SIZE] ; struct DISK_POINTER root_node ; struct DISK_POINTER end_of_file ; struct DISK_POINTER free_chunks ; struct DISK_POINTER extra ; char tag5 [TAG_SIZE] ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct FREE_CHUNK_TABLE { char start_tag [TAG_SIZE] ; struct DISK_POINTER small_first_block ; struct DISK_POINTER small_last_block ; struct DISK_POINTER medium_first_block ; struct DISK_POINTER medium_last_block ; struct DISK_POINTER large_first_block ; struct DISK_POINTER large_last_block ; char end_tag [TAG_SIZE] ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct FREE_CHUNK { char start_tag [TAG_SIZE] ; struct DISK_POINTER end_of_chunk_tag ; struct DISK_POINTER next_chunk ; char end_tag [TAG_SIZE] ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct NODE_HEADER { char node_start_tag [TAG_SIZE] ; char name [ADF_NAME_LENGTH] ; char label [ADF_LABEL_LENGTH] ; unsigned int num_sub_nodes ; unsigned int entries_for_sub_nodes ; struct DISK_POINTER sub_node_table ; char data_type [ADF_DATA_TYPE_LENGTH] ; unsigned int number_of_dimensions ; cgulong_t dimension_values [ADF_MAX_DIMENSIONS] ; unsigned int number_of_data_chunks ; struct DISK_POINTER data_chunks ; char node_end_tag [TAG_SIZE] ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct DATA_CHUNK_TABLE_ENTRY { struct DISK_POINTER start ; struct DISK_POINTER end ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct SUB_NODE_TABLE_ENTRY { char child_name[ ADF_NAME_LENGTH ] ; struct DISK_POINTER child_location ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ struct TOKENIZED_DATA_TYPE { char type[2] ; int file_type_size ; int machine_type_size ; unsigned int length ; } ; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*********************************************************************** Data structures for open ADF files in_use: number of times this file has been 'opened' nlinks : number of linked files opened by this file links : the list of linked files opened file_name : name of the open file open_mode: The mode the file was opened in. version_update: If library file version is greater than file version, library file version (what-string) is temporarily stored in this array to update to the file. The file only needs its version updated once while open, so don't expect the version to persist until file closing. Otherwise, the first byte in the string is null ('\0'). format : format of the file os_size : operating system size link_separator : separator character for links file: The system-returned file descriptor of an opened file. ***********************************************************************/ typedef struct { int in_use; int nlinks; unsigned int *links; char *file_name; char open_mode[10]; char version_update[WHAT_STRING_SIZE+1]; char format; char os_size; char link_separator; char old_version; int file; } ADF_FILE; extern ADF_FILE *ADF_file; extern int maximum_files; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*********************************************************************** Prototypes for Internal CORE Utility Routines ***********************************************************************/ #if defined (__cplusplus) extern "C" { #endif extern void ADFI_Abort( const int error_code ) ; extern void ADFI_ASCII_Hex_2_unsigned_int( const unsigned int minimum, const unsigned int maximum, const unsigned int string_length, const char string[], unsigned int *number, int *error_return ) ; extern void ADFI_add_2_sub_node_table( const int file_index, const struct DISK_POINTER *parent, const struct DISK_POINTER *child, int *error_return ) ; extern void ADFI_adjust_disk_pointer( struct DISK_POINTER *block_offset, int *error_return ) ; extern void ADFI_big_endian_to_cray( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_big_little_endian_swap( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_big_endian_32_swap_64( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_blank_fill_string( char *str, const int length ) ; extern void ADFI_chase_link( const double ID, double *LID, unsigned int *file_index, struct DISK_POINTER *block_offset, struct NODE_HEADER *node_header, int *error_return ) ; extern void ADFI_check_4_child_name( const int file_index, const struct DISK_POINTER *parent, const char *name, int *found, struct DISK_POINTER *sub_node_entry_location, struct SUB_NODE_TABLE_ENTRY *sub_node_entry, int *error_return ) ; extern void ADFI_check_string_length( const char *str, const int max_length, int *error_return ) ; extern void ADFI_close_file( const int top_file_index, int *error_return ) ; extern void ADFI_compare_node_names( const char *name, const char *new_name, int *names_match, int *error_return ) ; extern void ADFI_convert_number_format( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const int convert_dir, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const unsigned int length, unsigned char *from_data, unsigned char *to_data, int *error_return ) ; extern void ADFI_count_total_array_points( const unsigned int ndim, const cgulong_t dims[], const cgsize_t dim_start[], const cgsize_t dim_end[], const cgsize_t dim_stride[], cgulong_t *total_points, cgulong_t *starting_offset, int *error_return ) ; extern void ADFI_cray_to_big_endian( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_cray_to_little_endian( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_delete_data( const int file_index, const struct NODE_HEADER *node_header, int *error_return ) ; extern void ADFI_delete_from_sub_node_table( const int file_index, const struct DISK_POINTER *parent, const struct DISK_POINTER *child, int *error_return ) ; extern void ADFI_delete_sub_node_table( const int file_index, const struct DISK_POINTER *block_offset, const unsigned int size_sub_node_table, int *error_return ) ; extern void ADFI_disk_pointer_2_ASCII_Hex( const struct DISK_POINTER *block_offset, char block[8], char offset[4], int *error_return ) ; extern void ADFI_disk_pointer_from_ASCII_Hex( const char block[8], const char offset[4], struct DISK_POINTER *block_offset, int *error_return ) ; extern void ADFI_evaluate_datatype( const int file_index, const char data_type[], int *bytes_file, int *bytes_machine, struct TOKENIZED_DATA_TYPE *tokenized_data_type, char *file_format, char *machine_format, int *error_return ) ; extern void ADFI_figure_machine_format( const char *format, char *machine_format, char *format_to_use, char *os_to_use, int *error_return ) ; extern void ADFI_file_and_machine_compare( const int file_index, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, int *compare, int *error_return ) ; extern void ADFI_file_block_offset_2_ID( const int file_index, const cgulong_t file_block, const cgulong_t block_offset, double *ID, int *error_return ) ; extern void ADFI_file_free( const int file_index, const struct DISK_POINTER *block_offset, const cglong_t number_of_bytes, int *error_return ) ; extern void ADFI_file_malloc( const int file_index, const cglong_t size_bytes, struct DISK_POINTER *block_offset, int *error_return ) ; extern void ADFI_fill_initial_file_header( const char format, const char os_size, const char *what_string, struct FILE_HEADER *file_header, int *error_return ) ; extern void ADFI_fill_initial_free_chunk_table( struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) ; extern void ADFI_fill_initial_node_header( struct NODE_HEADER *node_header, int *error_return ) ; extern void ADFI_fseek_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, int *error_return ) ; extern void ADFI_get_current_date( char date[] ) ; extern void ADFI_get_direct_children_ids( const unsigned int file_index, const struct DISK_POINTER *node_block_offset, int *num_ids, double **ids, int *error_return ) ; extern void ADFI_get_file_index_from_name( const char *file_name, int *found, unsigned int *file_index, double *ID, int *error_return ) ; extern void ADFI_ID_2_file_block_offset( const double ID, unsigned int *file_index, cgulong_t *file_block, cgulong_t *block_offset, int *error_return ) ; extern void ADFI_increment_array( const unsigned int ndim, const cgulong_t dims[], const cgsize_t dim_start[], const cgsize_t dim_end[], const cgsize_t dim_stride[], cglong_t current_position[], cgulong_t *element_offset, int *error_return ) ; extern void ADFI_is_block_in_core() ; extern void ADFI_little_endian_to_cray( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_little_endian_32_swap_64( const char from_format, const char from_os_size, const char to_format, const char to_os_size, const char data_type[2], const cgulong_t delta_from_bytes, const cgulong_t delta_to_bytes, const unsigned char *from_data, unsigned char *to_data, int *error_return ); extern void ADFI_open_file( const char *file, const char *status, unsigned int *file_index, int *error_return ) ; extern void ADFI_read_chunk_length( const unsigned int file_index, const struct DISK_POINTER *block_offset, char tag[4], struct DISK_POINTER *end_of_chunk_tag, int *error_return ) ; extern void ADFI_read_data_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t chunk_bytes, const cglong_t start_offset, const cglong_t total_bytes, char *data, int *error_return ) ; extern void ADFI_read_data_chunk_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[], int *error_return ) ; extern void ADFI_read_data_translated( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t total_bytes, char *data, int *error_return ) ; extern void ADFI_read_disk_block() ; extern void ADFI_read_disk_pointer_from_disk( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, struct DISK_POINTER *block_and_offset, int *error_return ) ; extern void ADFI_read_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const cglong_t data_length, char *data, int *error_return ) ; extern void ADFI_read_file_header( const unsigned int file_index, struct FILE_HEADER *file_header, int *error_return ) ; extern void ADFI_read_free_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct FREE_CHUNK *free_chunk, int *error_return ) ; extern void ADFI_read_free_chunk_table( const unsigned int file_index, struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) ; extern void ADFI_read_node_header( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct NODE_HEADER *node_header, int *error_return ) ; extern void ADFI_read_sub_node_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct SUB_NODE_TABLE_ENTRY sub_node_table[], int *error_return ) ; extern void ADFI_read_sub_node_table_entry( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct SUB_NODE_TABLE_ENTRY *sub_node_table_entry, int *error_return ) ; extern void ADFI_remember_file_format( const int file_index, const char numeric_format, const char os_size, int *error_return ) ; extern void ADFI_remember_version_update( const int file_index, const char *what_string, int *error_return ) ; extern void ADFI_set_blank_disk_pointer( struct DISK_POINTER *block_offset) ; extern int ADFI_stridx_c( const char *str1, const char *str2 ) ; extern void ADFI_string_2_C_string( const char *string, const int string_length, char *c_string, int *error_return ) ; extern char *ADFI_strtok( char *string, char **string_pos, char *token ) ; extern void ADFI_unsigned_int_2_ASCII_Hex( const unsigned int number, const unsigned int minimum, const unsigned int maximum, const unsigned int string_length, char string[], int *error_return ) ; extern void ADFI_write_data_chunk( const unsigned int file_index, const struct DISK_POINTER *block_offset, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t chunk_bytes, const cglong_t start_offset, const cglong_t total_bytes, const char *data, int *error_return ) ; extern void ADFI_write_data_chunk_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, const int number_of_data_chunks, struct DATA_CHUNK_TABLE_ENTRY data_chunk_table[], int *error_return ) ; extern void ADFI_write_data_translated( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const struct TOKENIZED_DATA_TYPE *tokenized_data_type, const int data_size, const cglong_t total_bytes, const char *data, int *error_return ) ; extern void ADFI_write_disk_block() ; extern void ADFI_write_disk_pointer_2_disk( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const struct DISK_POINTER *block_and_offset, int *error_return ) ; extern void ADFI_write_file( const unsigned int file_index, const cgulong_t file_block, const cgulong_t block_offset, const cglong_t data_length, const char *data, int *error_return ) ; extern void ADFI_write_file_header( const int file_index, const struct FILE_HEADER *file_header, int *error_return ) ; extern void ADFI_write_free_chunk( const int file_index, const struct DISK_POINTER *block_offset, const struct FREE_CHUNK *free_chunk, int *error_return ) ; extern void ADFI_write_free_chunk_table( const int file_index, const struct FREE_CHUNK_TABLE *free_chunk_table, int *error_return ) ; extern void ADFI_write_modification_date( const int file_index, int *error_return ) ; extern void ADFI_write_node_header( const int file_index, const struct DISK_POINTER *block_offset, const struct NODE_HEADER *node_header, int *error_return ) ; extern void ADFI_write_sub_node_table( const unsigned int file_index, const struct DISK_POINTER *block_offset, const int number_of_sub_nodes, struct SUB_NODE_TABLE_ENTRY sub_node_table[], int *error_return ) ; extern void ADFI_write_sub_node_table_entry( const unsigned int file_index, const struct DISK_POINTER *block_offset, struct SUB_NODE_TABLE_ENTRY *sub_node_table_entry, int *error_return ) ; extern void ADFI_flush_buffers( const unsigned int file_index, int flush_mode, int *error_return ) ; extern void ADFI_fflush_file( const unsigned int file_index, int *error_return ) ; extern int ADFI_stack_control( const unsigned int file_index, const cgulong_t file_block, const unsigned int block_offset, const int stack_mode, const int stack_type, const unsigned int data_length, char *stack_data ) ; /*********************************************************************** Prototypes for the FORTRAN to C Interface Routines ***********************************************************************/ #include "ADF_fbind.h" extern void FNAME(adfcna2,ADFCNA2)( const Fdouble *PID, const Fint *istart, const Fint *imaxnum, const Fint *idim, const Fint *name_length, Fint *inum_ret, Fchar names, Fint *error_return ) ; extern void FNAME(adfcid2,ADFCID2)( const Fdouble *PID, const Fint *istart, const Fint *imaxnum, Fint *inum_ret, Fdouble *cIDs, Fint *error_return ) ; extern void FNAME(adfcre2,ADFCRE2)( const Fdouble *PID, const Fchar name, const Fint *name_length, Fdouble *ID, Fint *error_return ) ; extern void FNAME(adfdcl2,ADFDCL2)( const Fdouble *Root_ID, Fint *error_return ) ; extern void FNAME(adfdde2,ADFDDE2)( const Fchar filename, const Fint *name_length, Fint *error_return ) ; extern void FNAME(adfdgc2,ADFDGC2)( const Fdouble *ID, Fint *error_return ) ; extern void FNAME(adfdgf2,ADFDGF2)( const Fdouble *Root_ID, Fchar format, const Fint *format_length, Fint *error_return ) ; extern void FNAME(adfdop2,ADFDOP2)( const Fchar filename, const Fint *filename_length, Fchar status_in, const Fint *status_length, const Fchar format, const Fint *format_length, Fdouble *Root_ID, Fint *error_return ) ; extern void FNAME(adfdsf2,ADFDSF2)( const Fdouble *Root_ID, const Fchar format, const Fint *format_length, Fint *error_return ) ; extern void FNAME(adfdve2,ADFDVE2)( const Fdouble *Root_ID, Fchar version, Fchar creation_date, Fchar modification_date, const Fint *v_length, const Fint *c_length, const Fint *m_length, Fint *error_return ) ; extern void FNAME(adfdel2,ADFDEL2)( const Fdouble *PID, const Fdouble *ID, Fint *error_return ) ; extern void FNAME(adferr2,ADFERR2)( const Fint *error_return_input, Fchar error_string, const Fint *str_length ) ; extern void FNAME(adfftd2,ADFFTD2)( const Fdouble *ID, Fint *error_return ) ; extern void FNAME(adfgdt2,ADFGDT2)( const Fdouble *ID, Fchar data_type, const Fint *data_type_length, Fint *error_return ) ; extern void FNAME(adfgdv2,ADFGDV2)( const Fdouble *ID, Fint dim_vals[], Fint *error_return ) ; extern void FNAME(adfges2,ADFGES2)( Fint *error_state, Fint *error_return ) ; extern void FNAME(adfglb2,ADFGLB2)( const Fdouble *ID, Fchar label, const Fint *label_length, Fint *error_return ) ; extern void FNAME(adfglk2,ADFGLK2)( const Fdouble *ID, Fchar filename, const Fint *filename_length, Fchar link_path, const Fint *link_path_length, Fint *error_return ) ; extern void FNAME(adfgna2,ADFGNA2)( const Fdouble *ID, Fchar name, const Fint *name_length, Fint *error_return ) ; extern void FNAME(adfgni2,ADFGNI2)( const Fdouble *PID, const Fchar name, const Fint *name_length, Fdouble *ID, Fint *error_return ) ; extern void FNAME(adfgnd2,ADFGND2)( const Fdouble *ID, Fint *num_dims, Fint *error_return ) ; extern void FNAME(adfgri2,ADFGRI2)( const Fdouble *ID, Fdouble *Root_ID, Fint *error_return ) ; extern void FNAME(adfisl2,ADFISL2)( const Fdouble *ID, Fint *link_path_length, Fint *error_return ) ; extern void FNAME(adflve2,ADFLVE2)( Fchar version, const Fint *version_length, Fint *error_return ) ; extern void FNAME(adflin2,ADFLIN2)( const Fdouble *PID, const Fchar name, const Fchar file, const Fchar name_in_file, const Fint *name_length, const Fint *file_length, const Fint *nfile_length, Fdouble *ID, Fint *error_return ) ; extern void FNAME(adfmov2,ADFMOV2)( const Fdouble *PID, const Fdouble *ID, const Fdouble *NPID, Fint *error_return ) ; extern void FNAME(adfncl2,ADFNCL2)( const Fdouble *ID, Fint *num_children, Fint *error_return ) ; extern void FNAME(adfpdi2,ADFPDI2)( const Fdouble *ID, const Fchar data_type, const Fint *data_type_length, const Fint *dims, const Fint dim_vals[], Fint *error_return ) ; extern void FNAME(adfpna2,ADFPNA2)( const Fdouble *PID, const Fdouble *ID, const Fchar name, const Fint *name_length, Fint *error_return ) ; extern void FNAME(adfrall,ADFRALL)( const Fdouble *ID, Fchar data, Fint *error_return ) ; extern void FNAME(adfrblk,ADFRBLK)( const Fdouble *ID, const int *b_start, const int *b_end, Fchar data, Fint *error_return ) ; extern void FNAME(adfread,ADFREAD)( const Fdouble *ID, const Fint s_start[], const Fint s_end[], const Fint s_stride[], const Fint *m_num_dims, const Fint m_dims[], const Fint m_start[], const Fint m_end[], const Fint m_stride[], Fchar data, Fint *error_return ) ; extern void FNAME(adfses2,ADFSES2)( const Fint *error_state, Fint *error_return ) ; extern void FNAME(adfslb2,ADFSLB2)( const Fdouble *ID, const Fchar label, const Fint *label_length, Fint *error_return ) ; extern void FNAME(adfwall,ADFWALL)( const Fdouble *ID, const Fchar data, Fint *error_return ) ; extern void FNAME(adfwblk,ADFWBLK)( const Fdouble *ID, const int *b_start, const int *b_end, Fchar data, Fint *error_return ) ; extern void FNAME(adfwrit,ADFWRIT)( const Fdouble *ID, const Fint s_start[], const Fint s_end[], const Fint s_stride[], const Fint *m_num_dims, const Fint m_dims[], const Fint m_start[], const Fint m_end[], const Fint m_stride[], const Fchar data, Fint *error_return ) ; #if defined (__cplusplus) } #endif #endif CGNS-3.4.0/src/adf/adf_ftoc.c000066400000000000000000000212371343724673500155250ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include "fortran_macros.h" #include "ADF_internals.h" #if defined(_WIN32) && defined(BUILD_DLL) # define CGNSDLL __declspec(dllexport) #else # define CGNSDLL #endif /* ADF Fortran to C interface */ CGNSDLL void FMNAME(adfcnam, ADFCNAM) (double *ID, int *istart, int *inum, int *inamlen, int *inumret, STR_PSTR(names), int *ier STR_PLEN(names)) { int len_names = (int)STR_LEN(names); FMCALL(adfcna2,ADFCNA2)(ID, istart, inum, inamlen, &len_names, inumret, STR_PTR(names), ier); } CGNSDLL void FMNAME(adfcids, ADFCIDS) (double *ID, int *istart, int *inum, int *inumret, double *cIDs, int *ier) { FMCALL(adfcid2,ADFCID2)(ID, istart, inum, inumret, cIDs, ier); } CGNSDLL void FMNAME(adfcre, ADFCRE) (double *PID, STR_PSTR(name), double *ID, int *ier STR_PLEN(name)) { int len_name = (int)STR_LEN(name); FMCALL(adfcre2, ADFCRE2)(PID, STR_PTR(name), &len_name, ID, ier); } CGNSDLL void FMNAME(adfdclo, ADFDCLO) (double *RootID, int *ier) { FMCALL(adfdcl2, ADFDCL2)(RootID, ier); } CGNSDLL void FMNAME(adfddel, ADFDDEL) (STR_PSTR(filename), int *ier STR_PLEN(filename)) { int len_filename = (int)STR_LEN(filename); FMCALL(adfdde2, ADFDDE2)(STR_PTR(filename), &len_filename, ier); } CGNSDLL void FMNAME(adfdel, ADFDEL) (double *PID, double *ID, int *ier) { FMCALL(adfdel2, ADFDEL2)(PID, ID, ier); } CGNSDLL void FMNAME(adfdgc, ADFDGC) (double *ID, int *ier) { FMCALL(adfdgc2, ADFDGC2)(ID, ier); } CGNSDLL void FMNAME(adfdgf, ADFDGF) (double *RootID, STR_PSTR(format), int *ier STR_PLEN(format)) { int len_format = (int)STR_LEN(format); FMCALL(adfdgf2, ADFDGF2)(RootID, STR_PTR(format), &len_format, ier); } CGNSDLL void FMNAME(adfdopn, ADFDOPN) (STR_PSTR(filename), STR_PSTR(status), STR_PSTR(format), double *RootID, int *ier STR_PLEN(filename) STR_PLEN(status) STR_PLEN(format)) { int len_filename = (int)STR_LEN(filename); int len_status = (int)STR_LEN(status); int len_format = (int)STR_LEN(format); FMCALL(adfdop2, ADFDOP2)(STR_PTR(filename), &len_filename, STR_PTR(status), &len_status, STR_PTR(format), &len_format, RootID, ier); } CGNSDLL void FMNAME(adfdsf, ADFDSF) (double *RootID, STR_PSTR(format), int *ier STR_PLEN(format)) { int len_format = (int)STR_LEN(format); FMCALL(adfdsf2, ADFDSF2)(RootID, STR_PTR(format), &len_format, ier); } CGNSDLL void FMNAME(adfdver, ADFDVER) (double *RootID, STR_PSTR(version), STR_PSTR(cdate), STR_PSTR(mdate), int *ier STR_PLEN(version) STR_PLEN(cdate) STR_PLEN(mdate)) { int len_version = (int)STR_LEN(version); int len_cdate = (int)STR_LEN(cdate); int len_mdate = (int)STR_LEN(mdate); FMCALL(adfdve2, ADFDVE2)(RootID, STR_PTR(version), STR_PTR(cdate), STR_PTR(mdate), &len_version, &len_cdate, &len_mdate, ier); } CGNSDLL void FMNAME(adferr, ADFERR) (int *ier, STR_PSTR(errstr) STR_PLEN(errstr)) { int len_errstr = (int)STR_LEN(errstr); FMCALL(adferr2, ADFERR2)(ier, STR_PTR(errstr), &len_errstr); } CGNSDLL void FMNAME(adfftd, ADFFTD) (double *ID, int *ier) { FMCALL(adfftd2, ADFFTD2)(ID, ier); } CGNSDLL void FMNAME(adfgdt, ADFGDT) (double *ID, STR_PSTR(dtype), int *ier STR_PLEN(dtype)) { int len_dtype = (int)STR_LEN(dtype); FMCALL(adfgdt2, ADFGDT2)(ID, STR_PTR(dtype), &len_dtype, ier); } CGNSDLL void FMNAME(adfgdv, ADFGDV) (double *ID, int *dvals, int *ier) { FMCALL(adfgdv2, ADFGDV2)(ID, dvals, ier); } CGNSDLL void FMNAME(adfges, ADFGES) (int *estate, int *ier) { FMCALL(adfges2, ADFGES2)(estate, ier); } CGNSDLL void FMNAME(adfglb, ADFGLB) (double *ID, STR_PSTR(label), int *ier STR_PLEN(label)) { int len_label = (int)STR_LEN(label); FMCALL(adfglb2, ADFGLB2)(ID, STR_PTR(label), &len_label, ier); } CGNSDLL void FMNAME(adfglkp, ADFGLKP) (double *ID, STR_PSTR(file), STR_PSTR(name), int *ier STR_PLEN(file) STR_PLEN(name)) { int len_file = (int)STR_LEN(file); int len_name = (int)STR_LEN(name); FMCALL(adfglk2, ADFGLK2)(ID, STR_PTR(file), &len_file, STR_PTR(name), &len_name, ier); } CGNSDLL void FMNAME(adfgnam, ADFGNAM) (double *ID, STR_PSTR(name), int *ier STR_PLEN(name)) { int len_name = (int)STR_LEN(name); FMCALL(adfgna2, ADFGNA2)(ID, STR_PTR(name), &len_name, ier); } CGNSDLL void FMNAME(adfgnd, ADFGND) (double *ID, int *ndims, int *ier) { FMCALL(adfgnd2, ADFGND2)(ID, ndims, ier); } CGNSDLL void FMNAME(adfgnid, ADFGNID) (double *PID, STR_PSTR(name), double *ID, int *ier STR_PLEN(name)) { int len_name = (int)STR_LEN(name); FMCALL(adfgni2, ADFGNI2)(PID, STR_PTR(name), &len_name, ID, ier); } CGNSDLL void FMNAME(adfgrid, ADFGRID) (double *ID, double *RootID, int *ier) { FMCALL(adfgri2, ADFGRI2)(ID, RootID, ier); } CGNSDLL void FMNAME(adfislk, ADFISLK) (double *ID, int *lplen, int *ier) { FMCALL(adfisl2, ADFISL2)(ID, lplen, ier); } CGNSDLL void FMNAME(adflink, ADFLINK) (double *PID, STR_PSTR(name), STR_PSTR(file), STR_PSTR(nfile), double *ID, int *ier STR_PLEN(name) STR_PLEN(file) STR_PLEN(nfile)) { int len_name = (int)STR_LEN(name); int len_file = (int)STR_LEN(file); int len_nfile = (int)STR_LEN(nfile); FMCALL(adflin2, ADFLIN2)(PID, STR_PTR(name), STR_PTR(file), STR_PTR(nfile), &len_name, &len_file, &len_nfile, ID, ier); } CGNSDLL void FMNAME(adflver, ADFLVER) (STR_PSTR(version), int *ier STR_PLEN(version)) { int len_version = (int)STR_LEN(version); FMCALL(adflve2, ADFLVE2)(STR_PTR(version), &len_version, ier); } CGNSDLL void FMNAME(adfmove, ADFMOVE) (double *PID, double *ID, double *NPID, int *ier) { FMCALL(adfmov2, ADFMOV2)(PID, ID, NPID, ier); } CGNSDLL void FMNAME(adfncld, ADFNCLD) (double *ID, int *numcld, int *ier) { FMCALL(adfncl2, ADFNCL2)(ID, numcld, ier); } CGNSDLL void FMNAME(adfpdim, ADFPDIM) (double *ID, STR_PSTR(dtype), int *dims, int *dvals, int *ier STR_PLEN(dtype)) { int len_dtype = (int)STR_LEN(dtype); FMCALL(adfpdi2, ADFPDI2)(ID, STR_PTR(dtype), &len_dtype, dims, dvals, ier); } CGNSDLL void FMNAME(adfpnam, ADFPNAM) (double *PID, double *ID, STR_PSTR(name), int *ier STR_PLEN(name)) { int len_name = (int)STR_LEN(name); FMCALL(adfpna2, ADFPNA2)(PID, ID, STR_PTR(name), &len_name, ier); } CGNSDLL void FMNAME(adfses, ADFSES) (int *estate, int *ier) { FMCALL(adfses2, ADFSES2)(estate, ier); } CGNSDLL void FMNAME(adfslb, ADFSLB) (double *ID, STR_PSTR(label), int *ier STR_PLEN(label)) { int len_label = (int)STR_LEN(label); FMCALL(adfslb2, ADFSLB2)(ID, STR_PTR(label), &len_label, ier); } /* added mainly to handle character output under windows */ CGNSDLL void FMNAME(adfreadc, ADFREADC) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfread,ADFREAD)(ID, s_start, s_end, s_stride, m_num_dims, m_dims, m_start, m_end, m_stride, STR_PTR(data), ier); } CGNSDLL void FMNAME(adfrallc, ADFRALLC) (double *ID, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfrall, ADFRALL)(ID, STR_PTR(data), ier); } CGNSDLL void FMNAME(adfrblkc, ADFRBLKC) (double *ID, int *b_start, int *b_end, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfrblk, ADFRBLK)(ID, b_start, b_end, STR_PTR(data), ier); } CGNSDLL void FMNAME(adfwritc, ADFWRITC) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfwrit,ADFWRIT)(ID, s_start, s_end, s_stride, m_num_dims, m_dims, m_start, m_end, m_stride, STR_PTR(data), ier); } CGNSDLL void FMNAME(adfwallc, ADFWALLC) (double *ID, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfwall, ADFWALL)(ID, STR_PTR(data), ier); } CGNSDLL void FMNAME(adfwblkc, ADFWBLKC) (double *ID, int *b_start, int *b_end, STR_PSTR(data), int *ier STR_PLEN(data)) { FMCALL(adfwblk, ADFWBLK)(ID, b_start, b_end, STR_PTR(data), ier); } CGNS-3.4.0/src/adfh/000077500000000000000000000000001343724673500137575ustar00rootroot00000000000000CGNS-3.4.0/src/adfh/ADF.h000066400000000000000000000041531343724673500145250ustar00rootroot00000000000000/*------------------------------------------------------------------- * this is a replacement for ADF.h for HDF5 implementation *-------------------------------------------------------------------*/ #ifndef _ADF_H_ #define _ADF_H_ /* map ADF calls to ADFH calls */ #define ADF_Children_Names ADFH_Children_Names #define ADF_Children_IDs ADFH_Children_IDs #define ADF_Create ADFH_Create #define ADF_Database_Close ADFH_Database_Close #define ADF_Database_Delete ADFH_Database_Delete #define ADF_Database_Garbage_Collection ADFH_Database_Garbage_Collection #define ADF_Database_Get_Format ADFH_Database_Get_Format #define ADF_Database_Open ADFH_Database_Open #define ADF_Database_Valid ADFH_Database_Valid #define ADF_Database_Set_Format ADFH_Database_Set_Format #define ADF_Database_Version ADFH_Database_Version #define ADF_Delete ADFH_Delete #define ADF_Error_Message ADFH_Error_Message #define ADF_Flush_to_Disk ADFH_Flush_to_Disk #define ADF_Get_Data_Type ADFH_Get_Data_Type #define ADF_Get_Dimension_Values ADFH_Get_Dimension_Values #define ADF_Get_Error_State ADFH_Get_Error_State #define ADF_Get_Label ADFH_Get_Label #define ADF_Get_Link_Path ADFH_Get_Link_Path #define ADF_Get_Name ADFH_Get_Name #define ADF_Get_Node_ID ADFH_Get_Node_ID #define ADF_Get_Number_of_Dimensions ADFH_Get_Number_of_Dimensions #define ADF_Get_Root_ID ADFH_Get_Root_ID #define ADF_Is_Link ADFH_Is_Link #define ADF_Library_Version ADFH_Library_Version #define ADF_Link ADFH_Link #define ADF_Move_Child ADFH_Move_Child #define ADF_Number_of_Children ADFH_Number_of_Children #define ADF_Put_Dimension_Information ADFH_Put_Dimension_Information #define ADF_Put_Name ADFH_Put_Name #define ADF_Read_All_Data ADFH_Read_All_Data #define ADF_Read_Block_Data ADFH_Read_Block_Data #define ADF_Read_Data ADFH_Read_Data #define ADF_Set_Error_State ADFH_Set_Error_State #define ADF_Set_Label ADFH_Set_Label #define ADF_Write_All_Data ADFH_Write_All_Data #define ADF_Write_Block_Data ADFH_Write_Block_Data #define ADF_Write_Data ADFH_Write_Data #define ADF_Release_ID ADFH_Release_ID /* include ADFH.h */ #include "ADFH.h" #endif CGNS-3.4.0/src/adfh/ADFH.c000066400000000000000000002766441343724673500146500ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ /*------------------------------------------------------------------- * HDF5 interface to ADF *-------------------------------------------------------------------*/ #include #include #include #include #include #if defined(_WIN32) && !defined(__NUTC__) # include # define ACCESS _access # define UNLINK _unlink #else # include # define ACCESS access # define UNLINK unlink #endif #include "ADFH.h" #include "hdf5.h" #include "cgns_io.h" /* for cgio_find_file */ #ifdef BUILD_PARALLEL #include "mpi.h" extern int pcg_mpi_initialized; extern MPI_Info pcg_mpi_info; extern hid_t default_pio_mode; #endif #define ADFH_FORCE_ID_CLOSE /*#define ADFH_H5F_CLOSE_STRONG*/ /*#define ADFH_DEBUG_ON*/ #define ADFH_NO_ORDER #define ADFH_USE_STRINGS #define ADFH_FORTRAN_INDEXING static int CompressData = -1; #ifdef BUILD_PARALLEL static MPI_Comm ParallelMPICommunicator = MPI_COMM_WORLD; #endif #define TO_UPPER( c ) ((islower(c))?(toupper(c)):(c)) /* * ADF names are not allowed to start with a space. * Since HDF5 allows this, use the space to hide data */ /* dataset and group names */ #define D_PREFIX ' ' #ifdef ADFH_FORTRAN_INDEXING #define D_VERSION " hdf5version" #define D_OLDVERS " version" #else #define D_VERSION " version" #endif #define D_FORMAT " format" #define D_DATA " data" #define D_FILE " file" #define D_PATH " path" #define D_LINK " link" /* attribute names */ #define A_NAME "name" #define A_LABEL "label" #define A_TYPE "type" #define A_ORDER "order" #define A_MOUNT "mount" #define A_FILE "file" #define A_REFCNT "refcnt" #define A_FLAGS "flags" /* debugging */ #define ADFH_CHECK_HID( hid ) \ if (hid <0) {printf("#### BAD ID [%5d] ",__LINE__);fflush(stdout); } #define ADFH_PREFIX "#### DBG " #ifdef ADFH_DEBUG_ON #define ADFH_DEBUG(aaa) \ printf("#### DBG [%5d] ",__LINE__);fflush(stdout); \ printf aaa ; printf("\n"); fflush(stdout); #define DROP( msg ) printf("XX " msg "\n");fflush(stdout); #else #define ADFH_DEBUG(a) ; #define DROP( msg ) ; #endif /* ADF data types */ #define ADFH_MT "MT" #define ADFH_LK "LK" #define ADFH_B1 "B1" #define ADFH_C1 "C1" #define ADFH_I4 "I4" #define ADFH_I8 "I8" #define ADFH_U4 "U4" #define ADFH_U8 "U8" #define ADFH_R4 "R4" #define ADFH_R8 "R8" /* these are not supported */ #define ADFH_X4 "X4" #define ADFH_X8 "X8" /* file open modes */ #define ADFH_MODE_NEW 1 #define ADFH_MODE_OLD 2 #define ADFH_MODE_RDO 3 /* the following keeps track of open and mounted files */ #define ADFH_MAXIMUM_FILES 128 /* Start to prepare re-entrance into lib, gather statics in one global struct */ /* Then, you'll just have to handle struct with something else but a static... */ /* MTA stands for... Multi-Threads-Aware */ typedef struct _ADFH_MTA { int g_init; /* set when initialization done */ int g_error_state; /* zero means do not stop on error (one stops) */ int i_start; int i_len; int n_length; int n_names; #ifdef ADFH_NO_ORDER int i_count; #endif /* HDF5 property lists */ hid_t g_proplink; hid_t g_propgroupcreate; hid_t g_propdataset; int g_flags; hid_t g_files[ADFH_MAXIMUM_FILES]; #ifndef ADFH_FORCE_ID_CLOSE /* object ids returned to API user that should be closed */ hid_t *g_extids[ADFH_MAXIMUM_FILES]; int n_extids[ADFH_MAXIMUM_FILES]; /* number of extids */ int x_extids[ADFH_MAXIMUM_FILES]; /* max allocated in g_extids */ #endif } ADFH_MTA; static ADFH_MTA *mta_root=NULL; /* error codes and messages - do not care about multi-threading here */ static struct _ErrorList { int errcode; char *errmsg; } ErrorList[] = { {NO_ERROR, "No Error"}, {STRING_LENGTH_ZERO, "String length of zero or blank string detected"}, {STRING_LENGTH_TOO_BIG, "String length longer than maximum allowable length"}, {TOO_MANY_ADF_FILES_OPENED,"Too many files opened"}, {ADF_FILE_STATUS_NOT_RECOGNIZED,"File status was not recognized"}, {FILE_OPEN_ERROR, "File-open error"}, {NULL_STRING_POINTER, "A string pointer is NULL"}, {REQUESTED_NEW_FILE_EXISTS,"File Open Error: NEW - File already exists"}, {ADF_FILE_FORMAT_NOT_RECOGNIZED,"File format was not recognized"}, {REQUESTED_OLD_FILE_NOT_FOUND,"File Open Error: OLD - File does not exist"}, {MEMORY_ALLOCATION_FAILED,"Memory allocation failed"}, {DUPLICATE_CHILD_NAME, "Duplicate child name under a parent node"}, {ZERO_DIMENSIONS, "Node has no dimensions"}, {BAD_NUMBER_OF_DIMENSIONS,"Node's number-of-dimensions is not in legal range"}, {CHILD_NOT_OF_GIVEN_PARENT,"Specified child is NOT a child of the specified parent"}, {INVALID_DATA_TYPE, "Invalid Data-Type"}, {NULL_POINTER, "A pointer is NULL"}, {NO_DATA, "Node has no data associated with it"}, {END_OUT_OF_DEFINED_RANGE,"Bad end value"}, {BAD_STRIDE_VALUE, "Bad stride value"}, {MINIMUM_GT_MAXIMUM, "Minimum value is greater than the maximum value"}, {DATA_TYPE_NOT_SUPPORTED, "The data format is not support on a particular machine"}, {FILE_CLOSE_ERROR, "File Close error"}, {START_OUT_OF_DEFINED_RANGE,"Bad start value"}, {ZERO_LENGTH_VALUE, "A value of zero is not allowable"}, {BAD_DIMENSION_VALUE, "Bad dimension value"}, {BAD_ERROR_STATE, "Error state must be either a 0 (zero) or a 1 (one)"}, {UNEQUAL_MEMORY_AND_DISK_DIMS,"Unequal dimensional specifications for disk and memory"}, {NODE_IS_NOT_A_LINK, "The node is not a link. It was expected to be a link"}, {LINK_TARGET_NOT_THERE, "The linked-to node does not exist"}, {LINKED_TO_FILE_NOT_THERE,"The file of a linked-node is not accessable"}, {INVALID_NODE_NAME, "Node name contains invalid characters"}, {FFLUSH_ERROR, "H5Fflush:flush error"}, {NULL_NODEID_POINTER, "The node ID pointer is NULL"}, {MAX_FILE_SIZE_EXCEEDED, "The maximum size for a file exceeded"}, {MAX_INT32_SIZE_EXCEEDED, "dimensions exceed that for a 32-bit integer"}, {ADFH_ERR_GLINK, "H5Glink:soft link creation failed"}, {ADFH_ERR_NO_ATT, "Node attribute doesn't exist"}, {ADFH_ERR_AOPEN, "H5Aopen:open of node attribute failed"}, {ADFH_ERR_IGET_NAME, "H5Iget_name:failed to get node path from ID"}, {ADFH_ERR_GMOVE, "H5Gmove:moving a node group failed"}, {ADFH_ERR_GUNLINK, "H5Gunlink:node group deletion failed"}, {ADFH_ERR_GOPEN, "H5Gopen:open of a node group failed"}, {ADFH_ERR_DGET_SPACE, "H5Dget_space:couldn't get node dataspace"}, {ADFH_ERR_DOPEN, "H5Dopen:open of the node data failed"}, {ADFH_ERR_DEXTEND, "H5Dextend:couldn't extend the node dataspace"}, {ADFH_ERR_DCREATE, "H5Dcreate:node data creation failed"}, {ADFH_ERR_SCREATE_SIMPLE, "H5Screate_simple:dataspace creation failed"}, {ADFH_ERR_ACREATE, "H5Acreate:node attribute creation failed"}, {ADFH_ERR_GCREATE, "H5Gcreate:node group creation failed"}, {ADFH_ERR_DWRITE, "H5Dwrite:write to node data failed"}, {ADFH_ERR_DREAD, "H5Dread:read of node data failed"}, {ADFH_ERR_AWRITE, "H5Awrite:write to node attribute failed"}, {ADFH_ERR_AREAD, "H5Aread:read of node attribute failed"}, {ADFH_ERR_FMOUNT, "H5Fmount:file mount failed"}, {ADFH_ERR_LINK_MOVE, "Can't move a linked-to node"}, {ADFH_ERR_LINK_DATA, "Can't change the data for a linked-to node"}, {ADFH_ERR_LINK_NODE, "Parent of node is a link"}, {ADFH_ERR_LINK_DELETE, "Can't delete a linked-to node"}, {ADFH_ERR_NOT_HDF5_FILE, "File does not exist or is not a HDF5 file"}, {ADFH_ERR_FILE_DELETE, "unlink (delete) of file failed"}, {ADFH_ERR_FILE_INDEX, "couldn't get file index from node ID"}, {ADFH_ERR_TCOPY, "H5Tcopy:copy of existing datatype failed"}, {ADFH_ERR_AGET_TYPE, "H5Aget_type:couldn't get attribute datatype"}, {ADFH_ERR_TSET_SIZE, "H5Tset_size:couldn't set datatype size"}, {ADFH_ERR_NOT_IMPLEMENTED,"routine not implemented"}, {ADFH_ERR_NOTXLINK, "H5L: Link target is not an HDF5 external link"}, {ADFH_ERR_LIBREG, "HDF5: No external link feature available"}, {ADFH_ERR_OBJINFO_FAILED, "HDF5: Internal problem with objinfo"}, {ADFH_ERR_XLINK_NOVAL, "HDF5: No value for external link"}, {ADFH_ERR_XLINK_UNPACK, "HDF5: Cannot unpack external link"}, {ADFH_ERR_ROOTNULL, "HDF5: Root descriptor is NULL"}, {ADFH_ERR_NEED_TRANSPOSE, "dimensions need transposed - open in modify mode"}, {ADFH_ERR_INVALID_OPTION, "invalid configuration option"}, {ADFH_ERR_INVALID_USER_DATA, "invalid configuration data passed in"}, {ADFH_ERR_SENTINEL, ""} }; #define NUM_ERRORS (sizeof(ErrorList)/sizeof(struct _ErrorList)) #define ROOT_OR_DIE(err) \ if (mta_root == NULL){set_error(ADFH_ERR_ROOTNULL, err);return;} #define ROOT_OR_DIE_ERR(err) \ if (mta_root == NULL){set_error(ADFH_ERR_ROOTNULL, err);return 1;} /* usefull macros */ #define CMP_OSTAT(r,n) ((r)->objno[0]==(n)->objno[0] && \ (r)->objno[1]==(n)->objno[1] && \ (r)->fileno[0]==(n)->fileno[0] && \ (r)->fileno[1]==(n)->fileno[1]) static herr_t gfind_by_name(hid_t, const char *, void *); static herr_t find_by_name(hid_t, const char *, const H5A_info_t*, void *); #define has_child(ID,NAME) H5Giterate(ID,".",NULL,gfind_by_name,(void *)NAME) #define has_data(ID) H5Giterate(ID,".",NULL,gfind_by_name,(void *)D_DATA) #define has_att(ID,NAME) H5Aiterate2(ID,H5_INDEX_NAME,H5_ITER_NATIVE,NULL,find_by_name,(void *)NAME) #if 0 static herr_t gprint_name(hid_t, const char *, void *); static herr_t print_name(hid_t, const char *, const H5A_info_t*, void *); #define show_grp(ID) H5Giterate(ID,".",NULL,gprint_name,(void *)"GRP") #define show_att(ID,NAME) H5Aiterate2(ID,H5_INDEX_NAME,H5_ITER_NATIVE,NULL,print_name,(void *)NAME) #endif /* ---------------------------------------------------------------- * set error and terminate if error state set * ---------------------------------------------------------------- */ static void set_error(int errcode, int *err) { if ((mta_root != NULL)&&(errcode != NO_ERROR)&&(mta_root->g_error_state)) { char errmsg[ADF_MAX_ERROR_STR_LENGTH+1]; ADFH_Error_Message(errcode, errmsg); fprintf(stderr, "ERROR:%s\n", errmsg); exit(1); } *err = errcode; } /* ----- handle HDF5 errors --------------------------------------- */ static herr_t print_H5_error(int n, H5E_error2_t *desc, void *data) { const char *p; if ((p = strrchr(desc->file_name, '/')) == NULL && (p = strrchr(desc->file_name, '\\')) == NULL) p = desc->file_name; else p++; fprintf(stderr, "%s line %u in %s(): %s\n", p, desc->line, desc->func_name, desc->desc); return 0; } /* ----------------------------------------------------------------- */ static herr_t walk_H5_error(hid_t estack, void *data) { if ((mta_root != NULL) && (mta_root->g_error_state)) { fflush(stdout); fprintf(stderr, "\nHDF5 Error Trace Back\n"); return H5Ewalk2(H5E_DEFAULT, H5E_WALK_DOWNWARD, (H5E_walk2_t)print_H5_error, data); } return 0; } /* ----------------------------------------------------------------- * get file ID from node ID * ----------------------------------------------------------------- */ static hid_t get_file_id (hid_t id) { int n, nobj; hid_t *objs, fid = -1; H5G_stat_t gstat, rstat; /* find the file ID from the root ID */ if (H5Gget_objinfo(id, "/", 0, &gstat) >= 0) { nobj = H5Fget_obj_count(H5F_OBJ_ALL, H5F_OBJ_FILE); if (nobj > 0) { objs = (hid_t *) malloc (nobj * sizeof(hid_t)); if (objs == NULL) return fid; H5Fget_obj_ids(H5F_OBJ_ALL, H5F_OBJ_FILE, -1, objs); for (n = 0; n < nobj; n++) { H5Gget_objinfo(objs[n], "/", 0, &rstat); if (CMP_OSTAT(&gstat, &rstat)) { fid = objs[n]; break; } } free (objs); } } return fid; } /* ----------------------------------------------------------------- */ static int get_file_number (hid_t id, int *err) { int n; hid_t fid = get_file_id(id); if (mta_root == NULL) return -1; for (n = 0; n < ADFH_MAXIMUM_FILES; n++) { if (fid == mta_root->g_files[n]) { set_error(NO_ERROR, err); return n; } } set_error(ADFH_ERR_FILE_INDEX, err); return -1; } #ifndef ADFH_FORCE_ID_CLOSE /* ----------------------------------------------------------------- */ static track_id(hid_t refid, hid_t trackid) { int fn,er; int sname; char oname[256]; H5O_info_t objinfo; size_t maxhid; H5Oget_info(trackid,&objinfo); memset(oname,'\0',256); sname=H5Iget_name(trackid,oname,0); sname=H5Iget_name(trackid,oname,sname+1); fn=get_file_number(refid,&er); if (fn==-1) { ADFH_DEBUG((">ADFH track_ids cannot stat [%d][%s]",trackid,oname)); } else { if (mta_root->n_extids[fn]>mta_root->x_extids[fn]) { mta_root->x_extids[fn]+=256; maxhid=mta_root->x_extids[fn]*sizeof(hid_t*); mta_root->g_extids[fn]=(hid_t*)realloc(mta_root->g_extids[fn],maxhid); ADFH_DEBUG((">ADFH track_ids realloc up to [%d]",\ mta_root->x_extids[fn])); } mta_root->g_extids[fn][mta_root->n_extids[fn]]=trackid; ADFH_DEBUG((">ADFH track_ids [%d][%d][%s]",\ mta_root->n_extids[fn],trackid,oname)); mta_root->n_extids[fn]++; } } #endif /*----------------------------------------------------------------- * get the native format - returns pointer to static storage *----------------------------------------------------------------- */ static char *native_format(void) { static char format[ADF_FORMAT_LENGTH+1]; hid_t type = H5Tcopy(H5T_NATIVE_FLOAT); ADFH_CHECK_HID(type); if (H5Tequal(type, H5T_IEEE_F32BE)) strcpy(format, "IEEE_BIG_32"); else if (H5Tequal(type, H5T_IEEE_F32LE)) strcpy(format, "IEEE_LITTLE_32"); else if (H5Tequal(type, H5T_IEEE_F64BE)) strcpy(format, "IEEE_BIG_64"); else if (H5Tequal(type, H5T_IEEE_F64LE)) strcpy(format, "IEEE_LITTLE_64"); else sprintf(format, "NATIVE_%d", (int)H5Tget_precision(type)); H5Tclose(type); return format; } /* ----------------------------------------------------------------- * set/get attribute values * ----------------------------------------------------------------- */ static hid_t get_att_id(hid_t id, const char *name, int *err) { hid_t aid = H5Aopen_name(id, name); /* H5Aclose() performed elsewhere */ if (aid < 0) { if (!has_att(id, name)) set_error(ADFH_ERR_NO_ATT, err); else set_error(ADFH_ERR_AOPEN, err); } else set_error(NO_ERROR, err); return aid; } /* ----------------------------------------------------------------- */ static int new_str_att(hid_t id, const char *name, const char *value, int max_size, int *err) { #ifdef ADFH_USE_STRINGS hid_t sid, tid, aid; herr_t status; /* [1] the attribute is set on the GROUP (id is a group id) */ /* [2] all datatypes should be H5T_STRING and not H5T_NATIVE_CHAR which requires an array (see case below with a H5Screate_simple and providse an array of chars) */ sid = H5Screate(H5S_SCALAR); if (sid < 0) { set_error(ADFH_ERR_SCREATE_SIMPLE, err); return 1; } tid = H5Tcopy(H5T_C_S1); if (tid < 0) { H5Sclose(sid); set_error(ADFH_ERR_TCOPY, err); return 1; } if (H5Tset_size(tid, max_size + 1) < 0) { H5Tclose(tid); H5Sclose(sid); set_error(ADFH_ERR_TSET_SIZE, err); return 1; } aid = H5Acreate2(id, name, tid, sid, H5P_DEFAULT, H5P_DEFAULT); if (aid < 0) { H5Tclose(tid); H5Sclose(sid); set_error(ADFH_ERR_ACREATE, err); return 1; } status = H5Awrite(aid, tid, value); H5Aclose(aid); H5Tclose(tid); H5Sclose(sid); if (status < 0) { set_error(ADFH_ERR_AWRITE, err); return 1; } set_error(NO_ERROR, err); return 0; #else /* CAUTION: only use this for strings <= ADF_FILENAME_LENGTH */ hid_t sid, aid; hsize_t dim; herr_t status; char buff[ADF_FILENAME_LENGTH+1]; dim = max_size + 1; sid = H5Screate_simple(1, &dim, NULL); if (sid < 0) { set_error(ADFH_ERR_SCREATE_SIMPLE, err); return 1; } aid = H5Acreate2(id, name, H5T_NATIVE_CHAR, sid, H5P_DEFAULT, H5P_DEFAULT); if (aid < 0) { H5Sclose(sid); set_error(ADFH_ERR_ACREATE, err); return 1; } memset(buff, 0, ADF_FILENAME_LENGTH+1); strcpy(buff, value); status = H5Awrite(aid, H5T_NATIVE_CHAR, buff); H5Aclose(aid); H5Sclose(sid); if (status < 0) { set_error(ADFH_ERR_AWRITE, err); return 1; } set_error(NO_ERROR, err); return 0; #endif } /* ----------------------------------------------------------------- */ static int get_str_att(hid_t id, const char *name, char *value, int *err) { #ifdef ADFH_USE_STRINGS hid_t tid, att_id; herr_t status; ADFH_DEBUG((">ADFH get_str_att [%s]",name)); if ((att_id = get_att_id(id, name, err)) < 0) return 1; #if 0 status = H5Aread(att_id, H5T_NATIVE_CHAR, value); #else tid = H5Aget_type(att_id); if (tid < 0) { H5Aclose(att_id); set_error(ADFH_ERR_AGET_TYPE, err); return 1; } status = H5Aread(att_id, tid, value); H5Tclose(tid); #endif H5Aclose(att_id); ADFH_DEBUG(("i_count - mta_root->i_start; if (order >= 0 && order < mta_root->i_len) { p = (char *)namelist + order * mta_root->n_length; strncpy(p, name, mta_root->n_length-1); p[mta_root->n_length-1] = 0; mta_root->n_names++; } #else if ((gid = H5Gopen2(id, name, H5P_DEFAULT)) < 0) return 1; ADFH_DEBUG(("ADFH children_names [%d]",gid)); if (get_int_att(gid, A_ORDER, &order, &err)) { H5Gclose(gid); return 1; } order -= mta_root->i_start; if (order >= 0 && order < mta_root->i_len) { p = (char *)namelist + order * mta_root->n_length; strncpy(p, name, mta_root->n_length-1); p[mta_root->n_length-1] = 0; mta_root->n_names++; } H5Gclose(gid); #endif return 0; } /* ----------------------------------------------------------------- */ static herr_t children_ids(hid_t id, const char *name, const H5L_info_t *linfo, void *idlist) { hid_t gid; int order, err; ADFH_DEBUG((">ADFH children_ids [%s]",name)); ROOT_OR_DIE_ERR(&err); if (*name == D_PREFIX) return 0; if ((gid = H5Gopen2(id, name, H5P_DEFAULT)) < 0) return 1; #ifdef ADFH_NO_ORDER order = ++mta_root->i_count - mta_root->i_start; ADFH_DEBUG((">ADFH children_ids [%s] order is [%d]",name,order)); if (order >= 0 && order < mta_root->i_len) { to_ADF_ID(gid,((double *)idlist)[order]); mta_root->n_names++; #ifndef ADFH_FORCE_ID_CLOSE track_id(id,gid); #endif } else H5Gclose(gid); #else if (get_int_att(gid, A_ORDER, &order, &err)) { H5Gclose(gid); return 1; } order -= mta_root->i_start; if (order >= 0 && order < mta_root->i_len) { to_ADF_ID(gid,((double *)idlist)[order]); mta_root->n_names++; #ifndef ADFH_FORCE_ID_CLOSE track_id(id,gid); #endif } else H5Gclose(gid); #endif return 0; } #ifndef ADFH_NO_ORDER /* ----------------------------------------------------------------- called via H5Giterate in Move_Child & Delete functions. removes gaps in _order index attributes */ static herr_t fix_order(hid_t id, const char *name, void *data) { int start, order, err, ret = 0; hid_t gid, aid; if (mta_root == NULL) return ADFH_ERR_ROOTNULL; if (*name == D_PREFIX) return 0; if ((gid = H5Gopen2(id, name, H5P_DEFAULT)) < 0) return ADFH_ERR_GOPEN; if ((aid = get_att_id(gid, A_ORDER, &err)) < 0) { H5Gclose(gid); return err; } if (H5Aread(aid, H5T_NATIVE_INT, &order) < 0) ret = ADFH_ERR_AREAD; else { start = *((int *)data); if (order > start) { order--; if (H5Awrite(aid, H5T_NATIVE_INT, &order) < 0) ret = ADFH_ERR_AWRITE; } } ADFH_DEBUG(("ADFH fix_order [%d]",gid)); H5Aclose(aid); H5Gclose(gid); return ret; } #endif /* ----------------------------------------------------------------- */ static herr_t compare_children(hid_t id, const char *name, void *data) { H5G_stat_t stat, *pstat; if (*name != D_PREFIX) { pstat = (H5G_stat_t *)data; if (H5Gget_objinfo(id, name, 0, &stat) >= 0) return CMP_OSTAT(&stat, pstat); } return 0; } #if 0 /* ----------------------------------------------------------------- */ static herr_t print_children(hid_t id, const char *name, void *data) { if (*name != D_PREFIX) printf(" %s", name); return 0; } #endif /* ================================================================ * routines for dealing with links * ================================================================ */ static hid_t open_link(hid_t id, int *err) { hid_t lid; herr_t herr; const char *file; const char *path; H5G_stat_t sb; /* Object information */ char querybuff[512]; #ifdef ADFH_DEBUG_ON H5O_info_t oinfo;/* debug purpose only */ char buffname[ADF_NAME_LENGTH+1]; get_str_att(id, A_NAME, buffname, err); ADFH_DEBUG((">ADFH open_link [%s]",buffname)); #endif if (H5Lis_registered(H5L_TYPE_EXTERNAL) != 1) { set_error(ADFH_ERR_LIBREG, err); return -1; } herr=H5Gget_objinfo(id, D_LINK, (hbool_t)0, &sb); if (herr<0) { ADFH_DEBUG((">ADFH open_link type [%d][%d]",herr,sb.type)); set_error(ADFH_ERR_OBJINFO_FAILED, err); return -1; } /* Soft link -> link to our current file */ /* Hard link (User defined) -> link to an external file */ if (H5G_LINK != sb.type) { if (H5G_UDLINK != sb.type) { set_error(ADFH_ERR_NOTXLINK, err); return -1; } if (H5Lget_val(id,D_LINK,querybuff,sizeof(querybuff),H5P_DEFAULT)<0) { set_error(ADFH_ERR_XLINK_NOVAL, err); return -1; } if (H5Lunpack_elink_val(querybuff,sb.linklen,NULL,&file,&path)<0) { set_error(ADFH_ERR_XLINK_UNPACK, err); return -1; } /* open the actual link >> IN THE LINK GROUP << */ ADFH_DEBUG((">ADFH open_link (external)")); if ((lid = H5Gopen2(id, D_LINK, H5P_DEFAULT)) < 0) { set_error(LINK_TARGET_NOT_THERE, err); return lid; } } else { ADFH_DEBUG((">ADFH open_link (symbolic)")); if ((lid = H5Gopen2(id, D_LINK, H5P_DEFAULT)) < 0) { set_error(LINK_TARGET_NOT_THERE, err); return lid; } } #ifdef ADFH_DEBUG_ON H5Oget_info(lid, &oinfo); ADFH_DEBUG(("[%d]:%d",id,lid,oinfo.rc)); #endif return lid; } /* ----------------------------------------------------------------- */ static int is_link(hid_t id) { char type[3]; int err; if ((!get_str_att(id, A_TYPE, type, &err) && (0 == strcmp(ADFH_LK, type)))) { return 1; } return 0; } /* ----------------------------------------------------------------- */ static hid_t open_node(double id, int *err) { hid_t hid, gid, lid; ADFH_DEBUG((">ADFH open_node")); to_HDF_ID(id,hid); set_error(NO_ERROR, err); if (is_link(hid)) { lid=open_link(hid, err); /* bad id trapped in the function */ ADFH_DEBUG(("ADFH H5Gclose failed")); if (nid < 0) return nid; id = nid; } nid = parse_path(id, p, err); if (H5Gclose(id)<0) ADFH_DEBUG((">ADFH H5Gclose failed")); ADFH_DEBUG(("ADFH parse_path [%d]",nid)); return nid; } /* ----------------------------------------------------------------- * deletion routines * ----------------------------------------------------------------- */ static void delete_node(hid_t pid, const char *name) { H5Gunlink(pid, name); /* do we care about link ? no ? */ } /* ----------------------------------------------------------------- */ static herr_t delete_children(hid_t id, const char *name, void *data) { if (*name == D_PREFIX) { ADFH_DEBUG(("delete_children single")); if (! is_link(id)) { ADFH_DEBUG(("delete_children is not link [%s]",name)); H5Gunlink(id, name); } else { ADFH_DEBUG(("delete_children is link")); } ADFH_DEBUG(("delete_children single done")); } else { ADFH_DEBUG(("delete_children loop")); if (! is_link(id)) H5Giterate(id, name, NULL, delete_children, data); delete_node(id, name); } return 0; } /* ----------------------------------------------------------------- * check for valid node name * The return points to static storage - make a copy if needed * ----------------------------------------------------------------- */ static char *check_name(const char *new_name, int *err) { char *p; static char name[ADF_NAME_LENGTH+1]; if (new_name == NULL) { set_error(NULL_STRING_POINTER, err); return NULL; } /* skip leading space */ for (p = (char *)new_name; *p && isspace(*p); p++) ; if (!*p) { set_error(STRING_LENGTH_ZERO, err); return NULL; } if (strlen(p) > ADF_NAME_LENGTH) { set_error(STRING_LENGTH_TOO_BIG, err); return NULL; } strcpy(name, p); /* remove trailing space */ for (p = name+strlen(name)-1; p >= name && isspace(*p); p--) ; *++p = 0; if (!*name) { set_error(STRING_LENGTH_ZERO, err); return NULL; } /* these may cause problems with HDF5 */ if (NULL != strchr(name, '/') || 0 == strcmp (name, ".")) { set_error(INVALID_NODE_NAME, err); return NULL; } set_error(NO_ERROR, err); return name; } #ifdef ADFH_FORTRAN_INDEXING /*------------------------------------------------------------------ * transpose multi-dimensional indices recursively *------------------------------------------------------------------*/ static int swap_dimensions (hid_t gid) { char verstr[ADF_NAME_LENGTH+1]; sprintf(verstr, "/%s", D_OLDVERS); if (H5Lexists(gid, verstr, H5P_DEFAULT)) return 0; return 1; } static void transpose_dimensions (hid_t hid, const char *name) { #if 0 hid_t did, sid, tid, mid; int i, j, temp, ndims, diffs; hsize_t bytes, dims[ADF_MAX_DIMENSIONS]; void *data = NULL; #else hid_t did, sid; int i, j, ndims, diffs; hsize_t temp, dims[ADF_MAX_DIMENSIONS]; #endif if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) return; /* get dimensions and size */ sid = H5Dget_space(did); ndims = H5Sget_simple_extent_dims(sid, dims, NULL); H5Sclose(sid); if (ndims < 2) { H5Dclose(did); return; } #if 0 printf("%s:%d [%d", name, bytes, dims[0]); for (i = 1; i < ndims; i++) printf(",%d", dims[i]); printf("]\n"); fflush(stdout); #endif /* transpose dimensions */ diffs = 0; for (i = 0, j = ndims-1; i < j; i++, j--) { if (dims[i] != dims[j]) { temp = dims[i]; dims[i] = dims[j]; dims[j] = temp; diffs++; } } if (0 == diffs) { H5Dclose(did); return; } #if 0 /* read the data, then delete data set */ bytes = H5Dget_storage_size(did); tid = H5Dget_type(did); mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); if (bytes > 0) { data = malloc ((unsigned)bytes); H5Dread(did, mid, H5S_ALL, H5S_ALL, H5P_DEFAULT, data); } H5Dclose(did); H5Gunlink(hid, D_DATA); /* rewrite data with new dimensions */ sid = H5Screate_simple(ndims, dims, NULL); did = H5Dcreate2(hid, D_DATA, tid, sid, H5P_DEFAULT, mta_root->g_propdataset, H5P_DEFAULT); if (data != NULL) { H5Dwrite(did, mid, H5S_ALL, sid, H5P_DEFAULT, data); free(data); } H5Tclose(mid); H5Tclose(tid); H5Sclose(sid); #else if (H5Dset_extent(did, dims) < 0) { fprintf(stderr, "H5Dset_extent failed\n"); } #endif H5Dclose(did); } /* ----------------------------------------------------------------- */ static herr_t fix_dimensions(hid_t id, const char *name, void *data) { hid_t gid; int err; char type[ADF_DATA_TYPE_LENGTH+1]; if (*name != D_PREFIX && (gid = H5Gopen2(id, name, H5P_DEFAULT)) >= 0 && !get_str_att(gid, A_TYPE, type, &err) && strcmp(type, ADFH_LK)) { H5Giterate(gid, ".", NULL, fix_dimensions, NULL); transpose_dimensions(gid,name); H5Gclose(gid); } return 0; } #endif /* ================================================================= */ /* 1 to 1 mapping of ADF functions to HDF mimic functions */ /* ================================================================= */ void ADFH_Configure(const int option, const void *value, int *err) { if (option == ADFH_CONFIG_COMPRESS) { int compress = (int)((size_t)value); if (compress < 0) CompressData = 6; else if (compress > 9) CompressData = 9; else CompressData = compress; set_error(NO_ERROR, err); } #ifdef BUILD_PARALLEL else if (option == ADFH_CONFIG_MPI_COMM) { MPI_Comm* comm = (MPI_Comm*)value; if (!comm) { set_error(ADFH_ERR_INVALID_USER_DATA, err); } else { ParallelMPICommunicator = (MPI_Comm)*comm; set_error(NO_ERROR, err); } } #endif else { set_error(ADFH_ERR_INVALID_OPTION, err); } } /* ----------------------------------------------------------------- */ /* move a node */ void ADFH_Move_Child(const double pid, const double id, const double npid, int *err) { hid_t hpid; hid_t hid; hid_t hnpid; int len, namelen; #ifndef ADFH_NO_ORDER int old_order, new_order; #endif char buff[2]; char nodename[ADF_NAME_LENGTH+1]; char *newpath; herr_t status; H5G_stat_t stat; to_HDF_ID(pid,hpid); to_HDF_ID(id,hid); to_HDF_ID(npid,hnpid); ADFH_DEBUG(("ADFH_Move_Child")); if (is_link(hpid) || is_link(hnpid)) { set_error(ADFH_ERR_LINK_MOVE, err); return; } /* check that node is actually child of the parent */ if (H5Gget_objinfo(hid, ".", 0, &stat) < 0 || !H5Giterate(hpid, ".", NULL, compare_children, (void *)&stat)) { set_error(CHILD_NOT_OF_GIVEN_PARENT, err); return; } /* get node name */ if (get_str_att(hid, A_NAME, nodename, err)) return; namelen = (int)strlen(nodename); /* get new node path */ len = H5Iget_name(hnpid, buff, 2); if (len <= 0) { set_error(ADFH_ERR_IGET_NAME, err); return; } newpath = (char *) malloc (len+namelen+2); if (newpath == NULL) { set_error(MEMORY_ALLOCATION_FAILED, err); return; } H5Iget_name(hnpid, newpath, len+1); newpath[len++] = '/'; strcpy(&newpath[len], nodename); #ifdef ADFH_DEBUG_ON printf("%s move [%s]\n",ADFH_PREFIX,nodename); printf("%s to [%s]\n",ADFH_PREFIX,newpath); #endif status = H5Gmove(hpid, nodename, newpath); free(newpath); if (status < 0) { set_error(ADFH_ERR_GMOVE, err); return; } #ifdef ADFH_NO_ORDER set_error(NO_ERROR, err); #else /*update _order attribute for node we just moved*/ ADFH_Number_of_Children(npid, &new_order, err); if (*err != NO_ERROR) return; /*read/write _order attr*/ if (get_int_att(hid, A_ORDER, &old_order, err) || set_int_att(hid, A_ORDER, new_order, err)) return; /*see if we need to decrement any node _orders under the old parent*/ *err = H5Giterate(hpid, ".", NULL, fix_order, (void *)&old_order); if (!*err) set_error(NO_ERROR, err); #endif } /* ----------------------------------------------------------------- */ /* Change the label attribute value */ void ADFH_Set_Label(const double id, const char *label, int *err) { hid_t hid; to_HDF_ID(id, hid); ADFH_DEBUG(("ADFH_Set_Label [%s]",label)); if (label == NULL) { set_error(NULL_STRING_POINTER, err); return; } if (strlen(label) > ADF_NAME_LENGTH) { set_error(STRING_LENGTH_TOO_BIG, err); return; } if (is_link(hid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } set_str_att(hid, A_LABEL, label, err); } /* ----------------------------------------------------------------- */ /* Change attribute name and move the group name to new name */ void ADFH_Put_Name(const double pid, const double id, const char *name, int *err) { hid_t hpid; hid_t hid; char *nname, oname[ADF_NAME_LENGTH+1]; to_HDF_ID(pid,hpid); to_HDF_ID(id,hid); ADFH_DEBUG(("ADFH_Put_Name [%s]",name)); if ((nname = check_name(name, err)) == NULL) return; if (is_link(hpid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } if (has_child(hpid, nname)) { set_error(DUPLICATE_CHILD_NAME, err); return; } if (!get_str_att(hid, A_NAME, oname, err)) { #ifdef ADFH_DEBUG_ON printf("%s change [%s] to [%s]\n",ADFH_PREFIX,oname,nname); #endif if (H5Gmove(hpid, oname, nname) < 0) set_error(ADFH_ERR_GMOVE, err); else set_str_att(hid, A_NAME, nname, err); } } /* ----------------------------------------------------------------- */ /* Retrieve the name attribute value (same as group name) */ void ADFH_Get_Name(const double id, char *name, int *err) { hid_t hid; char buffname[ADF_NAME_LENGTH+1]; to_HDF_ID(id,hid); ADFH_DEBUG((">ADFH_Get_Name")); if (name == NULL) { set_error(NULL_STRING_POINTER, err); return; } get_str_att(hid, A_NAME, buffname, err); strcpy(name,buffname); ADFH_DEBUG(("ADFH_Get_Label [%d]",id)); if (label == NULL) { set_error(NULL_STRING_POINTER, err); return; } if ((hid = open_node(id, err)) >= 0) { get_str_att(hid, A_LABEL, bufflabel, err); if (H5Gclose(hid)<0) { ADFH_DEBUG((">ADFH H5Gclose failed (G)")); } } strcpy(label,bufflabel); ADFH_DEBUG(("ADFH_Create [%s][%d]",name,hpid)); if ((pname = check_name(name, err)) == NULL) return; if (id == NULL) { set_error(NULL_NODEID_POINTER, err); return; } /* if (is_link(hpid)) { set_error(ADFH_ERR_LINK_NODE, err); return; } */ if (has_child(hpid, pname)) { set_error(DUPLICATE_CHILD_NAME, err); return; } *id = 0; gid = H5Gcreate2(hpid, pname, H5P_DEFAULT, mta_root->g_propgroupcreate, H5P_DEFAULT); #ifdef ADFH_DEBUG_ON H5Lget_info(hpid,pname,&lkbuff,H5P_DEFAULT); ADFH_DEBUG((">ADFH_Create [%s] index [%d]",pname,lkbuff.corder)); #endif if (gid < 0) set_error(ADFH_ERR_GCREATE, err); else { #ifdef ADFH_NO_ORDER if (new_str_att(gid, A_NAME, pname, ADF_NAME_LENGTH, err) || new_str_att(gid, A_LABEL, "", ADF_NAME_LENGTH, err) || new_str_att(gid, A_TYPE, ADFH_MT, 2, err) || new_int_att(gid, A_FLAGS, mta_root->g_flags, err)) return; #else int order = 0; H5Giterate(hpid, ".", NULL, count_children, (void *)&order); if (new_str_att(gid, A_NAME, pname, ADF_NAME_LENGTH, err) || new_str_att(gid, A_LABEL, "", ADF_NAME_LENGTH, err) || new_str_att(gid, A_TYPE, ADFH_MT, 2, err) || new_int_att(gid, A_ORDER, order, err) || new_int_att(gid, A_FLAGS, mta_root->g_flags, err)) return; #endif to_ADF_ID(gid,*id); #ifndef ADFH_FORCE_ID_CLOSE track_id(hpid,gid); #endif ADFH_DEBUG(("ADFH_Number_of_Children")); if (number == NULL) { set_error(NULL_POINTER, err); return; } *number = 0; if ((hid = open_node(id, err)) >= 0) { H5Giterate(hid, ".", &gskip, count_children, (void*)number); H5Gclose(hid); } nn=*number; (void)nn; /* avoid unused variable warning */ ADFH_DEBUG(("ADFH_Get_Node_ID [%s][%d]",name,hpid)); if (name == NULL) { set_error(NULL_STRING_POINTER, err); return; } if (id == NULL) { set_error(NULL_NODEID_POINTER, err); return; } *id = 0; set_error(NO_ERROR, err); if (*name == '/') { hid_t rid; char *path = (char *) malloc (strlen(name)+1); if (path == NULL) { set_error(MEMORY_ALLOCATION_FAILED, err); return; } strcpy(path, &name[1]); rid = H5Gopen2(hpid, "/", H5P_DEFAULT); sid = parse_path(rid, path, err); H5Gclose(rid); free(path); } else if (is_link(hpid)) { hid_t lid = open_link(hpid, err); ADFH_DEBUG(("i_start = istart; mta_root->i_len = ilen; mta_root->n_length = name_length; mta_root->n_names = 0; #ifdef ADFH_NO_ORDER mta_root->i_count = 0; #endif /*initialize names to null*/ memset(names, 0, ilen*name_length); if ((hpid = open_node(pid, err)) >= 0) { H5Literate(hpid,H5_INDEX_CRT_ORDER,H5_ITER_INC, NULL,children_names,(void *)names); if (names[0]==0) { H5Literate(hpid,H5_INDEX_NAME,H5_ITER_INC, NULL,children_names,(void *)names); } H5Gclose(hpid); } *ilen_ret = mta_root->n_names; } /* ----------------------------------------------------------------- */ void ADFH_Children_IDs(const double pid, const int istart, const int icount, int *icount_ret, double *IDs, int *err) { hid_t hpid; ADFH_DEBUG(("ADFH_Children_IDs")); ROOT_OR_DIE(err); if (icount_ret == NULL) { set_error(NULL_POINTER, err); return; } if (IDs == NULL) { set_error(NULL_NODEID_POINTER, err); return; } IDs[0]=-1; mta_root->i_start = istart; mta_root->i_len = icount; mta_root->n_names = 0; #ifdef ADFH_NO_ORDER mta_root->i_count = 0; #endif if ((hpid = open_node(pid, err)) >= 0) { H5Literate(hpid,H5_INDEX_CRT_ORDER,H5_ITER_INC, NULL,children_ids,(void *)IDs); if (IDs[0]==-1) { H5Literate(hpid,H5_INDEX_NAME,H5_ITER_INC, NULL,children_ids,(void *)IDs); } H5Gclose(hpid); } *icount_ret = mta_root->n_names; return; } /* ----------------------------------------------------------------- */ void ADFH_Release_ID(const double ID) { hid_t hid; ADFH_DEBUG(("ADFH_Release_ID")); to_HDF_ID(ID, hid); H5Gclose(hid); } /* ----------------------------------------------------------------- */ void ADFH_Database_Open(const char *name, const char *stat, const char *fmt, double *root, int *err) { hid_t fid, gid; char *format, buff[ADF_VERSION_LENGTH+1]; int i, pos, mode; hid_t g_propfileopen; ADFH_DEBUG(("ADFH_Database_Open [%s]",name)); /* to be thread safe, should have critical section here */ if (mta_root==NULL) { mta_root=(ADFH_MTA*)malloc(sizeof(struct _ADFH_MTA)); mta_root->g_init = 0; } mta_root->g_error_state = 0; /* flags is int seen as bitfield, fortran flag is first 0x0001 it is found set to 1 in *all* MLL-based HDF5 files */ mta_root->g_flags = 1; #ifndef ADFH_DEBUG_ON H5Eset_auto2(H5E_DEFAULT, NULL, NULL); #endif if (!mta_root->g_init) { #ifndef ADFH_DEBUG_ON H5Eset_auto2(H5E_DEFAULT, walk_H5_error, NULL); #endif for (i = 0; i < ADFH_MAXIMUM_FILES; i++) mta_root->g_files[i] = 0; mta_root->g_init = 1; /* create properties - these are persistent accross all open files. When all files are closed, then delete properties */ /* H5Pclose performed at file close time */ mta_root->g_proplink=H5Pcreate(H5P_LINK_ACCESS); H5Pset_nlinks(mta_root->g_proplink, ADF_MAXIMUM_LINK_DEPTH); mta_root->g_propgroupcreate=H5Pcreate(H5P_GROUP_CREATE); H5Pset_link_creation_order(mta_root->g_propgroupcreate, H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED); mta_root->g_propdataset=H5Pcreate(H5P_DATASET_CREATE); } if (name == NULL || stat == NULL || fmt == NULL) { set_error(NULL_STRING_POINTER, err); return; } /* get open mode */ strncpy(buff, stat, 9); buff[9] = 0; for (i = 0; buff[i]; i++) buff[i] = TO_UPPER(buff[i]); if (0 == strcmp(buff, "UNKNOWN")) { if (ACCESS(name, 0)) mode = ADFH_MODE_NEW; else if (ACCESS(name, 2)) mode = ADFH_MODE_RDO; else mode = ADFH_MODE_OLD; } else if (0 == strcmp(buff, "NEW")) { if (!ACCESS(name, 0)) { set_error(REQUESTED_NEW_FILE_EXISTS, err); return; } mode = ADFH_MODE_NEW; } else if (0 == strcmp(buff, "READ_ONLY")) { if (ACCESS(name, 0)) { set_error(REQUESTED_OLD_FILE_NOT_FOUND, err); return; } mode = ADFH_MODE_RDO; } else if (0 == strcmp(buff, "OLD")) { if (ACCESS(name, 0)) { set_error(REQUESTED_OLD_FILE_NOT_FOUND, err); return; } mode = ADFH_MODE_OLD; } else { set_error(ADF_FILE_STATUS_NOT_RECOGNIZED, err); return; } /* get format */ #if 0 if (mode == ADFH_MODE_NEW) { strncpy(buff, fmt, 11); buff[11] = 0; for (i = 0; buff[i]; i++) buff[i] = TO_UPPER(buff[i]); if (strcmp(buff, "NATIVE") && strncmp(buff, "IEEE_BIG", 8) && strcmp(buff, "IEEE_LITTLE", 11) && strcmp(buff, "CRAY")) { set_error(ADF_FILE_FORMAT_NOT_RECOGNIZED, err); return; } } #endif /* get unused slot */ for (pos = 0; pos < ADFH_MAXIMUM_FILES; pos++) { if (mta_root->g_files[pos] == 0) break; } if (pos == ADFH_MAXIMUM_FILES) { set_error(TOO_MANY_ADF_FILES_OPENED, err); return; } // Patch from Manuel Gageik on IBM BLUEgene/Q systems for better cgp_open performance. #ifdef JFC_PATCH_2015_2 // http://www.hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_meta_block_size.htm // default setting is 2048 bytes H5Pset_meta_block_size(g_propfileopen, 4096); // 1024*1024 // http://hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_alignment.htm // attention: this can increase filesize dramatically if lots of small datasets H5Pset_alignment(g_propfileopen, 4096, 4096); // http://www.hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_buffer.htm // 1 MByte is default of hdf5 void *tconv; void *bkg; H5Pset_buffer(g_propfileopen, 10*1024*1024,tconv, bkg); // http://hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSieveBufSize // '.. used by file drivers that are capable of using data sieving' // 1 MByte is default of hdf5 H5Pset_sieve_buf_size(g_propfileopen, 4*1024*1024); #endif g_propfileopen = H5Pcreate(H5P_FILE_ACCESS); #ifdef ADFH_H5F_CLOSE_STRONG /* set access property to close all open accesses when file closed */ H5Pset_fclose_degree(g_propfileopen, H5F_CLOSE_STRONG); #endif /* H5Pset_latest_format(fapl, 1); */ /* Performance patch applied by KSH on 2009.05.18 */ H5Pset_libver_bounds(g_propfileopen, #if H5_VERSION_GE(1,10,3) H5F_LIBVER_V18, H5F_LIBVER_V18); #else H5F_LIBVER_LATEST, H5F_LIBVER_LATEST); #endif /* open the file */ #ifdef BUILD_PARALLEL int flag = 0; /* check if we are actually running a parallel program */ MPI_Initialized(&flag); if(flag) { /* Set the access property list to use MPI */ if (0 == strcmp(fmt, "PARALLEL")) { if(!pcg_mpi_info) pcg_mpi_info = MPI_INFO_NULL; #if HDF5_HAVE_COLL_METADATA H5Pset_coll_metadata_write(g_propfileopen, 1); #endif /*HDF5_HAVE_COLL_METADATA*/ H5Pset_fapl_mpio(g_propfileopen, ParallelMPICommunicator, pcg_mpi_info); } } #endif set_error(NO_ERROR, err); if (mode == ADFH_MODE_NEW) { hid_t g_propfilecreate = H5Pcreate(H5P_FILE_CREATE); #ifdef JFC_PATCH_2015_2 // http://www.hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_meta_block_size.htm // default setting is 2048 bytes H5Pset_meta_block_size(g_propfilecreate, 4096); // 1024*1024 // http://hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_alignment.htm // attention: this can increase filesize dramatically if lots of small datasets H5Pset_alignment(g_propfilecreate, 4096, 4096); // http://www.hdfgroup.org/HDF5/doc/RM/H5P/H5Pset_buffer.htm // 1 MByte is default of hdf5 void *tconv; void *bkg; H5Pset_buffer(g_propfilecreate, 10*1024*1024,tconv, bkg); // http://hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSieveBufSize // '.. used by file drivers that are capable of using data sieving' // 1 MByte is default of hdf5 H5Pset_sieve_buf_size(g_propfilecreate, 4*1024*1024); #endif /* add creation time for groups (used by iterators) (prop set to file creation )*/ H5Pset_link_creation_order(g_propfilecreate, H5P_CRT_ORDER_TRACKED | H5P_CRT_ORDER_INDEXED); fid = H5Fcreate(name, H5F_ACC_TRUNC, g_propfilecreate, g_propfileopen); H5Pclose(g_propfilecreate); H5Pclose(g_propfileopen); if (fid < 0) { set_error(FILE_OPEN_ERROR, err); return; } gid = H5Gopen2(fid, "/", H5P_DEFAULT); memset(buff, 0, ADF_VERSION_LENGTH+1); ADFH_Library_Version(buff, err); format = native_format(); if (new_str_att(gid, A_NAME, "HDF5 MotherNode", ADF_NAME_LENGTH, err) || new_str_att(gid, A_LABEL, "Root Node of HDF5 File", ADF_NAME_LENGTH, err) || new_str_att(gid, A_TYPE, ADFH_MT, 2, err) || new_str_data(gid, D_FORMAT, format, (int)strlen(format), err) || new_str_data(gid, D_VERSION, buff, ADF_VERSION_LENGTH, err)) { H5Gclose(gid); return; } } else { if (H5Fis_hdf5(name) <= 0) { H5Pclose(g_propfileopen); set_error(ADFH_ERR_NOT_HDF5_FILE, err); return; } #ifdef BUILD_PARALLEL #if HDF5_HAVE_COLL_METADATA H5Pset_all_coll_metadata_ops( g_propfileopen, 1 ); #endif #endif if (mode == ADFH_MODE_RDO) { fid = H5Fopen(name, H5F_ACC_RDONLY, g_propfileopen); } else { fid = H5Fopen(name, H5F_ACC_RDWR, g_propfileopen); } H5Pclose(g_propfileopen); if (fid < 0) { set_error(FILE_OPEN_ERROR, err); return; } gid = H5Gopen2(fid, "/", H5P_DEFAULT); #ifdef ADFH_FORTRAN_INDEXING if (mode != ADFH_MODE_RDO && has_child(gid, D_OLDVERS)) { H5Giterate(gid, ".", NULL, fix_dimensions, NULL); H5Gmove(gid, D_OLDVERS, D_VERSION); } #endif } mta_root->g_files[pos] = fid; #ifndef ADFH_FORCE_ID_CLOSE mta_root->g_extids[pos]=NULL; mta_root->n_extids[pos]=0; mta_root->x_extids[pos]=-1; track_id(fid,gid); #endif to_ADF_ID(gid, *root); } /* ----------------------------------------------------------------- */ void ADFH_Database_Valid(const char *name, int *err) { if (NULL == name || 0 == *name) *err = NULL_STRING_POINTER; else *err = H5Fis_hdf5(name); } /* ----------------------------------------------------------------- */ void ADFH_Database_Get_Format(const double rootid, char *format, int *err) { char node[ADF_NAME_LENGTH+1]; hid_t did, hid; herr_t status; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Database_Get_Format")); if (format == NULL) { set_error(NULL_STRING_POINTER, err); return; } *format = 0; set_error(NO_ERROR, err); sprintf(node, "/%s", D_FORMAT); to_HDF_ID(rootid,hid); if ((did = H5Dopen2(hid, node, H5P_DEFAULT)) < 0) { set_error(ADFH_ERR_DOPEN, err); return; } #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif status = H5Dread(did, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, xfer_prp, format); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } H5Pclose(fapl); /* close the property list */ #endif H5Dclose(did); if (status < 0) set_error(ADFH_ERR_DREAD, err); } /* ----------------------------------------------------------------- */ void ADFH_Database_Set_Format(const double rootid, const char *format, int *err) { ADFH_DEBUG(("ADFH_Database_Set_Format")); set_error(ADFH_ERR_NOT_IMPLEMENTED, err); } /* ----------------------------------------------------------------- */ void ADFH_Database_Delete(const char *name, int *err) { ADFH_DEBUG(("ADFH_Database_Delete [%s]",name)); if (H5Fis_hdf5(name) <= 0) set_error(ADFH_ERR_NOT_HDF5_FILE, err); else if (UNLINK(name)) set_error(ADFH_ERR_FILE_DELETE, err); else set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Database_Close(const double root, int *status) { int fn,idx; hid_t hid,fid; int nobj,n; #ifdef ADFH_FORCE_ID_CLOSE hid_t *objs; #endif ADFH_DEBUG(("ADFH_Database_Close")); if (mta_root == NULL) { ADFH_DEBUG(("ADFH_Database_Close [mta is null]")); return; } ADFH_DEBUG(("ADFH_Database_Close 4")); to_HDF_ID(root,hid); if ((fn = get_file_number(hid, status)) < 0) return; fid = mta_root->g_files[fn]; mta_root->g_files[fn] = 0; #if !defined(ADFH_H5F_CLOSE_STRONG) && !defined(ADFH_FORCE_ID_CLOSE) /* this gets the file data to disk even if there are open objects */ H5Fflush(fid, H5F_SCOPE_LOCAL); #endif /* free up all open accesses */ #ifndef ADFH_FORCE_ID_CLOSE for (nobj=0;nobjn_extids[fn];nobj++) { ADFH_DEBUG(("ADFH_Database_Close 3 [%.6d/%.6d]:[%d]",\ nobj,mta_root->n_extids[fn],mta_root->g_extids[fn][nobj])); if (H5Iis_valid(mta_root->g_extids[fn][nobj])) { H5Oclose(mta_root->g_extids[fn][nobj]); } } #else ADFH_DEBUG(("ADFH_Database_Close 3")); nobj = H5Fget_obj_count(fid, H5F_OBJ_ALL|H5F_OBJ_LOCAL); if (nobj) { objs = (hid_t *) malloc (nobj * sizeof(hid_t)); /* close datatypes */ nobj = H5Fget_obj_count(fid, H5F_OBJ_DATATYPE|H5F_OBJ_LOCAL); #ifdef ADFH_DEBUG_ON printf("%s close DataType [%d] HIDs\n",ADFH_PREFIX,nobj); #endif if (nobj) { H5Fget_obj_ids(fid, H5F_OBJ_DATATYPE|H5F_OBJ_LOCAL, -1, objs); for (n = 0; n < nobj; n++) H5Tclose(objs[n]); } /* close datasets */ nobj = H5Fget_obj_count(fid, H5F_OBJ_DATASET|H5F_OBJ_LOCAL); #ifdef ADFH_DEBUG_ON printf("%s close DataSet [%d] HIDs\n",ADFH_PREFIX,nobj); #endif if (nobj) { H5Fget_obj_ids(fid, H5F_OBJ_DATASET|H5F_OBJ_LOCAL, -1, objs); for (n = 0; n < nobj; n++) H5Dclose(objs[n]); } /* close attributes */ nobj = H5Fget_obj_count(fid, H5F_OBJ_ATTR|H5F_OBJ_LOCAL); #ifdef ADFH_DEBUG_ON printf("%s close Attr [%d] HIDs\n",ADFH_PREFIX,nobj); #endif if (nobj) { H5Fget_obj_ids(fid, H5F_OBJ_ATTR|H5F_OBJ_LOCAL, -1, objs); for (n = 0; n < nobj; n++) H5Aclose(objs[n]); } /* close groups */ nobj = H5Fget_obj_count(fid, H5F_OBJ_GROUP|H5F_OBJ_LOCAL); #ifdef ADFH_DEBUG_ON printf("%s close Group [%d] HIDs\n",ADFH_PREFIX,nobj); #endif if (nobj) { H5Fget_obj_ids(fid, H5F_OBJ_GROUP|H5F_OBJ_LOCAL, -1, objs); for (n = 0; n < nobj; n++) H5Gclose(objs[n]); } #if 0 /* close file accesses except for current */ nobj = H5Fget_obj_count(fid, H5F_OBJ_FILE|H5F_OBJ_LOCAL); if (nobj) { H5Fget_obj_ids(fid, H5F_OBJ_FILE|H5F_OBJ_LOCAL, -1, objs); for (n = 0; n < nobj; n++) { if (objs[n] != fid) H5Fclose(objs[n]); } } #endif free (objs); } #endif ADFH_DEBUG(("ADFH_Database_Close 2")); /* close file */ if (H5Fclose(fid) < 0) set_error(FILE_CLOSE_ERROR, status); else set_error(NO_ERROR, status); #ifndef ADFH_FORCE_ID_CLOSE free(mta_root->g_extids[fn]); #endif ADFH_DEBUG(("ADFH_Database_Close 1")); idx=0; for (n = 0; n < ADFH_MAXIMUM_FILES; n++) { if (mta_root->g_files[n]) { idx++; } } /* if no more files open, close properties and free MTA */ if (idx == 0) { H5Pclose(mta_root->g_proplink); H5Pclose(mta_root->g_propgroupcreate); H5Pclose(mta_root->g_propdataset); free(mta_root); mta_root=NULL; } ADFH_DEBUG(("ADFH_Database_Close 0")); } /* ----------------------------------------------------------------- */ void ADFH_Is_Link(const double id, int *link_path_length, int *err) { hid_t hid; to_HDF_ID(id,hid); ADFH_DEBUG(("ADFH_Is_Link")); if (is_link(hid)) { hid_t did, sid; hsize_t size; did = H5Dopen2(hid, D_PATH, H5P_DEFAULT); ADFH_CHECK_HID(did); sid = H5Dget_space(did); ADFH_CHECK_HID(sid); size = H5Sget_simple_extent_npoints(sid); H5Sclose(sid); H5Dclose(did); *link_path_length = (int)size; if (has_child(hid, D_FILE)) { did = H5Dopen2(hid, D_FILE, H5P_DEFAULT); ADFH_CHECK_HID(did); sid = H5Dget_space(did); ADFH_CHECK_HID(sid); size = H5Sget_simple_extent_npoints(sid); H5Sclose(sid); H5Dclose(did); *link_path_length += (int)size; } } else *link_path_length = 0; set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Link_Size(const double id, int *file_len, int *name_len, int *err) { hid_t hid; to_HDF_ID(id,hid); ADFH_DEBUG(("ADFH_Link_Size")); *name_len = *file_len = 0; if (is_link(hid)) { hid_t did, sid; hsize_t size; did = H5Dopen2(hid, D_PATH, H5P_DEFAULT); sid = H5Dget_space(did); size = H5Sget_simple_extent_npoints(sid); H5Sclose(sid); H5Dclose(did); *name_len = (int)size; if (has_child(hid, D_FILE)) { did = H5Dopen2(hid, D_FILE, H5P_DEFAULT); sid = H5Dget_space(did); size = H5Sget_simple_extent_npoints(sid); H5Sclose(sid); H5Dclose(did); *file_len = (int)size; } } set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Get_Root_ID(const double id, double *root_id, int *err) { hid_t rid, hid; ADFH_DEBUG(("ADFH_Get_Root_ID")); to_HDF_ID(id, hid); rid = H5Gopen2(hid, "/", H5P_DEFAULT); if (rid < 0) set_error(ADFH_ERR_GOPEN, err); else { to_ADF_ID(rid, *root_id); set_error(NO_ERROR, err); } #ifndef ADFH_FORCE_ID_CLOSE track_id(hid,rid); #endif ADFH_DEBUG(("ADFH_Get_Root_ID root id [%d]",rid)); } /* ----------------------------------------------------------------- */ void ADFH_Get_Data_Type(const double id, char *data_type, int *err) { hid_t hid; char buffdata_type[3]; ADFH_DEBUG(("ADFH_Get_Data_Type")); if ((hid = open_node(id, err)) >= 0) { get_str_att(hid, A_TYPE, buffdata_type, err); H5Gclose(hid); strcpy(data_type,buffdata_type); } } /* ----------------------------------------------------------------- */ void ADFH_Get_Number_of_Dimensions(const double id, int *num_dims, int *err) { hid_t hid, did, sid; char type[3]; ADFH_DEBUG(("ADFH_Get_Number_of_Dimensions")); *num_dims = 0; if ((hid = open_node(id, err)) < 0) return; if (get_str_att(hid, A_TYPE, type, err) || 0 == strcmp(type, ADFH_MT) || 0 == strcmp(type, ADFH_LK)) { H5Gclose(hid); return; } if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) set_error(NO_DATA, err); else { if ((sid = H5Dget_space(did)) < 0) set_error(ADFH_ERR_DGET_SPACE, err); else { *num_dims = H5Sget_simple_extent_ndims(sid); H5Sclose(sid); } H5Dclose(did); } H5Gclose(hid); } /* ----------------------------------------------------------------- */ void ADFH_Get_Dimension_Values(const double id, cgsize_t dim_vals[], int *err) { int i, ndims, swap = 0; hid_t hid, did, sid; hsize_t temp_vals[ADF_MAX_DIMENSIONS]; ADFH_DEBUG(("ADFH_Get_Dimension_Values")); ndims=0; dim_vals[0]=0; if ((hid = open_node(id, err)) < 0) return; if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) set_error(NO_DATA, err); else { if ((sid = H5Dget_space(did)) < 0) set_error(ADFH_ERR_DGET_SPACE, err); else { ndims = H5Sget_simple_extent_ndims(sid); if (ndims > 0) { H5Sget_simple_extent_dims(sid, temp_vals, NULL); #if CG_SIZEOF_SIZE == 32 for (i = 0; i < ndims; i++) { if (temp_vals[i] > CG_MAX_INT32) { set_error(MAX_INT32_SIZE_EXCEEDED, err); break; } } #endif #ifdef ADFH_FORTRAN_INDEXING if (ndims > 1) swap = swap_dimensions(hid); #endif if (swap) { for (i = 0; i < ndims; i++) { dim_vals[i] = (cgsize_t)temp_vals[ndims-1-i]; } } else { for (i = 0; i < ndims; i++) { dim_vals[i] = (cgsize_t)temp_vals[i]; } } } H5Sclose(sid); } H5Dclose(did); } H5Gclose(hid); } /* ----------------------------------------------------------------- */ void ADFH_Put_Dimension_Information(const double id, const char *data_type, const int dims, const cgsize_t dim_vals[], int *err) { hid_t hid; hid_t did, tid, sid, mid; int i, swap = 0; hsize_t old_size; hsize_t old_dims[ADF_MAX_DIMENSIONS]; hsize_t new_dims[ADF_MAX_DIMENSIONS]; char new_type[3]; hid_t xfer_prp = H5P_DEFAULT; to_HDF_ID(id,hid); ADFH_DEBUG(("ADFH_Put_Dimension_Information [%d]",hid)); if (is_link(hid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } for (i = 0; i < 2; i++) new_type[i] = TO_UPPER(data_type[i]); new_type[2] = 0; if (0 == strcmp(new_type, ADFH_MT)) { if (has_data(hid)) H5Gunlink(hid, D_DATA); set_str_att(hid, A_TYPE, new_type, err); return; } if (check_data_type(new_type, err)) return; if (dims < 1 || dims > ADF_MAX_DIMENSIONS) { set_error(BAD_NUMBER_OF_DIMENSIONS, err); return; } for (i = 0; i < dims; i++) { if (dim_vals[i] < 1) { set_error(BAD_DIMENSION_VALUE, err); return; } } /* * The ADF documentation allows the dimension values to be changed * without affecting the data, so long as the data type and number * of dimensions are the same. With HDF5, we could emulate that by * using extendable data spaces (with chunking). However this only * allows the data size to increase, not decrease, and coming up * with a good value for chunking is difficult. Since changing the * dimension values without rewriting the data is not a common * operation, I decided to use fixed sizes, then buffer the data * in these rare cases. */ old_size = 0; if(has_data(hid)) { ADFH_DEBUG(("ADFH_Put_Dimension_Information unlink [%d]",hid)); H5Gunlink(hid, D_DATA); } if (set_str_att(hid, A_TYPE, new_type, err)) { return; } /* recreate the data space with the new values */ #ifdef ADFH_FORTRAN_INDEXING if (dims > 1) swap = swap_dimensions(hid); #endif if (swap) { for (i = 0; i < dims; i++) new_dims[i] = (hsize_t)dim_vals[dims-1-i]; } else { for (i = 0; i < dims; i++) new_dims[i] = (hsize_t)dim_vals[i]; } tid = to_HDF_data_type(new_type); ADFH_CHECK_HID(tid); sid = H5Screate_simple(dims, new_dims, NULL); /* better idea? how to guess the right size? */ if (CompressData >= 0) { H5Pset_deflate(mta_root->g_propdataset, CompressData); } #if 0 this causes a problem with memory allocation. For example, writing an unstructured coordinate array of 5 billion values will result in the HDF5 library trying to allocation 20Gb of memory for the chunk, since the first dimension is 5 billion. We really need to try to do something more intelligent here H5Pset_chunk(mta_root->g_propdataset, dims, new_dims); #endif ADFH_CHECK_HID(sid); did = H5Dcreate2(hid, D_DATA, tid, sid, H5P_DEFAULT, mta_root->g_propdataset, H5P_DEFAULT); /* H5Eprint1(stdout);*/ ADFH_CHECK_HID(did); H5Sclose(sid); H5Tclose(tid); if (did < 0) set_error(ADFH_ERR_DCREATE, err); else { H5Dclose(did); set_error(NO_ERROR, err); } } /* ----------------------------------------------------------------- */ void ADFH_Get_Link_Path(const double id, char *filename, char *link_path, int *err) { hid_t hid, did; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Get_Link_Path")); to_HDF_ID(id,hid); ADFH_CHECK_HID(hid); if (!is_link(hid)) { set_error(NODE_IS_NOT_A_LINK, err); return; } #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif did = H5Dopen2(hid, D_PATH, H5P_DEFAULT); ADFH_CHECK_HID(did); H5Dread(did, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, xfer_prp, link_path); H5Dclose(did); if (has_child(hid, D_FILE)) { did = H5Dopen2(hid, D_FILE, H5P_DEFAULT); ADFH_CHECK_HID(did); H5Dread(did, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, xfer_prp, filename); H5Dclose(did); } else { *filename = 0; } #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { H5Pclose(xfer_prp); } #endif set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Link(const double pid, const char *name, const char *file, const char *name_in_file, double *id, int *err) { char *target; herr_t status; hid_t lid, hid; (void)hid; /* avoid unused variable warning */ ADFH_DEBUG(("ADFH_Link [%s][%s][%s]",name,file,name_in_file)); ROOT_OR_DIE(err); ADFH_Create(pid, name, id, err); if (*err != NO_ERROR) return; to_HDF_ID(*id,lid); ADFH_CHECK_HID(lid); if (set_str_att(lid, A_TYPE, ADFH_LK, err)) return; /* * If this is a link to a file, then need to create external link * Otherwise, create a soft link */ if (*file) { /* actual link is in the D_LINK group to avoid collision with "real" node because we cannot have a node ID and a link on this ID (can we?) set actual link to D_LINK name (not the current node) */ H5Lcreate_external(file, name_in_file, lid, D_LINK, H5P_DEFAULT, mta_root->g_proplink); } else { target = (char *) malloc (strlen(name_in_file)+2); if (target == NULL) { set_error(MEMORY_ALLOCATION_FAILED, err); return; } if (*name_in_file == '/') strcpy(target, name_in_file); else sprintf(target, "/%s", name_in_file); /* create a soft link */ status = H5Glink(lid, H5G_LINK_SOFT, target, D_LINK); free(target); if (status < 0) { set_error(ADFH_ERR_GLINK, err); return; } } /* save link path and file */ if (new_str_data(lid,D_PATH,name_in_file,(int)strlen(name_in_file),err)) return; if (*file && new_str_data(lid,D_FILE,file,(int)strlen(file),err)) return; #ifndef ADFH_FORCE_ID_CLOSE to_HDF_ID(pid,hid); track_id(hid,lid); #endif set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Flush_to_Disk(const double id, int *err) { hid_t hid; ADFH_DEBUG(("ADFH_Flush_to_Disk")); to_HDF_ID(id,hid); if(H5Fflush(hid, H5F_SCOPE_LOCAL) >=0 ) set_error(NO_ERROR, err); else set_error(FFLUSH_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Database_Garbage_Collection(const double id, int *err) { ADFH_DEBUG(("ADFH_Database_Garbage_Collection")); if(H5garbage_collect() >= 0) set_error(NO_ERROR, err); else set_error(NO_DATA, err); } /* ----------------------------------------------------------------- */ void ADFH_Database_Version(const double root_id, char *version, char *creation_date, char *modification_date, int *err) { char buff[ADF_VERSION_LENGTH+1]; char node[ADF_NAME_LENGTH+1]; hid_t hid, did; herr_t status; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Database_Version")); if (version == NULL) { set_error(NULL_STRING_POINTER, err); return; } *version = 0; if (creation_date != NULL) *creation_date = 0; if (modification_date != NULL) *modification_date = 0; set_error(NO_ERROR, err); sprintf(node, "/%s", D_VERSION); to_HDF_ID(root_id,hid); if ((did = H5Dopen2(hid, node, H5P_DEFAULT)) < 0) { #ifdef ADFH_FORTRAN_INDEXING sprintf(node, "/%s", D_OLDVERS); if ((did = H5Dopen2(hid, node, H5P_DEFAULT)) < 0) { set_error(ADFH_ERR_DOPEN, err); return; } #else set_error(ADFH_ERR_DOPEN, err); return; #endif } #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif status = H5Dread(did, H5T_NATIVE_CHAR, H5S_ALL, H5S_ALL, xfer_prp, buff); H5Dclose(did); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } #endif if (status < 0) set_error(ADFH_ERR_DREAD, err); else strcpy(version, buff); } /* ----------------------------------------------------------------- */ void ADFH_Library_Version(char *version, int *err) { unsigned maj, min, rel; ADFH_DEBUG(("ADFH_Library_Version")); if (version == NULL) { set_error(NULL_STRING_POINTER, err); return; } H5get_libversion(&maj, &min, &rel); sprintf(version, "HDF5 Version %d.%d.%d", maj, min, rel); set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Set_Error_State(const int error_state, int *error_return) { ADFH_DEBUG(("ADFH_Set_Error_State")); ROOT_OR_DIE(error_return); mta_root->g_error_state = error_state; set_error(NO_ERROR, error_return); } /* ----------------------------------------------------------------- */ void ADFH_Error_Message(const int error_return_input, char *error_string ) { int i; ADFH_DEBUG(("ADFH_Error_Message")); if (error_string == NULL) return; for (i = 0; i < NUM_ERRORS; i++) { if (ErrorList[i].errcode == error_return_input) { strcpy(error_string, ErrorList[i].errmsg); return; } } sprintf(error_string, "error number %d", error_return_input); } /* ----------------------------------------------------------------- */ void ADFH_Get_Error_State(int *error_state, int *error_return) { ADFH_DEBUG(("ADFH_Get_Error_State")); ROOT_OR_DIE(error_return); *error_state = mta_root->g_error_state; set_error(NO_ERROR, error_return); } /* ----------------------------------------------------------------- */ void ADFH_Read_Block_Data(const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *err ) { hid_t hid, did, mid, tid, dspace; size_t size, count, offset; char *buff; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Read_Block_Data")); if (data == NULL) { set_error(NULL_POINTER, err); return; } if (b_start > b_end) { set_error(MINIMUM_GT_MAXIMUM, err); return; } if (b_start < 1) { set_error(START_OUT_OF_DEFINED_RANGE, err); return; } if ((hid = open_node(ID, err)) < 0) return; if (!has_data(hid)) { H5Gclose(hid); set_error(NO_DATA, err); return; } if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) { H5Gclose(hid); set_error(ADFH_ERR_DOPEN, err); return; } dspace = H5Dget_space(did); ADFH_CHECK_HID(dspace); count = (size_t)H5Sget_simple_extent_npoints(dspace); H5Sclose(dspace); if ((size_t)b_end > count) { H5Dclose(did); H5Gclose(hid); set_error(END_OUT_OF_DEFINED_RANGE, err); return; } /* instead of trying to compute data space extents from * b_start and b_end, just read all the data into a * 1-d array and copy the range we want */ tid = H5Dget_type(did); ADFH_CHECK_HID(tid); mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); ADFH_CHECK_HID(mid); size = H5Tget_size(mid); if ((buff = (char *) malloc (size * count)) == NULL) { H5Tclose(mid); H5Tclose(tid); H5Dclose(did); H5Gclose(hid); set_error(MEMORY_ALLOCATION_FAILED, err); return; } #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif if (H5Dread(did, mid, H5S_ALL, H5S_ALL, xfer_prp, buff) < 0) set_error(ADFH_ERR_DREAD, err); else { offset = size * (size_t)(b_start - 1); count = size * (size_t)(b_end - b_start + 1); memcpy(data, &buff[offset], count); set_error(NO_ERROR, err); } free (buff); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } #endif H5Tclose(mid); H5Tclose(tid); H5Dclose(did); H5Gclose(hid); } /* ----------------------------------------------------------------- */ void ADFH_Read_Data(const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const char *m_data_type, const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], char *data, int *err ) { int n, ndim; hid_t hid, did, mid, tid, dspace, mspace; hsize_t dims[ADF_MAX_DIMENSIONS]; hsize_t start[ADF_MAX_DIMENSIONS]; hsize_t stride[ADF_MAX_DIMENSIONS]; hsize_t count[ADF_MAX_DIMENSIONS]; herr_t status; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Read_Data")); if ((hid = open_node(ID, err)) < 0) return; if (!has_data(hid)) { H5Gclose(hid); set_error(NO_DATA, err); return; } if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) { H5Gclose(hid); set_error(ADFH_ERR_DOPEN, err); return; } /* get data space extents */ dspace = H5Dget_space(did); ADFH_CHECK_HID(dspace); ndim = H5Sget_simple_extent_ndims(dspace); H5Sget_simple_extent_dims(dspace, dims, NULL); /* create data hyperslab */ #ifdef ADFH_FORTRAN_INDEXING if (ndim > 1 && !swap_dimensions(hid)) { H5Sclose(dspace); H5Dclose(did); H5Gclose(hid); set_error(ADFH_ERR_NEED_TRANSPOSE, err); return; } #endif for (n = 0; n < ndim; n++) { if (s_start[n] < 1) set_error(START_OUT_OF_DEFINED_RANGE, err); #ifdef ADFH_FORTRAN_INDEXING else if ((hsize_t)s_end[n] > dims[ndim-1-n]) #else else if ((hsize_t)s_end[n] > dims[n]) #endif set_error(END_OUT_OF_DEFINED_RANGE, err); else if (s_start[n] > s_end[n]) set_error(MINIMUM_GT_MAXIMUM, err); else if (s_stride[n] < 1 || s_stride[n] > (s_end[n] - s_start[n] + 1)) set_error(BAD_STRIDE_VALUE, err); else set_error(NO_ERROR, err); if (*err != NO_ERROR) { H5Sclose(dspace); H5Dclose(did); H5Gclose(hid); return; } #ifdef ADFH_FORTRAN_INDEXING start[ndim-1-n] = s_start[n] - 1; stride[ndim-1-n] = s_stride[n]; count[ndim-1-n] = (s_end[n] - s_start[n] + 1) / s_stride[n]; #else start[n] = s_start[n] - 1; stride[n] = s_stride[n]; count[n] = (s_end[n] - s_start[n] + 1) / s_stride[n]; #endif } H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, stride, count, NULL); /* create memory hyperslab */ for (n = 0; n < m_num_dims; n++) { if (m_start[n] < 1) set_error(START_OUT_OF_DEFINED_RANGE, err); else if (m_end[n] > m_dims[n]) set_error(END_OUT_OF_DEFINED_RANGE, err); else if (m_start[n] > m_end[n]) set_error(MINIMUM_GT_MAXIMUM, err); else if (m_stride[n] < 1 || m_stride[n] > (m_end[n] - m_start[n] + 1)) set_error(BAD_STRIDE_VALUE, err); else set_error(NO_ERROR, err); if (*err != NO_ERROR) { H5Sclose(dspace); H5Dclose(did); H5Gclose(hid); return; } #ifdef ADFH_FORTRAN_INDEXING dims[m_num_dims-1-n] = m_dims[n]; start[m_num_dims-1-n] = m_start[n] - 1; stride[m_num_dims-1-n] = m_stride[n]; count[m_num_dims-1-n] = (m_end[n] - m_start[n] + 1) / m_stride[n]; #else dims[n] = m_dims[n]; start[n] = m_start[n] - 1; stride[n] = m_stride[n]; count[n] = (m_end[n] - m_start[n] + 1) / m_stride[n]; #endif } mspace = H5Screate_simple(m_num_dims, dims, NULL); ADFH_CHECK_HID(mspace); H5Sselect_hyperslab(mspace, H5S_SELECT_SET, start, stride, count, NULL); if (H5Sget_select_npoints(mspace) != H5Sget_select_npoints(dspace)) { H5Sclose(mspace); H5Sclose(dspace); H5Dclose(did); H5Gclose(hid); set_error(UNEQUAL_MEMORY_AND_DISK_DIMS, err); return; } /* read the data */ tid = H5Dget_type(did); ADFH_CHECK_HID(tid); if (m_data_type) { mid = to_HDF_data_type(m_data_type); } else { mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); } ADFH_CHECK_HID(mid); #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, default_pio_mode); } #endif status = H5Dread(did, mid, mspace, dspace, xfer_prp, data); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } #endif H5Sclose(mspace); H5Sclose(dspace); H5Tclose(mid); H5Tclose(tid); H5Dclose(did); H5Gclose(hid); if (status < 0) set_error(ADFH_ERR_DREAD, err); else set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Read_All_Data(const double id, const char *m_data_type, char *data, int *err) { hid_t hid, did, tid, mid; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Read_All_Data")); if ((hid = open_node(id, err)) < 0) return; if (has_data(hid)) { did = H5Dopen2(hid, D_DATA, H5P_DEFAULT); ADFH_CHECK_HID(did); tid = H5Dget_type(did); ADFH_CHECK_HID(tid); if (m_data_type) { mid = to_HDF_data_type(m_data_type); } else { mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); } ADFH_CHECK_HID(mid); #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif if (H5Dread(did, mid, H5S_ALL, H5S_ALL, xfer_prp, data) < 0) set_error(ADFH_ERR_DREAD, err); else set_error(NO_ERROR, err); #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { H5Pclose(xfer_prp); } #endif H5Tclose(mid); H5Tclose(tid); H5Dclose(did); } else set_error(NO_DATA, err); H5Gclose(hid); } /* ----------------------------------------------------------------- */ void ADFH_Write_Block_Data(const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *err ) { hid_t hid, did, mid, tid, dspace; size_t size, count, offset; char *buff; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Write_Block_Data")); if (data == NULL) { set_error(NULL_POINTER, err); return; } if (b_start > b_end) { set_error(MINIMUM_GT_MAXIMUM, err); return; } if (b_start < 1) { set_error(START_OUT_OF_DEFINED_RANGE, err); return; } to_HDF_ID(ID,hid); if (is_link(hid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } if (!has_data(hid)) { set_error(NO_DATA, err); return; } if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) { set_error(ADFH_ERR_DOPEN, err); return; } dspace = H5Dget_space(did); ADFH_CHECK_HID(dspace); count = (size_t)H5Sget_simple_extent_npoints(dspace); H5Sclose(dspace); if ((size_t)b_end > count) { H5Dclose(did); set_error(END_OUT_OF_DEFINED_RANGE, err); return; } /* instead of trying to compute data space extents from * b_start and b_end, just read all the data into a * 1-d array, copy the range we want and rewrite the data */ ADFH_CHECK_HID(did); tid = H5Dget_type(did); ADFH_CHECK_HID(tid); mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); ADFH_CHECK_HID(mid); size = H5Tget_size(mid); if ((buff = (char *) malloc (size * count)) == NULL) { H5Tclose(mid); H5Tclose(tid); H5Dclose(did); set_error(MEMORY_ALLOCATION_FAILED, err); return; } #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE); } #endif if (H5Dread(did, mid, H5S_ALL, H5S_ALL, xfer_prp, buff) < 0) set_error(ADFH_ERR_DREAD, err); else { offset = size * (size_t)(b_start - 1); count = size * (size_t)(b_end - b_start + 1); memcpy(&buff[offset], data, count); if (H5Dwrite(did, mid, H5S_ALL, H5S_ALL, xfer_prp, buff) < 0) set_error(ADFH_ERR_DWRITE, err); else set_error(NO_ERROR, err); } free (buff); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } #endif H5Tclose(mid); H5Tclose(tid); H5Dclose(did); } /* ----------------------------------------------------------------- */ void ADFH_Write_Data(const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const char *m_data_type, const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], const char *data, int *err ) { int n, ndim; hid_t hid, did, mid, tid, dspace, mspace; hsize_t dims[ADF_MAX_DIMENSIONS]; hsize_t start[ADF_MAX_DIMENSIONS]; hsize_t stride[ADF_MAX_DIMENSIONS]; hsize_t count[ADF_MAX_DIMENSIONS]; herr_t status; hid_t xfer_prp = H5P_DEFAULT; ADFH_DEBUG(("ADFH_Write_Data")); if (data == NULL) { set_error(NULL_POINTER, err); return; } to_HDF_ID(ID,hid); if (is_link(hid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } if (!has_data(hid)) { set_error(NO_DATA, err); return; } if ((did = H5Dopen2(hid, D_DATA, H5P_DEFAULT)) < 0) { set_error(ADFH_ERR_DOPEN, err); return; } /* get data space extents */ dspace = H5Dget_space(did); ADFH_CHECK_HID(dspace); ndim = H5Sget_simple_extent_ndims(dspace); H5Sget_simple_extent_dims(dspace, dims, NULL); /* create data hyperslab */ #ifdef ADFH_FORTRAN_INDEXING if (ndim > 1 && !swap_dimensions(hid)) { H5Sclose(dspace); H5Dclose(did); set_error(ADFH_ERR_NEED_TRANSPOSE, err); return; } #endif for (n = 0; n < ndim; n++) { if (s_start[n] < 1) set_error(START_OUT_OF_DEFINED_RANGE, err); #ifdef ADFH_FORTRAN_INDEXING else if ((hsize_t)s_end[n] > dims[ndim-1-n]) #else else if ((hsize_t)s_end[n] > dims[n]) #endif set_error(END_OUT_OF_DEFINED_RANGE, err); else if (s_start[n] > s_end[n]) set_error(MINIMUM_GT_MAXIMUM, err); else if (s_stride[n] < 1 || s_stride[n] > (s_end[n] - s_start[n] + 1)) set_error(BAD_STRIDE_VALUE, err); else set_error(NO_ERROR, err); if (*err != NO_ERROR) { H5Sclose(dspace); H5Dclose(did); return; } #ifdef ADFH_FORTRAN_INDEXING start[ndim-1-n] = s_start[n] - 1; stride[ndim-1-n] = s_stride[n]; count[ndim-1-n] = (s_end[n] - s_start[n] + 1) / s_stride[n]; #else start[n] = s_start[n] - 1; stride[n] = s_stride[n]; count[n] = (s_end[n] - s_start[n] + 1) / s_stride[n]; #endif } H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, stride, count, NULL); /* create memory hyperslab */ for (n = 0; n < m_num_dims; n++) { if (m_start[n] < 1) set_error(START_OUT_OF_DEFINED_RANGE, err); else if (m_end[n] > m_dims[n]) set_error(END_OUT_OF_DEFINED_RANGE, err); else if (m_start[n] > m_end[n]) set_error(MINIMUM_GT_MAXIMUM, err); else if (m_stride[n] < 1 || m_stride[n] > (m_end[n] - m_start[n] + 1)) set_error(BAD_STRIDE_VALUE, err); else set_error(NO_ERROR, err); if (*err != NO_ERROR) { H5Sclose(dspace); H5Dclose(did); return; } #ifdef ADFH_FORTRAN_INDEXING dims[m_num_dims-1-n] = m_dims[n]; start[m_num_dims-1-n] = m_start[n] - 1; stride[m_num_dims-1-n] = m_stride[n]; count[m_num_dims-1-n] = (m_end[n] - m_start[n] + 1) / m_stride[n]; #else dims[n] = m_dims[n]; start[n] = m_start[n] - 1; stride[n] = m_stride[n]; count[n] = (m_end[n] - m_start[n] + 1) / m_stride[n]; #endif } mspace = H5Screate_simple(m_num_dims, dims, NULL); ADFH_CHECK_HID(mspace); H5Sselect_hyperslab(mspace, H5S_SELECT_SET, start, stride, count, NULL); if (H5Sget_select_npoints(mspace) != H5Sget_select_npoints(dspace)) { H5Sclose(mspace); H5Sclose(dspace); H5Dclose(did); set_error(UNEQUAL_MEMORY_AND_DISK_DIMS, err); return; } /* write the data */ ADFH_CHECK_HID(did); tid = H5Dget_type(did); ADFH_CHECK_HID(tid); if (m_data_type) { mid = to_HDF_data_type(m_data_type); } else { mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); } ADFH_CHECK_HID(mid); #ifdef BUILD_PARALLEL hid_t fid = get_file_id(hid); hid_t fapl=H5Fget_access_plist(fid); if (H5Pget_driver(fapl) == H5FD_MPIO) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); H5Pset_dxpl_mpio(xfer_prp, default_pio_mode); } #endif status = H5Dwrite(did, mid, mspace, dspace, xfer_prp, data); #ifdef BUILD_PARALLEL if (H5Pget_driver(fapl) == H5FD_MPIO) { H5Pclose(xfer_prp); } #endif H5Sclose(mspace); H5Sclose(dspace); H5Tclose(mid); H5Tclose(tid); H5Dclose(did); if (status < 0) set_error(ADFH_ERR_DWRITE, err); else set_error(NO_ERROR, err); } /* ----------------------------------------------------------------- */ void ADFH_Write_All_Data(const double id, const char *m_data_type, const char *data, int *err) { hid_t hid; hid_t did, tid, mid; hid_t xfer_prp = H5P_DEFAULT; to_HDF_ID(id, hid); ADFH_DEBUG(("ADFH_Write_All_Data")); if (data == NULL) { set_error(NULL_POINTER, err); return; } if (is_link(hid)) { set_error(ADFH_ERR_LINK_DATA, err); return; } if (has_data(hid)) { ADFH_CHECK_HID(hid); did = H5Dopen2(hid, D_DATA, H5P_DEFAULT); ADFH_CHECK_HID(did); tid = H5Dget_type(did); ADFH_CHECK_HID(tid); if (m_data_type) { mid = to_HDF_data_type(m_data_type); } else { mid = H5Tget_native_type(tid, H5T_DIR_ASCEND); } ADFH_CHECK_HID(mid); #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { xfer_prp = H5Pcreate(H5P_DATASET_XFER); ADFH_CHECK_HID(xfer_prp); if (H5Pset_dxpl_mpio(xfer_prp, H5FD_MPIO_COLLECTIVE) < 0) set_error(ADFH_ERR_DWRITE, err); } #endif if (H5Dwrite(did, mid, H5S_ALL, H5S_ALL, xfer_prp, data) < 0) set_error(ADFH_ERR_DWRITE, err); else set_error(NO_ERROR, err); #ifdef BUILD_PARALLEL if (pcg_mpi_initialized) { H5Pclose(xfer_prp); } #endif H5Tclose(mid); H5Tclose(tid); H5Dclose(did); } else set_error(NO_DATA, err); } CGNS-3.4.0/src/adfh/ADFH.h000066400000000000000000000275441343724673500146460ustar00rootroot00000000000000/* ------------------------------------------------------------------------- * * CGNS - CFD General Notation System (http://www.cgns.org) * * CGNS/MLL - Mid-Level Library header file * * Please see cgnsconfig.h file for this local installation configuration * * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. * ------------------------------------------------------------------------- */ /*------------------------------------------------------------------- * include file for the HDF5 replacement to ADF *-------------------------------------------------------------------*/ #ifndef _ADFH_H_ #define _ADFH_H_ #include "cgnstypes.h" /* some stuff needed from standard ADF.h */ #ifndef ADF_INCLUDE #define ADF_DATA_TYPE_LENGTH 32 #define ADF_DATE_LENGTH 32 #define ADF_FILENAME_LENGTH 1024 #define ADF_FORMAT_LENGTH 20 #define ADF_LABEL_LENGTH 32 #define ADF_MAXIMUM_LINK_DEPTH 100 #define ADF_MAX_DIMENSIONS 12 #define ADF_MAX_ERROR_STR_LENGTH 80 #define ADF_MAX_LINK_DATA_SIZE 4096 #define ADF_NAME_LENGTH 32 #define ADF_STATUS_LENGTH 32 #define ADF_VERSION_LENGTH 32 #define NO_ERROR -1 #define NUMBER_LESS_THAN_MINIMUM 1 #define NUMBER_GREATER_THAN_MAXIMUM 2 #define STRING_LENGTH_ZERO 3 #define STRING_LENGTH_TOO_BIG 4 #define STRING_NOT_A_HEX_STRING 5 #define TOO_MANY_ADF_FILES_OPENED 6 #define ADF_FILE_STATUS_NOT_RECOGNIZED 7 #define FILE_OPEN_ERROR 8 #define ADF_FILE_NOT_OPENED 9 #define FILE_INDEX_OUT_OF_RANGE 10 #define BLOCK_OFFSET_OUT_OF_RANGE 11 #define NULL_STRING_POINTER 12 #define FSEEK_ERROR 13 #define FWRITE_ERROR 14 #define FREAD_ERROR 15 #define ADF_MEMORY_TAG_ERROR 16 #define ADF_DISK_TAG_ERROR 17 #define REQUESTED_NEW_FILE_EXISTS 18 #define ADF_FILE_FORMAT_NOT_RECOGNIZED 19 #define FREE_OF_ROOT_NODE 20 #define FREE_OF_FREE_CHUNK_TABLE 21 #define REQUESTED_OLD_FILE_NOT_FOUND 22 #define UNIMPLEMENTED_CODE 23 #define SUB_NODE_TABLE_ENTRIES_BAD 24 #define MEMORY_ALLOCATION_FAILED 25 #define DUPLICATE_CHILD_NAME 26 #define ZERO_DIMENSIONS 27 #define BAD_NUMBER_OF_DIMENSIONS 28 #define CHILD_NOT_OF_GIVEN_PARENT 29 #define DATA_TYPE_TOO_LONG 30 #define INVALID_DATA_TYPE 31 #define NULL_POINTER 32 #define NO_DATA 33 #define ERROR_ZEROING_OUT_MEMORY 34 #define REQUESTED_DATA_TOO_LONG 35 #define END_OUT_OF_DEFINED_RANGE 36 #define BAD_STRIDE_VALUE 37 #define MINIMUM_GT_MAXIMUM 38 #define MACHINE_FORMAT_NOT_RECOGNIZED 39 #define CANNOT_CONVERT_NATIVE_FORMAT 40 #define CONVERSION_FORMATS_EQUAL 41 #define DATA_TYPE_NOT_SUPPORTED 42 #define FILE_CLOSE_ERROR 43 #define NUMERIC_OVERFLOW 44 #define START_OUT_OF_DEFINED_RANGE 45 #define ZERO_LENGTH_VALUE 46 #define BAD_DIMENSION_VALUE 47 #define BAD_ERROR_STATE 48 #define UNEQUAL_MEMORY_AND_DISK_DIMS 49 #define LINKS_TOO_DEEP 50 #define NODE_IS_NOT_A_LINK 51 #define LINK_TARGET_NOT_THERE 52 #define LINKED_TO_FILE_NOT_THERE 53 #define NODE_ID_ZERO 54 #define INCOMPLETE_DATA 55 #define INVALID_NODE_NAME 56 #define INVALID_VERSION 57 #define NODES_NOT_IN_SAME_FILE 58 #define PRISTK_NOT_FOUND 59 #define MACHINE_FILE_INCOMPATABLE 60 #define FFLUSH_ERROR 61 #define NULL_NODEID_POINTER 62 #define MAX_FILE_SIZE_EXCEEDED 63 #define MAX_INT32_SIZE_EXCEEDED 64 #endif /* ADF_INCLUDE */ /* end of ADF.h portion */ #define ADFH_ERR_GLINK 70 #define ADFH_ERR_NO_ATT 71 #define ADFH_ERR_AOPEN 72 #define ADFH_ERR_IGET_NAME 73 #define ADFH_ERR_GMOVE 74 #define ADFH_ERR_GUNLINK 75 #define ADFH_ERR_GOPEN 76 #define ADFH_ERR_DGET_SPACE 77 #define ADFH_ERR_DOPEN 78 #define ADFH_ERR_DEXTEND 79 #define ADFH_ERR_DCREATE 80 #define ADFH_ERR_SCREATE_SIMPLE 81 #define ADFH_ERR_ACREATE 82 #define ADFH_ERR_GCREATE 83 #define ADFH_ERR_DWRITE 84 #define ADFH_ERR_DREAD 85 #define ADFH_ERR_AWRITE 86 #define ADFH_ERR_AREAD 87 #define ADFH_ERR_FMOUNT 88 #define ADFH_ERR_LINK_MOVE 89 #define ADFH_ERR_LINK_DATA 90 #define ADFH_ERR_LINK_NODE 91 #define ADFH_ERR_LINK_DELETE 92 #define ADFH_ERR_NOT_HDF5_FILE 93 #define ADFH_ERR_FILE_DELETE 94 #define ADFH_ERR_FILE_INDEX 95 #define ADFH_ERR_TCOPY 96 #define ADFH_ERR_AGET_TYPE 97 #define ADFH_ERR_TSET_SIZE 98 #define ADFH_ERR_NOT_IMPLEMENTED 99 #define ADFH_ERR_NOTXLINK 100 #define ADFH_ERR_LIBREG 101 #define ADFH_ERR_OBJINFO_FAILED 102 #define ADFH_ERR_XLINK_NOVAL 103 #define ADFH_ERR_XLINK_UNPACK 104 #define ADFH_ERR_GCLOSE_LABEL 105 #define ADFH_ERR_ROOTNULL 106 #define ADFH_ERR_NEED_TRANSPOSE 107 #define ADFH_ERR_INVALID_OPTION 108 #define ADFH_ERR_INVALID_USER_DATA 109 #define ADFH_ERR_SENTINEL 999 /* configuration options */ #define ADFH_CONFIG_COMPRESS 1 #define ADFH_CONFIG_MPI_COMM 2 /*********************************************************************** Prototypes for Interface Routines ***********************************************************************/ #if defined(_WIN32) && defined(BUILD_DLL) # define EXTERN extern __declspec(dllexport) #else # define EXTERN extern #endif #if defined (__cplusplus) extern "C" { #endif EXTERN void ADFH_Configure( const int option, const void *value, int *error_return ) ; EXTERN void ADFH_Children_Names( const double PID, const int istart, const int ilen, const int name_length, int *ilen_ret, char *names, int *error_return ) ; EXTERN void ADFH_Children_IDs( const double PID, const int istart, const int ilen, int *ilen_ret, double *IDs, int *error_return ) ; EXTERN void ADFH_Create( const double PID, const char *name, double *ID, int *error_return ) ; EXTERN void ADFH_Database_Close( const double ID, int *error_return ) ; EXTERN void ADFH_Database_Delete( const char *filename, int *error_return ) ; EXTERN void ADFH_Database_Garbage_Collection( const double ID, int *error_return ) ; EXTERN void ADFH_Database_Get_Format( const double Root_ID, char *format, int *error_return ) ; EXTERN void ADFH_Database_Open( const char *filename, const char *status, const char *format, double *root_ID, int *error_return ) ; EXTERN void ADFH_Database_Valid( const char *filename, int *error_return ) ; EXTERN void ADFH_Database_Set_Format( const double Root_ID, const char *format, int *error_return ) ; EXTERN void ADFH_Database_Version( const double Root_ID, char *version, char *creation_date, char *modification_date, int *error_return ) ; EXTERN void ADFH_Delete( const double PID, const double ID, int *error_return ) ; EXTERN void ADFH_Error_Message( const int error_return_input, char *error_string ) ; EXTERN void ADFH_Flush_to_Disk( const double ID, int *error_return ) ; EXTERN void ADFH_Get_Data_Type( const double ID, char *data_type, int *error_return ) ; EXTERN void ADFH_Get_Dimension_Values( const double ID, cgsize_t dim_vals[], int *error_return ) ; EXTERN void ADFH_Get_Error_State( int *error_state, int *error_return ) ; EXTERN void ADFH_Get_Label( const double ID, char *label, int *error_return ) ; EXTERN void ADFH_Get_Link_Path( const double ID, char *filename, char *link_path, int *error_return ) ; EXTERN void ADFH_Get_Name( const double ID, char *name, int *error_return ) ; EXTERN void ADFH_Get_Node_ID( const double PID, const char *name, double *ID, int *error_return ) ; EXTERN void ADFH_Get_Number_of_Dimensions( const double ID, int *num_dims, int *error_return ) ; EXTERN void ADFH_Get_Root_ID( const double ID, double *Root_ID, int *error_return ) ; EXTERN void ADFH_Is_Link( const double ID, int *link_path_length, int *error_return ) ; EXTERN void ADFH_Library_Version( char *version, int *error_return ) ; EXTERN void ADFH_Link( const double PID, const char *name, const char *file, const char *name_in_file, double *ID, int *error_return ) ; EXTERN void ADFH_Link_Size( const double ID, int *file_length, int *name_length, int *error_return ) ; EXTERN void ADFH_Move_Child( const double PID, const double ID, const double NPID, int *error_return ) ; EXTERN void ADFH_Number_of_Children( const double ID, int *num_children, int *error_return ) ; EXTERN void ADFH_Put_Dimension_Information( const double ID, const char *data_type, const int dims, const cgsize_t dim_vals[], int *error_return ) ; EXTERN void ADFH_Put_Name( const double PID, const double ID, const char *name, int *error_return ) ; EXTERN void ADFH_Read_All_Data( const double ID, const char *m_data_type, char *data, int *error_return ) ; EXTERN void ADFH_Read_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) ; EXTERN void ADFH_Read_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const char *m_data_type, const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], char *data, int *error_return ) ; EXTERN void ADFH_Set_Error_State( const int error_state, int *error_return ) ; EXTERN void ADFH_Set_Label( const double ID, const char *label, int *error_return ) ; EXTERN void ADFH_Write_All_Data( const double ID, const char *m_data_type, const char *data, int *error_return ) ; EXTERN void ADFH_Write_Block_Data( const double ID, const cgsize_t b_start, const cgsize_t b_end, char *data, int *error_return ) ; EXTERN void ADFH_Write_Data( const double ID, const cgsize_t s_start[], const cgsize_t s_end[], const cgsize_t s_stride[], const char *m_data_type, const int m_num_dims, const cgsize_t m_dims[], const cgsize_t m_start[], const cgsize_t m_end[], const cgsize_t m_stride[], const char *data, int *error_return ) ; #define HAS_ADF_RELEASE_ID EXTERN void ADFH_Release_ID ( const double ID ); #if defined (__cplusplus) } #endif #undef EXTERN #endif /* _ADFH_H_ */ CGNS-3.4.0/src/adfh/ADFH_ftoc.c000066400000000000000000000415461343724673500156520ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include "fortran_macros.h" #include "ADFH.h" #if defined(_WIN32) && defined(BUILD_DLL) # define CGNSDLL __declspec(dllexport) #else # define CGNSDLL #endif /*-------------------------------------------------------------------*/ static void StringFtoC(char *string, int string_length, char *c_string, int max_len, int *ierr) { int i, iend; if (string == NULL || c_string == NULL) { *ierr = NULL_STRING_POINTER; return; } /** Skip and trailing blanks **/ for (iend = string_length-1; iend >= 0; iend--) { if (string[iend] != ' ') break; } if (iend >= max_len) { *ierr = STRING_LENGTH_TOO_BIG; return; } /** Copy the non-trailing blank portion of the string **/ for (i = 0; i <= iend; i++) c_string[i] = string[i]; /** NULL terminate the C string **/ c_string[i] = '\0'; *ierr = NO_ERROR; } /*-------------------------------------------------------------------*/ static void StringCtoF(char *c_string, char *string, int string_length, int *ierr) { int i, len; if (c_string == NULL || string == NULL) { *ierr = NULL_STRING_POINTER; return; } len = strlen(c_string); /* string truncated - should this be an error ? */ if (len > string_length) len = string_length; for (i = 0; i < len; i++) string[i] = c_string[i]; while (i < string_length) string[i++] = ' '; *ierr = NO_ERROR; } /*----- ADFH Fortran to C interface -----*/ CGNSDLL void FMNAME(adfcnam, ADFCNAM) (double *ID, int *istart, int *inum, int *inamlen, int *inumret, STR_PSTR(names), int *ier STR_PLEN(names)) { char *tmp, *p = STR_PTR(names); int n, len = *inamlen; *inumret = 0; if (*inum < 1) { *ier = NO_ERROR; return; } tmp = (char *) malloc (*inum * (len + 1)); if (tmp == NULL) { *ier = MEMORY_ALLOCATION_FAILED; return; } ADFH_Children_Names(*ID, *istart, *inum, len+1, inumret, tmp, ier); if (*ier == NO_ERROR) { for (n = 0; n < *inumret; n++) StringCtoF(&tmp[n*(len+1)], &p[n*len], len, ier); } free(tmp); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfcids, ADFCIDS) (double *ID, int *istart, int *inum, int *inumret, double *cIDs, int *ier) { ADFH_Children_IDs(*ID, *istart, *inum, inumret, cIDs, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfrid, ADFRID) (double *ID) { ADFH_Release_ID(*ID); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfcre, ADFCRE) (double *PID, STR_PSTR(name), double *ID, int *ier STR_PLEN(name)) { char c_name[ADF_NAME_LENGTH+1]; StringFtoC(STR_PTR(name), STR_LEN(name), c_name, ADF_NAME_LENGTH, ier); if (*ier == NO_ERROR) ADFH_Create(*PID, c_name, ID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdclo, ADFDCLO) (double *RootID, int *ier) { ADFH_Database_Close(*RootID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfddel, ADFDDEL) (STR_PSTR(filename), int *ier STR_PLEN(filename)) { int len = STR_LEN(filename); char *c_name; if ((c_name = (char *) malloc (len + 1)) == NULL) { *ier = MEMORY_ALLOCATION_FAILED; return; } StringFtoC(STR_PTR(filename), len, c_name, len, ier); if (*ier == NO_ERROR) ADFH_Database_Delete(c_name, ier); free (c_name); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdel, ADFDEL) (double *PID, double *ID, int *ier) { ADFH_Delete(*PID, *ID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdgc, ADFDGC) (double *ID, int *ier) { ADFH_Database_Garbage_Collection(*ID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdgf, ADFDGF) (double *RootID, STR_PSTR(format), int *ier STR_PLEN(format)) { char c_format[ADF_FORMAT_LENGTH+1]; ADFH_Database_Get_Format(*RootID, c_format, ier); if (*ier == NO_ERROR) StringCtoF(c_format, STR_PTR(format), STR_LEN(format), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdopn, ADFDOPN) (STR_PSTR(filename), STR_PSTR(status), STR_PSTR(format), double *RootID, int *ier STR_PLEN(filename) STR_PLEN(status) STR_PLEN(format)) { int len = STR_LEN(filename); char *c_filename; char c_status[ADF_STATUS_LENGTH+1]; char c_format[ADF_FORMAT_LENGTH+1]; StringFtoC(STR_PTR(status), STR_LEN(status), c_status, ADF_STATUS_LENGTH, ier); if (*ier != NO_ERROR) return; StringFtoC(STR_PTR(format), STR_LEN(format), c_format, ADF_FORMAT_LENGTH, ier); if (*ier != NO_ERROR) return; if ((c_filename = (char *) malloc (len + 1)) == NULL) { *ier = MEMORY_ALLOCATION_FAILED; return; } StringFtoC(STR_PTR(filename), len, c_filename, len, ier); if (*ier == NO_ERROR) ADFH_Database_Open(c_filename, c_status, c_format, RootID, ier); free (c_filename); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdsf, ADFDSF) (double *RootID, STR_PSTR(format), int *ier STR_PLEN(format)) { char c_format[ADF_FORMAT_LENGTH+1]; StringFtoC(STR_PTR(format), STR_LEN(format), c_format, ADF_FORMAT_LENGTH, ier); if (*ier == NO_ERROR) ADFH_Database_Set_Format(*RootID, c_format, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfdver, ADFDVER) (double *RootID, STR_PSTR(version), STR_PSTR(cdate), STR_PSTR(mdate), int *ier STR_PLEN(version) STR_PLEN(cdate) STR_PLEN(mdate)) { char c_version[ADF_VERSION_LENGTH+1]; char c_cdate[ADF_DATE_LENGTH+1]; char c_mdate[ADF_DATE_LENGTH+1]; ADFH_Database_Version(*RootID, c_version, c_cdate, c_mdate, ier); if (*ier == NO_ERROR) { StringCtoF(c_version, STR_PTR(version), STR_LEN(version), ier); StringCtoF(c_cdate, STR_PTR(cdate), STR_LEN(cdate), ier); StringCtoF(c_mdate, STR_PTR(mdate), STR_LEN(mdate), ier); } } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adferr, ADFERR) (int *ier, STR_PSTR(errstr) STR_PLEN(errstr)) { int err; char errmsg[ADF_MAX_ERROR_STR_LENGTH+1]; ADFH_Error_Message(*ier, errmsg); StringCtoF(errmsg, STR_PTR(errstr), STR_LEN(errstr), &err); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfftd, ADFFTD) (double *ID, int *ier) { ADFH_Flush_to_Disk(*ID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgdt, ADFGDT) (double *ID, STR_PSTR(dtype), int *ier STR_PLEN(dtype)) { char c_type[ADF_DATA_TYPE_LENGTH+1]; ADFH_Get_Data_Type(*ID, c_type, ier); if (*ier == NO_ERROR) StringCtoF(c_type, STR_PTR(dtype), STR_LEN(dtype), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgdv, ADFGDV) (double *ID, int *dvals, int *ier) { ADFH_Get_Dimension_Values(*ID, dvals, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfges, ADFGES) (int *estate, int *ier) { ADFH_Get_Error_State(estate, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfglb, ADFGLB) (double *ID, STR_PSTR(label), int *ier STR_PLEN(label)) { char c_label[ADF_LABEL_LENGTH+1]; ADFH_Get_Label(*ID, c_label, ier); if (*ier == NO_ERROR) StringCtoF(c_label, STR_PTR(label), STR_LEN(label), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfglkp, ADFGLKP) (double *ID, STR_PSTR(file), STR_PSTR(name), int *ier STR_PLEN(file) STR_PLEN(name)) { char c_file[ADF_FILENAME_LENGTH+1]; char c_name[ADF_MAX_LINK_DATA_SIZE+1]; ADFH_Get_Link_Path(*ID, c_file, c_name, ier); if (*ier == NO_ERROR) { StringCtoF(c_file, STR_PTR(file), STR_LEN(file), ier); StringCtoF(c_name, STR_PTR(name), STR_LEN(name), ier); } } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgnam, ADFGNAM) (double *ID, STR_PSTR(name), int *ier STR_PLEN(name)) { char c_name[ADF_NAME_LENGTH+1]; ADFH_Get_Name(*ID, c_name, ier); if (*ier == NO_ERROR) StringCtoF(c_name, STR_PTR(name), STR_LEN(name), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgnd, ADFGND) (double *ID, int *ndims, int *ier) { ADFH_Get_Number_of_Dimensions(*ID, ndims, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgnid, ADFGNID) (double *PID, STR_PSTR(name), double *ID, int *ier STR_PLEN(name)) { int len = STR_LEN(name); char *c_name; if ((c_name = (char *) malloc (len+1)) == NULL) { *ier = MEMORY_ALLOCATION_FAILED; return; } StringFtoC(STR_PTR(name), len, c_name, len, ier); if (*ier == NO_ERROR) ADFH_Get_Node_ID(*PID, c_name, ID, ier); free(c_name); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfgrid, ADFGRID) (double *ID, double *RootID, int *ier) { ADFH_Get_Root_ID(*ID, RootID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfislk, ADFISLK) (double *ID, int *lplen, int *ier) { ADFH_Is_Link(*ID, lplen, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adflink, ADFLINK) (double *PID, STR_PSTR(name), STR_PSTR(file), STR_PSTR(nfile), double *ID, int *ier STR_PLEN(name) STR_PLEN(file) STR_PLEN(nfile)) { char c_name[ADF_NAME_LENGTH+1]; char c_file[ADF_FILENAME_LENGTH+1]; char c_nfile[ADF_MAX_LINK_DATA_SIZE+1]; StringFtoC(STR_PTR(name), STR_LEN(name), c_name, ADF_NAME_LENGTH, ier); if (*ier != NO_ERROR) return; StringFtoC(STR_PTR(file), STR_LEN(file), c_file, ADF_FILENAME_LENGTH, ier); if (*ier != NO_ERROR) return; StringFtoC(STR_PTR(nfile), STR_LEN(nfile), c_nfile, ADF_MAX_LINK_DATA_SIZE, ier); if (*ier == NO_ERROR) ADFH_Link(*PID, c_name, c_file, c_nfile, ID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adflver, ADFLVER) (STR_PSTR(version), int *ier STR_PLEN(version)) { char c_version[ADF_VERSION_LENGTH+1]; ADFH_Library_Version(c_version, ier); if (*ier == NO_ERROR) StringCtoF(c_version, STR_PTR(version), STR_LEN(version), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfmove, ADFMOVE) (double *PID, double *ID, double *NPID, int *ier) { ADFH_Move_Child(*PID, *ID, *NPID, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfncld, ADFNCLD) (double *ID, int *numcld, int *ier) { ADFH_Number_of_Children(*ID, numcld, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfpdim, ADFPDIM) (double *ID, STR_PSTR(dtype), int *dims, int *dvals, int *ier STR_PLEN(dtype)) { char c_type[ADF_DATA_TYPE_LENGTH+1]; StringFtoC(STR_PTR(dtype), STR_LEN(dtype), c_type, ADF_DATA_TYPE_LENGTH, ier); if (*ier == NO_ERROR) ADFH_Put_Dimension_Information(*ID, c_type, *dims, dvals, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfpnam, ADFPNAM) (double *PID, double *ID, STR_PSTR(name), int *ier STR_PLEN(name)) { char c_name[ADF_NAME_LENGTH+1]; StringFtoC(STR_PTR(name), STR_LEN(name), c_name, ADF_NAME_LENGTH, ier); if (*ier == NO_ERROR) ADFH_Put_Name(*PID, *ID, c_name, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfses, ADFSES) (int *estate, int *ier) { ADFH_Set_Error_State(*estate, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfslb, ADFSLB) (double *ID, STR_PSTR(label), int *ier STR_PLEN(label)) { char c_label[ADF_LABEL_LENGTH+1]; StringFtoC(STR_PTR(label), STR_LEN(label), c_label, ADF_LABEL_LENGTH, ier); if (*ier == NO_ERROR) ADFH_Set_Label(*ID, c_label, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfread, ADFREAD) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, char *data, int *ier) { ADFH_Read_Data(*ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, data, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfrall, ADFRALL) (double *ID, char *data, int *ier) { ADFH_Read_All_Data(*ID, data, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfrblk, ADFRBLK) (double *ID, int *b_start, int *b_end, char *data, int *ier) { ADFH_Read_Block_Data(*ID, *b_start, *b_end, data, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwrit, ADFWRIT) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, char *data, int *ier) { ADFH_Write_Data(*ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, data, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwall, ADFWALL) (double *ID, char *data, int *ier) { ADFH_Write_All_Data(*ID, data, ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwblk, ADFRWBLK) (double *ID, int *b_start, int *b_end, char *data, int *ier) { ADFH_Write_Block_Data(*ID, *b_start, *b_end, data, ier); } /*----- added mainly to handle character output under windows -----*/ CGNSDLL void FMNAME(adfreadc, ADFREADC) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Read_Data(*ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, STR_PTR(data), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfrallc, ADFRALLC) (double *ID, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Read_All_Data(*ID, STR_PTR(data), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfrblkc, ADFRBLKC) (double *ID, int *b_start, int *b_end, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Read_Block_Data(*ID, *b_start, *b_end, STR_PTR(data), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwritc, ADFWRITC) (double *ID, int *s_start, int *s_end, int *s_stride, int *m_num_dims, int *m_dims, int *m_start, int *m_end, int *m_stride, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Write_Data(*ID, s_start, s_end, s_stride, *m_num_dims, m_dims, m_start, m_end, m_stride, STR_PTR(data), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwallc, ADFWALLC) (double *ID, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Write_All_Data(*ID, STR_PTR(data), ier); } /*-------------------------------------------------------------------*/ CGNSDLL void FMNAME(adfwblkc, ADFRBWLKC) (double *ID, int *b_start, int *b_end, STR_PSTR(data), int *ier STR_PLEN(data)) { ADFH_Write_Block_Data(*ID, *b_start, *b_end, STR_PTR(data), ier); } CGNS-3.4.0/src/cg_ftoc.c000066400000000000000000004430451343724673500146370ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include #include "fortran_macros.h" #include "cgnslib.h" #include "cgns_header.h" #include #include "cgns_io.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #ifdef BUILD_PARALLEL #include "pcgnslib.h" #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Convert between Fortran and C strings * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ static void string_2_C_string(char *string, int string_length, char *c_string, int max_len, cgint_f *ierr) { int i, iend; if (string == NULL || c_string == NULL) { cgi_error ("NULL string pointer"); *ierr = (cgint_f)CG_ERROR; return; } /** Skip and trailing blanks **/ for (iend = string_length-1; iend >= 0; iend--) { if (string[iend] != ' ') break; } if (iend >= max_len) iend = max_len - 1; /** Copy the non-trailing blank portion of the string **/ for (i = 0; i <= iend; i++) c_string[i] = string[i]; /** NULL terminate the C string **/ c_string[i] = '\0'; *ierr = (cgint_f)CG_OK; } /*-----------------------------------------------------------------------*/ static void string_2_F_string(char *c_string, char *string, int string_length, cgint_f *ierr) { int i, len; if (c_string == NULL || string == NULL) { cgi_error ("NULL string pointer"); *ierr = (cgint_f)CG_ERROR; return; } len = (int)strlen(c_string); if (len > string_length) len = string_length; for (i = 0; i < len; i++) string[i] = c_string[i]; while (i < string_length) string[i++] = ' '; *ierr = (cgint_f)CG_OK; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * LIBRARY FUNCTIONS * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_is_cgns_f, CG_IS_CGNS_F) (STR_PSTR(filename), cgint_f *file_type, cgint_f *ier STR_PLEN(filename)) { int length, i_file_type; char *c_name; length = (int) STR_LEN(filename); c_name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(filename), STR_LEN(filename), c_name, length, ier); if (*ier == 0) { *ier = (cgint_f)cg_is_cgns(c_name, &i_file_type); *file_type = (cgint_f)i_file_type; } CGNS_FREE(c_name); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_open_f, CG_OPEN_F) (STR_PSTR(filename), cgint_f *mode, cgint_f *fn, cgint_f *ier STR_PLEN(filename)) { int length, i_fn; char *c_name; length = (int) STR_LEN(filename); c_name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(filename), STR_LEN(filename), c_name, length, ier); if (*ier == 0) { #if DEBUG_FTOC printf("filename='%s'\n",c_name); #endif *ier = (cgint_f)cg_open(c_name, (int)*mode, &i_fn); *fn = (cgint_f)i_fn; } CGNS_FREE(c_name); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_version_f(cgint_f *fn, float *FileVersion, cgint_f *ier) { *ier = (cgint_f)cg_version((int)*fn, FileVersion); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_precision_f(cgint_f *fn, cgint_f *precision, cgint_f *ier) { int i_precision; *ier = (cgint_f)cg_precision((int)*fn, &i_precision); *precision = (cgint_f)i_precision; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_close_f(cgint_f *fn, cgint_f *ier) { *ier = (cgint_f)cg_close((int)*fn); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_save_as_f, CG_SAVE_AS_F) (cgint_f *fn, STR_PSTR(filename), cgint_f *file_type, cgint_f *follow_links, cgint_f *ier STR_PLEN(filename)) { int length; char *c_name; length = (int) STR_LEN(filename); c_name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(filename), STR_LEN(filename), c_name, length, ier); if (*ier == 0) *ier = (cgint_f)cg_save_as((int)*fn, c_name, (int)*file_type, (int)*follow_links); CGNS_FREE(c_name); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_set_file_type_f(cgint_f *ft, cgint_f *ier) { *ier = (cgint_f)cg_set_file_type((int)*ft); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_get_file_type_f(cgint_f *fn, cgint_f *ft, cgint_f *ier) { int i_ft; *ier = (cgint_f)cg_get_file_type((int)*fn, &i_ft); *ft = (cgint_f)i_ft; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_set_compress_f(cgint_f *cmpr, cgint_f *ier) { *ier = (cgint_f)cg_set_compress((int)*cmpr); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_get_compress_f(cgint_f *cmpr, cgint_f *ier) { int i_cmpr; *ier = (cgint_f)cg_get_compress(&i_cmpr); *cmpr = (cgint_f)i_cmpr; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_set_path_f, CG_SET_PATH_F) (STR_PSTR(pathname), cgint_f *ier STR_PLEN(pathname)) { int length; char *c_name; length = (int) STR_LEN(pathname); c_name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(pathname), STR_LEN(pathname), c_name, length, ier); if (*ier == 0) *ier = (cgint_f)cg_set_path(c_name); CGNS_FREE(c_name); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_add_path_f, CG_ADD_PATH_F) (STR_PSTR(pathname), cgint_f *ier STR_PLEN(pathname)) { int length; char *c_name; length = (int) STR_LEN(pathname); c_name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(pathname), STR_LEN(pathname), c_name, length, ier); if (*ier == 0) *ier = (cgint_f)cg_add_path(c_name); CGNS_FREE(c_name); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_set_rind_zero_f(cgint_f *ier) { *ier = (cgint_f)cg_configure(CG_CONFIG_RIND_INDEX, (void *)CG_CONFIG_RIND_ZERO); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_set_rind_core_f(cgint_f *ier) { *ier = (cgint_f)cg_configure(CG_CONFIG_RIND_INDEX, (void *)CG_CONFIG_RIND_CORE); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_get_cgio_f(cgint_f *fn, cgint_f *cgio_num, cgint_f *ier) { int i_cgio_num; *ier = (cgint_f)cg_get_cgio((int)*fn, &i_cgio_num); *cgio_num = (cgint_f)i_cgio_num; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_root_id_f(cgint_f *fn, double *rootid, cgint_f *ier) { *ier = (cgint_f)cg_root_id((int)*fn, rootid); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write CGNSBase_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nbases_f(cgint_f *fn, cgint_f *nbases, cgint_f *ier) { int i_nbases; *ier = (cgint_f)cg_nbases((int)*fn, &i_nbases); *nbases = (cgint_f)i_nbases; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_base_read_f, CG_BASE_READ_F) (cgint_f *fn, cgint_f *B, STR_PSTR(basename), cgint_f *cell_dim, cgint_f *phys_dim, cgint_f *ier STR_PLEN(basename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_cell_dim, i_phys_dim; *ier = (cgint_f)cg_base_read((int)*fn, (int)*B, c_name, &i_cell_dim, &i_phys_dim); if (*ier) return; string_2_F_string(c_name, STR_PTR(basename), STR_LEN(basename), ier); *cell_dim = (cgint_f)i_cell_dim; *phys_dim = (cgint_f)i_phys_dim; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_base_id_f(cgint_f *fn, cgint_f *B, double *base_id, cgint_f *ier) { *ier = (cgint_f)cg_base_id((int)*fn, (int)*B, base_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_base_write_f, CG_BASE_WRITE_F) (cgint_f *fn, STR_PSTR(basename), cgint_f *cell_dim, cgint_f *phys_dim, cgint_f *B, cgint_f *ier STR_PLEN(basename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_B; string_2_C_string(STR_PTR(basename), STR_LEN(basename), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("\nbasename='%s'\n", c_name); printf("cell_dim=%d\n",*cell_dim); printf("phys_dim=%d\n",*phys_dim); #endif *ier = (cgint_f)cg_base_write((int)*fn, c_name, (int)*cell_dim, (int)*phys_dim, &i_B); *B = (cgint_f)i_B; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_cell_dim_f(cgint_f *fn, cgint_f *B, cgint_f *dim, cgint_f *ier) { int i_dim; *ier = (cgint_f)cg_cell_dim((int)*fn, (int)*B, &i_dim); *dim = (cgint_f)i_dim; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Zone_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nzones_f(cgint_f *fn, cgint_f *B, cgint_f *nzones, cgint_f *ier) { int i_nzones; *ier = (cgint_f)cg_nzones((int)*fn, (int)*B, &i_nzones); *nzones = (cgint_f)i_nzones; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_zone_type_f(cgint_f *fn, cgint_f *B, cgint_f *Z, CGNS_ENUMT(ZoneType_t)*type, cgint_f *ier) { CGNS_ENUMT(ZoneType_t) i_type; *ier = (cgint_f)cg_zone_type((int)*fn, (int)*B, (int)*Z, &i_type); *type = i_type; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_zone_read_f, CG_ZONE_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(zonename), cgsize_t *size, cgint_f *ier STR_PLEN(zonename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_zone_read((int)*fn, (int)*B, (int)*Z, c_name, size); if (*ier == 0) string_2_F_string(c_name, STR_PTR(zonename), STR_LEN(zonename), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_zone_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, double *zone_id, cgint_f *ier) { *ier = (cgint_f)cg_zone_id((int)*fn, (int)*B, (int)*Z, zone_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_zone_write_f, CG_ZONE_WRITE_F) (cgint_f *fn, cgint_f *B, STR_PSTR(zonename), cgsize_t *size, CGNS_ENUMT(ZoneType_t) *type, cgint_f *Z, cgint_f *ier STR_PLEN(zonename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_Z; string_2_C_string(STR_PTR(zonename), STR_LEN(zonename), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("\n zonename='%s'\n", c_name); #endif *ier = (cgint_f)cg_zone_write((int)*fn, (int)*B, c_name, size, (CGNS_ENUMT(ZoneType_t))*type, &i_Z); *Z = (cgint_f)i_Z; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_index_dim_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *dim, cgint_f *ier) { int i_dim; *ier = (cgint_f)cg_index_dim((int)*fn, (int)*B, (int)*Z, &i_dim); *dim = (cgint_f)i_dim; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Family_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nfamilies_f(cgint_f *fn, cgint_f *B, cgint_f *nfamilies, cgint_f *ier) { int i_nfamilies; *ier = (cgint_f)cg_nfamilies((int)*fn, (int)*B, &i_nfamilies); *nfamilies = (cgint_f)i_nfamilies; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_family_read_f, CG_FAMILY_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *F, STR_PSTR(family_name), cgint_f *nboco, cgint_f *ngeos, cgint_f *ier STR_PLEN(family_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_nboco, i_ngeos; *ier = (cgint_f)cg_family_read((int)*fn, (int)*B, (int)*F, c_name, &i_nboco, &i_ngeos); if (*ier) return; string_2_F_string(c_name, STR_PTR(family_name), STR_LEN(family_name), ier); *nboco = (cgint_f)i_nboco; *ngeos = (cgint_f)i_ngeos; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_family_write_f, CG_FAMILY_WRITE_F) (cgint_f *fn, cgint_f *B, STR_PSTR(family_name), cgint_f *F, cgint_f *ier STR_PLEN(family_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_F; string_2_C_string(STR_PTR(family_name), STR_LEN(family_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_family_write((int)*fn, (int)*B, c_name, &i_F); *F = (cgint_f)i_F; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_nfamily_names_f(cgint_f *fn, cgint_f *B, cgint_f *F, cgint_f *nnames, cgint_f *ier) { int i_nnames; *ier = (cgint_f)cg_nfamily_names((int)*fn, (int)*B, (int)*F, &i_nnames); *nnames = (cgint_f)i_nnames; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_family_name_read_f, CG_FAMILY_NAME_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *F, cgint_f *N, STR_PSTR(name), STR_PSTR(family), cgint_f *ier STR_PLEN(name) STR_PLEN(family)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; char c_family[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_family_name_read((int)*fn, (int)*B, (int)*F, (int)*N, c_name, c_family); if (*ier) return; string_2_F_string(c_name, STR_PTR(name), STR_LEN(name), ier); if (*ier) return; string_2_F_string(c_family, STR_PTR(family), STR_LEN(family), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_family_name_write_f, CG_FAMILY_NAME_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *F, STR_PSTR(name), STR_PSTR(family), cgint_f *ier STR_PLEN(name) STR_PLEN(family)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; char c_family[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; string_2_C_string(STR_PTR(family), STR_LEN(family), c_family, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_family_name_write((int)*fn, (int)*B, (int)*F, c_name, c_family); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FamBC_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_fambc_read_f, CG_FAMBC_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *F, cgint_f *BC, STR_PSTR(fambc_name), CGNS_ENUMT(BCType_t) *bocotype, cgint_f *ier STR_PLEN(fambc_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(BCType_t) i_bocotype; *ier = (cgint_f)cg_fambc_read((int)*fn, (int)*B, (int)*F, (int)*BC, c_name, &i_bocotype); if (*ier) return; string_2_F_string(c_name, STR_PTR(fambc_name), STR_LEN(fambc_name), ier); *bocotype = (CGNS_ENUMT(BCType_t))i_bocotype; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_fambc_write_f, CG_FAMBC_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *F, STR_PSTR(fambc_name), CGNS_ENUMT(BCType_t) *bocotype, cgint_f *BC, cgint_f *ier STR_PLEN(fambc_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_BC; string_2_C_string(STR_PTR(fambc_name), STR_LEN(fambc_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_fambc_write((int)*fn, (int)*B, (int)*F, c_name, (CGNS_ENUMT(BCType_t))*bocotype, &i_BC); *BC = (cgint_f)i_BC; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GeometryReference_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_geo_read_f, CG_GEO_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *F, cgint_f *G, STR_PSTR(geo_name), STR_PSTR(geo_file), STR_PSTR(CAD_name), cgint_f *npart, cgint_f *ier STR_PLEN(geo_name) STR_PLEN(geo_file) STR_PLEN(CAD_name)) { char c_geo_name[CGIO_MAX_NAME_LENGTH+1]; char c_CAD_name[CGIO_MAX_NAME_LENGTH+1]; char *c_geo_file; int i_npart; *ier = (cgint_f)cg_geo_read((int)*fn, (int)*B, (int)*F, (int)*G, c_geo_name, &c_geo_file, c_CAD_name, &i_npart); if (*ier) return; *npart = (cgint_f)i_npart; string_2_F_string(c_geo_file, STR_PTR(geo_file), STR_LEN(geo_file), ier); CGNS_FREE(c_geo_file); if (*ier) return; string_2_F_string(c_geo_name, STR_PTR(geo_name), STR_LEN(geo_name), ier); if (*ier) return; string_2_F_string(c_CAD_name, STR_PTR(CAD_name), STR_LEN(CAD_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_geo_write_f, CG_GEO_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *F, STR_PSTR(geo_name), STR_PSTR(geo_file), STR_PSTR(CAD_name), cgint_f *G, cgint_f *ier STR_PLEN(geo_name) STR_PLEN(geo_file) STR_PLEN(CAD_name)) { char c_geo_name[CGIO_MAX_NAME_LENGTH+1]; char c_CAD_name[CGIO_MAX_NAME_LENGTH+1]; char *c_geo_file; int length, i_G; /* convert Fortran-text-string to a C-string */ string_2_C_string(STR_PTR(geo_name), STR_LEN(geo_name), c_geo_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; string_2_C_string(STR_PTR(CAD_name), STR_LEN(CAD_name), c_CAD_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; length = STR_LEN(geo_file); c_geo_file = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(geo_file), STR_LEN(geo_file), c_geo_file, length, ier); if (*ier == 0) { *ier = (cgint_f)cg_geo_write((int)*fn, (int)*B, (int)*F, c_geo_name, c_geo_file, c_CAD_name, &i_G); *G = (cgint_f)i_G; } CGNS_FREE(c_geo_file); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GeometryEntity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_part_read_f, CG_PART_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *F,cgint_f *G, cgint_f *P, STR_PSTR(part_name), cgint_f *ier STR_PLEN(part_name)) { char c_part_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_part_read((int)*fn, (int)*B, (int)*F, (int)*G, (int)*P, c_part_name); if (*ier == 0) string_2_F_string(c_part_name, STR_PTR(part_name), STR_LEN(part_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_part_write_f, CG_PART_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *F, cgint_f *G, STR_PSTR(part_name), cgint_f *P, cgint_f *ier STR_PLEN(part_name)) { char c_part_name[CGIO_MAX_NAME_LENGTH+1]; int i_P; /* convert Fortran-text-string to a C-string */ string_2_C_string(STR_PTR(part_name), STR_LEN(part_name), c_part_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_part_write((int)*fn, (int)*B, (int)*F, (int)*G, c_part_name, &i_P); *P = (cgint_f)i_P; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DiscreteData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_ndiscrete_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *ndiscrete, cgint_f *ier) { int i_ndiscrete; *ier = (cgint_f)cg_ndiscrete((int)*fn, (int)*B, (int)*Z, &i_ndiscrete); *ndiscrete = (cgint_f)i_ndiscrete; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_discrete_read_f, CG_DISCRETE_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *D, STR_PSTR(discrete_name), cgint_f *ier STR_PLEN(discrete_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_discrete_read((int)*fn, (int)*B, (int)*Z, (int)*D, c_name); if (*ier == 0) string_2_F_string(c_name, STR_PTR(discrete_name), STR_LEN(discrete_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_discrete_write_f, CG_DISCRETE_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(discrete_name), cgint_f *D, cgint_f *ier STR_PLEN(discrete_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_D; string_2_C_string(STR_PTR(discrete_name), STR_LEN(discrete_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" discrete_name='%s'\n", c_name); #endif *ier = (cgint_f)cg_discrete_write((int)*fn, (int)*B, (int)*Z, c_name, &i_D); *D = (cgint_f)i_D; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_discrete_size_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *D, cgint_f *ndim, cgsize_t *dims, cgint_f *ier) { int i_ndim; *ier = (cgint_f)cg_discrete_size((int)*fn, (int)*B, (int)*Z, (int)*D, &i_ndim, dims); *ndim = (cgint_f)i_ndim; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_discrete_ptset_info_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, CGNS_ENUMT(PointSetType_t) *ptype, cgsize_t *npnts, cgint_f *ier) { CGNS_ENUMT(PointSetType_t) i_ptype; *ier = (cgint_f)cg_discrete_ptset_info((int)*fn, (int)*B, (int)*Z, (int)*S, &i_ptype, npnts); *ptype = (CGNS_ENUMT(PointSetType_t))i_ptype; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_discrete_ptset_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_discrete_ptset_read((int)*fn, (int)*B, (int)*Z, (int)*S, pnts); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_discrete_ptset_write_f, CG_DISCRETE_PTSET_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(name), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptype, cgsize_t *npnts, cgsize_t *pnts, cgint_f *D, cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_D; string_2_C_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_discrete_ptset_write((int)*fn, (int)*B, (int)*Z, c_name, (CGNS_ENUMT(GridLocation_t))*location, (CGNS_ENUMT(PointSetType_t))*ptype, *npnts, pnts, &i_D); *D = (cgint_f)i_D; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridCoordinates_t/DataArray_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_ncoords_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *ncoords, cgint_f *ier) { int i_ncoords; *ier = (cgint_f)cg_ncoords((int)*fn, (int)*B, (int)*Z, &i_ncoords); *ncoords = (cgint_f)i_ncoords; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_info_f, CG_COORD_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, CGNS_ENUMT(DataType_t) *type, STR_PSTR(coordname), cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(DataType_t) i_type; *ier = (cgint_f)cg_coord_info((int)*fn, (int)*B, (int)*Z, (int)*C, &i_type, c_name); if (*ier) return; *type = (CGNS_ENUMT(DataType_t))i_type; string_2_F_string(c_name, STR_PTR(coordname), STR_LEN(coordname), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_read_f, CG_COORD_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(coordname), CGNS_ENUMT(DataType_t) *type, cgsize_t *rmin, cgsize_t *rmax, void *coord, cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(coordname), STR_LEN(coordname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("coordname='%s'\n", c_name); #endif *ier = (cgint_f)cg_coord_read((int)*fn, (int)*B, (int)*Z, c_name, *type, rmin, rmax, coord); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_general_read_f, CG_COORD_GENERAL_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(coordname), cgsize_t *s_rmin, cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) *m_type, cgint_f *m_numdim, cgsize_t *m_dimvals, cgsize_t *m_rmin, cgsize_t *m_rmax, void *coord, cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(coordname), STR_LEN(coordname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("coordname='%s'\n", c_name); #endif *ier = (cgint_f)cg_coord_general_read( (int)*fn, (int)*B, (int)*Z, c_name, s_rmin, s_rmax, *m_type, (int)*m_numdim, m_dimvals, m_rmin, m_rmax, coord); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_coord_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, double *coord_id, cgint_f *ier) { *ier = (cgint_f)cg_coord_id((int)*fn, (int)*B, (int)*Z, (int)*C, coord_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_write_f, CG_COORD_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, CGNS_ENUMT(DataType_t) *type, STR_PSTR(coordname), void *coord, cgint_f *C, cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_C; string_2_C_string(STR_PTR(coordname), STR_LEN(coordname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" coordname='%s'\n", c_name); #endif *ier = (cgint_f)cg_coord_write((int)*fn, (int)*B, (int)*Z, (CGNS_ENUMT(DataType_t))*type, c_name, coord, &i_C); *C = (cgint_f)i_C; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_partial_write_f, CG_COORD_PARTIAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, CGNS_ENUMT(DataType_t) *type, STR_PSTR(coordname), cgsize_t *rmin, cgsize_t *rmax, void *coord, cgint_f *C, cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_C; string_2_C_string(STR_PTR(coordname), STR_LEN(coordname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" coordname='%s'\n", c_name); #endif *ier = (cgint_f)cg_coord_partial_write((int)*fn, (int)*B, (int)*Z, (CGNS_ENUMT(DataType_t))*type, c_name, rmin, rmax, coord, &i_C); *C = (cgint_f)i_C; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_coord_general_write_f, CG_COORD_GENERAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(coordname), CGNS_ENUMT(DataType_t) *s_type, cgsize_t *s_rmin, cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) *m_type, cgint_f *m_numdim, cgsize_t *m_dims, cgsize_t *m_rmin, cgsize_t *m_rmax, void *coord, cgint_f *C, cgint_f *ier STR_PLEN(coordname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_C; string_2_C_string(STR_PTR(coordname), STR_LEN(coordname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" coordname='%s'\n", c_name); #endif *ier = (cgint_f)cg_coord_general_write((int)*fn, (int)*B, (int)*Z, c_name, *s_type, s_rmin, s_rmax, *m_type, (int)*m_numdim, m_dims, m_rmin, m_rmax, coord, &i_C); *C = (cgint_f)i_C; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Elements_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nsections_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nsections, cgint_f *ier) { int i_nsections; *ier = (cgint_f)cg_nsections((int)*fn, (int)*B, (int)*Z, &i_nsections); *nsections = (cgint_f)i_nsections; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_section_read_f, CG_SECTION_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *E, STR_PSTR(section_name), CGNS_ENUMT(ElementType_t) *type, cgsize_t *start, cgsize_t *end, cgint_f *nbndry, cgint_f *parent_flag, cgint_f *ier STR_PLEN(section_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(ElementType_t) i_type; int i_nbndry, i_parent_flag; *ier = (cgint_f)cg_section_read((int)*fn, (int)*B, (int)*Z, (int)*E, c_name, &i_type, start, end, &i_nbndry, &i_parent_flag); if (*ier) return; *type = (CGNS_ENUMT(ElementType_t))i_type; *nbndry = (cgint_f)i_nbndry; *parent_flag = (cgint_f)i_parent_flag; string_2_F_string(c_name, STR_PTR(section_name), STR_LEN(section_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_elements_read_f, CG_ELEMENTS_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *E, cgsize_t *elements, cgsize_t *parent_data, cgint_f *ier) { *ier = (cgint_f)cg_elements_read((int)*fn, (int)*B, (int)*Z, (int)*E, elements, parent_data); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_poly_elements_read_f, CG_POLY_ELEMENTS_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *E, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent_data, cgint_f *ier) { *ier = (cgint_f)cg_poly_elements_read((int)*fn, (int)*B, (int)*Z, (int)*E, elements, connect_offset, parent_data); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_elementdatasize_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *E, cgsize_t *ElementDataSize, cgint_f *ier) { *ier = (cgint_f)cg_ElementDataSize((int)*fn, (int)*B, (int)*Z, (int)*E, ElementDataSize); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_elementpartialsize_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *E, cgsize_t *start, cgsize_t *end, cgsize_t *ElementDataSize, cgint_f *ier) { *ier = (cgint_f)cg_ElementPartialSize((int)*fn, (int)*B, (int)*Z, (int)*E, *start, *end, ElementDataSize); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_section_write_f, CG_SECTION_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(section_name), CGNS_ENUMT(ElementType_t)*type, cgsize_t *start, cgsize_t *end, cgint_f *nbndry, cgsize_t *elements, cgint_f *S, cgint_f *ier STR_PLEN(section_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_S; /* convert Fortran-text-string to a C-string */ string_2_C_string(STR_PTR(section_name), STR_LEN(section_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_section_write((int)*fn, (int)*B, (int)*Z, c_name, *type, *start, *end, (int)*nbndry, elements, &i_S); *S = (cgint_f)i_S; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_poly_section_write_f, CG_POLY_SECTION_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(section_name), CGNS_ENUMT(ElementType_t)*type, cgsize_t *start, cgsize_t *end, cgint_f *nbndry, cgsize_t *elements, cgsize_t *connect_offset, cgint_f *S, cgint_f *ier STR_PLEN(section_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_S; /* convert Fortran-text-string to a C-string */ string_2_C_string(STR_PTR(section_name), STR_LEN(section_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_poly_section_write((int)*fn, (int)*B, (int)*Z, c_name, *type, *start, *end, (int)*nbndry, elements, connect_offset, &i_S); *S = (cgint_f)i_S; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_parent_data_write_f, CG_PARENT_DATA_WRITE_F )(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *parent_data, cgint_f *ier) { *ier = (cgint_f)cg_parent_data_write((int)*fn, (int)*B, (int)*Z, (int)*S, parent_data); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_section_partial_write_f, CG_SECTION_PARTIAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(section_name), CGNS_ENUMT(ElementType_t)*type, cgsize_t *start, cgsize_t *end, cgint_f *nbndry, cgint_f *S, cgint_f *ier STR_PLEN(section_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_S; /* convert Fortran-text-string to a C-string */ string_2_C_string(STR_PTR(section_name), STR_LEN(section_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_section_partial_write((int)*fn, (int)*B, (int)*Z, c_name, *type, *start, *end, (int)*nbndry, &i_S); *S = (cgint_f)i_S; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_elements_partial_write_f, CG_ELEMENTS_PARTIAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *rmin, cgsize_t *rmax, cgsize_t *elements, cgint_f *ier) { *ier = (cgint_f)cg_elements_partial_write((int)*fn, (int)*B, (int)*Z, (int)*S, *rmin, *rmax, elements); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_poly_elements_partial_write_f, CG_POLY_ELEMENTS_PARTIAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *rmin, cgsize_t *rmax, cgsize_t *elements, cgsize_t *connect_offset, cgint_f *ier) { *ier = (cgint_f)cg_poly_elements_partial_write((int)*fn, (int)*B, (int)*Z, (int)*S, *rmin, *rmax, elements, connect_offset); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_parent_data_partial_write_f, CG_PARENT_DATA_PARTIAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *rmin, cgsize_t *rmax, cgsize_t *parent_data, cgint_f *ier) { *ier = (cgint_f)cg_parent_data_partial_write((int)*fn, (int)*B, (int)*Z, (int)*S, *rmin, *rmax, parent_data); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_elements_partial_read_f, CG_ELEMENTS_PARTIAL_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *rmin, cgsize_t *rmax, cgsize_t *elements, cgsize_t *parent, cgint_f *ier) { *ier = (cgint_f)cg_elements_partial_read((int)*fn, (int)*B, (int)*Z, (int)*S, *rmin, *rmax, elements, parent); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_poly_elements_partial_read_f, CG_POLY_ELEMENTS_PARTIAL_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *rmin, cgsize_t *rmax, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent, cgint_f *ier) { *ier = (cgint_f)cg_poly_elements_partial_read((int)*fn, (int)*B, (int)*Z, (int)*S, *rmin, *rmax, elements, connect_offset, parent); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FlowSolution_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nsols_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nsols, cgint_f *ier) { int i_nsols; *ier = (cgint_f)cg_nsols((int)*fn, (int)*B, (int)*Z, &i_nsols); *nsols = (cgint_f)i_nsols; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_sol_info_f, CG_SOL_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(solname), CGNS_ENUMT(GridLocation_t) *location, cgint_f *ier STR_PLEN(solname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(GridLocation_t) i_location; *ier = (cgint_f)cg_sol_info((int)*fn, (int)*B, (int)*Z, (int)*S, c_name, &i_location); if (*ier) return; *location = (cgint_f)i_location; string_2_F_string(c_name, STR_PTR(solname), STR_LEN(solname), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_sol_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, double *sol_id, cgint_f *ier) { *ier = (cgint_f)cg_sol_id((int)*fn, (int)*B, (int)*Z, (int)*S, sol_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_sol_write_f, CG_SOL_WRITE_F)(cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(solname), CGNS_ENUMT(GridLocation_t)*location, cgint_f *S, cgint_f *ier STR_PLEN(solname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_S; string_2_C_string(STR_PTR(solname), STR_LEN(solname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("\n solname='%s'\n", c_name); #endif *ier = (cgint_f)cg_sol_write((int)*fn, (int)*B, (int)*Z, c_name, *location, &i_S); *S = (cgint_f)i_S; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_sol_size_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *ndim, cgsize_t *dims, cgint_f *ier) { int i_ndim; *ier = (cgint_f)cg_sol_size((int)*fn, (int)*B, (int)*Z, (int)*S, &i_ndim, dims); *ndim = (cgint_f)i_ndim; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_sol_ptset_info_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, CGNS_ENUMT(PointSetType_t) *ptype, cgsize_t *npnts, cgint_f *ier) { CGNS_ENUMT(PointSetType_t) i_ptype; *ier = (cgint_f)cg_sol_ptset_info((int)*fn, (int)*B, (int)*Z, (int)*S, &i_ptype, npnts); *ptype = i_ptype; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_sol_ptset_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_sol_ptset_read((int)*fn, (int)*B, (int)*Z, (int)*S, pnts); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_sol_ptset_write_f, CG_SOL_PTSET_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(name), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptype, cgsize_t *npnts, cgsize_t *pnts, cgint_f *S, cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_S; string_2_C_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_sol_ptset_write((int)*fn, (int)*B, (int)*Z, c_name, *location, *ptype, *npnts, pnts, &i_S); *S = (cgint_f)i_S; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write solution DataArray_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nfields_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *nfields, cgint_f *ier) { int i_nfields; *ier = (cgint_f)cg_nfields((int)*fn, (int)*B, (int)*Z, (int)*S, &i_nfields); *nfields = (cgint_f)i_nfields; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_info_f, CG_FIELD_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *F, CGNS_ENUMT(DataType_t) *type, STR_PSTR(fieldname), cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(DataType_t) i_type; *ier = (cgint_f)cg_field_info((int)*fn, (int)*B, (int)*Z, (int)*S, (int)*F, &i_type, c_name); if (*ier) return; *type = i_type; string_2_F_string(c_name, STR_PTR(fieldname), STR_LEN(fieldname), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_read_f, CG_FIELD_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(fieldname), CGNS_ENUMT(DataType_t) *type, cgsize_t *rmin, cgsize_t *rmax, void *field_ptr, cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(fieldname), STR_LEN(fieldname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("fieldname='%s'\n", c_name); #endif *ier = (cgint_f)cg_field_read((int)*fn, (int)*B, (int)*Z, (int)*S, c_name, *type, rmin, rmax, field_ptr); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_general_read_f, CG_FIELD_GENERAL_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(fieldname), cgsize_t *s_rmin, cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) *m_type, cgint_f *m_numdim, cgsize_t *m_dimvals, cgsize_t *m_rmin, cgsize_t *m_rmax, void *field_ptr, cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(fieldname), STR_LEN(fieldname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("fieldname='%s'\n", c_name); #endif *ier = (cgint_f)cg_field_general_read( (int)*fn, (int)*B, (int)*Z, (int)*S, c_name, s_rmin, s_rmax, *m_type, (int)*m_numdim, m_dimvals, m_rmin, m_rmax, field_ptr); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_field_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *F, double *field_id, cgint_f *ier) { *ier = (cgint_f)cg_field_id((int)*fn, (int)*B, (int)*Z, (int)*S, (int)*F, field_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_write_f, CG_FIELD_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, CGNS_ENUMT(DataType_t) *type, STR_PSTR(fieldname), void *field_ptr, cgint_f *F, cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_F; string_2_C_string(STR_PTR(fieldname), STR_LEN(fieldname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" fieldname='%s'\n", c_name); #endif *ier = (cgint_f)cg_field_write((int)*fn, (int)*B, (int)*Z, (int)*S, *type, c_name, field_ptr, &i_F); *F = (cgint_f)i_F; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_partial_write_f, CG_FIELD_PARTIAL_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, CGNS_ENUMT(DataType_t) *type, STR_PSTR(fieldname), cgsize_t *rmin, cgsize_t *rmax, void *field_ptr, cgint_f *F, cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_F; string_2_C_string(STR_PTR(fieldname), STR_LEN(fieldname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" fieldname='%s'\n", c_name); #endif *ier = (cgint_f)cg_field_partial_write((int)*fn, (int)*B, (int)*Z, (int)*S, *type, c_name, rmin, rmax, field_ptr, &i_F); *F = (cgint_f)i_F; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_field_general_write_f, CG_FIELD_GENERAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(fieldname), CGNS_ENUMT(DataType_t) *s_type, cgsize_t *s_rmin, cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) *m_type, cgint_f *m_numdim, cgsize_t *m_dims, cgsize_t *m_rmin, cgsize_t *m_rmax, void *field_ptr, cgint_f *F, cgint_f *ier STR_PLEN(fieldname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_F; string_2_C_string(STR_PTR(fieldname), STR_LEN(fieldname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf(" fieldname='%s'\n", c_name); #endif *ier = (cgint_f)cg_field_general_write((int)*fn, (int)*B, (int)*Z, (int)*S, c_name, *s_type, s_rmin, s_rmax, *m_type, (int)*m_numdim, m_dims, m_rmin, m_rmax, field_ptr, &i_F); *F = (cgint_f)i_F; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneSubRegion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nsubregs_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nsubreg, cgint_f *ier) { int i_nsub; *ier = (cgint_f)cg_nsubregs((int)*fn, (int)*B, (int)*Z, &i_nsub); *nsubreg = (cgint_f)i_nsub; } CGNSDLL void FMNAME(cg_subreg_info_f, CG_SUBREG_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(regname), cgint_f *dimension, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgint_f *bcname_len, cgint_f *gcname_len, cgint_f *ier STR_PLEN(regname)) { char c_regname[CGIO_MAX_NAME_LENGTH+1]; int i_dimension, i_bcname_len, i_gcname_len; CGNS_ENUMT(GridLocation_t) i_location; CGNS_ENUMT(PointSetType_t) i_ptset_type; *ier = (cgint_f)cg_subreg_info((int)*fn, (int)*B, (int)*Z, (int)*S, c_regname, &i_dimension, &i_location, &i_ptset_type, npnts, &i_bcname_len, &i_gcname_len); if (*ier) return; string_2_F_string(c_regname, STR_PTR(regname), STR_LEN(regname), ier); *dimension = (cgint_f)i_dimension; *location = i_location; *ptset_type = i_ptset_type; *bcname_len = (cgint_f)i_bcname_len; *gcname_len = (cgint_f)i_gcname_len; } CGNSDLL void cg_subreg_ptset_read_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_subreg_ptset_read((int)*fn, (int)*B, (int)*Z, (int)*S, pnts); } CGNSDLL void FMNAME(cg_subreg_bcname_read_f, CG_SUBREG_BCNAME_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(bcname), cgint_f *ier STR_PLEN(bcname)) { char *name = 0; char regname[CGIO_MAX_NAME_LENGTH+1]; int dimension, bclen, gclen; CGNS_ENUMT(GridLocation_t) location; CGNS_ENUMT(PointSetType_t) ptset_type; cgsize_t npnts; *ier = (cgint_f)cg_subreg_info((int)*fn, (int)*B, (int)*Z, (int)*S, regname, &dimension, &location, &ptset_type, &npnts, &bclen, &gclen); if (*ier) return; if (bclen) name = CGNS_NEW(char, bclen+1); *ier = (cgint_f)cg_subreg_bcname_read((int)*fn, (int)*B, (int)*Z, (int)*S, name); if (!*ier && name) string_2_F_string(name, STR_PTR(bcname), STR_LEN(bcname), ier); CGNS_FREE(name); } CGNSDLL void FMNAME(cg_subreg_gcname_read_f, CG_SUBREG_GCNAME_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, STR_PSTR(gcname), cgint_f *ier STR_PLEN(gcname)) { char *name = 0; char regname[CGIO_MAX_NAME_LENGTH+1]; int dimension, bclen, gclen; CGNS_ENUMT(GridLocation_t) location; CGNS_ENUMT(PointSetType_t) ptset_type; cgsize_t npnts; *ier = (cgint_f)cg_subreg_info((int)*fn, (int)*B, (int)*Z, (int)*S, regname, &dimension, &location, &ptset_type, &npnts, &bclen, &gclen); if (*ier) return; if (gclen) name = CGNS_NEW(char, gclen+1); *ier = (cgint_f)cg_subreg_gcname_read((int)*fn, (int)*B, (int)*Z, (int)*S, name); if (!*ier && name) string_2_F_string(name, STR_PTR(gcname), STR_LEN(gcname), ier); CGNS_FREE(name); } CGNSDLL void FMNAME(cg_subreg_ptset_write_f, CG_SUBREG_PTSET_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(regname), cgint_f *dimension, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgsize_t *pnts, cgint_f *S, cgint_f *ier STR_PLEN(regname)) { char c_regname[CGIO_MAX_NAME_LENGTH+1]; int i_S; string_2_C_string(STR_PTR(regname), STR_LEN(regname), c_regname, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_subreg_ptset_write((int)*fn, (int)*B, (int)*Z, c_regname, (int)*dimension, *location, *ptset_type, *npnts, pnts, &i_S); *S = (cgint_f)i_S; } CGNSDLL void FMNAME(cg_subreg_bcname_write_f, CG_SUBREG_BCNAME_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(regname), cgint_f *dimension, STR_PSTR(bcname), cgint_f *S, cgint_f *ier STR_PLEN(regname) STR_PLEN(bcname)) { char c_regname[CGIO_MAX_NAME_LENGTH+1]; char *name; int length, i_S; string_2_C_string(STR_PTR(regname), STR_LEN(regname), c_regname, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; length = (int)STR_LEN(bcname); name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(bcname), STR_LEN(bcname), name, length, ier); if (!*ier) { *ier = (cgint_f)cg_subreg_bcname_write((int)*fn, (int)*B, (int)*Z, c_regname, (int)*dimension, name, &i_S); *S = (cgint_f)i_S; } CGNS_FREE(name); } CGNSDLL void FMNAME(cg_subreg_gcname_write_f, CG_SUBREG_GCNAME_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(regname), cgint_f *dimension, STR_PSTR(gcname), cgint_f *S, cgint_f *ier STR_PLEN(regname) STR_PLEN(gcname)) { char c_regname[CGIO_MAX_NAME_LENGTH+1]; char *name; int length, i_S; string_2_C_string(STR_PTR(regname), STR_LEN(regname), c_regname, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; length = (int)STR_LEN(gcname); name = CGNS_NEW(char, length+1); string_2_C_string(STR_PTR(gcname), STR_LEN(gcname), name, length, ier); if (!*ier) { *ier = (cgint_f)cg_subreg_gcname_write((int)*fn, (int)*B, (int)*Z, c_regname, (int)*dimension, name, &i_S); *S = (cgint_f)i_S; } CGNS_FREE(name); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneGridConnectivity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nzconns_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nzconns, cgint_f *ier) { int i_nzconns; *ier = (cgint_f)cg_nzconns((int)*fn, (int)*B, (int)*Z, &i_nzconns); *nzconns = (cgint_f)i_nzconns; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_zconn_read_f, CG_ZCONN_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, STR_PSTR(name), cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_zconn_read((int)*fn, (int)*B, (int)*Z, (int)*C, c_name); if (!*ier) string_2_F_string(c_name, STR_PTR(name), STR_LEN(name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_zconn_write_f, CG_ZCONN_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(name), cgint_f *C, cgint_f *ier STR_PLEN(name)) { int i_C; char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_zconn_write((int)*fn, (int)*B, (int)*Z, c_name, &i_C); *C = (cgint_f)i_C; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_zconn_get_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgint_f *ier) { int i_C; *ier = (cgint_f)cg_zconn_get((int)*fn, (int)*B, (int)*Z, &i_C); *C = (cgint_f)i_C; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_zconn_set_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgint_f *ier) { *ier = (cgint_f)cg_zconn_set((int)*fn, (int)*B, (int)*Z, (int)*C); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write OversetHoles_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nholes_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nholes, cgint_f *ier) { int i_nholes; *ier = (cgint_f)cg_nholes((int)*fn, (int)*B, (int)*Z, &i_nholes); *nholes = (cgint_f)i_nholes; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_hole_info_f, CG_HOLE_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, STR_PSTR(holename), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *nptsets, cgsize_t *npnts, cgint_f *ier STR_PLEN(holename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(GridLocation_t) i_location; CGNS_ENUMT(PointSetType_t) i_ptset_type; int i_nptsets; *ier = (cgint_f)cg_hole_info((int)*fn, (int)*B, (int)*Z, (int)*I, c_name, &i_location, &i_ptset_type, &i_nptsets, npnts); if (*ier) return; *location = i_location; *ptset_type = i_ptset_type; *nptsets = i_nptsets; string_2_F_string(c_name, STR_PTR(holename), STR_LEN(holename), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_hole_read_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_hole_read((int)*fn, (int)*B, (int)*Z, (int)*I, pnts); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_hole_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, double *hole_id, cgint_f *ier) { *ier = (cgint_f)cg_hole_id((int)*fn, (int)*B, (int)*Z, (int)*I, hole_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_hole_write_f, CG_HOLE_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(holename), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgint_f *nptsets, cgsize_t *npnts, cgsize_t *pnts, cgint_f *I, cgint_f *ier STR_PLEN(holename)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_I; string_2_C_string(STR_PTR(holename), STR_LEN(holename), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("holename='%s'\n", c_name); #endif *ier = (cgint_f)cg_hole_write((int)*fn, (int)*B, (int)*Z, c_name, *location, *ptset_type, (int)*nptsets, *npnts, pnts, &i_I); *I = (cgint_f)i_I; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nconns_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nconns, cgint_f *ier) { int i_nconns; *ier = (cgint_f)cg_nconns((int)*fn, (int)*B, (int)*Z, &i_nconns); *nconns = (cgint_f)i_nconns; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_conn_info_f, CG_CONN_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, STR_PSTR(connectname), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(GridConnectivityType_t) *type, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, STR_PSTR(donorname), CGNS_ENUMT(ZoneType_t) *donor_zonetype, CGNS_ENUMT(PointSetType_t) *donor_ptset_type, CGNS_ENUMT(DataType_t) *donor_datatype, cgsize_t *ndata_donor, cgint_f *ier STR_PLEN(connectname) STR_PLEN(donorname)) { char cc_name[CGIO_MAX_NAME_LENGTH+1], dc_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(GridLocation_t) i_location; CGNS_ENUMT(GridConnectivityType_t) i_type; CGNS_ENUMT(PointSetType_t) i_ptset_type; CGNS_ENUMT(ZoneType_t) i_donor_zonetype; CGNS_ENUMT(PointSetType_t) i_donor_ptset_type; CGNS_ENUMT(DataType_t) i_donor_datatype; *ier = (cgint_f)cg_conn_info((int)*fn, (int)*B, (int)*Z, (int)*I, cc_name, &i_location, &i_type, &i_ptset_type, npnts, dc_name, &i_donor_zonetype, &i_donor_ptset_type, &i_donor_datatype, ndata_donor); if (*ier) return; string_2_F_string(cc_name, STR_PTR(connectname), STR_LEN(connectname), ier); if (*ier) return; string_2_F_string(dc_name, STR_PTR(donorname), STR_LEN(donorname), ier); if (*ier) return; *location = i_location; *type = i_type; *ptset_type = i_ptset_type; *donor_zonetype = i_donor_zonetype; *donor_ptset_type = i_donor_ptset_type; *donor_datatype = i_donor_datatype; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_conn_read_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, cgsize_t *pnts, CGNS_ENUMT(DataType_t) *donor_datatype, cgsize_t *donor_data, cgint_f *ier) { *ier = (cgint_f)cg_conn_read((int)*fn, (int)*B, (int)*Z, (int)*I, pnts, *donor_datatype, donor_data); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_conn_read_short_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_conn_read_short((int)*fn, (int)*B, (int)*Z, (int)*I, pnts); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_conn_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, double *conn_id, cgint_f *ier) { *ier = (cgint_f)cg_conn_id((int)*fn, (int)*B, (int)*Z, (int)*I, conn_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_conn_write_f, CG_CONN_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(connectname), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(GridConnectivityType_t) *type, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgsize_t *pnts, STR_PSTR(donorname), CGNS_ENUMT(ZoneType_t)*donor_zonetype, CGNS_ENUMT(PointSetType_t)*donor_ptset_type, CGNS_ENUMT(DataType_t)*donor_datatype, cgsize_t *ndata_donor, cgsize_t *donor_data, cgint_f *I, cgint_f *ier STR_PLEN(connectname) STR_PLEN(donorname)) { char cc_name[CGIO_MAX_NAME_LENGTH+1], dc_name[CGIO_MAX_NAME_LENGTH+1]; int i_I; string_2_C_string(STR_PTR(connectname), STR_LEN(connectname), cc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; string_2_C_string(STR_PTR(donorname), STR_LEN(donorname), dc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("connectname='%s'\n", cc_name); printf("donorname='%s'\n", dc_name); #endif *ier = (cgint_f)cg_conn_write((int)*fn, (int)*B, (int)*Z, cc_name, *location, *type, *ptset_type, *npnts, pnts, dc_name, *donor_zonetype, *donor_ptset_type, *donor_datatype, *ndata_donor, donor_data, &i_I); *I = (cgint_f)i_I; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_conn_write_short_f, CG_CONN_WRITE_SHORT_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(connectname), CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(GridConnectivityType_t) *type, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgsize_t *pnts, STR_PSTR(donorname), cgint_f *I, cgint_f *ier STR_PLEN(connectname) STR_PLEN(donorname)) { char cc_name[CGIO_MAX_NAME_LENGTH+1], dc_name[CGIO_MAX_NAME_LENGTH+1]; int i_I; string_2_C_string(STR_PTR(connectname), STR_LEN(connectname), cc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; string_2_C_string(STR_PTR(donorname), STR_LEN(donorname), dc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("connectname='%s'\n", cc_name); printf("donorname='%s'\n", dc_name); #endif *ier = (cgint_f)cg_conn_write_short((int)*fn, (int)*B, (int)*Z, cc_name, *location, *type, *ptset_type, *npnts, pnts, dc_name, &i_I); *I = (cgint_f)i_I; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivity1to1_t Nodes in a zone * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_n1to1_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f*n1to1, cgint_f *ier) { int i_n1to1; *ier = (cgint_f)cg_n1to1((int)*fn, (int)*B, (int)*Z, &i_n1to1); *n1to1 = (cgint_f)i_n1to1; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_1to1_read_f, CG_1TO1_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, STR_PSTR(connectname), STR_PSTR(donorname), cgsize_t *range, cgsize_t *donor_range, cgint_f *transform, cgint_f *ier STR_PLEN(connectname) STR_PLEN(donorname)) { char cc_name[CGIO_MAX_NAME_LENGTH+1], dc_name[CGIO_MAX_NAME_LENGTH+1]; int n, index_dim, i_transform[3]; *ier = (cgint_f)cg_index_dim((int)*fn, (int)*B, (int)*Z, &index_dim); if (*ier) return; *ier = (cgint_f)cg_1to1_read((int)*fn, (int)*B, (int)*Z, (int)*I, cc_name, dc_name, range, donor_range, i_transform); if (*ier) return; string_2_F_string(cc_name, STR_PTR(connectname), STR_LEN(connectname), ier); if (*ier) return; string_2_F_string(dc_name, STR_PTR(donorname), STR_LEN(donorname), ier); if (*ier) return; for (n = 0; n < index_dim; n++) transform[n] = (cgint_f)i_transform[n]; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_1to1_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, double *one21_id, cgint_f *ier) { *ier = (cgint_f)cg_1to1_id((int)*fn, (int)*B, (int)*Z, (int)*I, one21_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_1to1_write_f, CG_1TO1_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(connectname), STR_PSTR(donorname), cgsize_t *range, cgsize_t *donor_range, cgint_f *transform, cgint_f *I, cgint_f *ier STR_PLEN(connectname) STR_PLEN(donorname)) { char cc_name[CGIO_MAX_NAME_LENGTH+1], dc_name[CGIO_MAX_NAME_LENGTH+1]; int n, index_dim, i_I, i_transform[3]; *ier = (cgint_f)cg_index_dim((int)*fn, (int)*B, (int)*Z, &index_dim); if (*ier) return; string_2_C_string(STR_PTR(connectname), STR_LEN(connectname), cc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; string_2_C_string(STR_PTR(donorname), STR_LEN(donorname), dc_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("connectname='%s'\n", cc_name); printf("donorname='%s'\n", dc_name); #endif for (n = 0; n < index_dim; n++) i_transform[n] = (int)transform[n]; *ier = (cgint_f)cg_1to1_write((int)*fn, (int)*B, (int)*Z, cc_name, dc_name, range, donor_range, i_transform, &i_I); *I = (cgint_f)i_I; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read all GridConnectivity1to1_t Nodes of a base * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_n1to1_global_f(cgint_f *fn, cgint_f *B, cgint_f *n1to1_global, cgint_f *ier) { int i_n1to1_global; *ier = (cgint_f)cg_n1to1_global((int)*fn, (int)*B, &i_n1to1_global); *n1to1_global = (cgint_f)i_n1to1_global; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_1to1_read_global_f, CG_1TO1_READ_GLOBAL_F) (cgint_f *fn, cgint_f *B, STR_PSTR(connectname), STR_PSTR(zonename), STR_PSTR(donorname), cgsize_t *range, cgsize_t *donor_range, cgint_f *transform, cgint_f *ier STR_PLEN(connectname) STR_PLEN(zonename) STR_PLEN(donorname)) { int n, i, step, len; int cell_dim, phys_dim; /* number of dimension for model */ int Ndim; /* indexDimension */ int Nglobal; /* number of 1to1 interface in base */ char **c_connectname, **c_zonename, **c_donorname; char basename[CGIO_MAX_NAME_LENGTH+1]; cgsize_t **c_range, **c_donor_range; int **c_transform; /* get number of dimension for model: Ndim */ *ier = (cgint_f)cg_base_read((int)*fn, (int)*B, basename, &cell_dim, &phys_dim); if (*ier) return; /* For structured grid: */ Ndim = cell_dim; /* get number of 1to1 interface in base: Nglobal */ *ier = (cgint_f)cg_n1to1_global((int)*fn, (int)*B, &Nglobal); if (*ier) return; if (Nglobal < 1) { cgi_error("Number of interface must equal 1 or more"); *ier = 1; return; } /* allocate memory for C-arrays (ptr-to-ptr) */ if ((c_connectname = (char **)malloc(Nglobal*sizeof(char *)))==NULL || (c_zonename = (char **)malloc(Nglobal*sizeof(char *)))==NULL || (c_donorname = (char **)malloc(Nglobal*sizeof(char *)))==NULL || (c_range = (cgsize_t **)malloc(Nglobal*sizeof(cgsize_t *)))==NULL || (c_donor_range = (cgsize_t **)malloc(Nglobal*sizeof(cgsize_t *)))==NULL || (c_transform = (int **)malloc(Nglobal*sizeof(int *)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; goto cleanup; } len = CGIO_MAX_NAME_LENGTH+1; for (n = 0; n < Nglobal; n++) { if ((c_connectname[n] = (char *)malloc(len*sizeof(char)))==NULL || (c_zonename[n] = (char *)malloc(len*sizeof(char)))==NULL || (c_donorname[n] = (char *)malloc(len*sizeof(char)))==NULL || (c_range[n] = (cgsize_t *)malloc(6*sizeof(cgsize_t)))==NULL || (c_donor_range[n] = (cgsize_t *)malloc(6*sizeof(cgsize_t)))==NULL || (c_transform[n] = (int *)malloc(3*sizeof(int)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; goto cleanup; } } /* get all 1to1 interfaces */ *ier = (cgint_f)cg_1to1_read_global((int)*fn, (int)*B, c_connectname, c_zonename, c_donorname, c_range, c_donor_range, c_transform); /* copy C-arrays in Fortran arrays */ if (*ier == 0) { for (n = 0; n < Nglobal; n++) { step = n*CGIO_MAX_NAME_LENGTH; string_2_F_string(c_connectname[n], STR_PTR(connectname)+step, CGIO_MAX_NAME_LENGTH, ier); if (*ier) break; string_2_F_string(c_zonename[n], STR_PTR(zonename) +step, CGIO_MAX_NAME_LENGTH, ier); if (*ier) break; string_2_F_string(c_donorname[n], STR_PTR(donorname) +step, CGIO_MAX_NAME_LENGTH, ier); if (*ier) break; for (i = 0; i < Ndim; i++) { step = Ndim*2*n; range[step+i] = c_range[n][i]; range[step+i+Ndim] = c_range[n][i+Ndim]; donor_range[step+i] = c_donor_range[n][i]; donor_range[step+i+Ndim] = c_donor_range[n][i+Ndim]; transform[Ndim*n+i] = (cgint_f)c_transform[n][i]; } #if DEBUG_FTOC printf("c_connectname[n]='%s'\n",c_connectname[n]); printf("c_zonename [n]='%s'\n",c_zonename[n]); printf("c_donorname [n]='%s'\n",c_donorname[n]); printf("..................12345678901234567890123456789012\n"); #endif } #if DEBUG_FTOC printf("connectname='%s'\n",connectname); printf("zonename ='%s'\n",zonename); printf("donorname ='%s'\n",donorname); printf(".............+2345678901234567890123456789012+2345678901234567890123456789012\n"); #endif } cleanup: for (n = 0; n < Nglobal; n++) { CGNS_FREE(c_connectname[n]); CGNS_FREE(c_zonename[n]); CGNS_FREE(c_donorname[n]); CGNS_FREE(c_range[n]); CGNS_FREE(c_donor_range[n]); CGNS_FREE(c_transform[n]); } CGNS_FREE(c_connectname); CGNS_FREE(c_zonename); CGNS_FREE(c_donorname); CGNS_FREE(c_range); CGNS_FREE(c_donor_range); CGNS_FREE(c_transform); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BC_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_nbocos_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *nbocos, cgint_f *ier) { int i_nbocos; *ier = (cgint_f)cg_nbocos((int)*fn, (int)*B, (int)*Z, &i_nbocos); *nbocos = (cgint_f)i_nbocos; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_boco_info_f, CG_BOCO_INFO_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, STR_PSTR(boconame), CGNS_ENUMT(BCType_t) *bocotype, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgint_f *NormalIndex, cgsize_t *NormalListSize, CGNS_ENUMT(DataType_t) *NormalDataType, cgint_f *ndataset, cgint_f *ier STR_PLEN(boconame)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(BCType_t) i_bocotype; CGNS_ENUMT(PointSetType_t) i_ptset_type; CGNS_ENUMT(DataType_t) i_NormalDataType; int n, i_ndataset, index_dim, i_NormalIndex[3]; *ier = (cgint_f)cg_index_dim((int)*fn, (int)*B, (int)*Z, &index_dim); if (*ier) return; *ier = (cgint_f)cg_boco_info((int)*fn, (int)*B, (int)*Z, (int)*BC, c_name, &i_bocotype, &i_ptset_type, npnts, i_NormalIndex, NormalListSize, &i_NormalDataType, &i_ndataset); if (*ier) return; string_2_F_string(c_name, STR_PTR(boconame), STR_LEN(boconame), ier); *bocotype = i_bocotype; *ptset_type = i_ptset_type; *NormalDataType = i_NormalDataType; *ndataset = (cgint_f)i_ndataset; for (n = 0; n < index_dim; n++) NormalIndex[n] = (cgint_f)i_NormalIndex[n]; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_boco_read_f,CG_BOCO_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, cgsize_t *pnts, void *NormalList, cgint_f *ier) { *ier = (cgint_f)cg_boco_read((int)*fn, (int)*B, (int)*Z, (int)*BC, pnts, NormalList); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_boco_id_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, double *boco_id, cgint_f *ier) { *ier = (cgint_f)cg_boco_id((int)*fn, (int)*B, (int)*Z, (int)*BC, boco_id); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_boco_write_f, CG_BOCO_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(boconame), CGNS_ENUMT(BCType_t) *bocotype, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgsize_t *pnts, cgint_f *BC, cgint_f *ier STR_PLEN(boconame)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_BC; string_2_C_string(STR_PTR(boconame), STR_LEN(boconame), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("boconame='%s'\n", c_name); #endif *ier = (cgint_f)cg_boco_write((int)*fn, (int)*B, (int)*Z, c_name, *bocotype, *ptset_type, *npnts, pnts, &i_BC); *BC = (cgint_f)i_BC; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_boco_normal_write_f, CG_BOCO_NORMAL_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, cgsize_t *NormalIndex, cgint_f *NormalListFlag, CGNS_ENUMT(DataType_t) *NormalDataType, void *NormalList, cgint_f *ier) { int n, index_dim, i_NormalIndex[3]; *ier = (cgint_f)cg_index_dim((int)*fn, (int)*B, (int)*Z, &index_dim); if (*ier) return; for (n = 0; n < index_dim; n++) i_NormalIndex[n] = (int)NormalIndex[n]; *ier = (cgint_f)cg_boco_normal_write((int)*fn, (int)*B, (int)*Z, (int)*BC, i_NormalIndex, (int)*NormalListFlag, *NormalDataType, NormalList); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_boco_gridlocation_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(GridLocation_t) *location, cgint_f *ier) { CGNS_ENUMT(GridLocation_t) i_location; *ier = (cgint_f)cg_boco_gridlocation_read((int)*fn, (int)*B, (int)*Z, (int)*BC, &i_location); *location = i_location; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_boco_gridlocation_write_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(GridLocation_t) *location, cgint_f *ier) { *ier = (cgint_f)cg_boco_gridlocation_write((int)*fn, (int)*B, (int)*Z, (int)*BC, *location); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCProperty_t/WallFunction_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_bc_wallfunction_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(WallFunctionType_t) *WallFunctionType, cgint_f *ier) { CGNS_ENUMT(WallFunctionType_t) i_WallFunctionType; *ier = (cgint_f)cg_bc_wallfunction_read((int)*fn, (int)*B, (int)*Z, (int)*BC, &i_WallFunctionType); *WallFunctionType = i_WallFunctionType; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_bc_wallfunction_write_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(WallFunctionType_t) *WallFunctionType, cgint_f *ier) { *ier = (cgint_f)cg_bc_wallfunction_write((int)*fn, (int)*B, (int)*Z, (int)*BC, *WallFunctionType); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCProperty_t/Area_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_bc_area_read_f, CG_BC_AREA_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(AreaType_t) *AreaType, float *SurfaceArea, STR_PSTR(RegionName), cgint_f *ier STR_PLEN(RegionName)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(AreaType_t) i_AreaType; *ier = (cgint_f)cg_bc_area_read((int)*fn, (int)*B, (int)*Z, (int)*BC, &i_AreaType, SurfaceArea, c_name); if (*ier) return; string_2_F_string(c_name, STR_PTR(RegionName), STR_LEN(RegionName), ier); *AreaType = i_AreaType; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_bc_area_write_f, CG_BC_AREA_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, CGNS_ENUMT(AreaType_t) *AreaType, float *SurfaceArea, STR_PSTR(RegionName), cgint_f *ier STR_PLEN(RegionName)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; #if DEBUG_FTOC int n; #endif string_2_C_string(STR_PTR(RegionName), STR_LEN(RegionName), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("RegionName='"); for (n=0; n<32; n++) printf("%c",*((STR_PTR(RegionName))+n)); printf("', c_name='%s'\n", c_name); #endif *ier = (cgint_f)cg_bc_area_write((int)*fn, (int)*B, (int)*Z, (int)*BC, *AreaType, *SurfaceArea, c_name); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivityProperty_t/Periodic_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_conn_periodic_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, float *RotationCenter, float *RotationAngle, float *Translation, cgint_f *ier) { *ier = (cgint_f)cg_conn_periodic_read((int)*fn, (int)*B, (int)*Z, (int)*I, RotationCenter, RotationAngle, Translation); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_conn_periodic_write_f ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, float *RotationCenter, float *RotationAngle, float *Translation, cgint_f *ier) { *ier = (cgint_f)cg_conn_periodic_write((int)*fn, (int)*B, (int)*Z, (int)*I, RotationCenter, RotationAngle, Translation); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_1to1_periodic_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, float *RotationCenter, float *RotationAngle, float *Translation, cgint_f *ier) { *ier = (cgint_f)cg_1to1_periodic_read((int)*fn, (int)*B, (int)*Z, (int)*I, RotationCenter, RotationAngle, Translation); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_1to1_periodic_write_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, float *RotationCenter, float *RotationAngle, float *Translation, cgint_f *ier) { *ier = (cgint_f)cg_1to1_periodic_write((int)*fn, (int)*B, (int)*Z, (int)*I, RotationCenter, RotationAngle, Translation); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivityProperty_t/AverageInterface_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_conn_average_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType, cgint_f *ier) { CGNS_ENUMT(AverageInterfaceType_t) i_AverageInterfaceType; *ier = (cgint_f)cg_conn_average_read((int)*fn, (int)*B, (int)*Z, (int)*I, &i_AverageInterfaceType); *AverageInterfaceType = i_AverageInterfaceType; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_conn_average_write_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType, cgint_f *ier) { *ier = (cgint_f)cg_conn_average_write((int)*fn, (int)*B, (int)*Z, (int)*I, *AverageInterfaceType); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_1to1_average_read_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType, cgint_f *ier) { CGNS_ENUMT(AverageInterfaceType_t) i_AverageInterfaceType; *ier = (cgint_f)cg_1to1_average_read((int)*fn, (int)*B, (int)*Z, (int)*I, &i_AverageInterfaceType); *AverageInterfaceType = i_AverageInterfaceType; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_1to1_average_write_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType, cgint_f *ier) { *ier = (cgint_f)cg_1to1_average_write((int)*fn, (int)*B, (int)*Z, (int)*I, *AverageInterfaceType); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCDataSet_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_dataset_read_f, CG_DATASET_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, cgint_f *DSet, STR_PSTR(Dataset_name), CGNS_ENUMT(BCType_t) *BCType, cgint_f *DirichletFlag, cgint_f *NeumannFlag, cgint_f *ier STR_PLEN(Dataset_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(BCType_t) i_BCType; int i_DirichletFlag, i_NeumannFlag; *ier = (cgint_f)cg_dataset_read((int)*fn, (int)*B, (int)*Z, (int)*BC, (int)*DSet, c_name, &i_BCType, &i_DirichletFlag, &i_NeumannFlag); if (*ier) return; string_2_F_string(c_name, STR_PTR(Dataset_name), STR_LEN(Dataset_name), ier); *BCType = i_BCType; *DirichletFlag = (cgint_f)i_DirichletFlag; *NeumannFlag = (cgint_f)i_NeumannFlag; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_dataset_write_f, CG_DATASET_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, STR_PSTR(Dataset_name), CGNS_ENUMT(BCType_t) *BCType, cgint_f *Dset, cgint_f *ier STR_PLEN(Dataset_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_Dset; string_2_C_string(STR_PTR(Dataset_name), STR_LEN(Dataset_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("Dataset_name='%s'\n", c_name); #endif *ier = (cgint_f)cg_dataset_write((int)*fn, (int)*B, (int)*Z, (int)*BC, c_name, *BCType, &i_Dset); *Dset = (cgint_f)i_Dset; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_bcdataset_write_f, CG_BCDATASET_WRITE_F) ( STR_PSTR(Dataset_name), CGNS_ENUMT(BCType_t) *BCType, CGNS_ENUMT(BCDataType_t) *BCDataType, cgint_f *ier STR_PLEN(Dataset_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(Dataset_name), STR_LEN(Dataset_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; #if DEBUG_FTOC printf("Dataset_name='%s'\n", c_name); #endif *ier = (cgint_f)cg_bcdataset_write(c_name, *BCType, *BCDataType); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_bcdataset_info_f( cgint_f *ndataset, cgint_f *ier STR_PLEN(Dataset_name)) { int i_ndataset; *ier = (cgint_f)cg_bcdataset_info(&i_ndataset); *ndataset = (cgint_f)i_ndataset; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_bcdataset_read_f, CG_BCDATASET_READ_F) ( cgint_f *index, STR_PSTR(Dataset_name), CGNS_ENUMT(BCType_t) *BCType, cgint_f *DirichletFlag, cgint_f *NeumannFlag, cgint_f *ier STR_PLEN(Dataset_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(BCType_t) i_BCType; int i_DirichletFlag, i_NeumannFlag; *ier = (cgint_f)cg_bcdataset_read((int)*index, c_name, &i_BCType, &i_DirichletFlag, &i_NeumannFlag); if (*ier) return; *BCType = i_BCType; *DirichletFlag = (cgint_f)i_DirichletFlag; *NeumannFlag = (cgint_f)i_NeumannFlag; string_2_F_string(c_name, STR_PTR(Dataset_name), STR_LEN(Dataset_name), ier); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_bcdata_write_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *BC, cgint_f *Dset, CGNS_ENUMT(BCDataType_t) *BCDataType, cgint_f *ier) { *ier = (cgint_f)cg_bcdata_write((int)*fn, (int)*B, (int)*Z, (int)*BC, (int)*Dset, *BCDataType); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write RigidGridMotion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_n_rigid_motions_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *n_rigid_motions, cgint_f *ier) { int i_n_rigid_motions; *ier = (cgint_f)cg_n_rigid_motions((int)*fn, (int)*B, (int)*Z, &i_n_rigid_motions); *n_rigid_motions = (cgint_f)i_n_rigid_motions; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_rigid_motion_read_f, CG_RIGID_MOTION_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *R, STR_PSTR(rmotion_name), CGNS_ENUMT(RigidGridMotionType_t) *type, cgint_f *ier STR_PLEN(rmotion_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(RigidGridMotionType_t) i_type; *ier = (cgint_f)cg_rigid_motion_read((int)*fn, (int)*B, (int)*Z, (int)*R, c_name, &i_type); if (*ier) return; *type = i_type; string_2_F_string(c_name, STR_PTR(rmotion_name), STR_LEN(rmotion_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_rigid_motion_write_f, CG_RIGID_MOTION_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(rmotion_name), CGNS_ENUMT(RigidGridMotionType_t) *type, cgint_f *R, cgint_f *ier STR_PLEN(rmotion_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_R; string_2_C_string(STR_PTR(rmotion_name), STR_LEN(rmotion_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_rigid_motion_write((int)*fn, (int)*B, (int)*Z, c_name, *type, &i_R); *R = (cgint_f)i_R; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ArbitraryGridMotion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_n_arbitrary_motions_f( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *n_arbitrary_motions, cgint_f *ier) { int i_n_arbitrary_motions; *ier = (cgint_f)cg_n_arbitrary_motions((int)*fn, (int)*B, (int)*Z, &i_n_arbitrary_motions); *n_arbitrary_motions = (cgint_f)i_n_arbitrary_motions; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_arbitrary_motion_read_f, CG_ARBITRARY_MOTION_READ_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *A, STR_PSTR(amotion_name), CGNS_ENUMT(ArbitraryGridMotionType_t) *type, cgint_f *ier STR_PLEN(amotion_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; CGNS_ENUMT(ArbitraryGridMotionType_t) i_type; *ier = (cgint_f)cg_arbitrary_motion_read((int)*fn, (int)*B, (int)*Z, (int)*A, c_name, &i_type); if (*ier) return; *type = i_type; string_2_F_string(c_name, STR_PTR(amotion_name), STR_LEN(amotion_name), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_arbitrary_motion_write_f, CG_ARBITRARY_MOTION_WRITE_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(amotion_name), CGNS_ENUMT(ArbitraryGridMotionType_t) *type, cgint_f *A, cgint_f *ier STR_PLEN(amotion_name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_A; string_2_C_string(STR_PTR(amotion_name), STR_LEN(amotion_name), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_arbitrary_motion_write((int)*fn, (int)*B, (int)*Z, c_name, *type, &i_A); *A = (cgint_f)i_A; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridCoordinates_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_ngrids_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *ngrids, cgint_f *ier) { int i_ngrids; *ier = (cgint_f)cg_ngrids((int)*fn, (int)*B, (int)*Z, &i_ngrids); *ngrids = (cgint_f)i_ngrids; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_grid_read_f, CG_GRID_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *G, STR_PSTR(gridname), cgint_f *ier STR_PLEN(gridname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_grid_read((int)*fn, (int)*B, (int)*Z, (int)*G, c_name); if (!*ier) string_2_F_string(c_name, STR_PTR(gridname), STR_LEN(gridname), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_grid_write_f, CG_GRID_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(gridname), cgint_f *G, cgint_f *ier STR_PLEN(gridname)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_G; string_2_C_string(STR_PTR(gridname), STR_LEN(gridname), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier) return; *ier = (cgint_f)cg_grid_write((int)*fn, (int)*B, (int)*Z, c_name, &i_G); *G = (cgint_f)i_G; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write SimulationType_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_simulation_type_read_f ( cgint_f *fn, cgint_f *B, CGNS_ENUMT(SimulationType_t) *type, cgint_f *ier) { CGNS_ENUMT(SimulationType_t) i_type; *ier = (cgint_f)cg_simulation_type_read((int)*fn, (int)*B, &i_type); *type = i_type; } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_simulation_type_write_f( cgint_f *fn, cgint_f *B, CGNS_ENUMT(SimulationType_t) *type, cgint_f *ier) { *ier = (cgint_f)cg_simulation_type_write((int)*fn, (int)*B, *type); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BaseIterativeData_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_biter_read_f, CG_BITER_READ_F) (cgint_f *fn, cgint_f *B, STR_PSTR(bitername), cgint_f *nsteps, cgint_f *ier STR_PLEN(bitername)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; int i_nsteps; *ier = (cgint_f)cg_biter_read((int)*fn, (int)*B, c_name, &i_nsteps); if (*ier) return; *nsteps = (cgint_f)i_nsteps; string_2_F_string(c_name, STR_PTR(bitername), STR_LEN(bitername), ier); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_biter_write_f, CG_BITER_WRITE_F) (cgint_f *fn, cgint_f *B, STR_PSTR(bitername), cgint_f *nsteps, cgint_f *ier STR_PLEN(bitername)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(bitername), STR_LEN(bitername), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier == 0) *ier = (cgint_f)cg_biter_write((int)*fn, (int)*B, c_name, (int)*nsteps); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneIterativeData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cg_ziter_read_f, CG_ZITER_READ_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(zitername), cgint_f *ier STR_PLEN(zitername)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cg_ziter_read((int)*fn, (int)*B, (int)*Z, c_name); if (*ier == 0) { string_2_F_string(c_name, STR_PTR(zitername), STR_LEN(zitername), ier); } } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_ziter_write_f, CG_ZITER_WRITE_F) (cgint_f *fn, cgint_f *B, cgint_f *Z, STR_PSTR(zitername), cgint_f *ier STR_PLEN(zitername)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; string_2_C_string(STR_PTR(zitername), STR_LEN(zitername), c_name, CGIO_MAX_NAME_LENGTH, ier); if (*ier == 0) *ier = (cgint_f)cg_ziter_write((int)*fn, (int)*B, (int)*Z, c_name); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Gravity_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_gravity_read_f(cgint_f *fn, cgint_f *B, float *gravity_vector, cgint_f *ier) { *ier = (cgint_f)cg_gravity_read((int)*fn, (int)*B, gravity_vector); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_gravity_write_f(cgint_f *fn, cgint_f *B, float *gravity_vector, cgint_f *ier) { *ier = (cgint_f)cg_gravity_write((int)*fn, (int)*B, gravity_vector); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Axisymmetry_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_axisym_read_f(cgint_f *fn, cgint_f *B, float *ref_point, float *axis, cgint_f *ier) { *ier = (cgint_f)cg_axisym_read((int)*fn, (int)*B, ref_point, axis); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_axisym_write_f(cgint_f *fn, cgint_f *B, float *ref_point, float *axis, cgint_f *ier) { *ier = (cgint_f)cg_axisym_write((int)*fn, (int)*B, ref_point, axis); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write RotatingCoordinates_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_rotating_read_f( float *rot_rate, float *rot_center, cgint_f *ier) { *ier = (cgint_f)cg_rotating_read(rot_rate, rot_center); } /*-----------------------------------------------------------------------*/ CGNSDLL void cg_rotating_write_f( float *rot_rate, float *rot_center, cgint_f *ier) { *ier = (cgint_f)cg_rotating_write(rot_rate, rot_center); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write IndexArray/Range_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void cg_ptset_info_f( CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgint_f *ier) { CGNS_ENUMT(PointSetType_t) i_ptset_type; *ier = (cgint_f)cg_ptset_info(&i_ptset_type, npnts); *ptset_type = i_ptset_type; } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_ptset_read_f, CG_PTSET_READ_F) (cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_ptset_read(pnts); } /*-----------------------------------------------------------------------*/ CGNSDLL void FMNAME(cg_ptset_write_f, CG_PTSET_WRITE_F) ( CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, cgsize_t *pnts, cgint_f *ier) { *ier = (cgint_f)cg_ptset_write(*ptset_type, *npnts, pnts); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Go - To Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef WIN32_FORTRAN CGNSDLL void __stdcall cg_goto_f(cgint_f *fn, cgint_f *B, cgint_f *ier, ...) #else CGNSDLL void FMNAME(cg_goto_f, CG_GOTO_F)(cgint_f *fn, cgint_f *B, cgint_f *ier, ...) #endif { #ifdef _CRAY _fcd cray_string; #endif char *f_label[CG_MAX_GOTO_DEPTH], *label[CG_MAX_GOTO_DEPTH]; int index[CG_MAX_GOTO_DEPTH], n, i, len[CG_MAX_GOTO_DEPTH]; va_list ap; /* initialize ap to the last parameter before the variable argument list */ /* Note: On HP, print statements btw va_start and va_end create major problems */ va_start(ap, ier); /* read arguments */ for (n = 0; n < CG_MAX_GOTO_DEPTH; n++) { #ifdef _CRAY cray_string = va_arg(ap, _fcd); f_label[n] = _fcdtocp(cray_string); len[n] = _fcdlen(cray_string); #else f_label[n] = va_arg(ap, char *); # ifdef WIN32_FORTRAN /* In Windows, the arguments appear in a different order: char*, len, index,...*/ len[n] = (int)va_arg(ap, int); # endif #endif if (f_label[n][0] == ' ' || 0 == strncmp(f_label[n],"end",3) || 0 == strncmp(f_label[n],"END",3)) break; index[n] = (int)*(va_arg(ap, cgint_f *)); if (index[n] < 0) { cgi_error("Incorrect input to function cg_goto_f"); *ier = 1; return; } } #if !defined(_CRAY) && !defined(WIN32_FORTRAN) for (i=0; idata_type, "C1")) (void) va_arg(ap, int); ier = va_arg(ap, cgsize_t *); va_end(ap); #else CGNSDLL void FMNAME(cgp_array_write_data_f, CGP_ARRAY_WRITE_DATA_F) ( cgint_f *A, cgsize_t *rmin, cgsize_t *rmax, void *data, cgint_f *ier) { #endif *ier = (cgint_f)cgp_array_write_data((int)*A, rmin, rmax, data); } /*-----------------------------------------------------------------------*/ #ifdef WIN32_FORTRAN CGNSDLL void __stdcall cgp_array_read_data_f(cgint_f *A, cgsize_t *rmin, cgsize_t *rmax, void *data, ...) { va_list ap; int ierr; cgint_f *ier; cgns_array *array; int have_dup = 0; array = cgi_array_address(CG_MODE_READ, 0, (int)*A, "dummy", &have_dup, &ierr); if (array == NULL) return; va_start(ap, data); if (0 == strcmp(array->data_type, "C1")) (void) va_arg(ap, int); ier = va_arg(ap, cgsize_t *); va_end(ap); #else CGNSDLL void FMNAME(cgp_array_read_data_f, CGP_ARRAY_READ_DATA_F) ( cgint_f *A, cgsize_t *rmin, cgsize_t *rmax, void *data, cgint_f *ier) { #endif *ier = (cgint_f)cgp_array_read_data((int)*A, rmin, rmax, data); } /*-----------------------------------------------------------------------*/ CGNSDLL void cgp_error_exit_f() { cgp_error_exit(); } #if HDF5_HAVE_MULTI_DATASETS /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_coord_multi_read_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef WIN32_FORTRAN CGNSDLL void __stdcall cgp_coord_multi_read_data_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgsize_t *rmin, cgsize_t *rmax, void *coordsX, void *coordsY, void *coordsZ, cgint_f *ier) #else CGNSDLL void cgp_coord_multi_read_data_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgsize_t *rmin, cgsize_t *rmax, void *coordsX, void *coordsY, void *coordsZ, cgint_f *ier) #endif { *ier = (cgint_f)cgp_coord_multi_read_data((int)*fn, (int)*B, (int)*Z, (int*)C, rmin, rmax, coordsX, coordsY, coordsZ); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_coord_multi_write_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef WIN32_FORTRAN CGNSDLL void __stdcall cgp_coord_multi_write_data_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgsize_t *rmin, cgsize_t *rmax, void *coordsX, void *coordsY, void *coordsZ, cgint_f *ier) #else CGNSDLL void cgp_coord_multi_write_data_f(cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *C, cgsize_t *rmin, cgsize_t *rmax, void *coordsX, void *coordsY, void *coordsZ, cgint_f *ier) #endif { *ier = (cgint_f)cgp_coord_multi_write_data((int)*fn, (int)*B, (int)*Z, (int*)C, rmin, rmax, coordsX, coordsY, coordsZ); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_field_multi_write_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cgp_field_multi_write_data_f, CGP_FIELD_MULTI_WRITE_DATA_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *F, cgsize_t *rmin, cgsize_t *rmax, cgint_f *ier, cgsize_t *nsets, ...) { va_list ap; /* argument list passed from the API call */ int *F_c; int n; va_start(ap, nsets); if(sizeof(cgsize_t)!=sizeof(int)) { /* type cast F from cgsize_t to an int */ if ((F_c = (int *)malloc(*nsets*sizeof(int)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; return; } for (n = 0; n < *nsets; n++) { F_c[n] = (int)F[n]; } *ier = vcgp_field_multi_write_data((int)*fn, (int)*B, (int)*Z, (int)*S, F_c, rmin, rmax, (int)*nsets, ap); CGNS_FREE(F_c); } else { *ier = vcgp_field_multi_write_data((int)*fn, (int)*B, (int)*Z, (int)*S, F, rmin, rmax, (int)*nsets, ap); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_field_multi_read_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cgp_field_multi_read_data_f, CGP_FIELD_MULTI_READ_DATA_F) ( cgint_f *fn, cgint_f *B, cgint_f *Z, cgint_f *S, cgint_f *F, cgsize_t *rmin, cgsize_t *rmax, cgint_f *ier, cgint_f *nsets, ...) { va_list ap; /* argument list passed from the API call */ int *F_c; int n; va_start(ap, nsets); if(sizeof(cgsize_t)!=sizeof(int)) { /* type cast F from cgsize_t to an int */ if ((F_c = (int *)malloc(*nsets*sizeof(int)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; return; } for (n = 0; n < *nsets; n++) { F_c[n] = (int)F[n]; } *ier = (cgint_f)vcgp_field_multi_read_data((int)*fn, (int)*B, (int)*Z, (int)*S, F_c, rmin, rmax, (int)*nsets, ap); } else { *ier = (cgint_f)vcgp_field_multi_read_data((int)*fn, (int)*B, (int)*Z, (int)*S, F, rmin, rmax, (int)*nsets, ap); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_array_multi_write_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cgp_array_multi_write_data_f, CGP_ARRAY_MULTI_WRITE_DATA_F) ( cgint_f *fn, cgint_f *A, cgsize_t *rmin, cgsize_t *rmax, cgint_f *ier, cgint_f *nsets, ...) { va_list ap; /* argument list passed from the API call */ int *A_c; int n; va_start(ap, nsets); if(sizeof(cgsize_t)!=sizeof(int)) { /* type cast F from cgsize_t to an int */ if ((A_c = (int *)malloc(*nsets*sizeof(int)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; return; } for (n = 0; n < *nsets; n++) { A_c[n] = (int)A[n]; } *ier = (cgint_f)vcgp_array_multi_write_data((int)*fn, A_c, rmin, rmax, (int)*nsets, ap); }else { *ier = (cgint_f)vcgp_array_multi_write_data((int)*fn, A, rmin, rmax, (int)*nsets, ap); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * cgp_array_multi_read_data Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL void FMNAME(cgp_array_multi_read_data_f, CGP_ARRAY_MULTI_READ_DATA_F) ( cgint_f *fn, cgint_f *A, cgsize_t *rmin, cgsize_t *rmax, cgint_f *ier, cgint_f *nsets, ...) { va_list ap; /* argument list passed from the API call */ int *A_c; int n; va_start(ap, nsets); if(sizeof(cgsize_t)!=sizeof(int)) { /* type cast F from cgsize_t to an int */ if ((A_c = (int *)malloc(*nsets*sizeof(int)))==NULL) { cgi_error("Error allocating memory..."); *ier = 1; return; } for (n = 0; n < *nsets; n++) { A_c[n] = (int)A[n]; } *ier = (cgint_f)vcgp_array_multi_read_data((int)*fn, A_c, rmin, rmax, (int)*nsets, ap); }else { *ier = (cgint_f)vcgp_array_multi_read_data((int)*fn, A, rmin, rmax, (int)*nsets, ap); } } #endif /*HDF5_HAVE_MULTI_DATASETS*/ #endif /*BUILD_PARALLEL*/ CGNS-3.4.0/src/cg_malloc.c000066400000000000000000000033141343724673500151420ustar00rootroot00000000000000#include #include #include static size_t mem_now = 0; static size_t mem_max = 0; static size_t alloc_calls = 0; static size_t free_calls = 0; void *cgmalloc(size_t bytes) { size_t *data = (size_t *) malloc (bytes + 2 * sizeof(size_t)); if (data) { *data++ = bytes; *data = (size_t)(data + 1); data++; mem_now += bytes; if (mem_max < mem_now) mem_max = mem_now; } alloc_calls++; return (void *)data; } void *cgrealloc(void *olddata, size_t bytes) { size_t *data = (size_t *)olddata; if (data && *(data-1) == (size_t)olddata) { data -= 2; mem_now -= *data; } data = (size_t *) realloc (data, bytes + 2 * sizeof(size_t)); if (data) { *data++ = bytes; *data = (size_t)(data + 1); data++; mem_now += bytes; if (mem_max < mem_now) mem_max = mem_now; } /* alloc_calls++;*/ return (void *)data; } void *cgcalloc(size_t num, size_t bytes) { size_t count = num * bytes; size_t *data = (size_t *) malloc (count + 2 * sizeof(size_t)); if (data) { *data++ = count; *data = (size_t)(data + 1); data++; mem_now += count; if (mem_max < mem_now) mem_max = mem_now; memset(data, 0, count); } alloc_calls++; return (void *)data; } void cgfree(void *freedata) { size_t *data = (size_t *)freedata; if (data && *(data-1) == (size_t)freedata) { data -= 2; mem_now -= *data; free (data); } free_calls++; } size_t cgmemnow() {return mem_now;} size_t cgmemmax() {return mem_max;} size_t cgalloccalls() {return alloc_calls;} size_t cgfreecalls() {return free_calls;} CGNS-3.4.0/src/cg_malloc.h000066400000000000000000000006761343724673500151570ustar00rootroot00000000000000#ifndef __CG_MALLOC_H__ #define __CG_MALLOC_H__ #define malloc(S) cgmalloc(S) #define realloc(P,S) cgrealloc(P,S) #define calloc(N,S) cgcalloc(N,S) #define free(P) cgfree(P) extern void *cgmalloc(size_t); extern void *cgrealloc(void *,size_t); extern void *cgcalloc(size_t,size_t); extern void cgfree(void *); extern size_t cgmemnow(); extern size_t cgmemmax(); extern size_t cgalloccalls(); extern size_t cgfreecalls(); #endif CGNS-3.4.0/src/cgio_ftoc.c000066400000000000000000000460751343724673500151710ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include #include #include "fortran_macros.h" #include "cgns_io.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #if defined(_WIN32) && defined(BUILD_DLL) # define CGIODLL __declspec(dllexport) #else # define CGIODLL #endif /*========================================================= * local string conversions *=========================================================*/ static int to_c_string(char *f_str, int f_len, char *c_str, int c_len) { int i, iend; for (iend = f_len-1; iend >= 0; iend--) { if (f_str[iend] != ' ') break; } if (iend >= c_len) iend = c_len - 1; for (i = 0; i <= iend; i++) c_str[i] = f_str[i]; c_str[i] = 0; return i; } /*---------------------------------------------------------*/ static int to_f_string(char *c_str, char *f_str, int f_len) { int i, c_len; c_len = (int)strlen(c_str); if (c_len > f_len) c_len = f_len; for (i = 0; i < c_len; i++) f_str[i] = c_str[i]; while (i < f_len) f_str[i++] = ' '; return f_len; } /*---------------------------------------------------------*/ static char *new_c_string (char *str, int len, cgint_f *ier) { char *c_str; if (len < 1 || str == NULL) { *ier = (cgint_f)CGIO_ERR_NULL_STRING; return NULL; } else if ( len == 2 && strncmp(str, "\0", 2) == 92 ) { *ier = (cgint_f)CGIO_ERR_NULL_STRING; return NULL; } c_str = (char *) malloc (len + 1); if (c_str == NULL) { *ier = (cgint_f)CGIO_ERR_MALLOC; return NULL; } to_c_string (str, len, c_str, len); if (strlen(c_str) < 1) { free (c_str); *ier = (cgint_f)CGIO_ERR_NULL_STRING; return NULL; } *ier = 0; return c_str; } /*========================================================= * paths for searching for linked-to files *=========================================================*/ CGIODLL void FMNAME(cgio_path_add_f, CGIO_PATH_ADD_F) ( STR_PSTR(path), cgint_f *ier STR_PLEN(path)) { char *c_path = new_c_string(STR_PTR(path), STR_LEN(path), ier); if (*ier == 0) { *ier = (cgint_f)cgio_path_add(c_path); free(c_path); } } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_path_delete_f, CGIO_PATH_DELETE_F) ( STR_PSTR(path), cgint_f *ier STR_PLEN(path)) { char *c_path = new_c_string(STR_PTR(path), STR_LEN(path), ier); if (*ier == CGIO_ERR_MALLOC) return; *ier = (cgint_f)cgio_path_delete(c_path); if (c_path) free(c_path); } /*========================================================= * utility routines independent of open files *=========================================================*/ CGIODLL void cgio_is_supported_f( cgsize_t *file_type, cgint_f *ier) { *ier = (cgint_f)cgio_is_supported((int)*file_type); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_check_file_f, CGIO_CHECK_FILE_F) ( STR_PSTR(filename), cgint_f *file_type, cgint_f *ier STR_PLEN(filename)) { int i_file_type; char *c_name = new_c_string(STR_PTR(filename), STR_LEN(filename), ier); if (*ier == 0) { *ier = (cgint_f)cgio_check_file(c_name, &i_file_type); *file_type = (cgint_f)i_file_type; free(c_name); } } /*========================================================= * file operations *=========================================================*/ CGIODLL void FMNAME(cgio_open_file_f, CGIO_OPEN_FILE_F) ( STR_PSTR(filename), cgint_f *file_mode, cgint_f *file_type, cgint_f *cgio_num, cgint_f *ier STR_PLEN(filename)) { int i_cgio_num; char *c_name = new_c_string(STR_PTR(filename), STR_LEN(filename), ier); if (*ier == 0) { *ier = (cgint_f)cgio_open_file(c_name, (int)*file_mode, (int)*file_type, &i_cgio_num); *cgio_num = (cgint_f)i_cgio_num; free(c_name); } } /*---------------------------------------------------------*/ CGIODLL void cgio_close_file_f( cgint_f *cgio_num, cgint_f *ier) { *ier = (cgint_f)cgio_close_file((int)*cgio_num); } /*---------------------------------------------------------*/ CGIODLL void cgio_flush_to_disk_f( cgint_f *cgio_num, cgint_f *ier) { *ier = (cgint_f)cgio_flush_to_disk((int)*cgio_num); } /*========================================================= * file information *=========================================================*/ CGIODLL void FMNAME(cgio_library_version_f, CGIO_LIBRARY_VERSION_F) ( cgint_f *cgio_num, STR_PSTR(version), cgint_f *ier STR_PLEN(version)) { char c_version[CGIO_MAX_VERSION_LENGTH+1]; *ier = (cgint_f)cgio_library_version((int)*cgio_num, c_version); if (*ier == 0) to_f_string(c_version, STR_PTR(version), STR_LEN(version)); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_file_version_f, CGIO_FILE_VERSION_F) ( cgint_f *cgio_num, STR_PSTR(file_version), STR_PSTR(creation_date), STR_PSTR(modified_date), cgint_f *ier STR_PLEN(file_version) STR_PLEN(creation_date) STR_PLEN(modified_date)) { char c_version[CGIO_MAX_VERSION_LENGTH+1]; char c_cdate[CGIO_MAX_VERSION_LENGTH+1]; char c_mdate[CGIO_MAX_VERSION_LENGTH+1]; *ier = (cgint_f)cgio_file_version((int)*cgio_num, c_version, c_cdate, c_mdate); if (*ier == 0) { to_f_string(c_version, STR_PTR(file_version), STR_LEN(file_version)); to_f_string(c_cdate, STR_PTR(creation_date), STR_LEN(creation_date)); to_f_string(c_mdate, STR_PTR(modified_date), STR_LEN(modified_date)); } } /*---------------------------------------------------------*/ CGIODLL void cgio_get_root_id_f( cgint_f *cgio_num, double *rootid, cgint_f *ier) { *ier = (cgint_f)cgio_get_root_id((int)*cgio_num, rootid); } /*---------------------------------------------------------*/ CGIODLL void cgio_get_file_type_f( cgint_f *cgio_num, cgint_f *file_type, cgint_f *ier) { int i_file_type; *ier = (cgint_f)cgio_get_file_type((int)*cgio_num, &i_file_type); *file_type = (cgint_f)i_file_type; } /*========================================================= * error handling *=========================================================*/ CGIODLL void cgio_error_code_f( cgint_f *errcode, cgint_f *file_type) { int i_errcode, i_file_type; cgio_error_code(&i_errcode, &i_file_type); *errcode = (cgint_f)i_errcode; *file_type = (cgint_f)i_file_type; } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_error_message_f,CGIO_ERROR_MESSAGE_F) ( STR_PSTR(errmsg), cgint_f *ier STR_PLEN(errmsg)) { char c_error[CGIO_MAX_ERROR_LENGTH+1]; *ier = (cgint_f)cgio_error_message(c_error); if (*ier == 0) to_f_string(c_error, STR_PTR(errmsg), STR_LEN(errmsg)); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_error_exit_f, CGIO_ERROR_EXIT_F)( STR_PSTR(errmsg) STR_PLEN(errmsg)) { cgint_f ier; char *c_error = new_c_string(STR_PTR(errmsg), STR_LEN(errmsg), &ier); cgio_error_exit(c_error); } /*---------------------------------------------------------*/ CGIODLL void cgio_error_abort_f( cgint_f *abort_flag) { cgio_error_abort((int)*abort_flag); } /*========================================================= * basic node operations *=========================================================*/ CGIODLL void FMNAME(cgio_create_node_f, CGIO_CREATE_NODE_F) ( cgint_f *cgio_num, double *pid, STR_PSTR(name), double *id, cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; to_c_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH); *ier = (cgint_f)cgio_create_node((int)*cgio_num, *pid, c_name, id); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_new_node_f, CGIO_NEW_NODE_F) ( cgint_f *cgio_num, double *pid, STR_PSTR(name), STR_PSTR(label), STR_PSTR(data_type), cgint_f *ndims, cgsize_t *dims, void *data, double *id, cgint_f *ier STR_PLEN(name) STR_PLEN(label) STR_PLEN(data_type)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; char c_label[CGIO_MAX_LABEL_LENGTH+1]; char c_dtype[CGIO_MAX_DATATYPE_LENGTH+1]; to_c_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH); to_c_string(STR_PTR(label), STR_LEN(label), c_label, CGIO_MAX_LABEL_LENGTH); to_c_string(STR_PTR(data_type), STR_LEN(data_type), c_dtype, CGIO_MAX_DATATYPE_LENGTH); *ier = (cgint_f)cgio_new_node((int)*cgio_num, *pid, c_name, c_label, c_dtype, (int)*ndims, dims, data, id); } /*---------------------------------------------------------*/ CGIODLL void cgio_delete_node_f( cgint_f *cgio_num, double *pid, double *id, cgint_f *ier) { *ier = (cgint_f)cgio_delete_node((int)*cgio_num, *pid, *id); } /*---------------------------------------------------------*/ CGIODLL void cgio_move_node_f( cgint_f *cgio_num, double *pid, double *id, double *npid, cgint_f *ier) { *ier = (cgint_f)cgio_move_node((int)*cgio_num, *pid, *id, *npid); } /*---------------------------------------------------------*/ CGIODLL void cgio_release_id_f( cgint_f *cgio_num, double *id, cgint_f *ier) { *ier = (cgint_f)cgio_release_id((int)*cgio_num, *id); } /*========================================================= * links *=========================================================*/ CGIODLL void cgio_is_link_f( cgint_f *cgio_num, double *id, cgint_f *link_len, cgint_f *ier) { int i_link_len; *ier = (cgint_f)cgio_is_link((int)*cgio_num, *id, &i_link_len); *link_len = (cgint_f)i_link_len; } /*---------------------------------------------------------*/ CGIODLL void cgio_link_size_f( cgint_f *cgio_num, double *id, cgint_f *file_len, cgint_f *name_len, cgint_f *ier) { int i_file_len, i_name_len; *ier = (cgint_f)cgio_link_size((int)*cgio_num, *id, &i_file_len, &i_name_len); *file_len = (cgint_f)i_file_len; *name_len = (cgint_f)i_name_len; } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_create_link_f, CGIO_CREATE_LINK_F) ( cgint_f *cgio_num, double *pid, STR_PSTR(name), STR_PSTR(filename), STR_PSTR(name_in_file), double *id, cgint_f *ier STR_PLEN(name) STR_PLEN(filename) STR_PLEN(name_in_file)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; char *c_file, *c_link; c_file = new_c_string(STR_PTR(filename), STR_LEN(filename), ier); if (*ier) { if (*ier != CGIO_ERR_NULL_STRING) return; c_file = ""; } c_link = new_c_string(STR_PTR(name_in_file), STR_LEN(name_in_file), ier); if (*ier) { if (*c_file) free(c_file); return; } to_c_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH); *ier = (cgint_f)cgio_create_link((int)*cgio_num, *pid, c_name, c_file, c_link, id); if (*c_file) free(c_file); free(c_link); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_get_link_f, CGIO_GET_LINK_F) ( cgint_f *cgio_num, double *id, STR_PSTR(filename), STR_PSTR(name_in_file), cgint_f *ier STR_PLEN(filename) STR_PLEN(name_in_file)) { char c_file[CGIO_MAX_FILE_LENGTH+1]; char c_link[CGIO_MAX_LINK_LENGTH+1]; *ier = (cgint_f)cgio_get_link((int)*cgio_num, *id, c_file, c_link); if (*ier == 0) { to_f_string(c_file, STR_PTR(filename), STR_LEN(filename)); to_f_string(c_link, STR_PTR(name_in_file), STR_LEN(name_in_file)); } } /*========================================================= * node children *=========================================================*/ CGIODLL void cgio_number_children_f( cgint_f *cgio_num, double *pid, cgint_f *num_children, cgint_f *ier) { int i_num_children; *ier = cgio_number_children(*cgio_num, *pid, &i_num_children); *num_children = (cgint_f)i_num_children; } /*---------------------------------------------------------*/ CGIODLL void cgio_children_ids_f( cgint_f *cgio_num, double *pid, cgint_f *start, cgint_f *max_ret, cgint_f *num_ret, double *ids, cgint_f *ier) { int i_num_ret; *ier = cgio_children_ids((int)*cgio_num, *pid, (int)*start, (int)*max_ret, &i_num_ret, ids); *num_ret = (cgint_f)i_num_ret; } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_children_names_f, CGIO_CHILDREN_NAMES_F) ( cgint_f *cgio_num, double *pid, cgint_f *start, cgint_f *max_ret, cgint_f *name_len, cgint_f *num_ret, STR_PSTR(names), cgint_f *ier STR_PLEN(names)) { int i_num_ret, i_name_len = (int)*name_len; char *c_names; c_names = (char *) malloc ((size_t)*max_ret * (CGIO_MAX_NAME_LENGTH + 1)); if (c_names == NULL) { *ier = (cgint_f)CGIO_ERR_MALLOC; return; } *ier = (cgint_f)cgio_children_names((int)*cgio_num, *pid, (int)*start, (int)*max_ret, CGIO_MAX_NAME_LENGTH + 1, &i_num_ret, c_names); if (*ier == 0) { int n; char *pc = c_names; char *pf = STR_PTR(names); for (n = 0; n < i_num_ret; n++) { to_f_string(pc, pf, i_name_len); pc += (CGIO_MAX_NAME_LENGTH + 1); pf += i_name_len; } *num_ret = (cgint_f)i_num_ret; } free(c_names); } /*========================================================= * read nodes *=========================================================*/ CGIODLL void FMNAME(cgio_get_node_id_f, CGIO_GET_NODE_ID_F) ( cgint_f *cgio_num, double *pid, STR_PSTR(name), double *id, cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; to_c_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH); *ier = (cgint_f)cgio_get_node_id((int)*cgio_num, *pid, c_name, id); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_get_name_f, CGIO_GET_NAME_F) ( cgint_f *cgio_num, double *id, STR_PSTR(name), cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; *ier = (cgint_f)cgio_get_name((int)*cgio_num, *id, c_name); if (*ier == 0) to_f_string(c_name, STR_PTR(name), STR_LEN(name)); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_get_label_f, CGIO_GET_LABEL_F) ( cgint_f *cgio_num, double *id, STR_PSTR(label), cgint_f *ier STR_PLEN(label)) { char c_label[CGIO_MAX_LABEL_LENGTH+1]; *ier = (cgint_f)cgio_get_label((int)*cgio_num, *id, c_label); if (*ier == 0) to_f_string(c_label, STR_PTR(label), STR_LEN(label)); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_get_data_type_f, CGIO_GET_DATA_TYPE_F) ( cgint_f *cgio_num, double *id, STR_PSTR(data_type), cgint_f *ier STR_PLEN(data_type)) { char c_type[CGIO_MAX_DATATYPE_LENGTH+1]; *ier = (cgint_f)cgio_get_data_type((int)*cgio_num, *id, c_type); if (*ier == 0) to_f_string(c_type, STR_PTR(data_type), STR_LEN(data_type)); } /*---------------------------------------------------------*/ CGIODLL void cgio_get_data_size_f( cgint_f *cgio_num, double *id, cgsize_t *size, cgint_f *ier) { cglong_t data_size; *ier = (cgint_f)cgio_get_data_size((int)*cgio_num, *id, &data_size); *size = (cgsize_t)data_size; } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_read_all_data_f, CGIO_READ_ALL_DATA_F) ( cgint_f *cgio_num, double *id, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_read_all_data((int)*cgio_num, *id, data); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_read_block_data_f, CGIO_READ_BLOCK_DATA_F) ( cgint_f *cgio_num, double *id, cgsize_t *b_start, cgsize_t *b_end, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_read_block_data((int)*cgio_num, *id, *b_start, *b_end, data); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_read_data_f, CGIO_READ_DATA_F) ( cgint_f *cgio_num, double *id, cgsize_t *s_start, cgsize_t *s_end, cgsize_t *s_stride, cgint_f *m_ndims, cgsize_t *m_dims, cgsize_t *m_start, cgsize_t *m_end, cgsize_t *m_stride, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_read_data((int)*cgio_num, *id, s_start, s_end, s_stride, (int)*m_ndims, m_dims, m_start, m_end, m_stride, data); } /*========================================================= * write nodes *=========================================================*/ CGIODLL void FMNAME(cgio_set_name_f, CGIO_SET_NAME_F) ( cgint_f *cgio_num, double *pid, double *id, STR_PSTR(name), cgint_f *ier STR_PLEN(name)) { char c_name[CGIO_MAX_NAME_LENGTH+1]; to_c_string(STR_PTR(name), STR_LEN(name), c_name, CGIO_MAX_NAME_LENGTH); *ier = (cgint_f)cgio_set_name((int)*cgio_num, *pid, *id, c_name); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_set_label_f, CGIO_SET_LABEL_F) ( cgint_f *cgio_num, double *id, STR_PSTR(label), cgint_f *ier STR_PLEN(label)) { char c_label[CGIO_MAX_LABEL_LENGTH+1]; to_c_string(STR_PTR(label), STR_LEN(label), c_label, CGIO_MAX_LABEL_LENGTH); *ier = (cgint_f)cgio_set_label((int)*cgio_num, *id, c_label); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_write_all_data_f, CGIO_WRITE_ALL_DATA_F) ( cgint_f *cgio_num, double *id, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_write_all_data((int)*cgio_num, *id, data); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_write_block_data_f, CGIO_WRITE_BLOCK_DATA_F) ( cgint_f *cgio_num, double *id, cgsize_t *b_start, cgsize_t *b_end, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_write_block_data((int)*cgio_num, *id, *b_start, *b_end, data); } /*---------------------------------------------------------*/ CGIODLL void FMNAME(cgio_write_data_f, CGIO_WRITE_DATA_F) ( cgint_f *cgio_num, double *id, cgsize_t *s_start, cgsize_t *s_end, cgsize_t *s_stride, cgsize_t *m_ndims, cgsize_t *m_dims, cgsize_t *m_start, cgsize_t *m_end, cgsize_t *m_stride, void *data, cgint_f *ier) { *ier = (cgint_f)cgio_write_data((int)*cgio_num, *id, s_start, s_end, s_stride, (int)*m_ndims, m_dims, m_start, m_end, m_stride, data); } #undef CGIODLL CGNS-3.4.0/src/cgnsBuild.defs.in000066400000000000000000000055551343724673500162510ustar00rootroot00000000000000# makefile include for building CGNS code # this file contains the options and libraries used for # building and linking CGNS code, and is intended to be # included in a user's Makefile from the installation #----------------------------------------------------------------------- # CGNS library build options. A 1 indicates that the library # was built with that option, a 0 indicates without # CGNS_DEBUG = debug # CGNS_LEGACY = legacy code (prior to 3.0) # CGNS_SCOPING = scoping of enums # CGNS_64BIT = 64 bit support # CGNS_FORTRAN = Fortran interface # CGNS_PARALLEL = parallel I/O # CGNS_BASESCOPE = Base scope for family and zone reference-to #----------------------------------------------------------------------- CGNS_DEBUG = @BUILDDEBUG@ CGNS_LEGACY = @BUILDLEGACY@ CGNS_SCOPING = @BUILDSCOPE@ CGNS_64BIT = @BUILD64BIT@ CGNS_FORTRAN = @BUILDFORTRAN@ CGNS_PARALLEL = @BUILDPARALLEL@ CGNS_BASESCOPE = @BUILDBASESCOPE@ #----------------------------------------------------------------------- # CGNS_LIBDIR - installation directory for CGNS library # CGNS_INCLUDEDIR - installation directory for CGNS headers #----------------------------------------------------------------------- CGNS_LIBDIR = @LIBDIR@ CGNS_INCLUDEDIR = @INCLUDEDIR@ #----------------------------------------------------------------------- # CGNS_CC - C compiler used to build library # CGNS_CFLAGS - compiler flags used to build library # CGNS_LDFLAGS - any additional linking flags #----------------------------------------------------------------------- CGNS_CC = @CC@ CGNS_CFLAGS = @CFLAGS@ @SYSCFLAGS@ @CFGFLAGS@ CGNS_LDFLAGS = @LDFLAGS@ #----------------------------------------------------------------------- # LIBCGNS - CGNS library name #----------------------------------------------------------------------- CGNS_LIB = $(CGNS_LIBDIR)/@CGNSLIB@ #----------------------------------------------------------------------- # CGNS_HDF5INC - path to HDF5 header files # CGNS_HDF5LIB - HDF5 library # CGNS_SZIPLIB - szip library (if needed) # CGNS_ZLIBLIB - zlib library (if needed) #----------------------------------------------------------------------- CGNS_HDF5INC = @HDF5INC@ CGNS_HDF5LIB = @HDF5LIB@ CGNS_SZIPLIB = @SZIPLIB@ CGNS_ZLIBLIB = @ZLIBLIB@ #----------------------------------------------------------------------- # CGNS_MPIINC - path to MPI header files # CGNS_MPILIBS - MPI libraries #----------------------------------------------------------------------- CGNS_MPIINC = @MPIINC@ CGNS_MPILIBS = @MPILIBS@ #----------------------------------------------------------------------- # CGNS_LINKLIBS contains the list of libraries # with which a CGNS application needs to link #----------------------------------------------------------------------- CGNS_LINKLIBS = $(CGNS_LIB) $(CGNS_HDF5LIB) $(CGNS_SZIPLIB) \ $(CGNS_ZLIBLIB) $(CGNS_MPILIBS) @LIBS@ CGNS-3.4.0/src/cgnsKeywords.h000066400000000000000000001223261343724673500157160ustar00rootroot00000000000000/* @#@#@ $Id: cgnsKeywords.h,v 1.3 2008/07/11 00:25:35 brucewedan Exp $ @#@#@ CHECKSUM: 296864779 40788 @#@#@ (cat cgnsKeywords.h | grep -v '@#@#@' | cksum) */ /*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ /* _____ __ __ _____ ____ _____ _______ _ _ _______ * |_ _| \/ | __ \ / __ \| __ \__ __|/\ | \ | |__ __| * | | | \ / | |__) | | | | |__) | | | / \ | \| | | | * | | | |\/| | ___/| | | | _ / | | / /\ \ | . ` | | | * _| |_| | | | | | |__| | | \ \ | |/ ____ \| |\ | | | * |_____|_| |_|_| \____/|_| \_\ |_/_/ \_\_| \_| |_| * * ------------------- DEVELOPER'S NOTES --------------------------- * * (1) If a new keyword is introduced into this file then the same keyword * needs to be added to cgns_f.F90 in order to maintain Fortran * compatibility. * */ #ifndef CGNSLIB_KEYWORDS_H #define CGNSLIB_KEYWORDS_H /* THIS HEADER CAN BE READ BY ANY C LANGAGE PRE-PROCESSOR ENUMERATES DEFINITIONS ARE DECLARED, IN THE CASE YOU DO NOT WANT THESE DEFINITIONS (e.g. you compile Fortran) THEN YOU HAVE TO UNSET THE __CGNS_ENUMS__ #undef __CGNS_ENUMS__ BY DEFAULT YOU WANT TO DECLARE THESE ENUMERATES #define __CGNS_ENUMS__ */ #define __CGNS_ENUMS__ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * VERSION NUMBER * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define CGNS_VERSION 3130 #define CGNS_DOTVERS 3.13 #define CGNS_COMPATVERSION 2540 #define CGNS_COMPATDOTVERS 2.54 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * modes for cgns file * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * modes for cgns file * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define CG_MODE_READ 0 #define CG_MODE_WRITE 1 #define CG_MODE_MODIFY 2 #define CG_MODE_CLOSED 3 /* function return codes */ #define CG_OK 0 #define CG_ERROR 1 #define CG_NODE_NOT_FOUND 2 #define CG_INCORRECT_PATH 3 #define CG_NO_INDEX_DIM 4 /* Null and UserDefined enums */ #define CG_Null 0 #define CG_UserDefined 1 /* max goto depth */ #define CG_MAX_GOTO_DEPTH 20 /* configuration options */ #define CG_CONFIG_ERROR 1 #define CG_CONFIG_COMPRESS 2 #define CG_CONFIG_SET_PATH 3 #define CG_CONFIG_ADD_PATH 4 #define CG_CONFIG_FILE_TYPE 5 /* The Null and the UserDefined string constants are always the same, whatever enumerate you consider. */ #define CG_Null_s "Null" #define CG_UserDefined_s "Userdefined" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Dimensional Units * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Mass ---*/ #ifdef __CGNS_ENUMS__ typedef enum { MassUnitsNull, MassUnitsUserDefined, Kilogram, Gram, Slug, PoundMass } MassUnits_t; #endif #define NofValidMassUnits 6 #define Kilogram_s "Kilogram" #define Gram_s "Gram" #define Slug_s "Slug" #define PoundMass_s "PoundMass" #define Meter_s "Meter" /* Length ---*/ #ifdef __CGNS_ENUMS__ typedef enum { LengthUnitsNull, LengthUnitsUserDefined, Meter, Centimeter, Millimeter, Foot, Inch } LengthUnits_t; #endif #define NofValidLengthUnits 7 #define Centimeter_s "Centimeter" #define Millimeter_s "Millimeter" #define Foot_s "Foot" #define Inch_s "Inch" /* Mass ---*/ #ifdef __CGNS_ENUMS__ typedef enum { TimeUnitsNull, TimeUnitsUserDefined, Second } TimeUnits_t; #endif #define NofValidTimeUnits 3 #define Second_s "Second" /* Temperature ---*/ #ifdef __CGNS_ENUMS__ typedef enum { TemperatureUnitsNull, TemperatureUnitsUserDefined, Kelvin, Celsius, Rankine, Fahrenheit } TemperatureUnits_t; #endif #define NofValidTemperatureUnits 6 #define Kelvin_s "Kelvin" #define Celsius_s "Celsius" #define Rankine_s "Rankine" #define Fahrenheit_s "Fahrenheit" /* Angle ---*/ #ifdef __CGNS_ENUMS__ typedef enum { AngleUnitsNull, AngleUnitsUserDefined, Degree, Radian } AngleUnits_t; #endif #define NofValidAngleUnits 4 #define Degree_s "Degree" #define Radian_s "Radian" /* ElectricCurrent ---*/ #ifdef __CGNS_ENUMS__ typedef enum { ElectricCurrentUnitsNull, ElectricCurrentUnitsUserDefined, Ampere, Abampere, Statampere, Edison, auCurrent } ElectricCurrentUnits_t; #endif #define NofValidElectricCurrentUnits 7 #define Ampere_s "Ampere" #define Abampere_s "Abampere" #define Statampere_s "Statampere" #define Edison_s "Edison" #define auCurrent_s "auCurrent" /* SubstanceAmount ---*/ #ifdef __CGNS_ENUMS__ typedef enum { SubstanceAmountUnitsNull, SubstanceAmountUnitsUserDefined, Mole, Entities, StandardCubicFoot, StandardCubicMeter } SubstanceAmountUnits_t; #endif #define NofValidSubstanceAmountUnits 6 #define Mole_s "Mole" #define Entities_s "Entities" #define StandardCubicFoot_s "StandardCubicFoot" #define StandardCubicMeter_s "StandardCubicMeter" /* LuminousIntensity ---*/ #ifdef __CGNS_ENUMS__ typedef enum { LuminousIntensityUnitsNull, LuminousIntensityUnitsUserDefined, Candela, Candle, Carcel, Hefner, Violle } LuminousIntensityUnits_t; #endif #define NofValidLuminousIntensityUnits 7 #define Candela_s "Candela" #define Candle_s "Candle" #define Carcel_s "Carcel" #define Hefner_s "Hefner" #define Violle_s "Violle" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Data Class * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { DataClassNull, DataClassUserDefined, Dimensional, NormalizedByDimensional, NormalizedByUnknownDimensional, NondimensionalParameter, DimensionlessConstant } DataClass_t; #endif #define NofValidDataClass 7 #define Dimensional_s "Dimensional" #define NormalizedByDimensional_s "NormalizedByDimensional" #define NormalizedByUnknownDimensional_s "NormalizedByUnknownDimensional" #define NondimensionalParameter_s "NondimensionalParameter" #define DimensionlessConstant_s "DimensionlessConstant" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Location \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { GridLocationNull, GridLocationUserDefined, Vertex, CellCenter, FaceCenter, IFaceCenter, JFaceCenter, KFaceCenter, EdgeCenter } GridLocation_t; #endif #define NofValidGridLocation 9 #define Vertex_s "Vertex" #define CellCenter_s "CellCenter" #define FaceCenter_s "FaceCenter" #define IFaceCenter_s "IFaceCenter" #define JFaceCenter_s "JFaceCenter" #define KFaceCenter_s "KFaceCenter" #define EdgeCenter_s "EdgeCenter" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * BCData Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { BCDataTypeNull, BCDataTypeUserDefined, Dirichlet, Neumann } BCDataType_t; #endif #define NofValidBCDataTypes 4 #define Dirichlet_s "Dirichlet" #define Neumann_s "Neumann" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Connectivity Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { GridConnectivityTypeNull, GridConnectivityTypeUserDefined, Overset, Abutting, Abutting1to1 } GridConnectivityType_t; #endif #define NofValidGridConnectivityTypes 5 #define Overset_s "Overset" #define Abutting_s "Abutting" #define Abutting1to1_s "Abutting1to1" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Point Set Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { PointSetTypeNull, PointSetTypeUserDefined, PointList, PointListDonor, PointRange, PointRangeDonor, ElementRange, ElementList, CellListDonor } PointSetType_t; #endif #define NofValidPointSetTypes 9 #define PointList_s "PointList" #define PointListDonor_s "PointListDonor" #define PointRange_s "PointRange" #define PointRangeDonor_s "PointRangeDonor" #define ElementRange_s "ElementRange" #define ElementList_s "ElementList" #define CellListDonor_s "CellListDonor" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Governing Equations and Physical Models Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { GoverningEquationsNull, GoverningEquationsUserDefined, FullPotential, Euler, NSLaminar, NSTurbulent, NSLaminarIncompressible, NSTurbulentIncompressible } GoverningEquationsType_t; #endif #define NofValidGoverningEquationsTypes 8 #define FullPotential_s "FullPotential" #define Euler_s "Euler" #define NSLaminar_s "NSLaminar" #define NSTurbulent_s "NSTurbulent" #define NSLaminarIncompressible_s "NSLaminarIncompressible" #define NSTurbulentIncompressible_s "NSTurbulentIncompressible" /* Any model type will accept both ModelTypeNull and ModelTypeUserDefined. ** The following models will accept these values as vaild... ** ** GasModel_t: Ideal, VanderWaals, CaloricallyPerfect, ThermallyPerfect, ** ConstantDensity, RedlichKwong ** ** ViscosityModel_t: Constant, PowerLaw, SutherlandLaw ** ** ThermalConductivityModel_t: PowerLaw, SutherlandLaw, ConstantPrandtl ** ** TurbulenceModel_t: Algebraic_BaldwinLomax, Algebraic_CebeciSmith, ** HalfEquation_JohnsonKing, OneEquation_BaldwinBarth, ** OneEquation_SpalartAllmaras, TwoEquation_JonesLaunder, ** TwoEquation_MenterSST,TwoEquation_Wilcox ** ** TurbulenceClosure_t: EddyViscosity, ReynoldsStress, ReynoldsStressAlgebraic ** ** ThermalRelaxationModel_t: Frozen, ThermalEquilib, ThermalNonequilib ** ** ChemicalKineticsModel_t: Frozen, ChemicalEquilibCurveFit, ** ChemicalEquilibMinimization, ChemicalNonequilib ** ** EMElectricFieldModel_t: Voltage, Interpolated, Constant, Frozen ** ** EMMagneticFieldModel_t: Interpolated, Constant, Frozen ** ** EMConductivityModel_t: Constant, Frozen, Equilibrium_LinRessler, ** Chemistry_LinRessler */ #ifdef __CGNS_ENUMS__ typedef enum { ModelTypeNull, ModelTypeUserDefined, Ideal, VanderWaals, Constant, PowerLaw, SutherlandLaw, ConstantPrandtl, EddyViscosity, ReynoldsStress, ReynoldsStressAlgebraic, Algebraic_BaldwinLomax, Algebraic_CebeciSmith, HalfEquation_JohnsonKing, OneEquation_BaldwinBarth, OneEquation_SpalartAllmaras, TwoEquation_JonesLaunder, TwoEquation_MenterSST, TwoEquation_Wilcox, CaloricallyPerfect, ThermallyPerfect, ConstantDensity, RedlichKwong, Frozen, ThermalEquilib, ThermalNonequilib, ChemicalEquilibCurveFit, ChemicalEquilibMinimization, ChemicalNonequilib, EMElectricField, EMMagneticField, EMConductivity, Voltage, Interpolated, Equilibrium_LinRessler, Chemistry_LinRessler } ModelType_t; #endif #define NofValidModelTypes 36 #define Ideal_s "Ideal" #define VanderWaals_s "VanderWaals" #define Constant_s "Constant" #define PowerLaw_s "PowerLaw" #define SutherlandLaw_s "SutherlandLaw" #define ConstantPrandtl_s "ConstantPrandtl" #define EddyViscosity_s "EddyViscosity" #define ReynoldsStress_s "ReynoldsStress" #define Algebraic_s "Algebraic" #define BaldwinLomax_s "BaldwinLomax" #define ReynoldsStressAlgebraic_s "ReynoldsStressAlgebraic" #define Algebraic_CebeciSmith_s "Algebraic_CebeciSmith" #define HalfEquation_JohnsonKing_s "HalfEquation_JohnsonKing" #define OneEquation_BaldwinBarth_s "OneEquation_BaldwinBarth" #define OneEquation_SpalartAllmaras_s "OneEquation_SpalartAllmaras" #define TwoEquation_JonesLaunder_s "TwoEquation_JonesLaunder" #define TwoEquation_MenterSST_s "TwoEquation_MenterSST" #define TwoEquation_Wilcox_s "TwoEquation_Wilcox" #define CaloricallyPerfect_s "CaloricallyPerfect" #define ThermallyPerfect_s "ThermallyPerfect" #define ConstantDensity_s "ConstantDensity" #define RedlichKwong_s "RedlichKwong" #define Frozen_s "Frozen" #define ThermalEquilib_s "ThermalEquilib" #define ThermalNonequilib_s "ThermalNonequilib" #define ChemicalEquilibCurveFit_s "ChemicalEquilibCurveFit" #define ChemicalEquilibMinimization_s "ChemicalEquilibMinimization" #define ChemicalNonequilib_s "ChemicalNonequilib" #define EMElectricField_s "EMElectricField" #define EMMagneticField_s "EMMagneticField" #define EMConductivity_s "EMConductivity" #define Voltage_s "Voltage" #define Interpolated_s "Interpolated" #define Equilibrium_LinRessler_s "Equilibrium_LinRessler" #define Chemistry_LinRessler_s "Chemistry_LinRessler" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Boundary Condition Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { BCTypeNull, BCTypeUserDefined, BCAxisymmetricWedge, BCDegenerateLine, BCDegeneratePoint, BCDirichlet, BCExtrapolate, BCFarfield, BCGeneral, BCInflow, BCInflowSubsonic, BCInflowSupersonic, BCNeumann, BCOutflow, BCOutflowSubsonic, BCOutflowSupersonic, BCSymmetryPlane, BCSymmetryPolar, BCTunnelInflow, BCTunnelOutflow, BCWall, BCWallInviscid, BCWallViscous, BCWallViscousHeatFlux, BCWallViscousIsothermal, FamilySpecified } BCType_t; #endif #define NofValidBCTypes 26 #define BCAxisymmetricWedge_s "BCAxisymmetricWedge" #define BCDegenerateLine_s "BCDegenerateLine" #define BCDegeneratePoint_s "BCDegeneratePoint" #define BCDirichlet_s "BCDirichlet" #define BCExtrapolate_s "BCExtrapolate" #define BCFarfield_s "BCFarfield" #define BCGeneral_s "BCGeneral" #define BCInflow_s "BCInflow" #define BCInflowSubsonic_s "BCInflowSubsonic" #define BCInflowSupersonic_s "BCInflowSupersonic" #define BCNeumann_s "BCNeumann" #define BCOutflow_s "BCOutflow" #define BCOutflowSubsonic_s "BCOutflowSubsonic" #define BCOutflowSupersonic_s "BCOutflowSupersonic" #define BCSymmetryPlane_s "BCSymmetryPlane" #define BCSymmetryPolar_s "BCSymmetryPolar" #define BCTunnelInflow_s "BCTunnelInflow" #define BCTunnelOutflow_s "BCTunnelOutflow" #define BCWall_s "BCWall" #define BCWallInviscid_s "BCWallInviscid" #define BCWallViscous_s "BCWallViscous" #define BCWallViscousHeatFlux_s "BCWallViscousHeatFlux" #define BCWallViscousIsothermal_s "BCWallViscousIsothermal" #define FamilySpecified_s "FamilySpecified" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Data types: Can not add data types and stay forward compatible * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { DataTypeNull, DataTypeUserDefined, Integer, RealSingle, RealDouble, Character, LongInteger } DataType_t; #endif #define NofValidDataTypes 7 #define Integer_s "Integer" #define RealSingle_s "RealSingle" #define RealDouble_s "RealDouble" #define Character_s "Character" #define LongInteger_s "LongInteger" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Element types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { ElementTypeNull, ElementTypeUserDefined, /* 0, 1, */ NODE, BAR_2, BAR_3, /* 2, 3, 4, */ TRI_3, TRI_6, /* 5, 6, */ QUAD_4, QUAD_8, QUAD_9, /* 7, 8, 9, */ TETRA_4, TETRA_10, /* 10, 11, */ PYRA_5, PYRA_14, /* 12, 13, */ PENTA_6, PENTA_15, PENTA_18, /* 14, 15, 16, */ HEXA_8, HEXA_20, HEXA_27, /* 17, 18, 19, */ MIXED, PYRA_13, NGON_n, NFACE_n /* 20, 21, 22, 23*/ } ElementType_t; #endif #define NofValidElementTypes 24 #define NODE_s "NODE" #define BAR_2_s "BAR_2" #define BAR_3_s "BAR_3" #define TRI_3_s "TRI_3" #define TRI_6_s "TRI_6" #define QUAD_4_s "QUAD_4" #define QUAD_8_s "QUAD_8" #define QUAD_9_s "QUAD_9" #define TETRA_4_s "TETRA_4" #define TETRA_10_s "TETRA_10" #define PYRA_5_s "PYRA_5" #define PYRA_14_s "PYRA_14" #define PENTA_6_s "PENTA_6" #define PENTA_15_s "PENTA_15" #define PENTA_18_s "PENTA_18" #define HEXA_8_s "HEXA_8" #define HEXA_20_s "HEXA_20" #define HEXA_27_s "HEXA_27" #define MIXED_s "MIXED" #define PYRA_13_s "PYRA_13" #define NGON_n_s "NGON_n" #define NFACE_n_s "NFACE_n" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Zone types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { ZoneTypeNull, ZoneTypeUserDefined, Structured, Unstructured } ZoneType_t; #endif #define NofValidZoneTypes 4 #define Structured_s "Structured" #define Unstructured_s "Unstructured" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Rigid Grid Motion types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { RigidGridMotionTypeNull, RigidGridMotionTypeUserDefined, ConstantRate, VariableRate } RigidGridMotionType_t; #endif #define NofValidRigidGridMotionTypes 4 #define ConstantRate_s "ConstantRate" #define VariableRate_s "VariableRate" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Arbitrary Grid Motion types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { ArbitraryGridMotionTypeNull, ArbitraryGridMotionTypeUserDefined, NonDeformingGrid, DeformingGrid } ArbitraryGridMotionType_t; #endif #define NofValidArbitraryGridMotionTypes 4 #define NonDeformingGrid_s "NonDeformingGrid" #define DeformingGrid_s "DeformingGrid" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Simulation types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { SimulationTypeNull, SimulationTypeUserDefined, TimeAccurate, NonTimeAccurate } SimulationType_t; #endif #define NofValidSimulationTypes 4 #define TimeAccurate_s "TimeAccurate" #define NonTimeAccurate_s "NonTimeAccurate" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * BC Property types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { WallFunctionTypeNull, WallFunctionTypeUserDefined, Generic } WallFunctionType_t; #endif #define NofValidWallFunctionTypes 3 #define Generic_s "Generic" #ifdef __CGNS_ENUMS__ typedef enum { AreaTypeNull, AreaTypeUserDefined, BleedArea, CaptureArea } AreaType_t; #endif #define NofValidAreaTypes 4 #define BleedArea_s "BleedArea" #define CaptureArea_s "CaptureArea" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Connectivity Property types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #ifdef __CGNS_ENUMS__ typedef enum { AverageInterfaceTypeNull, AverageInterfaceTypeUserDefined, AverageAll, AverageCircumferential, AverageRadial, AverageI, AverageJ, AverageK } AverageInterfaceType_t; #endif #define NofValidAverageInterfaceTypes 8 #define AverageAll_s "AverageAll" #define AverageCircumferential_s "AverageCircumferential" #define AverageRadial_s "AverageRadial" #define AverageI_s "AverageI" #define AverageJ_s "AverageJ" #define AverageK_s "AverageK" /* The strings defined below are node names or node name patterns */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Coordinate system * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define CoordinateX_s "CoordinateX" #define CoordinateY_s "CoordinateY" #define CoordinateZ_s "CoordinateZ" #define CoordinateR_s "CoordinateR" #define CoordinateTheta_s "CoordinateTheta" #define CoordinatePhi_s "CoordinatePhi" #define CoordinateNormal_s "CoordinateNormal" #define CoordinateTangential_s "CoordinateTangential" #define CoordinateXi_s "CoordinateXi" #define CoordinateEta_s "CoordinateEta" #define CoordinateZeta_s "CoordinateZeta" #define CoordinateTransform_s "CoordinateTransform" #define InterpolantsDonor_s "InterpolantsDonor" #define ElementConnectivity_s "ElementConnectivity" #define ParentData_s "ParentData" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * FlowSolution Quantities * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Patterns --- */ #define VectorX_ps "%sX" #define VectorY_ps "%sY" #define VectorZ_ps "%sZ" #define VectorTheta_ps "%sTheta" #define VectorPhi_ps "%sPhi" #define VectorMagnitude_ps "%sMagnitude" #define VectorNormal_ps "%sNormal" #define VectorTangential_ps "%sTangential" #define Potential_s "Potential" #define StreamFunction_s "StreamFunction" #define Density_s "Density" #define Pressure_s "Pressure" #define Temperature_s "Temperature" #define EnergyInternal_s "EnergyInternal" #define Enthalpy_s "Enthalpy" #define Entropy_s "Entropy" #define EntropyApprox_s "EntropyApprox" #define DensityStagnation_s "DensityStagnation" #define PressureStagnation_s "PressureStagnation" #define TemperatureStagnation_s "TemperatureStagnation" #define EnergyStagnation_s "EnergyStagnation" #define EnthalpyStagnation_s "EnthalpyStagnation" #define EnergyStagnationDensity_s "EnergyStagnationDensity" #define VelocityX_s "VelocityX" #define VelocityY_s "VelocityY" #define VelocityZ_s "VelocityZ" #define VelocityR_s "VelocityR" #define VelocityTheta_s "VelocityTheta" #define VelocityPhi_s "VelocityPhi" #define VelocityMagnitude_s "VelocityMagnitude" #define VelocityNormal_s "VelocityNormal" #define VelocityTangential_s "VelocityTangential" #define VelocitySound_s "VelocitySound" #define VelocitySoundStagnation_s "VelocitySoundStagnation" #define MomentumX_s "MomentumX" #define MomentumY_s "MomentumY" #define MomentumZ_s "MomentumZ" #define MomentumMagnitude_s "MomentumMagnitude" #define RotatingVelocityX_s "RotatingVelocityX" #define RotatingVelocityY_s "RotatingVelocityY" #define RotatingVelocityZ_s "RotatingVelocityZ" #define RotatingMomentumX_s "RotatingMomentumX" #define RotatingMomentumY_s "RotatingMomentumY" #define RotatingMomentumZ_s "RotatingMomentumZ" #define RotatingVelocityMagnitude_s "RotatingVelocityMagnitude" #define RotatingPressureStagnation_s "RotatingPressureStagnation" #define RotatingEnergyStagnation_s "RotatingEnergyStagnation" #define RotatingEnergyStagnationDensity_s "RotatingEnergyStagnationDensity" #define RotatingEnthalpyStagnation_s "RotatingEnthalpyStagnation" #define EnergyKinetic_s "EnergyKinetic" #define PressureDynamic_s "PressureDynamic" #define SoundIntensityDB_s "SoundIntensityDB" #define SoundIntensity_s "SoundIntensity" #define VorticityX_s "VorticityX" #define VorticityY_s "VorticityY" #define VorticityZ_s "VorticityZ" #define VorticityMagnitude_s "VorticityMagnitude" #define SkinFrictionX_s "SkinFrictionX" #define SkinFrictionY_s "SkinFrictionY" #define SkinFrictionZ_s "SkinFrictionZ" #define SkinFrictionMagnitude_s "SkinFrictionMagnitude" #define VelocityAngleX_s "VelocityAngleX" #define VelocityAngleY_s "VelocityAngleY" #define VelocityAngleZ_s "VelocityAngleZ" #define VelocityUnitVectorX_s "VelocityUnitVectorX" #define VelocityUnitVectorY_s "VelocityUnitVectorY" #define VelocityUnitVectorZ_s "VelocityUnitVectorZ" #define MassFlow_s "MassFlow" #define ViscosityKinematic_s "ViscosityKinematic" #define ViscosityMolecular_s "ViscosityMolecular" #define ViscosityEddyDynamic_s "ViscosityEddyDynamic" #define ViscosityEddy_s "ViscosityEddy" #define ThermalConductivity_s "ThermalConductivity" #define PowerLawExponent_s "PowerLawExponent" #define SutherlandLawConstant_s "SutherlandLawConstant" #define TemperatureReference_s "TemperatureReference" #define ViscosityMolecularReference_s "ViscosityMolecularReference" #define ThermalConductivityReference_s "ThermalConductivityReference" #define IdealGasConstant_s "IdealGasConstant" #define SpecificHeatPressure_s "SpecificHeatPressure" #define SpecificHeatVolume_s "SpecificHeatVolume" #define ReynoldsStressXX_s "ReynoldsStressXX" #define ReynoldsStressXY_s "ReynoldsStressXY" #define ReynoldsStressXZ_s "ReynoldsStressXZ" #define ReynoldsStressYY_s "ReynoldsStressYY" #define ReynoldsStressYZ_s "ReynoldsStressYZ" #define ReynoldsStressZZ_s "ReynoldsStressZZ" #define LengthReference_s "LengthReference" #define MolecularWeight_s "MolecularWeight" #define MolecularWeight_ps "MolecularWeight%s" #define HeatOfFormation_s "HeatOfFormation" #define HeatOfFormation_ps "HeatOfFormation%s" #define FuelAirRatio_s "FuelAirRatio" #define ReferenceTemperatureHOF_s "ReferenceTemperatureHOF" #define MassFraction_s "MassFraction" #define MassFraction_ps "MassFraction%s" #define LaminarViscosity_s "LaminarViscosity" #define LaminarViscosity_ps "LaminarViscosity%s" #define ThermalConductivity_ps "ThermalConductivity%s" #define EnthalpyEnergyRatio_s "EnthalpyEnergyRatio" #define CompressibilityFactor_s "CompressibilityFactor" #define VibrationalElectronEnergy_s "VibrationalElectronEnergy" #define VibrationalElectronTemperature_s "VibrationalElectronTemperature" #define SpeciesDensity_s "SpeciesDensity" #define SpeciesDensity_ps "SpeciesDensity%s" #define MoleFraction_s "MoleFraction" #define MoleFraction_ps "MoleFraction%s" #define ElectricFieldX_s "ElectricFieldX" #define ElectricFieldY_s "ElectricFieldY" #define ElectricFieldZ_s "ElectricFieldZ" #define MagneticFieldX_s "MagneticFieldX" #define MagneticFieldY_s "MagneticFieldY" #define MagneticFieldZ_s "MagneticFieldZ" #define CurrentDensityX_s "CurrentDensityX" #define CurrentDensityY_s "CurrentDensityY" #define CurrentDensityZ_s "CurrentDensityZ" #define LorentzForceX_s "LorentzForceX" #define LorentzForceY_s "LorentzForceY" #define LorentzForceZ_s "LorentzForceZ" #define ElectricConductivity_s "ElectricConductivity" #define JouleHeating_s "JouleHeating" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Typical Turbulence Models * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define TurbulentDistance_s "TurbulentDistance" #define TurbulentEnergyKinetic_s "TurbulentEnergyKinetic" #define TurbulentDissipation_s "TurbulentDissipation" #define TurbulentDissipationRate_s "TurbulentDissipationRate" #define TurbulentBBReynolds_s "TurbulentBBReynolds" #define TurbulentSANuTilde_s "TurbulentSANuTilde" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Nondimensional Parameters * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define Mach_s "Mach" #define Mach_Velocity_s "Mach_Velocity" #define Mach_VelocitySound_s "Mach_VelocitySound" #define Reynolds_s "Reynolds" #define Reynolds_Velocity_s "Reynolds_Velocity" #define Reynolds_Length_s "Reynolds_Length" #define Reynolds_ViscosityKinematic_s "Reynolds_ViscosityKinematic" #define Prandtl_s "Prandtl" #define Prandtl_ThermalConductivity_s "Prandtl_ThermalConductivity" #define Prandtl_ViscosityMolecular_s "Prandtl_ViscosityMolecular" #define Prandtl_SpecificHeatPressure_s "Prandtl_SpecificHeatPressure" #define PrandtlTurbulent_s "PrandtlTurbulent" #define SpecificHeatRatio_s "SpecificHeatRatio" #define SpecificHeatRatio_Pressure_s "SpecificHeatRatio_Pressure" #define SpecificHeatRatio_Volume_s "SpecificHeatRatio_Volume" #define CoefPressure_s "CoefPressure" #define CoefSkinFrictionX_s "CoefSkinFrictionX" #define CoefSkinFrictionY_s "CoefSkinFrictionY" #define CoefSkinFrictionZ_s "CoefSkinFrictionZ" #define Coef_PressureDynamic_s "Coef_PressureDynamic" #define Coef_PressureReference_s "Coef_PressureReference" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Characteristics and Riemann invariant * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define Vorticity_s "Vorticity" #define Acoustic_s "Acoustic" #define RiemannInvariantPlus_s "RiemannInvariantPlus" #define RiemannInvariantMinus_s "RiemannInvariantMinus" #define CharacteristicEntropy_s "CharacteristicEntropy" #define CharacteristicVorticity1_s "CharacteristicVorticity1" #define CharacteristicVorticity2_s "CharacteristicVorticity2" #define CharacteristicAcousticPlus_s "CharacteristicAcousticPlus" #define CharacteristicAcousticMinus_s "CharacteristicAcousticMinus" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Forces and Moments * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define ForceX_s "ForceX" #define ForceY_s "ForceY" #define ForceZ_s "ForceZ" #define ForceR_s "ForceR" #define ForceTheta_s "ForceTheta" #define ForcePhi_s "ForcePhi" #define Lift_s "Lift" #define Drag_s "Drag" #define MomentX_s "MomentX" #define MomentY_s "MomentY" #define MomentZ_s "MomentZ" #define MomentR_s "MomentR" #define MomentTheta_s "MomentTheta" #define MomentPhi_s "MomentPhi" #define MomentXi_s "MomentXi" #define MomentEta_s "MomentEta" #define MomentZeta_s "MomentZeta" #define Moment_CenterX_s "Moment_CenterX" #define Moment_CenterY_s "Moment_CenterY" #define Moment_CenterZ_s "Moment_CenterZ" #define CoefLift_s "CoefLift" #define CoefDrag_s "CoefDrag" #define CoefMomentX_s "CoefMomentX" #define CoefMomentY_s "CoefMomentY" #define CoefMomentZ_s "CoefMomentZ" #define CoefMomentR_s "CoefMomentR" #define CoefMomentTheta_s "CoefMomentTheta" #define CoefMomentPhi_s "CoefMomentPhi" #define CoefMomentXi_s "CoefMomentXi" #define CoefMomentEta_s "CoefMomentEta" #define CoefMomentZeta_s "CoefMomentZeta" #define Coef_PressureDynamic_s "Coef_PressureDynamic" #define Coef_Area_s "Coef_Area" #define Coef_Length_s "Coef_Length" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Time dependent flow * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define TimeValues_s "TimeValues" #define IterationValues_s "IterationValues" #define NumberOfZones_s "NumberOfZones" #define NumberOfFamilies_s "NumberOfFamilies" #define ZonePointers_s "ZonePointers" #define FamilyPointers_s "FamilyPointers" #define RigidGridMotionPointers_s "RigidGridMotionPointers" #define ArbitraryGridMotionPointers_s "ArbitraryGridMotionPointers" #define GridCoordinatesPointers_s "GridCoordinatesPointers" #define FlowSolutionPointers_s "FlowSolutionPointers" #define OriginLocation_s "OriginLocation" #define RigidRotationAngle_s "RigidRotationAngle" #define RigidVelocity_s "RigidVelocity" #define RigidRotationRate_s "RigidRotationRate" #define GridVelocityX_s "GridVelocityX" #define GridVelocityY_s "GridVelocityY" #define GridVelocityZ_s "GridVelocityZ" #define GridVelocityR_s "GridVelocityR" #define GridVelocityTheta_s "GridVelocityTheta" #define GridVelocityPhi_s "GridVelocityPhi" #define GridVelocityXi_s "GridVelocityXi" #define GridVelocityEta_s "GridVelocityEta" #define GridVelocityZeta_s "GridVelocityZeta" /* The strings defined below are type names used for node labels */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Types as strings * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define ArbitraryGridMotion_ts "ArbitraryGridMotion_t" #define Area_ts "Area_t" #define AverageInterface_ts "AverageInterface_t" #define Axisymmetry_ts "Axisymmetry_t" #define BCDataSet_ts "BCDataSet_t" #define BCData_ts "BCData_t" #define BCProperty_ts "BCProperty_t" #define BC_ts "BC_t" #define BaseIterativeData_ts "BaseIterativeData_t" #define CGNSBase_ts "CGNSBase_t" #define CGNSLibraryVersion_ts "CGNSLibraryVersion_t" #define ChemicalKineticsModel_ts "ChemicalKineticsModel_t" #define ConvergenceHistory_ts "ConvergenceHistory_t" #define DataArray_ts "DataArray_t" #define DataClass_ts "DataClass_t" #define DataConversion_ts "DataConversion_t" #define Descriptor_ts "Descriptor_t" #define DimensionalExponents_ts "DimensionalExponents_t" #define DimensionalUnits_ts "DimensionalUnits_t" #define DiscreteData_ts "DiscreteData_t" #define Elements_ts "Elements_t" #define FamilyBC_ts "FamilyBC_t" #define FamilyName_ts "FamilyName_t" #define Family_ts "Family_t" #define FlowEquationSet_ts "FlowEquationSet_t" #define FlowSolution_ts "FlowSolution_t" #define GasModel_ts "GasModel_t" #define GeometryEntity_ts "GeometryEntity_t" #define GeometryFile_ts "GeometryFile_t" #define GeometryFormat_ts "GeometryFormat_t" #define GeometryReference_ts "GeometryReference_t" #define GoverningEquations_ts "GoverningEquations_t" #define Gravity_ts "Gravity_t" #define GridConnectivity1to1_ts "GridConnectivity1to1_t" #define GridConnectivityProperty_ts "GridConnectivityProperty_t" #define GridConnectivityType_ts "GridConnectivityType_t" #define GridConnectivity_ts "GridConnectivity_t" #define GridCoordinates_ts "GridCoordinates_t" #define GridLocation_ts "GridLocation_t" #define IndexArray_ts "IndexArray_t" #define IndexRange_ts "IndexRange_t" #define IntegralData_ts "IntegralData_t" #define InwardNormalList_ts "InwardNormalList_t" #define Ordinal_ts "Ordinal_t" #define OversetHoles_ts "OversetHoles_t" #define Periodic_ts "Periodic_t" #define ReferenceState_ts "ReferenceState_t" #define RigidGridMotion_ts "RigidGridMotion_t" #define Rind_ts "Rind_t" #define RotatingCoordinates_ts "RotatingCoordinates_t" #define SimulationType_ts "SimulationType_t" #define ThermalConductivityModel_ts "ThermalConductivityModel_t" #define ThermalRelaxationModel_ts "ThermalRelaxationModel_t" #define TurbulenceClosure_ts "TurbulenceClosure_t" #define TurbulenceModel_ts "TurbulenceModel_t" #define UserDefinedData_ts "UserDefinedData_t" #define ViscosityModel_ts "ViscosityModel_t" #define WallFunction_ts "WallFunction_t" #define ZoneBC_ts "ZoneBC_t" #define ZoneGridConnectivity_ts "ZoneGridConnectivity_t" #define ZoneIterativeData_ts "ZoneIterativeData_t" #define ZoneType_ts "ZoneType_t" #define Zone_ts "Zone_t" /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * No line after this comment - * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #endif CGNS-3.4.0/src/cgns_error.c000066400000000000000000000044671343724673500153770ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include #include "cgnslib.h" #include "cgns_header.h" #include "cgns_io.h" void (*cgns_error_handler)(int, char *) = 0; char cgns_error_mess[200] = "no CGNS error reported"; CGNSDLL void cgi_error(const char *format, ...) { va_list arg; va_start(arg, format); vsprintf(cgns_error_mess,format, arg); va_end(arg); if (cgns_error_handler) (*cgns_error_handler)(1, cgns_error_mess); } CGNSDLL void cgi_warning(const char *format, ...) { va_list arg; va_start(arg, format); if (cgns_error_handler) { char warning_msg[200]; vsprintf(warning_msg, format, arg); (*cgns_error_handler)(0, warning_msg); } else { fprintf(stdout,"*** Warning:"); vfprintf(stdout,format,arg); fprintf(stdout," ***\n"); } va_end(arg); } CGNSDLL const char *cg_get_error() { return cgns_error_mess; } CGNSDLL void cg_error_exit() { if (cgns_error_handler) (*cgns_error_handler)(-1, cgns_error_mess); else fprintf(stderr,"%s\n",cgns_error_mess); cgio_cleanup(); exit(1); } CGNSDLL void cg_error_print() { fprintf(stderr,"%s\n",cgns_error_mess); } CGNSDLL void cg_io_error (const char *funcname) { char errmsg[CGIO_MAX_ERROR_LENGTH+1]; cgio_error_message(errmsg); cgi_error("%s:%s", funcname, errmsg); } CGNS-3.4.0/src/cgns_f.F90000066400000000000000000005373021343724673500146060ustar00rootroot00000000000000!------------------------------------------------------------------------- !This software is provided 'as-is', without any express or implied warranty. !In no event will the authors be held liable for any damages arising from !the use of this software. ! !Permission is granted to anyone to use this software for any purpose, !including commercial applications, and to alter it and redistribute it !freely, subject to the following restrictions: ! !1. The origin of this software must not be misrepresented; you must not ! claim that you wrote the original software. If you use this software ! in a product, an acknowledgment in the product documentation would be ! appreciated but is not required. ! !2. Altered source versions must be plainly marked as such, and must not ! be misrepresented as being the original software. ! !3. This notice may not be removed or altered from any source distribution. !------------------------------------------------------------------------- ! _____ _____ _ _ _____ ! / ____/ ____| \ | |/ ____| ! | | | | __| \| | (___ ! | | | | |_ | . ` |\___ \ ! | |___| |__| | |\ |____) | ! \_____\_____|_| \_|_____/ ! ! PURPOSE: ! Provides a module for the Fortran wrapper interfaces and CGNS ! constant parameters. ! ! ! KNOWN ISSUES: ! Routines passing an argument to a C API argument of type ! void * do not have explicit interfaces. They are the routines which ! are commented out. ! MODULE cgns USE ISO_C_BINDING, ONLY : C_INT, C_FLOAT, C_DOUBLE, C_LONG_LONG, C_CHAR, C_PTR IMPLICIT NONE #include "cgnstypes_f03.h" !These definitions are needed for Windows DLLs !DEC$ IF DEFINED(WINNT) !DEC$ ATTRIBUTES REFERENCE, C, VARYING :: cg_goto_f !DEC$ ATTRIBUTES REFERENCE, C, VARYING :: cg_array_read_f !DEC$ ATTRIBUTES REFERENCE, C, VARYING :: cg_array_read_as_f !DEC$ ATTRIBUTES REFERENCE, C, VARYING :: cg_array_write_f !DEC$ ENDIF #if CG_BUILD_64BIT_F # if HAVE_FORTRAN_2003 INTEGER, PARAMETER :: CGSIZE_T = C_LONG_LONG INTEGER, PARAMETER :: CGID_T = C_DOUBLE INTEGER, PARAMETER :: CGLONG_T = C_LONG_LONG # else INTEGER, PARAMETER :: cgint_kind = SELECTED_INT_KIND(15) ! should map to INTEGER*8 on most modern processors INTEGER, PARAMETER :: cgdouble_kind = SELECTED_REAL_KIND(10) ! should map to REAL*8 on most modern processors INTEGER, PARAMETER :: CGSIZE_T = cgint_kind INTEGER, PARAMETER :: CGID_T = cgdouble_kind INTEGER, PARAMETER :: CGLONG_T = cgint_kind # endif LOGICAL, PARAMETER :: CG_BUILD_64BIT = .TRUE. #else # if HAVE_FORTRAN_2003 INTEGER, PARAMETER :: CGSIZE_T = C_INT INTEGER, PARAMETER :: CGID_T = C_DOUBLE INTEGER, PARAMETER :: CGLONG_T = C_LONG_LONG # else INTEGER, PARAMETER :: cgint_kind = SELECTED_INT_KIND(5) ! should map to INTEGER*4 on most modern processors INTEGER, PARAMETER :: cglong_kind = SELECTED_INT_KIND(15) ! should map to INTEGER*8 on most modern processors INTEGER, PARAMETER :: cgdouble_kind = SELECTED_REAL_KIND(10) ! should map to REAL*8 on most modern processors INTEGER, PARAMETER :: CGSIZE_T = cgint_kind INTEGER, PARAMETER :: CGID_T = cgdouble_kind INTEGER, PARAMETER :: CGLONG_T = cglong_kind # endif LOGICAL, PARAMETER :: CG_BUILD_64BIT = .FALSE. #endif INTEGER, PARAMETER, PRIVATE :: MAX_LEN = 32 INTERFACE cgio_set_dimensions_f SUBROUTINE cgio_set_dimensions_f_0(cgio_num, id, data_type, ndims, dims, ier) ! BIND(C, NAME="cgio_set_dimensions_f_0") IMPORT :: CGSIZE_T, C_DOUBLE, C_CHAR IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR, LEN=*) :: data_type INTEGER :: ndims INTEGER(CGSIZE_T) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_set_dimensions_f_0 SUBROUTINE cgio_set_dimensions_f_1(cgio_num, id, data_type, ndims, dims, ier) ! BIND(C, NAME="cgio_set_dimensions_f_1") IMPORT :: CGSIZE_T, C_DOUBLE, C_CHAR IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR, LEN=*) :: data_type INTEGER :: ndims INTEGER(CGSIZE_T), DIMENSION(*) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_set_dimensions_f_1 END INTERFACE INTERFACE cgio_get_dimensions_f SUBROUTINE cgio_get_dimensions_f_0(cgio_num, id, ndims, dims, ier) BIND(C, NAME="cgio_get_dimensions_f_0") IMPORT :: C_DOUBLE, CGSIZE_T IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER :: ndims INTEGER(CGSIZE_T) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_dimensions_f_0 SUBROUTINE cgio_get_dimensions_f_1(cgio_num, id, ndims, dims, ier) BIND(C, NAME="cgio_get_dimensions_f_1") IMPORT :: C_DOUBLE, CGSIZE_T IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER :: ndims INTEGER(CGSIZE_T), DIMENSION(*) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_dimensions_f_1 END INTERFACE ! Fortran version of cgnslib.h ! !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* modes for cgns file * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTEGER(C_INT), PARAMETER :: CG_MODE_READ = 0 INTEGER(C_INT), PARAMETER :: CG_MODE_WRITE = 1 INTEGER(C_INT), PARAMETER :: CG_MODE_MODIFY = 2 INTEGER(C_INT), PARAMETER :: CG_MODE_CLOSED = 3 ! file open modes (found in cgns_io.h) INTEGER(C_INT), PARAMETER :: CGIO_MODE_READ = 0 INTEGER(C_INT), PARAMETER :: CGIO_MODE_WRITE = 1 INTEGER(C_INT), PARAMETER :: CGIO_MODE_MODIFY = 2 ! database file types (found in cgns_io.h) INTEGER(C_INT), PARAMETER :: CGIO_FILE_NONE = 0 INTEGER(C_INT), PARAMETER :: CGIO_FILE_ADF = 1 INTEGER(C_INT), PARAMETER :: CGIO_FILE_HDF5 = 2 INTEGER(C_INT), PARAMETER :: CGIO_FILE_ADF2 = 3 !* legacy code support INTEGER(C_INT) MODE_READ, MODE_WRITE, MODE_MODIFY PARAMETER (MODE_READ = 0) PARAMETER (MODE_WRITE = 1) PARAMETER (MODE_MODIFY = 2) !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* file types (found in cgnslib.h) * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTEGER(C_INT), PARAMETER :: CG_FILE_NONE = 0 INTEGER(C_INT), PARAMETER :: CG_FILE_ADF = 1 INTEGER(C_INT), PARAMETER :: CG_FILE_HDF5 = 2 INTEGER(C_INT), PARAMETER :: CG_FILE_ADF2 = 3 !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* some error code (found in cgnslib.h) * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTEGER(C_INT), PARAMETER :: CG_OK = 0 INTEGER(C_INT), PARAMETER :: CG_ERROR = 1 INTEGER(C_INT), PARAMETER :: CG_NODE_NOT_FOUND = 2 INTEGER(C_INT), PARAMETER :: CG_INCORRECT_PATH = 3 INTEGER(C_INT), PARAMETER :: CG_CG_NO_INDEX_DIM = 4 !* legacy code support INTEGER(C_INT) ALL_OK, ERROR, NODE_NOT_FOUND, INCORRECT_PATH PARAMETER (ALL_OK = 0) PARAMETER (ERROR = 1) PARAMETER (NODE_NOT_FOUND = 2) PARAMETER (INCORRECT_PATH = 3) !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Parallel CGNS parameters * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ENUM, BIND(C) ENUMERATOR :: CGP_INDEPENDENT = 0 ENUMERATOR :: CGP_COLLECTIVE = 1 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Dimensional Units (found in cgnslib.h) * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTEGER(C_INT), PARAMETER :: CG_Null = 0 INTEGER(C_INT), PARAMETER :: CG_UserDefined = 1 !* legacy code support INTEGER(C_INT) Null, UserDefined PARAMETER (Null = 0) PARAMETER (UserDefined = 1) CHARACTER(LEN=MAX_LEN) :: MassUnitsName(0:5) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(MassUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(MassUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Kilogram) = 2 ENUMERATOR :: CGNS_ENUMV(Gram) = 3 ENUMERATOR :: CGNS_ENUMV(Slug) = 4 ENUMERATOR :: CGNS_ENUMV(PoundMass) = 5 END ENUM CHARACTER(LEN=MAX_LEN) :: LengthUnitsName(0:6) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(LengthUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(LengthUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Meter) = 2 ENUMERATOR :: CGNS_ENUMV(Centimeter) = 3 ENUMERATOR :: CGNS_ENUMV(Millimeter) = 4 ENUMERATOR :: CGNS_ENUMV(Foot) = 5 ENUMERATOR :: CGNS_ENUMV(Inch) = 6 END ENUM CHARACTER(LEN=MAX_LEN) :: TimeUnitsName(0:2) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(TimeUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(TimeUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Second) = 2 END ENUM CHARACTER(LEN=MAX_LEN) :: TemperatureUnitsName(0:5) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(TemperatureUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(TemperatureUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Kelvin) = 2 ENUMERATOR :: CGNS_ENUMV(Celsius) = 3 ENUMERATOR :: CGNS_ENUMV(Rankine) = 4 ENUMERATOR :: CGNS_ENUMV(Fahrenheit) = 5 END ENUM CHARACTER(LEN=MAX_LEN) :: AngleUnitsName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(AngleUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(AngleUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Degree) = 2 ENUMERATOR :: CGNS_ENUMV(Radian) = 3 END ENUM CHARACTER(LEN=MAX_LEN) :: ElectricCurrentUnitsName(0:6) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(ElectricCurrentUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(ElectricCurrentUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Ampere) = 2 ENUMERATOR :: CGNS_ENUMV(Abampere) = 3 ENUMERATOR :: CGNS_ENUMV(Statampere) = 4 ENUMERATOR :: CGNS_ENUMV(Edison) = 5 ENUMERATOR :: CGNS_ENUMV(auCurrent) = 6 END ENUM CHARACTER(LEN=MAX_LEN) :: SubstanceAmountUnitsName(0:5) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(SubstanceAmountUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(SubstanceAmountUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Mole) = 2 ENUMERATOR :: CGNS_ENUMV(Entities) = 3 ENUMERATOR :: CGNS_ENUMV(StandardCubicFoot) = 4 ENUMERATOR :: CGNS_ENUMV(StandardCubicMeter) = 5 END ENUM CHARACTER(LEN=MAX_LEN) :: LuminousIntensityUnitsName(0:6) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(LuminousIntensityUnitsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(LuminousIntensityUnitsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Candela) = 2 ENUMERATOR :: CGNS_ENUMV(Candle) = 3 ENUMERATOR :: CGNS_ENUMV(Carcel) = 4 ENUMERATOR :: CGNS_ENUMV(Hefner) = 5 ENUMERATOR :: CGNS_ENUMV(Violle) = 6 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Data Class (found in cgnslib.h * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: DataClassName(0:6) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(DataClassNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(DataClassUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Dimensional) = 2 ENUMERATOR :: CGNS_ENUMV(NormalizedByDimensional) = 3 ENUMERATOR :: CGNS_ENUMV(NormalizedByUnknownDimensional) = 4 ENUMERATOR :: CGNS_ENUMV(NondimensionalParameter) = 5 ENUMERATOR :: CGNS_ENUMV(DimensionlessConstant) = 6 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Location * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: GridLocationName(0:8) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(GridLocationNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(GridLocationUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Vertex) = 2 ENUMERATOR :: CGNS_ENUMV(CellCenter) = 3 ENUMERATOR :: CGNS_ENUMV(FaceCenter) = 4 ENUMERATOR :: CGNS_ENUMV(IFaceCenter) = 5 ENUMERATOR :: CGNS_ENUMV(JFaceCenter) = 6 ENUMERATOR :: CGNS_ENUMV(KFaceCenter) = 7 ENUMERATOR :: CGNS_ENUMV(EdgeCenter) = 8 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Connectivity Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: GridConnectivityTypeName(0:4) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(GridConnectivityTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(GridConnectivityTypeUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Overset) = 2 ENUMERATOR :: CGNS_ENUMV(Abutting) = 3 ENUMERATOR :: CGNS_ENUMV(Abutting1to1) = 4 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Point Set Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: PointSetTypeName(0:8) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(PointSetTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(PointSetTypeUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(PointList) = 2 ENUMERATOR :: CGNS_ENUMV(PointListDonor) = 3 ENUMERATOR :: CGNS_ENUMV(PointRange) = 4 ENUMERATOR :: CGNS_ENUMV(PointRangeDonor) = 5 ENUMERATOR :: CGNS_ENUMV(ElementRange) = 6 ENUMERATOR :: CGNS_ENUMV(ElementList) = 7 ENUMERATOR :: CGNS_ENUMV(CellListDonor) = 8 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Governing Equations and Physical Models Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: GoverningEquationsTypeName(0:7) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(GoverningEquationsNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(GoverningEquationsUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(FullPotential) = 2 ENUMERATOR :: CGNS_ENUMV(Euler) = 3 ENUMERATOR :: CGNS_ENUMV(NSLaminar) = 4 ENUMERATOR :: CGNS_ENUMV(NSTurbulent) = 5 ENUMERATOR :: CGNS_ENUMV(NSLaminarIncompressible) = 6 ENUMERATOR :: CGNS_ENUMV(NSTurbulentIncompressible) = 7 END ENUM !** Any model type will accept both ModelTypeNull and ModelTypeUserDefined. !** The following models will accept these values as vaild... !** !** GasModel_t: Ideal, VanderWaals, CaloricallyPerfect, ThermallyPerfect, !** ConstantDensity, RedlichKwong !** !** ViscosityModel_t: Constant, PowerLaw, SutherlandLaw !** !** ThermalConductivityModel_t: PowerLaw, SutherlandLaw, ConstantPrandtl !** !** TurbulenceModel_t: Algebraic_BaldwinLomax, Algebraic_CebeciSmith, !** HalfEquation_JohnsonKing, OneEquation_BaldwinBarth, !** OneEquation_SpalartAllmaras, TwoEquation_JonesLaunder, !** TwoEquation_MenterSST,TwoEquation_Wilcox !** !** TurbulenceClosure_t: EddyViscosity, ReynoldsStress, !** ReynoldsStressAlgebraic !** !** ThermalRelaxationModel_t: Frozen, ThermalEquilib, ThermalNonequilib !** !** ChemicalKineticsModel_t: Frozen, ChemicalEquilibCurveFit, !** ChemicalEquilibMinimization, ChemicalNonequilib !** !** EMElectricFieldModel_t: Voltage, Interpolated, Constant, Frozen !** !** EMMagneticFieldModel_t: Interpolated, Constant, Frozen !** !** EMConductivityModel_t: Constant, Frozen, Equilibrium_LinRessler, !** Chemistry_LinRessler CHARACTER(LEN=MAX_LEN) :: ModelTypeName(0:35) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(ModelTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(ModelTypeUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Ideal) = 2 ENUMERATOR :: CGNS_ENUMV(VanderWaals) = 3 ENUMERATOR :: CGNS_ENUMV(Constant) = 4 ENUMERATOR :: CGNS_ENUMV(PowerLaw) = 5 ENUMERATOR :: CGNS_ENUMV(SutherlandLaw) = 6 ENUMERATOR :: CGNS_ENUMV(ConstantPrandtl) = 7 ENUMERATOR :: CGNS_ENUMV(EddyViscosity) = 8 ENUMERATOR :: CGNS_ENUMV(ReynoldsStress) = 9 ENUMERATOR :: CGNS_ENUMV(ReynoldsStressAlgebraic) = 10 ENUMERATOR :: CGNS_ENUMV(Algebraic_BaldwinLomax) = 11 ENUMERATOR :: CGNS_ENUMV(Algebraic_CebeciSmith) = 12 ENUMERATOR :: CGNS_ENUMV(HalfEquation_JohnsonKing) = 13 ENUMERATOR :: CGNS_ENUMV(OneEquation_BaldwinBarth) = 14 ENUMERATOR :: CGNS_ENUMV(OneEquation_SpalartAllmaras) = 15 ENUMERATOR :: CGNS_ENUMV(TwoEquation_JonesLaunder) = 16 ENUMERATOR :: CGNS_ENUMV(TwoEquation_MenterSST) = 17 ENUMERATOR :: CGNS_ENUMV(TwoEquation_Wilcox) = 18 ENUMERATOR :: CGNS_ENUMV(CaloricallyPerfect) = 19 ENUMERATOR :: CGNS_ENUMV(ThermallyPerfect) = 20 ENUMERATOR :: CGNS_ENUMV(ConstantDensity) = 21 ENUMERATOR :: CGNS_ENUMV(RedlichKwong) = 22 ENUMERATOR :: CGNS_ENUMV(Frozen) = 23 ENUMERATOR :: CGNS_ENUMV(ThermalEquilib) = 24 ENUMERATOR :: CGNS_ENUMV(ThermalNonequilib) = 25 ENUMERATOR :: CGNS_ENUMV(ChemicalEquilibCurveFit) = 26 ENUMERATOR :: CGNS_ENUMV(ChemicalEquilibMinimization) = 27 ENUMERATOR :: CGNS_ENUMV(ChemicalNonequilib) = 28 ENUMERATOR :: CGNS_ENUMV(EMElectricField) = 29 ENUMERATOR :: CGNS_ENUMV(EMMagneticField) = 30 ENUMERATOR :: CGNS_ENUMV(EMConductivity) = 31 ENUMERATOR :: CGNS_ENUMV(Voltage) = 32 ENUMERATOR :: CGNS_ENUMV(Interpolated) = 33 ENUMERATOR :: CGNS_ENUMV(Equilibrium_LinRessler) = 34 ENUMERATOR :: CGNS_ENUMV(Chemistry_LinRessler) = 35 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Boundary Condition Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: BCTypeName(0:25) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(BCTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(BCTypeUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(BCAxisymmetricWedge) = 2 ENUMERATOR :: CGNS_ENUMV(BCDegenerateLine) = 3 ENUMERATOR :: CGNS_ENUMV(BCDegeneratePoint) = 4 ENUMERATOR :: CGNS_ENUMV(BCDirichlet) = 5 ENUMERATOR :: CGNS_ENUMV(BCExtrapolate) = 6 ENUMERATOR :: CGNS_ENUMV(BCFarfield) = 7 ENUMERATOR :: CGNS_ENUMV(BCGeneral) = 8 ENUMERATOR :: CGNS_ENUMV(BCInflow) = 9 ENUMERATOR :: CGNS_ENUMV(BCInflowSubsonic) = 10 ENUMERATOR :: CGNS_ENUMV(BCInflowSupersonic) = 11 ENUMERATOR :: CGNS_ENUMV(BCNeumann) = 12 ENUMERATOR :: CGNS_ENUMV(BCOutflow) = 13 ENUMERATOR :: CGNS_ENUMV(BCOutflowSubsonic) = 14 ENUMERATOR :: CGNS_ENUMV(BCOutflowSupersonic) = 15 ENUMERATOR :: CGNS_ENUMV(BCSymmetryPlane) = 16 ENUMERATOR :: CGNS_ENUMV(BCSymmetryPolar) = 17 ENUMERATOR :: CGNS_ENUMV(BCTunnelInflow) = 18 ENUMERATOR :: CGNS_ENUMV(BCTunnelOutflow) = 19 ENUMERATOR :: CGNS_ENUMV(BCWall) = 20 ENUMERATOR :: CGNS_ENUMV(BCWallInviscid) = 21 ENUMERATOR :: CGNS_ENUMV(BCWallViscous) = 22 ENUMERATOR :: CGNS_ENUMV(BCWallViscousHeatFlux) = 23 ENUMERATOR :: CGNS_ENUMV(BCWallViscousIsothermal) = 24 ENUMERATOR :: CGNS_ENUMV(FamilySpecified) = 25 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Data types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: DataTypeName(0:6) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(DataTypeNull) ENUMERATOR :: CGNS_ENUMV(DataTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(Integer) ENUMERATOR :: CGNS_ENUMV(RealSingle) ENUMERATOR :: CGNS_ENUMV(RealDouble) ENUMERATOR :: CGNS_ENUMV(Character) ENUMERATOR :: CGNS_ENUMV(LongInteger) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* BCData_t types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: BCDataTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(BCDataTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(BCDataTypeUserDefined) = CG_UserDefined ENUMERATOR :: CGNS_ENUMV(Dirichlet) = 2 ENUMERATOR :: CGNS_ENUMV(Neumann) = 3 END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Element types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: ElementTypeName(0:56) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(ElementTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(ElementTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(NODE) ENUMERATOR :: CGNS_ENUMV(BAR_2) ENUMERATOR :: CGNS_ENUMV(BAR_3) ENUMERATOR :: CGNS_ENUMV(TRI_3) ENUMERATOR :: CGNS_ENUMV(TRI_6) ENUMERATOR :: CGNS_ENUMV(QUAD_4) ENUMERATOR :: CGNS_ENUMV(QUAD_8) ENUMERATOR :: CGNS_ENUMV(QUAD_9) ENUMERATOR :: CGNS_ENUMV(TETRA_4) ENUMERATOR :: CGNS_ENUMV(TETRA_10) ENUMERATOR :: CGNS_ENUMV(PYRA_5) ENUMERATOR :: CGNS_ENUMV(PYRA_14) ENUMERATOR :: CGNS_ENUMV(PENTA_6) ENUMERATOR :: CGNS_ENUMV(PENTA_15) ENUMERATOR :: CGNS_ENUMV(PENTA_18) ENUMERATOR :: CGNS_ENUMV(HEXA_8) ENUMERATOR :: CGNS_ENUMV(HEXA_20) ENUMERATOR :: CGNS_ENUMV(HEXA_27) ENUMERATOR :: CGNS_ENUMV(MIXED) ENUMERATOR :: CGNS_ENUMV(PYRA_13) ENUMERATOR :: CGNS_ENUMV(NGON_n) ENUMERATOR :: CGNS_ENUMV(NFACE_n) ENUMERATOR :: CGNS_ENUMV(BAR_4) ENUMERATOR :: CGNS_ENUMV(TRI_9) ENUMERATOR :: CGNS_ENUMV(TRI_10) ENUMERATOR :: CGNS_ENUMV(QUAD_12) ENUMERATOR :: CGNS_ENUMV(QUAD_16) ENUMERATOR :: CGNS_ENUMV(TETRA_16) ENUMERATOR :: CGNS_ENUMV(TETRA_20) ENUMERATOR :: CGNS_ENUMV(PYRA_21) ENUMERATOR :: CGNS_ENUMV(PYRA_29) ENUMERATOR :: CGNS_ENUMV(PYRA_30) ENUMERATOR :: CGNS_ENUMV(PENTA_24) ENUMERATOR :: CGNS_ENUMV(PENTA_38) ENUMERATOR :: CGNS_ENUMV(PENTA_40) ENUMERATOR :: CGNS_ENUMV(HEXA_32) ENUMERATOR :: CGNS_ENUMV(HEXA_56) ENUMERATOR :: CGNS_ENUMV(HEXA_64) ENUMERATOR :: CGNS_ENUMV(BAR_5) ENUMERATOR :: CGNS_ENUMV(TRI_12) ENUMERATOR :: CGNS_ENUMV(TRI_15) ENUMERATOR :: CGNS_ENUMV(QUAD_P4_16) ENUMERATOR :: CGNS_ENUMV(QUAD_25) ENUMERATOR :: CGNS_ENUMV(TETRA_22) ENUMERATOR :: CGNS_ENUMV(TETRA_34) ENUMERATOR :: CGNS_ENUMV(TETRA_35) ENUMERATOR :: CGNS_ENUMV(PYRA_P4_29) ENUMERATOR :: CGNS_ENUMV(PYRA_50) ENUMERATOR :: CGNS_ENUMV(PYRA_55) ENUMERATOR :: CGNS_ENUMV(PENTA_33) ENUMERATOR :: CGNS_ENUMV(PENTA_66) ENUMERATOR :: CGNS_ENUMV(PENTA_75) ENUMERATOR :: CGNS_ENUMV(HEXA_44) ENUMERATOR :: CGNS_ENUMV(HEXA_98) ENUMERATOR :: CGNS_ENUMV(HEXA_125) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Zone types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: ZoneTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(ZoneTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(ZoneTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(Structured) ENUMERATOR :: CGNS_ENUMV(Unstructured) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Rigid Grid Motion types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: RigidGridMotionTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(RigidGridMotionTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(RigidGridMotionTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(ConstantRate) ENUMERATOR :: CGNS_ENUMV(VariableRate) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Arbitrary Grid Motion types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: ArbitraryGridMotionTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(ArbitraryGridMotionTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(ArbitraryGridMotionTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(NonDeformingGrid) ENUMERATOR :: CGNS_ENUMV(DeformingGrid) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Simulation type * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: SimulationTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(SimulationTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(SimulationTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(TimeAccurate) ENUMERATOR :: CGNS_ENUMV(NonTimeAccurate) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* BC Property types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: WallFunctionTypeName(0:2) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(WallFunctionTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(WallFunctionTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(Generic) END ENUM CHARACTER(LEN=MAX_LEN) :: AreaTypeName(0:3) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(AreaTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(AreaTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(BleedArea) ENUMERATOR :: CGNS_ENUMV(CaptureArea) END ENUM !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Connectivity Property types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CHARACTER(LEN=MAX_LEN) :: AverageInterfaceTypeName(0:7) ENUM, BIND(C) ENUMERATOR :: CGNS_ENUMV(AverageInterfaceTypeNull) = CG_Null ENUMERATOR :: CGNS_ENUMV(AverageInterfaceTypeUserDefined) ENUMERATOR :: CGNS_ENUMV(AverageAll) ENUMERATOR :: CGNS_ENUMV(AverageCircumferential) ENUMERATOR :: CGNS_ENUMV(AverageRadial) ENUMERATOR :: CGNS_ENUMV(AverageI) ENUMERATOR :: CGNS_ENUMV(AverageJ) ENUMERATOR :: CGNS_ENUMV(AverageK) END ENUM ! For portability to Linux Absoft, all data statements were moved after the ! variables and parametres declarations !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Dimensional Units * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA MassUnitsName /'Null','UserDefined','Kilogram','Gram', & 'Slug','PoundMass'/ DATA LengthUnitsName / 'Null', 'UserDefined', & 'Meter','Centimeter','Millimeter','Foot','Inch'/ DATA TimeUnitsName /'Null','UserDefined','Second'/ DATA TemperatureUnitsName /'Null','UserDefined', & 'Kelvin','Celsius','Rankine','Fahrenheit'/ DATA AngleUnitsName /'Null','UserDefined','Degree','Radian'/ DATA ElectricCurrentUnitsName /'Null', 'UserDefined', 'Ampere', & 'Abampere', 'Statampere', 'Edison', 'a.u.'/ DATA SubstanceAmountUnitsName /'Null', 'UserDefined', 'Mole', & 'Entities', 'StandardCubicFoot', 'StandardCubicMeter'/ DATA LuminousIntensityUnitsName /'Null', 'UserDefined', & 'Candela', 'Candle', 'Carcel', 'Hefner', 'Violle'/ !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Data Class * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA DataClassName / 'Null','UserDefined', & 'Dimensional','NormalizedByDimensional', & 'NormalizedByUnknownDimensional', & 'NondimensionalParameter','DimensionlessConstant'/ !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Location * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA GridLocationName / 'Null','UserDefined', & 'Vertex','CellCenter','FaceCenter','IFaceCenter', & 'JFaceCenter','KFaceCenter','EdgeCenter' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Connectivity Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA GridConnectivityTypeName / 'Null','UserDefined', & 'Overset','Abutting','Abutting1to1'/ !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Point Set Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA PointSetTypeName / 'Null','UserDefined', & 'PointList','PointListDonor', & 'PointRange','PointRangeDonor', & 'ElementRange','ElementList','CellListDonor'/ !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Governing Equations and Physical Models Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA GoverningEquationsTypeName / 'Null','UserDefined', & 'FullPotential','Euler', 'NSLaminar', 'NSTurbulent', & 'NSLaminarIncompressible', 'NSTurbulentIncompressible'/ DATA ModelTypeName / 'Null','UserDefined', & 'Ideal','VanderWaals', 'Constant','PowerLaw', & 'SutherlandLaw','ConstantPrandtl','EddyViscosity', & 'ReynoldsStress','ReynoldsStressAlgebraic', & 'Algebraic_BaldwinLomax','Algebraic_CebeciSmith', & 'HalfEquation_JohnsonKing','OneEquation_BaldwinBarth', & 'OneEquation_SpalartAllmaras','TwoEquation_JonesLaunder', & 'TwoEquation_MenterSST','TwoEquation_Wilcox', & 'CaloricallyPerfect', 'ThermallyPerfect', & 'ConstantDensity', 'RedlichKwong', 'Frozen', & 'ThermalEquilib', 'ThermalNonequilib', & 'ChemicalEquilibCurveFit', 'ChemicalEquilibMinimization', & 'ChemicalNonequilib', 'EMElectricField', & 'EMMagneticField', 'EMConductivity', 'Voltage', & 'Interpolated', 'Equilibrium_LinRessler', & 'Chemistry_LinRessler'/ !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Boundary Condition Types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA BCTypeName / 'Null','UserDefined', & 'BCAxisymmetricWedge','BCDegenerateLine', & 'BCDegeneratePoint','BCDirichlet','BCExtrapolate', & 'BCFarfield','BCGeneral','BCInflow','BCInflowSubsonic', & 'BCInflowSupersonic','BCNeumann','BCOutflow', & 'BCOutflowSubsonic','BCOutflowSupersonic', & 'BCSymmetryPlane','BCSymmetryPolar','BCTunnelInflow', & 'BCTunnelOutflow','BCWall','BCWallInviscid', & 'BCWallViscous','BCWallViscousHeatFlux', & 'BCWallViscousIsothermal','FamilySpecified' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Data types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA DataTypeName / 'Null','UserDefined', & 'Integer','RealSingle','RealDouble','Character', & 'LongInteger' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* BCData_t types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA BCDataTypeName / 'Null','UserDefined', & 'Dirichlet', 'Neumann' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Element types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA ElementTypeName / 'Null','UserDefined', & 'NODE', 'BAR_2', 'BAR_3', 'TRI_3', 'TRI_6', & 'QUAD_4', 'QUAD_8', 'QUAD_9', 'TETRA_4', 'TETRA_10', & 'PYRA_5', 'PYRA_14', 'PENTA_6', 'PENTA_15', & 'PENTA_18', 'HEXA_8', 'HEXA_20', 'HEXA_27', 'MIXED', & 'PYRA_13', 'NGON_n', 'NFACE_n', & 'BAR_4', 'TRI_9', 'TRI_10', & 'QUAD_12', 'QUAD_16', & 'TETRA_16', 'TETRA_20', & 'PYRA_21', 'PYRA_29', 'PYRA_30', & 'PENTA_24', 'PENTA_38', 'PENTA_40', & 'HEXA_32', 'HEXA_56', 'HEXA_64', & 'BAR_5', 'TRI_12', 'TRI_15', & 'QUAD_P4_16', 'QUAD_25', & 'TETRA_22', 'TETRA_34', 'TETRA_35', & 'PYRA_P4_29', 'PYRA_50', 'PYRA_55', & 'PENTA_33', 'PENTA_66', 'PENTA_75', & 'HEXA_44', 'HEXA_98', 'HEXA_125' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Zone types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA ZoneTypeName / 'Null','UserDefined', & 'Structured', 'Unstructured' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Rigid Grid Motion types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA RigidGridMotionTypeName / 'Null','UserDefined', & 'ConstantRate', 'VariableRate' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Arbitrary Grid Motion types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA ArbitraryGridMotionTypeName / 'Null','UserDefined', & 'NonDeformingGrid', 'DeformingGrid' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Simulation type * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA SimulationTypeName / 'Null','UserDefined', & 'TimeAccurate', 'NonTimeAccurate' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* BC Property types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA WallFunctionTypeName / 'Null','UserDefined',& 'Generic' / DATA AreaTypeName / 'Null','UserDefined', & 'BleedArea', 'CaptureArea' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* Grid Connectivity Property types * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * DATA AverageInterfaceTypeName / 'Null','UserDefined', & 'AverageAll', 'AverageCircumferential', 'AverageRadial', & 'AverageI', 'AverageJ', 'AverageK' / !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* ENUMTYPE FOR FORTRAN FUNCTIONS * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTEGER, PARAMETER :: cgenum_t = KIND(CGP_INDEPENDENT) !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* INTERFACES FOR THE FORTRAN FUNCTIONS * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * INTERFACE INTEGER(C_INT) FUNCTION cg_is_cgns(filename, file_type) BIND(C,NAME="cg_is_cgns") USE ISO_C_BINDING IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER, INTENT(OUT) :: file_type END FUNCTION cg_is_cgns END INTERFACE INTERFACE INTEGER(C_INT) FUNCTION cg_open(filename, mode, fn) BIND(C,NAME="cg_open") USE ISO_C_BINDING IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER(C_INT), INTENT(IN), VALUE :: mode INTEGER, INTENT(OUT) :: fn END FUNCTION cg_open END INTERFACE INTERFACE SUBROUTINE cg_version_f(fn,FileVersion, ier) BIND(C,NAME="cg_version_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn REAL(C_FLOAT) :: FileVersion INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_version_f END INTERFACE INTERFACE SUBROUTINE cg_precision_f(fn, PRECISION, ier) BIND(C,NAME="cg_precision_f") IMPLICIT NONE INTEGER :: fn INTEGER :: PRECISION INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_precision_f END INTERFACE INTERFACE SUBROUTINE cg_close_f(fn, ier) BIND(C,NAME="cg_close_f") IMPLICIT NONE INTEGER :: fn INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_close_f END INTERFACE INTERFACE SUBROUTINE cg_save_as_f(fn, filename, file_type, follow_links, ier) ! BIND(C,NAME="cg_save_as_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER :: file_type INTEGER :: follow_links INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_save_as_f END INTERFACE INTERFACE SUBROUTINE cg_set_file_type_f(ft, ier) BIND(C,NAME="cg_set_file_type_f") IMPLICIT NONE INTEGER :: ft INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_set_file_type_f END INTERFACE INTERFACE SUBROUTINE cg_get_file_type_f(fn, ft, ier) BIND(C,NAME="cg_get_file_type_f") IMPLICIT NONE INTEGER :: fn INTEGER :: ft INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_get_file_type_f END INTERFACE INTERFACE SUBROUTINE cg_set_compress_f(cmpr, ier) BIND(C, NAME="cg_set_compress_f") IMPLICIT NONE INTEGER :: cmpr INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_set_compress_f END INTERFACE INTERFACE SUBROUTINE cg_get_compress_f(cmpr, ier) BIND(C, NAME="cg_get_compress_f") INTEGER :: cmpr INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_get_compress_f END INTERFACE INTERFACE SUBROUTINE cg_set_path_f(pathname, ier) !BIND(C, NAME="cg_set_path_f") USE ISO_C_BINDING IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: pathname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_set_path_f END INTERFACE INTERFACE SUBROUTINE cg_add_path_f(pathname, ier) !BIND(C, NAME="cg_add_path_f") USE ISO_C_BINDING IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: pathname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_add_path_f END INTERFACE INTERFACE SUBROUTINE cg_set_rind_zero_f(ier) BIND(C, NAME="cg_set_rind_zero_f") IMPLICIT NONE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_set_rind_zero_f END INTERFACE INTERFACE SUBROUTINE cg_set_rind_core_f(ier) BIND(C, NAME="cg_set_rind_core_f") IMPLICIT NONE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_set_rind_core_f END INTERFACE INTERFACE SUBROUTINE cg_get_cgio_f(fn, cgio_num, ier) BIND(C, NAME="cg_get_cgio_f") IMPLICIT NONE INTEGER :: fn INTEGER :: cgio_num INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_get_cgio_f END INTERFACE INTERFACE SUBROUTINE cg_root_id_f(fn, rootid, ier) BIND(C, NAME="cg_root_id_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn REAL(C_DOUBLE) :: rootid INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_root_id_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! Read and write CGNSBase_t Nodes ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INTERFACE SUBROUTINE cg_nbases_f(fn, nbases, ier) BIND(C, NAME="cg_nbases_f") IMPLICIT NONE INTEGER :: fn INTEGER :: nbases INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nbases_f END INTERFACE INTERFACE SUBROUTINE cg_base_read_f(fn, B, basename, cell_dim, phys_dim, ier) !BIND(C, NAME="cg_base_read_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn INTEGER :: B CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: basename INTEGER :: cell_dim INTEGER :: phys_dim INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_base_read_f END INTERFACE INTERFACE SUBROUTINE cg_base_id_f(fn, B, base_id, ier) BIND(C, NAME="cg_base_id_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn INTEGER :: B REAL(C_DOUBLE) :: base_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_base_id_f END INTERFACE INTERFACE SUBROUTINE cg_base_write_f(fn, basename, cell_dim, phys_dim, B, ier) !BIND(C, NAME="cg_base_write_f") USE ISO_C_BINDING IMPLICIT NONE INTEGER :: fn CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: basename INTEGER :: cell_dim INTEGER :: phys_dim INTEGER :: B INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_base_write_f END INTERFACE INTERFACE SUBROUTINE cg_cell_dim_f(fn, B, dim, ier) BIND(C, NAME="cg_cell_dim_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: dim INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_cell_dim_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! Read and write Zone_t Nodes ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - INTERFACE SUBROUTINE cg_nzones_f(fn, B, nzones, ier) BIND(C, NAME="cg_nzones_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: nzones INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nzones_f END INTERFACE INTERFACE SUBROUTINE cg_zone_type_f(fn, B, Z, type, ier) BIND(C, NAME="cg_zone_type_f") IMPORT :: cgenum_t, c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER(cgenum_t) :: type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zone_type_f END INTERFACE INTERFACE SUBROUTINE cg_zone_read_f(fn, B, Z, zonename, size, ier) !BIND(C, NAME="cg_zone_read_f") IMPORT :: CGSIZE_T, c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: zonename INTEGER(CGSIZE_T), DIMENSION(*) :: size INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zone_read_f END INTERFACE INTERFACE SUBROUTINE cg_zone_id_f(fn, B, Z, zone_id, ier) BIND(C, NAME="cg_zone_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z REAL(C_DOUBLE) :: zone_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zone_id_f END INTERFACE INTERFACE SUBROUTINE cg_zone_write_f(fn, B, zonename, size, TYPE, Z, ier) !BIND(C, NAME="cg_zone_write_f") IMPORT :: cgenum_t, c_char, cgsize_t IMPLICIT NONE INTEGER, INTENT(IN) :: fn INTEGER, INTENT(IN) :: B CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: zonename INTEGER(CGSIZE_T), DIMENSION(*), INTENT(IN) :: size INTEGER(cgenum_t), INTENT(IN) :: TYPE INTEGER, INTENT(OUT) :: Z INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zone_write_f END INTERFACE INTERFACE SUBROUTINE cg_index_dim_f(fn, B, Z, dim, ier) BIND(C, NAME="cg_index_dim_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: dim INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_index_dim_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write Family_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nfamilies_f(fn, B, nfamilies, ier) BIND(C, NAME="cg_nfamilies_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: nfamilies INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nfamilies_f END INTERFACE INTERFACE SUBROUTINE cg_family_read_f(fn, B, F, family_name, nboco, ngeos, ier) !BIND(C, NAME="cg_family_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family_name INTEGER :: nboco INTEGER :: ngeos INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_family_read_f END INTERFACE INTERFACE SUBROUTINE cg_family_write_f(fn, B, family_name, F, ier) !BIND(C, NAME="cg_family_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family_name INTEGER :: F INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_family_write_f END INTERFACE INTERFACE SUBROUTINE cg_nfamily_names_f(fn, B, F, nnames, ier) BIND(C, NAME="cg_nfamily_names_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: nnames INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nfamily_names_f END INTERFACE INTERFACE SUBROUTINE cg_family_name_read_f(fn, B, F, N, name, family, ier) !BIND(C, NAME="cg_family_name_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: N CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_family_name_read_f END INTERFACE INTERFACE SUBROUTINE cg_family_name_write_f(fn, B, F, name, family, ier) !BIND(C, NAME="cg_family_name_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_family_name_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write FamBC_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_fambc_read_f(fn, B, F, BC, fambc_name, bocotype, ier) !BIND(C, NAME="cg_fambc_read_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: BC CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fambc_name INTEGER(cgenum_t) :: bocotype INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_fambc_read_f END INTERFACE INTERFACE SUBROUTINE cg_fambc_write_f(fn, B, F, fambc_name, bocotype, BC, ier) !BIND(C, NAME="cg_fambc_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fambc_name INTEGER(cgenum_t) :: bocotype INTEGER :: BC INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_fambc_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GeometryReference_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_geo_read_f(fn, B, F, G, geo_name, geo_file, CAD_name, npart, ier) !BIND(C, NAME="cg_geo_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: G CHARACTER(KIND=C_CHAR), DIMENSION(*) :: geo_name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: geo_file CHARACTER(KIND=C_CHAR), DIMENSION(*) :: CAD_name INTEGER :: npart INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_geo_read_f END INTERFACE INTERFACE SUBROUTINE cg_geo_write_f(fn, B, F, geo_name, geo_file, CAD_name, G, ier) !BIND(C, NAME="cg_geo_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F CHARACTER(KIND=C_CHAR), DIMENSION(*) :: geo_name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: geo_file CHARACTER(KIND=C_CHAR), DIMENSION(*) :: CAD_name INTEGER :: G INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_geo_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GeometryEntity_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_part_read_f(fn, B, F,G, P, part_name, ier) !BIND(C, NAME="cg_part_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: G INTEGER :: P CHARACTER(KIND=C_CHAR), DIMENSION(*) :: part_name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_part_read_f END INTERFACE INTERFACE SUBROUTINE cg_part_write_f(fn, B, F, G, part_name, P, ier) !BIND(C, NAME="cg_part_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: F INTEGER :: G CHARACTER(KIND=C_CHAR), DIMENSION(*) :: part_name INTEGER :: P INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_part_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write DiscreteData_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_ndiscrete_f(fn, B, Z, ndiscrete, ier) BIND(C, NAME="cg_ndiscrete_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: ndiscrete INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ndiscrete_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_read_f(fn, B, Z, D, discrete_name, ier) !BIND(C, NAME="cg_discrete_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: D CHARACTER(KIND=C_CHAR), DIMENSION(*) :: discrete_name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_read_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_write_f(fn, B, Z, discrete_name, D, ier) !BIND(C, NAME="cg_discrete_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: discrete_name INTEGER :: D INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_write_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_size_f(fn, B, Z, D, ndim, dims, ier) BIND(C, NAME="cg_discrete_size_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: D INTEGER :: ndim INTEGER(CGSIZE_T), DIMENSION(*) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_size_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_ptset_info_f(fn, B, Z, S, ptype, npnts, ier) BIND(C, NAME="cg_discrete_ptset_info_f") IMPORT :: cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(cgenum_t) :: ptype INTEGER(CGSIZE_T) :: npnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_ptset_info_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_ptset_read_f( fn, B, Z, S, pnts, ier) BIND(C, NAME="cg_discrete_ptset_read_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(CGSIZE_T) :: pnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_ptset_read_f END INTERFACE INTERFACE SUBROUTINE cg_discrete_ptset_write_f( fn, B, Z, name, location, ptype, npnts, pnts, D, ier) !BIND(C, NAME="cg_discrete_ptset_write_f") IMPORT :: CGSIZE_T, cgenum_t, c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptype INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T) :: pnts INTEGER :: D INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_discrete_ptset_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridCoordinates_t/DataArray_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_ncoords_f(fn, B, Z, ncoords, ier) BIND(C, NAME="cg_ncoords_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: ncoords INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ncoords_f END INTERFACE INTERFACE SUBROUTINE cg_coord_info_f(fn, B, Z, C, TYPE, coordname, ier) !BIND(C, NAME="cg_coord_info_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: C INTEGER(cgenum_t) :: TYPE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_coord_info_f END INTERFACE #if HAVE_FORTRAN_2008 INTERFACE cg_coord_read_f SUBROUTINE cg_coord_read_c_double (fn, B, Z, coordname, TYPE, rmin, rmax, coord, ier) !BIND(C, NAME="cg_coord_read_c_double") IMPORT :: c_char, cgenum_t, CGSIZE_T, c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname INTEGER(cgenum_t) :: TYPE INTEGER(CGSIZE_T) :: rmin INTEGER(CGSIZE_T) :: rmax REAL(C_DOUBLE), DIMENSION(*) :: coord INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_coord_read_c_double SUBROUTINE cg_coord_read_c_float (fn, B, Z, coordname, TYPE, rmin, rmax, coord, ier) !BIND(C, NAME="cg_coord_read_c_float") IMPORT :: c_char, cgenum_t, CGSIZE_T, c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname INTEGER(cgenum_t) :: TYPE INTEGER(CGSIZE_T) :: rmin INTEGER(CGSIZE_T) :: rmax REAL(C_FLOAT), DIMENSION(*) :: coord INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_coord_read_c_float SUBROUTINE cg_coord_read_f03 (fn, B, Z, coordname, TYPE, rmin, rmax, coord, ier) BIND(C, NAME="cg_coord_read_f03") IMPORT :: c_char, cgenum_t, CGSIZE_T, c_ptr IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname INTEGER(cgenum_t) :: TYPE INTEGER(CGSIZE_T) :: rmin INTEGER(CGSIZE_T) :: rmax TYPE(C_PTR), VALUE :: coord INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_coord_read_f03 END INTERFACE #endif INTERFACE SUBROUTINE cg_coord_id_f(fn, B, Z, C, coord_id, ier) BIND(C, NAME="cg_coord_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: C REAL(C_DOUBLE) :: coord_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_coord_id_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_coord_write_f(fn, B, Z, TYPE, coordname, coord, C, ier) BIND(C, NAME="") !!$ IMPORT :: c_char, cgenum_t, c_ptr !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER(cgenum_t) :: TYPE !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname !!$ TYPE(C_PTR), VALUE :: coord !!$ INTEGER :: C !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_coord_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_coord_partial_write_f( fn, B, Z, TYPE, coordname, rmin, rmax, coord, C, ier) BIND(C, NAME="") !!$ IMPORT :: c_char, cgenum_t, CGSIZE_T, c_ptr !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER(cgenum_t) :: TYPE !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: coordname !!$ INTEGER(CGSIZE_T) :: rmin !!$ INTEGER(CGSIZE_T) :: rmax !!$ TYPE(C_PTR) :: coord !!$ INTEGER :: C !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_coord_partial_write_f !!$ END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write Elements_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nsections_f(fn, B, Z, nsections, ier) BIND(C, NAME="cg_nsections_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nsections INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nsections_f END INTERFACE INTERFACE SUBROUTINE cg_section_read_f(fn, B, Z, E, section_name, TYPE, start, END, nbndry, parent_flag, ier) !BIND(C, NAME="cg_section_read_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: E CHARACTER(KIND=C_CHAR), DIMENSION(*) :: section_name INTEGER(cgenum_t) :: TYPE INTEGER(CGSIZE_T) ::start INTEGER(CGSIZE_T) ::END INTEGER :: nbndry INTEGER :: parent_flag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_section_read_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_elements_read_f(fn, B, Z, E, elements, parent_data, ier) BIND(C, NAME="cg_elements_read_f") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: E !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: elements !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: parent_data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_elements_read_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_elementdatasize_f(fn, B, Z, E, ElementDataSize, ier) BIND(C, NAME="cg_elementdatasize_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: E INTEGER(CGSIZE_T) :: ElementDataSize INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_elementdatasize_f END INTERFACE INTERFACE SUBROUTINE cg_elementpartialsize_f(fn, B, Z, E, start, END, ElementDataSize, ier) BIND(C, NAME="cg_elementpartialsize_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: E INTEGER(CGSIZE_T) :: start INTEGER(CGSIZE_T) :: END INTEGER(CGSIZE_T) :: ElementDataSize INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_elementpartialsize_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_section_write_f(fn, B, Z, section_name, TYPE, start, END, nbndry, elements, S, ier) !BIND(C, NAME="cg_section_write_f") !!$ IMPORT :: c_char, cgenum_t, CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: section_name !!$ INTEGER(cgenum_t) :: TYPE !!$ INTEGER(CGSIZE_T) :: start !!$ INTEGER(CGSIZE_T) :: END !!$ INTEGER :: nbndry !!$ INTEGER(CGSIZE_T), DIMENSION() :: elements !!$ INTEGER :: S !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_section_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_parent_data_write_f(fn, B, Z, S, parent_data, ier) BIND(C, NAME="cg_parent_data_write_f") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: parent_data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_parent_data_write_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_section_partial_write_f( fn, B, Z, section_name, TYPE, start, END, nbndry, S, ier) !BIND(C, NAME="cg_section_partial_write_f") IMPORT :: c_char, CGSIZE_T, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: section_name INTEGER(cgenum_t) ::TYPE INTEGER(CGSIZE_T) ::start INTEGER(CGSIZE_T) ::END INTEGER :: nbndry INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_section_partial_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_elements_partial_write_f(fn, B, Z, S, rmin, rmax, elements, ier) & !!$ BIND(C, NAME="cg_elements_partial_write_f") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S !!$ INTEGER(CGSIZE_T) :: rmin !!$ INTEGER(CGSIZE_T) :: rmax !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: elements !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_elements_partial_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_parent_data_partial_write_f(fn, B, Z, S, rmin, rmax, parent_data, ier) & !!$ BIND(C, NAME="cg_parent_data_partial_write_f") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S !!$ INTEGER(CGSIZE_T) :: rmin !!$ INTEGER(CGSIZE_T) :: rmax !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: parent_data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_parent_data_partial_write_f !!$ END INTERFACE !!$ !!$ INTERFACE !!$ SUBROUTINE cg_elements_partial_read_f(fn, B, Z, S, rmin, rmax, elements, parent, ier) & !!$ BIND(C, NAME="cg_elements_partial_read_f") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S !!$ INTEGER(CGSIZE_T) ::rmin !!$ INTEGER(CGSIZE_T) ::rmax !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: elements !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: parent !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_elements_partial_read_f !!$ END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write FlowSolution_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nsols_f(fn, B, Z, nsols, ier) BIND(C, NAME="cg_nsols_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nsols INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nsols_f END INTERFACE INTERFACE SUBROUTINE cg_sol_info_f(fn, B, Z, S, solname, location, ier) !BIND(C, NAME="cg_sol_info_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S CHARACTER(KIND=C_CHAR), DIMENSION(*) :: solname INTEGER(cgenum_t) :: location INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_info_f END INTERFACE INTERFACE SUBROUTINE cg_sol_id_f(fn, B, Z, S, sol_id, ier) BIND(C, NAME="cg_sol_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S REAL(C_DOUBLE) :: sol_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_id_f END INTERFACE INTERFACE SUBROUTINE cg_sol_write_f(fn, B, Z, solname, location, S, ier) !BIND(C, NAME="cg_sol_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: solname INTEGER(cgenum_t) :: location INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_write_f END INTERFACE INTERFACE SUBROUTINE cg_sol_size_f(fn, B, Z, S, ndim, dims, ier) BIND(C, NAME="cg_sol_size_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER :: ndim INTEGER(CGSIZE_T), DIMENSION(*) :: dims INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_size_f END INTERFACE INTERFACE SUBROUTINE cg_sol_ptset_info_f( fn, B, Z, S, ptype, npnts, ier) BIND(C, NAME="cg_sol_ptset_info_f") IMPORT :: cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(cgenum_t) :: ptype INTEGER(CGSIZE_T) :: npnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_ptset_info_f END INTERFACE INTERFACE SUBROUTINE cg_sol_ptset_read_f(fn, B, Z, S, pnts, ier) BIND(C, NAME="cg_sol_ptset_read_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(CGSIZE_T) ::pnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_ptset_read_f END INTERFACE INTERFACE SUBROUTINE cg_sol_ptset_write_f(fn, B, Z, name, location, ptype, npnts, pnts, S, ier) !BIND(C, NAME="cg_sol_ptset_write_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptype INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T) :: pnts INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_sol_ptset_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write solution DataArray_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nfields_f(fn, B, Z, S, nfields, ier) BIND(C, NAME="cg_nfields_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER :: nfields INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nfields_f END INTERFACE INTERFACE SUBROUTINE cg_field_info_f(fn, B, Z, S, F, TYPE, fieldname, ier) !BIND(C, NAME="cg_field_info_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER :: F INTEGER(cgenum_t) :: TYPE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_field_info_f END INTERFACE !!$INTERFACE !!$ SUBROUTINE cg_field_read_f(fn, B, Z, S, fieldname), TYPE, rmin, rmax, field_ptr, ier) BIND(C, NAME="") !!$ INTEGER :: fn !!$ INTEGER :: B, !!$ INTEGER :: Z !!$ INTEGER :: S, CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldname), INTEGER(cgenum_t) :: TYPE !!$ INTEGER(CGSIZE_T) ::rmin, !!$ INTEGER(CGSIZE_T) ::rmax !!$ void *field_ptr, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_field_read_f !!$END INTERFACE INTERFACE SUBROUTINE cg_field_id_f(fn, B, Z, S, F, field_id, ier) !BIND(C, NAME="cg_field_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER :: F REAL(C_DOUBLE) :: field_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_field_id_f END INTERFACE !!$INTERFACE !!$ SUBROUTINE cg_field_write_f(fn, B, Z, S, TYPE, fieldname, field_ptr, F, ier) BIND(C, NAME="") !!$ INTEGER :: fn !!$ INTEGER :: B, !!$ INTEGER :: Z !!$ INTEGER :: S !!$ INTEGER(cgenum_t) :: TYPE !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldname !!$ void *field_ptr, !!$ INTEGER :: F !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_field_write_f !!$END INTERFACE !!$INTERFACE !!$ SUBROUTINE cg_field_partial_write_f) (fn, B, Z, S, TYPE, fieldname, rmin, rmax, void *field_ptr, F, ier) BIND(C, NAME="") !!$ INTEGER :: fn, !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S, INTEGER(cgenum_t) :: TYPE !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldname !!$ INTEGER(CGSIZE_T) :: rmin !!$ INTEGER(CGSIZE_T) :: rmax !!$ void *field_ptr !!$ INTEGER :: F !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_field_partial_write_f !!$END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write ZoneSubRegion_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nsubregs_f(fn, B, Z, nsubreg, ier) BIND(C, NAME="cg_nsubregs_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nsubreg INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nsubregs_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_info_f(fn, B, Z, S, regname, DIMENSION, & location, ptset_type, npnts, bcname_len, gcname_len, ier) !BIND(C, NAME="cg_subreg_info_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S CHARACTER(KIND=C_CHAR), DIMENSION(*) :: regname INTEGER :: DIMENSION INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) ::npnts INTEGER :: bcname_len INTEGER :: gcname_len INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_info_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_ptset_read_f( fn, B, Z, S, pnts, ier) BIND(C, NAME="cg_subreg_ptset_read_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_ptset_read_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_bcname_read_f( fn, B, Z, S, bcname, ier) !BIND(C, NAME="cg_subreg_bcname_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S CHARACTER(KIND=C_CHAR), DIMENSION(*) :: bcname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_bcname_read_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_gcname_read_f(fn, B, Z, S, gcname, ier) !BIND(C, NAME="cg_subreg_gcname_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S CHARACTER(KIND=C_CHAR), DIMENSION(*) :: gcname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_gcname_read_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_ptset_write_f(fn, B, Z, regname, DIMENSION, location, ptset_type, npnts, pnts, S, ier) !BIND(C, NAME="cg_subreg_ptset_write_f") IMPORT :: cgenum_t, c_char, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: regname INTEGER :: DIMENSION INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_ptset_write_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_bcname_write_f( fn, B, Z, regname, DIMENSION, bcname, S, ier) !BIND(C, NAME="cg_subreg_bcname_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: regname INTEGER :: DIMENSION CHARACTER(KIND=C_CHAR), DIMENSION(*) :: bcname INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_bcname_write_f END INTERFACE INTERFACE SUBROUTINE cg_subreg_gcname_write_f( fn, B, Z, regname, DIMENSION, gcname, S, ier) !BIND(C, NAME="cg_subreg_gcname_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: regname INTEGER :: DIMENSION CHARACTER(KIND=C_CHAR), DIMENSION(*) :: gcname INTEGER :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_subreg_gcname_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write ZoneGridConnectivity_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nzconns_f(fn, B, Z, nzconns, ier) BIND(C, NAME="cg_nzconns_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nzconns INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nzconns_f END INTERFACE INTERFACE SUBROUTINE cg_zconn_read_f(fn, B, Z, C, name, ier) !BIND(C, NAME="cg_zconn_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: C CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zconn_read_f END INTERFACE INTERFACE SUBROUTINE cg_zconn_write_f(fn, B, Z, name, C, ier) !BIND(C, NAME="cg_zconn_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER :: C INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zconn_write_f END INTERFACE INTERFACE SUBROUTINE cg_zconn_get_f(fn, B, Z, C, ier) BIND(C, NAME="cg_zconn_get_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: C INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zconn_get_f END INTERFACE INTERFACE SUBROUTINE cg_zconn_set_f(fn, B, Z, C, ier) BIND(C, NAME="cg_zconn_set_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: C INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_zconn_set_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write OversetHoles_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nholes_f(fn, B, Z, nholes, ier) BIND(C, NAME="cg_nholes_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nholes INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nholes_f END INTERFACE INTERFACE SUBROUTINE cg_hole_info_f(fn, B, Z, I, holename, location, ptset_type, nptsets, npnts, ier) !BIND(C, NAME="cg_hole_info_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I CHARACTER(KIND=C_CHAR), DIMENSION(*) :: holename INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: nptsets INTEGER(CGSIZE_T) :: npnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_hole_info_f END INTERFACE INTERFACE SUBROUTINE cg_hole_read_f(fn, B, Z, I, pnts, ier) BIND(C, NAME="cg_hole_read_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_hole_read_f END INTERFACE INTERFACE SUBROUTINE cg_hole_id_f(fn, B, Z, I, hole_id, ier) BIND(C, NAME="cg_hole_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_DOUBLE) :: hole_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_hole_id_f END INTERFACE INTERFACE SUBROUTINE cg_hole_write_f(fn, B, Z, holename, location, ptset_type, nptsets, npnts, pnts, I, ier) !BIND(C, NAME="cg_hole_write_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: holename INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: ptset_type INTEGER :: nptsets INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER :: I INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_hole_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridConnectivity_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nconns_f(fn, B, Z, nconns, ier) BIND(C, NAME="cg_nconns_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nconns INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nconns_f END INTERFACE INTERFACE SUBROUTINE cg_conn_info_f(fn, B, Z, I, connectname, location, & TYPE, ptset_type, npnts, donorname, donor_zonetype, donor_ptset_type, & donor_datatype, ndata_donor, ier) !BIND(C, NAME="cg_conn_info_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: TYPE INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER(cgenum_t) :: donor_zonetype INTEGER(cgenum_t) :: donor_ptset_type INTEGER(cgenum_t) :: donor_datatype INTEGER(CGSIZE_T) :: ndata_donor INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_info_f END INTERFACE INTERFACE SUBROUTINE cg_conn_read_f(fn, B, Z, I, pnts, donor_datatype, donor_data, ier) BIND(C, NAME="cg_conn_read_f") IMPORT :: cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER(cgenum_t) :: donor_datatype INTEGER(CGSIZE_T), DIMENSION(*) :: donor_data INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_read_f END INTERFACE INTERFACE SUBROUTINE cg_conn_read_short_f(fn, B, Z, I, pnts, ier) BIND(C, NAME="cg_conn_read_short_f") IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(CGSIZE_T) ::pnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_read_short_f END INTERFACE INTERFACE SUBROUTINE cg_conn_id_f(fn, B, Z, I, conn_id, ier) BIND(C, NAME="cg_conn_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_DOUBLE) :: conn_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_id_f END INTERFACE INTERFACE SUBROUTINE cg_conn_write_f(fn, B, Z, connectname, location, TYPE, ptset_type, & npnts, pnts, donorname, donor_zonetype, donor_ptset_type, & donor_datatype, ndata_donor, donor_data, I, ier) !BIND(C, NAME="cg_conn_write_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: TYPE INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T), DIMENSION(*) :: pnts CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER(cgenum_t) :: donor_zonetype INTEGER(cgenum_t) :: donor_ptset_type INTEGER(cgenum_t) :: donor_datatype INTEGER(CGSIZE_T) :: ndata_donor INTEGER(CGSIZE_T), DIMENSION(*) :: donor_data INTEGER :: I INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_write_f END INTERFACE INTERFACE SUBROUTINE cg_conn_write_short_f(fn, B, Z, connectname, location, & TYPE, ptset_type, npnts, pnts, donorname, I, ier) !BIND(C, NAME="cg_conn_write_short_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname INTEGER(cgenum_t) :: location INTEGER(cgenum_t) :: TYPE INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T) :: pnts CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER :: I INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_write_short_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridConnectivity1to1_t Nodes in a zone * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_n1to1_f(fn, B, Z, n1to1, ier) BIND(C, NAME="cg_n1to1_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: n1to1 INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_n1to1_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_read_f(fn, B, Z, I, connectname, donorname, & range, donor_range, transform, ier) !BIND(C, NAME="cg_1to1_read_f") IMPORT :: c_char, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER(CGSIZE_T), DIMENSION(*) :: range INTEGER(CGSIZE_T), DIMENSION(*) :: donor_range INTEGER, DIMENSION(*) :: transform INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_read_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_id_f(fn, B, Z, I, one21_id, ier) !BIND(C, NAME="cg_1to1_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_DOUBLE) :: one21_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_id_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_write_f(fn, B, Z, connectname, donorname, range, & donor_range, transform, I, ier) !BIND(C, NAME="cg_1to1_write_f") IMPORT :: c_char, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER(CGSIZE_T), DIMENSION(*) :: range INTEGER(CGSIZE_T), DIMENSION(*) :: donor_range INTEGER, DIMENSION(*) :: transform INTEGER :: I INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read all GridConnectivity1to1_t Nodes of a base * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_n1to1_global_f(fn, B, n1to1_global, ier) BIND(C, NAME="cg_n1to1_global_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: n1to1_global INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_n1to1_global_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_read_global_f(fn, B, connectname, zonename, donorname, & range, donor_range, transform, ier) !BIND(C, NAME="cg_1to1_read_global_f") IMPORT :: c_char, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B CHARACTER(KIND=C_CHAR), DIMENSION(*) :: connectname CHARACTER(KIND=C_CHAR), DIMENSION(*) :: zonename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: donorname INTEGER(CGSIZE_T), DIMENSION(*) :: range INTEGER(CGSIZE_T), DIMENSION(*) :: donor_range INTEGER, DIMENSION(*) :: transform INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_read_global_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BC_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_nbocos_f(fn, B, Z, nbocos, ier) BIND(C, NAME="cg_nbocos_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: nbocos INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nbocos_f END INTERFACE INTERFACE SUBROUTINE cg_boco_info_f(fn, B, Z, BC, boconame, bocotype, & ptset_type, npnts, NormalIndex, & NormalListSize, NormalDataType, ndataset, ier) !BIND(C, NAME="cg_boco_info_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC CHARACTER(KIND=C_CHAR), DIMENSION(*) :: boconame INTEGER(cgenum_t) :: bocotype INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER, DIMENSION(*) :: NormalIndex INTEGER(CGSIZE_T) :: NormalListSize INTEGER(cgenum_t) :: NormalDataType INTEGER :: ndataset INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_boco_info_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_boco_read_f(fn, B, Z, BC, pnts, NormalList, ier) BIND(C, NAME="") !!$ IMPORT :: CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: BC !!$ INTEGER(CGSIZE_T) :: pnts !!$ void *NormalList !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_boco_read_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_boco_id_f(fn, B, Z, BC, boco_id, ier) BIND(C, NAME="cg_boco_id_f") IMPORT :: c_double IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC REAL(C_DOUBLE) :: boco_id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_boco_id_f END INTERFACE INTERFACE SUBROUTINE cg_boco_write_f(fn, B, Z, boconame, bocotype, ptset_type, npnts, pnts, BC, ier) !BIND(C, NAME="cg_boco_write_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: boconame INTEGER(cgenum_t) :: bocotype INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER(CGSIZE_T), DIMENSION(*) :: pnts INTEGER :: BC INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_boco_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_boco_normal_write_f( fn, B, Z, BC, NormalIndex, NormalListFlag, !!$ NormalDataType, NormalList, ier) BIND(C, NAME="") !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: BC, !!$ INTEGER(CGSIZE_T) ::NormalIndex !!$ INTEGER :: NormalListFlag, !!$ INTEGER(cgenum_t) :: NormalDataType !!$ ! void *NormalList, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_boco_normal_write_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_boco_gridlocation_read_f(fn, B, Z, BC, location, ier) BIND(C, NAME="cg_boco_gridlocation_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: location INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_boco_gridlocation_read_f END INTERFACE INTERFACE SUBROUTINE cg_boco_gridlocation_write_f( fn, B, Z, BC, location, ier) BIND(C, NAME="cg_boco_gridlocation_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: location INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_boco_gridlocation_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BCProperty_t/WallFunction_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_bc_wallfunction_read_f(fn, B, Z, BC, WallFunctionType, ier) BIND(C, NAME="cg_bc_wallfunction_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: WallFunctionType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bc_wallfunction_read_f END INTERFACE INTERFACE SUBROUTINE cg_bc_wallfunction_write_f(fn, B, Z, BC, WallFunctionType, ier) BIND(C, NAME="cg_bc_wallfunction_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: WallFunctionType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bc_wallfunction_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BCProperty_t/Area_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_bc_area_read_f(fn, B, Z, BC, AreaType, SurfaceArea, RegionName, ier) !BIND(C, NAME="cg_bc_area_read_f") IMPORT :: c_char, cgenum_t, c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: AreaType REAL(C_FLOAT) :: SurfaceArea CHARACTER(KIND=C_CHAR), DIMENSION(*) :: RegionName INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bc_area_read_f END INTERFACE INTERFACE SUBROUTINE cg_bc_area_write_f(fn, B, Z, BC, AreaType, SurfaceArea, RegionName, ier) !BIND(C, NAME="cg_bc_area_write_f") IMPORT :: c_char, cgenum_t, c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER(cgenum_t) :: AreaType REAL(C_FLOAT) :: SurfaceArea CHARACTER(KIND=C_CHAR), DIMENSION(*) :: RegionName INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bc_area_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridConnectivityProperty_t/Periodic_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_conn_periodic_read_f(fn, B, Z, I, RotationCenter, RotationAngle, Translation, ier) & BIND(C, NAME="cg_conn_periodic_read_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_FLOAT), DIMENSION(*) :: RotationCenter REAL(C_FLOAT), DIMENSION(*) :: RotationAngle REAL(C_FLOAT), DIMENSION(*) :: Translation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_periodic_read_f END INTERFACE INTERFACE SUBROUTINE cg_conn_periodic_write_f( fn, B, Z, I, RotationCenter, RotationAngle, Translation, ier) & BIND(C, NAME="cg_conn_periodic_write_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_FLOAT), DIMENSION(*) :: RotationCenter REAL(C_FLOAT), DIMENSION(*) :: RotationAngle REAL(C_FLOAT), DIMENSION(*) :: Translation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_periodic_write_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_periodic_read_f(fn, B, Z, I, RotationCenter, RotationAngle, Translation, ier) & BIND(C, NAME="cg_1to1_periodic_read_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_FLOAT), DIMENSION(*) :: RotationCenter REAL(C_FLOAT), DIMENSION(*) :: RotationAngle REAL(C_FLOAT), DIMENSION(*) :: Translation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_periodic_read_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_periodic_write_f(fn, B, Z, I, RotationCenter, RotationAngle, Translation, ier) & BIND(C, NAME="cg_1to1_periodic_write_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I REAL(C_FLOAT), DIMENSION(*) :: RotationCenter REAL(C_FLOAT), DIMENSION(*) :: RotationAngle REAL(C_FLOAT), DIMENSION(*) :: Translation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_periodic_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridConnectivityProperty_t/AverageInterface_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_conn_average_read_f(fn, B, Z, I, AverageInterfaceType, ier) & BIND(C, NAME="cg_conn_average_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(cgenum_t) :: AverageInterfaceType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_average_read_f END INTERFACE INTERFACE SUBROUTINE cg_conn_average_write_f(fn, B, Z, I, AverageInterfaceType, ier) & BIND(C, NAME="cg_conn_average_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(cgenum_t) :: AverageInterfaceType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conn_average_write_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_average_read_f(fn, B, Z, I, AverageInterfaceType, ier) & BIND(C, NAME="cg_1to1_average_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(cgenum_t) :: AverageInterfaceType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_average_read_f END INTERFACE INTERFACE SUBROUTINE cg_1to1_average_write_f(fn, B, Z, I,AverageInterfaceType, ier) BIND(C, NAME="cg_1to1_average_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: I INTEGER(cgenum_t) :: AverageInterfaceType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_1to1_average_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BCDataSet_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_dataset_read_f(fn, B, Z, BC, DSet, Dataset_name, BCType, DirichletFlag, & NeumannFlag, ier) !BIND(C, NAME="cg_dataset_read_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER :: DSet CHARACTER(KIND=C_CHAR), DIMENSION(*) :: Dataset_name INTEGER(cgenum_t) :: BCType INTEGER :: DirichletFlag INTEGER :: NeumannFlag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_dataset_read_f END INTERFACE INTERFACE SUBROUTINE cg_dataset_write_f(fn, B, Z, BC, Dataset_name,BCType, Dset, ier) !BIND(C, NAME="cg_dataset_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC CHARACTER(KIND=C_CHAR), DIMENSION(*) :: Dataset_name INTEGER(cgenum_t) :: BCType INTEGER :: Dset INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_dataset_write_f END INTERFACE INTERFACE SUBROUTINE cg_bcdataset_write_f(Dataset_name, BCType, BCDataType, ier) !BIND(C, NAME="cg_bcdataset_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: Dataset_name INTEGER(cgenum_t) :: BCType INTEGER(cgenum_t) :: BCDataType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bcdataset_write_f END INTERFACE INTERFACE SUBROUTINE cg_bcdataset_info_f(ndataset, ier) BIND(C, NAME="cg_bcdataset_info_f") IMPLICIT NONE INTEGER :: ndataset INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bcdataset_info_f END INTERFACE INTERFACE SUBROUTINE cg_bcdataset_read_f(index, Dataset_name, BCType, & DirichletFlag, NeumannFlag,ier) !BIND(C, NAME="cg_bcdataset_read_f") IMPORT :: c_char, cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER ::index CHARACTER(KIND=C_CHAR), DIMENSION(*) :: Dataset_name INTEGER(cgenum_t) :: BCType INTEGER :: DirichletFlag INTEGER :: NeumannFlag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bcdataset_read_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BCData_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_bcdata_write_f(fn, B, Z, BC, Dset, BCDataType, ier) BIND(C, NAME="cg_bcdata_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: BC INTEGER :: Dset INTEGER(cgenum_t) :: BCDataType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_bcdata_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write RigidGridMotion_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_n_rigid_motions_f(fn, B, Z, n_rigid_motions, ier) BIND(C, NAME="cg_n_rigid_motions_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: n_rigid_motions INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_n_rigid_motions_f END INTERFACE INTERFACE SUBROUTINE cg_rigid_motion_read_f(fn, B, Z, R, rmotion_name, TYPE, ier) !BIND(C, NAME="cg_rigid_motion_read_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: R CHARACTER(KIND=C_CHAR), DIMENSION(*) :: rmotion_name INTEGER(cgenum_t) :: TYPE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rigid_motion_read_f END INTERFACE INTERFACE SUBROUTINE cg_rigid_motion_write_f(fn, B, Z, rmotion_name, TYPE, R, ier) !BIND(C, NAME="cg_rigid_motion_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: rmotion_name INTEGER(cgenum_t) :: TYPE INTEGER :: R INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rigid_motion_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write ArbitraryGridMotion_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_n_arbitrary_motions_f( fn, B, Z, n_arbitrary_motions, ier) BIND(C, NAME="cg_n_arbitrary_motions_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: n_arbitrary_motions INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_n_arbitrary_motions_f END INTERFACE INTERFACE SUBROUTINE cg_arbitrary_motion_read_f(fn, B, Z, A, amotion_name, TYPE, ier) !BIND(C, NAME="cg_arbitrary_motion_read_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: A CHARACTER(KIND=C_CHAR), DIMENSION(*) :: amotion_name INTEGER(cgenum_t) :: TYPE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_arbitrary_motion_read_f END INTERFACE INTERFACE SUBROUTINE cg_arbitrary_motion_write_f(fn, B, Z, amotion_name, TYPE, A, ier) !BIND(C, NAME="cg_arbitrary_motion_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: amotion_name INTEGER(cgenum_t) :: TYPE INTEGER :: A INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_arbitrary_motion_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write GridCoordinates_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_ngrids_f(fn, B, Z, ngrids, ier) BIND(C, NAME="cg_ngrids_f") IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: ngrids INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ngrids_f END INTERFACE INTERFACE SUBROUTINE cg_grid_read_f(fn, B, Z, G, gridname, ier) ! BIND(C, NAME="cg_grid_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: G CHARACTER(KIND=C_CHAR), DIMENSION(*) :: gridname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_grid_read_f END INTERFACE INTERFACE SUBROUTINE cg_grid_write_f(fn, B, Z, gridname, G, ier) !BIND(C, NAME="cg_grid_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: gridname INTEGER :: G INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_grid_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write SimulationType_t Node * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_simulation_type_read_f(fn, B, TYPE, ier) BIND(C, NAME="cg_simulation_type_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER(cgenum_t) :: TYPE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_simulation_type_read_f END INTERFACE INTERFACE SUBROUTINE cg_simulation_type_write_f(fn, B, TYPE, ier) BIND(C, NAME="cg_simulation_type_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER(cgenum_t) :: TYPE INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_simulation_type_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write BaseIterativeData_t Node * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_biter_read_f(fn, B, bitername, nsteps, ier) !BIND(C, NAME="cg_biter_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B CHARACTER(KIND=C_CHAR), DIMENSION(*) :: bitername INTEGER :: nsteps INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_biter_read_f END INTERFACE INTERFACE SUBROUTINE cg_biter_write_f(fn, B, bitername, nsteps, ier) !BIND(C, NAME="cg_biter_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B CHARACTER(KIND=C_CHAR), DIMENSION(*) :: bitername INTEGER :: nsteps INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_biter_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write ZoneIterativeData_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_ziter_read_f(fn, B, Z, zitername, ier) !BIND(C, NAME="cg_ziter_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: zitername INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ziter_read_f END INTERFACE INTERFACE SUBROUTINE cg_ziter_write_f(fn, B, Z, zitername, ier) !BIND(C, NAME="cg_ziter_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*) :: zitername INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ziter_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write Gravity_t Node * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_gravity_read_f(fn, B, gravity_vector, ier) BIND(C, NAME="cg_gravity_read_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B REAL(C_FLOAT), DIMENSION(*) :: gravity_vector INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_gravity_read_f END INTERFACE INTERFACE SUBROUTINE cg_gravity_write_f(fn, B, gravity_vector, ier) BIND(C, NAME="cg_gravity_write_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B REAL(C_FLOAT), DIMENSION(*) :: gravity_vector INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_gravity_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write Axisymmetry_t Node * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_axisym_read_f(fn, B, ref_point, axis, ier) BIND(C, NAME="cg_axisym_read_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B REAL(C_FLOAT), DIMENSION(*) :: ref_point REAL(C_FLOAT), DIMENSION(*) :: axis INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_axisym_read_f END INTERFACE INTERFACE SUBROUTINE cg_axisym_write_f(fn, B, ref_point, axis, ier) BIND(C, NAME="cg_axisym_write_f") IMPORT :: c_float IMPLICIT NONE INTEGER :: fn INTEGER :: B REAL(C_FLOAT), DIMENSION(*) :: ref_point REAL(C_FLOAT), DIMENSION(*) :: axis INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_axisym_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write RotatingCoordinates_t Node * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_rotating_read_f(rot_rate, rot_center, ier) BIND(C, NAME="cg_rotating_read_f") IMPORT :: c_float IMPLICIT NONE REAL(C_FLOAT), DIMENSION(*) :: rot_rate REAL(C_FLOAT), DIMENSION(*) :: rot_center INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rotating_read_f END INTERFACE INTERFACE SUBROUTINE cg_rotating_write_f(rot_rate, rot_center, ier) BIND(C, NAME="cg_rotating_write_f") IMPORT :: c_float IMPLICIT NONE REAL(C_FLOAT), DIMENSION(*) :: rot_rate REAL(C_FLOAT), DIMENSION(*) :: rot_center INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rotating_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read and write IndexArray/Range_t Nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_ptset_info_f(ptset_type, npnts, ier) BIND(C, NAME="cg_ptset_info_f") IMPORT :: cgenum_t, CGSIZE_T IMPLICIT NONE INTEGER(cgenum_t) :: ptset_type INTEGER(CGSIZE_T) :: npnts INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ptset_info_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_ptset_read_f(pnts, ier) BIND(C, NAME="cg_ptset_read_f") !!$ IMPORT :: cgenum_t, CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: pnts !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_ptset_read_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_ptset_write_f(ptset_type, npnts, pnts, ier) BIND(C, NAME="cg_ptset_write_f") !!$ IMPORT :: cgenum_t, CGSIZE_T !!$ IMPLICIT NONE !!$ INTEGER(cgenum_t) :: ptset_type !!$ INTEGER(CGSIZE_T) :: npnts !!$ INTEGER(CGSIZE_T), DIMENSION() :: pnts !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_ptset_write_f !!$ END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Go - To Function * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ INTERFACE !!$ SUBROUTINE cg_goto_f, CG_GOTO_F)(cgint_f *fn, cgint_f *B, ier, ...) !!$cgint_f *fn, cgint_f *B, ier, ...) !!$ !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ !!$ INTERFACE !!$ SUBROUTINE cg_gorel_f, CG_GOREL_F)(cgint_f *fn, ier, ...) !!$cgint_f *fn, ier, ...) !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE INTERFACE SUBROUTINE cg_gopath_f(fn,path, ier) !BIND(C, NAME="cg_gopath_f") IMPORT :: C_CHAR IMPLICIT NONE INTEGER :: fn CHARACTER(KIND=C_CHAR), DIMENSION(*) :: path INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_gopath_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Read Multiple path nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_famname_read_f(famname, ier) !BIND(C, NAME="cg_famname_read_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: famname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_famname_read_f END INTERFACE INTERFACE SUBROUTINE cg_nmultifam_f(nfam, ier) BIND(C, NAME="cg_nmultifam_f") IMPLICIT NONE INTEGER :: nfam INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nmultifam_f END INTERFACE INTERFACE SUBROUTINE cg_multifam_read_f(N,name, family, ier) !BIND(C, NAME="cg_multifam_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: N CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_multifam_read_f END INTERFACE INTERFACE SUBROUTINE cg_convergence_read_f(iterations, NormDefinitions, ier) !BIND(C, NAME="cg_convergence_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: iterations CHARACTER(KIND=C_CHAR), DIMENSION(*) :: NormDefinitions INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_convergence_read_f END INTERFACE INTERFACE SUBROUTINE cg_state_size_f(size, ier) !BIND(C, NAME="cg_state_size_f") IMPLICIT NONE INTEGER :: size INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_state_size_f END INTERFACE INTERFACE SUBROUTINE cg_state_read_f(StateDescription, ier) !BIND(C, NAME="cg_state_read_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: StateDescription INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_state_read_f END INTERFACE INTERFACE SUBROUTINE cg_equationset_read_f(EquationDimension, GoverningEquationsFlag, & GasModelFlag, ViscosityModelFlag, ThermalConductivityModelFlag, & TurbulenceClosureFlag, TurbulenceModelFlag, ier) BIND(C, NAME="cg_equationset_read_f") IMPLICIT NONE INTEGER :: EquationDimension INTEGER :: GoverningEquationsFlag INTEGER :: GasModelFlag INTEGER :: ViscosityModelFlag INTEGER :: ThermalConductivityModelFlag INTEGER :: TurbulenceClosureFlag INTEGER :: TurbulenceModelFlag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_equationset_read_f END INTERFACE INTERFACE SUBROUTINE cg_equationset_chemistry_read_f(ThermalRelaxationFlag, ChemicalKineticsFlag, ier) & BIND(C, NAME="cg_equationset_chemistry_read_f") IMPLICIT NONE INTEGER :: ThermalRelaxationFlag INTEGER :: ChemicalKineticsFlag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_equationset_chemistry_read_f END INTERFACE INTERFACE SUBROUTINE cg_equationset_elecmagn_read_f(ElecFldModelFlag, MagnFldModelFlag, & ConductivityModelFlag, ier) BIND(C, NAME="cg_equationset_elecmagn_read_f") IMPLICIT NONE INTEGER :: ElecFldModelFlag INTEGER :: MagnFldModelFlag INTEGER :: ConductivityModelFlag INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_equationset_elecmagn_read_f END INTERFACE INTERFACE SUBROUTINE cg_governing_read_f(EquationsType, ier) BIND(C, NAME="cg_governing_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: EquationsType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_governing_read_f END INTERFACE INTERFACE SUBROUTINE cg_diffusion_read_f(diffusion_model, ier) BIND(C, NAME="cg_diffusion_read_f") IMPLICIT NONE INTEGER, DIMENSION(*) :: diffusion_model INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_diffusion_read_f END INTERFACE INTERFACE SUBROUTINE cg_model_read_f(ModelLabel, ModelType, ier) !BIND(C, NAME="cg_model_read_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ModelLabel INTEGER(cgenum_t) :: ModelType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_model_read_f END INTERFACE INTERFACE SUBROUTINE cg_narrays_f(narrays, ier) BIND(C, NAME="cg_narrays_f") IMPLICIT NONE INTEGER :: narrays INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_narrays_f END INTERFACE INTERFACE SUBROUTINE cg_array_info_f(A, ArrayName, DataType, DataDimension, DimensionVector, ier) !BIND(C, NAME="cg_array_info_f") IMPORT :: c_char, CGSIZE_T, cgenum_t IMPLICIT NONE INTEGER :: A CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ArrayName INTEGER(cgenum_t) :: DataType INTEGER :: DataDimension INTEGER(CGSIZE_T), DIMENSION(*) :: DimensionVector INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_array_info_f END INTERFACE !$ INTERFACE !!$ SUBROUTINE cg_array_read_f(A, DATA, ier) BIND(C, NAME="") !!$ INTEGER :: A, !!$ void *DATA, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_array_read_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_array_read_as_f(A, TYPE, DATA, ier) BIND(C, NAME="") !!$ IMPORT :: cgenum_t !!$ IMPLICIT NONE !!$ INTEGER :: A !!$ INTEGER(cgenum_t) :: TYPE !!$ void *DATA !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_array_read_as_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_nintegrals_f(nintegrals, ier) BIND(C, NAME="cg_nintegrals_f") IMPLICIT NONE INTEGER :: nintegrals INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nintegrals_f END INTERFACE INTERFACE SUBROUTINE cg_integral_read_f(IntegralDataIndex, IntegralDataName,ier) !BIND(C, NAME="cg_integral_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: IntegralDataIndex CHARACTER(KIND=C_CHAR), DIMENSION(*) :: IntegralDataName INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_integral_read_f END INTERFACE INTERFACE SUBROUTINE cg_rind_read_f(RindData, ier) BIND(C, NAME="cg_rind_read_f") IMPLICIT NONE INTEGER, DIMENSION(*) :: RindData INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rind_read_f END INTERFACE INTERFACE SUBROUTINE cg_ndescriptors_f(ndescriptors, ier) BIND(C, NAME="cg_ndescriptors_f") IMPLICIT NONE INTEGER :: ndescriptors INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ndescriptors_f END INTERFACE INTERFACE SUBROUTINE cg_descriptor_size_f(descr_no, descr_size, ier) BIND(C, NAME="cg_descriptor_size_f") IMPLICIT NONE INTEGER :: descr_no INTEGER :: descr_size INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_descriptor_size_f END INTERFACE INTERFACE SUBROUTINE cg_descriptor_read_f(descr_no, descr_name, descr_text, ier) !BIND(C, NAME="cg_descriptor_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: descr_no CHARACTER(KIND=C_CHAR), DIMENSION(*) :: descr_name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: descr_text INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_descriptor_read_f END INTERFACE INTERFACE SUBROUTINE cg_nunits_f(nunits, ier) BIND(C, NAME="cg_nunits_f") IMPLICIT NONE INTEGER :: nunits INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nunits_f END INTERFACE INTERFACE SUBROUTINE cg_units_read_f(mass, length, time, temperature, angle, ier) BIND(C, NAME="cg_units_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: mass INTEGER(cgenum_t) :: length INTEGER(cgenum_t) :: time INTEGER(cgenum_t) :: temperature INTEGER(cgenum_t) :: angle INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_units_read_f END INTERFACE INTERFACE SUBROUTINE cg_unitsfull_read_f(mass, length, time, temperature, angle, current, & amount, intensity, ier) BIND(C, NAME="cg_unitsfull_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: mass INTEGER(cgenum_t) :: length INTEGER(cgenum_t) :: time INTEGER(cgenum_t) :: temperature INTEGER(cgenum_t) :: angle INTEGER(cgenum_t) :: current INTEGER(cgenum_t) :: amount INTEGER(cgenum_t) :: intensity INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_unitsfull_read_f END INTERFACE INTERFACE SUBROUTINE cg_exponents_info_f(DataType, ier) BIND(C, NAME="cg_exponents_info_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: DataType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_exponents_info_f END INTERFACE INTERFACE SUBROUTINE cg_nexponents_f(nexps, ier) BIND(C, NAME="cg_nexponents_f") IMPLICIT NONE INTEGER :: nexps INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nexponents_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_exponents_read_f(void *exponents, ier) BIND(C, NAME="") !!$ void *exponents !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_exponents_read_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_expfull_read_f(exponents, ier) BIND(C, NAME="") !!$ void *exponents, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_expfull_read_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_conversion_info_f(DataType, ier) BIND(C, NAME="cg_conversion_info_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: DataType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_conversion_info_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_conversion_read_f(ConversionFactors, ier) BIND(C, NAME="") !!$ void *ConversionFactors, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_conversion_read_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_dataclass_read_f(dataclass, ier) BIND(C, NAME="cg_dataclass_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: dataclass INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_dataclass_read_f END INTERFACE INTERFACE SUBROUTINE cg_gridlocation_read_f(GridLocation, ier) BIND(C, NAME="cg_gridlocation_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: GridLocation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_gridlocation_read_f END INTERFACE INTERFACE SUBROUTINE cg_ordinal_read_f(Ordinal, ier) BIND(C, NAME="cg_ordinal_read_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER :: Ordinal INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ordinal_read_f END INTERFACE INTERFACE SUBROUTINE cg_npe_f(TYPE,npe, ier) BIND(C, NAME="cg_npe_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: TYPE INTEGER :: npe INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_npe_f END INTERFACE INTERFACE SUBROUTINE cg_is_link_f(path_length, ier) BIND(C, NAME="cg_is_link_f") IMPLICIT NONE INTEGER :: path_length INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_is_link_f END INTERFACE INTERFACE SUBROUTINE cg_link_read_f(filename, link_path, ier) !BIND(C, NAME="cg_link_read_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: filename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: link_path INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_link_read_f END INTERFACE INTERFACE SUBROUTINE cg_nuser_data_f(nuser_data, ier) BIND(C, NAME="cg_nuser_data_f") IMPLICIT NONE INTEGER :: nuser_data INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_nuser_data_f END INTERFACE INTERFACE SUBROUTINE cg_user_data_read_f(index,dataname, ier) !BIND(C, NAME="cg_user_data_read_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: index CHARACTER(KIND=C_CHAR), DIMENSION(*) :: dataname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_user_data_read_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Write Multiple path nodes * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_famname_write_f(family_name, ier) !BIND(C, NAME="cg_famname_write_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family_name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_famname_write_f END INTERFACE INTERFACE SUBROUTINE cg_multifam_write_f(name, family, ier) !BIND(C, NAME="cg_multifam_write_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: family INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_multifam_write_f END INTERFACE INTERFACE SUBROUTINE cg_convergence_write_f(iterations, NormDefinitions, ier) !BIND(C, NAME="cg_convergence_write_f") IMPORT :: c_char IMPLICIT NONE INTEGER :: iterations CHARACTER(KIND=C_CHAR), DIMENSION(*) :: NormDefinitions INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_convergence_write_f END INTERFACE INTERFACE SUBROUTINE cg_state_write_f(StateDescription, ier) !BIND(C, NAME="cg_state_write_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: StateDescription INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_state_write_f END INTERFACE INTERFACE SUBROUTINE cg_equationset_write_f(EquationDimension, ier) BIND(C, NAME="cg_equationset_write_f") IMPLICIT NONE INTEGER :: EquationDimension INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_equationset_write_f END INTERFACE INTERFACE SUBROUTINE cg_governing_write_f(Equationstype, ier) BIND(C, NAME="cg_governing_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: Equationstype INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_governing_write_f END INTERFACE INTERFACE SUBROUTINE cg_diffusion_write_f(diffusion_model, ier) BIND(C, NAME="cg_diffusion_write_f") IMPLICIT NONE INTEGER, DIMENSION(*) :: diffusion_model INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_diffusion_write_f END INTERFACE INTERFACE SUBROUTINE cg_model_write_f(ModelLabel, ModelType, ier) !BIND(C, NAME="cg_model_write_f") IMPORT :: c_char, cgenum_t IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ModelLabel INTEGER(cgenum_t) :: ModelType INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_model_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_array_write_f(ArrayName, DataType, DataDimension, DimensionVector, & !!$ void *Data, ier) BIND(C, NAME="") !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ArrayName !!$ INTEGER(cgenum_t) :: DataType !!$ INTEGER :: DataDimension !!$ INTEGER(CGSIZE_T) :: DimensionVector !!$ void *DATA !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_array_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_array_write_f03(ArrayName, DataType, DataDimension, DimensionVector, DATA, ier) & !!$ BIND(C, NAME="cg_array_write_f03") !!$ IMPORT :: c_char, cgenum_t, cgsize_t, c_ptr !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ArrayName !!$ INTEGER(cgenum_t) :: DataType !!$ INTEGER :: DataDimension !!$ INTEGER(cgsize_t), DIMENSION(*) :: DimensionVector !!$ TYPE(C_PTR), VALUE :: Data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_array_write_f03 !!$ END INTERFACE INTERFACE SUBROUTINE cg_integral_write_f(IntegralDataName, ier) !BIND(C, NAME="cg_integral_write_f") IMPORT :: c_char CHARACTER(KIND=C_CHAR), DIMENSION(*) :: IntegralDataName INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_integral_write_f END INTERFACE INTERFACE SUBROUTINE cg_rind_write_f(RindData, ier) BIND(C, NAME="cg_rind_write_f") IMPLICIT NONE INTEGER, DIMENSION(*) :: RindData INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_rind_write_f END INTERFACE INTERFACE SUBROUTINE cg_descriptor_write_f(descr_name, descr_text, ier) !BIND(C, NAME="cg_descriptor_write_f") IMPORT :: c_char CHARACTER(KIND=C_CHAR), DIMENSION(*) :: descr_name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: descr_text INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_descriptor_write_f END INTERFACE INTERFACE SUBROUTINE cg_units_write_f(mass, length, time, temperature, angle, ier) BIND(C, NAME="cg_units_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: mass INTEGER(cgenum_t) :: length INTEGER(cgenum_t) :: time INTEGER(cgenum_t) :: temperature INTEGER(cgenum_t) :: angle INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_units_write_f END INTERFACE INTERFACE SUBROUTINE cg_unitsfull_write_f(mass, length, time, temperature, angle, current, & amount, intensity, ier) BIND(C, NAME="cg_unitsfull_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: mass INTEGER(cgenum_t) :: length INTEGER(cgenum_t) :: time INTEGER(cgenum_t) :: temperature INTEGER(cgenum_t) :: angle INTEGER(cgenum_t) :: current INTEGER(cgenum_t) :: amount INTEGER(cgenum_t) :: intensity INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_unitsfull_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_exponents_write_f(DataType, void *exponents, ier) BIND(C, NAME="") !!$ !!$ INTEGER(cgenum_t) :: DataType_t)*DataType, void *exponents, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_exponents_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_expfull_write_f(DataType, void *exponents, ier) BIND(C, NAME="") !!$ INTEGER(cgenum_t) :: DataType !!$ void *exponents, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_expfull_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cg_conversion_write_f( DataType, ConversionFactors, ier) BIND(C, NAME="") !!$ INTEGER(cgenum_t) :: DataType !!$ void *ConversionFactors !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cg_conversion_write_f !!$ END INTERFACE INTERFACE SUBROUTINE cg_dataclass_write_f(dataclass, ier) BIND(C, NAME="cg_dataclass_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: dataclass INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_dataclass_write_f END INTERFACE INTERFACE SUBROUTINE cg_gridlocation_write_f(GridLocation, ier) BIND(C, NAME="cg_gridlocation_write_f") IMPORT :: cgenum_t IMPLICIT NONE INTEGER(cgenum_t) :: GridLocation INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_gridlocation_write_f END INTERFACE INTERFACE SUBROUTINE cg_ordinal_write_f(Ordinal, ier) BIND(C, NAME="cg_ordinal_write_f") IMPLICIT NONE INTEGER :: Ordinal INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_ordinal_write_f END INTERFACE INTERFACE SUBROUTINE cg_link_write_f(nodename, filename, name_in_file, ier) !BIND(C, NAME="cg_link_write_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: nodename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: filename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name_in_file INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_link_write_f END INTERFACE INTERFACE SUBROUTINE cg_user_data_write_f(dataname, ier) ! BIND(C, NAME="cg_user_data_write_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: dataname INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_user_data_write_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! General Delete Function * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_delete_node_f(node_name, ier) !BIND(C, NAME="cg_delete_node_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: node_name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_delete_node_f END INTERFACE ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ ! Error Handling Functions * ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ INTERFACE SUBROUTINE cg_get_error_f(errmsg) !BIND(C, NAME="cg_get_error_f") IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: errmsg END SUBROUTINE cg_get_error_f END INTERFACE INTERFACE SUBROUTINE cg_error_exit_f() BIND(C, NAME="cg_error_exit_f") IMPLICIT NONE END SUBROUTINE cg_error_exit_f END INTERFACE INTERFACE SUBROUTINE cg_error_print_f() BIND(C, NAME="cg_error_print_f") IMPLICIT NONE END SUBROUTINE cg_error_print_f END INTERFACE INTERFACE SUBROUTINE cg_exit_on_error_f(flag) BIND(C, NAME="cg_exit_on_error_f") IMPLICIT NONE INTEGER :: flag END SUBROUTINE cg_exit_on_error_f END INTERFACE #ifdef BUILD_PARALLEL !====================================================================== ! parallel IO interface !====================================================================== INTERFACE SUBROUTINE cgp_mpi_comm_f( mpi_comm_f, ier) BIND(C, NAME="cgp_mpi_comm_f") IMPLICIT NONE INTEGER :: mpi_comm_f INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_mpi_comm_f END INTERFACE INTERFACE SUBROUTINE cgp_pio_mode_f( mode, ier) BIND(C, NAME="cgp_pio_mode_f") IMPORT :: C_INT IMPLICIT NONE INTEGER(C_INT) :: mode INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_pio_mode_f END INTERFACE INTERFACE SUBROUTINE cgp_open_f(filename, mode, fn, ier) !BIND(C, NAME="cgp_open_f") IMPORT :: C_CHAR, C_INT IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: filename INTEGER(C_INT) :: mode INTEGER :: fn INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_open_f END INTERFACE INTERFACE SUBROUTINE cgp_close_f(fn, ier) BIND(C, NAME="cgp_close_f") IMPLICIT NONE INTEGER, INTENT(IN) :: fn INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_close_f END INTERFACE INTERFACE SUBROUTINE cgp_coord_write_f(fn, B, Z, type, coordname, C, ier) !BIND(C, NAME="cgp_coord_write_f") IMPORT :: cgenum_t, c_char IMPLICIT NONE INTEGER, INTENT(IN) :: fn INTEGER, INTENT(IN) :: B INTEGER, INTENT(IN) :: Z INTEGER(cgenum_t), INTENT(IN) :: type CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: coordname INTEGER, INTENT(IN) :: C INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_coord_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_coord_write_data_f(fn, B, Z, C, !!$ CGSIZE_T *rmin, CGSIZE_T *rmax, void *data, ier) BIND(C, NAME="") !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: C, !!$ INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, void *DATA, !!$ INTEGER, INTENT(OUT) :: ier !!$END SUBROUTINE cgp_coord_write_data_f !!$END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_coord_read_data_f( !!$ fn, B, Z, C, !!$ CGSIZE_T *rmin, CGSIZE_T *rmax, void *data, ier) BIND(C, NAME="") !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: C, !!$ INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, void *data, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE INTERFACE SUBROUTINE cgp_section_write_f( fn, B, Z, section_name, & TYPE,start,END, nbndry, S, ier) !BIND(C, NAME="cgp_section_write_f") IMPORT :: cgenum_t, cgsize_t, c_char IMPLICIT NONE INTEGER, INTENT(IN) :: fn INTEGER, INTENT(IN) :: B INTEGER, INTENT(IN) :: Z CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: section_name INTEGER(cgenum_t) :: TYPE INTEGER(CGSIZE_T), INTENT(IN) :: start INTEGER(CGSIZE_T), INTENT(IN) :: END INTEGER, INTENT(IN) :: nbndry INTEGER, INTENT(IN) :: S INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_section_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_elements_write_data_f( fn, B, Z, S, CGSIZE_T *start, & !!$ CGSIZE_T *END, CGSIZE_T *elements, ier) BIND(C, NAME="cgp_elements_write_data_f") !!$ IMPORT :: cgsize_t !!$ IMPLICIT NONE !!$ IMPLICIT NONE !!$ INTEGER, INTENT(IN) :: fn !!$ INTEGER, INTENT(IN) :: B !!$ INTEGER, INTENT(IN) :: Z !!$ INTEGER, INTENT(IN) :: S !!$ INTEGER(CGSIZE_T), INTENT(IN) :: start !!$ INTEGER(CGSIZE_T), INTENT(IN) :: end !!$ INTEGER(CGSIZE_T) , INTENT(IN) :: elements !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgp_elements_write_data_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_elements_read_data_f(fn, B, Z, S, start, & !!$ end, elements, ier) BIND(C, NAME="cgp_elements_read_data_f") !!$ IMPORT :: cgsize_t !!$ IMPLICIT NONE !!$ INTEGER, INTENT(IN) :: fn !!$ INTEGER, INTENT(IN) :: B !!$ INTEGER, INTENT(IN) :: Z !!$ INTEGER, INTENT(IN) :: S !!$ INTEGER(CGSIZE_T), INTENT(IN) :: start !!$ INTEGER(CGSIZE_T), INTENT(IN) :: end !!$ INTEGER(CGSIZE_T) :: elements !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgp_elements_read_data_f !!$ END INTERFACE INTERFACE SUBROUTINE cgp_field_write_f(fn, B, Z, S, TYPE, fieldname, F, ier)! BIND(C, NAME="cgp_field_write_f") IMPORT :: cgenum_t, c_char IMPLICIT NONE INTEGER :: fn INTEGER :: B INTEGER :: Z INTEGER :: S INTEGER(cgenum_t) :: type CHARACTER(KIND=C_CHAR), DIMENSION(*) :: fieldname INTEGER :: F INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_field_write_f END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_field_read_data_f( fn, B, Z, S, F, rmin, rmax, void *field_ptr, !!$ ier) BIND(C, NAME="") !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S, !!$ INTEGER :: F, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, void *field_ptr !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_array_write_f(ArrayName, DataType, DataDimension, DimensionVector, A, ier) !BIND(C, NAME="cgp_array_write_f") !!$ IMPORT :: cgenum_t, cgsize_t, c_char !!$ IMPLICIT NONE !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: ArrayName !!$ INTEGER(cgenum_t) :: DataType !!$ INTEGER :: DataDimension !!$ INTEGER(CGSIZE_T) :: DimensionVector !!$ INTEGER :: A !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgp_array_write_f !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_array_write_data_f( !!$ A, CGSIZE_T *rmin, CGSIZE_T *rmax, void *data, !!$ ier) BIND(C, NAME="") !!$ INTEGER :: A, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, void *data, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ INTERFACE !!$ SUBROUTINE cgp_array_read_data_f( !!$ A, CGSIZE_T *rmin, CGSIZE_T *rmax, void *data, !!$ ier) BIND(C, NAME="") !!$ INTEGER :: A, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, void *data, !!$ !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE INTERFACE SUBROUTINE cgp_error_exit_f() BIND(C, NAME="cgp_error_exit_f") IMPLICIT NONE END SUBROUTINE cgp_error_exit_f END INTERFACE INTERFACE SUBROUTINE cgp_mpi_info_f(pcg_mpi_info_f, ier) BIND(C,NAME='cgp_mpi_info_f') IMPORT :: C_INT IMPLICIT NONE INTEGER(C_INT), INTENT(IN) :: pcg_mpi_info_f INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgp_mpi_info_f END INTERFACE !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_coord_multi_read_data_f, CGP_COORD_MULTI_READ_DATA_F)(fn, B, Z, C, !!$ CGSIZE_T *rmin, CGSIZE_T *rmax, !!$ void *coordsX, void *coordsY, void *coordsZ, ier) BIND(C, NAME="") !!$INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: C, !!$ INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, !!$ void *coordsX, void *coordsY, void *coordsZ, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ !!$ !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ !!$! cgp_coord_multi_write_data Function * !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_coord_multi_write_data_f, CGP_COORD_MULTI_WRITE_DATA_F)(fn, B, Z, C, !!$ CGSIZE_T *rmin, CGSIZE_T *rmax, !!$ void *coordsX, void *coordsY, void *coordsZ, ier) BIND(C, NAME="") !!$INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: C, !!$ INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, !!$ void *coordsX, void *coordsY, void *coordsZ !!$ !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ !!$! cgp_field_multi_write_data Function * !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_field_multi_write_data_f( !!$ fn, B, Z, S, !!$ F, CGSIZE_T *rmin, CGSIZE_T *rmax, ier, CGSIZE_T *nsets, ...) !!$ fn, B, Z, S, !!$ F, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, ier, INTEGER(CGSIZE_T) :: nsets, ... !!$ !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ !!$! cgp_field_multi_read_data Function * !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_field_multi_read_data_f( !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S, !!$ F, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, ier, nsets, ...) !!$ !!$ INTEGER :: fn !!$ INTEGER :: B !!$ INTEGER :: Z !!$ INTEGER :: S, !!$ INTEGER :: F, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, ier !!$ INTEGER :: nsets, ... !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ !!$! cgp_array_multi_write_data Function * !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_array_multi_write_data_f( !!$ fn, A, CGSIZE_T *rmin, CGSIZE_T *rmax, !!$ ier, nsets, ...) !!$ INTEGER :: fn !!$ INTEGER :: A, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, !!$ ier !!$ INTEGER :: nsets, ... !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ !!$ !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ !!$! cgp_array_multi_read_data Function * !!$! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ !!$ !!$ INTERFACE !!$ SUBROUTINE cgp_array_multi_read_data_f( !!$ fn, A, CGSIZE_T *rmin, CGSIZE_T *rmax, !!$ ier, nsets, ...) !!$ !!$ INTEGER :: fn !!$ INTEGER :: A, INTEGER(CGSIZE_T) :: rmin, INTEGER(CGSIZE_T) :: rmax, !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE !!$ END INTERFACE !!$ !!$#endif HDF5_HAVE_MULTI_DATASETS #endif !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* INTERFACES FOR THE C FUNCTIONS * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_open(filename, mode, fn) BIND(C, name='cgp_open') !!$ IMPORT :: c_int, c_char !!$ IMPLICIT NONE !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: filename !!$ INTEGER(C_INT), INTENT(IN), VALUE :: mode !!$ INTEGER(C_INT), INTENT(OUT) :: fn !!$ END FUNCTION cgp_open !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_pio_mode(mode) BIND(C, name='cgp_pio_mode') !!$ USE ISO_C_BINDING !!$ INTEGER(KIND(CGP_COLLECTIVE)), INTENT(IN), VALUE :: mode !!$ END FUNCTION cgp_pio_mode !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_base_write(fn, basename, cell_dim, phys_dim, B) BIND(C, name='cg_base_write') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: basename !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: cell_dim !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: phys_dim !!$ INTEGER(C_INT) , INTENT(OUT) :: B !!$ END FUNCTION cg_base_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_zone_write(fn, B, zonename, nijk, itype, Z) BIND(C, name='cg_zone_write') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: zonename !!$ INTEGER(CGSIZE_T), DIMENSION(*), INTENT(IN) :: nijk !!$ INTEGER(KIND(CGP_COLLECTIVE)), INTENT(IN), VALUE :: itype !!$ INTEGER(C_INT) , INTENT(OUT) :: Z !!$ END FUNCTION cg_zone_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_base_read(fn, B, basename, cell_dim, phys_dim) BIND(C, name='cg_base_read') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(OUT) :: basename !!$ INTEGER(C_INT) , INTENT(OUT) :: cell_dim !!$ INTEGER(C_INT) , INTENT(OUT) :: phys_dim !!$ END FUNCTION cg_base_read !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_zone_read(fn, B, Z, zonename, nijk) !BIND(C, name='cg_zone_read') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(OUT) :: zonename !!$ INTEGER(CGSIZE_T), DIMENSION(*), INTENT(OUT) :: nijk !!$ END FUNCTION cg_zone_read !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_coord_write(fn, B, Z, itype, coordname, C) BIND(C, name='cgp_coord_write') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(KIND(CGP_INDEPENDENT)), INTENT(IN), VALUE :: itype !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: coordname !!$ INTEGER(C_INT) , INTENT(OUT) :: C !!$ END FUNCTION cgp_coord_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_coord_write_data(fn, B, Z, C, rmin, rmax, coords) BIND(C, name='cgp_coord_write_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: C !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: coords !!$ END FUNCTION cgp_coord_write_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_field_write(fn, B, Z, S, itype, fieldname, F) BIND(C, name='cgp_field_write') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: S !!$ INTEGER(KIND(CGP_INDEPENDENT)), INTENT(IN), VALUE :: itype !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: fieldname !!$ INTEGER(C_INT) , INTENT(OUT) :: F !!$ END FUNCTION cgp_field_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_field_write_data(fn, B, Z, S, F, rmin, rmax, data) BIND(C, name='cgp_field_write_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: S !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: F !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: data !!$ END FUNCTION cgp_field_write_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_field_read_data(fn, B, Z, S, F, rmin, rmax, data) BIND(C, name='cgp_field_read_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: S !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: F !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: data !!$ END FUNCTION cgp_field_read_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_coord_read_data(fn, B, Z, C, rmin, rmax, coords) BIND(C, name='cgp_coord_read_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: C !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: coords !!$ END FUNCTION cgp_coord_read_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_section_write(fn,B,Z,sectionname,itype,start,end,nbndry,S) BIND(C, name='cgp_section_write') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: sectionname !!$ INTEGER(KIND(CGP_INDEPENDENT)), INTENT(IN), VALUE :: itype !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: start !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: end !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: nbndry !!$ INTEGER(C_INT) , INTENT(OUT) :: S !!$ END FUNCTION cgp_section_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_array_write(arrayname,itype,DataDimension,DimensionVector,A) BIND(C, name='cgp_array_write') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: arrayname !!$ INTEGER(KIND(CGP_INDEPENDENT)), INTENT(IN), VALUE :: itype !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: DataDimension !!$ INTEGER(CGSIZE_T), DIMENSION(1:DataDimension), INTENT(IN) :: DimensionVector !!$ INTEGER(C_INT) , INTENT(OUT) :: A !!$ END FUNCTION cgp_array_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_array_write_data(A, rmin, rmax, data) BIND(C, name='cgp_array_write_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: A !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: data !!$ END FUNCTION cgp_array_write_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_elements_write_data(fn,B,Z,S,emin,emax,elements) BIND(C, name='cgp_elements_write_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: S !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: emin !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: emax !!$ TYPE(C_PTR), VALUE :: elements !!$ END FUNCTION cgp_elements_write_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_elements_read_data(fn,B,Z,S,start,end,elements) BIND(C, name='cgp_elements_read_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: S !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: start !!$ INTEGER(CGSIZE_T), INTENT(IN), VALUE :: end !!$ TYPE(C_PTR), VALUE :: elements !!$ END FUNCTION cgp_elements_read_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_array_read_data(A, rmin, rmax, data) BIND(C, name='cgp_array_read_data') !!$ USE ISO_C_BINDING !!$ IMPORT :: CGSIZE_T !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: A !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmin !!$ INTEGER(CGSIZE_T), INTENT(IN) :: rmax !!$ TYPE(C_PTR), VALUE :: data !!$ END FUNCTION cgp_array_read_data !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_sol_write(fn,B,Z,solname,location,S) BIND(C, name='cg_sol_write') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: fn !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: B !!$ INTEGER(C_INT) , INTENT(IN), VALUE :: Z !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: solname !!$ INTEGER(KIND(CGP_INDEPENDENT)), INTENT(IN), VALUE :: location !!$ INTEGER(C_INT) , INTENT(OUT) :: S !!$ END FUNCTION cg_sol_write !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_error_exit() BIND(C, name='cgp_error_exit') !!$ USE ISO_C_BINDING !!$ END FUNCTION cgp_error_exit !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_close(fn) BIND(C, name='cgp_close') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT), INTENT(IN), VALUE :: fn !!$ END FUNCTION cgp_close !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_queue_set(use_queue) BIND(C, name='cgp_queue_set') !!$ USE ISO_C_BINDING !!$ INTEGER(C_INT), INTENT(IN), VALUE :: use_queue !!$ END FUNCTION cgp_queue_set !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cgp_queue_flush() BIND(C, name='cgp_queue_flush') !!$ USE ISO_C_BINDING !!$ END FUNCTION cgp_queue_flush !!$ END INTERFACE !!$ !!$ INTERFACE !!$ INTEGER(C_INT) FUNCTION cg_user_data_write(UserDataName) BIND(C, name='cg_user_data_write') !!$ USE ISO_C_BINDING !!$ CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN) :: UserDataName !!$ END FUNCTION cg_user_data_write !!$ END INTERFACE #if HAVE_FORTRAN_2008TS ! THE FOLLOWING CODE ONLY WORKS FOR COMPILERS HAVING F2008 STANDARD EXTENSION: ! TS 29113 Further Interoperability of FORTRAN with C WG5/N1942 ! The number of optional parameters should be set to ! CG_MAX_GOTO_DEPTH, which is currently set to 20. INTERFACE INTEGER(C_INT) FUNCTION cg_gorel(fn, & UserDataName1, i1, UserDataName2, i2, & UserDataName3, i3, UserDataName4, i4, & UserDataName5, i5, UserDataName6, i6, & UserDataName7, i7, UserDataName8, i8, & UserDataName9, i9, UserDataName10, i10, & UserDataName11, i11, UserDataName12, i12, & UserDataName13, i13, UserDataName14, i14, & UserDataName15, i15, UserDataName16, i16, & UserDataName17, i17, UserDataName18, i18, & UserDataName19, i19, UserDataName20, i20, & end) BIND(C, name='cg_gorel_f08') USE ISO_C_BINDING INTEGER(C_INT) , INTENT(IN), VALUE :: fn CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN), OPTIONAL :: UserDataName1,UserDataName2, & UserDataName3,UserDataName4,UserDataName5,UserDataName6,UserDataName7,UserDataName8, & UserDataName9,UserDataName10,UserDataName11,UserDataName12,UserDataName13,UserDataName14, & UserDataName15,UserDataName16,UserDataName17,UserDataName18,UserDataName19,UserDataName20 INTEGER(C_INT), INTENT(IN), OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16, & i17, i18, i19, i20 CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN), OPTIONAL :: end END FUNCTION cg_gorel END INTERFACE ! The number of optional parameters should be set to ! CG_MAX_GOTO_DEPTH, which is currently set to 20. INTERFACE INTEGER(C_INT) FUNCTION cg_goto(fn, B, & UserDataName1, i1, UserDataName2, i2, & UserDataName3, i3, UserDataName4, i4, & UserDataName5, i5, UserDataName6, i6, & UserDataName7, i7, UserDataName8, i8, & UserDataName9, i9, UserDataName10, i10, & UserDataName11, i11, UserDataName12, i12, & UserDataName13, i13, UserDataName14, i14, & UserDataName15, i15, UserDataName16, i16, & UserDataName17, i17, UserDataName18, i18, & UserDataName19, i19, UserDataName20, i20, & end) BIND(C, name='cg_goto_f08') USE ISO_C_BINDING INTEGER(C_INT) , INTENT(IN), VALUE :: fn INTEGER(C_INT) , INTENT(IN), VALUE :: B CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN), OPTIONAL :: UserDataName1,UserDataName2, & UserDataName3,UserDataName4,UserDataName5,UserDataName6,UserDataName7,UserDataName8, & UserDataName9,UserDataName10,UserDataName11,UserDataName12,UserDataName13,UserDataName14, & UserDataName15,UserDataName16,UserDataName17,UserDataName18,UserDataName19,UserDataName20 INTEGER(C_INT), INTENT(IN), OPTIONAL :: i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16, & i17, i18, i19, i20 CHARACTER(C_CHAR), DIMENSION(*), INTENT(IN), OPTIONAL :: end END FUNCTION cg_goto END INTERFACE #endif INTERFACE SUBROUTINE cg_open_f(filename, mode, fn, ier) IMPORT :: C_CHAR, C_INT IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER(C_INT), INTENT(IN) :: mode INTEGER, INTENT(OUT) :: fn INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_open_f END INTERFACE INTERFACE SUBROUTINE cg_is_cgns_f(filename, file_type, ier) IMPORT :: C_CHAR IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER, INTENT(OUT) :: file_type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cg_is_cgns_f END INTERFACE INTERFACE cg_get_type MODULE PROCEDURE cg_get_type_c_int MODULE PROCEDURE cg_get_type_c_long_long MODULE PROCEDURE cg_get_type_c_float MODULE PROCEDURE cg_get_type_c_double END INTERFACE !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !* INTERFACES FOR THE CGIO FORTRAN FUNCTIONS * !* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * !*========================================================= !* paths for searching for linked-to files !*========================================================= INTERFACE SUBROUTINE cgio_path_add_f(path, ier) ! BIND(C,NAME='cgio_path_add_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: path INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_path_add_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_path_delete_f(path, ier) ! BIND(C,NAME='cgio_path_delete_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: path INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_path_delete_f END INTERFACE !*========================================================= !* utility routines independent of open files !*========================================================= INTERFACE SUBROUTINE cgio_is_supported_f(file_type, ier) BIND(C,NAME='cgio_is_supported_f') IMPORT :: CGSIZE_T IMPLICIT NONE INTEGER(CGSIZE_T) :: file_type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_is_supported_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_check_file_f(filename, file_type, ier) !BIND(C,NAME='cgio_check_file_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER :: file_type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_check_file_f END INTERFACE !*========================================================= !* file operations !*========================================================= INTERFACE SUBROUTINE cgio_open_file_f(filename, file_mode, file_type, cgio_num, ier) ! BIND(C,NAME='cgio_open_file_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: filename INTEGER :: file_mode INTEGER :: file_type INTEGER :: cgio_num INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_open_file_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_close_file_f(cgio_num, ier) BIND(C,NAME='cgio_close_file_f') IMPLICIT NONE INTEGER :: cgio_num INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_close_file_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_flush_to_disk_f(cgio_num, ier) BIND(C,NAME='cgio_flush_to_disk_f') IMPLICIT NONE INTEGER :: cgio_num INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_flush_to_disk_f END INTERFACE !*========================================================= !* file information !*========================================================= INTERFACE SUBROUTINE cgio_library_version_f(cgio_num, version, ier) ! BIND(C,NAME='cgio_library_version_f') IMPORT :: c_char IMPLICIT NONE INTEGER :: cgio_num CHARACTER(KIND=C_CHAR), DIMENSION(*) :: version INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_library_version_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_file_version_f(cgio_num, file_version, creation_date, modified_date, ier) ! BIND(C,NAME='cgio_file_version_f') IMPORT :: c_char IMPLICIT NONE INTEGER :: cgio_num CHARACTER(KIND=C_CHAR), DIMENSION(*) :: file_version CHARACTER(KIND=C_CHAR), DIMENSION(*) :: creation_date CHARACTER(KIND=C_CHAR), DIMENSION(*) :: modified_date INTEGER, INTENT(OUT) :: ier END SUBROUTINE END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_root_id_f(cgio_num, rootid, ier) BIND(C,NAME='cgio_get_root_id_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(c_double) :: rootid INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_root_id_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_file_type_f(cgio_num, file_type, ier) BIND(C,NAME='cgio_get_file_type_f') IMPLICIT NONE INTEGER :: cgio_num INTEGER :: file_type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_file_type_f END INTERFACE !*========================================================= !* error handling !*========================================================= INTERFACE SUBROUTINE cgio_error_code_f(errcode, file_type) BIND(C,NAME='cgio_error_code_f') IMPLICIT NONE INTEGER :: errcode INTEGER :: file_type END SUBROUTINE cgio_error_code_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_error_message_f(errmsg, ier) ! BIND(C,NAME='cgio_error_message_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: errmsg INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_error_message_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_error_exit_f(errmsg) ! BIND(C,NAME='cgio_error_exit_f') IMPORT :: c_char IMPLICIT NONE CHARACTER(KIND=C_CHAR), DIMENSION(*) :: errmsg END SUBROUTINE cgio_error_exit_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_error_abort_f(abort_flag) BIND(C,NAME='cgio_error_abort_f') IMPLICIT NONE INTEGER :: abort_flag END SUBROUTINE cgio_error_abort_f END INTERFACE !*========================================================= !* basic node operations !*========================================================= INTERFACE SUBROUTINE cgio_create_node_f(cgio_num, pid, name, id, ier) ! BIND(C,NAME='cgio_create_node_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name REAL(C_DOUBLE) :: id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_create_node_f END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_new_node_f(cgio_num, pid, name, label, data_type, ndims, dims, DATA, id, ier) BIND(C,NAME='') !!$ IMPORT :: c_char, c_double !!$ IMPLICIT NONE !!$ INTEGER :: cgio_num !!$ REAL(C_DOUBLE) :: pid !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: label !!$ CHARACTER(KIND=C_CHAR), DIMENSION(*) :: data_type !!$ INTEGER :: ndims !!$ INTEGER(CGSIZE_T), DIMENSION(*) :: dims !!$ TYPE(C_PTR) :: DATA !!$ REAL(C_DOUBLE) :: id !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgio_new_node_f !!$ END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_delete_node_f(cgio_num, pid, id, ier) BIND(C,NAME='cgio_delete_node_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid REAL(C_DOUBLE) :: id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_delete_node_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_move_node_f(cgio_num, pid, id, npid, ier) BIND(C,NAME='cgio_move_node_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid REAL(C_DOUBLE) :: id REAL(C_DOUBLE) :: npid INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_move_node_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_release_id_f(cgio_num, id, ier) BIND(C,NAME='cgio_release_id_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_release_id_f END INTERFACE !*========================================================= !* links !*========================================================= INTERFACE SUBROUTINE cgio_is_link_f(cgio_num, id, link_len, ier) BIND(C,NAME='cgio_is_link_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER :: link_len INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_is_link_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_link_size_f(cgio_num, id, file_len, name_len, ier) BIND(C,NAME='cgio_link_size_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER :: file_len INTEGER :: name_len INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_link_size_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_create_link_f(cgio_num, pid, name, filename, name_in_file, id, ier) ! BIND(C,NAME='cgio_create_link_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name CHARACTER(KIND=C_CHAR), DIMENSION(*) :: filename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name_in_file REAL(C_DOUBLE) :: id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_create_link_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_link_f(cgio_num, id, filename, name_in_file, ier) ! BIND(C,NAME='cgio_get_link_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: filename CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name_in_file INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_link_f END INTERFACE !*========================================================= !* node children !*========================================================= INTERFACE SUBROUTINE cgio_number_children_f(cgio_num, pid, num_children, ier) & BIND(C,NAME='cgio_number_children_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid INTEGER :: num_children INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_number_children_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_children_ids_f(cgio_num, pid, start, max_ret, num_ret, ids, ier) & BIND(C,NAME='cgio_children_ids_f') IMPORT :: c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid INTEGER :: start INTEGER :: max_ret INTEGER :: num_ret REAL(C_DOUBLE) :: ids INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_children_ids_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_children_names_f(cgio_num, pid, start, max_ret, name_len, num_ret, names, ier) !BIND(C,NAME='cgio_children_names_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid INTEGER :: start INTEGER :: max_ret INTEGER :: name_len INTEGER :: num_ret CHARACTER(KIND=C_CHAR), DIMENSION(*) :: names INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_children_names_f END INTERFACE !*========================================================= !* read nodes !*========================================================= INTERFACE SUBROUTINE cgio_get_node_id_f(cgio_num, pid, name, id, ier) !BIND(C,NAME='cgio_get_node_id_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name REAL(C_DOUBLE) :: id INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_node_id_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_name_f(cgio_num, id, name, ier) !BIND(C,NAME='cgio_get_name_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_name_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_label_f(cgio_num, id, label, ier) !BIND(C,NAME='cgio_get_label_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: label INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_label_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_data_type_f(cgio_num, id, data_type, ier) !BIND(C,NAME='cgio_get_data_type_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: data_type INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_data_type_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_get_data_size_f(cgio_num, id, size, ier) BIND(C,NAME='cgio_get_data_size_f') IMPORT :: c_double, cgsize_t IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id INTEGER(CGSIZE_T) :: size INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_get_data_size_f END INTERFACE !*--------------------------------------------------------- !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_read_all_data_f(cgio_num, id, DATA, ier) BIND(C,NAME='') !!$ IMPORT :: c_double, cgsize_t !!$ IMPLICIT NONE !!$ INTEGER :: cgio_num !!$ REAL(C_DOUBLE) :: id !!$ TYPE(C_PTR) :: data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgio_read_all_data_f !!$ END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_read_block_data_f(cgio_num, id, b_start, b_end, DATA, ier) BIND(C,NAME='') !!$ IMPORT :: c_double, cgsize_t, C_PTR !!$ IMPLICIT NONE !!$ INTEGER :: cgio_num !!$ REAL(C_DOUBLE) :: id !!$ INTEGER(CGSIZE_T) :: b_start !!$ INTEGER(CGSIZE_T) :: b_end !!$ TYPE(C_PTR) :: data !!$ INTEGER, INTENT(OUT) :: ier !!$ END SUBROUTINE cgio_read_block_data_f !!$ END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_read_data_f( !!$ cgint_f *cgio_num, double *id, cgsize_t *s_start, cgsize_t *s_end, !!$ cgsize_t *s_stride, cgint_f *m_ndims, cgsize_t *m_dims, cgsize_t *m_start, !!$ cgsize_t *m_end, cgsize_t *m_stride, void *data, cgint_f *ier) BIND(C,NAME='') !!$ END INTERFACE !*========================================================= !* write nodes !*========================================================= INTERFACE SUBROUTINE cgio_set_name_f(cgio_num, pid, id, name, ier) !BIND(C,NAME='cgio_set_name_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: pid REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: name INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_set_name_f END INTERFACE !*--------------------------------------------------------- INTERFACE SUBROUTINE cgio_set_label_f(cgio_num, id, label, ier) !BIND(C,NAME='cgio_set_label_f') IMPORT :: c_char, c_double IMPLICIT NONE INTEGER :: cgio_num REAL(C_DOUBLE) :: id CHARACTER(KIND=C_CHAR), DIMENSION(*) :: label INTEGER, INTENT(OUT) :: ier END SUBROUTINE cgio_set_label_f END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_write_all_data_f( !!$ cgint_f *cgio_num, double *id, void *data, cgint_f *ier) BIND(C,NAME='') !!$ END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_write_block_data_f( !!$ cgint_f *cgio_num, double *id, cgsize_t *b_start, cgsize_t *b_end, !!$ void *data, cgint_f *ier) BIND(C,NAME='') !!$ !!$ END INTERFACE !*--------------------------------------------------------- !!$ INTERFACE !!$ SUBROUTINE cgio_write_data_f( !!$ cgint_f *cgio_num, double *id, cgsize_t *s_start, cgsize_t *s_end, !!$ cgsize_t *s_stride, cgsize_t *m_ndims, cgsize_t *m_dims, cgsize_t *m_start, !!$ cgsize_t *m_end, cgsize_t *m_stride, void *data, cgint_f *ier) BIND(C,NAME='') !!$ !!$ END INTERFACE CONTAINS FUNCTION cg_get_type_c_int(a) USE ISO_C_BINDING INTEGER(C_INT) :: a INTEGER(KIND(CGNS_ENUMV(Integer))) :: cg_get_type_c_int cg_get_type_c_int = CGNS_ENUMV(Integer) END FUNCTION cg_get_type_c_int FUNCTION cg_get_type_c_long_long(a) USE ISO_C_BINDING INTEGER(C_LONG_LONG) :: a INTEGER(KIND(CGNS_ENUMV(Longinteger))) :: cg_get_type_c_long_long cg_get_type_c_long_long = CGNS_ENUMV(LongInteger) END FUNCTION cg_get_type_c_long_long FUNCTION cg_get_type_c_float(a) USE ISO_C_BINDING REAL(C_FLOAT) :: a INTEGER(KIND(CGNS_ENUMV(RealSingle))) :: cg_get_type_c_float cg_get_type_c_float = CGNS_ENUMV(RealSingle) END FUNCTION cg_get_type_c_float FUNCTION cg_get_type_c_double(a) USE ISO_C_BINDING REAL(C_DOUBLE) :: a INTEGER(KIND(CGNS_ENUMV(RealDouble))) :: cg_get_type_c_double cg_get_type_c_double = CGNS_ENUMV(RealDouble) END FUNCTION cg_get_type_c_double ! These have issues when using xlf and the calling ! program does not use the modules, CGNS-25 ! SUBROUTINE cg_is_cgns_f(filename, file_type, ier) BIND(C,NAME='') ! USE ISO_C_BINDING ! IMPLICIT NONE ! CHARACTER(KIND=C_CHAR, LEN=*), INTENT(IN) :: filename ! INTEGER, INTENT(OUT) :: file_type ! INTEGER, INTENT(OUT) :: ier ! ! ier = cg_is_cgns(TRIM(filename)//C_NULL_CHAR, file_type) ! ! END SUBROUTINE cg_is_cgns_f ! ! SUBROUTINE cg_open_f(filename, mode, fn, ier) BIND(C,NAME='') ! USE ISO_C_BINDING ! IMPLICIT NONE ! CHARACTER(KIND=C_CHAR, LEN=*), INTENT(IN) :: filename ! INTEGER(C_INT), INTENT(IN) :: mode ! INTEGER, INTENT(OUT) :: fn ! INTEGER, INTENT(OUT) :: ier ! ! ier = cg_open(TRIM(filename)//C_NULL_CHAR, mode, fn) ! ! END SUBROUTINE cg_open_f END MODULE cgns CGNS-3.4.0/src/cgns_fortrandll.def.in000066400000000000000000000133451343724673500173310ustar00rootroot00000000000000EXPORTS ; CGNS FORTRAN INTERFACES CGNS_mp_cg_version_f CGNS_mp_cg_precision_f CGNS_mp_cg_close_f CGNS_mp_cg_save_as_f CGNS_mp_cg_set_file_type_f CGNS_mp_cg_get_file_type_f CGNS_mp_cg_set_compress_f CGNS_mp_cg_get_compress_f CGNS_mp_cg_set_path_f CGNS_mp_cg_add_path_f CGNS_mp_cg_set_rind_zero_f CGNS_mp_cg_set_rind_core_f CGNS_mp_cg_get_cgio_f CGNS_mp_cg_root_id_f CGNS_mp_cg_nbases_f CGNS_mp_cg_base_read_f CGNS_mp_cg_base_id_f CGNS_mp_cg_base_write_f CGNS_mp_cg_cell_dim_f CGNS_mp_cg_nzones_f CGNS_mp_cg_zone_type_f CGNS_mp_cg_zone_read_f CGNS_mp_cg_zone_id_f CGNS_mp_cg_zone_write_f CGNS_mp_cg_index_dim_f CGNS_mp_cg_nfamilies_f CGNS_mp_cg_family_read_f CGNS_mp_cg_family_write_f CGNS_mp_cg_nfamily_names_f CGNS_mp_cg_family_name_read_f CGNS_mp_cg_family_name_write_f CGNS_mp_cg_fambc_read_f CGNS_mp_cg_fambc_write_f CGNS_mp_cg_geo_read_f CGNS_mp_cg_geo_write_f CGNS_mp_cg_part_read_f CGNS_mp_cg_part_write_f CGNS_mp_cg_ndiscrete_f CGNS_mp_cg_discrete_read_f CGNS_mp_cg_discrete_write_f CGNS_mp_cg_discrete_size_f CGNS_mp_cg_discrete_ptset_info_f CGNS_mp_cg_discrete_ptset_read_f CGNS_mp_cg_discrete_ptset_write_f CGNS_mp_cg_ncoords_f CGNS_mp_cg_coord_info_f CGNS_mp_cg_coord_id_f CGNS_mp_cg_nsections_f CGNS_mp_cg_section_read_f CGNS_mp_cg_elements_read_f CGNS_mp_cg_elementdatasize_f CGNS_mp_cg_elementpartialsize_f CGNS_mp_cg_section_write_f CGNS_mp_cg_parent_data_write_f CGNS_mp_cg_section_partial_write_f CGNS_mp_cg_elements_partial_write_f CGNS_mp_cg_parent_data_partial_write_f CGNS_mp_cg_elements_partial_read_f CGNS_mp_cg_nsols_f CGNS_mp_cg_sol_info_f CGNS_mp_cg_sol_id_f CGNS_mp_cg_sol_write_f CGNS_mp_cg_sol_size_f CGNS_mp_cg_sol_ptset_info_f CGNS_mp_cg_sol_ptset_read_f CGNS_mp_cg_sol_ptset_write_f CGNS_mp_cg_nfields_f CGNS_mp_cg_field_info_f CGNS_mp_cg_field_id_f CGNS_mp_cg_nsubregs_f CGNS_mp_cg_subreg_info_f CGNS_mp_cg_subreg_ptset_read_f CGNS_mp_cg_subreg_bcname_read_f CGNS_mp_cg_subreg_gcname_read_f CGNS_mp_cg_subreg_ptset_write_f CGNS_mp_cg_subreg_bcname_write_f CGNS_mp_cg_subreg_gcname_write_f CGNS_mp_cg_nzconns_f CGNS_mp_cg_zconn_read_f CGNS_mp_cg_zconn_write_f CGNS_mp_cg_zconn_get_f CGNS_mp_cg_zconn_set_f CGNS_mp_cg_nholes_f CGNS_mp_cg_hole_info_f CGNS_mp_cg_hole_read_f CGNS_mp_cg_hole_id_f CGNS_mp_cg_hole_write_f CGNS_mp_cg_nconns_f CGNS_mp_cg_conn_info_f CGNS_mp_cg_conn_read_f CGNS_mp_cg_conn_read_short_f CGNS_mp_cg_conn_id_f CGNS_mp_cg_conn_write_f CGNS_mp_cg_conn_write_short_f CGNS_mp_cg_n1to1_f CGNS_mp_cg_1to1_read_f CGNS_mp_cg_1to1_id_f CGNS_mp_cg_1to1_write_f CGNS_mp_cg_n1to1_global_f CGNS_mp_cg_1to1_read_global_f CGNS_mp_cg_nbocos_f CGNS_mp_cg_boco_info_f CGNS_mp_cg_boco_id_f CGNS_mp_cg_boco_write_f CGNS_mp_cg_boco_gridlocation_read_f CGNS_mp_cg_boco_gridlocation_write_f CGNS_mp_cg_bc_wallfunction_read_f CGNS_mp_cg_bc_wallfunction_write_f CGNS_mp_cg_bc_area_read_f CGNS_mp_cg_bc_area_write_f CGNS_mp_cg_conn_periodic_read_f CGNS_mp_cg_conn_periodic_write_f CGNS_mp_cg_1to1_periodic_read_f CGNS_mp_cg_1to1_periodic_write_f CGNS_mp_cg_conn_average_read_f CGNS_mp_cg_conn_average_write_f CGNS_mp_cg_1to1_average_read_f CGNS_mp_cg_1to1_average_write_f CGNS_mp_cg_dataset_read_f CGNS_mp_cg_dataset_write_f CGNS_mp_cg_bcdataset_write_f CGNS_mp_cg_bcdataset_info_f CGNS_mp_cg_bcdataset_read_f CGNS_mp_cg_bcdata_write_f CGNS_mp_cg_n_rigid_motions_f CGNS_mp_cg_rigid_motion_read_f CGNS_mp_cg_rigid_motion_write_f CGNS_mp_cg_n_arbitrary_motions_f CGNS_mp_cg_arbitrary_motion_read_f CGNS_mp_cg_arbitrary_motion_write_f CGNS_mp_cg_ngrids_f CGNS_mp_cg_grid_read_f CGNS_mp_cg_grid_write_f CGNS_mp_cg_simulation_type_read_f CGNS_mp_cg_simulation_type_write_f CGNS_mp_cg_biter_read_f CGNS_mp_cg_biter_write_f CGNS_mp_cg_ziter_read_f CGNS_mp_cg_ziter_write_f CGNS_mp_cg_gravity_read_f CGNS_mp_cg_gravity_write_f CGNS_mp_cg_axisym_read_f CGNS_mp_cg_axisym_write_f CGNS_mp_cg_rotating_read_f CGNS_mp_cg_rotating_write_f CGNS_mp_cg_ptset_info_f CGNS_mp_cg_ptset_read_f CGNS_mp_cg_ptset_write_f CGNS_mp_cg_gopath_f CGNS_mp_cg_famname_read_f CGNS_mp_cg_nmultifam_f CGNS_mp_cg_multifam_read_f CGNS_mp_cg_convergence_read_f CGNS_mp_cg_state_size_f CGNS_mp_cg_state_read_f CGNS_mp_cg_equationset_read_f CGNS_mp_cg_equationset_chemistry_read_f CGNS_mp_cg_equationset_elecmagn_read_f CGNS_mp_cg_governing_read_f CGNS_mp_cg_diffusion_read_f CGNS_mp_cg_model_read_f CGNS_mp_cg_narrays_f CGNS_mp_cg_array_info_f CGNS_mp_cg_nintegrals_f CGNS_mp_cg_integral_read_f CGNS_mp_cg_rind_read_f CGNS_mp_cg_ndescriptors_f CGNS_mp_cg_descriptor_size_f CGNS_mp_cg_descriptor_read_f CGNS_mp_cg_nunits_f CGNS_mp_cg_units_read_f CGNS_mp_cg_unitsfull_read_f CGNS_mp_cg_exponents_info_f CGNS_mp_cg_nexponents_f CGNS_mp_cg_conversion_info_f CGNS_mp_cg_dataclass_read_f CGNS_mp_cg_gridlocation_read_f CGNS_mp_cg_ordinal_read_f CGNS_mp_cg_npe_f CGNS_mp_cg_is_link_f CGNS_mp_cg_link_read_f CGNS_mp_cg_nuser_data_f CGNS_mp_cg_user_data_read_f CGNS_mp_cg_famname_write_f CGNS_mp_cg_multifam_write_f CGNS_mp_cg_convergence_write_f CGNS_mp_cg_state_write_f CGNS_mp_cg_equationset_write_f CGNS_mp_cg_governing_write_f CGNS_mp_cg_diffusion_write_f CGNS_mp_cg_model_write_f CGNS_mp_cg_integral_write_f CGNS_mp_cg_rind_write_f CGNS_mp_cg_descriptor_write_f CGNS_mp_cg_units_write_f CGNS_mp_cg_unitsfull_write_f CGNS_mp_cg_dataclass_write_f CGNS_mp_cg_gridlocation_write_f CGNS_mp_cg_ordinal_write_f CGNS_mp_cg_link_write_f CGNS_mp_cg_user_data_write_f CGNS_mp_cg_delete_node_f CGNS_mp_cg_get_error_f CGNS_mp_cg_error_exit_f CGNS_mp_cg_error_print_f CGNS_mp_cg_exit_on_error_f CGNS_mp_cgio_set_dimensions_f_0 CGNS_mp_cgio_set_dimensions_f_1 CGNS_mp_cgio_get_dimensions_f_0 CGNS_mp_cgio_get_dimensions_f_1 CGNS_mp_cgp_mpi_comm_f CGNS_mp_cgp_pio_mode_f CGNS_mp_cgp_queue_set_f CGNS_mp_cgp_queue_flush_f CGNS_mp_cgp_open_f CGNS_mp_cgp_close_f CGNS_mp_cgp_coord_write_f CGNS_mp_cgp_section_write_f CGNS_mp_cgp_field_write_f CGNS_mp_cgp_error_exit_f CGNS_mp_cgp_mpi_info_f CGNS-3.4.0/src/cgns_header.h000066400000000000000000002200251343724673500154710ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #ifndef CGNS_HEADER_H #define CGNS_HEADER_H #include /* included for definition of HUGE */ #include "cgnstypes.h" #include "cgns_io.h" typedef char char_33[33]; #ifdef CG_BUILD_BASESCOPE typedef char char_66[66]; /* 32 + '/' + 32 + '\0' */ #else typedef char char_66[33]; /* 32 + '\0' (caller's malloc compat issues) */ #endif typedef char const cchar_33[33]; typedef cgsize_t cgsize6_t[6]; typedef int cgint3_t[3]; #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) #define CGNS_DELETE_SHIFT(nchild, child, func_free) {\ for (n=0; nnchild && strcmp(parent->child[n].name,node_name); n++);\ if (n==parent->nchild) {\ cgi_error("Error in cg_delete: Can't find node '%s'",node_name);\ return 1;\ }\ func_free(&parent->child[n]);\ for (m=n+1; mnchild; m++) parent->child[m-1] = parent->child[m];\ if (--parent->nchild == 0) {\ free(parent->child);\ parent->child=0;\ }\ } #define CGNS_DELETE_CHILD(child, func_free) {\ if (parent->child) {\ func_free(parent->child);\ free(parent->child);\ }\ parent->child = 0;\ } #define ADDRESS4MULTIPLE(parent_type, nchild, child, child_type) {\ parent_type *parent = (parent_type *)posit->posit;\ child = 0;\ if (local_mode == CG_MODE_WRITE) {\ for (n=0; nnchild && strcmp(parent->child[n].name,given_name);n++);\ if (n==parent->nchild) {\ if (parent->nchild==0) parent->child = CGNS_NEW(child_type, 1);\ else parent->child = CGNS_RENEW(child_type,parent->nchild+1, parent->child);\ child = &parent->child[parent->nchild];\ parent->nchild++;\ } else {\ if (cg->mode == CG_MODE_WRITE || allow_dup) error1=1;\ if (cg->mode != CG_MODE_WRITE || allow_dup) {\ parent_id = parent->id;\ child= &(parent->child[n]);\ }\ }\ } else if (local_mode == CG_MODE_READ) {\ if (given_no > parent->nchild || given_no<=0) error2=1;\ else child = &parent->child[given_no-1];\ }\ } #define ADDRESS4SINGLE_ALLOC(parent_type, child) {\ parent_type *parent = (parent_type *)posit->posit;\ child = &parent->child;\ parent_id = parent->id;\ } #define ADDRESS4SINGLE(parent_type, child, child_type, size) {\ parent_type *parent = (parent_type *)posit->posit;\ if (local_mode==CG_MODE_WRITE) {\ if (parent->child==0) parent->child = CGNS_NEW(child_type, size);\ else {\ if (cg->mode == CG_MODE_WRITE) error1=1;\ else parent_id = parent->id;\ }\ }\ child = parent->child;\ } #define NDESCRIPTOR(parent_type) {\ parent_type *parent = (parent_type *)posit->posit;\ (*ndescriptors)= parent->ndescr;\ } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Macros, moved from cgnslib.h * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define CGNS_NEW(type,size) (type *)cgi_malloc((size_t)(size),sizeof(type)) #define CGNS_RENEW(type,size,old) (type *)cgi_realloc(old,(size_t)(size)*sizeof(type)) #define CGNS_FREE(data) free(data); #define INVALID_ENUM(E,EMAX) ((int)(E)<0 || (int)(E)>=(EMAX)) #define DEBUG_FILE 0 #define DEBUG_BASE 0 #define DEBUG_ZONE 0 #define DEBUG_SORT 0 #define DEBUG_ARRAY 0 #define DEBUG_SOL 0 #define DEBUG_HOLE 0 #define DEBUG_CONN 0 #define DEBUG_1TO1 0 #define DEBUG_BOCO 0 #define DEBUG_GOTO 0 #define DEBUG_FTOC 0 #define DEBUG_VERSION 0 #define DEBUG_LINKS 0 #define SKIP_DATA 0 #define READ_DATA 1 /* flag for parallel reading or parallel writing */ typedef enum { CGI_Read, CGI_Write } cgi_rw; /* * Internal Structures: */ /* Note that the link information held in these structs are only needed ** until the CGNS file is written. At that point the ADF link mechanism ** takes over and reading/modifying linked nodes is transparent to this ** API. */ typedef struct { char *filename; /* filename to use for the link; empty if within file */ char *name_in_file; /* path of the node which the link will point to */ } cgns_link; /* V2.1 */ typedef struct { /* Descriptor_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ char *text; /* Copy of Descriptor data */ } cgns_descr; /* CPEX 0033 */ typedef struct { double id; char_33 name; char_66 family; } cgns_famname; typedef struct { /* DimensionalUnits_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int nunits; /* number of units (5 or 8) */ CGNS_ENUMT(MassUnits_t) mass; CGNS_ENUMT(LengthUnits_t) length; CGNS_ENUMT(TimeUnits_t) time; CGNS_ENUMT(TemperatureUnits_t) temperature; CGNS_ENUMT(AngleUnits_t) angle; CGNS_ENUMT(ElectricCurrentUnits_t) current; CGNS_ENUMT(SubstanceAmountUnits_t) amount; CGNS_ENUMT(LuminousIntensityUnits_t) intensity; } cgns_units; typedef struct { /* DimensionalExponents_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ char_33 data_type; /* type of data */ void *data; /* MassExponent, LengthExponent, TimeExponent, TemperatureExponent, AngleExponent */ /* ElecCurrentExponent, MoleExponent, LumIntensityExponent */ int nexps; /* number of exponents written */ } cgns_exponent; typedef struct { /* DataConversion_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ char_33 data_type; /* type of data */ void *data; /* ConversionScale, ConversionOffset */ } cgns_conversion; typedef struct { /* DataArray_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ char_33 data_type; /* type of data */ int data_dim; /* number of dimensions */ cgsize_t dim_vals[12]; /* Size in each dimension */ void *data; /* data */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ cgns_exponent *exponents;/* ptrs to in-memory copy of exponents */ cgns_conversion *convert;/* ptrs to in-memory copy of convert */ cgsize_t range[2]; /* index range for currently stored data*/ } cgns_array; typedef struct { /* IndexArray/Range_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ CGNS_ENUMT(PointSetType_t) type; /* PointList, PointRange, ... */ char_33 data_type; /* type of data */ cgsize_t npts; /* number of points to define the patch */ cgsize_t size_of_patch; /* nr of nodes or elements in patch */ void *data; /* data (only loaded in MODE_MODIFY */ } cgns_ptset; /* when version mismatch) */ typedef struct cgns_user_data_s /* UserDefinedData_t Node */ { char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* No of DataArray_t nodes */ cgns_array *array; /* ptrs to in-mem. copy of Data Arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ CGNS_ENUMT(GridLocation_t) location;/* Grid location where data is recorded */ char_66 family_name; /* Family name */ int ordinal; /* option to specify a rank */ cgns_ptset *ptset; /* PointList, PointRange */ int nuser_data; /* number of user defined data nodes */ struct cgns_user_data_s *user_data; /* User defined data. */ /* CPEX 0034 */ int nfamname; cgns_famname *famname; } cgns_user_data; /* V2.1 */ typedef struct { /* IntegralData_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* number of data arrays */ cgns_array *array; /* ptrs to in-memory copies of data_arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_integral; typedef struct { /* DiscreteData_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_ptset *ptset; /* PointList, PointRange */ CGNS_ENUMT(GridLocation_t) location;/* Grid location where data is recorded*/ int *rind_planes; /* No. of rind-planes on each zone face */ int narrays; /* number of data arrays */ cgns_array *array; /* ptrs to in-memory copies of data_arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_discrete; typedef struct { /* ConvergenceHistory_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int iterations; /* no of iterations */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_descr *NormDefinitions; /* Document the norms */ int narrays; /* number of data arrays */ cgns_array *array; /* ptrs to in-memory copies of data_arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_converg; typedef struct { /* ReferenceState_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_descr *StateDescription;/* ReferenceStateDescription */ int narrays; /* number of data arrays */ cgns_array *array; /* ptrs to in-memory copies of data_arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_state; typedef struct { /* Gravity_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* should be 0 or 1 */ cgns_array *vector; /* ptrs to in-memory copy of GravityVector */ CGNS_ENUMT(DataClass_t)data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_gravity; typedef struct { /* Axisymmetry_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* should be 2, 3 or 4 */ cgns_array *array; /* ptrs to in-memory copy of data arrays*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_axisym; typedef struct { /* RotatingCoordinates_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* should be 2, 3 or 4 */ cgns_array *array; /* ptrs to in-memory copy of data arrays*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_rotating; typedef struct { /* WallFunction_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(WallFunctionType_t) type;/* Type of wall function */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_bcwall; typedef struct { /* Area_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(AreaType_t) type; /* type of area */ int narrays; /* should be 2 */ cgns_array *array; /* ptrs to in-memory copy of data arrays*/ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_bcarea; typedef struct { /* BCProperty_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_bcwall *bcwall; /* ptrs to in-memory copy of bcwall */ cgns_bcarea *bcarea; /* ptrs to in-memory copy of bcarea */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_bprop; typedef struct { /* Periodic_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* should be 3 */ cgns_array *array; /* ptrs to in-memory copy of data arrays*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_cperio; typedef struct { /* AverageInterface_t node */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(AverageInterfaceType_t) type; /* type of interface */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_caverage; typedef struct { /* GridConnectivityProperty_t */ /* V2.2 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_cperio *cperio; /* ptrs to in-memory copy of cperio */ cgns_caverage *caverage;/* ptrs to in-memory copy of caverage */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ } cgns_cprop; typedef struct { /* xxx Model_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ CGNS_ENUMT(ModelType_t) type; int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* No of DataArray_t nodes */ cgns_array *array; /* ptrs to in-mem. copy of Data Arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int *diffusion_model; /* only for turbulence model. */ int dim_vals; /* dim. value for diffusion_model */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_model; typedef struct { /* GoverningEquations_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ CGNS_ENUMT(GoverningEquationsType_t) type; int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int *diffusion_model; int dim_vals; /* dim. value for diffusion_model */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_governing; typedef struct { /* FlowEquationSet_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int equation_dim; /* dimensionality of the governing equations */ cgns_governing *governing; /* ptrs to in-mem. copy of GoverningEquations */ cgns_model *gas; /* ptrs to in-mem. copy of GasModel */ cgns_model *visc; /* ptrs to in-mem. copy of ViscosityM. */ cgns_model *conduct; /* ptrs to in-mem. copy of ThermalCond. */ cgns_model *closure; /* ptrs to in-mem. copy of Turb.Closure */ cgns_model *turbulence; /* ptrs to in-mem. copy of TurbulenceM. */ cgns_model *relaxation; /* ptrs to in-mem. copy of ThermalRelaxation . */ cgns_model *chemkin; /* ptrs to in-mem. copy of ChemicalKinetics. */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* ptrs to in-memory copy of units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ cgns_model *elecfield; /* ptrs to in-mem. copy of EMElecFieldM. */ cgns_model *magnfield; /* ptrs to in-mem. copy of EMMagneticFieldM. */ cgns_model *emconduct; /* ptrs to in-mem. copy of EMConductivityM. */ } cgns_equations; typedef struct { /* BCData_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* no. of global data arrays */ cgns_array *array; /* ptrs to in-mem. copy of local data */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_bcdata; typedef struct { /* BCDataSet_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(BCType_t) type;/* type of boco */ cgns_bcdata *dirichlet; /* ptrs to in-mem. copy of DirichletData*/ cgns_bcdata *neumann; /* ptrs to in-mem. copy of NeumannData */ cgns_state *state; /* ptrs to in-memory copies of Ref.state*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ CGNS_ENUMT(GridLocation_t) location;/* Grid location where data is recorded */ cgns_ptset *ptset; /* PointList, PointRange */ } cgns_dataset; typedef struct { /* Elements_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(ElementType_t) el_type; /* element type */ int el_bound; /* nr of bound. el. if sorted, else 0 */ cgsize_t range[2]; /* index of first and last element */ int *rind_planes; /* No. of rind-elements */ cgns_array *connect; /* ElementConnectivity */ cgns_array *connect_offset; /* ElementStartOffset */ cgns_array *parelem; /* ParentElements */ cgns_array *parface; /* ParentElementsPosition */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_section; typedef struct { /* BC_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(GridLocation_t) location;/* Grid location */ CGNS_ENUMT(BCType_t) type; /* type of boco */ cgns_ptset *ptset; /* PointList, PointRange */ char_66 family_name; /* Family name for the bound. patch */ int *Nindex; /* Inward Normal Index */ double index_id; /* ADF ID number of InwardNormalIndex */ cgns_array *normal; /* Inward Normal List */ int ndataset; /* no of BCDataSet nodes */ cgns_dataset *dataset; /* ptrs to in-mem. copy of BCDataSet */ cgns_bprop *bprop; /* ptrs to in-mem. copy of BCProperty_t */ /* V2.2 */ cgns_state *state; /* ptrs to in-memory copies of Ref.state*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int ordinal; /* option to define a rank */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ /* CPEX 0034 */ int nfamname; cgns_famname *famname; } cgns_boco; typedef struct { /* ZoneBC_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int nbocos; /* number of BC_t nodes */ cgns_boco *boco; /* ptrs to in-memory copies of bocos */ cgns_state *state; /* ptrs to in-memory copies of Ref.state*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_zboco; typedef struct { /* OversetHoles_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(GridLocation_t) location;/* Grid location */ int nptsets; /* Number of point-sets */ cgns_ptset *ptset; /* any no of PointList and/or PointRange*/ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_hole; typedef struct { /* GridConnectivity_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(GridConnectivityType_t) type; /*Overset, Abutting or Abutting1to1*/ CGNS_ENUMT(GridLocation_t) location;/* Grid location */ cgns_ptset ptset; /* PointList or PointRange */ cgns_ptset dptset; /* PointListDonor or CellListDonor */ int narrays; /* should be 0 or 1 */ cgns_array *interpolants;/* InterpolantsDonor */ char_66 donor; /* donor name */ cgns_cprop *cprop; /* ptrs to in-memory copies of cprop */ /* V2.2 */ int ordinal; /* option to specify a rank */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_conn; typedef struct { /* GridConnectivity1to1_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int *transform; /* short form of transformation matrix */ cgns_ptset ptset; /* PointRange */ cgns_ptset dptset; /* PointRangeDonor */ char_66 donor; /* donor name */ int ordinal; /* option to specify a rank */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ cgns_cprop *cprop; /* ptrs to in-memory copies of cprop */ } cgns_1to1; typedef struct { /* ZoneGridConnectivity_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int n1to1; /* number of GridConnectivity1to1 nodes */ cgns_1to1 *one21; /* ptrs to in-memory copies of one21 */ int nconns; /* number of GridConnectivity_t nodes */ cgns_conn *conn; /* ptrs to in-memory copies of conns */ int nholes; /* number of OversetHoles_t nodes */ cgns_hole *hole; /* ptrs to in-memory copies of holes */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_zconn; typedef struct { /* FlowSolution_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ cgns_ptset *ptset; /* PointList, PointRange */ CGNS_ENUMT(GridLocation_t) location;/* Grid location type */ int *rind_planes; /* No. of rind-planes on each zone face */ int nfields; /* number of flow solution arrays */ cgns_array *field; /* ptrs to in-memory copies of sol.field*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_sol; typedef struct { /* GridCoordinates_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int *rind_planes; /* No. of rind-planes on each zone face */ int ncoords; /* number of coordinates arrays */ cgns_array *coord; /* ptrs to in-mem. copy of coord-arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_zcoor; typedef struct { /* RigidGridMotion_t node */ /* V2.0 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(RigidGridMotionType_t) type; /* type of rigid motion */ int narrays; /* no. of data arrays */ cgns_array *array; /* ptrs to in-mem. copy of local data */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_rmotion; typedef struct { /* ArbitraryGridMotion_t node */ /* V2.0 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ CGNS_ENUMT(ArbitraryGridMotionType_t) type;/* type of arbitrary motion */ CGNS_ENUMT(GridLocation_t) location;/* Grid location type */ int *rind_planes; /* No. of rind-planes on each zone face */ int narrays; /* no. of data arrays */ cgns_array *array; /* ptrs to in-mem. copy of misc. arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_amotion; typedef struct { /* ZoneIterativeData_t node */ /* V2.0 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* no. of data arrays */ cgns_array *array; /* ptrs to in-mem. copy of misc. arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_ziter; typedef struct { /* BaseIterativeData_t node */ /* V2.0 */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int nsteps; /* NumberOfSteps */ int narrays; /* no. of data arrays */ cgns_array *array; /* ptrs to in-mem. copy of misc. arrays */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_biter; typedef struct { /* ZoneSubRegion_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int reg_dim; /* nr of indices to specify a node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int narrays; /* no. of data arrays */ cgns_array *array; /* ptrs to in-mem. copy of misc. arrays */ cgns_ptset *ptset; /* PointList, PointRange */ cgns_descr *bcname; /* BC_t node name */ cgns_descr *gcname; /* GridConnectivity node name */ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ CGNS_ENUMT(GridLocation_t) location;/* Grid location where data is recorded */ char_66 family_name; /* Family name */ int *rind_planes; /* No. of rind-planes on each zone face */ int nuser_data; /* number of user defined data nodes */ cgns_user_data *user_data; /* User defined data. */ /* CPEX 0034 */ int nfamname; cgns_famname *famname; } cgns_subreg; typedef struct { /* Zone_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ CGNS_ENUMT(ZoneType_t) type; /* Structured or Unstructured */ int index_dim; /* nr of indices to specify a node */ cgsize_t *nijk; /* size of zone in vertex and cells */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int nzcoor; /* no of GridCoordinates_t nodes */ /* V2.0 */ cgns_zcoor *zcoor; /* ptrs to in-memory copies of coords */ int nsections; /* no of Elements_t nodes */ cgns_section *section; /* ptrs to in-memory copies of section */ char_66 family_name; /* family name of the unstr. zone */ int nsols; /* number of FlowSolution_t nodes */ cgns_sol *sol; /* ptrs to in-memory copies of sols */ int ndiscrete; /* number of DiscreteData_t nodes */ cgns_discrete *discrete;/* ptrs to in-memory copy of discrete */ int nintegrals; /* number of IntegralData_t nodes */ cgns_integral *integral;/* ptrs to in-memory copy of integral */ /* version 3.2 - multiple ZoneGridConnectivity_t */ int active_zconn; /* currently active zconn */ int nzconn; /* no of ZoneGridConnectivity_t nodes */ cgns_zconn *zconn; /* ptrs to in-mem. copy of ZoneGridConn.*/ cgns_zboco *zboco; /* ptrs to in-memory copies of ZoneBC */ cgns_state *state; /* ptrs to in-memory copies of Ref.state*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ cgns_equations *equations;/* ptrs to in-mem. copy of FlowEqu. */ cgns_converg *converg; /* ptrs to in-mem. copy of Conv.Hist. */ int ordinal; /* option to assign a rank */ int nrmotions; /* number of RigidGridMotion_t nodes */ /* V2.0 */ cgns_rmotion *rmotion; /* ptrs to in-mem. copy of RigidGridMot.*/ /* V2.0 */ int namotions; /* number of ArbitraryGridMotion_t nodes*/ /* V2.0 */ cgns_amotion *amotion; /* ptrs to in-mem. copy of Arb.GridMot. */ /* V2.0 */ cgns_ziter *ziter; /* ptrs to in-mem. copies of ZoneIter. */ /* V2.0 */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ cgns_rotating *rotating;/* ptrs to in-memory copy of Rot. Coord.*/ /* V2.2 */ /* version 3.2 */ int nsubreg; /* num subregions */ cgns_subreg *subreg; /* subregion ptrs */ /* CPEX 0034 */ int nfamname; cgns_famname *famname; } cgns_zone; typedef struct { /* */ char_33 name; /* name of Geometry part */ double id; /* ADF ID */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ } cgns_part; typedef struct { /* GeometryReference_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ char *file; /* name of geometry file */ char_33 format; /* name of geometry format */ int npart; /* number of geo. entities */ cgns_part *part; /* list of geometry entities */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ } cgns_geo; typedef struct { /* FamilyBC_t node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ CGNS_ENUMT(BCType_t) type;/* type of boco */ int ndataset; /* no of BCDataSet nodes */ cgns_dataset *dataset; /* ptrs to in-mem. copy of BCDataSet */ } cgns_fambc; typedef struct { /* Family_t node */ char_33 name; /* Family name & name of ADF node */ double id; /* ADF ID number (address) of node */ cgns_link *link; /* link information */ /* V2.1 */ int in_link; /* set if child of a linked node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int nfambc; /* number of FamilyBC_t nodes */ cgns_fambc *fambc; /* FamilyBC */ int ngeos; /* no of GeometryReference_t nodes */ cgns_geo *geo; /* Geometry reference */ int ordinal; /* option to assign a rank */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ cgns_rotating *rotating;/* ptrs to in-memory copy of Rot. Coord.*/ /* CPEX 0033 */ int nfamname; cgns_famname *famname; } cgns_family; typedef struct { /* CGNSBase_t Node */ char_33 name; /* name of ADF node */ double id; /* ADF ID number (address) of node */ int cell_dim; /* highest cell dimension */ int phys_dim; /* nr of coordinates to specify a node */ int ndescr; /* no of Descriptor_t nodes */ cgns_descr *descr; /* ptrs to in-memory copy of descr */ int nzones; /* number of zones in base */ cgns_zone *zone; /* ptrs to in-memory copies of zones */ int nfamilies; /* number of families */ cgns_family *family; /* ptrs to in-memory copies of families */ cgns_state *state; /* ptrs to in-memory copies of Ref.state*/ CGNS_ENUMT(DataClass_t) data_class; /* Class of data */ cgns_units *units; /* Dimensional Units */ cgns_equations *equations; /* ptrs to in-mem. copy of FlowEqu. */ cgns_converg *converg; /* ptrs to in-mem. copy of Conv.Hist. */ int nintegrals; /* no of IntegralData_t nodes */ cgns_integral *integral;/* ptrs to in-mem. copy of integral data*/ cgns_biter *biter; /* ptrs to in-mem. copy of BaseIter. */ /* V2.0 */ CGNS_ENUMT(SimulationType_t) type; /* Simulation type */ /* V2.0 */ double type_id; /* ADF ID number of SimulationType_t */ /* V2.0 */ int nuser_data; /* number of user defined data nodes */ /* V2.1 */ cgns_user_data *user_data; /* User defined data. */ /* V2.1 */ cgns_gravity *gravity; /* ptrs to in-memory copy of gravity */ /* V2.2 */ cgns_axisym *axisym; /* ptrs to in-memory copy of Axisymmetry*/ /* V2.2 */ cgns_rotating *rotating;/* ptrs to in-memory copy of Rot. Coord.*/ /* V2.2 */ } cgns_base; typedef struct { char *filename; /* name of file */ int filetype; /* type of file */ int version; /* version of the CGNS file * 1000 */ int cgio; /* index of I/O control */ double rootid; /* root ID of file */ int mode; /* reading or writing */ int file_number; /* external identifier */ int deleted; /* number of deleted nodes */ int added; /* number of added nodes */ char_33 dtb_version; /* ADF Database Version */ char_33 creation_date; /* creation date of the file */ char_33 modify_date; /* last modification date of the file */ char_33 adf_lib_version;/* ADF Library Version */ int nbases; /* number of bases in the file */ cgns_base *base; /* ptrs to in-memory copies of bases */ } cgns_file; typedef struct { void *posit; char label[33]; int index; double id; } cgns_posit; /* need some of these routines exported for CGNStools */ #if defined(_WIN32) && defined(BUILD_DLL) # define CGNSDLL __declspec(dllexport) #else # define CGNSDLL #endif #ifdef __cplusplus extern "C" { #endif /* * Extern variables */ extern cgns_file *cgns_files; extern cgns_file *cg; /* current file */ extern int n_cgns_files; extern int file_number_offset; extern int CGNSLibVersion; /* CGNSLib Version number */ /* goto stuff */ extern cgns_posit *posit; extern int posit_file, posit_base, posit_zone; extern int posit_depth; extern cgns_posit posit_stack[CG_MAX_GOTO_DEPTH+1]; /* * Internal Functions */ CGNSDLL void *cgi_malloc(size_t cnt,size_t size); CGNSDLL void *cgi_realloc(void *old,size_t bytes); /* retrieve addresses of nodes who may have children */ CGNSDLL cgns_file *cgi_get_file (int file_number); CGNSDLL cgns_base *cgi_get_base (cgns_file *cg, int B); CGNSDLL cgns_zone *cgi_get_zone (cgns_file *cg, int B, int Z); CGNSDLL cgns_family *cgi_get_family (cgns_file *cg, int B, int F); CGNSDLL cgns_biter *cgi_get_biter (cgns_file *cg, int B); CGNSDLL cgns_gravity *cgi_get_gravity(cgns_file *cg, int B); CGNSDLL cgns_axisym *cgi_get_axisym (cgns_file *cg, int B); CGNSDLL cgns_ziter *cgi_get_ziter (cgns_file *cg, int B, int Z); CGNSDLL cgns_zcoor *cgi_get_zcoor (cgns_file *cg, int B, int Z, int C); CGNSDLL cgns_zcoor *cgi_get_zcoorGC(cgns_file *cg, int B, int Z); CGNSDLL cgns_section *cgi_get_section(cgns_file *cg, int B, int Z, int S); CGNSDLL cgns_sol *cgi_get_sol (cgns_file *cg, int B, int Z, int S); CGNSDLL cgns_array *cgi_get_field (cgns_file *cg, int B, int Z, int S, int F); CGNSDLL cgns_zconn *cgi_get_zconnZC(cgns_file *cg, int B, int Z, int C); CGNSDLL cgns_zconn *cgi_get_zconn (cgns_file *cg, int B, int Z); CGNSDLL cgns_hole *cgi_get_hole (cgns_file *cg, int B, int Z, int I); CGNSDLL cgns_conn *cgi_get_conn (cgns_file *cg, int B, int Z, int I); CGNSDLL cgns_1to1 *cgi_get_1to1 (cgns_file *cg, int B, int Z, int I); CGNSDLL cgns_zboco *cgi_get_zboco (cgns_file *cg, int B, int Z); CGNSDLL cgns_boco *cgi_get_boco (cgns_file *cg, int B, int Z, int BC); CGNSDLL cgns_dataset *cgi_get_dataset(cgns_file *cg, int B, int Z, int BC, int DSet); CGNSDLL cgns_bcdata *cgi_get_bcdata (cgns_file *cg, int B, int Z, int BC, int Dset, CGNS_ENUMT(BCDataType_t) type); CGNSDLL cgns_model *cgi_get_model (cgns_file *cg, int B, int Z, char *model); CGNSDLL cgns_state *cgi_get_state (cgns_file *cg, int B, int Z, int ZBC, int BC, int Dset); CGNSDLL cgns_converg *cgi_get_converg(cgns_file *cg, int B, int Z); CGNSDLL cgns_equations *cgi_get_equations(cgns_file *cg, int B, int Z); CGNSDLL cgns_governing *cgi_get_governing(cgns_file *cg, int B, int Z); CGNSDLL cgns_integral *cgi_get_integral (cgns_file *cg, int B, int Z, int N); CGNSDLL cgns_discrete *cgi_get_discrete (cgns_file *cg, int B, int Z, int D); CGNSDLL cgns_rmotion *cgi_get_rmotion (cgns_file *cg, int B, int Z, int R); CGNSDLL cgns_amotion *cgi_get_amotion (cgns_file *cg, int B, int Z, int R); CGNSDLL cgns_rotating *cgi_get_rotating (cgns_file *cg, int B, int Z); CGNSDLL cgns_bprop *cgi_get_bprop (cgns_file *cg, int B, int Z, int BC); CGNSDLL cgns_cprop *cgi_get_cprop (cgns_file *cg, int B, int Z, int I); CGNSDLL cgns_subreg *cgi_get_subreg (cgns_file *cg, int B, int Z, int S); /* find position lead by the goto function */ CGNSDLL int cgi_update_posit(int cnt, int *index, char **label); CGNSDLL int cgi_set_posit(int fn, int B, int n, int *index, char **label); CGNSDLL int cgi_posit_id(double *posit_id); CGNSDLL cgns_posit *cgi_get_posit(); CGNSDLL int cgi_posit_index_dim(); /* retrieve memory address of multiple patch children knowing their parent label (posit_label) and their parent memory address (posit) */ cgns_descr *cgi_descr_address(int local_mode, int descr_no, char const *descr_name, int *ier); CGNS_ENUMT(DataClass_t) *cgi_dataclass_address(int local_mode, int *ier); cgns_units *cgi_units_address(int local_mode, int *ier); int *cgi_ordinal_address(int local_mode, int *ier); int *cgi_rind_address(int local_mode, int *ier); CGNS_ENUMT(GridLocation_t) *cgi_location_address(int local_mode, int *ier); cgns_conversion *cgi_conversion_address(int local_mode, int *ier); cgns_exponent *cgi_exponent_address(int local_mode, int *ier); cgns_integral *cgi_integral_address(int local_mode, int integral_no, char const *integral_name, int *ier); cgns_equations *cgi_equations_address(int local_mode, int *ier); cgns_state *cgi_state_address(int local_mode, int *ier); cgns_converg *cgi_converg_address(int local_mode, int *ier); cgns_governing *cgi_governing_address(int local_mode, int *ier); int *cgi_diffusion_address(int local_mode, int *ier); cgns_array *cgi_array_address(int local_mode, int allow_dup, int array_no, char const *array_name, int* have_dup, int *ier); cgns_model *cgi_model_address(int local_mode, char const *ModelLabel, int *ier); char *cgi_famname_address(int local_mode, int *ier); cgns_famname *cgi_multfam_address(int mode, int num, char const *name, int *ier); cgns_user_data *cgi_user_data_address(int local_mode, int given_no, char const *given_name, int *ier); cgns_rotating *cgi_rotating_address(int local_mode, int *ier); cgns_ptset *cgi_ptset_address(int local_mode, int *ier); cgns_dataset * cgi_bcdataset_address(int local_mode, int given_no, char const *given_name, int *ier); /* read CGNS file into internal database */ int cgi_read(); int cgi_read_base(cgns_base *base); int cgi_read_zone(cgns_zone *zone); int cgi_read_zonetype(double parent_id, char_33 parent_name, CGNS_ENUMT(ZoneType_t) *type); int cgi_read_family(cgns_family *family); int cgi_read_family_dataset(int in_link, double parent_id, int *ndataset, cgns_dataset **dataset); int cgi_read_family_name(int in_link, double parent_id, char_33 parent_name, char_33 family_name); int cgi_read_array(cgns_array *array, char *parent_label, double parent_id); int cgi_read_section(int in_link, double parent_id, int *nsections, cgns_section **section); int cgi_read_hole(cgns_hole *hole); int cgi_read_conn(cgns_conn *conn); int cgi_read_1to1(cgns_1to1 *one21); int cgi_read_one_ptset(int linked, double parent_id, cgns_ptset **ptset); int cgi_read_ptset(double parent_id, cgns_ptset *ptset); int cgi_read_string(double id, char_33 name, char **string_data); int cgi_read_boco(cgns_boco *boco); int cgi_read_location(double parent_id, char_33 parent_name, CGNS_ENUMT(GridLocation_t) *location); int cgi_read_state(int in_link, double parent_id, cgns_state **state); int cgi_read_converg(int in_link, double parent_id, cgns_converg **converg); int cgi_read_units(int in_link, double parent_id, cgns_units **units); int cgi_read_equations(int in_link, double parent_id, cgns_equations **equations); int cgi_read_model(int in_link, double parent_id, char *label, cgns_model **model); int cgi_read_conversion(int in_link, double parent_id, cgns_conversion **convert); int cgi_read_exponents(int in_link, double parent_id, cgns_exponent **exponents); int cgi_read_integral(int in_link, double parent_id, int *nintegrals, cgns_integral **integral); int cgi_read_discrete(int in_link, double parent_id, int *ndiscrete, cgns_discrete **discrete); int cgi_read_sol(int in_link, double parent_id, int *nsols, cgns_sol **sol); int cgi_read_zcoor(int in_link, double parent_id, int *nzcoor, cgns_zcoor **zcoor); int cgi_read_zconn(int in_link, double parent_id, int *nzconn, cgns_zconn **zconn); int cgi_read_zboco(int in_link, double parent_id, cgns_zboco **zboco); int cgi_read_dataset(int in_link, double parent_id, int *ndataset, cgns_dataset **dataset); int cgi_read_bcdata(cgns_bcdata *bcdata); int cgi_read_rind(double parent_id, int **rind_planes); int cgi_read_ordinal(double parent_id, int *ordinal); int cgi_read_DDD(int in_link, double parent_id, int *ndescr, cgns_descr **descr, CGNS_ENUMT(DataClass_t) *data_class, cgns_units **units); int cgi_read_rmotion(int in_link, double parent_id, int *nrmotions, cgns_rmotion **rmotion); int cgi_read_amotion(int in_link, double parent_id, int *namotions, cgns_amotion **amotion); int cgi_read_simulation(double parent_id, CGNS_ENUMT(SimulationType_t) *type, double *type_id); int cgi_read_biter(int in_link, double parent_id, cgns_biter **biter); int cgi_read_ziter(int in_link, double parent_id, cgns_ziter **ziter); int cgi_read_gravity(int in_link, double parent_id, cgns_gravity **gravity); int cgi_read_axisym(int in_link, double parent_id, cgns_axisym **axisym); int cgi_read_rotating(int in_link, double parent_id, cgns_rotating **rotating); int cgi_read_bprop(int in_link, double parent_id, cgns_bprop **bprop); int cgi_read_cprop(int in_link, double parent_id, cgns_cprop **cprop); int cgi_read_user_data(int in_link, double parent_id, int *nuser_data, cgns_user_data **user_data); int cgi_read_subregion(int in_link, double parent_id, int *nsubreg, cgns_subreg **subreg); cgns_link *cgi_read_link(double node_id); CGNSDLL int cgi_datasize(int Idim, cgsize_t *CurrentDim, CGNS_ENUMT(GridLocation_t) location, int *rind_planes, cgsize_t *DataSize); int cgi_read_node(double node_id, char_33 name, char_33 data_type, int *ndim, cgsize_t *dim_vals, void **data, int data_flag); CGNSDLL int cgi_get_nodes(double parent_id, char *label, int *nnodes, double **id); /* write ADF file from internal database */ int cgi_write(int file_number); int cgi_write_zone(double parent_id, cgns_zone *zone); int cgi_write_family(double parent_id, cgns_family *family); int cgi_write_zcoor(double parent_id, cgns_zcoor *zcoor); int cgi_write_section(double parent_id, cgns_section *section); int cgi_write_sol(double parent_id, cgns_sol *sol); int cgi_write_zconn(double parent_id, cgns_zconn *zconn); int cgi_write_1to1(double parent_id, cgns_1to1 *one21); int cgi_write_conns(double parent_id, cgns_conn *conn); int cgi_write_holes(double parent_id, cgns_hole *hole); int cgi_write_zboco(double parent_id, cgns_zboco *zboco); int cgi_write_boco(double parent_id, cgns_boco *boco); int cgi_write_dataset(double parent_id, const char *label, cgns_dataset *dataset); int cgi_write_bcdata(double bcdata_id, cgns_bcdata *bcdata); int cgi_write_ptset(double id, char_33 name, cgns_ptset *ptset, int Ndim, void *ptset_ptr); int cgi_write_equations(double parent_id, cgns_equations *equations); int cgi_write_model(double parent_id, cgns_model *model); int cgi_write_state(double parent_id, cgns_state *state); int cgi_write_converg(double parent_id, cgns_converg *converg); int cgi_write_discrete(double parent_id, cgns_discrete *discrete); int cgi_write_integral(double parent_id, cgns_integral *integral); CGNSDLL int cgi_write_array(double parent_id, cgns_array *array); int cgi_write_rind(double parent_id, int *rind_planes, int idim); int cgi_write_units(double parent_id, cgns_units *units); int cgi_write_exponents(double parent_id, cgns_exponent *exponents); CGNSDLL int cgi_write_dataclass(double parent_id, CGNS_ENUMT(DataClass_t) data_class); int cgi_write_descr(double parent_id, cgns_descr *descr); CGNSDLL int cgi_write_ordinal(double parent_id, int ordinal); int cgi_write_rmotion(double parent_id, cgns_rmotion *rmotion); int cgi_write_amotion(double parent_id, cgns_amotion *amotion); int cgi_write_biter(double parent_id, cgns_biter *biter); int cgi_write_ziter(double parent_id, cgns_ziter *ziter); int cgi_write_gravity(double parent_id, cgns_gravity *gravity); int cgi_write_axisym(double parent_id, cgns_axisym *axisym); int cgi_write_rotating(double parent_id, cgns_rotating *rotating); int cgi_write_bprop(double parent_id, cgns_bprop *bprop); int cgi_write_cprop(double parent_id, cgns_cprop *cprop); int cgi_write_user_data(double parent_id, cgns_user_data *user_data); int cgi_write_link(double parent_id, char *name, cgns_link *link, double *node_id); CGNSDLL int cgi_new_node(double parent_id, char const *name, char const *label, double *node_id, char const *data_type, int ndim, cgsize_t const *dim_vals, void const *data); int cgi_new_node_partial(double parent_id, char const *name, char const *label, double *node_id, char const *data_type, int numdim, cgsize_t const *dims, cgsize_t const *s_start, cgsize_t const *s_end, int m_numdim, cgsize_t const *m_dims, cgsize_t const *m_start, cgsize_t const *m_end, void const *data); int cgi_move_node(double old_id, double node_id, double new_id, cchar_33 node_name); int cgi_delete_node (double parent_id, double node_id); /* general array reading and writing */ int cgi_array_general_verify_range(const cgi_rw op_rw, const void* rind_index, const int* rind_planes, const int s_numdim, const cgsize_t *s_dimvals, const cgsize_t *rmin, const cgsize_t *rmax, const int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, cgsize_t *s_rmin, cgsize_t *s_rmax, cgsize_t *stride, int *s_access_full_range, int *m_access_full_range, cgsize_t *numpt); int cgi_array_general_read(const cgns_array *array, const void* rind_index, const int *rind_planes, const int s_numdim, const cgsize_t *rmin, const cgsize_t *rmax, CGNS_ENUMT(DataType_t) m_type, const int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, void* data); int cgi_array_general_write(double p_id, int *p_narraylist, cgns_array **p_arraylist, const char *const arrayname, const void* rind_index, const int* rind_planes, CGNS_ENUMT(DataType_t) s_type, const int s_numdim, const cgsize_t *s_dimvals, const cgsize_t *rmin, const cgsize_t *rmax, CGNS_ENUMT(DataType_t) m_type, const int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, const void* data, int *A); /* error handling */ CGNSDLL void cgi_error(const char *format, ...); CGNSDLL void cgi_warning(const char *format, ...); CGNSDLL void cg_io_error(const char *routine_name); /* retrieve list number from list name */ int cgi_GridLocation(char *GridLocationName, CGNS_ENUMT(GridLocation_t) *type); int cgi_GridConnectivityType(char *GridConnectivityName, CGNS_ENUMT(GridConnectivityType_t) *type); int cgi_PointSetType(char *PointSetName, CGNS_ENUMT(PointSetType_t) *type); int cgi_BCType(char *BCName, CGNS_ENUMT(BCType_t) *type); int cgi_DataClass(char *Name, CGNS_ENUMT(DataClass_t) *data_class); int cgi_MassUnits(char *Name, CGNS_ENUMT(MassUnits_t) *mass_unit); int cgi_LengthUnits(char *Name, CGNS_ENUMT(LengthUnits_t) *length_unit); int cgi_TimeUnits(char *Name, CGNS_ENUMT(TimeUnits_t) *time_unit); int cgi_TemperatureUnits(char *Name, CGNS_ENUMT(TemperatureUnits_t) *temperature_unit); int cgi_AngleUnits(char *Name, CGNS_ENUMT(AngleUnits_t) *angle_unit); int cgi_ElectricCurrentUnits(char *Name, CGNS_ENUMT(ElectricCurrentUnits_t) *unit); int cgi_SubstanceAmountUnits(char *Name, CGNS_ENUMT(SubstanceAmountUnits_t) *unit); int cgi_LuminousIntensityUnits(char *Name, CGNS_ENUMT(LuminousIntensityUnits_t) *unit); int cgi_GoverningEquationsType(char *Name, CGNS_ENUMT(GoverningEquationsType_t) *type); int cgi_ModelType(char *Name, CGNS_ENUMT(ModelType_t) *type); int cgi_ZoneType(char *Name, CGNS_ENUMT(ZoneType_t) *type); int cgi_RigidGridMotionType(char *Name, CGNS_ENUMT(RigidGridMotionType_t) *type); int cgi_ArbitraryGridMotionType(char *Name, CGNS_ENUMT(ArbitraryGridMotionType_t) *type); int cgi_SimulationType(char *Name, CGNS_ENUMT(SimulationType_t) *type); int cgi_WallFunctionType(char *Name, CGNS_ENUMT(WallFunctionType_t) *type); int cgi_AreaType(char *Name, CGNS_ENUMT(AreaType_t) *type); int cgi_AverageInterfaceType(char *Name, CGNS_ENUMT(AverageInterfaceType_t) *type); int cgi_zone_no(cgns_base *base, char *zonename, int *zone_no); /* miscelleneous */ int cgi_sort_names(int n, double *ids); int size_of(const char_33 adf_type); char *type_of(char_33 data_type); int cgi_check_strlen(char const * string); int cgi_check_strlen_x2(char const *string); int cgi_check_mode(char const * filename, int file_mode, int mode_wanted); const char *cgi_adf_datatype(CGNS_ENUMT(DataType_t) type); CGNSDLL CGNS_ENUMT(DataType_t) cgi_datatype(cchar_33 adf_type); int cgi_check_dimensions(int ndims, cglong_t *dims); int cgi_check_location(int dim, CGNS_ENUMT(ZoneType_t) type, CGNS_ENUMT(GridLocation_t) loc); CGNSDLL int cgi_read_int_data(double id, char_33 data_type, cgsize_t cnt, cgsize_t *data); int cgi_convert_data(cgsize_t cnt, CGNS_ENUMT(DataType_t) from_type, const void *from_data, CGNS_ENUMT(DataType_t) to_type, void *to_data); int cgi_add_czone(char_33 zonename, cgsize6_t range, cgsize6_t donor_range, int idim, int *ndouble, char_33 **Dzonename, cgsize6_t **Drange, cgsize6_t **Ddonor_range); void cgi_array_print(char *routine, cgns_array *array); cgsize_t cgi_element_data_size(CGNS_ENUMT(ElementType_t) type, cgsize_t nelems, const cgsize_t *connect, const cgsize_t *connect_offset); /* free memory */ void cgi_free_file(cgns_file *cg); void cgi_free_base(cgns_base *base); void cgi_free_zone(cgns_zone *zone); void cgi_free_family(cgns_family *family); void cgi_free_fambc(cgns_fambc *fambc); void cgi_free_famname(cgns_famname *famname); void cgi_free_geo(cgns_geo *geo); void cgi_free_part(cgns_part *part); void cgi_free_zcoor(cgns_zcoor *zcoor); void cgi_free_section(cgns_section *section); void cgi_free_zboco(cgns_zboco *zboco); void cgi_free_zconn(cgns_zconn *zconn); void cgi_free_sol(cgns_sol *sol); void cgi_free_1to1(cgns_1to1 *one21); void cgi_free_hole(cgns_hole *hole); void cgi_free_conn(cgns_conn *conn); void cgi_free_boco(cgns_boco *boco); void cgi_free_dataset(cgns_dataset *dataset); void cgi_free_bcdata(cgns_bcdata *bcdata); void cgi_free_ptset(cgns_ptset *ptset); void cgi_free_equations(cgns_equations *equations); void cgi_free_governing(cgns_governing *governing); void cgi_free_model(cgns_model *model); void cgi_free_state(cgns_state *state); void cgi_free_converg(cgns_converg *converg); void cgi_free_discrete(cgns_discrete *discrete); void cgi_free_integral(cgns_integral *integral); void cgi_free_array(cgns_array *array); void cgi_free_convert(cgns_conversion *convert); void cgi_free_exponents(cgns_exponent *exponents); void cgi_free_units(cgns_units *units); void cgi_free_descr(cgns_descr *descr); void cgi_free_rmotion(cgns_rmotion *rmotion); void cgi_free_amotion(cgns_amotion *amotion); void cgi_free_biter(cgns_biter *biter); void cgi_free_ziter(cgns_ziter *ziter); void cgi_free_gravity(cgns_gravity *gravity); void cgi_free_axisym(cgns_axisym *axisym); void cgi_free_rotating(cgns_rotating *rotating); void cgi_free_bprop(cgns_bprop *bprop); void cgi_free_bcwall(cgns_bcwall *bcwall); void cgi_free_bcarea(cgns_bcarea *bcarea); void cgi_free_cprop(cgns_cprop *cprop); void cgi_free_cperio(cgns_cperio *cperio); void cgi_free_caverage(cgns_caverage *caverage); void cgi_free_user_data(cgns_user_data *user_data); void cgi_free_subreg(cgns_subreg *subreg); #ifdef __cplusplus } #endif #endif CGNS-3.4.0/src/cgns_internals.c000066400000000000000000017510361343724673500162470ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #include #include #include #include #include #if !defined(_WIN32) || defined(__NUTC__) #include #endif #include "cgnsconfig.h" #include "cgnslib.h" #include "cgns_header.h" #include "cgns_io.h" #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #ifdef BUILD_HDF5 #include "adfh/ADFH.h" #include "hdf5.h" #endif #define CGNS_NAN(x) (!((x) < HUGE_VAL && (x) > -HUGE_VAL)) /*********************************************************************** * global variable definitions ***********************************************************************/ int Idim; /* current IndexDimension */ int Cdim; /* current CellDimension */ int Pdim; /* current PhysicalDimension */ cgsize_t CurrentDim[9]; /* current vertex, cell & bnd zone size*/ CGNS_ENUMT( ZoneType_t ) CurrentZoneType; /* current zone type */ int NumberOfSteps; /* Number of steps */ /*----- the goto stack -----*/ int posit_depth = 0; cgns_posit posit_stack[CG_MAX_GOTO_DEPTH+1]; /***********************************************************************\ * Internal functions * \***********************************************************************/ void *cgi_malloc(size_t cnt, size_t size) { void *buf = calloc(cnt, size); if (buf == NULL) { cgi_error("calloc failed for %d values of size %d", cnt, size); exit (1); } return buf; } void *cgi_realloc(void *oldbuf, size_t bytes) { void *buf = realloc(oldbuf, bytes); if (buf == NULL) { cgi_error("realloc failed for %d bytes", bytes); exit (1); } return buf; } /***********************************************************************\ * Read CGNS file and store in internal data structures * \***********************************************************************/ int cgi_read() { int b; double *id; /* get number of CGNSBase_t nodes and their ID */ if (cgi_get_nodes(cg->rootid, "CGNSBase_t", &cg->nbases, &id)) return CG_ERROR; if (cg->nbases==0) return CG_OK; cg->base = CGNS_NEW(cgns_base,cg->nbases); for (b=0; bnbases; b++) cg->base[b].id = id[b]; CGNS_FREE(id); /* read and save CGNSBase_t data */ for (b=0; bnbases; b++) if (cgi_read_base(&cg->base[b])) return CG_ERROR; return CG_OK; } int cgi_read_base(cgns_base *base) { char_33 data_type; int ndim, *index; double *id; int n; void *vdata; cgsize_t dim_vals[12]; /* Read CGNSBase_t Node */ if (cgi_read_node(base->id, base->name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading base"); return CG_ERROR; } index = (int *)vdata; /* check data type */ if (strcmp(data_type,"I4")!=0) { cgi_error("Unexpected data type for dimension data of base %s='%s'", base->name, data_type); return CG_ERROR; } if ((cg->version==1050 && (ndim != 1 || dim_vals[0]!=1)) || (cg->version >= 1100 && (ndim != 1 || dim_vals[0]!=2))) { cgi_error("Wrong definition of Base Dimensions."); return CG_ERROR; } if (cg->version == 1050) { /* old multiblock format */ base->cell_dim = base->phys_dim = index[0]; } else { base->cell_dim = index[0]; base->phys_dim = index[1]; } CGNS_FREE(vdata); if (base->cell_dim<1 || base->cell_dim>3) { cgi_error("Invalid value for base cell dimension (=%d)", base->cell_dim); return CG_ERROR; } if (base->phys_dim<1 || base->phys_dim>3) { cgi_error("Invalid value for base physical dimension(=%d)", base->phys_dim); return CG_ERROR; } /* set Global variable */ Cdim = base->cell_dim; Pdim = base->phys_dim; /* update version */ if (cg->mode == CG_MODE_MODIFY && cg->version < 1100) { dim_vals[0] = 2; if (cgio_set_dimensions(cg->cgio, base->id, "I4", 1, dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } dim_vals[0] = base->cell_dim; dim_vals[1] = base->phys_dim; if (cgio_write_all_data(cg->cgio, base->id, dim_vals)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } /* Family_t */ if (cgi_get_nodes(base->id, "Family_t", &base->nfamilies, &id)) return CG_ERROR; if (base->nfamilies>0) { /* read & save families */ base->family = CGNS_NEW(cgns_family, base->nfamilies); for (n=0; nnfamilies; n++) { base->family[n].id = id[n]; base->family[n].link = cgi_read_link(id[n]); base->family[n].in_link = 0; if (cgi_read_family(&base->family[n])) return CG_ERROR; } CGNS_FREE(id); } /* ReferenceState_t */ if (cgi_read_state(0, base->id, &base->state)) return CG_ERROR; /* Gravity_t */ if (cgi_read_gravity(0, base->id, &base->gravity)) return CG_ERROR; /* Axisymmetry_t */ if (cgi_read_axisym(0, base->id, &base->axisym)) return CG_ERROR; /* RotatingCoordinates_t */ if (cgi_read_rotating(0, base->id, &base->rotating)) return CG_ERROR; /* ConvergenceHistory_t */ if (cgi_read_converg(0, base->id, &base->converg)) return CG_ERROR; /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(0, base->id, &base->ndescr, &base->descr, &base->data_class, &base->units)) return CG_ERROR; /* FlowEquationSet_t */ if (cgi_read_equations(0, base->id, &base->equations)) return CG_ERROR; /* IntegralData_t */ if (cgi_read_integral(0, base->id, &base->nintegrals, &base->integral)) return CG_ERROR; /* SimulationType_t */ if (cgi_read_simulation(base->id, &base->type, &base->type_id)) return CG_ERROR; /* BaseIterativeData_t */ if (cgi_read_biter(0, base->id, &base->biter)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(0, base->id, &base->nuser_data, &base->user_data)) return CG_ERROR; /* Zone_t (depends on NumberOfSteps) */ if (cgi_get_nodes(base->id, "Zone_t", &base->nzones, &id)) return CG_ERROR; if (base->nzones>0) { /* Order zones alpha-numerically */ if (cgi_sort_names(base->nzones, id)) { cgi_error("Error sorting zone names..."); return CG_ERROR; } /* read & save zones in sorted order */ base->zone = CGNS_NEW(cgns_zone, base->nzones); for (n=0; nnzones; n++) { base->zone[n].id = id[n]; base->zone[n].link = cgi_read_link(id[n]); base->zone[n].in_link = 0; if (cgi_read_zone(&base->zone[n])) return CG_ERROR; } CGNS_FREE(id); } return CG_OK; } int cgi_read_zone(cgns_zone *zone) { int n, ndim; int in_link = zone->link ? 1 : zone->in_link; char_33 data_type; void *vdata; double *id; cgsize_t dim_vals[12]; /* Zone_t */ if (cgi_read_node(zone->id, zone->name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading node Zone_t"); return CG_ERROR; } /* verify data read */ if (ndim!=2) { cgi_error("Wrong number of dimension for a Zone_t node"); return CG_ERROR; } /* ZoneType_t */ if (cgi_read_zonetype(zone->id, zone->name, &zone->type)) return CG_ERROR; /* Set IndexDimension of zone */ if (zone->type==CGNS_ENUMV(Structured)) zone->index_dim=Cdim; else zone->index_dim=1; /* save Global Variable Idim */ Idim = zone->index_dim; if (dim_vals[0]!=zone->index_dim || ((cg->version==1050 && dim_vals[1]!=2) || (cg->version>=1100 && dim_vals[1]!=3))) { cgi_error("Wrong number of dimension values for Zone_t %s",zone->name); return CG_ERROR; } /* allocate memory to record zone size */ zone->nijk=CGNS_NEW(cgsize_t, zone->index_dim*3); if (0 == strcmp(data_type, "I8")) { cglong_t *mesh_dim = (cglong_t *)vdata; #if CG_SIZEOF_SIZE == 32 /*if (cgi_check_dimensions(zone->index_dim, mesh_dim)) return CG_ERROR;*/ /* Modified by zbhfut , 2017-11-09 For unstructured mesh, mesh_dim = {nnode,nelem}, the multiply product of mesh_dim may be exceed the limit of 32-bit integer. We don't need check the product actually but the component of mesh_dim. */ if (zone->type == CGNS_ENUMV(Structured)) { if (cgi_check_dimensions(zone->index_dim, mesh_dim)) return 1; } else{ for (n=0; nindex_dim; ++n) { if (mesh_dim[n] > CG_MAX_INT32) { cgi_error("array size exceeds that for a 32-bit integer"); return 1; } } } #endif for (n=0; nindex_dim; n++) { zone->nijk[n] = (cgsize_t)mesh_dim[n]; zone->nijk[n+Idim] = (cgsize_t)mesh_dim[n+Idim]; if (cg->version==1050) zone->nijk[n+2*Idim] = (cgsize_t)0; else zone->nijk[n+2*Idim] = (cgsize_t)mesh_dim[n+2*Idim]; } } else if (0 == strcmp(data_type, "I4")) { int *mesh_dim = (int *)vdata; for (n=0; nindex_dim; n++) { zone->nijk[n] = (cgsize_t)mesh_dim[n]; zone->nijk[n+Idim] = (cgsize_t)mesh_dim[n+Idim]; if (cg->version==1050) zone->nijk[n+2*Idim] = (cgsize_t)0; else zone->nijk[n+2*Idim] = (cgsize_t)mesh_dim[n+2*Idim]; } } else { cgi_error("Unsupported data type for Zone_t node %s= %s", zone->name, data_type); return CG_ERROR; } CGNS_FREE(vdata); /* save Global Variables */ for (n=0; nnijk[n]; CurrentZoneType = zone->type; /* verify data */ if (zone->type==CGNS_ENUMV(Structured)) { for (n=0; nindex_dim; n++) { if (zone->nijk[n] <=0 || zone->nijk[n]!=zone->nijk[n+Idim]+1) { cgi_error("Invalid structured zone dimensions"); return CG_ERROR; } } } else { if (zone->nijk[0]<0 || zone->nijk[1]<0 || zone->nijk[2]>zone->nijk[0]) { cgi_error("Invalid unstructured zone dimensions"); return CG_ERROR; } } /* update version */ if (cg->mode == CG_MODE_MODIFY && cg->version < 1100 && !in_link) { dim_vals[0] = zone->index_dim; dim_vals[1] = 3; if (cgio_set_dimensions(cg->cgio, zone->id, CG_SIZE_DATATYPE, 2, dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, zone->id, zone->nijk)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } /* GridCoordinates_t */ if (cgi_read_zcoor(in_link, zone->id, &zone->nzcoor, &zone->zcoor)) return CG_ERROR; /* Elements_t: Only for Unstructured zones */ if (cgi_read_section(in_link, zone->id, &zone->nsections, &zone->section)) return CG_ERROR; if (zone->type==CGNS_ENUMV( Structured ) && zone->nsections!=0) { cgi_error("Elements_t nodes is valid only for unstructured zones"); return CG_ERROR; } /* FamilyName_t */ if (cgi_read_family_name(in_link, zone->id, zone->name, zone->family_name)) return CG_ERROR; /* CPEX 0034 */ if (cgi_get_nodes(zone->id, "AdditionalFamilyName_t", &zone->nfamname, &id)) return CG_ERROR; if (zone->nfamname > 0) { char *fam; zone->famname = CGNS_NEW(cgns_famname, zone->nfamname); for (n = 0; n < zone->nfamname; n++) { zone->famname[n].id = id[n]; if (cgi_read_string(id[n], zone->famname[n].name, &fam)) return CG_ERROR; strncpy(zone->famname[n].family, fam, 32); CGNS_FREE(fam); } CGNS_FREE(id); } /* FlowSolution_t */ if (cgi_read_sol(in_link, zone->id, &zone->nsols, &zone->sol)) return CG_ERROR; /* ZoneGridConnectivity_t */ if (cgi_read_zconn(in_link, zone->id, &zone->nzconn, &zone->zconn)) return CG_ERROR; /* ZoneBC_t */ if (cgi_read_zboco(in_link, zone->id, &zone->zboco)) return CG_ERROR; /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(in_link, zone->id, &zone->ndescr, &zone->descr, &zone->data_class, &zone->units)) return CG_ERROR; /* DiscreteData_t */ if (cgi_read_discrete(in_link, zone->id, &zone->ndiscrete, &zone->discrete)) return CG_ERROR; /* IntegralData_t */ if (cgi_read_integral(in_link, zone->id, &zone->nintegrals, &zone->integral)) return CG_ERROR; /* ReferenceState_t */ if (cgi_read_state(in_link, zone->id, &zone->state)) return CG_ERROR; /* ConvergenceHistory_t */ if (cgi_read_converg(in_link, zone->id, &zone->converg)) return CG_ERROR; /* FlowEquationSet_t */ if (cgi_read_equations(in_link, zone->id, &zone->equations)) return CG_ERROR; /* Ordinal_t */ if (cgi_read_ordinal(zone->id, &zone->ordinal)) return CG_ERROR; /* RigidGridMotion_t */ if (cgi_read_rmotion(in_link, zone->id, &zone->nrmotions, &zone->rmotion)) return CG_ERROR; /* ArbitraryGridMotion_t */ if (cgi_read_amotion(in_link, zone->id, &zone->namotions, &zone->amotion)) return CG_ERROR; /* ZoneIterativeData_t can only exist if BaseIterativeData_t exist because it depends on it */ if (NumberOfSteps) { if (cgi_read_ziter(in_link, zone->id, &zone->ziter)) return CG_ERROR; } else zone->ziter = 0; /* UserDefinedData_t */ if (cgi_read_user_data(in_link, zone->id, &zone->nuser_data, &zone->user_data)) return CG_ERROR; /* RotatingCoordinates_t */ if (cgi_read_rotating(in_link, zone->id, &zone->rotating)) return CG_ERROR; /* ZoneSubRegion_t */ if (cgi_read_subregion(in_link, zone->id, &zone->nsubreg, &zone->subreg)) return CG_ERROR; return CG_OK; } int cgi_read_family(cgns_family *family) { int n, linked, in_link = family->link ? 1 : family->in_link; double *id; char *boconame; /* Family name */ if (cgio_get_name(cg->cgio, family->id, family->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* CPEX 0033 */ if (cgi_get_nodes(family->id, "FamilyName_t", &family->nfamname, &id)) return CG_ERROR; if (family->nfamname > 0) { char *fam; family->famname = CGNS_NEW(cgns_famname, family->nfamname); for (n = 0; n < family->nfamname; n++) { family->famname[n].id = id[n]; if (cgi_read_string(id[n], family->famname[n].name, &fam)) return CG_ERROR; strncpy(family->famname[n].family, fam, 32); CGNS_FREE(fam); } CGNS_FREE(id); } /* FamilyBC_t */ if (cgi_get_nodes(family->id, "FamilyBC_t", &family->nfambc, &id)) return CG_ERROR; if (family->nfambc>0) { family->fambc = CGNS_NEW(cgns_fambc, family->nfambc); for (n=0; nnfambc; n++) { family->fambc[n].id = id[n]; family->fambc[n].link = cgi_read_link(id[n]); family->fambc[n].in_link = in_link; if (cgi_read_string(id[n], family->fambc[n].name, &boconame)) return CG_ERROR; /* get BCType */ if (cgi_BCType(boconame, &family->fambc[n].type)) return CG_ERROR; CGNS_FREE(boconame); /* FamilyBCDataSet_t */ linked = family->fambc[n].link ? 1 : in_link; if (cgi_read_family_dataset(linked, family->fambc[n].id, &family->fambc[n].ndataset, &family->fambc[n].dataset)) return CG_ERROR; } CGNS_FREE(id); } /* GeometryReference_t */ if (cgi_get_nodes(family->id, "GeometryReference_t", &family->ngeos, &id)) return CG_ERROR; if (family->ngeos>0) { family->geo = CGNS_NEW(cgns_geo, family->ngeos); for (n=0; nngeos; n++) { family->geo[n].id = id[n]; family->geo[n].link = cgi_read_link(id[n]); family->geo[n].in_link = in_link; /* GeometryReference Name */ if (cgio_get_name(cg->cgio, family->geo[n].id, family->geo[n].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* UserDefinedData_t */ linked = family->geo[n].link ? 1 : in_link; if (cgi_read_user_data(linked, family->geo[n].id, &family->geo[n].nuser_data, &family->geo[n].user_data)) return CG_ERROR; } CGNS_FREE(id); } /* GeometryReference_t Children */ for (n=0; nngeos; n++) { int i, flag; char_33 dummy_name; cgns_geo *geo = &family->geo[n]; /* Descriptor_t */ if (cgi_get_nodes(geo->id, "Descriptor_t", &geo->ndescr, &id)) return CG_ERROR; if (geo->ndescr>0) { geo->descr = CGNS_NEW(cgns_descr, geo->ndescr); for (i=0; indescr; i++) { geo->descr[i].id = id[i]; geo->descr[i].link = cgi_read_link(id[i]); geo->descr[i].in_link = in_link; if (cgi_read_string(id[i], geo->descr[i].name, &geo->descr[i].text)) return CG_ERROR; } CGNS_FREE(id); } /* GeometryFile_t */ if (cgi_get_nodes(geo->id, "GeometryFile_t", &flag, &id)) return CG_ERROR; if (flag==1) { if (cgi_read_string(id[0], dummy_name, &geo->file)) return CG_ERROR; } else { cgi_error("Incorrect definition of GeometryFile_t"); return CG_ERROR; } if (flag) CGNS_FREE(id); /* GeometryFormat_t */ if (cgi_get_nodes(geo->id, "GeometryFormat_t", &flag, &id)) return CG_ERROR; if (flag==1) { char *geoformat; if (cgi_read_string(id[0], dummy_name, &geoformat)) return CG_ERROR; if (strlen(geoformat)>32) { cgi_error("Geometry File Format is limited to 32 characters"); return CG_ERROR; } else strcpy(geo->format, geoformat); CGNS_FREE(geoformat); } else { cgi_error("Incorrect definition of GeometryFormat_t"); return CG_ERROR; } if (flag) CGNS_FREE(id); /* GeometryEntity_t */ if (cgi_get_nodes(geo->id, "GeometryEntity_t", &geo->npart, &id)) return CG_ERROR; if (geo->npart>0) { geo->part = CGNS_NEW(cgns_part, geo->npart); for (i=0; inpart; i++) { geo->part[i].id = id[i]; geo->part[i].link = cgi_read_link(id[i]); geo->part[i].in_link = in_link; if (cgio_get_name(cg->cgio, id[i], geo->part[i].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } } CGNS_FREE(id); } } /* loop through ngeos */ /* Descriptor_t under Family_t */ if (cgi_get_nodes(family->id, "Descriptor_t", &family->ndescr, &id)) return CG_ERROR; if (family->ndescr>0) { family->descr = CGNS_NEW(cgns_descr, family->ndescr); for (n=0; nndescr; n++) { family->descr[n].id = id[n]; family->descr[n].link = cgi_read_link(id[n]); family->descr[n].in_link = in_link; if (cgi_read_string(id[n], family->descr[n].name, &family->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* Ordinal_t */ if (cgi_read_ordinal(family->id, &family->ordinal)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(in_link, family->id, &family->nuser_data, &family->user_data)) return CG_ERROR; /* RotatingCoordinates_t */ if (cgi_read_rotating(in_link, family->id, &family->rotating)) return CG_ERROR; return CG_OK; } int cgi_read_family_dataset(int in_link, double parent_id, int *ndataset, cgns_dataset **pdataset) { int n, i, nnod, linked; double *id, *ids; char_33 name; char *string_data; int modified = 0; cgns_dataset *dataset; /* FamilyBCDataSet_t */ if (cgi_get_nodes(parent_id, "FamilyBCDataSet_t", ndataset, &id)) return CG_ERROR; /* if not found, check for BCDataSet_t (pre 3.1.3) */ if (*ndataset <= 0) { if (cgi_get_nodes(parent_id, "BCDataSet_t", ndataset, &id)) return CG_ERROR; modified = (cg->filetype != CG_FILE_ADF2); } if (*ndataset <= 0) { *pdataset = NULL; return CG_OK; } dataset = CGNS_NEW(cgns_dataset, (*ndataset)); *pdataset = dataset; for (n = 0; n < *ndataset; n++) { dataset[n].id = id[n]; dataset[n].link = cgi_read_link(id[n]); dataset[n].in_link = in_link; linked = dataset[n].link ? 1 : in_link; if (cgi_read_string(dataset[n].id, dataset[n].name, &string_data) || cgi_BCType(string_data, &dataset[n].type)) return CG_ERROR; CGNS_FREE(string_data); /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, dataset[n].id, &dataset[n].ndescr, &dataset[n].descr, &dataset[n].data_class, &dataset[n].units)) return CG_ERROR; /* ReferenceState_t */ if (cgi_read_state(linked, dataset[n].id, &dataset[n].state)) return CG_ERROR; /* BCData_t */ dataset[n].dirichlet = dataset[n].neumann = NULL; if (cgi_get_nodes(dataset[n].id, "BCData_t", &nnod, &ids)) return CG_ERROR; if (nnod > 0) { for (i = 0; i < nnod; i++) { /* Name */ if (cgio_get_name(cg->cgio, ids[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "DirichletData")==0) { if (dataset[n].dirichlet!=0) { cgi_error("Dirichet Data defined more than once..."); return CG_ERROR; } dataset[n].dirichlet=CGNS_NEW(cgns_bcdata, 1); dataset[n].dirichlet->id = ids[i]; dataset[n].dirichlet->link = cgi_read_link(ids[i]); dataset[n].dirichlet->in_link = linked; strcpy(dataset[n].dirichlet->name,"DirichletData"); if (cgi_read_bcdata(dataset[n].dirichlet)) return CG_ERROR; } else if (strcmp(name, "NeumannData")==0) { if (dataset[n].neumann!=0) { cgi_error("Neumann Data defined more than once..."); return CG_ERROR; } dataset[n].neumann=CGNS_NEW(cgns_bcdata, 1); dataset[n].neumann->id = ids[i]; dataset[n].neumann->link = cgi_read_link(ids[i]); dataset[n].neumann->in_link = linked; strcpy(dataset[n].neumann->name,"NeumannData"); if (cgi_read_bcdata(dataset[n].neumann)) return CG_ERROR; } } CGNS_FREE(ids); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, dataset[n].id, &dataset[n].nuser_data, &dataset[n].user_data)) return CG_ERROR; /* fix label if needed */ if (modified && !linked && cg->mode == CG_MODE_MODIFY) { if (cgio_set_label(cg->cgio, id[n], "FamilyBCDataSet_t")) { cg_io_error("cgio_set_label"); return CG_ERROR; } } } CGNS_FREE(id); return CG_OK; } int cgi_read_family_name(int in_link, double parent_id, char_33 parent_name, char_33 family_name) { int fam_flag; double *id; char_33 NodeName; char *FamilyName=0; /* allocated in cgi_read_node */ family_name[0]='\0'; if (cgi_get_nodes(parent_id, "FamilyName_t", &fam_flag, &id)) return CG_ERROR; if (fam_flag==1) { if (cg->version>1200) { /* FamilyName in data field of the ADF node */ if (cgi_read_string(id[0], NodeName, &FamilyName)) return CG_ERROR; if (strlen(FamilyName) > 32) FamilyName[32]='\0'; strcpy(family_name, FamilyName); if (FamilyName) CGNS_FREE(FamilyName); } else { /* FamilyName is the ADF node name */ if (cgio_get_name(cg->cgio, id[0], family_name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* update version */ if (cg->mode == CG_MODE_MODIFY && !in_link) { double dummy_id; cgsize_t len = (cgsize_t)strlen(family_name); if (cgi_delete_node(parent_id, id[0])) return CG_ERROR; if (cgi_new_node(parent_id, "FamilyName", "FamilyName_t", &dummy_id, "C1", 1, &len, (void *)family_name)) return CG_ERROR; } } CGNS_FREE(id); } else if (fam_flag<0 || fam_flag>1) { cgi_error("Family name defined incorrectly under '%s',",parent_name); return CG_ERROR; } return CG_OK; } int cgi_read_zcoor(int in_link, double parent_id, int *nzcoor, cgns_zcoor **zcoor) { double *idg, *id; int g, z, n, linked; cgsize_t DataSize[3]; if (cgi_get_nodes(parent_id, "GridCoordinates_t", nzcoor, &idg)) return CG_ERROR; if ((*nzcoor)<=0) return CG_OK; zcoor[0] = CGNS_NEW(cgns_zcoor, (*nzcoor)); for (g=0; g<(*nzcoor); g++) { zcoor[0][g].id = idg[g]; zcoor[0][g].link = cgi_read_link(idg[g]); zcoor[0][g].in_link = in_link; linked = zcoor[0][g].link ? 1 : in_link; /* Name */ if (cgio_get_name(cg->cgio, zcoor[0][g].id, zcoor[0][g].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* Rind Planes */ if (cgi_read_rind(zcoor[0][g].id, &zcoor[0][g].rind_planes)) return CG_ERROR; /* Assume that the coordinates are always at the node */ if (cgi_datasize(Idim, CurrentDim, CGNS_ENUMV(Vertex), zcoor[0][g].rind_planes, DataSize)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(zcoor[0][g].id, "DataArray_t", &zcoor[0][g].ncoords, &id)) return CG_ERROR; if (zcoor[0][g].ncoords > 0) { zcoor[0][g].coord = CGNS_NEW(cgns_array, zcoor[0][g].ncoords); for (z=0; zversion < 3100) { if (cg->version < 3000) { if (el_type > CGNS_ENUMV(MIXED)) { cgi_error("Element Type %s not supported in:'%s'", cg_ElementTypeName(el_type), section[0][n].name); return CG_ERROR; } } /* reordered in 3.1 */ else if (el_type > CGNS_ENUMV(PYRA_5) && el_type < CGNS_ENUMV(NGON_n)) { if (el_type == CGNS_ENUMV(PYRA_14)) el_type = CGNS_ENUMV(PYRA_13); else el_type--; changed++; } } section[0][n].el_type = el_type; section[0][n].el_bound = edata[1]; CGNS_FREE(vdata); if (INVALID_ENUM(el_type,NofValidElementTypes)) { cgi_error("Invalid Element Type for Elements_t :'%s'", section[0][n].name); return CG_ERROR; } /* Descriptor_t */ if (cgi_get_nodes(section[0][n].id, "Descriptor_t", §ion[0][n].ndescr, &idi)) return CG_ERROR; if (section[0][n].ndescr>0) { section[0][n].descr = CGNS_NEW(cgns_descr, section[0][n].ndescr); for (i=0; icgio, idi[i], temp_name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* ElementConnectivity */ if (strcmp(temp_name,"ElementConnectivity")==0) { if (section[0][n].connect) { cgi_error("Error: ElementConnectivity defined more than once"); return CG_ERROR; } section[0][n].connect = CGNS_NEW(cgns_array, 1); section[0][n].connect->id = idi[i]; section[0][n].connect->link = cgi_read_link(idi[i]); section[0][n].connect->in_link = linked; if (cgi_read_array(section[0][n].connect, "Elements_t", section[0][n].id)) return CG_ERROR; /* check data */ if (strcmp(section[0][n].connect->data_type,"I4") && strcmp(section[0][n].connect->data_type,"I8")) { cgi_error("Datatype %s not supported for element connectivity", section[0][n].connect->data_type); return CG_ERROR; } if (cg_npe(section[0][n].el_type, &npe)) return CG_ERROR; if (cg->version <= 1100) { if (section[0][n].connect->dim_vals[0] != npe || section[0][n].connect->dim_vals[1] != nelements || section[0][n].connect->data_dim != 2 ) { cgi_error("Error exit: Element connectivity incorrectly defined"); return CG_ERROR; } /* Rewrite with new data array parameters starting with version 1200 */ section[0][n].connect->data_dim = 1; section[0][n].connect->dim_vals[0] = npe*nelements; section[0][n].connect->dim_vals[1] = 0; if (cg->mode == CG_MODE_MODIFY && !linked) { /* read the data into memory */ if (cgi_read_node(section[0][n].connect->id, section[0][n].connect->name, section[0][n].connect->data_type, &ndim, dim_vals, &vdata, READ_DATA)) return CG_ERROR; if (cgio_set_dimensions(cg->cgio, section[0][n].connect->id, "I4", 1, section[0][n].connect->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section[0][n].connect->id, vdata)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } CGNS_FREE(vdata); } } else if (cg->version < 3100) { cgsize_t size, *elem_data = 0; int modified = 0; if (section[0][n].el_type == CGNS_ENUMV(MIXED)) { int ne; size = section[0][n].connect->dim_vals[0]; elem_data = CGNS_NEW(cgsize_t, size); if (cgi_read_int_data(section[0][n].connect->id, section[0][n].connect->data_type, size, elem_data)) return CG_ERROR; for (size = 0, ne = 0; ne < nelements; ne++) { el_type = (CGNS_ENUMT(ElementType_t))elem_data[size]; if (cg->version < 3000) { if (el_type > CGNS_ENUMV(MIXED)) { modified++; el_type++; elem_data[size] = el_type; } } else { if (el_type > CGNS_ENUMV(PYRA_5) && el_type < CGNS_ENUMV(NGON_n)) { if (el_type == CGNS_ENUMV(PYRA_14)) el_type = CGNS_ENUMV(PYRA_13); else el_type--; modified++; elem_data[size] = el_type; } } if (el_type > CGNS_ENUMV(NGON_n)) npe = el_type - CGNS_ENUMV(NGON_n); else cg_npe (el_type, &npe); if (npe <= 0) { cgi_error("Error exit: invalid element type in MIXED elements"); return CG_ERROR; } size += (npe + 1); } if (!modified) { CGNS_FREE(elem_data); elem_data = 0; } } size = cgi_element_data_size(section[0][n].el_type, nelements, elem_data, NULL); if (size < 0) return CG_ERROR; /* size may be zero, since elements not read */ if ((size && section[0][n].connect->dim_vals[0] != size) || section[0][n].connect->data_dim != 1) { cgi_error("Error exit: Element connectivity incorrectly defined"); return CG_ERROR; } /* rewrite if needed */ if ((changed || modified) && cg->mode == CG_MODE_MODIFY && !linked) { if (changed) { dim_vals[0] = (cgsize_t)section[0][n].el_type; dim_vals[1] = (cgsize_t)section[0][n].el_bound; if (cgio_write_all_data(cg->cgio, section[0][n].id, dim_vals)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } changed = 0; } if (modified) { if (strcmp(section[0][n].connect->data_type, CG_SIZE_DATATYPE)) { if (cgio_set_dimensions(cg->cgio, section[0][n].connect->id, CG_SIZE_DATATYPE, 1, section[0][n].connect->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } strcpy(section[0][n].connect->data_type, CG_SIZE_DATATYPE); } if (cgio_write_all_data(cg->cgio, section[0][n].connect->id, elem_data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } CGNS_FREE(elem_data); elem_data = 0; } } if (elem_data) { strcpy(section[0][n].connect->data_type, CG_SIZE_DATATYPE); section[0][n].connect->data = (void *)elem_data; } } if (cg->version < 3400) { cgsize_t size, *elem_data = 0; if (section[0][n].el_type == CGNS_ENUMV(NGON_n) || section[0][n].el_type == CGNS_ENUMV(NFACE_n) ) { cgsize_t size_offset, size_connect; cgsize_t *connect_offset = 0; cgsize_t *connect_new = 0; cgsize_t ne; size = section[0][n].connect->dim_vals[0]; elem_data = CGNS_NEW(cgsize_t, size); if (cgi_read_int_data(section[0][n].connect->id, section[0][n].connect->data_type, size, elem_data)) return CG_ERROR; size_offset = nelements +1; connect_offset = CGNS_NEW(cgsize_t, size_offset); connect_offset[0] = 0; for (size = 0, size_connect = 0, ne = 0; ne < nelements; ne++) { int idx = 0; npe = (int) elem_data[size++]; connect_offset[ne + 1] = connect_offset[ne] + npe; for (idx = 0; idx < npe; idx++) { elem_data[size_connect] = elem_data[size]; size_connect++; size++; } } if (section[0][n].connect_offset) { CGNS_FREE(section[0][n].connect_offset); section[0][n].connect_offset = 0; } section[0][n].connect_offset = CGNS_NEW(cgns_array, 1); memset(section[0][n].connect_offset, 0, sizeof(cgns_array)); strcpy(section[0][n].connect_offset->data_type, CG_SIZE_DATATYPE); strcpy(section[0][n].connect_offset->name, "ElementStartOffset"); section[0][n].connect_offset->data_dim = 1; section[0][n].connect_offset->dim_vals[0] = size_offset; section[0][n].connect_offset->data = (void *)connect_offset; if (cg->mode == CG_MODE_MODIFY && !linked) { section[0][n].connect->dim_vals[0] = size_connect; if (cgio_set_dimensions(cg->cgio, section[0][n].connect->id, CG_SIZE_DATATYPE, 1, section[0][n].connect->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } strcpy(section[0][n].connect->data_type, CG_SIZE_DATATYPE); if (cgio_write_all_data(cg->cgio, section[0][n].connect->id, elem_data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } CGNS_FREE(elem_data); elem_data = 0; cgi_write_array(section[0][n].id, section[0][n].connect_offset); section[0][n].connect_offset->data = 0; CGNS_FREE(connect_offset); connect_offset = 0; } else { connect_new = CGNS_NEW(cgsize_t, size_connect); memcpy(connect_new, elem_data, size_connect*sizeof(cgsize_t)); strcpy(section[0][n].connect->data_type, CG_SIZE_DATATYPE); section[0][n].connect->dim_vals[0] = size_connect; section[0][n].connect->data = (void *) connect_new; CGNS_FREE(elem_data); elem_data = 0; } } if (section[0][n].el_type == CGNS_ENUMV(MIXED)) { cgsize_t size_offset; cgsize_t *elem_offset = 0; int ne; size = section[0][n].connect->dim_vals[0]; elem_data = CGNS_NEW(cgsize_t, size); if (cgi_read_int_data(section[0][n].connect->id, section[0][n].connect->data_type, size, elem_data)) return CG_ERROR; size_offset = nelements +1; elem_offset = CGNS_NEW(cgsize_t, size_offset); elem_offset[0] = 0; for (size = 0, ne = 0; ne < nelements; ne++) { cg_npe(elem_data[size], &npe); elem_offset[ne + 1] = elem_offset[ne] + (npe + 1); size += (npe + 1); } CGNS_FREE(elem_data); elem_data = 0; /* check */ if (section[0][n].connect_offset) { CGNS_FREE(section[0][n].connect_offset); section[0][n].connect_offset = 0; } section[0][n].connect_offset = CGNS_NEW(cgns_array, 1); memset(section[0][n].connect_offset, 0, sizeof(cgns_array)); strcpy(section[0][n].connect_offset->data_type, CG_SIZE_DATATYPE); strcpy(section[0][n].connect_offset->name, "ElementStartOffset"); section[0][n].connect_offset->data_dim = 1; section[0][n].connect_offset->dim_vals[0] = size_offset; section[0][n].connect_offset->data = (void *)elem_offset; if (cg->mode == CG_MODE_MODIFY && !linked) { cgi_write_array(section[0][n].id, section[0][n].connect_offset); section[0][n].connect_offset->data = 0; CGNS_FREE(elem_offset); elem_offset = 0; } } } } else if (strcmp(temp_name,"ElementStartOffset")==0) { if (section[0][n].connect_offset) { cgi_error("Error: ElementStartOffset defined more than once"); return CG_ERROR; } section[0][n].connect_offset = CGNS_NEW(cgns_array, 1); section[0][n].connect_offset->id = idi[i]; section[0][n].connect_offset->link = cgi_read_link(idi[i]); section[0][n].connect_offset->in_link = linked; if (cgi_read_array(section[0][n].connect_offset, "Elements_t", section[0][n].id)) return CG_ERROR; /* check data */ if (strcmp(section[0][n].connect_offset->data_type,"I4") && strcmp(section[0][n].connect_offset->data_type,"I8")) { cgi_error("Datatype %s not supported for element 'ElementStartOffset'", section[0][n].connect_offset->data_type); return CG_ERROR; } } else if (strcmp(temp_name,"ParentData")==0) { if (section[0][n].parelem) { cgi_error("Error: Element ParentData defined more than once"); return CG_ERROR; } section[0][n].parelem = CGNS_NEW(cgns_array, 1); section[0][n].parelem->id = idi[i]; section[0][n].parelem->link = cgi_read_link(idi[i]); section[0][n].parelem->in_link = linked; if (cgi_read_array(section[0][n].parelem, "Elements_t", section[0][n].id)) return CG_ERROR; /* check data */ if (strcmp(section[0][n].parelem->data_type,"I4") && strcmp(section[0][n].parelem->data_type,"I8")) { cgi_error("Datatype %s not supported for element 'ParentData'", section[0][n].parelem->data_type); return CG_ERROR; } if(section[0][n].parelem->range[0] > 0 && section[0][n].parelem->range[1] > 0) pdata_cnt = section[0][n].parelem->range[1] - section[0][n].parelem->range[0] + 1; else pdata_cnt = nelements; if (section[0][n].parelem->dim_vals[0] != pdata_cnt || section[0][n].parelem->dim_vals[1] != 4 || section[0][n].parelem->data_dim != 2 ) { cgi_error("Error exit: Element 'ParentData' incorrectly defined"); return CG_ERROR; } } else if (strcmp(temp_name,"ParentElements")==0) { if (section[0][n].parelem) { cgi_error("Error: Element ParentElements defined more than once"); return CG_ERROR; } section[0][n].parelem = CGNS_NEW(cgns_array, 1); section[0][n].parelem->id = idi[i]; section[0][n].parelem->link = cgi_read_link(idi[i]); section[0][n].parelem->in_link = linked; if (cgi_read_array(section[0][n].parelem, "Elements_t", section[0][n].id)) return CG_ERROR; /* check data */ if (strcmp(section[0][n].parelem->data_type,"I4") && strcmp(section[0][n].parelem->data_type,"I8")) { cgi_error("Datatype %s not supported for element 'ParentElements'", section[0][n].parelem->data_type); return CG_ERROR; } if(section[0][n].parelem->range[0] > 0 && section[0][n].parelem->range[1] > 0) pdata_cnt = section[0][n].parelem->range[1] - section[0][n].parelem->range[0] + 1; else pdata_cnt = nelements; if (section[0][n].parelem->dim_vals[0] != pdata_cnt || section[0][n].parelem->dim_vals[1] != 2 || section[0][n].parelem->data_dim != 2 ) { cgi_error("Error exit: Element 'ParentElements' incorrectly defined"); return CG_ERROR; } } else if (strcmp(temp_name,"ParentElementsPosition")==0) { if (section[0][n].parface) { cgi_error("Error: Element ParentElementsPosition defined more than once"); return CG_ERROR; } section[0][n].parface = CGNS_NEW(cgns_array, 1); section[0][n].parface->id = idi[i]; section[0][n].parface->link = cgi_read_link(idi[i]); section[0][n].parface->in_link = linked; if (cgi_read_array(section[0][n].parface, "Elements_t", section[0][n].id)) return CG_ERROR; /* check data */ if (strcmp(section[0][n].parface->data_type,"I4") && strcmp(section[0][n].parface->data_type,"I8")) { cgi_error("Datatype %s not supported for element 'ParentElementsPosition'", section[0][n].parelem->data_type); return CG_ERROR; } if(section[0][n].parface->range[0] > 0 && section[0][n].parface->range[1] > 0) pdata_cnt = section[0][n].parface->range[1] - section[0][n].parface->range[0] + 1; else pdata_cnt = nelements; if (section[0][n].parface->dim_vals[0] != pdata_cnt || section[0][n].parface->dim_vals[1] != 2 || section[0][n].parface->data_dim != 2 ) { cgi_error("Error exit: Element 'ParentElementsPosition' incorrectly defined"); return CG_ERROR; } } } /* loop through DataArray_t */ /* check cgi_array_print("connect",section[0][n].connect); if (section[0][n].parent) cgi_array_print("parent",section[0][n].parent); */ if (nchild) CGNS_FREE(idi); if (section[0][n].connect == 0) { cgi_error("Error exit: ElementConnectivity undefined in Element_t node '%s'.", section[0][n].name); return CG_ERROR; } /* UserDefinedData_t */ if (cgi_read_user_data(linked, section[0][n].id, §ion[0][n].nuser_data, §ion[0][n].user_data)) return CG_ERROR; if (section[0][n].parelem != NULL && 0 == strcmp(section[0][n].parelem->name, "ParentData") && cg->mode == CG_MODE_MODIFY && !linked && cg->filetype != CG_FILE_ADF2) { void *pardata; pdata_cnt = section[0][n].parelem->dim_vals[0]; strcpy(data_type, section[0][n].parelem->data_type); if (0 == strcmp(data_type, "I8")) { pardata = malloc((size_t)(pdata_cnt * 4 * sizeof(cglong_t))); vdata = (void *)(((cglong_t *)pardata) + (pdata_cnt * 2)); } else { pardata = malloc((size_t)(pdata_cnt * 4 * sizeof(int))); vdata = (void *)(((int *)pardata) + (pdata_cnt * 2)); } if (pardata == NULL) { cgi_error("malloc failed for ParentData conversion array"); return CG_ERROR; } if (cgio_read_all_data(cg->cgio, section[0][n].parelem->id, pardata)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } if (cgi_delete_node(section[0][n].id, section[0][n].parelem->id)) return CG_ERROR; memset(section[0][n].parelem, 0, sizeof(cgns_array)); strcpy(section[0][n].parelem->data_type, data_type); strcpy(section[0][n].parelem->name, "ParentElements"); section[0][n].parelem->data_dim =2; section[0][n].parelem->dim_vals[0]=pdata_cnt; section[0][n].parelem->dim_vals[1]=2; if (cgi_write_array(section[0][n].id, section[0][n].parelem)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section[0][n].parelem->id, pardata)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } section[0][n].parface = CGNS_NEW(cgns_array, 1); strcpy(section[0][n].parface->data_type, data_type); strcpy(section[0][n].parface->name, "ParentElementsPosition"); section[0][n].parface->data_dim =2; section[0][n].parface->dim_vals[0]=pdata_cnt; section[0][n].parface->dim_vals[1]=2; if (cgi_write_array(section[0][n].id, section[0][n].parface)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section[0][n].parface->id, vdata)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } } /* loop through element sections */ CGNS_FREE(id); return CG_OK; } int cgi_read_sol(int in_link, double parent_id, int *nsols, cgns_sol **sol) { double *id, *idf; int s, z, n, linked; cgsize_t DataSize[3], DataCount = 0; if (cgi_get_nodes(parent_id, "FlowSolution_t", nsols, &id)) return CG_ERROR; if (*nsols<=0) { sol[0] = 0; return CG_OK; } sol[0] = CGNS_NEW(cgns_sol, (*nsols)); for (s=0; s<(*nsols); s++) { sol[0][s].id = id[s]; sol[0][s].link = cgi_read_link(id[s]); sol[0][s].in_link = in_link; linked = sol[0][s].link ? 1 : in_link; /* FlowSolution_t Name */ if (cgio_get_name(cg->cgio, sol[0][s].id, sol[0][s].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* GridLocation */ if (cgi_read_location(sol[0][s].id, sol[0][s].name, &sol[0][s].location)) return CG_ERROR; /* Rind Planes */ if (cgi_read_rind(sol[0][s].id, &sol[0][s].rind_planes)) return CG_ERROR; /* Determine data size */ if (cgi_datasize(Idim, CurrentDim, sol[0][s].location, sol[0][s].rind_planes, DataSize)) return CG_ERROR; /* check for PointList/PointRange */ if (cgi_read_one_ptset(linked, sol[0][s].id, &sol[0][s].ptset)) return CG_ERROR; if (sol[0][s].ptset != NULL) { if (sol[0][s].ptset->type == CGNS_ENUMV(ElementList) || sol[0][s].ptset->type == CGNS_ENUMV(ElementRange)) { cgi_error("ElementList/Range not supported under FlowSolution"); return CG_ERROR; } DataCount = sol[0][s].ptset->size_of_patch; } /* DataArray_t */ if (cgi_get_nodes(sol[0][s].id, "DataArray_t", &sol[0][s].nfields, &idf)) return CG_ERROR; if (sol[0][s].nfields > 0) { sol[0][s].field = CGNS_NEW(cgns_array, sol[0][s].nfields); for (z=0; zcgio, zc[i].id, zc[i].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* OversetHoles_t */ if (cgi_get_nodes(zc[i].id, "OversetHoles_t", &zc[i].nholes, &id)) return CG_ERROR; if (zc[i].nholes > 0) { zc[i].hole = CGNS_NEW(cgns_hole,zc[i].nholes); for (n=0; n 0) { zc[i].conn = CGNS_NEW(cgns_conn,zc[i].nconns); for (n=0; n0) { zc[i].one21 = CGNS_NEW(cgns_1to1, zc[i].n1to1); for (n=0; n0) { zc[i].descr = CGNS_NEW(cgns_descr, zc[i].ndescr); for (n=0; nlink ? 1 : one21->in_link; double *IA_id, *IR_id, *id; char_33 name, data_type; char *string_data; void *vdata; cgsize_t dim_vals[12]; /* get donor name */ if (cgi_read_string(one21->id, one21->name, &string_data)) return CG_ERROR; strcpy(one21->donor, string_data); CGNS_FREE(string_data); /* get ADF-ID of point sets for donor and receiver */ one21->ptset.id=0; one21->ptset.link=0; one21->dptset.id=0; one21->dptset.link=0; if (cgi_get_nodes(one21->id, "IndexRange_t", &nIR_t, &IR_id)) return CG_ERROR; for (i=0; icgio, IR_id[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointRange")==0) { if (one21->ptset.id==0) { one21->ptset.id=IR_id[i]; one21->ptset.link=cgi_read_link(IR_id[i]); one21->ptset.in_link=linked; one21->ptset.type=CGNS_ENUMV(PointRange); } else { cgi_error("Multiple PointRange definition for %s",one21->name); return CG_ERROR; } } else if (strcmp(name, "PointRangeDonor")==0) { if (one21->dptset.id==0) { one21->dptset.id=IR_id[i]; one21->dptset.link=cgi_read_link(IR_id[i]); one21->dptset.in_link=linked; one21->dptset.type=CGNS_ENUMV(PointRangeDonor); } else { cgi_error("Multiple PointRangeDonor definition for %s",one21->name); return CG_ERROR; } } } if (nIR_t>0) CGNS_FREE(IR_id); if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (one21->ptset.id==0 || one21->dptset.id==0) { cgi_error("PointRange or PointRangeDonor undefined for %s",one21->name); return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { /* * Convert the double id to a hid_t id and compare that to 0 instead of * comparing doubles, this avoids issues with comparing doubles when * compiler optimization is enabled. */ hid_t hid_ptset, hid_dptset; to_HDF_ID(one21->ptset.id,hid_ptset); to_HDF_ID(one21->dptset.id,hid_dptset); if (hid_ptset==0 || hid_dptset==0) { cgi_error("PointRange or PointRangeDonor undefined for %s",one21->name); return CG_ERROR; } } #endif else { return CG_ERROR; } /* Read Point set Receiver */ if (cgi_read_ptset(one21->id, &one21->ptset)) return CG_ERROR; /* Read Point set Donor */ if (cgi_read_ptset(one21->id, &one21->dptset)) return CG_ERROR; /* Get "int[IndexDimension]" children */ if (cgi_get_nodes(one21->id, "\"int[IndexDimension]\"", &nIA_t, &IA_id)) return CG_ERROR; if (nIA_t==0) { one21->transform = CGNS_NEW(int, Idim); /* set default transformation matrix to 1,2,3 */ for (i=0; itransform[i]=i+1; } else if (nIA_t<0 || nIA_t>1) { cgi_error("Invalid definition of transformation matrix for %s",one21->name); return CG_ERROR; } else if (nIA_t==1) { if (cgi_read_node(IA_id[0], name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading 1to1-connectivity transformation matrix"); return CG_ERROR; } one21->transform = (int *)vdata; /* verify plausibility of data */ if (strcmp("Transform", name)) { cgi_error("The ADF name should be 'Transform' and not '%s'",name); return CG_ERROR; } if (strcmp(data_type, "I4")!=0) { cgi_error("Data type '%s' not supported for Transform",data_type); return CG_ERROR; } if (ndim != 1 || dim_vals[0] != Idim) { cgi_error("Error in dimension for node type Transform"); return CG_ERROR; } for (i=0; itransform[i] >Idim || one21->transform[i] <(-1*Idim)) { cgi_error("Invalid transformation matrix"); return CG_ERROR; } } CGNS_FREE(IA_id); } /* Ordinal_t */ if (cgi_read_ordinal(one21->id, &one21->ordinal)) return CG_ERROR; /* Descriptor_t */ if (cgi_get_nodes(one21->id, "Descriptor_t", &one21->ndescr, &id)) return CG_ERROR; if (one21->ndescr>0) { one21->descr = CGNS_NEW(cgns_descr, one21->ndescr); for (n=0; nndescr; n++) { one21->descr[n].id = id[n]; one21->descr[n].link = cgi_read_link(id[n]); one21->descr[n].in_link = linked; if (cgi_read_string(id[n], one21->descr[n].name, &one21->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, one21->id, &one21->nuser_data, &one21->user_data)) return CG_ERROR; /* GridConnectivityProperty_t */ if (cgi_read_cprop(linked, one21->id, &one21->cprop)) return CG_ERROR; return CG_OK; } int cgi_read_conn(cgns_conn *conn) { int i, nchild; int linked = conn->link ? 1 : conn->in_link; char_33 name, parent_label; double *id, parent_id; char *string_data; /* allocated in cgi_read_node */ /* get donor name */ if (cgi_read_string(conn->id, conn->name, &string_data)) return CG_ERROR; if (cgi_check_strlen(string_data)) return CG_ERROR; strcpy(conn->donor, string_data); CGNS_FREE(string_data); /* GridLocation */ if (cgi_read_location(conn->id, conn->name, &conn->location)) return CG_ERROR; if (conn->location != CGNS_ENUMV(Vertex) && conn->location != CGNS_ENUMV(CellCenter) && conn->location != CGNS_ENUMV(FaceCenter) && conn->location != CGNS_ENUMV(IFaceCenter) && conn->location != CGNS_ENUMV(JFaceCenter) && conn->location != CGNS_ENUMV(KFaceCenter)) { cgi_error("Unsupported GridLocation %s for Connectivity %s", cg_GridLocationName(conn->location), conn->name); return CG_ERROR; } /* Receiver IndexArray_t ? */ conn->ptset.id=0; conn->ptset.link=0; if (cgi_get_nodes(conn->id, "IndexArray_t", &nchild, &id)) return CG_ERROR; for (i=0; icgio, id[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointList")==0) { if (conn->ptset.id==0) { conn->ptset.id=id[i]; conn->ptset.link=cgi_read_link(id[i]); conn->ptset.in_link=linked; conn->ptset.type=CGNS_ENUMV( PointList ); if (cgi_read_ptset(conn->id, &conn->ptset)) return CG_ERROR; } else { cgi_error("Multiple PointList definition for %s",conn->name); return CG_ERROR; } } } if (nchild>0) CGNS_FREE(id); /* Receiver IndexRange_t ? */ if (cgi_get_nodes(conn->id, "IndexRange_t", &nchild, &id)) return CG_ERROR; for (i=0; icgio, id[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointRange")==0) { if (conn->ptset.id==0) { conn->ptset.id=id[i]; conn->ptset.link=cgi_read_link(id[i]); conn->ptset.in_link=linked; conn->ptset.type=CGNS_ENUMV( PointRange ); if (cgi_read_ptset(conn->id, &conn->ptset)) return CG_ERROR; } else { cgi_error("Multiple PointSet definition for %s",conn->name); return CG_ERROR; } } } if (nchild>0) CGNS_FREE(id); /* check */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (conn->ptset.id==0) { cgi_error("Niether PointRange nor PointList defined for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(conn->ptset.id, hid); if (hid==0) { cgi_error("Niether PointRange nor PointList defined for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } } #endif else { return CG_ERROR; } /* Find the parent node for Donor IndexArray_t */ parent_id = 0; parent_label[0]='\0'; if (cg->version <1100 || cg->version>1200) { /* Version 1.05 and 1.27+ put IndexArray_t directly under GridConnectivity_t */ parent_id = conn->id; strcpy(parent_label,"GridConnectivity_t"); } else { /* version 1.1 to 1.20 used intermediate structures StructuredDonor_t & UnstructuredDonor_t */ if (cgi_get_nodes(conn->id, "StructuredDonor_t", &nchild, &id)) return CG_ERROR; if (nchild>1) { cgi_error("StructuredDonor_t defined more than once for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } else if (nchild==1) { parent_id = id[0]; strcpy(parent_label,"StructuredDonor_t"); CGNS_FREE(id); } if (cgi_get_nodes(conn->id, "UnstructuredDonor_t", &nchild, &id)) return CG_ERROR; if (nchild>1) { cgi_error("UnstructuredDonor_t defined more than once for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } else if (nchild==1) { if (parent_id) { cgi_error("Multiple donors found under GridConnectivity_t '%s'",conn->name); return CG_ERROR; } parent_id = id[0]; strcpy(parent_label,"UnstructuredDonor_t"); CGNS_FREE(id); } if (!parent_id) { cgi_error("Error: Donor data undefined for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } } /* Read Donor IndexArray_t */ conn->dptset.id=0; conn->dptset.link=0; if (cgi_get_nodes(parent_id, "IndexArray_t", &nchild, &id)) return CG_ERROR; for (i=0; icgio, id[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointListDonor") && strcmp(name, "CellListDonor")) continue; if (conn->dptset.id==0) { conn->dptset.id=id[i]; conn->dptset.link=cgi_read_link(id[i]); conn->dptset.in_link=linked; if (strcmp(name, "PointListDonor")==0) conn->dptset.type=CGNS_ENUMV( PointListDonor ); else { if (strcmp(parent_label,"StructuredDonor_t")==0) { cgi_error("StructuredDonor_t doesn't support CellListDonor"); return CG_ERROR; } conn->dptset.type=CGNS_ENUMV( CellListDonor ); } if (cgi_read_ptset(parent_id, &conn->dptset)) return CG_ERROR; } else { cgi_error("Multiple PointListDonor/CellListDonor definition for %s",conn->name); return CG_ERROR; } } if (nchild>0) CGNS_FREE(id); /* if (conn->dptset.id==0) { cgi_error("Error: Donor patch undefined for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } */ /* Read InterpolantsDonor if it exist */ conn->interpolants=0; conn->narrays = 0; if (strcmp(parent_label,"StructuredDonor_t")) { if (cgi_get_nodes(parent_id, "DataArray_t", &nchild, &id)) return CG_ERROR; conn->narrays = nchild; for (i=0; icgio, id[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "InterpolantsDonor")) continue; if (conn->interpolants==0) { conn->interpolants = CGNS_NEW(cgns_array, 1); conn->interpolants->id = id[0]; conn->interpolants->link = cgi_read_link(id[0]); conn->interpolants->in_link = linked; if (cgi_read_array(conn->interpolants, parent_label, parent_id)) return CG_ERROR; } else { cgi_error("InterpolantsDonor defined more than once for GridConnectivity_t '%s'", conn->name); return CG_ERROR; } } if (nchild) CGNS_FREE(id); } /* Get GridConnectivityType_t (conn->type) */ if (cgi_get_nodes(conn->id, "GridConnectivityType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { conn->type = CGNS_ENUMV( Overset ); } else if (nchild<0 || nchild>1) { cgi_error("Invalid definition of GridConnectivityType_t for %s",conn->name); return CG_ERROR; } else if (nchild==1) { /* Read the grid connectivity type value in the GridConnectivityType_t node */ if (cgi_read_string(id[0], name, &string_data)) return CG_ERROR; if (cgi_GridConnectivityType(string_data, &conn->type)) return CG_ERROR; CGNS_FREE(string_data); } if (nchild) CGNS_FREE(id); /* update the version */ if (cg->mode == CG_MODE_MODIFY && !linked && cg->version >= 1100 && cg->version <= 1200) { if (cgio_move_node(cg->cgio, parent_id, conn->dptset.id, conn->id)) { cg_io_error("cgio_move_node"); return CG_ERROR; } if (conn->interpolants) { if (cgio_move_node(cg->cgio, parent_id, conn->interpolants->id, conn->id)) { cg_io_error("cgio_move_node"); return CG_ERROR; } } if (cgi_delete_node(conn->id, parent_id)) return CG_ERROR; } /* Ordinal_t */ conn->ordinal=0; if (cgi_read_ordinal(conn->id, &conn->ordinal)) return CG_ERROR; /* Descriptor_t */ if (cgi_get_nodes(conn->id, "Descriptor_t", &conn->ndescr, &id)) return CG_ERROR; if (conn->ndescr>0) { conn->descr = CGNS_NEW(cgns_descr, conn->ndescr); for (i=0; indescr; i++) { conn->descr[i].id = id[i]; conn->descr[i].link = cgi_read_link(id[i]); conn->descr[i].in_link = linked; if (cgi_read_string(id[i], conn->descr[i].name, &conn->descr[i].text)) return CG_ERROR; } CGNS_FREE(id); } /* GridConnectivityProperty_t */ if (cgi_read_cprop(linked, conn->id, &conn->cprop)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, conn->id, &conn->nuser_data, &conn->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_cprop(int in_link, double parent_id, cgns_cprop **cprop) { int nchild, n, linked; double *id; char *type_name; /* allocated in cgi_read_node */ char_33 name; /* get number of GridConnectivityProperty_t nodes and their ID */ if (cgi_get_nodes(parent_id, "GridConnectivityProperty_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { cprop[0]=0; return CG_OK; } else if (nchild>1) { cgi_error("Error: Multiple GridConnectivityProperty_t found..."); CGNS_FREE(id); return CG_ERROR; } cprop[0] = CGNS_NEW(cgns_cprop, 1); cprop[0]->id = id[0]; cprop[0]->link = cgi_read_link(id[0]); cprop[0]->in_link = in_link; linked = cprop[0]->link ? 1 : in_link; CGNS_FREE(id); /* Descriptor_t */ if (cgi_get_nodes(cprop[0]->id, "Descriptor_t", &nchild, &id)) return CG_ERROR; cprop[0]->ndescr = 0; if (nchild>0) { cprop[0]->ndescr = nchild; cprop[0]->descr = CGNS_NEW(cgns_descr, nchild); for (n=0; ndescr[n].id = id[n]; cprop[0]->descr[n].link = cgi_read_link(id[n]); cprop[0]->descr[n].in_link = linked; if (cgi_read_string(id[n], cprop[0]->descr[n].name, &cprop[0]->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, cprop[0]->id, &cprop[0]->nuser_data, &cprop[0]->user_data)) return CG_ERROR; /* AverageInterface_t */ if (cgi_get_nodes(cprop[0]->id, "AverageInterface_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { cprop[0]->caverage = 0; } else if (nchild>1) { cgi_error("Error: Multiple AverageInterface_t found..."); CGNS_FREE(id); return CG_ERROR; } else { cprop[0]->caverage = CGNS_NEW(cgns_caverage, 1); cprop[0]->caverage->id = id[0]; cprop[0]->caverage->link = cgi_read_link(id[0]); cprop[0]->caverage->in_link = linked; in_link = cprop[0]->caverage->link ? 1 : linked; CGNS_FREE(id); /* Descriptor_t */ if (cgi_get_nodes(cprop[0]->caverage->id, "Descriptor_t", &nchild, &id)) return CG_ERROR; cprop[0]->caverage->ndescr = 0; if (nchild>0) { cprop[0]->caverage->ndescr = nchild; cprop[0]->caverage->descr = CGNS_NEW(cgns_descr, nchild); for (n=0; ncaverage->descr[n].id = id[n]; cprop[0]->caverage->descr[n].link = cgi_read_link(id[n]); cprop[0]->caverage->descr[n].in_link = in_link; if (cgi_read_string(id[n], cprop[0]->caverage->descr[n].name, &cprop[0]->caverage->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(in_link, cprop[0]->caverage->id, &cprop[0]->caverage->nuser_data, &cprop[0]->caverage->user_data)) return CG_ERROR; /* AverageInterfaceType_t */ if (cgi_get_nodes(cprop[0]->caverage->id, "AverageInterfaceType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { cgi_error("Error: AverageInterfaceType_t missing under AverageInterface_t"); return CG_ERROR; } else if (nchild >1) { cgi_error("File incorrect: multiple definition of AverageInterfaceType"); CGNS_FREE(id); return CG_ERROR; } else { if (cgi_read_string(id[0], name, &type_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_AverageInterfaceType(type_name, &cprop[0]->caverage->type)) return CG_ERROR; CGNS_FREE(type_name); } } /* Periodic_t */ if (cgi_get_nodes(cprop[0]->id, "Periodic_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { cprop[0]->cperio = 0; } else if (nchild>1) { cgi_error("Error: Multiple Periodic_t found..."); CGNS_FREE(id); return CG_ERROR; } else { cprop[0]->cperio = CGNS_NEW(cgns_cperio, 1); cprop[0]->cperio->id = id[0]; cprop[0]->cperio->link = cgi_read_link(id[0]); cprop[0]->cperio->in_link = linked; in_link = cprop[0]->cperio->link ? 1 : linked; CGNS_FREE(id); /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(in_link, cprop[0]->cperio->id, &cprop[0]->cperio->ndescr, &cprop[0]->cperio->descr, &cprop[0]->cperio->data_class, &cprop[0]->cperio->units)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(in_link, cprop[0]->cperio->id, &cprop[0]->cperio->nuser_data, &cprop[0]->cperio->user_data)) return CG_ERROR; /* DataArray_t: RotationCenter, RotationAngle, Translation: */ if (cgi_get_nodes(cprop[0]->cperio->id, "DataArray_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { cgi_error("Error: Three DataArray_t nodes missing under Periodic_t"); return CG_ERROR; } else if (nchild!=3) { cgi_error("Error: 3 DataArray_t required under Periodic_t"); CGNS_FREE(id); return CG_ERROR; } cprop[0]->cperio->narrays = nchild; cprop[0]->cperio->array = CGNS_NEW(cgns_array, cprop[0]->cperio->narrays); for (n=0; n<(cprop[0]->cperio->narrays); n++) { cgns_array *array; cprop[0]->cperio->array[n].id = id[n]; cprop[0]->cperio->array[n].link = cgi_read_link(id[n]); cprop[0]->cperio->array[n].in_link = in_link; if (cgi_read_array(&cprop[0]->cperio->array[n], "Periodic_t", cprop[0]->cperio->id)) return CG_ERROR; array = &cprop[0]->cperio->array[n]; /* check data */ if (strcmp("RotationCenter",array->name) && strcmp("RotationAngle",array->name) && strcmp("Translation",array->name)) { cgi_error("Error: Wrong DataArray_t found under Periodic_t: '%s'",array->name); CGNS_FREE(id); return CG_ERROR; } else if (strcmp(array->data_type,"R4") || array->data_dim!=1 || array->dim_vals[0]!=Pdim) { cgi_error("Error: Array '%s' incorrectly sized",array->name); CGNS_FREE(id); return CG_ERROR; } } /* loop through arrays */ CGNS_FREE(id); } return CG_OK; } int cgi_read_hole(cgns_hole *hole) { int linked = hole->link ? 1 : hole->in_link; int nIA_t, nIR_t; double *IA_id, *IR_id, *id; int set, n; /* name of OversetHoles_t Node */ if (cgio_get_name(cg->cgio, hole->id, hole->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* GridLocation */ if (cgi_read_location(hole->id, hole->name, &hole->location)) return CG_ERROR; if (hole->location != CGNS_ENUMV( Vertex ) && hole->location != CGNS_ENUMV( CellCenter )) { cgi_error("Unsupported GridLocation %s for Overset Hole %s", cg_GridLocationName(hole->location), hole->name); return CG_ERROR; } /* get number of IndexArray_t and IndexRange_t nodes and their ID */ if (cgi_get_nodes(hole->id, "IndexArray_t", &nIA_t, &IA_id)) return CG_ERROR; if (cgi_get_nodes(hole->id, "IndexRange_t", &nIR_t, &IR_id)) return CG_ERROR; /* Hole defined with several PointRange */ if (nIA_t==0 && nIR_t>0) { hole->nptsets = nIR_t; hole->ptset = CGNS_NEW(cgns_ptset, nIR_t); for (set=0; setptset[set].id = IR_id[set]; hole->ptset[set].link = cgi_read_link(IR_id[set]); hole->ptset[set].in_link = linked; hole->ptset[set].type = CGNS_ENUMV( PointRange ); if (cgi_read_ptset(hole->id, &hole->ptset[set])) return CG_ERROR; } CGNS_FREE(IR_id); /* Hole defined with one single PointList */ } else if (nIA_t==1 && nIR_t==0) { hole->nptsets = 1; hole->ptset = CGNS_NEW(cgns_ptset, 1); hole->ptset[0].id = IA_id[0]; hole->ptset[0].link = cgi_read_link(IA_id[0]); hole->ptset[0].in_link = linked; hole->ptset[0].type = CGNS_ENUMV( PointList ); if (cgi_read_ptset(hole->id, &hole->ptset[0])) return CG_ERROR; CGNS_FREE(IA_id); /* Empty hole (requested by Cetin) */ } else if (nIA_t==0 && nIR_t==0) { hole->nptsets = 1; hole->ptset = CGNS_NEW(cgns_ptset, 1); hole->ptset[0].npts = 0; hole->ptset[0].type = CGNS_ENUMV( PointList ); /* initialize */ strcpy(hole->ptset[0].data_type, "I4"); hole->ptset[0].id = 0; hole->ptset[0].link = 0; hole->ptset[0].in_link = linked; strcpy(hole->ptset[0].name,"Empty"); } else { cgi_error("Overset hole '%s' defined incorrectly with %d IndexArray_t and %d IndexRange_t.", hole->name, nIA_t, nIR_t); return CG_ERROR; } /* Descriptor_t */ if (cgi_get_nodes(hole->id, "Descriptor_t", &hole->ndescr, &id)) return CG_ERROR; if (hole->ndescr>0) { hole->descr = CGNS_NEW(cgns_descr, hole->ndescr); for (n=0; nndescr; n++) { hole->descr[n].id = id[n]; hole->descr[n].link = cgi_read_link(id[n]); hole->descr[n].in_link = linked; if (cgi_read_string(id[n], hole->descr[n].name, &hole->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, hole->id, &hole->nuser_data, &hole->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_zboco(int in_link, double parent_id, cgns_zboco **zboco) { int nnod, n, linked; double *id; if (cgi_get_nodes(parent_id, "ZoneBC_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { zboco[0] = 0; return CG_OK; } zboco[0] = CGNS_NEW(cgns_zboco, 1); zboco[0]->id = id[0]; zboco[0]->link = cgi_read_link(id[0]); zboco[0]->in_link = in_link; linked = zboco[0]->link ? 1 : in_link; CGNS_FREE(id); /* Name */ if (cgio_get_name(cg->cgio, zboco[0]->id, zboco[0]->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* get number of BC_t */ if (cgi_get_nodes(zboco[0]->id, "BC_t", &zboco[0]->nbocos, &id)) return CG_ERROR; if (zboco[0]->nbocos > 0) { zboco[0]->boco = CGNS_NEW(cgns_boco,zboco[0]->nbocos); for (n=0; nnbocos; n++) { zboco[0]->boco[n].id = id[n]; zboco[0]->boco[n].link = cgi_read_link(id[n]); zboco[0]->boco[n].in_link = linked; if (cgi_read_boco(&zboco[0]->boco[n])) return CG_ERROR; } /* loop through BC_t nodes */ CGNS_FREE(id); } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, zboco[0]->id, &zboco[0]->ndescr, &zboco[0]->descr, &zboco[0]->data_class, &zboco[0]->units)) return CG_ERROR; /* ReferenceState_t */ if (cgi_read_state(linked, zboco[0]->id, &zboco[0]->state)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, zboco[0]->id, &zboco[0]->nuser_data, &zboco[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_boco(cgns_boco *boco) { int ierr=0, modified = 0; int linked = boco->link ? 1 : boco->in_link; int nIA_t, n, i; double *IA_id, *id; char *boconame; char_33 name, data_type; cgns_ptset *ptset; int ndim; cgsize_t dim_vals[12]; void *vdata; /* get BC_t */ if (cgi_read_string(boco->id, boco->name, &boconame) || cgi_BCType(boconame, &boco->type)) return CG_ERROR; CGNS_FREE(boconame); /* GridLocation_t */ if (cg->version > 1200) { if (cgi_read_location(boco->id, boco->name, &boco->location)) return CG_ERROR; } else { /* Until version 1.2, GridLocation was under BCDataSet_t */ if (boco->ndataset) { /* Wild assumption that all BCDataSet have same GridLocation_t value */ if (cgi_read_location(boco->dataset[0].id, boco->dataset[0].name, &boco->location)) return CG_ERROR; } else { boco->location= CGNS_ENUMV(Vertex); } } /* read point set */ if (cgi_read_one_ptset(linked, boco->id, &boco->ptset)) return CG_ERROR; if (boco->ptset == 0) { cgi_error("Boundary condition patch '%s' not defined",boco->name); return CG_ERROR; } #ifdef CG_FIX_ELEMENTLIST_RANGE /* fix ElementList/Range - no longer allowed (CPEX 0031) */ if (boco->ptset->type == CGNS_ENUMV(ElementList) || boco->ptset->type == CGNS_ENUMV(ElementRange)) { modified++; if (boco->ptset->type == CGNS_ENUMV(ElementList)) { boco->ptset->type = CGNS_ENUMV(PointList); strcpy(boco->ptset->name, "PointList"); } else { boco->ptset->type = CGNS_ENUMV(PointRange); strcpy(boco->ptset->name, "PointRange"); } if (Cdim == 1) boco->location = CGNS_ENUMV(Vertex); else if (Cdim == 2) boco->location = CGNS_ENUMV(EdgeCenter); else boco->location = CGNS_ENUMV(FaceCenter); } #endif /* fix GridLocation */ #ifdef CG_FIX_BC_CELL_CENTER if (boco->location == CGNS_ENUMV(CellCenter)) { if (Cdim == 1) boco->location = CGNS_ENUMV(Vertex); else if (Cdim == 2) boco->location = CGNS_ENUMV(EdgeCenter); else boco->location = CGNS_ENUMV(FaceCenter); cgi_warning("GridLocation CellCenter for BC_t is deprecated - " "changed to %s", GridLocationName[boco->location]); modified++; } #endif /* FamilyName_t */ if (cgi_read_family_name(linked, boco->id, boco->name, boco->family_name)) return CG_ERROR; /* CPEX 0034 */ if (cgi_get_nodes(boco->id, "AdditionalFamilyName_t", &boco->nfamname, &id)) return CG_ERROR; if (boco->nfamname > 0) { char *fam; boco->famname = CGNS_NEW(cgns_famname, boco->nfamname); for (n = 0; n < boco->nfamname; n++) { boco->famname[n].id = id[n]; if (cgi_read_string(id[n], boco->famname[n].name, &fam)) return CG_ERROR; strncpy(boco->famname[n].family, fam, 32); CGNS_FREE(fam); } CGNS_FREE(id); } /* InwardNormalList */ boco->normal = 0; if (cgi_get_nodes(boco->id, "IndexArray_t", &nIA_t, &IA_id)) return CG_ERROR; for (n=0; ncgio, IA_id[n], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "InwardNormalList")) continue; boco->normal = CGNS_NEW(cgns_array, 1); boco->normal->id = IA_id[n]; boco->normal->link = cgi_read_link(IA_id[n]); boco->normal->in_link = linked; if (cgi_read_node(IA_id[n], boco->normal->name, boco->normal->data_type, &boco->normal->data_dim, boco->normal->dim_vals, &boco->normal->data, READ_DATA)) { cgi_error("Error reading boco->normal"); return CG_ERROR; } /* set to NULL useless elements of data structure */ boco->normal->ndescr = 0; boco->normal->units = 0; boco->normal->exponents = 0; boco->normal->convert = 0; /* data verify */ if (boco->normal->data_dim!=2 || boco->normal->dim_vals[0]!=Pdim || boco->normal->dim_vals[1]!=boco->ptset->size_of_patch || (strcmp(boco->normal->data_type,"R4") && strcmp(boco->normal->data_type,"R8"))) { /*printf("boco->normal->dim_vals[1]=%d, boco->ptset->size_of_patch=%d\n", boco->normal->dim_vals[1],boco->ptset->size_of_patch);*/ cgi_error("InwardNormalList incorrectly defined for BC_t '%s'",boco->name); return CG_ERROR; } break; } if (nIA_t) CGNS_FREE(IA_id); /* InwardNormalIndex */ boco->Nindex = 0; if (cgi_get_nodes(boco->id, "\"int[IndexDimension]\"", &nIA_t, &IA_id)) return CG_ERROR; for (n=0; ncgio, IA_id[n], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "InwardNormalIndex")) continue; boco->index_id=IA_id[n]; if (cgi_read_node(IA_id[n], name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) return CG_ERROR; if (strcmp(data_type,"I4")!=0 || dim_vals[0]!=Idim) { cgi_error("InwardNormalIndex incorrectly defined for BC_t '%s'",boco->name); return CG_ERROR; } boco->Nindex = (int *)vdata; break; } if (nIA_t) CGNS_FREE(IA_id); /* BCDataSet_t */ if (cgi_read_dataset(linked, boco->id, &boco->ndataset, &boco->dataset)) return CG_ERROR; /* Verify that BCData for Dirichlet/Neumann contains the right number of data */ for (n=0; nndataset; n++) { ptset = boco->dataset[n].ptset ? boco->dataset[n].ptset : boco->ptset; if (boco->dataset[n].dirichlet) { for (i=0; idataset[n].dirichlet->narrays; i++) { cgns_array array = boco->dataset[n].dirichlet->array[i]; if (array.data_dim!=1 || (array.dim_vals[0] != 1 && array.dim_vals[0] != ptset->size_of_patch)) { cgi_error("Wrong array size for Dirichlet data"); return CG_ERROR; } } } if (boco->dataset[n].neumann) { for (i=0; idataset[n].neumann->narrays; i++) { cgns_array array = boco->dataset[n].neumann->array[i]; if (array.data_dim!=1 || (array.dim_vals[0] != 1 && array.dim_vals[0] != ptset->size_of_patch)) { cgi_error("Wrong array size for Neumann data"); return CG_ERROR; } } } } if ((cg->version <= 1270 || modified) && cg->mode == CG_MODE_MODIFY && !linked) { double dummy_id; /* fix point set name */ if (cgio_get_name(cg->cgio, boco->ptset->id, name) || strcmp(name, boco->ptset->name)) { if (cgio_set_name(cg->cgio, boco->id, boco->ptset->id, boco->ptset->name)) { cg_io_error("cgio_set_name"); return CG_ERROR; } } /* fix grid location */ ierr = cgio_get_node_id(cg->cgio, boco->id, "GridLocation", &dummy_id); if (!ierr) cgi_delete_node(boco->id, dummy_id); if (boco->location != CGNS_ENUMV(Vertex)) { const char *locname = GridLocationName[boco->location]; cgsize_t len = (cgsize_t)strlen(locname); if (cgi_new_node(boco->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &len, locname)) return CG_ERROR; } } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, boco->id, &boco->ndescr, &boco->descr, &boco->data_class, &boco->units)) return CG_ERROR; /* ReferenceState_t */ if (cgi_read_state(linked, boco->id, &boco->state)) return CG_ERROR; /* Ordinal_t */ if (cgi_read_ordinal(boco->id, &boco->ordinal)) return CG_ERROR; /* BCProperty_t */ if (cgi_read_bprop(linked, boco->id, &boco->bprop)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, boco->id, &boco->nuser_data, &boco->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_bprop(int in_link, double parent_id, cgns_bprop **bprop) { int nchild, n, linked; double *id; char *type_name; /* allocated in cgi_read_node */ char_33 name; /* get number of BCProperty_t nodes and their ID */ if (cgi_get_nodes(parent_id, "BCProperty_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { bprop[0]=0; return CG_OK; } else if (nchild>1) { cgi_error("Error: Multiple BCProperty_t found..."); CGNS_FREE(id); return CG_ERROR; } bprop[0] = CGNS_NEW(cgns_bprop, 1); bprop[0]->id = id[0]; bprop[0]->link = cgi_read_link(id[0]); bprop[0]->in_link = in_link; linked = bprop[0]->link ? 1 : in_link; CGNS_FREE(id); /* Descriptor_t */ if (cgi_get_nodes(bprop[0]->id, "Descriptor_t", &nchild, &id)) return CG_ERROR; bprop[0]->ndescr = 0; if (nchild>0) { bprop[0]->ndescr = nchild; bprop[0]->descr = CGNS_NEW(cgns_descr, nchild); for (n=0; ndescr[n].id = id[n]; bprop[0]->descr[n].link = cgi_read_link(id[n]); bprop[0]->descr[n].in_link = linked; if (cgi_read_string(id[n], bprop[0]->descr[n].name, &bprop[0]->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, bprop[0]->id, &bprop[0]->nuser_data, &bprop[0]->user_data)) return CG_ERROR; /* WallFunction_t */ if (cgi_get_nodes(bprop[0]->id, "WallFunction_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { bprop[0]->bcwall = 0; } else if (nchild>1) { cgi_error("Error: Multiple WallFunction_t found..."); CGNS_FREE(id); return CG_ERROR; } else { bprop[0]->bcwall = CGNS_NEW(cgns_bcwall, 1); bprop[0]->bcwall->id = id[0]; bprop[0]->bcwall->link = cgi_read_link(id[0]); bprop[0]->bcwall->in_link = linked; in_link = bprop[0]->bcwall->link ? 1 : linked; CGNS_FREE(id); /* Descriptor_t */ if (cgi_get_nodes(bprop[0]->bcwall->id, "Descriptor_t", &nchild, &id)) return CG_ERROR; bprop[0]->bcwall->ndescr = 0; if (nchild>0) { bprop[0]->bcwall->ndescr = nchild; bprop[0]->bcwall->descr = CGNS_NEW(cgns_descr, nchild); for (n=0; nbcwall->descr[n].id = id[n]; bprop[0]->bcwall->descr[n].link = cgi_read_link(id[n]); bprop[0]->bcwall->descr[n].in_link = in_link; if (cgi_read_string(id[n], bprop[0]->bcwall->descr[n].name, &bprop[0]->bcwall->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(in_link, bprop[0]->bcwall->id, &bprop[0]->bcwall->nuser_data, &bprop[0]->bcwall->user_data)) return CG_ERROR; /* WallFunctionType_t */ if (cgi_get_nodes(bprop[0]->bcwall->id, "WallFunctionType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { cgi_error("Error: WallFunctionType_t missing under WallFunction_t"); return CG_ERROR; } else if (nchild >1) { cgi_error("File incorrect: multiple definition of WallFunctionType"); CGNS_FREE(id); return CG_ERROR; } else { if (cgi_read_string(id[0], name, &type_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_WallFunctionType(type_name, &bprop[0]->bcwall->type)) return CG_ERROR; CGNS_FREE(type_name); } } /* Area_t */ if (cgi_get_nodes(bprop[0]->id, "Area_t", &nchild, &id)) return CG_ERROR; if (nchild<=0) { bprop[0]->bcarea = 0; } else if (nchild>1) { cgi_error("Error: Multiple Area_t found..."); CGNS_FREE(id); return CG_ERROR; } else { bprop[0]->bcarea = CGNS_NEW(cgns_bcarea, 1); bprop[0]->bcarea->id = id[0]; bprop[0]->bcarea->link = cgi_read_link(id[0]); bprop[0]->bcarea->in_link = linked; in_link = bprop[0]->bcarea->link ? 1 : linked; CGNS_FREE(id); /* Descriptor_t */ if (cgi_get_nodes(bprop[0]->bcarea->id, "Descriptor_t", &nchild, &id)) return CG_ERROR; bprop[0]->bcarea->ndescr = 0; if (nchild>0) { bprop[0]->bcarea->ndescr = nchild; bprop[0]->bcarea->descr = CGNS_NEW(cgns_descr, nchild); for (n=0; nbcarea->descr[n].id = id[n]; bprop[0]->bcarea->descr[n].link = cgi_read_link(id[n]); bprop[0]->bcarea->descr[n].in_link = in_link; if (cgi_read_string(id[n], bprop[0]->bcarea->descr[n].name, &bprop[0]->bcarea->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(in_link, bprop[0]->bcarea->id, &bprop[0]->bcarea->nuser_data, &bprop[0]->bcarea->user_data)) return CG_ERROR; /* AreaType_t */ if (cgi_get_nodes(bprop[0]->bcarea->id, "AreaType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { cgi_error("Error: AreaType_t missing under Area_t"); return CG_ERROR; } else if (nchild >1) { cgi_error("File incorrect: multiple definition of AreaType"); CGNS_FREE(id); return CG_ERROR; } else { if (cgi_read_string(id[0], name, &type_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_AreaType(type_name, &bprop[0]->bcarea->type)) return CG_ERROR; CGNS_FREE(type_name); } /* DataArray_t: SurfaceArea , RegionName */ if (cgi_get_nodes(bprop[0]->bcarea->id, "DataArray_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { cgi_error("Error: SurfaceArea and RegionName missing under Area_t"); return CG_ERROR; } else if (nchild!=2) { cgi_error("Error: 2 DataArray_t (SurfaceArea & RegionName) required under Area_t"); CGNS_FREE(id); return CG_ERROR; } bprop[0]->bcarea->narrays = nchild; bprop[0]->bcarea->array = CGNS_NEW(cgns_array, bprop[0]->bcarea->narrays); for (n=0; n<(bprop[0]->bcarea->narrays); n++) { cgns_array *array; bprop[0]->bcarea->array[n].id = id[n]; bprop[0]->bcarea->array[n].link = cgi_read_link(id[n]); bprop[0]->bcarea->array[n].in_link = in_link; if (cgi_read_array(&bprop[0]->bcarea->array[n], "Area_t", bprop[0]->bcarea->id)) return CG_ERROR; /* check data */ array = &bprop[0]->bcarea->array[n]; if ((strcmp("SurfaceArea",array->name)==0 && (strcmp(array->data_type,"R4") || array->data_dim!=1 || array->dim_vals[0]!=1)) || (strcmp("RegionName",array->name)==0 && (strcmp(array->data_type,"C1") || array->data_dim!=1 || array->dim_vals[0]!=32)) ){ cgi_error("Error: Array '%s' incorrectly sized",array->name); CGNS_FREE(id); return CG_ERROR; } else if (strcmp("SurfaceArea",array->name) && strcmp("RegionName",array->name)) { cgi_error("Error: Wrong DataArray_t found under Area_t: '%s'",array->name); CGNS_FREE(id); return CG_ERROR; } } /* loop through arrays */ CGNS_FREE(id); } return CG_OK; } int cgi_read_dataset(int in_link, double parent_id, int *ndataset, cgns_dataset **dataset) { int n, i, nnod, linked; double *id, *ids; char_33 name; char *string_data; double *IA_id, *IR_id; int nIA_t, nIR_t, nn; /* BCDataSet_t */ if (cgi_get_nodes(parent_id, "BCDataSet_t", ndataset, &id)) return CG_ERROR; if (*ndataset<=0) { dataset[0]=0; return CG_OK; } dataset[0]=CGNS_NEW(cgns_dataset, (*ndataset)); for (n=0; n<*ndataset; n++) { dataset[0][n].id = id[n]; dataset[0][n].link = cgi_read_link(id[n]); dataset[0][n].in_link = in_link; linked = dataset[0][n].link ? 1 : in_link; if (cgi_read_string(dataset[0][n].id, dataset[0][n].name, &string_data) || cgi_BCType(string_data, &dataset[0][n].type)) return CG_ERROR; CGNS_FREE(string_data); /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, dataset[0][n].id, &dataset[0][n].ndescr, &dataset[0][n].descr, &dataset[0][n].data_class, &dataset[0][n].units)) return CG_ERROR; /* ReferenceState_t */ if (cgi_read_state(linked, dataset[0][n].id, &dataset[0][n].state)) return CG_ERROR; /* BCData_t */ dataset[0][n].dirichlet=dataset[0][n].neumann=0; if (cgi_get_nodes(dataset[0][n].id, "BCData_t", &nnod, &ids)) return CG_ERROR; if (nnod>0) { for (i=0; icgio, ids[i], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"DirichletData")==0) { if (dataset[0][n].dirichlet!=0) { cgi_error("Dirichet Data defined more than once..."); return CG_ERROR; } dataset[0][n].dirichlet=CGNS_NEW(cgns_bcdata, 1); dataset[0][n].dirichlet->id = ids[i]; dataset[0][n].dirichlet->link = cgi_read_link(ids[i]); dataset[0][n].dirichlet->in_link = linked; strcpy(dataset[0][n].dirichlet->name,"DirichletData"); if (cgi_read_bcdata(dataset[0][n].dirichlet)) return CG_ERROR; } else if (strcmp(name,"NeumannData")==0) { if (dataset[0][n].neumann!=0) { cgi_error("Neumann Data defined more than once..."); return CG_ERROR; } dataset[0][n].neumann=CGNS_NEW(cgns_bcdata, 1); dataset[0][n].neumann->id = ids[i]; dataset[0][n].neumann->link = cgi_read_link(ids[i]); dataset[0][n].neumann->in_link = linked; strcpy(dataset[0][n].neumann->name,"NeumannData"); if (cgi_read_bcdata(dataset[0][n].neumann)) return CG_ERROR; } } CGNS_FREE(ids); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, dataset[0][n].id, &dataset[0][n].nuser_data, &dataset[0][n].user_data)) return CG_ERROR; /* GridLocation_t */ if (cgi_read_location(dataset[0][n].id, dataset[0][n].name, &dataset[0][n].location)) return CG_ERROR; /* PointSet */ /* get number of IndexArray_t and IndexRange_t nodes and their * ID */ if (cgi_get_nodes(dataset[0][n].id, "IndexArray_t", &nIA_t, &IA_id)) return CG_ERROR; if (cgi_get_nodes(dataset[0][n].id, "IndexRange_t", &nIR_t, &IR_id)) return CG_ERROR; /* initialized */ dataset[0][n].ptset = 0; for (nn=0; nncgio, IR_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"PointRange") && strcmp(name,"ElementRange")) { cgi_error("Invalid name for IndexRange_t"); return CG_ERROR; } if (dataset[0][n].ptset!=0) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } dataset[0][n].ptset = CGNS_NEW(cgns_ptset, 1); if (strcmp(name,"ElementRange")==0) dataset[0][n].ptset->type = CGNS_ENUMV(ElementRange); else dataset[0][n].ptset->type = CGNS_ENUMV(PointRange); dataset[0][n].ptset->id=IR_id[nn]; dataset[0][n].ptset->link=cgi_read_link(IR_id[nn]); dataset[0][n].ptset->in_link=linked; if (cgi_read_ptset(dataset[0][n].id, dataset[0][n].ptset)) return CG_ERROR; } if (nIR_t) CGNS_FREE(IR_id); for (nn=0; nncgio, IA_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointList") && strcmp(name,"ElementList")) continue; if (dataset[0][n].ptset!=0) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } dataset[0][n].ptset = CGNS_NEW(cgns_ptset, 1); if (strcmp(name,"ElementList")==0) dataset[0][n].ptset->type = CGNS_ENUMV( ElementList ); else dataset[0][n].ptset->type = CGNS_ENUMV( PointList ); dataset[0][n].ptset->id = IA_id[nn]; dataset[0][n].ptset->link = cgi_read_link(IA_id[nn]); dataset[0][n].ptset->in_link = linked; if (cgi_read_ptset(dataset[0][n].id, dataset[0][n].ptset)) return CG_ERROR; } if (nIA_t) CGNS_FREE(IA_id); } CGNS_FREE(id); return CG_OK; } int cgi_read_bcdata(cgns_bcdata *bcdata) { int n, linked = bcdata->link ? 1 : bcdata->in_link; double *id; /* DataArray_t */ if (cgi_get_nodes(bcdata->id, "DataArray_t", &bcdata->narrays, &id)) return CG_ERROR; if (bcdata->narrays>0) { bcdata->array = CGNS_NEW(cgns_array, bcdata->narrays); for (n=0; nnarrays; n++) { bcdata->array[n].id = id[n]; bcdata->array[n].link = cgi_read_link(id[n]); bcdata->array[n].in_link = linked; cgi_read_array(&bcdata->array[n],"BCData_t",bcdata->id); } CGNS_FREE(id); } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, bcdata->id, &bcdata->ndescr, &bcdata->descr, &bcdata->data_class, &bcdata->units)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, bcdata->id, &bcdata->nuser_data, &bcdata->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_one_ptset(int linked, double parent_id, cgns_ptset **pptset) { int i, nI_t; double *I_id; char_33 name; cgns_ptset *ptset = NULL; if (cgi_get_nodes(parent_id, "IndexArray_t", &nI_t, &I_id)) return CG_ERROR; for (i = 0; i < nI_t; i++) { if (cgio_get_name(cg->cgio, I_id[i], name)) { cg_io_error("cgio_get_name for PointList"); return CG_ERROR; } if (strcmp(name, "PointList") && strcmp(name, "ElementList")) continue; if (ptset != NULL) { cgi_error("Multiple definitions of PointList/PointRange"); return CG_ERROR; } ptset = CGNS_NEW(cgns_ptset, 1); if (0 == strcmp(name, "ElementList")) ptset->type = CGNS_ENUMV(ElementList); else ptset->type = CGNS_ENUMV(PointList); ptset->id=I_id[i]; ptset->link=cgi_read_link(I_id[i]); ptset->in_link=linked; if (cgi_read_ptset(I_id[i], ptset)) return CG_ERROR; } if (nI_t) CGNS_FREE(I_id); if (cgi_get_nodes(parent_id, "IndexRange_t", &nI_t, &I_id)) return CG_ERROR; for (i = 0; i < nI_t; i++) { if (cgio_get_name(cg->cgio, I_id[i], name)) { cg_io_error("cgio_get_name for PointRange"); return CG_ERROR; } if (strcmp(name, "PointRange") && strcmp(name, "ElementRange")) continue; if (ptset != NULL) { cgi_error("Multiple definitions of PointList/PointRange"); return CG_ERROR; } ptset = CGNS_NEW(cgns_ptset, 1); if (0 == strcmp(name, "ElementRange")) ptset->type = CGNS_ENUMV(ElementRange); else ptset->type = CGNS_ENUMV(PointRange); ptset->id=I_id[i]; ptset->link=cgi_read_link(I_id[i]); ptset->in_link=linked; if (cgi_read_ptset(I_id[i], ptset)) return CG_ERROR; } if (nI_t) CGNS_FREE(I_id); *pptset = ptset; return CG_OK; } int cgi_read_ptset(double parent_id, cgns_ptset *ptset) { int ndim; cgsize_t dim_vals[12]; void **dummy=0; /* Get name of point set just to verify consistency */ if (cgi_read_node(ptset->id, ptset->name, ptset->data_type, &ndim, dim_vals, dummy, SKIP_DATA)) { cgi_error("Error reading ptset"); return CG_ERROR; } /* change read data for ElementList/Range stuff */ if (cg->version <= 1200 && ndim == 1 && (ptset->type == CGNS_ENUMV(ElementRange) || ptset->type == CGNS_ENUMV(ElementList))) { ndim = 2; dim_vals[1]=dim_vals[0]; dim_vals[0]=Idim; if (cg->mode == CG_MODE_MODIFY && ptset->link == 0 && ptset->in_link == 0) { if (cgio_set_dimensions(cg->cgio, ptset->id, CG_SIZE_DATATYPE, 2, dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } } } /* verify that the name matches the type intended */ if (INVALID_ENUM(ptset->type,NofValidPointSetTypes)) { cgi_error("Invalid point set type: '%s'",ptset->name); return CG_ERROR; } /* verify data type */ if (strcmp(ptset->data_type,"I4") && strcmp(ptset->data_type,"I8")) { cgi_error("Data type %s not supported for point set type %d", ptset->data_type, ptset->type); return CG_ERROR; } /* verify dimension vector */ if (!(ndim==2 && dim_vals[0]>0 && dim_vals[1]>0)) { cgi_error("Invalid definition of point set: ptset->type='%s', ndim=%d, dim_vals[0]=%d", PointSetTypeName[ptset->type], ndim, dim_vals[0]); return CG_ERROR; } /* npts */ ptset->npts = dim_vals[1]; /* size_of_patch */ if (ptset->type == CGNS_ENUMV(PointList) || ptset->type == CGNS_ENUMV(ElementList) || ptset->type == CGNS_ENUMV(PointListDonor)) { ptset->size_of_patch = ptset->npts; } else { /* read points to calculate size_of_patch */ int i; cgsize_t size=1; for (i=0; iname); return CG_ERROR; } if (0 == strcmp(ptset->data_type,"I8")) { cglong_t total = 1; cglong_t *pnts = CGNS_NEW(cglong_t, size); if (cgio_read_all_data(cg->cgio, ptset->id, pnts)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } #if CG_SIZEOF_SIZE == 32 if (cgio_check_dimensions(2*Idim, pnts)) { cg_io_error("cgio_check_dimensions"); return CG_ERROR; } #endif for (i=0; i CG_MAX_INT32) { cgi_error("patch size too large for a 32-bit integer"); return CG_ERROR; } #endif ptset->size_of_patch = (cgsize_t)total; } else if (0 == strcmp(ptset->data_type,"I4")) { int *pnts = CGNS_NEW(int, size); if (cgio_read_all_data(cg->cgio, ptset->id, pnts)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } ptset->size_of_patch = 1; for (i=0; isize_of_patch *= (pnts[i+Idim]-pnts[i]+1); CGNS_FREE(pnts); } else { cgi_error("Invalid datatype for a range pointset"); return CG_ERROR; } } return CG_OK; } int cgi_read_equations(int in_link, double parent_id, cgns_equations **equations) { double *id; int n, nnod, ndim, linked; char *string_data; char_33 name, data_type; cgsize_t dim_vals[12]; void *vdata; if (cgi_get_nodes(parent_id, "FlowEquationSet_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { equations[0]=0; return CG_OK; } equations[0] = CGNS_NEW(cgns_equations, 1); equations[0]->id = id[0]; equations[0]->link = cgi_read_link(id[0]); equations[0]->in_link = in_link; linked = equations[0]->link ? 1 : in_link; CGNS_FREE(id); strcpy(equations[0]->name, "FlowEquationSet"); /* GoverningEquations_t */ equations[0]->governing = 0; if (cgi_get_nodes(equations[0]->id, "GoverningEquations_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { equations[0]->governing = CGNS_NEW(cgns_governing,1); equations[0]->governing->id = id[0]; equations[0]->governing->link = cgi_read_link(id[0]); equations[0]->governing->in_link = linked; if (cgi_read_string(id[0], equations[0]->governing->name, &string_data) || cgi_GoverningEquationsType(string_data, &equations[0]->governing->type)) return CG_ERROR; CGNS_FREE(string_data); CGNS_FREE(id); /* initialize dependants */ equations[0]->governing->diffusion_model=0; /* DiffusionModel */ if (cgi_get_nodes(equations[0]->governing->id, "\"int[1+...+IndexDimension]\"", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_node(id[0], name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading diffusion model"); return CG_ERROR; } if (ndim!=1 || dim_vals[0]<=0 || strcmp(data_type,"I4")) { cgi_error("Diffusion Model '%s' defined incorrectly",name); return CG_ERROR; } equations[0]->governing->dim_vals = (int)dim_vals[0], equations[0]->governing->diffusion_model = (int *)vdata; CGNS_FREE(id); } /* Descriptor_t */ if (cgi_get_nodes(equations[0]->governing->id, "Descriptor_t", &equations[0]->governing->ndescr, &id)) return CG_ERROR; if (equations[0]->governing->ndescr>0) { equations[0]->governing->descr = CGNS_NEW(cgns_descr, equations[0]->governing->ndescr); for (n=0; ngoverning->ndescr; n++) { equations[0]->governing->descr[n].id = id[n]; equations[0]->governing->descr[n].link = cgi_read_link(id[n]); equations[0]->governing->descr[n].in_link = linked; if (cgi_read_string(id[n], equations[0]->governing->descr[n].name, &equations[0]->governing->descr[n].text)) return CG_ERROR; } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, equations[0]->governing->id, &equations[0]->governing->nuser_data, &equations[0]->governing->user_data)) return CG_ERROR; } /* GasModel_t */ if (cgi_read_model(linked, equations[0]->id, "GasModel_t", &equations[0]->gas)) return CG_ERROR; /* ViscosityModel_t */ if (cgi_read_model(linked, equations[0]->id, "ViscosityModel_t", &equations[0]->visc)) return CG_ERROR; /* ThermalConductivityModel_t */ if (cgi_read_model(linked, equations[0]->id, "ThermalConductivityModel_t", &equations[0]->conduct)) return CG_ERROR; /* TurbulenceClosure_t */ if (cgi_read_model(linked, equations[0]->id, "TurbulenceClosure_t", &equations[0]->closure)) return CG_ERROR; /* TurbulenceModel_t */ if (cgi_read_model(linked, equations[0]->id, "TurbulenceModel_t", &equations[0]->turbulence)) return CG_ERROR; /* initialize dependants */ if (equations[0]->turbulence) { equations[0]->turbulence->diffusion_model=0; /* DiffusionModel */ if (cgi_get_nodes(equations[0]->turbulence->id, "\"int[1+...+IndexDimension]\"", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_node(id[0], name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading Turbulence Diffusion Model"); return CG_ERROR; } if (ndim!=1 || dim_vals[0]<=0 || strcmp(data_type,"I4")) { cgi_error("Diffusion Model '%s' defined incorrectly",name); return CG_ERROR; } equations[0]->turbulence->dim_vals = (int)dim_vals[0], equations[0]->turbulence->diffusion_model = (int *)vdata; CGNS_FREE(id); } } /* ThermalRelaxationModel_t */ if (cgi_read_model(linked, equations[0]->id, "ThermalRelaxationModel_t", &equations[0]->relaxation)) return CG_ERROR; /* ChemicalKineticsModel_t */ if (cgi_read_model(linked, equations[0]->id, "ChemicalKineticsModel_t", &equations[0]->chemkin)) return CG_ERROR; /* EquationDimension */ equations[0]->equation_dim = 0; if (cgi_get_nodes(equations[0]->id, "\"int\"", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_node(id[0], name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading base"); return CG_ERROR; } /* verify data */ if (strcmp(name,"EquationDimension") || strcmp(data_type, "I4") || ndim!=1 || dim_vals[0]!=1) { cgi_error("Error reading equation dimension for Flow Equation Set"); return CG_ERROR; } equations[0]->equation_dim = *((int *)vdata); CGNS_FREE(vdata); CGNS_FREE(id); } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, equations[0]->id, &equations[0]->ndescr, &equations[0]->descr, &equations[0]->data_class, &equations[0]->units)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, equations[0]->id, &equations[0]->nuser_data, &equations[0]->user_data)) return CG_ERROR; /* EMElectricFieldModel_t */ if (cgi_read_model(linked, equations[0]->id, "EMElectricFieldModel_t", &equations[0]->elecfield)) return CG_ERROR; /* EMMagneticFieldModel_t */ if (cgi_read_model(linked, equations[0]->id, "EMMagneticFieldModel_t", &equations[0]->magnfield)) return CG_ERROR; /* EMConductivityModel_t */ if (cgi_read_model(linked, equations[0]->id, "EMConductivityModel_t", &equations[0]->emconduct)) return CG_ERROR; return CG_OK; } int cgi_read_model(int in_link, double parent_id, char *label, cgns_model **model) { int n, nnod, linked; double *id; char *string_data; if (cgi_get_nodes(parent_id, label, &nnod, &id)) return CG_ERROR; if (nnod<=0) { model[0]=0; return CG_OK; } model[0] = CGNS_NEW(cgns_model,1); model[0]->id = id[0]; model[0]->link = cgi_read_link(id[0]); model[0]->in_link = in_link; linked = model[0]->link ? 1 : in_link; CGNS_FREE(id); /* Model Type */ if (cgi_read_string(model[0]->id, model[0]->name, &string_data)) return CG_ERROR; if (cgi_ModelType(string_data, &model[0]->type)) return CG_ERROR; CGNS_FREE(string_data); /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, model[0]->id, &model[0]->ndescr, &model[0]->descr, &model[0]->data_class, &model[0]->units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(model[0]->id, "DataArray_t", &model[0]->narrays, &id)) return CG_ERROR; if (model[0]->narrays>0) { model[0]->array = CGNS_NEW(cgns_array, model[0]->narrays); for (n=0; nnarrays; n++) { model[0]->array[n].id = id[n]; model[0]->array[n].link = cgi_read_link(id[n]); model[0]->array[n].in_link = linked; if (cgi_read_array(&model[0]->array[n],"Model_t", model[0]->id)) return CG_ERROR; /* verify data */ if (model[0]->array[n].data_dim!=1 || model[0]->array[n].dim_vals[0]!=1) { cgi_error("Wrong data dimension in %s definition",model[0]->name); return CG_ERROR; } } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, model[0]->id, &model[0]->nuser_data, &model[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_state(int in_link, double parent_id, cgns_state **state) { char_33 name; int n, nnod, defined=0, linked; double *id; char *string_data; if (cgi_get_nodes(parent_id, "ReferenceState_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { state[0]=0; return CG_OK; } state[0] = CGNS_NEW(cgns_state, 1); state[0]->id=id[0]; state[0]->link=cgi_read_link(id[0]); state[0]->in_link=in_link; linked = state[0]->link ? 1 : in_link; CGNS_FREE(id); /* Name */ if (cgio_get_name(cg->cgio, state[0]->id, state[0]->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* initialize dependents */ state[0]->data_class = CGNS_ENUMV( DataClassNull ); state[0]->StateDescription = 0; state[0]->ndescr=0; /* Descriptor_t and ReferenceStateDescription */ if (cgi_get_nodes(state[0]->id, "Descriptor_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { for (n=0; ncgio, id[n], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"ReferenceStateDescription")) { if (state[0]->ndescr==0) state[0]->descr = CGNS_NEW(cgns_descr, 1); else state[0]->descr = CGNS_RENEW(cgns_descr, state[0]->ndescr+1, state[0]->descr); state[0]->descr[state[0]->ndescr].id = id[n]; state[0]->descr[state[0]->ndescr].link = cgi_read_link(id[n]); state[0]->descr[state[0]->ndescr].in_link = linked; if (cgi_read_string(id[n], state[0]->descr[state[0]->ndescr].name, &state[0]->descr[state[0]->ndescr].text)) return CG_ERROR; state[0]->ndescr++; } else { if (defined) { cgi_error("Reference State node may only hold one ReferenceStateDescription"); return CG_ERROR; } state[0]->StateDescription= CGNS_NEW(cgns_descr, 1); state[0]->StateDescription->id = id[n]; state[0]->StateDescription->link = cgi_read_link(id[n]); state[0]->StateDescription->in_link = linked; if (cgi_read_string(id[n], state[0]->StateDescription->name, &state[0]->StateDescription->text)) return CG_ERROR; defined ++; } } CGNS_FREE(id); } /* DataClass_t */ if (cgi_get_nodes(state[0]->id, "DataClass_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_string(id[0], name, &string_data)) return CG_ERROR; cgi_DataClass(string_data, &state[0]->data_class); CGNS_FREE(string_data); CGNS_FREE(id); } /* DimensionalUnits_t */ if (cgi_read_units(linked, state[0]->id, &state[0]->units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(state[0]->id, "DataArray_t", &state[0]->narrays, &id)) return CG_ERROR; if (state[0]->narrays>0) { state[0]->array = CGNS_NEW(cgns_array, state[0]->narrays); for (n=0; nnarrays; n++) { state[0]->array[n].id = id[n]; state[0]->array[n].link = cgi_read_link(id[n]); state[0]->array[n].in_link = linked; if (cgi_read_array(&state[0]->array[n],"ReferenceState_t", state[0]->id)) return CG_ERROR; /* verify data */ if (state[0]->array[n].data_dim!=1 || state[0]->array[n].dim_vals[0]!=1) { cgi_error("Wrong data dimension in Reference State definition"); return CG_ERROR; } } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, state[0]->id, &state[0]->nuser_data, &state[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_gravity(int in_link, double parent_id, cgns_gravity **gravity) { int i, nnod, linked; double *id; char_33 temp_name; if (cgi_get_nodes(parent_id, "Gravity_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { gravity[0]=0; return CG_OK; } gravity[0] = CGNS_NEW(cgns_gravity, 1); gravity[0]->id=id[0]; gravity[0]->link=cgi_read_link(id[0]); gravity[0]->in_link=in_link; linked = gravity[0]->link ? 1 : in_link; CGNS_FREE(id); /* Name */ if (cgio_get_name(cg->cgio, gravity[0]->id, gravity[0]->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* initialize dependents */ gravity[0]->vector=0; gravity[0]->narrays = 0; /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, gravity[0]->id, &gravity[0]->ndescr, &gravity[0]->descr, &gravity[0]->data_class, &gravity[0]->units)) return CG_ERROR; /* DataArray_t: GravityVector */ if (cgi_get_nodes(gravity[0]->id, "DataArray_t", &nnod, &id)) return CG_ERROR; for (i=0; icgio, id[i], temp_name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* GravityVector */ if (strcmp(temp_name,"GravityVector")==0) { gravity[0]->vector = CGNS_NEW(cgns_array, 1); gravity[0]->vector->id = id[i]; gravity[0]->vector->link = cgi_read_link(id[i]); gravity[0]->vector->in_link = linked; if (cgi_read_array(gravity[0]->vector, "Gravity_t", gravity[0]->id)) return CG_ERROR; gravity[0]->narrays = 1; /* check data */ if (strcmp(gravity[0]->vector->data_type,"R4")) { cgi_error("Datatype %s not supported for gravity vector",gravity[0]->vector->data_type); return CG_ERROR; } if (gravity[0]->vector->data_dim != 1 || gravity[0]->vector->dim_vals[0] != Pdim) { cgi_error("Error exit: Gravity vector incorrectly dimensioned"); return CG_ERROR; } } } /* loop through DataArray_t */ if (nnod) CGNS_FREE(id); /* check data */ if (gravity[0]->vector == 0) { cgi_error("Error exit: Gravity vector undefined in Gravity_t node"); return CG_ERROR; } /* UserDefinedData_t */ if (cgi_read_user_data(linked, gravity[0]->id, &gravity[0]->nuser_data, &gravity[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_axisym(int in_link, double parent_id, cgns_axisym **axisym) { int i, nnod, linked, ref_point_flag=0, axis_flag=0; double *id; char_33 temp_name; if (cgi_get_nodes(parent_id, "Axisymmetry_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { axisym[0]=0; return CG_OK; } if (Pdim !=2) { cgi_error("Error: Axisymmetry_t can only be defined for 2D data model"); return CG_ERROR; } axisym[0] = CGNS_NEW(cgns_axisym, 1); axisym[0]->id=id[0]; axisym[0]->link=cgi_read_link(id[0]); axisym[0]->in_link=in_link; linked = axisym[0]->link ? 1 : in_link; CGNS_FREE(id); /* Name */ if (cgio_get_name(cg->cgio, axisym[0]->id, axisym[0]->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* initialize dependents */ axisym[0]->narrays=0; /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, axisym[0]->id, &axisym[0]->ndescr, &axisym[0]->descr, &axisym[0]->data_class, &axisym[0]->units)) return CG_ERROR; /* DataArray_t: Required: AxisymmetryReferencePoint, AxisymmetryAxisVector Optional: AxisymmetryAngle, CoordinateNames */ if (cgi_get_nodes(axisym[0]->id, "DataArray_t", &nnod, &id)) return CG_ERROR; if (nnod > 0) axisym[0]->array = CGNS_NEW(cgns_array, nnod); for (i=0; icgio, id[i], temp_name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* AxisymmetryReferencePoint & AxisymmetryAxisVector */ if (strcmp(temp_name,"AxisymmetryReferencePoint")==0 || strcmp(temp_name,"AxisymmetryAxisVector")==0) { if (strcmp(temp_name,"AxisymmetryReferencePoint")==0) ref_point_flag = 1; else if (strcmp(temp_name,"AxisymmetryAxisVector")==0) axis_flag = 1; axisym[0]->array[axisym[0]->narrays].id = id[i]; axisym[0]->array[axisym[0]->narrays].link = cgi_read_link(id[i]); axisym[0]->array[axisym[0]->narrays].in_link = linked; if (cgi_read_array(&axisym[0]->array[axisym[0]->narrays], "Axisymmetry_t", axisym[0]->id)) return CG_ERROR; /* check data */ if (strcmp(axisym[0]->array[axisym[0]->narrays].data_type,"R4")) { cgi_error("Error: Datatype %s not supported for %s", axisym[0]->array[axisym[0]->narrays].data_type, temp_name); return CG_ERROR; } if (axisym[0]->array[axisym[0]->narrays].data_dim != 1 || axisym[0]->array[axisym[0]->narrays].dim_vals[0] != Pdim) { cgi_error("Error: %s incorrectly dimensioned",temp_name); return CG_ERROR; } axisym[0]->narrays ++; } /* AxisymmetryAngle */ else if (strcmp(temp_name,"AxisymmetryAngle")==0) { axisym[0]->array[axisym[0]->narrays].id = id[i]; axisym[0]->array[axisym[0]->narrays].link = cgi_read_link(id[i]); axisym[0]->array[axisym[0]->narrays].in_link = linked; if (cgi_read_array(&axisym[0]->array[axisym[0]->narrays], "Axisymmetry_t", axisym[0]->id)) return CG_ERROR; /* check data */ if (strcmp(axisym[0]->array[axisym[0]->narrays].data_type,"R4")) { cgi_error("Error: Datatype %s not supported for %s", axisym[0]->array[axisym[0]->narrays].data_type, temp_name); return CG_ERROR; } if (axisym[0]->array[axisym[0]->narrays].data_dim != 1 || axisym[0]->array[axisym[0]->narrays].dim_vals[0] != 1) { cgi_error("Error: %s incorrectly dimensioned",temp_name); return CG_ERROR; } axisym[0]->narrays ++; } /* CoordinateNames */ else if (strcmp(temp_name,"CoordinateNames")==0) { axisym[0]->array[axisym[0]->narrays].id = id[i]; axisym[0]->array[axisym[0]->narrays].link = cgi_read_link(id[i]); axisym[0]->array[axisym[0]->narrays].in_link = linked; if (cgi_read_array(&axisym[0]->array[axisym[0]->narrays], "Axisymmetry_t", axisym[0]->id)) return CG_ERROR; /* check data */ if (strcmp(axisym[0]->array[axisym[0]->narrays].data_type,"C1")) { cgi_error("Error: Datatype %s not supported for %s", axisym[0]->array[axisym[0]->narrays].data_type, temp_name); return CG_ERROR; } if (axisym[0]->array[axisym[0]->narrays].data_dim != 2 || axisym[0]->array[axisym[0]->narrays].dim_vals[0] != 32 || axisym[0]->array[axisym[0]->narrays].dim_vals[1] != 2) { cgi_error("Error: %s incorrectly dimensioned",temp_name); return CG_ERROR; } axisym[0]->narrays ++; } } /* loop through DataArray_t */ if (nnod) CGNS_FREE(id); /* check data */ if (!ref_point_flag || !axis_flag) { cgi_error("Error: AxisymmetryReferencePoint & AxisymmetryAxisVector are required"); return CG_ERROR; } /* UserDefinedData_t */ if (cgi_read_user_data(linked, axisym[0]->id, &axisym[0]->nuser_data, &axisym[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_rotating(int in_link, double parent_id, cgns_rotating **rotating) { int i, nnod, linked, rot_rate_flag=0, rot_center_flag=0; double *id; char_33 temp_name; if (cgi_get_nodes(parent_id, "RotatingCoordinates_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { rotating[0]=0; return CG_OK; } rotating[0] = CGNS_NEW(cgns_rotating, 1); rotating[0]->id=id[0]; rotating[0]->link=cgi_read_link(id[0]); rotating[0]->in_link=in_link; linked = rotating[0]->link ? 1 : in_link; CGNS_FREE(id); /* Name */ if (cgio_get_name(cg->cgio, rotating[0]->id, rotating[0]->name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* initialize dependents */ rotating[0]->narrays=0; /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, rotating[0]->id, &rotating[0]->ndescr, &rotating[0]->descr, &rotating[0]->data_class, &rotating[0]->units)) return CG_ERROR; /* DataArray_t: Required: RotationCenter, RotationRateVector Optional: none */ if (cgi_get_nodes(rotating[0]->id, "DataArray_t", &nnod, &id)) return CG_ERROR; if (nnod > 0) rotating[0]->array = CGNS_NEW(cgns_array, nnod); for (i=0; icgio, id[i], temp_name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* RotationCenter, RotationRateVector */ if (strcmp(temp_name,"RotationCenter")==0 || strcmp(temp_name,"RotationRateVector")==0) { if (strcmp(temp_name,"RotationCenter")==0) rot_center_flag = 1; else if (strcmp(temp_name,"RotationRateVector")==0) rot_rate_flag = 1; rotating[0]->array[rotating[0]->narrays].id = id[i]; rotating[0]->array[rotating[0]->narrays].link = cgi_read_link(id[i]); rotating[0]->array[rotating[0]->narrays].in_link = linked; if (cgi_read_array(&rotating[0]->array[rotating[0]->narrays], "RotatingCoordinates_t", rotating[0]->id)) return CG_ERROR; /* check data */ if (strcmp(rotating[0]->array[rotating[0]->narrays].data_type,"R4")) { cgi_error("Error: Datatype %s not supported for %s", rotating[0]->array[rotating[0]->narrays].data_type, temp_name); return CG_ERROR; } if (rotating[0]->array[rotating[0]->narrays].data_dim != 1 || rotating[0]->array[rotating[0]->narrays].dim_vals[0] != Pdim) { cgi_error("Error: %s incorrectly dimensioned",temp_name); return CG_ERROR; } rotating[0]->narrays ++; } } /* loop through DataArray_t */ if (nnod) CGNS_FREE(id); /* check data */ if (!rot_rate_flag || !rot_center_flag) { cgi_error("Error: RotationCenter & RotationRateVector are required"); return CG_ERROR; } /* UserDefinedData_t */ if (cgi_read_user_data(linked, rotating[0]->id, &rotating[0]->nuser_data, &rotating[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_converg(int in_link, double parent_id, cgns_converg **converg) { char_33 data_type, name; int ndim, n, nnod; double *id; char *string_data; void *iterations; int nnorm=0, linked; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "ConvergenceHistory_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { converg[0]=0; return CG_OK; } converg[0] = CGNS_NEW(cgns_converg, 1); converg[0]->id = id[0]; converg[0]->link = cgi_read_link(id[0]); converg[0]->in_link = in_link; linked = converg[0]->link ? 1 : in_link; CGNS_FREE(id); if (cgi_read_node(converg[0]->id, converg[0]->name, data_type, &ndim, dim_vals, &iterations, READ_DATA)) { cgi_error("Error reading Convergence History node"); return CG_ERROR; } /* verify data: Temporarily commented and replaced by 4 lines below if (strcmp(data_type,"I4") || ndim!=1 || dim_vals[0]!=1) { cgi_error("ConvergenceHistory_t node '%s' incorrect",converg[0]->name); return CG_ERROR; } converg[0]->iterations = *((int *)iterations); CGNS_FREE(iterations); */ /* The check was removed because Bob was storing other type of data at the level. This is a temporary changed */ if (strcmp(data_type,"I4")==0 && dim_vals[0]>=1) { converg[0]->iterations = *((int *)iterations); CGNS_FREE(iterations); } else converg[0]->iterations=0; /* initialize dependents */ converg[0]->data_class = CGNS_ENUMV( DataClassNull ); converg[0]->NormDefinitions = 0; converg[0]->ndescr=0; /* Descriptor_t and NormDefinitions */ if (cgi_get_nodes(converg[0]->id, "Descriptor_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { for (n=0; ncgio, id[n], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"NormDefinitions")) { if (converg[0]->ndescr==0) converg[0]->descr = CGNS_NEW(cgns_descr, 1); else converg[0]->descr=CGNS_RENEW(cgns_descr,converg[0]->ndescr+1,converg[0]->descr); converg[0]->descr[converg[0]->ndescr].id = id[n]; converg[0]->descr[converg[0]->ndescr].link = cgi_read_link(id[n]); converg[0]->descr[converg[0]->ndescr].in_link = linked; if (cgi_read_string(id[n], converg[0]->descr[converg[0]->ndescr].name, &converg[0]->descr[converg[0]->ndescr].text)) return CG_ERROR; converg[0]->ndescr++; } else { if (nnorm) { cgi_error("Convergence History may only hold one NormDefinitions Node"); return CG_ERROR; } converg[0]->NormDefinitions = CGNS_NEW(cgns_descr, 1); converg[0]->NormDefinitions->id = id[n]; converg[0]->NormDefinitions->link = cgi_read_link(id[n]); converg[0]->NormDefinitions->in_link = linked; if (cgi_read_string(id[n], converg[0]->NormDefinitions->name, &converg[0]->NormDefinitions->text)) return CG_ERROR; nnorm ++; } } CGNS_FREE(id); } /* DataClass_t */ if (cgi_get_nodes(converg[0]->id, "DataClass_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_string(id[0], name, &string_data)) return CG_ERROR; cgi_DataClass(string_data, &converg[0]->data_class); CGNS_FREE(string_data); CGNS_FREE(id); } /* DimensionalUnits_t */ if (cgi_read_units(linked, converg[0]->id, &converg[0]->units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(converg[0]->id, "DataArray_t", &converg[0]->narrays, &id)) return CG_ERROR; if (converg[0]->narrays>0) { converg[0]->array = CGNS_NEW(cgns_array, converg[0]->narrays); for (n=0; nnarrays; n++) { converg[0]->array[n].id = id[n]; converg[0]->array[n].link = cgi_read_link(id[n]); converg[0]->array[n].in_link = linked; if (cgi_read_array(&converg[0]->array[n],"ConvergenceHistory_t", converg[0]->id)) return CG_ERROR; /* verify data : Temporiraly commented for Bob Bush if (converg[0]->array[n].data_dim!=1) { cgi_error("Wrong nr of dimension in Conversion History definition"); return CG_ERROR; } */ } CGNS_FREE(id); } /* UserDefinedData_t */ if (cgi_read_user_data(linked, converg[0]->id, &converg[0]->nuser_data, &converg[0]->user_data)) return CG_ERROR; return CG_OK; } int cgi_read_discrete(int in_link, double parent_id, int *ndiscrete, cgns_discrete **discrete) { double *id, *idi; int n, i, j, linked; cgsize_t DataSize[3], DataCount = 0; if (cgi_get_nodes(parent_id, "DiscreteData_t", ndiscrete, &id)) return CG_ERROR; if (*ndiscrete<=0) { discrete[0] = 0; return CG_OK; } discrete[0] = CGNS_NEW(cgns_discrete, (*ndiscrete)); for (n=0; n<(*ndiscrete); n++) { discrete[0][n].id = id[n]; discrete[0][n].link = cgi_read_link(id[n]); discrete[0][n].in_link = in_link; linked = discrete[0][n].link ? 1 : in_link; /* name of node */ if (cgio_get_name(cg->cgio, id[n], discrete[0][n].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, id[n], &discrete[0][n].ndescr, &discrete[0][n].descr, &discrete[0][n].data_class, &discrete[0][n].units)) return CG_ERROR; /* GridLocation_t */ if (cgi_read_location(discrete[0][n].id, discrete[0][n].name, &discrete[0][n].location)) return CG_ERROR; /* Rind Planes */ if (cgi_read_rind(discrete[0][n].id, &discrete[0][n].rind_planes)) return CG_ERROR; /* Determine data size */ if (cgi_datasize(Idim, CurrentDim, discrete[0][n].location, discrete[0][n].rind_planes, DataSize)) return CG_ERROR; /* check for PointList/PointRange */ if (cgi_read_one_ptset(linked, discrete[0][n].id, &discrete[0][n].ptset)) return CG_ERROR; if (discrete[0][n].ptset != NULL) { if (discrete[0][n].ptset->type == CGNS_ENUMV(ElementList) || discrete[0][n].ptset->type == CGNS_ENUMV(ElementRange)) { cgi_error("ElementList/Range not supported under DiscreteData"); return CG_ERROR; } DataCount = discrete[0][n].ptset->size_of_patch; } /* DataArray_t */ if (cgi_get_nodes(discrete[0][n].id, "DataArray_t", &discrete[0][n].narrays, &idi)) return CG_ERROR; if (discrete[0][n].narrays>0) { discrete[0][n].array = CGNS_NEW(cgns_array, discrete[0][n].narrays); for (i=0; icgio, integral[0][n].id, integral[0][n].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, id[n], &integral[0][n].ndescr, &integral[0][n].descr, &integral[0][n].data_class, &integral[0][n].units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(id[n], "DataArray_t", &integral[0][n].narrays, &idi)) return CG_ERROR; if (integral[0][n].narrays>0) { integral[0][n].array = CGNS_NEW(cgns_array, integral[0][n].narrays); for (i=0; iname)==0 || strcmp("RigidRotationAngle",array->name)==0 || strcmp("RigidVelocity" ,array->name)==0 || strcmp("RigidRotationRate" ,array->name)==0) { if (strcmp(array->data_type,"R4") && strcmp(array->data_type,"R8")) { cgi_error("Wrong data type for %s",array->name); return CG_ERROR; } if ((strcmp("OriginLocation",array->name)==0 && array->data_dim!=2) || (strcmp("OriginLocation",array->name) && array->data_dim!=1) || array->dim_vals[0]!=Pdim || (strcmp("OriginLocation",array->name)==0 && array->dim_vals[1]!=2)) { cgi_error("Wrong data dimension in '%s' definition",array->name); return CG_ERROR; } } } /* loop through DataArray_t */ for (i=0; i0) { amotion[0][n].array = CGNS_NEW(cgns_array, amotion[0][n].narrays); for (i=0; ilink ? 1 : array->in_link; char_33 data_type, temp_name; int nchild, ndim; double *idi; cgsize_t dim_vals[12]; /* These data arrays are not loaded in memory, just their addresses */ if (strcmp(parent_label,"GridCoordinates_t")==0 || strcmp(parent_label,"FlowSolution_t")==0 || strcmp(parent_label,"Elements_t")==0 || strcmp(parent_label,"ZoneSubRegion_t")==0 || strcmp(parent_label,"DiscreteData_t")==0 || strcmp(parent_label,"UserDefinedData_t")==0) { data_flag=SKIP_DATA; array->data=0; } if (cgi_read_node(array->id, array->name, array->data_type, &array->data_dim, array->dim_vals, &array->data, data_flag)) { cgi_error("Error reading array under %s",parent_label); return CG_ERROR; } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, array->id, &array->ndescr, &array->descr, &array->data_class, &array->units)) return CG_ERROR; /* DataConversion_t */ if (cgi_read_conversion(linked, array->id, &array->convert)) return CG_ERROR; /* DimensionalExponents_t */ if (cgi_read_exponents(linked, array->id, &array->exponents)) return CG_ERROR; /* IndexRange_t */ if (cgi_get_nodes(array->id, "IndexRange_t", &nchild, &idi)) return CG_ERROR; if (nchild==1) { void *vdata; if (cgi_read_node(idi[0], temp_name, data_type, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading array range"); return CG_ERROR; } if (nchild) CGNS_FREE(idi); /* verify that the name matches the type intended */ if (strcmp(temp_name,"ArrayDataRange")) { cgi_error("Invalid point set type: '%s'",temp_name); return CG_ERROR; } /* Accept only I4 and I8 */ if (strcmp(data_type,"I4") && strcmp(data_type,"I8")) { cgi_error("Data type %s not supported for ArrayDataRange", data_type); return CG_ERROR; } /* verify dimension vector */ if (ndim!=1 || dim_vals[0]!=2) { cgi_error("Invalid dimensions in definition of ArrayDataRange"); return CG_ERROR; } /* nelements */ if (0 == strcmp(data_type,"I8")) { cglong_t *data = (cglong_t *)vdata; #if CG_SIZEOF_SIZE == 32 if (cgio_check_dimensions(2, data)) { cg_io_error("cgio_check_dimensions"); return CG_ERROR; } #endif array->range[0] = (cgsize_t)data[0]; array->range[1] = (cgsize_t)data[1]; } else { int *data = (int *)vdata; array->range[0] = (cgsize_t)data[0]; array->range[1] = (cgsize_t)data[1]; } CGNS_FREE(vdata); } return CG_OK; } int cgi_read_conversion(int in_link, double parent_id, cgns_conversion **convert) { int nnod, ndim; double *id; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "DataConversion_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { convert[0]=0; return CG_OK; } convert[0] = CGNS_NEW(cgns_conversion, 1); convert[0]->id = id[0]; convert[0]->link = cgi_read_link(id[0]); convert[0]->in_link = in_link; CGNS_FREE(id); if (cgi_read_node(convert[0]->id, convert[0]->name, convert[0]->data_type, &ndim, dim_vals, &convert[0]->data, READ_DATA)) { cgi_error("Error reading '%s'",convert[0]->name); return CG_ERROR; } if (strcmp(convert[0]->data_type,"R4") && strcmp(convert[0]->data_type,"R8")) { cgi_error("Wrong Data Type in '%s'",convert[0]->name); return CG_ERROR; } if (ndim!=1 || dim_vals[0]!=2) { cgi_error("Wrong dimensions in '%s'",convert[0]->name); return CG_ERROR; } return CG_OK; } int cgi_read_exponents(int in_link, double parent_id, cgns_exponent **exponents) { int nnod, ndim; double *id; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "DimensionalExponents_t", &nnod, &id)) return CG_ERROR; if (nnod <= 0) { exponents[0]=0; return CG_OK; } exponents[0] = CGNS_NEW(cgns_exponent, 1); exponents[0]->id = id[0]; exponents[0]->link = cgi_read_link(id[0]); exponents[0]->in_link = in_link; CGNS_FREE(id); if (cgi_read_node(exponents[0]->id, exponents[0]->name, exponents[0]->data_type, &ndim, dim_vals, &exponents[0]->data, READ_DATA)) { cgi_error("Error reading '%s'",exponents[0]->name); return CG_ERROR; } if (strcmp(exponents[0]->data_type,"R4") && strcmp(exponents[0]->data_type,"R8")) { cgi_error("Wrong Data Type in '%s'",exponents[0]->name); return CG_ERROR; } if (ndim != 1 || dim_vals[0] != 5) { cgi_error("Wrong dimensions in '%s'",exponents[0]->name); return CG_ERROR; } exponents[0]->nexps = 5; if (cgi_get_nodes(exponents[0]->id, "AdditionalExponents_t", &nnod, &id)) return CG_ERROR; if (nnod > 0) { int ierr; char_33 data_type, name; void *data; ierr = cgi_read_node(id[0], name, data_type, &ndim, dim_vals, &data, READ_DATA); CGNS_FREE(id); if (ierr) { cgi_error("Error reading AdditionalExponents for 's'", exponents[0]->name); return CG_ERROR; } if (strcmp(data_type, exponents[0]->data_type)) { CGNS_FREE(data); cgi_error("mismatch in data type for AdditionalExponents for '%s'", exponents[0]->name); return CG_ERROR; } if (ndim != 1 || dim_vals[0] != 3) { CGNS_FREE(data); cgi_error("Wrong dimensions in AdditionalExponents for '%s'", exponents[0]->name); return CG_ERROR; } exponents[0]->data = (void *) realloc (exponents[0]->data, 8 * size_of(exponents[0]->data_type)); if (exponents[0]->data == NULL) { CGNS_FREE(data); cgi_error("realloc failed for DimensionalExponents"); return CG_ERROR; } if (0 == strcmp(exponents[0]->data_type,"R4")) { float *exps = (float *)exponents[0]->data; for (ndim = 0; ndim < 3; ndim++) exps[5+ndim] = *((float *)data + ndim); } else { double *exps = (double *)exponents[0]->data; for (ndim = 0; ndim < 3; ndim++) exps[5+ndim] = *((double *)data + ndim); } exponents[0]->nexps = 8; CGNS_FREE(data); } return CG_OK; } int cgi_read_units(int in_link, double parent_id, cgns_units **units) { char_33 unit_name; char *string_data; double *id; int nnod; if (cgi_get_nodes(parent_id, "DimensionalUnits_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { units[0]=0; return CG_OK; } units[0] = CGNS_NEW(cgns_units, 1); units[0]->id = id[0]; units[0]->link = cgi_read_link(id[0]); units[0]->in_link = in_link; CGNS_FREE(id); if (cgi_read_string(units[0]->id, units[0]->name, &string_data)) return CG_ERROR; if (strlen(string_data) != 32*5) { CGNS_FREE(string_data); cgi_error("Dimensional Units defined incorrectly."); return CG_ERROR; } units[0]->nunits = 5; /* change from Celcius to Celsius */ if (0 == strncmp(&string_data[96], "Celcius", 7)) { string_data[99] = 's'; if (cg->mode == CG_MODE_MODIFY && !in_link) { if (cgio_write_all_data(cg->cgio, units[0]->id, string_data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } } strncpy (unit_name, string_data, 32); unit_name[32] = 0; cgi_MassUnits(unit_name, &units[0]->mass); strncpy (unit_name, &string_data[32], 32); unit_name[32] = 0; cgi_LengthUnits(unit_name, &units[0]->length); strncpy (unit_name, &string_data[64], 32); unit_name[32] = 0; cgi_TimeUnits(unit_name, &units[0]->time); strncpy (unit_name, &string_data[96], 32); unit_name[32] = 0; cgi_TemperatureUnits(unit_name, &units[0]->temperature); strncpy (unit_name, &string_data[128], 32); unit_name[32] = 0; cgi_AngleUnits(unit_name, &units[0]->angle); CGNS_FREE(string_data); units[0]->current = CGNS_ENUMV( ElectricCurrentUnitsNull ); units[0]->amount = CGNS_ENUMV( SubstanceAmountUnitsNull ); units[0]->intensity = CGNS_ENUMV( LuminousIntensityUnitsNull ); if (cgi_get_nodes(units[0]->id, "AdditionalUnits_t", &nnod, &id)) return CG_ERROR; if (nnod > 0) { int ierr = cgi_read_string(id[0], unit_name, &string_data); CGNS_FREE(id); if (ierr) return CG_ERROR; if (strlen(string_data) != 32*3) { CGNS_FREE(string_data); cgi_error("AdditionalUnits for '%s' defined incorrectly.", units[0]->name); return CG_ERROR; } units[0]->nunits = 8; strncpy (unit_name, string_data, 32); unit_name[32] = 0; cgi_ElectricCurrentUnits(unit_name, &units[0]->current); strncpy (unit_name, &string_data[32], 32); unit_name[32] = 0; cgi_SubstanceAmountUnits(unit_name, &units[0]->amount); strncpy (unit_name, &string_data[64], 32); unit_name[32] = 0; cgi_LuminousIntensityUnits(unit_name, &units[0]->intensity); CGNS_FREE(string_data); } return CG_OK; } int cgi_read_string(double id, char_33 name, char **string_data) { int n, ndim; char_33 data_type; cgsize_t length[2], len=1; if (cgi_read_node(id, name, data_type, &ndim, length, (void **)string_data, READ_DATA)) { cgi_error("Error reading string"); return CG_ERROR; } /* verify dimensions */ if (strcmp(data_type,"C1")!=0) { cgi_error("Invalid datatype for character data: %s",data_type); return CG_ERROR; } /* add the string terminator */ for (n=0; n0) { descr[0] = CGNS_NEW(cgns_descr, (*ndescr)); for (n=0; n<(*ndescr); n++) { descr[0][n].id = id[n]; descr[0][n].link = cgi_read_link(id[n]); descr[0][n].in_link = in_link; if (cgi_read_string(id[n], descr[0][n].name, &descr[0][n].text)) return CG_ERROR; } CGNS_FREE(id); } /* DataClass_t */ *data_class = CGNS_ENUMV( DataClassNull ); if (cgi_get_nodes(parent_id, "DataClass_t", &nnod, &id)) return CG_ERROR; if (nnod>0) { if (cgi_read_string(id[0], name, &string_data)) return CG_ERROR; cgi_DataClass(string_data, data_class); CGNS_FREE(string_data); CGNS_FREE(id); } /* DimensionalUnits_t */ if (cgi_read_units(in_link, parent_id, units)) return CG_ERROR; return CG_OK; } int cgi_read_ordinal(double parent_id, int *ordinal) { int nnod; double *id; char_33 name, data_type; int ndim; void *ordinal_data; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "Ordinal_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { (*ordinal)=0; return CG_OK; } if (cgi_read_node(id[0], name, data_type, &ndim, dim_vals, &ordinal_data, READ_DATA)) { cgi_error("Error reading Ordinal node"); return CG_ERROR; } if (ndim!=1 || dim_vals[0]!=1 || strcmp(data_type,"I4")) { cgi_error("Ordinal '%s' defined incorrectly",name); return CG_ERROR; } CGNS_FREE(id); (*ordinal)=*(int *)ordinal_data; CGNS_FREE(ordinal_data); return CG_OK; } int cgi_read_rind(double parent_id, int **rind_planes) { int n, nnod; double *id; char_33 name, data_type; int ndim; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "Rind_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { rind_planes[0] = (int *) malloc (2*Idim*sizeof(int)); if (!rind_planes[0]) { cgi_error("Error allocating rind_planes."); return CG_ERROR; } for (n=0; n<2*Idim; n++) rind_planes[0][n]=0; return CG_OK; } if (cgi_read_node(id[0], name, data_type, &ndim, dim_vals, (void **)rind_planes, READ_DATA)) { cgi_error("Error reading Rind Planes"); return CG_ERROR; } if (ndim!=1 || dim_vals[0]!=2*Idim || strcmp(data_type,"I4")) { cgi_error("Rind Planes '%s' defined incorrectly",name); return CG_ERROR; } CGNS_FREE(id); return CG_OK; } int cgi_read_location(double parent_id, char_33 parent_name, CGNS_ENUMT(GridLocation_t) *location) { int nGL_t; double *id; char *location_name; /* allocated in cgi_read_node */ char_33 name; /* get number of GridLocation_t nodes and their ID */ if (cgi_get_nodes(parent_id, "GridLocation_t", &nGL_t, &id)) return CG_ERROR; if (nGL_t==0) { *location = CGNS_ENUMV( Vertex ); } else if (nGL_t<0 || nGL_t >1) { cgi_error("Invalid definition of GridLocation for %s",parent_name); return CG_ERROR; } else if (nGL_t==1) { /* Read the grid location value in the GridLocation_t node */ if (cgi_read_string(id[0], name, &location_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_GridLocation(location_name, location)) return CG_ERROR; CGNS_FREE(location_name); } return CG_OK; } int cgi_read_zonetype(double parent_id, char_33 parent_name, CGNS_ENUMT(ZoneType_t) *type) { int nchild; double *id; char *zonetype_name; /* allocated in cgi_read_node */ char_33 name; /* get number of ZoneType_t nodes and their ID */ if (cgi_get_nodes(parent_id, "ZoneType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) { /* set default */ *type = CGNS_ENUMV( Structured ); return CG_OK; } if (nchild >1) { cgi_error("Invalid definition of ZoneType for %s",parent_name); return CG_ERROR; } if (cgi_read_string(id[0], name, &zonetype_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_ZoneType(zonetype_name, type)) return CG_ERROR; CGNS_FREE(zonetype_name); return CG_OK; } int cgi_read_simulation(double parent_id, CGNS_ENUMT(SimulationType_t) *type, double *type_id) { int nchild; double *id; char *type_name; /* allocated in cgi_read_node */ char_33 name; /* initialize */ *type = CGNS_ENUMV( SimulationTypeNull ); *type_id = 0; /* get number of SimulationType_t nodes and their ID */ if (cgi_get_nodes(parent_id, "SimulationType_t", &nchild, &id)) return CG_ERROR; if (nchild==0) return CG_OK; if (nchild >1) { cgi_error("File incorrect: multiple definition of SimulationType"); return CG_ERROR; } *type_id = id[0]; if (cgi_read_string(id[0], name, &type_name)) return CG_ERROR; CGNS_FREE(id); if (cgi_SimulationType(type_name, type)) return CG_ERROR; CGNS_FREE(type_name); return CG_OK; } int cgi_read_biter(int in_link, double parent_id, cgns_biter **biter) { double *id; char_33 datatype; cgns_array *array; int ndim, *data, nnod; int i, linked; int nzones_max = 0, nfamilies_max = 0; void *vdata; cgsize_t dim_vals[12]; /* get number of BaseIterativeData_t node */ if (cgi_get_nodes(parent_id, "BaseIterativeData_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { biter[0]=0; return CG_OK; } else if (nnod>1) { cgi_error("Error: Multiple BaseIterativeData_t found..."); return CG_ERROR; } biter[0] = CGNS_NEW(cgns_biter, 1); biter[0]->id = id[0]; biter[0]->link = cgi_read_link(id[0]); biter[0]->in_link = in_link; linked = biter[0]->link ? 1 : in_link; CGNS_FREE(id); /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, biter[0]->id, &biter[0]->ndescr, &biter[0]->descr, &biter[0]->data_class, &biter[0]->units)) return CG_ERROR; /* Name and NumberOfSteps */ NumberOfSteps = biter[0]->nsteps = 0; if (cgi_read_node(biter[0]->id, biter[0]->name, datatype, &ndim, dim_vals, &vdata, READ_DATA)) { cgi_error("Error reading BaseIterativeData_t"); return CG_ERROR; } if (ndim!=1 || dim_vals[0]!=1 || strcmp(datatype,"I4")) { cgi_error("Error in data dimension or type for NumberOfSteps"); return CG_ERROR; } data = (int *)vdata; if (data[0]<0) { cgi_error("Error in data: NumberOfSteps<0!"); return CG_ERROR; } NumberOfSteps = biter[0]->nsteps = data[0]; if (biter[0]->nsteps == 0) return CG_OK; CGNS_FREE(vdata); /* UserDefinedData_t */ if (cgi_read_user_data(linked, biter[0]->id, &biter[0]->nuser_data, &biter[0]->user_data)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(biter[0]->id, "DataArray_t", &biter[0]->narrays, &id)) return CG_ERROR; if (biter[0]->narrays == 0) return CG_OK; /* If no arrays we're done. */ biter[0]->array = CGNS_NEW(cgns_array, biter[0]->narrays); for (i=0; i<(biter[0]->narrays); i++) { biter[0]->array[i].id = id[i]; biter[0]->array[i].link = cgi_read_link(id[i]); biter[0]->array[i].in_link = linked; if (cgi_read_array(&biter[0]->array[i], "BaseIterativeData_t", biter[0]->id)) return CG_ERROR; array = &biter[0]->array[i]; /* check data */ if (strcmp("TimeValues",array->name)==0 || strcmp("IterationValues",array->name)==0 || strcmp("NumberOfZones",array->name)==0 || strcmp("NumberOfFamilies",array->name)==0) { if (array->data_dim!=1 || array->dim_vals[0]!=biter[0]->nsteps) { cgi_error("Error: Array '%s' incorrectly sized",array->name); return CG_ERROR; } if ((strcmp("TimeValues",array->name)==0 && strcmp(array->data_type,"R4") && strcmp(array->data_type,"R8")) || (strcmp("IterationValues",array->name)==0 && strcmp(array->data_type,"I4"))) { cgi_error("Incorrect data type for %s under %s",array->name,biter[0]->name); return CG_ERROR; } } } /* loop through arrays */ CGNS_FREE(id); /* check data: verify that at least one of {TimeValues or IterationValues} is defined */ for (i=0; i<(biter[0]->narrays); i++) { array = &biter[0]->array[i]; if (strcmp("TimeValues",array->name)==0 || strcmp("IterationValues",array->name)==0) break; if (i == ((biter[0]->narrays)-1)) { cgi_error("Error: TimeValues or IterationValues must be defined for '%s'",biter[0]->name); return CG_ERROR; } } /* check data: Compute nzones_max and nfamilies_max */ for (i=0; i<(biter[0]->narrays); i++) { int step; array = &biter[0]->array[i]; if (strcmp("NumberOfZones",array->name)==0) { for (step=0; stepnsteps; step++) { int nzones = *((int *)(array->data)+step); nzones_max = MAX(nzones_max, nzones); } } else if (strcmp("NumberOfFamilies",array->name)==0) { for (step=0; stepnsteps; step++) { int nfamilies = *((int *)(array->data)+step); nfamilies_max = MAX(nfamilies_max, nfamilies); } } } /* check data: ZonePointers can't be defined without NumberOfZones and FamilyPointers can't be defined without NumberOfFamilies */ for (i=0; i<(biter[0]->narrays); i++) { array = &biter[0]->array[i]; if (strcmp("ZonePointers",array->name)==0) { if (nzones_max==0) { cgi_error("NumberofZones (DataArray_t) missing under %s",biter[0]->name); return CG_ERROR; } else { /* check dimensions and data type */ if (array->data_dim!=3 || array->dim_vals[0]!=32 || array->dim_vals[1]!=nzones_max || array->dim_vals[2]!=biter[0]->nsteps || strcmp(array->data_type,"C1")) { cgi_error("Incorrect definition of ZonePointers under %s",biter[0]->name); return CG_ERROR; } } } else if (strcmp("FamilyPointers",array->name)==0) { if (nfamilies_max==0) { cgi_error("NumberOfFamilies (DataArray_t) missing under %s",biter[0]->name); return CG_ERROR; } else { /* check dimensions and data type */ if (array->data_dim!=3 || array->dim_vals[0]!=32 || array->dim_vals[1]!=nfamilies_max || array->dim_vals[2]!=biter[0]->nsteps || strcmp(array->data_type,"C1")) { cgi_error("Incorrect definition of FamilyPointers under %s",biter[0]->name); return CG_ERROR; } } } } return CG_OK; } int cgi_read_ziter(int in_link, double parent_id, cgns_ziter **ziter) { double *id = NULL; cgns_array *array = NULL; char_33 datatype; int ndim, nnod; void *data = NULL; int i, linked; cgsize_t dim_vals[12]; /* get number of ZoneIterativeData_t node */ if (cgi_get_nodes(parent_id, "ZoneIterativeData_t", &nnod, &id)) return CG_ERROR; if (nnod<=0) { ziter[0]=0; return CG_OK; } else if (nnod>1) { cgi_error("Error: Multiple ZoneIterativeData_t found..."); goto cleanup; } ziter[0] = CGNS_NEW(cgns_ziter, 1); ziter[0]->id = id[0]; ziter[0]->link = cgi_read_link(id[0]); ziter[0]->in_link = in_link; linked = ziter[0]->link ? 1 : in_link; /* Name */ if (cgi_read_node(ziter[0]->id, ziter[0]->name, datatype, &ndim, dim_vals, &data, READ_DATA)) { cgi_error("Error reading ZoneIterativeData_t"); goto cleanup; } if (strcmp(datatype,"MT")) { cgi_error("Error in ZoneIterativeData_t node"); goto cleanup; } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, ziter[0]->id, &ziter[0]->ndescr, &ziter[0]->descr, &ziter[0]->data_class, &ziter[0]->units)) goto cleanup; /* UserDefinedData_t */ if (cgi_read_user_data(linked, ziter[0]->id, &ziter[0]->nuser_data, &ziter[0]->user_data)) goto cleanup; /* DataArray_t */ CGNS_FREE(id); if (cgi_get_nodes(ziter[0]->id, "DataArray_t", &ziter[0]->narrays, &id)) goto cleanup; if (ziter[0]->narrays==0) return CG_OK; /* If no arrays we're done. */ ziter[0]->array = CGNS_NEW(cgns_array,ziter[0]->narrays); for (i=0; i<(ziter[0]->narrays); i++) { ziter[0]->array[i].id = id[i]; ziter[0]->array[i].link = cgi_read_link(id[i]); ziter[0]->array[i].in_link = linked; if (cgi_read_array(&ziter[0]->array[i], "ZoneIterativeData_t", ziter[0]->id)) goto cleanup; array = &ziter[0]->array[i]; /* check data */ if (strcmp("RigidGridMotionPointers",array->name)==0 || strcmp("ArbitraryGridMotionPointers",array->name)==0 || strcmp("GridCoordinatesPointers",array->name)==0 || strcmp("FlowSolutionPointers",array->name)==0) { if (array->data_dim!=2 || array->dim_vals[0]!=32 || array->dim_vals[1]!=NumberOfSteps) { cgi_error("Error: Array '%s/%s' incorrectly sized", ziter[0]->name, array->name); goto cleanup; } if (strcmp(array->data_type,"C1")) { cgi_error("Incorrect data type for %s under %s",array->name,ziter[0]->name); goto cleanup; } } } /* loop through arrays */ CGNS_FREE(id); return CG_OK; cleanup: CGNS_FREE(id); return CG_ERROR; } int cgi_read_user_data(int in_link, double parent_id, int *nuser_data, cgns_user_data **user_data) { double *id, *idi; int n, i, linked; double *IA_id, *IR_id; int nIA_t, nIR_t, nn; char_33 name; if (cgi_get_nodes(parent_id, "UserDefinedData_t", nuser_data, &id)) return CG_ERROR; if (*nuser_data<=0) { user_data[0] = 0; return CG_OK; } user_data[0] = CGNS_NEW(cgns_user_data, (*nuser_data)); for (n=0; n<(*nuser_data); n++) { user_data[0][n].id = id[n]; user_data[0][n].link = cgi_read_link(id[n]); user_data[0][n].in_link = in_link; linked = user_data[0][n].link ? 1 : in_link; /* UserDefinedData_t Name */ if (cgio_get_name(cg->cgio, user_data[0][n].id, user_data[0][n].name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* Descriptor_t, DataClass_t, DimensionalUnits_t */ if (cgi_read_DDD(linked, id[n], &user_data[0][n].ndescr, &user_data[0][n].descr, &user_data[0][n].data_class, &user_data[0][n].units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(id[n], "DataArray_t", &user_data[0][n].narrays, &idi)) return CG_ERROR; if (user_data[0][n].narrays>0) { user_data[0][n].array = CGNS_NEW(cgns_array, user_data[0][n].narrays); for (i=0; i 0) { char *fam; user_data[0][n].famname = CGNS_NEW(cgns_famname, user_data[0][n].nfamname); for (i = 0; i < user_data[0][n].nfamname; i++) { user_data[0][n].famname[i].id = idi[i]; if (cgi_read_string(idi[i], user_data[0][n].famname[i].name, &fam)) return CG_ERROR; strncpy(user_data[0][n].famname[i].family, fam, 32); CGNS_FREE(fam); } CGNS_FREE(idi); } /* Ordinal_t */ if (cgi_read_ordinal(user_data[0][n].id, &user_data[0][n].ordinal)) return CG_ERROR; /* PointSet */ /* get number of IndexArray_t and IndexRange_t nodes and their * ID */ if (cgi_get_nodes(user_data[0][n].id, "IndexArray_t", &nIA_t, &IA_id)) return CG_ERROR; if (cgi_get_nodes(user_data[0][n].id, "IndexRange_t", &nIR_t, &IR_id)) return CG_ERROR; /* initialized */ user_data[0][n].ptset = 0; for (nn=0; nncgio, IR_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"PointRange") && strcmp(name,"ElementRange")) { cgi_error("Invalid name for IndexRange_t"); return CG_ERROR; } if (user_data[0][n].ptset!=0) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } user_data[0][n].ptset = CGNS_NEW(cgns_ptset, 1); if (strcmp(name,"ElementRange")==0) user_data[0][n].ptset->type = CGNS_ENUMV( ElementRange ); else user_data[0][n].ptset->type = CGNS_ENUMV( PointRange ); user_data[0][n].ptset->id=IR_id[nn]; user_data[0][n].ptset->link=cgi_read_link(IR_id[nn]); user_data[0][n].ptset->in_link=linked; if (cgi_read_ptset(user_data[0][n].id, user_data[0][n].ptset)) return CG_ERROR; } if (nIR_t) CGNS_FREE(IR_id); for (nn=0; nncgio, IA_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointList") && strcmp(name,"ElementList")) continue; if (user_data[0][n].ptset!=0) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } user_data[0][n].ptset = CGNS_NEW(cgns_ptset, 1); if (strcmp(name,"ElementList")==0) user_data[0][n].ptset->type = CGNS_ENUMV( ElementList ); else user_data[0][n].ptset->type = CGNS_ENUMV( PointList ); user_data[0][n].ptset->id = IA_id[nn]; user_data[0][n].ptset->link = cgi_read_link(IA_id[nn]); user_data[0][n].ptset->in_link = linked; if (cgi_read_ptset(user_data[0][n].id, user_data[0][n].ptset)) return CG_ERROR; } if (nIA_t) CGNS_FREE(IA_id); /* UserDefinedData_t */ if (cgi_read_user_data(linked, user_data[0][n].id, &user_data[0][n].nuser_data, &user_data[0][n].user_data)) return CG_ERROR; } CGNS_FREE(id); return CG_OK; } int cgi_read_subregion(int in_link, double parent_id, int *nsubreg, cgns_subreg **subreg) { double *id, *idi; int n, i, linked; double *IA_id, *IR_id; int nIA_t, nIR_t, nn; char_33 data_type, name; cgns_subreg *reg; int ndim, ndescr; char *text; void *data; cgsize_t dim_vals[12]; if (cgi_get_nodes(parent_id, "ZoneSubRegion_t", nsubreg, &id)) return CG_ERROR; if (*nsubreg <= 0) { *subreg = 0; return CG_OK; } reg = CGNS_NEW(cgns_subreg, (*nsubreg)); *subreg = reg; for (n = 0; n < (*nsubreg); n++) { reg[n].id = id[n]; reg[n].link = cgi_read_link(id[n]); reg[n].in_link = in_link; linked = reg[n].link ? 1 : in_link; if (cgi_read_node(reg[n].id, reg[n].name, data_type, &ndim, dim_vals, &data, READ_DATA)) { cgi_error("Error reading ZoneSubRegion node"); return CG_ERROR; } if (ndim != 1 || dim_vals[0] != 1 || strcmp(data_type, "I4")) { cgi_error("Bad dimension value for ZoneSubRegion node"); return CG_ERROR; } reg[n].reg_dim = *((int *)data); CGNS_FREE(data); /* Descriptor_t */ if (cgi_get_nodes(id[n], "Descriptor_t", &nn, &idi)) return CG_ERROR; ndescr = 0; if (nn > 0) { for (i = 0; i < nn; i++) { if (cgi_read_string(idi[i], name, &text)) return CG_ERROR; if (0 == strcmp(name, "BCRegionName")) { reg[n].bcname = CGNS_NEW(cgns_descr, 1); reg[n].bcname->id = idi[i]; reg[n].bcname->link = cgi_read_link(idi[i]); reg[n].bcname->in_link = in_link; strcpy(reg[n].bcname->name, name); reg[n].bcname->text = text; } else if (0 == strcmp(name, "GridConnectivityRegionName")) { reg[n].gcname = CGNS_NEW(cgns_descr, 1); reg[n].gcname->id = idi[i]; reg[n].gcname->link = cgi_read_link(idi[i]); reg[n].gcname->in_link = in_link; strcpy(reg[n].gcname->name, name); reg[n].gcname->text = text; } else { CGNS_FREE(text); ndescr++; } } } if (ndescr > 0) { int j = 0; reg[n].ndescr = ndescr; reg[n].descr = CGNS_NEW(cgns_descr, ndescr); for (i = 0; i < nn; i++) { if (cgi_read_string(idi[i], name, &text)) return CG_ERROR; if (strcmp(name, "BCRegionName") && strcmp(name, "GridConnectivityRegionName")) { reg[n].descr[j].id = idi[i]; reg[n].descr[j].link = cgi_read_link(idi[i]); reg[n].descr[j].in_link = in_link; strcpy(reg[n].descr[j].name, name); reg[n].descr[j].text = text; j++; } else { CGNS_FREE(text); } } } if (nn) CGNS_FREE(idi); /* DataClass_t */ if (cgi_get_nodes(id[n], "DataClass_t", &nn, &idi)) return CG_ERROR; if (nn > 0) { if (cgi_read_string(idi[0], name, &text)) return CG_ERROR; cgi_DataClass(text, ®[n].data_class); CGNS_FREE(text); CGNS_FREE(idi); } /* DimensionalUnits_t */ if (cgi_read_units(in_link, id[n], ®[n].units)) return CG_ERROR; /* DataArray_t */ if (cgi_get_nodes(id[n], "DataArray_t", ®[n].narrays, &idi)) return CG_ERROR; if (reg[n].narrays > 0) { reg[n].array = CGNS_NEW(cgns_array, reg[n].narrays); for (i = 0; i < reg[n].narrays; i++) { reg[n].array[i].id = idi[i]; reg[n].array[i].link = cgi_read_link(idi[i]); reg[n].array[i].in_link = linked; if (cgi_read_array(®[n].array[i], "ZoneSubRegion_t", reg[n].id)) return CG_ERROR; } CGNS_FREE(idi); } /* GridLocation_t */ if (cgi_read_location(reg[n].id, reg[n].name, ®[n].location)) return CG_ERROR; /* FamilyName_t */ if (cgi_read_family_name(linked, reg[n].id, reg[n].name, reg[n].family_name)) return CG_ERROR; /* CPEX 0034 */ if (cgi_get_nodes(reg[n].id, "AdditionalFamilyName_t", ®[n].nfamname, &idi)) return CG_ERROR; if (reg[n].nfamname > 0) { char *fam; reg[n].famname = CGNS_NEW(cgns_famname, reg[n].nfamname); for (i = 0; i < reg[n].nfamname; i++) { reg[n].famname[i].id = idi[i]; if (cgi_read_string(idi[i], reg[n].famname[i].name, &fam)) return CG_ERROR; strncpy(reg[n].famname[i].family, fam, 32); CGNS_FREE(fam); } CGNS_FREE(idi); } /* PointSet */ /* get number of IndexArray_t and IndexRange_t nodes and their ID */ if (cgi_get_nodes(reg[n].id, "IndexArray_t", &nIA_t, &IA_id)) return CG_ERROR; if (cgi_get_nodes(reg[n].id, "IndexRange_t", &nIR_t, &IR_id)) return CG_ERROR; /* initialized */ reg[n].ptset = 0; for (nn = 0; nn < nIR_t; nn++) { if (cgio_get_name(cg->cgio, IR_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name,"PointRange")) { cgi_error("Invalid name for IndexRange_t"); return CG_ERROR; } if (reg[n].ptset != NULL) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } reg[n].ptset = CGNS_NEW(cgns_ptset, 1); reg[n].ptset->type = CGNS_ENUMV(PointRange); reg[n].ptset->id=IR_id[nn]; reg[n].ptset->link=cgi_read_link(IR_id[nn]); reg[n].ptset->in_link=linked; if (cgi_read_ptset(reg[n].id, reg[n].ptset)) return CG_ERROR; } if (nIR_t) CGNS_FREE(IR_id); for (nn = 0; nn < nIA_t; nn++) { if (cgio_get_name(cg->cgio, IA_id[nn], name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } if (strcmp(name, "PointList")) continue; if (reg[n].ptset != NULL) { cgi_error("Multiple definition of boundary patch found"); return CG_ERROR; } reg[n].ptset = CGNS_NEW(cgns_ptset, 1); reg[n].ptset->type = CGNS_ENUMV(PointList); reg[n].ptset->id = IA_id[nn]; reg[n].ptset->link = cgi_read_link(IA_id[nn]); reg[n].ptset->in_link = linked; if (cgi_read_ptset(reg[n].id, reg[n].ptset)) return CG_ERROR; } if (nIA_t) CGNS_FREE(IA_id); /* Rind Planes */ if (cgi_read_rind(reg[n].id, ®[n].rind_planes)) return CG_ERROR; /* UserDefinedData_t */ if (cgi_read_user_data(linked, reg[n].id, ®[n].nuser_data, ®[n].user_data)) return CG_ERROR; } CGNS_FREE(id); return CG_OK; } int cgi_read_node(double node_id, char_33 name, char_33 data_type, int *ndim, cgsize_t *dim_vals, void **data, int data_flag) { int n; cgsize_t size=1; /* name of node */ if (cgio_get_name(cg->cgio, node_id, name)) { cg_io_error("cgio_get_name"); return CG_ERROR; } /* read node data type */ if (cgio_get_data_type(cg->cgio, node_id, data_type)) { cg_io_error("cgio_get_data_type"); return CG_ERROR; } if (strcmp(data_type,"MT")==0) { *ndim = 0; return CG_OK; } if (cgio_get_dimensions(cg->cgio, node_id, ndim, dim_vals)) { cg_io_error("cgio_get_dimensions"); return CG_ERROR; } /* Skipping data */ if (!data_flag) return CG_OK; /* allocate data */ for (n=0; n<(*ndim); n++) size*=dim_vals[n]; if (size<=0) { cgi_error("Error reading node %s",name); return CG_ERROR; } if (strcmp(data_type,"I4")==0) data[0]=CGNS_NEW(int, size); else if (strcmp(data_type,"I8")==0) data[0]=CGNS_NEW(cglong_t, size); else if (strcmp(data_type,"R4")==0) data[0]=CGNS_NEW(float, size); else if (strcmp(data_type,"R8")==0) data[0]=CGNS_NEW(double, size); else if (strcmp(data_type,"C1")==0) data[0]=CGNS_NEW(char, size+1); /* read data */ if (cgio_read_all_data(cg->cgio, node_id, data[0])) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } return CG_OK; } cgns_link *cgi_read_link (double node_id) { int len; cgns_link *link; if (cgio_is_link(cg->cgio, node_id, &len)) { cg_io_error ("cgio_is_link"); return CG_OK; } if (len > 0) { int file_len, name_len; if (cgio_link_size (cg->cgio, node_id, &file_len, &name_len)) { cg_io_error ("cgio_link_size"); return CG_OK; } len = name_len + file_len + 2; link = (cgns_link *) cgi_malloc (1, len + sizeof(cgns_link)); link->filename = (char *)(link + 1); link->name_in_file = link->filename + file_len + 1; if (cgio_get_link(cg->cgio, node_id, link->filename, link->name_in_file)) { free (link); cg_io_error ("cgio_get_link"); return CG_OK; } link->filename[file_len] = 0; link->name_in_file[name_len] = 0; return link; } return CG_OK; } int cgi_datasize(int Idim, cgsize_t *CurrentDim, CGNS_ENUMV(GridLocation_t) location, int *rind_planes, cgsize_t *DataSize) { int j; if (location==CGNS_ENUMV( Vertex )) { for (j=0; j CG_MAX_INT32) { cgi_error("array size exceeds that for a 32-bit integer"); return CG_ERROR; } return CG_OK; } int cgi_check_location(int dim, CGNS_ENUMT(ZoneType_t) type, CGNS_ENUMT(GridLocation_t) loc) { if (loc == CGNS_ENUMV(Vertex) || loc == CGNS_ENUMV(CellCenter)) return CG_OK; if (loc == CGNS_ENUMV(EdgeCenter)) { if (dim >= 2) return CG_OK; } else if (loc == CGNS_ENUMV(FaceCenter)) { if (dim >= 3) return CG_OK; } else if (loc == CGNS_ENUMV(IFaceCenter) || loc == CGNS_ENUMV(JFaceCenter) || loc == CGNS_ENUMV(KFaceCenter)) { if (type != CGNS_ENUMV(Structured)) { cgi_error("GridLocation [IJK]FaceCenter only valid for Structured Grid"); return CG_ERROR; } if (dim >= 3) return CG_OK; } cgi_error("GridLocation %s not valid for CellDimension %d", cg_GridLocationName(loc), dim); return CG_ERROR; } int cgi_read_int_data(double id, char_33 data_type, cgsize_t cnt, cgsize_t *data) { cgsize_t n; #if CG_SIZEOF_SIZE == 64 if (0 == strcmp(data_type, "I4")) { int *pnts = (int *)malloc((size_t)(cnt*sizeof(int))); if (NULL == pnts) { cgi_error("Error allocating I4->I8 data array..."); return CG_ERROR; } if (cgio_read_all_data(cg->cgio, id, (void *)pnts)) { cg_io_error("cgio_read_all_data"); CGNS_FREE(pnts); return CG_ERROR; } for (n = 0; n < cnt; n++) data[n] = (cgsize_t)pnts[n]; CGNS_FREE(pnts); } #else if (0 == strcmp(data_type, "I8")) { cglong_t *pnts = (cglong_t *)malloc((size_t)(cnt*sizeof(cglong_t))); if (NULL == pnts) { cgi_error("Error allocating I8->I4 data array..."); return CG_ERROR; } if (cgio_read_all_data(cg->cgio, id, (void *)pnts)) { cg_io_error("cgio_read_all_data"); CGNS_FREE(pnts); return CG_ERROR; } for (n = 0; n < cnt; n++) data[n] = (cgsize_t)pnts[n]; CGNS_FREE(pnts); } #endif else { if (cgio_read_all_data(cg->cgio, id, (void *)data)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } } return CG_OK; } int cgi_convert_data(cgsize_t cnt, CGNS_ENUMT(DataType_t) from_type, const void *from_data, CGNS_ENUMT(DataType_t) to_type, void *to_data) { int ierr = 0; cgsize_t n; if (from_type == CGNS_ENUMV(Character)) { const char *src = (const char *)from_data; /* C1 -> C1 */ if (to_type == CGNS_ENUMV(Character)) { char *dest = (char *)to_data; for (n = 0; n < cnt; n++) dest[n] = (char)src[n]; } /* C1 -> I4 */ else if (to_type == CGNS_ENUMV(Integer)) { int *dest = (int *)to_data; for (n = 0; n < cnt; n++) dest[n] = (int)src[n]; } /* C1 -> I8 */ else if (to_type == CGNS_ENUMV(LongInteger)) { cglong_t *dest = (cglong_t *)to_data; for (n = 0; n < cnt; n++) dest[n] = (cglong_t)src[n]; } /* C1 -> R4 */ else if (to_type == CGNS_ENUMV(RealSingle)) { float *dest = (float *)to_data; for (n = 0; n < cnt; n++) dest[n] = (float)src[n]; } /* C1 -> R8 */ else if (to_type == CGNS_ENUMV(RealDouble)) { double *dest = (double *)to_data; for (n = 0; n < cnt; n++) dest[n] = (double)src[n]; } else { ierr = 1; } } else if (from_type == CGNS_ENUMV(Integer)) { const int *src = (const int *)from_data; /* I4 -> C1 */ if (to_type == CGNS_ENUMV(Character)) { char *dest = (char *)to_data; for (n = 0; n < cnt; n++) dest[n] = (char)src[n]; } /* I4 -> I4 */ else if (to_type == CGNS_ENUMV(Integer)) { int *dest = (int *)to_data; for (n = 0; n < cnt; n++) dest[n] = (int)src[n]; } /* I4 -> I8 */ else if (to_type == CGNS_ENUMV(LongInteger)) { cglong_t *dest = (cglong_t *)to_data; for (n = 0; n < cnt; n++) dest[n] = (cglong_t)src[n]; } /* I4 -> R4 */ else if (to_type == CGNS_ENUMV(RealSingle)) { float *dest = (float *)to_data; for (n = 0; n < cnt; n++) dest[n] = (float)src[n]; } /* I4 -> R8 */ else if (to_type == CGNS_ENUMV(RealDouble)) { double *dest = (double *)to_data; for (n = 0; n < cnt; n++) dest[n] = (double)src[n]; } else { ierr = 1; } } else if (from_type == CGNS_ENUMV(LongInteger)) { const cglong_t *src = (const cglong_t *)from_data; /* I8 -> C1 */ if (to_type == CGNS_ENUMV(Character)) { char *dest = (char *)to_data; for (n = 0; n < cnt; n++) dest[n] = (char)src[n]; } /* I8 -> I4 */ else if (to_type == CGNS_ENUMV(Integer)) { int *dest = (int *)to_data; for (n = 0; n < cnt; n++) dest[n] = (int)src[n]; } /* I8 -> I8 */ else if (to_type == CGNS_ENUMV(LongInteger)) { cglong_t *dest = (cglong_t *)to_data; for (n = 0; n < cnt; n++) dest[n] = (cglong_t)src[n]; } /* I8 -> R4 */ else if (to_type == CGNS_ENUMV(RealSingle)) { float *dest = (float *)to_data; for (n = 0; n < cnt; n++) dest[n] = (float)src[n]; } /* I8 -> R8 */ else if (to_type == CGNS_ENUMV(RealDouble)) { double *dest = (double *)to_data; for (n = 0; n < cnt; n++) dest[n] = (double)src[n]; } else { ierr = 1; } } else if (from_type == CGNS_ENUMV(RealSingle)) { const float *src = (const float *)from_data; /* R4 -> C1 */ if (to_type == CGNS_ENUMV(Character)) { char *dest = (char *)to_data; for (n = 0; n < cnt; n++) dest[n] = (char)src[n]; } /* R4 -> I4 */ else if (to_type == CGNS_ENUMV(Integer)) { int *dest = (int *)to_data; for (n = 0; n < cnt; n++) dest[n] = (int)src[n]; } /* R4 -> I8 */ else if (to_type == CGNS_ENUMV(LongInteger)) { cglong_t *dest = (cglong_t *)to_data; for (n = 0; n < cnt; n++) dest[n] = (cglong_t)src[n]; } /* R4 -> R4 */ else if (to_type == CGNS_ENUMV(RealSingle)) { float *dest = (float *)to_data; for (n = 0; n < cnt; n++) dest[n] = (float)src[n]; } /* R4 -> R8 */ else if (to_type == CGNS_ENUMV(RealDouble)) { double *dest = (double *)to_data; for (n = 0; n < cnt; n++) dest[n] = (double)src[n]; } else { ierr = 1; } } else if (from_type == CGNS_ENUMV(RealDouble)) { const double *src = (const double *)from_data; /* R8 -> C1 */ if (to_type == CGNS_ENUMV(Character)) { char *dest = (char *)to_data; for (n = 0; n < cnt; n++) dest[n] = (char)src[n]; } /* R8 -> I4 */ else if (to_type == CGNS_ENUMV(Integer)) { int *dest = (int *)to_data; for (n = 0; n < cnt; n++) dest[n] = (int)src[n]; } /* R8 -> I8 */ else if (to_type == CGNS_ENUMV(LongInteger)) { cglong_t *dest = (cglong_t *)to_data; for (n = 0; n < cnt; n++) dest[n] = (cglong_t)src[n]; } /* R8 -> R4 */ else if (to_type == CGNS_ENUMV(RealSingle)) { float *dest = (float *)to_data; for (n = 0; n < cnt; n++) dest[n] = (float)src[n]; } /* R8 -> R8 */ else if (to_type == CGNS_ENUMV(RealDouble)) { double *dest = (double *)to_data; for (n = 0; n < cnt; n++) dest[n] = (double)src[n]; } else { ierr = 1; } } else { ierr = 1; } if (ierr) cgi_error("invalid data type conversion %d->%d", from_type, to_type); return ierr; } /***********************************************************************\ * Write a CGNS file from in-memory data * \***********************************************************************/ int cgi_write(int file_number) { cgns_base *base; int n, b; cgsize_t dim_vals; double dummy_id; float FileVersion; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* write version number */ dim_vals = 1; /* Changed due to round off error on CRAY: FileVersion = (float)CGNSLibVersion/1000; */ /* The FileVersion will always be the latest if (cg->version == 1050) FileVersion = (float) 1.05; else if (cg->version == 1100) FileVersion = (float) 1.10; else if (cg->version == 1200) FileVersion = (float) 1.2; else if (cg->version == 1270) FileVersion = (float) 1.27; else if (cg->version == 2000) FileVersion = (float) 2.00; else if (cg->version == 2100) FileVersion = (float) 2.10; else { cgi_error("FileVersion can't be set in cgi_write!"); return CG_ERROR; } */ FileVersion = (float) CGNS_DOTVERS; if (cgi_new_node(cg->rootid, "CGNSLibraryVersion", "CGNSLibraryVersion_t", &dummy_id, "R4", 1, &dim_vals, (void *)&FileVersion)) return CG_ERROR; /* write all CGNSBase_t nodes in ADF file */ for (b=0; bnbases; b++) { int *data; data = CGNS_NEW(int, 2); base = &(cg->base[b]); data[0]=base->cell_dim; data[1]=base->phys_dim; /* Create the CGNSBase_t nodes */ dim_vals=2; if (cgi_new_node(cg->rootid, base->name, "CGNSBase_t", &base->id, "I4", 1, &dim_vals, (void *)data)) return CG_ERROR; CGNS_FREE(data); /* set Global variable */ Cdim = base->cell_dim; Pdim = base->phys_dim; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(base->id, &base->descr[n])) return CG_ERROR; /* ReferenceState_t */ if (base->state && cgi_write_state(base->id, base->state)) return CG_ERROR; /* Gravity_t */ if (base->gravity && cgi_write_gravity(base->id, base->gravity)) return CG_ERROR; /* Axisymmetry_t */ if (base->axisym && cgi_write_axisym(base->id, base->axisym)) return CG_ERROR; /* RotatingCoordinates_t */ if (base->rotating && cgi_write_rotating(base->id, base->rotating)) return CG_ERROR; /* Zone_t */ for (n=0; nnzones; n++) { if (cgi_write_zone(base->id, &base->zone[n])) return CG_ERROR; } /* Family_t */ for (n=0; nnfamilies; n++) if (cgi_write_family(base->id, &base->family[n])) return CG_ERROR; /* DataClass_t */ if (base->data_class && cgi_write_dataclass(base->id, base->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (base->units && cgi_write_units(base->id, base->units)) return CG_ERROR; /* ConvergenceHistory_t */ if (base->converg && cgi_write_converg(base->id, base->converg)) return CG_ERROR; /* FlowEquationSet_t */ if (base->equations && cgi_write_equations(base->id, base->equations)) return CG_ERROR; /* IntegralData_t */ for (n=0; nnintegrals; n++) if (cgi_write_integral(base->id, &base->integral[n])) return CG_ERROR; /* SimulationType_t */ if (base->type) { dim_vals = (cgsize_t)strlen(SimulationTypeName[base->type]); if (cgi_new_node(base->id, "SimulationType", "SimulationType_t", &base->type_id, "C1", 1, &dim_vals, (void *)SimulationTypeName[base->type])) return CG_ERROR; } /* BaseIterativeData_t */ if (base->biter && cgi_write_biter(base->id, base->biter)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(base->id, &base->user_data[n])) return CG_ERROR; } return CG_OK; } int cgi_write_zone(double parent_id, cgns_zone *zone) { int n; cgsize_t dim_vals[2]; double dummy_id; Idim = zone->index_dim; if (zone->link) { return cgi_write_link(parent_id, zone->name, zone->link, &zone->id); } /* Create the Zone_t nodes */ dim_vals[0]= Idim; dim_vals[1]= 3; if (cgi_new_node(parent_id, zone->name, "Zone_t", &zone->id, CG_SIZE_DATATYPE, 2, dim_vals, (void *)zone->nijk)) return CG_ERROR; /* write ZoneType */ dim_vals[0] = (cgsize_t)strlen(ZoneTypeName[zone->type]); if (cgi_new_node(zone->id, "ZoneType", "ZoneType_t", &dummy_id, "C1", 1, dim_vals, (void *)ZoneTypeName[zone->type])) return CG_ERROR; /* set Global variable for (n=0; nnijk[n]; */ /* GridCoordinates_t */ for (n=0; nnzcoor; n++) if (cgi_write_zcoor(zone->id, &zone->zcoor[n])) return CG_ERROR; /* FamilyName_t */ if (zone->family_name[0]!='\0') { dim_vals[0] = (cgsize_t)strlen(zone->family_name); if (cgi_new_node(zone->id, "FamilyName", "FamilyName_t", &dummy_id, "C1", 1, dim_vals, (void *)zone->family_name)) return CG_ERROR; } /* CPEX 0034 */ for (n = 0; n < zone->nfamname; n++) { dim_vals[0] = (cgsize_t)strlen(zone->famname[n].family); if (cgi_new_node(zone->id, zone->famname[n].name, "AdditionalFamilyName_t", &dummy_id, "C1", 1, dim_vals, (void *)zone->famname[n].family)) return CG_ERROR; } /* Elements_t */ for (n=0; nnsections; n++) if (cgi_write_section(zone->id, &zone->section[n])) return CG_ERROR; /* FlowSolution_t */ for (n=0; nnsols; n++) if (cgi_write_sol(zone->id, &zone->sol[n])) return CG_ERROR; /* ZoneGridConnectivity_t */ for (n=0; nnzconn; n++) if (cgi_write_zconn(zone->id, &zone->zconn[n])) return CG_ERROR; /* ZoneBC_t */ if (zone->zboco && cgi_write_zboco(zone->id, zone->zboco)) return CG_ERROR; /* DescreteData_t */ for (n=0; nndiscrete; n++) if (cgi_write_discrete(zone->id, &zone->discrete[n])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(zone->id, &zone->descr[n])) return CG_ERROR; /* ReferenceState_t */ if (zone->state && cgi_write_state(zone->id, zone->state)) return CG_ERROR; /* DataClass_t */ if (zone->data_class && cgi_write_dataclass(zone->id, zone->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (zone->units && cgi_write_units(zone->id, zone->units)) return CG_ERROR; /* ConvergenceHistory_t */ if (zone->converg && cgi_write_converg(zone->id, zone->converg)) return CG_ERROR; /* FlowEquationSet_t */ if (zone->equations && cgi_write_equations(zone->id, zone->equations)) return CG_ERROR; /* IntegralData_t */ for (n=0; nnintegrals; n++) if (cgi_write_integral(zone->id, &zone->integral[n])) return CG_ERROR; /* Ordinal_t */ if (zone->ordinal && cgi_write_ordinal(zone->id, zone->ordinal)) return CG_ERROR; /* RigidGridMotion_t */ for (n=0; nnrmotions; n++) if (cgi_write_rmotion(zone->id, &zone->rmotion[n])) return CG_ERROR; /* ArbitraryGridMotion_t */ for (n=0; nnamotions; n++) if (cgi_write_amotion(zone->id, &zone->amotion[n])) return CG_ERROR; /* ZoneIterativeData_t */ if (zone->ziter && cgi_write_ziter(zone->id, zone->ziter)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(zone->id, &zone->user_data[n])) return CG_ERROR; /* RotatingCoordinates_t */ if (zone->rotating && cgi_write_rotating(zone->id, zone->rotating)) return CG_ERROR; return CG_OK; } int cgi_write_family(double parent_id, cgns_family *family) { int n; cgsize_t dim_vals; if (family->link) { return cgi_write_link(parent_id, family->name, family->link, &family->id); } /* Family_t */ if (cgi_new_node(parent_id, family->name, "Family_t", &family->id, "MT", 0, 0, 0)) return CG_ERROR; /* CPEX 0033 */ for (n = 0; n < family->nfamname; n++) { dim_vals = (cgsize_t)strlen(family->famname[n].family); if (cgi_new_node(family->id, family->famname[n].name, "FamilyName_t", &family->famname[n].id, "C1", 1, &dim_vals, (void *)family->famname[n].family)) return CG_ERROR; } /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(family->id, &family->descr[n])) return CG_ERROR; /* FamilyBC_t */ for (n=0; nnfambc; n++) { cgns_fambc *fambc = &family->fambc[n]; if (fambc->link) { if (cgi_write_link(family->id, fambc->name, fambc->link, &fambc->id)) return CG_ERROR; } else { int i; dim_vals = (cgsize_t)strlen(BCTypeName[fambc->type]); if (cgi_new_node(family->id, fambc->name, "FamilyBC_t", &fambc->id, "C1", 1, &dim_vals, BCTypeName[fambc->type])) return CG_ERROR; /* FamilyBCDataSet_t */ for (i=0; i < fambc->ndataset; i++) if (cgi_write_dataset(fambc->id, "FamilyBCDataSet_t", &fambc->dataset[i])) return CG_ERROR; } } /* GeometryReference_t */ for (n=0; nngeos; n++) { int i; double dummy_id; cgns_geo *geo = &family->geo[n]; if (geo->link) { if (cgi_write_link(family->id, geo->name, geo->link, &geo->id)) return CG_ERROR; } else { if (cgi_new_node(family->id, geo->name, "GeometryReference_t", &geo->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor */ for (i=0; indescr; i++) if (cgi_write_descr(geo->id, &geo->descr[i])) return CG_ERROR; /* GeometryFile */ dim_vals = (cgsize_t)strlen(geo->file); if (cgi_new_node(geo->id, "GeometryFile", "GeometryFile_t", &dummy_id, "C1", 1, &dim_vals, geo->file)) return CG_ERROR; /* GeometryFormat */ dim_vals = (cgsize_t)strlen(geo->format); if (cgi_new_node(geo->id, "GeometryFormat", "GeometryFormat_t", &dummy_id, "C1", 1, &dim_vals, geo->format)) return CG_ERROR; /* GeometryEntities */ for (i=0; inpart; i++) { if (cgi_new_node(geo->id, geo->part[i].name, "GeometryEntity_t", &dummy_id, "MT", 0, 0, 0)) return CG_ERROR; } /* UserDefinedData_t */ for (i=0; inuser_data; i++) { if (cgi_write_user_data(geo->id, &geo->user_data[i])) return CG_ERROR; } } } /* Ordinal_t */ if (family->ordinal && cgi_write_ordinal(family->id, family->ordinal)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(family->id, &family->user_data[n])) return CG_ERROR; /* RotatingCoordinates_t */ if (family->rotating && cgi_write_rotating(family->id, family->rotating)) return CG_ERROR; return CG_OK; } int cgi_write_section(double parent_id, cgns_section *section) { int n, data[2]; cgsize_t dim_vals; double dummy_id; if (section->link) { return cgi_write_link(parent_id, section->name, section->link, §ion->id); } /* Elements_t */ dim_vals = 2; data[0]=section->el_type; data[1]=section->el_bound; if (cgi_new_node(parent_id, section->name, "Elements_t", §ion->id, "I4", 1, &dim_vals, data)) return CG_ERROR; /* ElementRange */ if (cgi_new_node(section->id, "ElementRange", "IndexRange_t", &dummy_id, CG_SIZE_DATATYPE, 1, &dim_vals, section->range)) return CG_ERROR; /* ElementConnectivity */ if (section->connect && cgi_write_array(section->id, section->connect)) return CG_ERROR; /* ElementStartOffset */ if (section->connect_offset && cgi_write_array(section->id, section->connect_offset)) return CG_ERROR; /* ParentData */ if (section->parelem && cgi_write_array(section->id, section->parelem)) return CG_ERROR; if (section->parface && cgi_write_array(section->id, section->parface)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(section->id, §ion->descr[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(section->id, §ion->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_zcoor(double parent_id, cgns_zcoor *zcoor) { int n; if (zcoor->link) { return cgi_write_link(parent_id, zcoor->name, zcoor->link, &zcoor->id); } /* GridCoordinates_t */ if (cgi_new_node(parent_id, zcoor->name, "GridCoordinates_t", &zcoor->id, "MT", 0, 0, 0)) return CG_ERROR; /* Rind_t */ if (cgi_write_rind(zcoor->id, zcoor->rind_planes, Idim)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(zcoor->id, &zcoor->descr[n])) return CG_ERROR; /* DataClass_t */ if (zcoor->data_class && cgi_write_dataclass(zcoor->id, zcoor->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (zcoor->units && cgi_write_units(zcoor->id, zcoor->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nncoords; n++) if (cgi_write_array(zcoor->id, &zcoor->coord[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(zcoor->id, &zcoor->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_sol(double parent_id, cgns_sol *sol) { int n; cgsize_t dim_vals; double dummy_id; if (sol->link) { return cgi_write_link(parent_id, sol->name, sol->link, &sol->id); } /* FlowSolution_t */ if (cgi_new_node(parent_id, sol->name, "FlowSolution_t", &sol->id, "MT", 0, 0, 0)) return CG_ERROR; /* GridLocation_t */ if (sol->location!=CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[sol->location]); if (cgi_new_node(sol->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[sol->location])) return CG_ERROR; } /* Rind_t */ if (cgi_write_rind(sol->id, sol->rind_planes, Idim)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(sol->id, &sol->descr[n])) return CG_ERROR; /* DataClass_t */ if (sol->data_class && cgi_write_dataclass(sol->id, sol->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (sol->units && cgi_write_units(sol->id, sol->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnfields; n++) if (cgi_write_array(sol->id, &sol->field[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(sol->id, &sol->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_zconn(double parent_id, cgns_zconn *zconn) { int n; if (zconn->link) { return cgi_write_link(parent_id, zconn->name, zconn->link, &zconn->id); } /* ZoneGridConnectivity_t */ if (cgi_new_node(parent_id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; /* GridConnectivity1to1_t */ for (n=0; nn1to1; n++) if (cgi_write_1to1(zconn->id, &zconn->one21[n])) return CG_ERROR; /* GridConnectivity_t */ for (n=0; nnconns; n++) if (cgi_write_conns(zconn->id, &zconn->conn[n])) return CG_ERROR; /* OversetHoles_t */ for (n=0; nnholes; n++) if (cgi_write_holes(zconn->id, &zconn->hole[n])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(zconn->id, &zconn->descr[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(zconn->id, &zconn->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_1to1(double parent_id, cgns_1to1 *one21) { int n; cgsize_t dim_vals; double dummy_id; cgns_ptset *ptset; if (one21->link) { return cgi_write_link(parent_id, one21->name, one21->link, &one21->id); } dim_vals = (cgsize_t)strlen(one21->donor); if (cgi_new_node(parent_id, one21->name, "GridConnectivity1to1_t", &one21->id, "C1", 1, &dim_vals, one21->donor)) return CG_ERROR; /* Transform */ dim_vals = Idim; if (cgi_new_node(one21->id, "Transform", "\"int[IndexDimension]\"", &dummy_id, "I4", 1, &dim_vals, (void *)one21->transform)) return CG_ERROR; /* PointRange & PointRangeDonor: Move nodes to their final positions */ ptset = &(one21->ptset); if (cgi_move_node(cg->rootid, ptset->id, one21->id, PointSetTypeName[ptset->type])) return CG_ERROR; ptset = &(one21->dptset); if (cgi_move_node(cg->rootid, ptset->id, one21->id, PointSetTypeName[ptset->type])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(one21->id, &one21->descr[n])) return CG_ERROR; /* Ordinal_t */ if (one21->ordinal && cgi_write_ordinal(one21->id, one21->ordinal)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(one21->id, &one21->user_data[n])) return CG_ERROR; /* GridConnectivityProperty_t */ if (one21->cprop && cgi_write_cprop(one21->id, one21->cprop)) return CG_ERROR; return CG_OK; } int cgi_write_conns(double parent_id, cgns_conn *conn) { int n; cgsize_t dim_vals; double dummy_id; cgns_ptset *ptset; if (conn->link) { return cgi_write_link(parent_id, conn->name, conn->link, &conn->id); } dim_vals = (cgsize_t)strlen(conn->donor); if (cgi_new_node(parent_id, conn->name, "GridConnectivity_t", &conn->id, "C1", 1, &dim_vals, conn->donor)) return CG_ERROR; /* GridConnectivityType_t */ dim_vals = (cgsize_t)strlen(GridConnectivityTypeName[conn->type]); if (cgi_new_node(conn->id, "GridConnectivityType", "GridConnectivityType_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridConnectivityTypeName[conn->type])) return CG_ERROR; /* write GridLocation */ if (conn->location!=CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[conn->location]); if (cgi_new_node(conn->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[conn->location])) return CG_ERROR; } /* PointRange or PointList: Move node to its final position */ ptset = &(conn->ptset); if (cgi_move_node(cg->rootid, ptset->id, conn->id, PointSetTypeName[ptset->type])) return CG_ERROR; /* Cell or Point ListDonor: Move node to its final position */ ptset = &(conn->dptset); if (ptset->id) { if (cgi_move_node(cg->rootid, ptset->id, conn->id, PointSetTypeName[ptset->type])) return CG_ERROR; } /* InterpolantsDonor */ if (conn->interpolants) { if (cgi_write_array(conn->id, conn->interpolants)) return CG_ERROR; } /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(conn->id, &conn->descr[n])) return CG_ERROR; /* Ordinal_t */ if (conn->ordinal && cgi_write_ordinal(conn->id, conn->ordinal)) return CG_ERROR; /* GridConnectivityProperty_t */ if (conn->cprop && cgi_write_cprop(conn->id, conn->cprop)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(conn->id, &conn->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_cprop(double parent_id, cgns_cprop *cprop) { cgsize_t dim_vals; int n; double dummy_id; if (cprop->link) { return cgi_write_link(parent_id, "GridConnectivityProperty", cprop->link, &cprop->id); } /* GridConnectivityProperty_t */ if (cgi_new_node(parent_id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(cprop->id, &cprop->descr[n])) return CG_ERROR; /* AverageInterface_t */ if (cprop->caverage) { cgns_caverage *caverage = cprop->caverage; if (caverage->link) { if (cgi_write_link(cprop->id, "AverageInterface", caverage->link, &caverage->id)) return CG_ERROR; } else { if (cgi_new_node(cprop->id, "AverageInterface", "AverageInterface_t", &caverage->id, "MT", 0, 0, 0)) return CG_ERROR; /* AverageInterface_t/Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(caverage->id, &caverage->descr[n])) return CG_ERROR; /* AverageInterface_t/AverageInterfaceType_t */ dim_vals = (cgsize_t)strlen(AverageInterfaceTypeName[caverage->type]); if (cgi_new_node(caverage->id, "AverageInterfaceType", "AverageInterfaceType_t", &dummy_id, "C1", 1, &dim_vals, (void *)AverageInterfaceTypeName[caverage->type])) return CG_ERROR; /* AverageInterface_t/UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(caverage->id, &caverage->user_data[n])) return CG_ERROR; } } /* Periodic_t */ if (cprop->cperio) { cgns_cperio *cperio = cprop->cperio; if (cperio->link) { if (cgi_write_link(cprop->id, "Periodic", cperio->link, &cperio->id)) return CG_ERROR; } else { if (cgi_new_node(cprop->id, "Periodic", "Periodic_t", &cperio->id, "MT", 0, 0, 0)) return CG_ERROR; /* Periodic_t/Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(cperio->id, &cperio->descr[n])) return CG_ERROR; /* Periodic_t/DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(cperio->id, &cperio->array[n])) return CG_ERROR; /* Periodic_t/DataClass_t */ if (cperio->data_class && cgi_write_dataclass(cperio->id, cperio->data_class)) return CG_ERROR; /* Periodic_t/DimensionalUnits_t */ if (cperio->units && cgi_write_units(cperio->id, cperio->units)) return CG_ERROR; /* Periodic_t/UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(cperio->id, &cperio->user_data[n])) return CG_ERROR; } } /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(cprop->id, &cprop->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_holes(double parent_id, cgns_hole *hole) { int n; cgsize_t dim_vals; double dummy_id; char PointSetName[33]; cgns_ptset *ptset; if (hole->link) { return cgi_write_link(parent_id, hole->name, hole->link, &hole->id); } /* OversetHoles_t */ if (cgi_new_node(parent_id, hole->name, "OversetHoles_t", &hole->id, "MT", 0, 0, 0)) return CG_ERROR; /* GridLocation_t */ if (hole->location!=CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[hole->location]); if (cgi_new_node(hole->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[hole->location])) return CG_ERROR; } /* PointRange(s) and PointList */ for (n=0; nnptsets; n++) { ptset = &(hole->ptset[n]); if (ptset->type == CGNS_ENUMV( PointRange )) sprintf(PointSetName,"PointRange%d",n+1); else sprintf(PointSetName,"PointSetTypeName[ptset->type]"); /* Move node to its final position */ if (cgi_move_node(cg->rootid, ptset->id, hole->id, PointSetName)) return CG_ERROR; } /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(hole->id, &hole->descr[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(hole->id, &hole->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_zboco(double parent_id, cgns_zboco *zboco) { int n; if (zboco->link) { return cgi_write_link(parent_id, "ZoneBC", zboco->link, &zboco->id); } /* ZoneBC_t */ if (cgi_new_node(parent_id, "ZoneBC", "ZoneBC_t", &zboco->id, "MT", 0, 0, 0)) return CG_ERROR; /* BC_t */ for (n=0; nnbocos; n++) if (cgi_write_boco(zboco->id, &zboco->boco[n])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(zboco->id, &zboco->descr[n])) return CG_ERROR; /* ReferenceState_t */ if (zboco->state && cgi_write_state(zboco->id, zboco->state)) return CG_ERROR; /* DataClass_t */ if (zboco->data_class && cgi_write_dataclass(zboco->id, zboco->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (zboco->units && cgi_write_units(zboco->id, zboco->units)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(zboco->id, &zboco->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_boco(double parent_id, cgns_boco *boco) { cgsize_t dim_vals; int n; double dummy_id; if (boco->link) { return cgi_write_link(parent_id, boco->name, boco->link, &boco->id); } /* BC_t */ dim_vals = (cgsize_t)strlen(BCTypeName[boco->type]); if (cgi_new_node(parent_id, boco->name, "BC_t", &boco->id, "C1", 1, &dim_vals, BCTypeName[boco->type])) return CG_ERROR; /* PointRange, PointList: Move node to its final position */ if (boco->ptset) { /* Move node to its final position */ if (cgi_move_node(cg->rootid, boco->ptset->id, boco->id, PointSetTypeName[boco->ptset->type])) return CG_ERROR; } /* GridLocation_t */ if (boco->location != CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[boco->location]); if (cgi_new_node(boco->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[boco->location])) return CG_ERROR; } /* FamilyName_t */ if (boco->family_name[0]!='\0') { dim_vals = (cgsize_t)strlen(boco->family_name); if (cgi_new_node(boco->id, "FamilyName", "FamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)boco->family_name)) return CG_ERROR; } /* CPEX 0034 */ for (n = 0; n < boco->nfamname; n++) { dim_vals = (cgsize_t)strlen(boco->famname[n].family); if (cgi_new_node(boco->id, boco->famname[n].name, "AdditionalFamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)boco->famname[n].family)) return CG_ERROR; } /* BCDataSet_t */ for (n=0; nndataset; n++) if (cgi_write_dataset(boco->id, "BCDataSet_t", &boco->dataset[n])) return CG_ERROR; /* InwardNormalIndex */ if (boco->Nindex) { dim_vals = Idim; if (cgi_new_node(boco->id, "InwardNormalIndex", "\"int[IndexDimension]\"", &boco->index_id, "I4", 1, &dim_vals, (void *)boco->Nindex)) return CG_ERROR; } /* InwardNormalList */ if (boco->normal) { if (boco->normal->link) { if (cgi_write_link(boco->id, boco->normal->name, boco->normal->link, &boco->normal->id)) return CG_ERROR; } else { if (cgi_new_node(boco->id, boco->normal->name, "IndexArray_t", &boco->normal->id, boco->normal->data_type, boco->normal->data_dim, boco->normal->dim_vals, boco->normal->data)) return CG_ERROR; } } /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(boco->id, &boco->descr[n])) return CG_ERROR; /* ReferenceState_t */ if (boco->state && cgi_write_state(boco->id, boco->state)) return CG_ERROR; /* DataClass_t */ if (boco->data_class && cgi_write_dataclass(boco->id, boco->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (boco->units && cgi_write_units(boco->id, boco->units)) return CG_ERROR; /* Ordinal_t */ if (boco->ordinal && cgi_write_ordinal(boco->id, boco->ordinal)) return CG_ERROR; /* BCProperty_t */ if (boco->bprop && cgi_write_bprop(boco->id, boco->bprop)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(boco->id, &boco->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_bprop(double parent_id, cgns_bprop *bprop) { cgsize_t dim_vals; int n; double dummy_id; if (bprop->link) { return cgi_write_link(parent_id, "BCProperty", bprop->link, &bprop->id); } /* BCProperty_t */ if (cgi_new_node(parent_id, "BCProperty", "BCProperty_t", &bprop->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(bprop->id, &bprop->descr[n])) return CG_ERROR; /* WallFunction_t */ if (bprop->bcwall) { cgns_bcwall *bcwall = bprop->bcwall; if (bcwall->link) { if (cgi_write_link(bprop->id, "WallFunction", bcwall->link, &bcwall->id)) return CG_ERROR; } else { if (cgi_new_node(bprop->id, "WallFunction", "WallFunction_t", &bcwall->id, "MT", 0, 0, 0)) return CG_ERROR; /* WallFunction_t/Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(bcwall->id, &bcwall->descr[n])) return CG_ERROR; /* WallFunction_t/WallFunctionType_t */ dim_vals = (cgsize_t)strlen(WallFunctionTypeName[bcwall->type]); if (cgi_new_node(bcwall->id, "WallFunctionType", "WallFunctionType_t", &dummy_id, "C1", 1, &dim_vals, (void *)WallFunctionTypeName[bcwall->type])) return CG_ERROR; /* WallFunction_t/UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(bcwall->id, &bcwall->user_data[n])) return CG_ERROR; } } /* Area_t */ if (bprop->bcarea) { cgns_bcarea *bcarea = bprop->bcarea; if (bcarea->link) { if (cgi_write_link(bprop->id, "Area", bcarea->link, &bcarea->id)) return CG_ERROR; } else { if (cgi_new_node(bprop->id, "Area", "Area_t", &bcarea->id, "MT", 0, 0, 0)) return CG_ERROR; /* Area_t/Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(bcarea->id, &bcarea->descr[n])) return CG_ERROR; /* Area_t/AreaType_t */ dim_vals = (cgsize_t)strlen(AreaTypeName[bcarea->type]); if (cgi_new_node(bcarea->id, "AreaType", "AreaType_t", &dummy_id, "C1", 1, &dim_vals, (void *)AreaTypeName[bcarea->type])) return CG_ERROR; /* Area_t/DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(bcarea->id, &bcarea->array[n])) return CG_ERROR; /* Area_t/UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(bcarea->id, &bcarea->user_data[n])) return CG_ERROR; } } /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(bprop->id, &bprop->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_dataset(double parent_id, const char *label, cgns_dataset *dataset) { cgsize_t dim_vals; int n; double dummy_id; if (dataset->link) { return cgi_write_link(parent_id, dataset->name, dataset->link, &dataset->id); } /* BCDataSet_t */ dim_vals= (cgsize_t)strlen(BCTypeName[dataset->type]); if (cgi_new_node(parent_id, dataset->name, label, &dataset->id, "C1", 1, &dim_vals, (void *)BCTypeName[dataset->type])) return CG_ERROR; /* DirichletData */ if (dataset->dirichlet) { if (dataset->dirichlet->link) { if (cgi_write_link(dataset->id, "DirichletData", dataset->dirichlet->link, &dataset->dirichlet->id)) return CG_ERROR; } else { if (cgi_new_node(dataset->id, "DirichletData", "BCData_t", &dataset->dirichlet->id, "MT", 0, 0, 0)) return CG_ERROR; if (cgi_write_bcdata(dataset->dirichlet->id, dataset->dirichlet)) return CG_ERROR; } } /* NeumannData */ if (dataset->neumann) { if (dataset->neumann->link) { if (cgi_write_link(dataset->id, "NeumannData", dataset->neumann->link, &dataset->neumann->id)) return CG_ERROR; } else { if (cgi_new_node(dataset->id, "NeumannData", "BCData_t", &dataset->neumann->id, "MT", 0, 0, 0)) return CG_ERROR; if (cgi_write_bcdata(dataset->neumann->id, dataset->neumann)) return CG_ERROR; } } /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(dataset->id, &dataset->descr[n])) return CG_ERROR; /* ReferenceState_t */ if (dataset->state && cgi_write_state(dataset->id, dataset->state)) return CG_ERROR; /* DataClass_t */ if (dataset->data_class && cgi_write_dataclass(dataset->id, dataset->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (dataset->units && cgi_write_units(dataset->id, dataset->units)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(dataset->id, &dataset->user_data[n])) return CG_ERROR; /* GridLocation_t */ if (dataset->location != CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[dataset->location]); if (cgi_new_node(dataset->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[dataset->location])) return CG_ERROR; } /* PointRange, PointList: Move node to its final position */ if (dataset->ptset) { /* Move node to its final position */ if (cgi_move_node(cg->rootid, dataset->ptset->id, dataset->id, PointSetTypeName[dataset->ptset->type])) return CG_ERROR; } return CG_OK; } int cgi_write_bcdata(double bcdata_id, cgns_bcdata *bcdata) { int n; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(bcdata_id, &bcdata->array[n])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(bcdata_id, &bcdata->descr[n])) return CG_ERROR; /* DataClass_t */ if (bcdata->data_class && cgi_write_dataclass(bcdata->id, bcdata->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (bcdata->units && cgi_write_units(bcdata->id, bcdata->units)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(bcdata->id, &bcdata->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_ptset(double parent_id, char_33 name, cgns_ptset *ptset, int Idim, void *ptset_ptr) { cgsize_t dim_vals[12]; int ndim; char_33 label; if (ptset->link) { return cgi_write_link(parent_id, name, ptset->link, &ptset->id); } /* Set label */ if (ptset->type == CGNS_ENUMV(PointRange) || ptset->type == CGNS_ENUMV(ElementRange) || ptset->type == CGNS_ENUMV(PointRangeDonor)) strcpy(label,"IndexRange_t"); else strcpy(label,"IndexArray_t"); /* Dimension vector */ dim_vals[0]=Idim; dim_vals[1]=ptset->npts; ndim = 2; /* Create the node */ if (cgi_new_node(parent_id, name, label, &ptset->id, ptset->data_type, ndim, dim_vals, ptset_ptr)) return CG_ERROR; return CG_OK; } int cgi_write_equations(double parent_id, cgns_equations *equations) { int n; cgsize_t dim_vals; double dummy_id; cgns_governing *governing; if (equations->link) { return cgi_write_link(parent_id, "FlowEquationSet", equations->link, &equations->id); } /* FlowEquationSet_t */ if (cgi_new_node(parent_id, "FlowEquationSet", "FlowEquationSet_t", &equations->id, "MT", 0, 0, 0)) return CG_ERROR; /* EquationDimension */ if (equations->equation_dim) { dim_vals=1; if (cgi_new_node(equations->id, "EquationDimension", "\"int\"", &dummy_id, "I4", 1, &dim_vals, (void *)&equations->equation_dim)) return CG_ERROR; } /* GoverningEquations_t */ if (equations->governing) { governing = equations->governing; if (governing->link) { if (cgi_write_link(equations->id, "GoverningEquations", governing->link, &governing->id)) return CG_ERROR; } else { dim_vals = (cgsize_t)strlen(GoverningEquationsTypeName[governing->type]); if (cgi_new_node(equations->id, "GoverningEquations", "GoverningEquations_t", &governing->id, "C1", 1, &dim_vals, GoverningEquationsTypeName[governing->type])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(governing->id, &governing->descr[n])) return CG_ERROR; /* DiffusionModel */ if (governing->diffusion_model) { dim_vals=governing->dim_vals; if (cgi_new_node(governing->id, "DiffusionModel", "\"int[1+...+IndexDimension]\"", &dummy_id, "I4", 1, &dim_vals, (void *)governing->diffusion_model)) return CG_ERROR; } /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(governing->id, &governing->user_data[n])) return CG_ERROR; } } /* GasModel_t */ if (equations->gas && cgi_write_model(equations->id, equations->gas)) return CG_ERROR; /* ViscosityModel_t */ if (equations->visc && cgi_write_model(equations->id, equations->visc)) return CG_ERROR; /* ThermalConductivityModel_t */ if (equations->conduct && cgi_write_model(equations->id, equations->conduct)) return CG_ERROR; /* TurbulenceClosure_t */ if (equations->closure && cgi_write_model(equations->id, equations->closure)) return CG_ERROR; /* TurbulenceModel_t */ if (equations->turbulence) { if (cgi_write_model(equations->id, equations->turbulence)) return CG_ERROR; /* DiffusionModel */ if (equations->turbulence->diffusion_model) { dim_vals=equations->turbulence->dim_vals; if (cgi_new_node(equations->turbulence->id, "DiffusionModel", "\"int[1+...+IndexDimension]\"", &dummy_id, "I4", 1, &dim_vals, (void *) equations->turbulence->diffusion_model)) return CG_ERROR; } } /* ThermalRelaxationModel_t */ if (equations->relaxation && cgi_write_model(equations->id, equations->relaxation)) return CG_ERROR; /* ChemicalKineticsModel_t */ if (equations->chemkin && cgi_write_model(equations->id, equations->chemkin)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(equations->id, &equations->descr[n])) return CG_ERROR; /* DataClass_t */ if (equations->data_class && cgi_write_dataclass(equations->id, equations->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (equations->units && cgi_write_units(equations->id, equations->units)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(equations->id, &equations->user_data[n])) return CG_ERROR; /* EMElectricFieldModel_t */ if (equations->elecfield && cgi_write_model(equations->id, equations->elecfield)) return CG_ERROR; /* EMMagneticFieldModel_t */ if (equations->magnfield && cgi_write_model(equations->id, equations->magnfield)) return CG_ERROR; /* EMConductivityModel_t */ if (equations->emconduct && cgi_write_model(equations->id, equations->emconduct)) return CG_ERROR; return CG_OK; } int cgi_write_model(double parent_id, cgns_model *model) { int n; cgsize_t dim_vals; char_33 label; if (model->link) { return cgi_write_link(parent_id, model->name, model->link, &model->id); } /* xModel_t */ sprintf(label,"%.30s_t",model->name); dim_vals = (cgsize_t)strlen(ModelTypeName[model->type]); if (cgi_new_node(parent_id, model->name, label, &model->id, "C1", 1, &dim_vals, ModelTypeName[model->type])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(model->id, &model->descr[n])) return CG_ERROR; /* DataClass_t */ if (model->data_class && cgi_write_dataclass(model->id, model->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (model->units && cgi_write_units(model->id, model->units)) return CG_ERROR; /* DataArray */ for (n=0; nnarrays; n++) if (cgi_write_array(model->id, &model->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(model->id, &model->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_state(double parent_id, cgns_state *state) { int n; if (state->link) { return cgi_write_link(parent_id, "ReferenceState", state->link, &state->id); } /* ReferenceState_t */ if (cgi_new_node(parent_id, "ReferenceState", "ReferenceState_t", &state->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(state->id, &state->descr[n])) return CG_ERROR; /* ReferenceStateDescription */ if (state->StateDescription && cgi_write_descr(state->id, state->StateDescription)) return CG_ERROR; /* DataClass_t */ if (state->data_class && cgi_write_dataclass(state->id, state->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (state->units && cgi_write_units(state->id, state->units)) return CG_ERROR; /* DataArray */ for (n=0; nnarrays; n++) if (cgi_write_array(state->id, &state->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(state->id, &state->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_gravity(double parent_id, cgns_gravity *gravity) { int n; if (gravity->link) { return cgi_write_link(parent_id, "Gravity", gravity->link, &gravity->id); } /* Gravity_t */ if (cgi_new_node(parent_id, "Gravity", "Gravity_t", &gravity->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(gravity->id, &gravity->descr[n])) return CG_ERROR; /* DataClass_t */ if (gravity->data_class && cgi_write_dataclass(gravity->id, gravity->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (gravity->units && cgi_write_units(gravity->id, gravity->units)) return CG_ERROR; /* DataArray */ if (gravity->vector && cgi_write_array(gravity->id, gravity->vector)) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(gravity->id, &gravity->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_axisym(double parent_id, cgns_axisym *axisym) { int n; if (axisym->link) { return cgi_write_link(parent_id, "Axisymmetry", axisym->link, &axisym->id); } /* Axisymmetry_t */ if (cgi_new_node(parent_id, "Axisymmetry", "Axisymmetry_t", &axisym->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(axisym->id, &axisym->descr[n])) return CG_ERROR; /* DataClass_t */ if (axisym->data_class && cgi_write_dataclass(axisym->id, axisym->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (axisym->units && cgi_write_units(axisym->id, axisym->units)) return CG_ERROR; /* DataArray */ for (n=0; nnarrays; n++) if (cgi_write_array(axisym->id, &axisym->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(axisym->id, &axisym->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_rotating(double parent_id, cgns_rotating *rotating) { int n; if (rotating->link) { return cgi_write_link(parent_id, "RotatingCoordinates", rotating->link, &rotating->id); } /* RotatingCoordinates_t */ if (cgi_new_node(parent_id, "RotatingCoordinates", "RotatingCoordinates_t", &rotating->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(rotating->id, &rotating->descr[n])) return CG_ERROR; /* DataClass_t */ if (rotating->data_class && cgi_write_dataclass(rotating->id, rotating->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (rotating->units && cgi_write_units(rotating->id, rotating->units)) return CG_ERROR; /* DataArray */ for (n=0; nnarrays; n++) if (cgi_write_array(rotating->id, &rotating->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(rotating->id, &rotating->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_converg(double parent_id, cgns_converg *converg) { int n; cgsize_t dim_vals; if (converg->link) { return cgi_write_link(parent_id, converg->name, converg->link, &converg->id); } /* ConvergenceHistory_t */ dim_vals = 1; if (cgi_new_node(parent_id, converg->name, "ConvergenceHistory_t", &converg->id, "I4", 1, &dim_vals, (void *)&converg->iterations)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(converg->id, &converg->descr[n])) return CG_ERROR; /* NormDefinitions */ if (converg->NormDefinitions && cgi_write_descr(converg->id, converg->NormDefinitions)) return CG_ERROR; /* DataClass_t */ if (converg->data_class && cgi_write_dataclass(converg->id, converg->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (converg->units && cgi_write_units(converg->id, converg->units)) return CG_ERROR; /* DataArray */ for (n=0; nnarrays; n++) if (cgi_write_array(converg->id, &converg->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(converg->id, &converg->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_discrete(double parent_id, cgns_discrete *discrete) { int n; cgsize_t dim_vals; double dummy_id; if (discrete->link) { return cgi_write_link(parent_id, discrete->name, discrete->link, &discrete->id); } /* DiscreteData_t */ if (cgi_new_node(parent_id, discrete->name, "DiscreteData_t", &discrete->id, "MT", 0, 0, 0)) return CG_ERROR; /* GridLocation_t */ if (discrete->location != CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[discrete->location]); if (cgi_new_node(discrete->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[discrete->location])) return CG_ERROR; } /* Rind_t */ if (cgi_write_rind(discrete->id, discrete->rind_planes, Idim)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(discrete->id, &discrete->descr[n])) return CG_ERROR; /* DataClass_t */ if (discrete->data_class && cgi_write_dataclass(discrete->id, discrete->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (discrete->units && cgi_write_units(discrete->id, discrete->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(discrete->id, &discrete->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(discrete->id, &discrete->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_integral(double parent_id, cgns_integral *integral) { int n; if (integral->link) { return cgi_write_link(parent_id, integral->name, integral->link, &integral->id); } /* IntegralData_t */ if (cgi_new_node(parent_id, integral->name, "IntegralData_t", &integral->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(integral->id, &integral->descr[n])) return CG_ERROR; /* DataClass_t */ if (integral->data_class && cgi_write_dataclass(integral->id, integral->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (integral->units && cgi_write_units(integral->id, integral->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(integral->id, &integral->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(integral->id, &integral->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_rmotion(double parent_id, cgns_rmotion *rmotion) { int n; cgsize_t dim_vals; if (rmotion->link) { return cgi_write_link(parent_id, rmotion->name, rmotion->link, &rmotion->id); } /* RigidGridMotion_t Name and RigidGridMotionType_t */ dim_vals=(cgsize_t)strlen(RigidGridMotionTypeName[rmotion->type]); if (cgi_new_node(parent_id, rmotion->name, "RigidGridMotion_t", &rmotion->id, "C1", 1, &dim_vals, (void *)RigidGridMotionTypeName[rmotion->type])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(rmotion->id, &rmotion->descr[n])) return CG_ERROR; /* DataClass_t */ if (rmotion->data_class && cgi_write_dataclass(rmotion->id, rmotion->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (rmotion->units && cgi_write_units(rmotion->id, rmotion->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(rmotion->id, &rmotion->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(rmotion->id, &rmotion->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_amotion(double parent_id, cgns_amotion *amotion) { int n; cgsize_t dim_vals; double dummy_id; if (amotion->link) { return cgi_write_link(parent_id, amotion->name, amotion->link, &amotion->id); } /* ArbitraryGridMotion_t Name and ArbitraryGridMotionType_t */ dim_vals=(cgsize_t)strlen(ArbitraryGridMotionTypeName[amotion->type]); if (cgi_new_node(parent_id, amotion->name, "ArbitraryGridMotion_t", &amotion->id, "C1", 1, &dim_vals, (void *)ArbitraryGridMotionTypeName[amotion->type])) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(amotion->id, &amotion->descr[n])) return CG_ERROR; /* GridLocation_t */ if (amotion->location != CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[amotion->location]); if (cgi_new_node(amotion->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[amotion->location])) return CG_ERROR; } /* Rind_t */ if (cgi_write_rind(amotion->id, amotion->rind_planes, Idim)) return CG_ERROR; /* DataClass_t */ if (amotion->data_class && cgi_write_dataclass(amotion->id, amotion->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (amotion->units && cgi_write_units(amotion->id, amotion->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(amotion->id, &amotion->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(amotion->id, &amotion->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_biter(double parent_id, cgns_biter *biter) { int n; cgsize_t dim_vals; if (biter->link) { return cgi_write_link(parent_id, biter->name, biter->link, &biter->id); } /* BaseIterativeData_t name and NumberOfSteps */ dim_vals=1; if (cgi_new_node(parent_id, biter->name, "BaseIterativeData_t", &biter->id, "I4", 1, &dim_vals, (void *)&biter->nsteps)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(biter->id, &biter->descr[n])) return CG_ERROR; /* DataClass_t */ if (biter->data_class && cgi_write_dataclass(biter->id, biter->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (biter->units && cgi_write_units(biter->id, biter->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(biter->id, &biter->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(biter->id, &biter->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_ziter(double parent_id, cgns_ziter *ziter) { int n; if (ziter->link) { return cgi_write_link(parent_id, ziter->name, ziter->link, &ziter->id); } /* ZoneIterativeData_t name */ if (cgi_new_node(parent_id, ziter->name, "ZoneIterativeData_t", &ziter->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(ziter->id, &ziter->descr[n])) return CG_ERROR; /* DataClass_t */ if (ziter->data_class && cgi_write_dataclass(ziter->id, ziter->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (ziter->units && cgi_write_units(ziter->id, ziter->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(ziter->id, &ziter->array[n])) return CG_ERROR; /* UserDefinedData_t */ for (n=0; nnuser_data; n++) if (cgi_write_user_data(ziter->id, &ziter->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_array(double parent_id, cgns_array *array) { int n; cgsize_t dim_vals; double dummy_id; if (array->link) { return cgi_write_link(parent_id, array->name, array->link, &array->id); } if (cgi_new_node(parent_id, array->name, "DataArray_t", &array->id, array->data_type, array->data_dim, array->dim_vals, array->data)) return CG_ERROR; /* DimensionalExponents_t */ if (array->exponents && cgi_write_exponents(array->id, array->exponents)) return CG_ERROR; /* DataConversion_t */ if (array->convert) { dim_vals=2; if (cgi_new_node(array->id, "DataConversion", "DataConversion_t", &array->convert->id, array->convert->data_type, 1, &dim_vals, array->convert->data)) return CG_ERROR; } /* DataClass_t */ if (array->data_class && cgi_write_dataclass(array->id, array->data_class)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(array->id, &array->descr[n])) return CG_ERROR; /* DimensionalUnits_t */ if (array->units && cgi_write_units(array->id, array->units)) return CG_ERROR; /* ElementRange */ dim_vals = 2; if(array->range[0] != 0 && array->range[1] != 0) if (cgi_new_node(array->id, "ArrayDataRange", "IndexRange_t", &dummy_id, "I4", 1, &dim_vals, array->range)) return CG_ERROR; return CG_OK; } int cgi_write_rind(double parent_id, int *rind_planes, int index_dim) { int n; cgsize_t dim_vals; double dummy_id; /* write Rind only if different from the default (6*0) */ if (rind_planes==0) return CG_OK; for (n=0; n<2*index_dim; n++) { if (rind_planes[n]!=0) { dim_vals=2*index_dim; if (cgi_new_node(parent_id, "Rind", "Rind_t", &dummy_id, "I4", 1, &dim_vals, (void *)rind_planes)) return CG_ERROR; return CG_OK; } } return CG_OK; } int cgi_write_units(double parent_id, cgns_units *units) { char *string_data; cgsize_t dim_vals[2]; if (units->link) { return cgi_write_link(parent_id, "DimensionalUnits", units->link, &units->id); } string_data = (char *) malloc ((32*5+1)*sizeof(char)); if (string_data == NULL) { cgi_error("Error allocating memory in cgi_write_units."); return CG_ERROR; } sprintf(string_data,"%-32s%-32s%-32s%-32s%-32s",MassUnitsName[units->mass], LengthUnitsName[units->length], TimeUnitsName[units->time], TemperatureUnitsName[units->temperature], AngleUnitsName[units->angle]); dim_vals[0]=32; dim_vals[1]=5; if (cgi_new_node(parent_id, "DimensionalUnits", "DimensionalUnits_t", &units->id, "C1", 2, dim_vals, (void *)string_data)) return CG_ERROR; if (units->nunits == 8) { double dummy_id; sprintf(string_data, "%-32s%-32s%-32s", ElectricCurrentUnitsName[units->current], SubstanceAmountUnitsName[units->amount], LuminousIntensityUnitsName[units->intensity]); dim_vals[1]=3; if (cgi_new_node(units->id, "AdditionalUnits", "AdditionalUnits_t", &dummy_id, "C1", 2, dim_vals, (void *)string_data)) return CG_ERROR; } CGNS_FREE(string_data); return CG_OK; } int cgi_write_exponents(double parent_id, cgns_exponent *exponent) { cgsize_t dim_vals = 5; if (cgi_new_node(parent_id, "DimensionalExponents", "DimensionalExponents_t", &exponent->id, exponent->data_type, 1, &dim_vals, exponent->data)) return CG_ERROR; if (exponent->nexps == 8) { double dummy_id; void *data; if (0 == strcmp(exponent->data_type,"R4")) data = (void *)((float *)exponent->data + 5); else data = (void *)((double *)exponent->data + 5); dim_vals = 3; if (cgi_new_node(exponent->id, "AdditionalExponents", "AdditionalExponents_t", &dummy_id, exponent->data_type, 1, &dim_vals, data)) return CG_ERROR; } return CG_OK; } int cgi_write_dataclass(double parent_id, CGNS_ENUMV(DataClass_t) data_class) { cgsize_t dim_vals; double dummy_id; dim_vals=(cgsize_t)strlen(DataClassName[data_class]); if (cgi_new_node(parent_id, "DataClass", "DataClass_t", &dummy_id, "C1", 1, &dim_vals, (void *)DataClassName[data_class])) return CG_ERROR; return CG_OK; } int cgi_write_descr(double parent_id, cgns_descr *descr) { cgsize_t dim_vals; if (descr->link) { return cgi_write_link(parent_id, descr->name, descr->link, &descr->id); } dim_vals=(cgsize_t)strlen(descr->text); if (cgi_new_node(parent_id, descr->name, "Descriptor_t", &descr->id, "C1", 1, &dim_vals, (void *)descr->text)) return CG_ERROR; return CG_OK; } int cgi_write_ordinal(double parent_id, int ordinal) { cgsize_t dim_vals; double dummy_id; dim_vals=1; if (cgi_new_node(parent_id, "Ordinal", "Ordinal_t", &dummy_id, "I4", 1, &dim_vals, (void *)&ordinal)) return CG_ERROR; return CG_OK; } int cgi_write_user_data(double parent_id, cgns_user_data *user_data) { int n; cgsize_t dim_vals; double dummy_id; if (user_data->link) { return cgi_write_link(parent_id, user_data->name, user_data->link, &user_data->id); } /* UserDefinedData_t */ if (cgi_new_node(parent_id, user_data->name, "UserDefinedData_t", &user_data->id, "MT", 0, 0, 0)) return CG_ERROR; /* Descriptor_t */ for (n=0; nndescr; n++) if (cgi_write_descr(user_data->id, &user_data->descr[n])) return CG_ERROR; /* DataClass_t */ if (user_data->data_class && cgi_write_dataclass(user_data->id, user_data->data_class)) return CG_ERROR; /* DimensionalUnits_t */ if (user_data->units && cgi_write_units(user_data->id, user_data->units)) return CG_ERROR; /* DataArray_t */ for (n=0; nnarrays; n++) if (cgi_write_array(user_data->id, &user_data->array[n])) return CG_ERROR; /* GridLocation_t */ if (user_data->location != CGNS_ENUMV( Vertex )) { dim_vals = (cgsize_t)strlen(GridLocationName[user_data->location]); if (cgi_new_node(user_data->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[user_data->location])) return CG_ERROR; } /* FamilyName_t */ if (user_data->family_name[0]!='\0') { dim_vals = (cgsize_t)strlen(user_data->family_name); if (cgi_new_node(user_data->id, "FamilyName", "FamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)user_data->family_name)) return CG_ERROR; } /* CPEX 0034 */ for (n = 0; n < user_data->nfamname; n++) { dim_vals = (cgsize_t)strlen(user_data->famname[n].family); if (cgi_new_node(user_data->id, user_data->famname[n].name, "AdditionalFamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)user_data->famname[n].family)) return CG_ERROR; } /* Ordinal_t */ if (user_data->ordinal && cgi_write_ordinal(user_data->id, user_data->ordinal)) return CG_ERROR; /* PointRange, PointList: Move node to its final position */ if (user_data->ptset) { /* Move node to its final position */ if (cgi_move_node(cg->rootid, user_data->ptset->id, user_data->id, PointSetTypeName[user_data->ptset->type])) return CG_ERROR; } /* UserDefinedData_t */ for (n=0; n < user_data->nuser_data; n++) if (cgi_write_user_data(user_data->id, &user_data->user_data[n])) return CG_ERROR; return CG_OK; } int cgi_write_link(double parent_id, char *name, cgns_link *link, double *id) { if (cgio_create_link(cg->cgio, parent_id, name, link->filename, link->name_in_file, id)) { cg_io_error("cgio_create_link"); return CG_ERROR; } (cg->added)++; return CG_OK; } /* cgi_new_node creates an ADF node under parent_id and returns node_id */ int cgi_new_node(double parent_id, char const *name, char const *label, double *node_id, char const *data_type, int ndim, cgsize_t const *dim_vals, void const *data) { /* verify input */ if (cgi_check_strlen(name) || cgi_check_strlen(label) || cgi_check_strlen(data_type)) return CG_ERROR; if (cgio_create_node(cg->cgio, parent_id, name, node_id)) { cg_io_error("cgio_create_node"); return CG_ERROR; } (cg->added)++; if (cgio_set_label(cg->cgio, *node_id, label)) { cg_io_error("cgio_set_label"); return CG_ERROR; } /* return if empty */ if (strcmp(data_type, "MT")==0) return CG_OK; if (cgio_set_dimensions(cg->cgio, *node_id, data_type, ndim, dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (data == NULL) return CG_OK; #if 0 /* verify that data doesn't contain NaN */ if (strcmp(data_type,"I4")==0 || strcmp(data_type,"I8")==0 || strcmp(data_type,"R4")==0 || strcmp(data_type,"R8")==0) { cgsize_t i, ndata=1, nbad=0; for (i=0; icgio, *node_id, data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } return CG_OK; } /* cgi_new_node_partial creates an ADF node under parent_id and returns * node_id * It will write data for a subset of dim_vals based on rmin and rmax * using ADF_Write_Data(..). */ int cgi_new_node_partial(double parent_id, char const *name, char const *label, double *node_id, char const *data_type, int numdim, cgsize_t const *dims, cgsize_t const *s_start, cgsize_t const *s_end, int m_numdim, cgsize_t const *m_dims, cgsize_t const *m_start, cgsize_t const *m_end, void const *data) { cgsize_t i; /* stride used for both file and memory */ cgsize_t stride[CGIO_MAX_DIMENSIONS]; /* verify input */ if (cgi_check_strlen(name) || cgi_check_strlen(label) || cgi_check_strlen(data_type)) return CG_ERROR; if (cgio_create_node(cg->cgio, parent_id, name, node_id)) { cg_io_error("cgio_create_node"); return CG_ERROR; } (cg->added)++; if (cgio_set_label(cg->cgio, *node_id, label)) { cg_io_error("cgio_set_label"); return CG_ERROR; } /* return if empty */ if (strcmp(data_type, "MT")==0) return CG_OK; if (cgio_set_dimensions(cg->cgio, *node_id, data_type, numdim, dims)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (data == NULL) return CG_OK; #if 0 /* verify that data doesn't contain NaN */ if (strcmp(data_type,"I4")==0 || strcmp(data_type,"I8")==0 || strcmp(data_type,"R4")==0 || strcmp(data_type,"R8")==0) { cgsize_t ndata = 1, nbad=0; for (i=0; icgio, *node_id, s_start, s_end, stride, m_numdim, m_dims, m_start, m_end, stride, data)) { cg_io_error("cgio_write_data"); return CG_ERROR; } return CG_OK; } int cgi_move_node(double current_parent_id, double node_id, double new_parent_id, cchar_33 node_name) { if (cgio_move_node(cg->cgio, current_parent_id, node_id, new_parent_id)) { cg_io_error("cgio_move_node"); return CG_ERROR; } if (cgio_set_name(cg->cgio, new_parent_id, node_id, node_name)) { cg_io_error("cgio_set_name"); return CG_ERROR; } return CG_OK; } int cgi_delete_node (double parent_id, double node_id) { (cg->deleted)++; if (cgio_delete_node(cg->cgio, parent_id, node_id)) { cg_io_error ("cgio_delete_node"); return CG_ERROR; } return CG_OK; } /***********************************************************************\ * General array reading and writing * \***********************************************************************/ int cgi_array_general_verify_range( const cgi_rw op_rw, /* [I] CGI_Read or CGI_Write */ const void* rind_index, /* [I] how to index rind planes */ const int* rind_planes, /* [I] sizes of rind planes */ const int s_numdim, /* [I] rank in file */ const cgsize_t *s_dimvals, /* [I] dimensions of array in memory */ const cgsize_t *rmin, /* [I] range min in file */ const cgsize_t *rmax, /* [I] range max in file */ const int m_numdim, /* [I] rank in memory */ const cgsize_t *m_dimvals, /* [I] dimensions of array in memory */ const cgsize_t *m_rmin, /* [I] range min in memory */ const cgsize_t *m_rmax, /* [I] range max in memory */ cgsize_t *s_rmin, /* [O] internal range min in file */ cgsize_t *s_rmax, /* [O] internal range max in file */ cgsize_t *stride, /* [O] stride (always 1) */ int *s_access_full_range, /* [O] T: access all of file array */ int *m_access_full_range, /* [O] T: access all of memory array */ cgsize_t *numpt) /* [O] number of points accessed */ { cgsize_t s_numpt = 1, m_numpt = 1; int n, npt; int s_reset_range = 1; *s_access_full_range = 1; *m_access_full_range = 1; /*** verfication for dataset in file */ /* verify that range requested is not NULL */ if (rmin == NULL || rmax == NULL) { cgi_error("NULL range value"); return CG_ERROR; } /* check if requested to return full range */ for (n=0; n rmax[n] || rmax[n] > s_dimvals[n] || rmin[n] < 1) { cgi_error("Invalid range of data requested"); return CG_ERROR; } } else { /* new behavior consitent with SIDS */ if (rmin[n] > rmax[n] || rmax[n] > (s_dimvals[n] - rind_planes[2*n]) || rmin[n] < (1 - rind_planes[2*n])) { cgi_error("Invalid range of data requested"); return CG_ERROR; } } } } /*** verification for dataset in memory */ /* verify the rank and dimensions of the memory array */ if (m_numdim <= 0 || m_numdim > CGIO_MAX_DIMENSIONS) { cgi_error("Invalid number of dimensions in memory array"); return CG_ERROR; } if (m_dimvals == NULL) { cgi_error("NULL dimension value"); return CG_ERROR; } for (n=0; n m_rmax[n] || m_rmax[n] > m_dimvals[n] || m_rmin[n] < 1) { cgi_error("Invalid range of memory array provided"); return CG_ERROR; } } /* check if requested to return full range */ for (n=0; ndata_type); const cgsize_t *s_dimvals = array->dim_vals; /* verify the ranges provided and set s_rmin and s_rmax giving internal file-space ranges */ cgsize_t s_rmin[CGIO_MAX_DIMENSIONS], s_rmax[CGIO_MAX_DIMENSIONS]; cgsize_t stride[CGIO_MAX_DIMENSIONS]; ier = cgi_array_general_verify_range( CGI_Read, rind_index, rind_planes, s_numdim, s_dimvals, rmin, rmax, m_numdim, m_dimvals, m_rmin, m_rmax, s_rmin, s_rmax, stride, &s_access_full_range, &m_access_full_range, &numpt); if (ier != CG_OK) return ier; const int access_full_range = (s_access_full_range == 1) && (m_access_full_range == 1); if (s_type == m_type) { /* quick transfer of data if same data types */ if (access_full_range) { if (cgio_read_all_data(cg->cgio, array->id, data)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } } else { if (cgio_read_data(cg->cgio, array->id, s_rmin, s_rmax, stride, m_numdim, m_dimvals, m_rmin, m_rmax, stride, data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } } else if (cg->filetype == CGIO_FILE_ADF2 || cg->filetype == CGIO_FILE_ADF) { /* need to read into temp array to convert data */ /* only able to convert for full range in memory */ if (!m_access_full_range) { cgi_error("Reading to partial range in memory with data conversion " "is not supported in ADF file format"); return CG_ERROR; } void *conv_data; conv_data = malloc((size_t)(numpt*size_of(array->data_type))); if (conv_data == NULL) { cgi_error("Error allocating conv_data"); return CG_ERROR; } if (access_full_range) { if (cgio_read_all_data(cg->cgio, array->id, conv_data)) { free(conv_data); cg_io_error("cgio_read_all_data"); return CG_ERROR; } } else { if (cgio_read_data(cg->cgio, array->id, s_rmin, s_rmax, stride, m_numdim, m_dimvals, m_rmin, m_rmax, stride, conv_data)) { free(conv_data); cg_io_error("cgio_read_data"); return CG_ERROR; } } ier = cgi_convert_data(numpt, s_type, conv_data, m_type, data); free(conv_data); if (ier) return CG_ERROR; } else { /* in-situ conversion */ if (access_full_range) { if (cgio_read_all_data_type(cg->cgio, array->id, cgi_adf_datatype(m_type), data)) { cg_io_error("cgio_read_all_data_type"); return CG_ERROR; } } else { if (cgio_read_data_type(cg->cgio, array->id, s_rmin, s_rmax, stride, cgi_adf_datatype(m_type), m_numdim, m_dimvals, m_rmin, m_rmax, stride, data)) { cg_io_error("cgio_read_data_type"); return CG_ERROR; } } } return CG_OK; } /* s_ prefix is file space, m_ prefix is memory space, p_ is parent node data */ int cgi_array_general_write( double p_id, /* [I] id of parent node */ int *p_narraylist, /* [I/O] number of arrays in parent */ cgns_array **p_arraylist, /* [I/O] arrays in parent */ const char *const arrayname, /* [I] name of array to write to */ const void* rind_index, /* [I] how to index rind planes */ const int* rind_planes, /* [I] sizes of rind planes */ CGNS_ENUMT(DataType_t) s_type, /* [I] data type in file */ const int s_numdim, /* [I] rank in file */ const cgsize_t *s_dimvals, /* [I] dimensions of array in file */ const cgsize_t *rmin, /* [I] range min in file */ const cgsize_t *rmax, /* [I] range max in file */ CGNS_ENUMT(DataType_t) m_type, /* [I] data type in memory */ const int m_numdim, /* [I] rank in memory */ const cgsize_t *m_dimvals, /* [I] dimensions of array in memory */ const cgsize_t *m_rmin, /* [I] range min in memory */ const cgsize_t *m_rmax, /* [I] range max in memory */ const void* data, /* [I] data to store */ int *A) /* [O] array index for new array */ { int s_access_full_range, m_access_full_range, n, idx, ier; cgsize_t numpt; /* verify the ranges provided and set s_rmin and s_rmax giving internal file-space ranges */ cgsize_t s_rmin[CGIO_MAX_DIMENSIONS], s_rmax[CGIO_MAX_DIMENSIONS]; cgsize_t stride[CGIO_MAX_DIMENSIONS]; ier = cgi_array_general_verify_range( CGI_Write, rind_index, rind_planes, s_numdim, s_dimvals, rmin, rmax, m_numdim, m_dimvals, m_rmin, m_rmax, s_rmin, s_rmax, stride, &s_access_full_range, &m_access_full_range, &numpt); if (ier != CG_OK) return ier; const int access_full_range = (s_access_full_range == 1) && (m_access_full_range == 1); cgns_array *array; /* check for existing array */ int have_dup = 0; if (p_narraylist == NULL) { /* data array */ int ier = 0; /* note: this will allocate a DataArray_t node if existing not found */ array = cgi_array_address(CG_MODE_WRITE, 1, 0, arrayname, &have_dup, &ier); if (array == 0) return ier; if (cgi_posit_id(&p_id)) return CG_ERROR; } else { for (idx=0; idx<(*p_narraylist); idx++) { if (strcmp(arrayname, (*p_arraylist)[idx].name) == 0) { have_dup = 1; array = &((*p_arraylist)[idx]); break; } } } if (have_dup) { /* overwrite a DataArray_t node of same name, size and data-type: */ /* array rank in file must agree */ if (array->data_dim != s_numdim) { cgi_error("Mismatch in array rank"); return CG_ERROR; } /* array dimensions in file must agree */ for (n = 0; ndim_vals[n] != s_dimvals[n]) { cgi_error("Mismatch in array dimension %d", n); return CG_ERROR; } } /* data type in file must agree */ if (strcmp(array->data_type, cgi_adf_datatype(s_type))) { cgi_error("Mismatch in data types"); return CG_ERROR; } } else { /* add a DataArray_t node if not already done */ if (p_narraylist) { if (*p_narraylist == 0) { *p_arraylist = CGNS_NEW(cgns_array, (*p_narraylist)+1); } else { *p_arraylist = CGNS_RENEW(cgns_array, (*p_narraylist)+1, *p_arraylist); } array = &((*p_arraylist)[*p_narraylist]); ++(*p_narraylist); (*A) = *p_narraylist; } /* save array information in memory */ memset(array, 0, sizeof(cgns_array)); strcpy(array->data_type, cgi_adf_datatype(m_type)); strcpy(array->name, arrayname); array->data_dim = s_numdim; for (n = 0; ndim_vals[n] = s_dimvals[n]; } /* save DataArray_t node on disk: */ if (cgi_new_node_partial(p_id, array->name, "DataArray_t", &array->id, array->data_type, s_numdim, s_dimvals, s_rmin, s_rmax, m_numdim, m_dimvals, m_rmin, m_rmax, NULL)) { return CG_ERROR; } } /* Do not write the data if NULL pointer. This is often used in parallel * cgns where only the metadata is being written in serial */ if (data == NULL) return CG_OK; if (s_type == m_type) { /* quick transfer of data if same data types */ if (access_full_range) { if (cgio_write_all_data(cg->cgio, array->id, data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } else { if (cgio_write_data(cg->cgio, array->id, s_rmin, s_rmax, stride, m_numdim, m_dimvals, m_rmin, m_rmax, stride, data)) { cg_io_error("cgio_write_data"); return CG_ERROR; } } } else if (cg->filetype == CGIO_FILE_ADF2 || cg->filetype == CGIO_FILE_ADF) { /* need to write into temp array to convert data */ /* only able to convert for full range in memory */ if (!m_access_full_range) { cgi_error("Writing from partial range in memory with data " "conversion is not supported in ADF file format"); return CG_ERROR; } void *conv_data; conv_data = malloc((size_t)(numpt*size_of(array->data_type))); if (conv_data == NULL) { cgi_error("Error allocating conv_data"); return CG_ERROR; } if (cgi_convert_data(numpt, m_type, data, s_type, conv_data)) { free(conv_data); return CG_ERROR; } if (access_full_range) { if (cgio_write_all_data(cg->cgio, array->id, conv_data)) { free(conv_data); cg_io_error("cgio_write_all_data"); return CG_ERROR; } } else { if (cgio_write_data(cg->cgio, array->id, s_rmin, s_rmax, stride, m_numdim, m_dimvals, m_rmin, m_rmax, stride, conv_data)) { free(conv_data); cg_io_error("cgio_write_data"); return CG_ERROR; } } free(conv_data); } else { /* in-situ conversion */ if (access_full_range) { if (cgio_write_all_data_type(cg->cgio, array->id, cgi_adf_datatype(m_type), data)) { cg_io_error("cgio_write_all_data_type"); return CG_ERROR; } } else { if (cgio_write_data_type(cg->cgio, array->id, s_rmin, s_rmax, stride, cgi_adf_datatype(m_type), m_numdim, m_dimvals, m_rmin, m_rmax, stride, data)) { cg_io_error("cgio_write_data_type"); return CG_ERROR; } } } return CG_OK; } /***********************************************************************\ * Alphanumerical sorting routine * \***********************************************************************/ int cgi_sort_names(int nnam, double *ids) { int i,j,k; int leni, lenj; char_33 temp; double temp_id; char_33 *names; names = CGNS_NEW(char_33, nnam); for (i=0; icgio, ids[i], names[i])) { cg_io_error("cgio_get_name"); CGNS_FREE(names); return CG_ERROR; } } for (i=0; i(int)names[i][k]) { break; } if (k==(int)(strlen(names[j])-1)) { strcpy(temp, names[i]); strcpy(names[i], names[j]); strcpy(names[j], temp); leni=(int)strlen(names[i]); temp_id = ids[i]; ids[i]=ids[j]; ids[j]=temp_id; } } } } CGNS_FREE(names); return CG_OK; } /***********************************************************************\ * ADF parser: returns the children id with "label" under "parent_id" * \***********************************************************************/ int cgi_get_nodes(double parent_id, char *label, int *nnodes, double **id) { int nid, n, nchildren, len; char nodelabel[CGIO_MAX_NAME_LENGTH+1]; double *idlist; *nnodes = 0; if (cgio_number_children(cg->cgio, parent_id, &nchildren)) { cg_io_error ("cgio_number_children"); return CG_ERROR; } if (nchildren < 1) return CG_OK; idlist = CGNS_NEW (double, nchildren); if (cgio_children_ids(cg->cgio, parent_id, 1, nchildren, &len, idlist)) { cg_io_error ("cgio_children_ids"); return CG_ERROR; } if (len != nchildren) { CGNS_FREE (idlist); cgi_error ("mismatch in number of children and child IDs read"); return CG_ERROR; } nid = 0; for (nid = 0, n = 0; n < nchildren; n++) { if (cgio_get_label(cg->cgio, idlist[n], nodelabel)) { cg_io_error ("cgio_get_label"); return CG_ERROR; } if (0 == strcmp (nodelabel, label)) { if (nid < n) idlist[nid] = idlist[n]; nid++; } else cgio_release_id (cg->cgio, idlist[n]); } if (nid > 0) { *id = idlist; *nnodes = nid; } else CGNS_FREE (idlist); return CG_OK; } /***********************************************************************\ * Data Types functions * \***********************************************************************/ char *type_of(char_33 data_type) { if (strcmp(data_type, "I4")==0) return "int"; else if (strcmp(data_type, "R4")==0) return "float"; else if (strcmp(data_type, "R8")==0) return "double"; else if (strcmp(data_type, "C1")==0) return "char"; else { cgi_error("data_type '%s' not supported by function 'type_of'",data_type); return CG_OK; } } int size_of(const char_33 data_type) { if (strcmp(data_type, "I4") == 0) return sizeof(int); if (strcmp(data_type, "I8") == 0) return sizeof(cglong_t); if (strcmp(data_type, "R4") == 0) return sizeof(float); if (strcmp(data_type, "R8") == 0) return sizeof(double); if (strcmp(data_type, "C1") == 0) return sizeof(char); cgi_error("data_type '%s' not supported by function 'size_of'",data_type); return CG_OK; } const char *cgi_adf_datatype(CGNS_ENUMV(DataType_t) type) { if (type == CGNS_ENUMV(Integer)) return "I4"; if (type == CGNS_ENUMV(LongInteger)) return "I8"; if (type == CGNS_ENUMV(RealSingle)) return "R4"; if (type == CGNS_ENUMV(RealDouble)) return "R8"; if (type == CGNS_ENUMV(Character)) return "C1"; return "NULL"; } CGNS_ENUMT(DataType_t) cgi_datatype(cchar_33 adf_type) { if (strcmp(adf_type, "I4") == 0) return CGNS_ENUMV(Integer); if (strcmp(adf_type, "I8") == 0) return CGNS_ENUMV(LongInteger); if (strcmp(adf_type, "R4") == 0) return CGNS_ENUMV(RealSingle); if (strcmp(adf_type, "R8") == 0) return CGNS_ENUMV(RealDouble); if (strcmp(adf_type, "C1") == 0) return CGNS_ENUMV(Character); return CGNS_ENUMV(DataTypeNull); } /***********************************************************************\ * Check input functions * \***********************************************************************/ int cgi_zone_no(cgns_base *base, char *zonename, int *zone_no) { int i; for (i=0; inzones; i++) { if (strcmp(base->zone[i].name,zonename)==0) { *zone_no = i+1; return CG_OK; } } cgi_error("Zone %s not found",zonename); return CG_ERROR; } int cgi_check_strlen(char const *string) { if (strlen(string) > 32) { cgi_error("Name exceeds 32 characters limit: %s",string); return CG_ERROR; } return CG_OK; } int cgi_check_strlen_x2(char const *string) { int n1,n2,p; if (strlen(string) > 65) { cgi_error("Name exceeds 65 characters limit: %s",string); return CG_ERROR; } p=0; n1=0; n2=0; while (string[p]) { if (string[p]=='/') { if (n2!=0){ cgi_error("Zone or Family with base scope should have only one / : %s",string); return CG_ERROR; } if (n1==0){ cgi_error("Base part of the name is empty in %s",string); return CG_ERROR; } if (p==strlen(string)-1){ cgi_error("Zone or Family part of the name is empty in %s",string); return CG_ERROR; } n2++; } if (!n2) n1++; else n2++; if (n1>32){ cgi_error("Base part of the name exceed 32 chars limit: %s",string); return CG_ERROR; } if (n2>34){ cgi_error("Zone or Family part of the name exceed 32 chars limit: %s",string); return CG_ERROR; } p++; } return CG_OK; } int cgi_check_mode(char const *filename, int file_mode, int mode_wanted) { if (mode_wanted==CG_MODE_READ && file_mode==CG_MODE_WRITE) { cgi_error("File %s not open for reading", filename); return CG_ERROR; } if (mode_wanted==CG_MODE_WRITE && file_mode==CG_MODE_READ) { cgi_error("File %s not open for writing", filename); return CG_ERROR; } return CG_OK; } /***********************************************************************\ * Miscellaneous * \***********************************************************************/ int cgi_add_czone(char_33 zonename, cgsize6_t range, cgsize6_t donor_range, int index_dim, int *ndouble, char_33 **Dzonename, cgsize6_t **Drange, cgsize6_t **Ddonor_range) { int differ=1, k, j; /* check if this interface was already found */ for (k=0; k<(*ndouble); k++) { differ=0; if (strcmp(Dzonename[0][k],zonename)) { differ=1; continue; } for (j=0; jversion < 3200 && type >= CGNS_ENUMV(NGON_n)) npe = (int)(type - CGNS_ENUMV(NGON_n)); else cg_npe(type, &npe); if (npe <= 0) { cgi_error("unhandled element type in MIXED list - %d\n", type); return -1; } size += npe; } } else if (type == CGNS_ENUMV(NGON_n) || type == CGNS_ENUMV(NFACE_n)) { if (connect == 0) return CG_OK; /* Need to handle old version when opening old files */ if (connect_offset == 0) { if (cg->version < 3400) { for (ne = 0; ne < nelems; ne++) { npe = (int)connect[size++]; size += npe; } } else { cgi_error("missing ElementStartOffset for NGON_n or NFACE_n\n"); return -1; } } else { size = (connect_offset[nelems] - connect_offset[0]); } } else { if (cg_npe(type, &npe) || npe <= 0) { cgi_error("unhandled element type - %d\n", type); return -1; } size = nelems * npe; } return size; } /***********************************************************************\ * Get the memory address of a data structure * \***********************************************************************/ cgns_file *cgi_get_file(int file_number) { int filenum = file_number - file_number_offset; if (filenum <= 0 || filenum > n_cgns_files) { cgi_error("CGNS file %d is not open",file_number); return CG_OK; } cg = &(cgns_files[filenum-1]); if (cg->mode == CG_MODE_CLOSED) { cgi_error("CGNS %d is closed",file_number); return CG_OK; } return cg; } cgns_base *cgi_get_base(cgns_file *cg, int B) { if (B>cg->nbases || B<=0) { cgi_error("Base number %d invalid",B); return CG_OK; } return &(cg->base[B-1]); } cgns_zone *cgi_get_zone(cgns_file *cg, int B, int Z) { cgns_base *base; base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (Z>base->nzones || Z<=0) { cgi_error("Zone number %d invalid",Z); return CG_OK; } return &(base->zone[Z-1]); } cgns_family *cgi_get_family(cgns_file *cg, int B, int F) { cgns_base *base; base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (F>base->nfamilies || F<=0) { cgi_error("Family number %d invalid",F); return CG_OK; } return &base->family[F-1]; } cgns_biter *cgi_get_biter(cgns_file *cg, int B) { cgns_base *base; base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->biter == 0) { cgi_error("BaseIterativeData_t node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->biter; } cgns_gravity *cgi_get_gravity(cgns_file *cg, int B) { cgns_base *base; base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->gravity==0) { cgi_error("Gravity_t node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->gravity; } cgns_axisym *cgi_get_axisym(cgns_file *cg, int B) { cgns_base *base; base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->axisym==0) { cgi_error("Axisymmetry_t node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->axisym; } cgns_rotating *cgi_get_rotating(cgns_file *cg, int B, int Z) { cgns_base *base; cgns_zone *zone; /* RotatingCoordinates_t under a base */ if (Z==0) { base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->rotating==0) { cgi_error("RotatingCoordinates_t node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->rotating; } else { zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (zone->rotating==0) { cgi_error("RotatingCoordinates_t node doesn't exist under zone %d",Z); return CG_OK; } else return zone->rotating; } } cgns_ziter *cgi_get_ziter(cgns_file *cg, int B, int Z) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (zone->ziter == 0) { cgi_error("ZoneIterativeData_t node doesn't exist under zone %d",Z); return CG_OK; } else return zone->ziter; } cgns_zcoor *cgi_get_zcoorGC(cgns_file *cg, int B, int Z) { cgns_zone *zone; int i, index_dim; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; index_dim = zone->index_dim; if (zone->nzcoor == 0 && (cg->mode == CG_MODE_WRITE || cg->mode == CG_MODE_MODIFY)) { zone->zcoor = CGNS_NEW(cgns_zcoor, 1); strcpy(zone->zcoor->name, "GridCoordinates"); zone->zcoor->id = 0; zone->zcoor->link = 0; zone->zcoor->ndescr = 0; zone->zcoor->rind_planes = CGNS_NEW(int, 2*index_dim); for (i=0; i<2*index_dim; i++) zone->zcoor->rind_planes[i]=0; zone->zcoor->ncoords = 0; zone->zcoor->data_class = CGNS_ENUMV( DataClassNull ); zone->zcoor->units = 0; zone->zcoor->nuser_data= 0; if (cg->mode == CG_MODE_MODIFY) { /* Create node GridCoordinates_t node in file */ if (cgi_new_node(zone->id, "GridCoordinates", "GridCoordinates_t", &zone->zcoor->id, "MT", 0, 0, 0)) return CG_OK; } zone->nzcoor=1; return zone->zcoor; } else { for (i=0; inzcoor; i++) { if (strcmp(zone->zcoor[i].name,"GridCoordinates")==0) { return &zone->zcoor[i]; } } } cgi_error("Node 'GridCoordinates' not found for zone '%s'",zone->name); return CG_OK; } cgns_zcoor *cgi_get_zcoor(cgns_file *cg, int B, int Z, int C) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (C>zone->nzcoor || C<=0) { cgi_error("GridCoordinates node number %d invalid",C); return CG_OK; } return &(zone->zcoor[C-1]); } cgns_sol *cgi_get_sol(cgns_file *cg, int B, int Z, int S) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (S>zone->nsols || S<=0) { cgi_error("FlowSolution node number %d invalid",S); return CG_OK; } return &(zone->sol[S-1]); } cgns_section *cgi_get_section(cgns_file *cg, int B, int Z, int S) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (S>zone->nsections || S<=0) { cgi_error("Elements_t node number %d invalid",S); return CG_OK; } return &zone->section[S-1]; } cgns_array *cgi_get_field(cgns_file *cg, int B, int Z, int S, int F) { cgns_sol *sol; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_OK; if (F>sol->nfields || F<=0) { cgi_error("Solution array number %d invalid",F); return CG_OK; } return &(sol->field[F-1]); } cgns_zconn *cgi_get_zconnZC(cgns_file *cg, int B, int Z, int C) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (C > 0 && C <= zone->nzconn) { zone->active_zconn = C; return &zone->zconn[C-1]; } cgi_error("ZoneGridConnectivity_t node number %d invalid",C); return CG_OK; } cgns_zconn *cgi_get_zconn(cgns_file *cg, int B, int Z) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; /* return active zconn if set */ if (zone->nzconn > 0 && zone->active_zconn > 0 && zone->active_zconn <= zone->nzconn) { return &zone->zconn[zone->active_zconn-1]; } /* Allocate automatically only in MODE_WRITE. In MODE_MODIFY, can't do it because a cg_goto would create the node even if not wanted */ if (zone->zconn == 0) { if (cg->mode == CG_MODE_WRITE) { zone->zconn = CGNS_NEW(cgns_zconn, 1); strcpy(zone->zconn->name, "ZoneGridConnectivity"); zone->zconn->id=0; zone->zconn->link=0; zone->zconn->ndescr=0; zone->zconn->n1to1=0; zone->zconn->nconns=0; zone->zconn->nholes=0; zone->zconn->nuser_data=0; } else { cgi_error("No grid connectivity information for zone %d", Z); return CG_OK; } } zone->active_zconn = 1; return zone->zconn; } cgns_cprop *cgi_get_cprop(cgns_file *cg, int B, int Z, int I) { cgns_conn *conn; conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_OK; if (conn->cprop == 0) cgi_error("GridConnectivityProperty_t node doesn't exist under GridConnectivity_t %d",I); return conn->cprop; } cgns_hole *cgi_get_hole(cgns_file *cg, int B, int Z, int I) { cgns_zconn *zconn; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) return CG_OK; if (I>zconn->nholes || I<=0) { cgi_error("OversetHoles node number %d invalid",I); return CG_OK; } return &(zconn->hole[I-1]); } cgns_conn *cgi_get_conn(cgns_file *cg, int B, int Z, int I) { cgns_zconn *zconn; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) return CG_OK; if (I>zconn->nconns || I<=0) { cgi_error("GridConnectivity_t node number %d invalid",I); return CG_OK; } return &(zconn->conn[I-1]); } cgns_1to1 *cgi_get_1to1(cgns_file *cg, int B, int Z, int I) { cgns_zconn *zconn; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) return CG_OK; if (I>zconn->n1to1 || I<=0) { cgi_error("GridConnectivity1to1_t node number %d invalid",I); return CG_OK; } return &(zconn->one21[I-1]); } cgns_zboco *cgi_get_zboco(cgns_file *cg, int B, int Z) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; /* Allocate automatically only in MODE_WRITE. In MODE_MODIFY, can't do it because a cg_goto would create the node even if not wanted */ if (zone->zboco == 0) { if (cg->mode == CG_MODE_WRITE) { zone->zboco = CGNS_NEW(cgns_zboco, 1); strcpy(zone->zboco->name,"ZoneBC"); zone->zboco->id=0; zone->zboco->link=0; zone->zboco->ndescr=0; zone->zboco->nbocos=0; zone->zboco->state=0; zone->zboco->data_class=CGNS_ENUMV( DataClassNull ); zone->zboco->units=0; zone->zboco->nuser_data=0; } else { cgi_error("No boundary condition data in zone %d",Z); return CG_OK; } } return zone->zboco; } cgns_bprop *cgi_get_bprop(cgns_file *cg, int B, int Z, int BC) { cgns_boco *boco; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_OK; if (boco->bprop == 0) cgi_error("BCProperty_t node doesn't exist under BC_t %d",BC); return boco->bprop; } cgns_boco *cgi_get_boco(cgns_file *cg, int B, int Z, int BC) { cgns_zboco *zboco; zboco = cgi_get_zboco(cg, B, Z); if (zboco==0) return CG_OK; if (BC>zboco->nbocos || BC<=0) { cgi_error("BC_t node number %d invalid",BC); return CG_OK; } return &(zboco->boco[BC-1]); } cgns_dataset *cgi_get_dataset(cgns_file *cg, int B, int Z, int BC, int DSet) { cgns_boco *boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_OK; if (DSet>boco->ndataset || DSet<=0) { cgi_error("BCDataSet_t node number %d invalid",DSet); return CG_OK; } return &boco->dataset[DSet-1]; } cgns_bcdata *cgi_get_bcdata(cgns_file *cg, int B, int Z, int BC, int Dset, CGNS_ENUMV( BCDataType_t ) type) { cgns_dataset *dataset = cgi_get_dataset(cg, B, Z, BC, Dset); if (dataset==0) return CG_OK; if (type==CGNS_ENUMV( Dirichlet )) { if (dataset->dirichlet==0) { cgi_error("BCData_t type Dirichlet doesn't exist for Zone %d, BC=%d, BCDataSet=%d", Z, BC, Dset); return CG_OK; } else return dataset->dirichlet; } else if (type==CGNS_ENUMV( Neumann )) { if (dataset->neumann==0) { cgi_error("BCData_t type Neumann doesn't exist for Zone %d, BC=%d, BCDataSet=%d", Z, BC, Dset); return CG_OK; } else return dataset->neumann; } else { cgi_error("BCData must be of type Dirichlet or Neumann"); return CG_OK; } } cgns_converg *cgi_get_converg(cgns_file *cg, int B, int Z) { if (Z==0) { cgns_base *base=cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->converg== 0) { cgi_error("ConvergenceHistory_t node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->converg; } else { cgns_zone *zone=cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (zone->converg== 0) { cgi_error("ConvergenceHistory_t node doesn't exist under CGNSBase %d, Zone %d",B,Z); return CG_OK; } else return zone->converg; } } cgns_equations *cgi_get_equations(cgns_file *cg, int B, int Z) { if (Z==0) { cgns_base *base=cgi_get_base(cg, B); if (base==0) return CG_OK; /* todo: error checking if node doesn't exist in all these cgi_get_functions */ /* also make sure that they are all initialized correctly */ if (base->equations == 0) { cgi_error("FlowEquationSet_t Node doesn't exist under CGNSBase %d",B); return CG_OK; } else return base->equations; } else { cgns_zone *zone=cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (zone->equations == 0) { cgi_error("FlowEquationSet_t Node doesn't exist under CGNSBase %d, Zone %d",B,Z); return CG_OK; } else return zone->equations; } } cgns_governing *cgi_get_governing(cgns_file *cg, int B, int Z) { cgns_equations *eq=cgi_get_equations(cg, B, Z); if (eq==0) return CG_OK; if (eq->governing==0) { if (Z==0) cgi_error("GoverningEquations_t undefined for CGNSBase %d",B); else cgi_error("GoverningEquations_t undefined for CGNSBase %d, Zone %d", B, Z); return CG_OK; } else return eq->governing; } cgns_model *cgi_get_model(cgns_file *cg, int B, int Z, char *model) { cgns_equations *eq=cgi_get_equations(cg, B, Z); if (eq==0) return CG_OK; if (strcmp(model, "GasModel_t")==0 && eq->gas) return eq->gas; else if (strcmp(model, "ViscosityModel_t")==0 && eq->visc) return eq->visc; else if (strcmp(model, "ThermalConductivityModel_t")==0 && eq->conduct) return eq->conduct; else if (strcmp(model, "TurbulenceModel_t")==0 && eq->turbulence) return eq->turbulence; else if (strcmp(model, "TurbulenceClosure_t")==0 && eq->closure) return eq->closure; else if (strcmp(model, "ThermalRelaxationModel_t")==0 && eq->relaxation) return eq->relaxation; else if (strcmp(model, "ChemicalKineticsModel_t")==0 && eq->chemkin) return eq->chemkin; else if (strcmp(model, "EMElectricFieldModel_t")==0 && eq->elecfield) return eq->elecfield; else if (strcmp(model, "EMMagneticFieldModel_t")==0 && eq->magnfield) return eq->magnfield; else if (strcmp(model, "EMConductivityModel_t")==0 && eq->emconduct) return eq->emconduct; else { if (Z==0) cgi_error("%s undefined for CGNSBase %d",model, B); else cgi_error("%s undefined for CGNSBase %d, Zone %d",model, B, Z); return CG_OK; } } cgns_integral *cgi_get_integral(cgns_file *cg, int B, int Z, int N) { if (Z==0) { cgns_base *base=cgi_get_base(cg, B); if (base==0) return CG_OK; if (N>base->nintegrals || N<=0) { cgi_error("IntegralData_t node number %d invalid under CGNSBase %d",N, B); return CG_OK; } else return &base->integral[N-1]; } else { cgns_zone *zone=cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (N>zone->nintegrals || N<=0) { cgi_error("IntegralData_t node number %d invalid under CGNSBase %d, Zone %d",N,B,Z); return CG_OK; } else return &zone->integral[N-1]; } } cgns_discrete *cgi_get_discrete(cgns_file *cg, int B, int Z, int D) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (D>zone->ndiscrete || D<=0) { cgi_error("DiscreteData node number %d invalid",D); return CG_OK; } return &zone->discrete[D-1]; } cgns_rmotion *cgi_get_rmotion(cgns_file *cg, int B, int Z, int R) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (R>zone->nrmotions || R<=0) { cgi_error("RigidGridMotion node number %d invalid",R); return CG_OK; } return &zone->rmotion[R-1]; } cgns_amotion *cgi_get_amotion(cgns_file *cg, int B, int Z, int R) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (R>zone->namotions || R<=0) { cgi_error("ArbitraryGridMotion node number %d invalid",R); return CG_OK; } return &zone->amotion[R-1]; } cgns_state *cgi_get_state(cgns_file *cg, int B, int Z, int ZBC, int BC, int Dset) { /* defined under CGNSBase_t */ if (Z==0 && ZBC==0 && BC==0 && Dset==0) { cgns_base *base = cgi_get_base(cg, B); if (base==0) return CG_OK; if (base->state==0) { cgi_error("ReferenceState_t undefined under CGNSBase %d",B); return CG_OK; } else return base->state; /* defined under Zone_t */ } else if (ZBC==0 && BC==0 && Dset==0) { cgns_zone *zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (zone->state==0) { cgi_error("ReferenceState_t undefined under CGNSBase %d, Zone %d",B,Z); return CG_OK; } else return zone->state; /* defined under ZoneBC_t */ } else if (BC==0 && Dset==0) { cgns_zboco *zboco = cgi_get_zboco(cg, B, Z); if (zboco==0) return CG_OK; if (zboco->state==0) { cgi_error("ReferenceState_t undefined under CGNSBase %d, Zone %d, ZoneBC_t",B,Z); return CG_OK; } else return zboco->state; /* defined under BC_t */ } else if (Dset==0) { cgns_boco *boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_OK; if (boco->state==0) { cgi_error("ReferenceState_t undefined under CGNSBase %d, Zone %d, BC_t %d",B,Z,BC); return CG_OK; } else return boco->state; /* defined under BCDataSet_t */ } else { cgns_dataset *dataset = cgi_get_dataset(cg, B, Z, BC, Dset); if (dataset==0) return CG_OK; if (dataset->state==0) { cgi_error("ReferenceState_t undefined under CGNSBase %d, Zone %d, BC_t %d, BCDataSet %d", B,Z,BC,Dset); return CG_OK; } else return dataset->state; } } cgns_subreg *cgi_get_subreg(cgns_file *cg, int B, int Z, int S) { cgns_zone *zone; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_OK; if (S > 0 && S <= zone->nsubreg) return &(zone->subreg[S-1]); cgi_error("ZoneSubRegion node number %d invalid", S); return NULL; } /******************* Functions related to cg_goto **********************************/ static int cgi_add_posit(void *pos, char *label, int index, double id) { if (posit_depth == CG_MAX_GOTO_DEPTH) { cgi_error("max goto depth exceeded"); return CG_ERROR; } posit_stack[posit_depth].posit = pos; strcpy (posit_stack[posit_depth].label, label); posit_stack[posit_depth].index = index; posit_stack[posit_depth].id = id; posit = &posit_stack[posit_depth++]; return CG_OK; } static int cgi_next_posit(char *label, int index, char *name) { int n; /* CGNSBase_t */ if (0 == strcmp (posit->label, "CGNSBase_t")) { cgns_base *b = (cgns_base *)posit->posit; if (0 == strcmp (label, "Zone_t")) { if (--index < 0) { for (n = 0; n < b->nzones; n++) { if (0 == strcmp (b->zone[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nzones) { posit_zone = index + 1; return cgi_add_posit((void *)&b->zone[index], label, index + 1, b->zone[index].id); } } else if (0 == strcmp (label, "ReferenceState_t")) { if (b->state && (index == 1 || 0 == strcmp (b->state->name, name))) { return cgi_add_posit((void *)b->state, label, 1, b->state->id); } } else if (0 == strcmp (label, "Family_t")) { if (--index < 0) { for (n = 0; n < b->nfamilies; n++) { if (0 == strcmp (b->family[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nfamilies) { return cgi_add_posit((void *)&b->family[index], label, index + 1, b->family[index].id); } } else if (0 == strcmp (label, "BaseIterativeData_t")) { if (b->biter && (index == 1 || 0 == strcmp (b->biter->name, name))) { return cgi_add_posit((void *)b->biter, label, 1, b->biter->id); } } else if (0 == strcmp (label, "ConvergenceHistory_t")) { if (b->converg && (index == 1 || 0 == strcmp (b->converg->name, name))) { return cgi_add_posit((void *)b->converg, label, 1, b->converg->id); } } else if (0 == strcmp (label, "FlowEquationSet_t")) { if (b->equations && (index == 1 || 0 == strcmp (b->equations->name, name))) { return cgi_add_posit((void *)b->equations, label, 1, b->equations->id); } } else if (0 == strcmp (label, "IntegralData_t")) { if (--index < 0) { for (n = 0; n < b->nintegrals; n++) { if (0 == strcmp (b->integral[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nintegrals) { return cgi_add_posit((void *)&b->integral[index], label, index + 1, b->integral[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < b->nuser_data; n++) { if (0 == strcmp (b->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nuser_data) { return cgi_add_posit((void *)&b->user_data[index], label, index + 1, b->user_data[index].id); } } else if (0 == strcmp (label, "Gravity_t")) { if (b->gravity && (index == 1 || 0 == strcmp (b->gravity->name, name))) { return cgi_add_posit((void *)b->gravity, label, 1, b->gravity->id); } } else if (0 == strcmp (label, "Axisymmetry_t")) { if (b->axisym && (index == 1 || 0 == strcmp (b->axisym->name, name))) { return cgi_add_posit((void *)b->axisym, label, 1, b->axisym->id); } } else if (0 == strcmp (label, "RotatingCoordinates_t")) { if (b->rotating && (index == 1 || 0 == strcmp (b->rotating->name, name))) { return cgi_add_posit((void *)b->rotating, label, 1, b->rotating->id); } } else return CG_INCORRECT_PATH; } /* Zone_t */ else if (0 == strcmp (posit->label, "Zone_t")) { cgns_zone *z = (cgns_zone *)posit->posit; if (0 == strcmp (label, "GridCoordinates_t")) { if (--index < 0) { for (n = 0; n < z->nzcoor; n++) { if (0 == strcmp (z->zcoor[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nzcoor) { return cgi_add_posit((void *)&z->zcoor[index], label, index + 1, z->zcoor[index].id); } } else if (0 == strcmp (label, "ZoneIterativeData_t")) { if (z->ziter && (index == 1 || 0 == strcmp (z->ziter->name, name))) { return cgi_add_posit((void *)z->ziter, label, 1, z->ziter->id); } } else if (0 == strcmp (label, "Elements_t")) { if (--index < 0) { for (n = 0; n < z->nsections; n++) { if (0 == strcmp (z->section[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nsections) { return cgi_add_posit((void *)&z->section[index], label, index + 1, z->section[index].id); } } else if (0 == strcmp (label, "FlowSolution_t")) { if (--index < 0) { for (n = 0; n < z->nsols; n++) { if (0 == strcmp (z->sol[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nsols) { return cgi_add_posit((void *)&z->sol[index], label, index + 1, z->sol[index].id); } } else if (0 == strcmp (label, "RigidGridMotion_t")) { if (--index < 0) { for (n = 0; n < z->nrmotions; n++) { if (0 == strcmp (z->rmotion[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nrmotions) { return cgi_add_posit((void *)&z->rmotion[index], label, index + 1, z->rmotion[index].id); } } else if (0 == strcmp (label, "ArbitraryGridMotion_t")) { if (--index < 0) { for (n = 0; n < z->namotions; n++) { if (0 == strcmp (z->amotion[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->namotions) { return cgi_add_posit((void *)&z->amotion[index], label, index + 1, z->amotion[index].id); } } else if (0 == strcmp (label, "ZoneGridConnectivity_t")) { if (--index < 0) { for (n = 0; n < z->nzconn; n++) { if (0 == strcmp (z->zconn[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nzconn) { return cgi_add_posit((void *)&z->zconn[index], label, index + 1, z->zconn[index].id); } } else if (0 == strcmp (label, "ZoneBC_t")) { if (z->zboco && (index == 1 || 0 == strcmp (z->zboco->name, name))) { return cgi_add_posit((void *)z->zboco, label, 1, z->zboco->id); } } else if (0 == strcmp (label, "DiscreteData_t")) { if (--index < 0) { for (n = 0; n < z->ndiscrete; n++) { if (0 == strcmp (z->discrete[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->ndiscrete) { return cgi_add_posit((void *)&z->discrete[index], label, index + 1, z->discrete[index].id); } } else if (0 == strcmp (label, "FlowEquationSet_t")) { if (z->equations && (index == 1 || 0 == strcmp (z->equations->name, name))) { return cgi_add_posit((void *)z->equations, label, 1, z->equations->id); } } else if (0 == strcmp (label, "ConvergenceHistory_t")) { if (z->converg && (index == 1 || 0 == strcmp (z->converg->name, name))) { return cgi_add_posit((void *)z->converg, label, 1, z->converg->id); } } else if (0 == strcmp (label, "IntegralData_t")) { if (--index < 0) { for (n = 0; n < z->nintegrals; n++) { if (0 == strcmp (z->integral[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nintegrals) { return cgi_add_posit((void *)&z->integral[index], label, index + 1, z->integral[index].id); } } else if (0 == strcmp (label, "ReferenceState_t")) { if (z->state && (index == 1 || 0 == strcmp (z->state->name, name))) { return cgi_add_posit((void *)z->state, label, 1, z->state->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < z->nuser_data; n++) { if (0 == strcmp (z->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nuser_data) { return cgi_add_posit((void *)&z->user_data[index], label, index + 1, z->user_data[index].id); } } else if (0 == strcmp (label, "RotatingCoordinates_t")) { if (z->rotating && (index == 1 || 0 == strcmp (z->rotating->name, name))) { return cgi_add_posit((void *)z->rotating, label, 1, z->rotating->id); } } else if (0 == strcmp (label, "ZoneSubRegion_t")) { if (--index < 0) { for (n = 0; n < z->nsubreg; n++) { if (0 == strcmp (z->subreg[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nsubreg) { return cgi_add_posit((void *)&z->subreg[index], label, index + 1, z->subreg[index].id); } } else return CG_INCORRECT_PATH; } /* GridCoordinates_t */ else if (0 == strcmp (posit->label, "GridCoordinates_t")) { cgns_zcoor *z = (cgns_zcoor *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < z->ncoords; n++) { if (0 == strcmp (z->coord[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->ncoords) { return cgi_add_posit((void *)&z->coord[index], label, index + 1, z->coord[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < z->nuser_data; n++) { if (0 == strcmp (z->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nuser_data) { return cgi_add_posit((void *)&z->user_data[index], label, index + 1, z->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* FlowSolution_t */ else if (0 == strcmp (posit->label, "FlowSolution_t")) { cgns_sol *s = (cgns_sol *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < s->nfields; n++) { if (0 == strcmp (s->field[n].name, name)) { index = n; break; } } } if (index >= 0 && index < s->nfields) { return cgi_add_posit((void *)&s->field[index], label, index + 1, s->field[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < s->nuser_data; n++) { if (0 == strcmp (s->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < s->nuser_data) { return cgi_add_posit((void *)&s->user_data[index], label, index + 1, s->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ZoneGridConnectivity_t */ else if (0 == strcmp (posit->label, "ZoneGridConnectivity_t")) { cgns_zconn *z = (cgns_zconn *)posit->posit; if (0 == strcmp (label, "OversetHoles_t")) { if (--index < 0) { for (n = 0; n < z->nholes; n++) { if (0 == strcmp (z->hole[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nholes) { return cgi_add_posit((void *)&z->hole[index], label, index + 1, z->hole[index].id); } } else if (0 == strcmp (label, "GridConnectivity_t")) { if (--index < 0) { for (n = 0; n < z->nconns; n++) { if (0 == strcmp (z->conn[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nconns) { return cgi_add_posit((void *)&z->conn[index], label, index + 1, z->conn[index].id); } } else if (0 == strcmp (label, "GridConnectivity1to1_t")) { if (--index < 0) { for (n = 0; n < z->n1to1; n++) { if (0 == strcmp (z->one21[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->n1to1) { return cgi_add_posit((void *)&z->one21[index], label, index + 1, z->one21[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < z->nuser_data; n++) { if (0 == strcmp (z->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nuser_data) { return cgi_add_posit((void *)&z->user_data[index], label, index + 1, z->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* OversetHoles_t */ else if (0 == strcmp (posit->label, "OversetHoles_t")) { cgns_hole *h = (cgns_hole *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < h->nuser_data; n++) { if (0 == strcmp (h->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < h->nuser_data) { return cgi_add_posit((void *)&h->user_data[index], label, index + 1, h->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GridConnectivity_t */ else if (0 == strcmp (posit->label, "GridConnectivity_t")) { cgns_conn *c = (cgns_conn *)posit->posit; if (0 == strcmp (label, "GridConnectivityProperty_t")) { if (c->cprop && (index == 1 || 0 == strcmp (c->cprop->name, name))) { return cgi_add_posit((void *)c->cprop, label, 1, c->cprop->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < c->nuser_data; n++) { if (0 == strcmp (c->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < c->nuser_data) { return cgi_add_posit((void *)&c->user_data[index], label, index + 1, c->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GridConnectivity1to1_t */ else if (0 == strcmp (posit->label, "GridConnectivity1to1_t")) { cgns_1to1 *c = (cgns_1to1 *)posit->posit; if (0 == strcmp (label, "GridConnectivityProperty_t")) { if (c->cprop && (index == 1 || 0 == strcmp (c->cprop->name, name))) { return cgi_add_posit((void *)c->cprop, label, 1, c->cprop->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < c->nuser_data; n++) { if (0 == strcmp (c->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < c->nuser_data) { return cgi_add_posit((void *)&c->user_data[index], label, index + 1, c->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ZoneBC_t */ else if (0 == strcmp (posit->label, "ZoneBC_t")) { cgns_zboco *z = (cgns_zboco *)posit->posit; if (0 == strcmp (label, "BC_t")) { if (--index < 0) { for (n = 0; n < z->nbocos; n++) { if (0 == strcmp (z->boco[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nbocos) { return cgi_add_posit((void *)&z->boco[index], label, index + 1, z->boco[index].id); } } else if (0 == strcmp (label, "ReferenceState_t")) { if (z->state && (index == 1 || 0 == strcmp (z->state->name, name))) { return cgi_add_posit((void *)z->state, label, 1, z->state->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < z->nuser_data; n++) { if (0 == strcmp (z->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nuser_data) { return cgi_add_posit((void *)&z->user_data[index], label, index + 1, z->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* BC_t */ else if (0 == strcmp (posit->label, "BC_t")) { cgns_boco *b = (cgns_boco *)posit->posit; if (0 == strcmp (label, "BCDataSet_t")) { if (--index < 0) { for (n = 0; n < b->ndataset; n++) { if (0 == strcmp (b->dataset[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->ndataset) { return cgi_add_posit((void *)&b->dataset[index], label, index + 1, b->dataset[index].id); } } else if (0 == strcmp (label, "BCProperty_t")) { if (b->bprop && (index == 1 || 0 == strcmp (b->bprop->name, name))) { return cgi_add_posit((void *)b->bprop, label, 1, b->bprop->id); } } else if (0 == strcmp (label, "ReferenceState_t")) { if (b->state && (index == 1 || 0 == strcmp (b->state->name, name))) { return cgi_add_posit((void *)b->state, label, 1, b->state->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < b->nuser_data; n++) { if (0 == strcmp (b->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nuser_data) { return cgi_add_posit((void *)&b->user_data[index], label, index + 1, b->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* BCDataSet_t and FamilyBCDataSet_t */ else if (0 == strcmp (posit->label, "BCDataSet_t") || 0 == strcmp (posit->label, "FamilyBCDataSet_t")) { cgns_dataset *d = (cgns_dataset *)posit->posit; if (0 == strcmp (label, "BCData_t")) { if (d->dirichlet && (index == CGNS_ENUMV(Dirichlet) || 0 == strcmp (d->dirichlet->name, name))) { return cgi_add_posit((void *)d->dirichlet, label, 1, d->dirichlet->id); } if (d->neumann && (index == CGNS_ENUMV(Neumann) || 0 == strcmp (d->neumann->name, name))) { return cgi_add_posit((void *)d->neumann, label, 1, d->neumann->id); } } else if (0 == strcmp (label, "ReferenceState_t")) { if (d->state && (index == 1 || 0 == strcmp (d->state->name, name))) { return cgi_add_posit((void *)d->state, label, 1, d->state->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < d->nuser_data; n++) { if (0 == strcmp (d->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < d->nuser_data) { return cgi_add_posit((void *)&d->user_data[index], label, index + 1, d->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* BCData_t */ else if (0 == strcmp (posit->label, "BCData_t")) { cgns_bcdata *b = (cgns_bcdata *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < b->narrays; n++) { if (0 == strcmp (b->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->narrays) { return cgi_add_posit((void *)&b->array[index], label, index + 1, b->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < b->nuser_data; n++) { if (0 == strcmp (b->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nuser_data) { return cgi_add_posit((void *)&b->user_data[index], label, index + 1, b->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* DiscreteData_t */ else if (0 == strcmp (posit->label, "DiscreteData_t")) { cgns_discrete *d = (cgns_discrete *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < d->narrays; n++) { if (0 == strcmp (d->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < d->narrays) { return cgi_add_posit((void *)&d->array[index], label, index + 1, d->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < d->nuser_data; n++) { if (0 == strcmp (d->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < d->nuser_data) { return cgi_add_posit((void *)&d->user_data[index], label, index + 1, d->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* FlowEquationSet_t */ else if (0 == strcmp (posit->label, "FlowEquationSet_t")) { cgns_equations *e = (cgns_equations *)posit->posit; if (0 == strcmp (label, "GoverningEquations_t")) { if (e->governing && (index == 1 || 0 == strcmp (e->governing->name, name))) { return cgi_add_posit((void *)e->governing, label, 1, e->governing->id); } } else if (0 == strcmp (label, "GasModel_t")) { if (e->gas && (index == 1 || 0 == strcmp (e->gas->name, name))) { return cgi_add_posit((void *)e->gas, label, 1, e->gas->id); } } else if (0 == strcmp (label, "ViscosityModel_t")) { if (e->visc && (index == 1 || 0 == strcmp (e->visc->name, name))) { return cgi_add_posit((void *)e->visc, label, 1, e->visc->id); } } else if (0 == strcmp (label, "ThermalConductivityModel_t")) { if (e->conduct && (index == 1 || 0 == strcmp (e->conduct->name, name))) { return cgi_add_posit((void *)e->conduct, label, 1, e->conduct->id); } } else if (0 == strcmp (label, "TurbulenceModel_t")) { if (e->turbulence && (index == 1 || 0 == strcmp (e->turbulence->name, name))) { return cgi_add_posit((void *)e->turbulence, label, 1, e->turbulence->id); } } else if (0 == strcmp (label, "TurbulenceClosure_t")) { if (e->closure && (index == 1 || 0 == strcmp (e->closure->name, name))) { return cgi_add_posit((void *)e->closure, label, 1, e->closure->id); } } else if (0 == strcmp (label, "ThermalRelaxationModel_t")) { if (e->relaxation && (index == 1 || 0 == strcmp (e->relaxation->name, name))) { return cgi_add_posit((void *)e->relaxation, label, 1, e->relaxation->id); } } else if (0 == strcmp (label, "ChemicalKineticsModel_t")) { if (e->chemkin && (index == 1 || 0 == strcmp (e->chemkin->name, name))) { return cgi_add_posit((void *)e->chemkin, label, 1, e->chemkin->id); } } else if (0 == strcmp (label, "EMConductivityModel_t")) { if (e->emconduct && (index == 1 || 0 == strcmp (e->emconduct->name, name))) { return cgi_add_posit((void *)e->emconduct, label, 1, e->emconduct->id); } } else if (0 == strcmp (label, "EMElectricFieldModel_t")) { if (e->elecfield && (index == 1 || 0 == strcmp (e->elecfield->name, name))) { return cgi_add_posit((void *)e->elecfield, label, 1, e->elecfield->id); } } else if (0 == strcmp (label, "EMMagneticFieldModel_t")) { if (e->magnfield && (index == 1 || 0 == strcmp (e->magnfield->name, name))) { return cgi_add_posit((void *)e->magnfield, label, 1, e->magnfield->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < e->nuser_data; n++) { if (0 == strcmp (e->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < e->nuser_data) { return cgi_add_posit((void *)&e->user_data[index], label, index + 1, e->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GoverningEquations_t */ else if (0 == strcmp (posit->label, "GoverningEquations_t")) { cgns_governing *g = (cgns_governing *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < g->nuser_data; n++) { if (0 == strcmp (g->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < g->nuser_data) { return cgi_add_posit((void *)&g->user_data[index], label, index + 1, g->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GasModel_t */ /* ViscosityModel_t */ /* ThermalConductivityModel_t */ /* TurbulenceModel_t */ /* TurbulenceClosure_t */ /* ThermalRelaxationModel_t */ /* ChemicalKineticsModel_t */ /* EMConductivityModel_t */ /* EMElectricFieldModel_t */ /* EMMagneticFieldModel_t */ else if (0 == strcmp (posit->label, "GasModel_t") || 0 == strcmp (posit->label, "ViscosityModel_t") || 0 == strcmp (posit->label, "ThermalConductivityModel_t") || 0 == strcmp (posit->label, "TurbulenceModel_t") || 0 == strcmp (posit->label, "TurbulenceClosure_t") || 0 == strcmp (posit->label, "ThermalRelaxationModel_t") || 0 == strcmp (posit->label, "ChemicalKineticsModel_t") || 0 == strcmp (posit->label, "EMConductivityModel_t") || 0 == strcmp (posit->label, "EMElectricFieldModel_t") || 0 == strcmp (posit->label, "EMMagneticFieldModel_t")) { cgns_model *m = (cgns_model *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < m->narrays; n++) { if (0 == strcmp (m->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->narrays) { return cgi_add_posit((void *)&m->array[index], label, index + 1, m->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < m->nuser_data; n++) { if (0 == strcmp (m->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->nuser_data) { return cgi_add_posit((void *)&m->user_data[index], label, index + 1, m->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ConvergenceHistory_t */ else if (0 == strcmp (posit->label, "ConvergenceHistory_t")) { cgns_converg *c = (cgns_converg *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < c->narrays; n++) { if (0 == strcmp (c->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < c->narrays) { return cgi_add_posit((void *)&c->array[index], label, index + 1, c->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < c->nuser_data; n++) { if (0 == strcmp (c->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < c->nuser_data) { return cgi_add_posit((void *)&c->user_data[index], label, index + 1, c->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* IntegralData_t */ else if (0 == strcmp (posit->label, "IntegralData_t")) { cgns_integral *i = (cgns_integral *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < i->narrays; n++) { if (0 == strcmp (i->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < i->narrays) { return cgi_add_posit((void *)&i->array[index], label, index + 1, i->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < i->nuser_data; n++) { if (0 == strcmp (i->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < i->nuser_data) { return cgi_add_posit((void *)&i->user_data[index], label, index + 1, i->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ReferenceState_t */ else if (0 == strcmp (posit->label, "ReferenceState_t")) { cgns_state *s = (cgns_state *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < s->narrays; n++) { if (0 == strcmp (s->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < s->narrays) { return cgi_add_posit((void *)&s->array[index], label, index + 1, s->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < s->nuser_data; n++) { if (0 == strcmp (s->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < s->nuser_data) { return cgi_add_posit((void *)&s->user_data[index], label, index + 1, s->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Elements_t */ else if (0 == strcmp (posit->label, "Elements_t")) { cgns_section *s = (cgns_section *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < s->nuser_data; n++) { if (0 == strcmp (s->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < s->nuser_data) { return cgi_add_posit((void *)&s->user_data[index], label, index + 1, s->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Family_t */ else if (0 == strcmp (posit->label, "Family_t")) { cgns_family *f = (cgns_family *)posit->posit; if (0 == strcmp (label, "GeometryReference_t")) { if (--index < 0) { for (n = 0; n < f->ngeos; n++) { if (0 == strcmp (f->geo[n].name, name)) { index = n; break; } } } if (index >= 0 && index < f->ngeos) { return cgi_add_posit((void *)&f->geo[index], label, index + 1, f->geo[index].id); } } else if (0 == strcmp (label, "FamilyBC_t")) { if (--index < 0) { for (n = 0; n < f->nfambc; n++) { if (0 == strcmp (f->fambc[n].name, name)) { index = n; break; } } } if (index >= 0 && index < f->nfambc) { return cgi_add_posit((void *)&f->fambc[index], label, index + 1, f->fambc[index].id); } } else if (0 == strcmp (label, "RotatingCoordinates_t")) { if (f->rotating && (index == 1 || 0 == strcmp (f->rotating->name, name))) { return cgi_add_posit((void *)f->rotating, label, 1, f->rotating->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < f->nuser_data; n++) { if (0 == strcmp (f->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < f->nuser_data) { return cgi_add_posit((void *)&f->user_data[index], label, index + 1, f->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GeometryReference_t */ else if (0 == strcmp (posit->label, "GeometryReference_t")) { cgns_geo *g = (cgns_geo *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < g->nuser_data; n++) { if (0 == strcmp (g->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < g->nuser_data) { return cgi_add_posit((void *)&g->user_data[index], label, index + 1, g->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* FamilyBC_t */ else if (0 == strcmp (posit->label, "FamilyBC_t")) { cgns_fambc *f = (cgns_fambc *)posit->posit; if (0 == strcmp (label, "FamilyBCDataSet_t") || /* backwards compatibily */ 0 == strcmp (label, "BCDataSet_t")) { if (--index < 0) { for (n = 0; n < f->ndataset; n++) { if (0 == strcmp (f->dataset[n].name, name)) { index = n; break; } } } if (index >= 0 && index < f->ndataset) { return cgi_add_posit((void *)&f->dataset[index], "FamilyBCDataSet_t", index + 1, f->dataset[index].id); } } else return CG_INCORRECT_PATH; } /* RigidGridMotion_t */ else if (0 == strcmp (posit->label, "RigidGridMotion_t")) { cgns_rmotion *m = (cgns_rmotion *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < m->narrays; n++) { if (0 == strcmp (m->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->narrays) { return cgi_add_posit((void *)&m->array[index], label, index + 1, m->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < m->nuser_data; n++) { if (0 == strcmp (m->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->nuser_data) { return cgi_add_posit((void *)&m->user_data[index], label, index + 1, m->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ArbitraryGridMotion_t */ else if (0 == strcmp (posit->label, "ArbitraryGridMotion_t")) { cgns_amotion *m = (cgns_amotion *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < m->narrays; n++) { if (0 == strcmp (m->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->narrays) { return cgi_add_posit((void *)&m->array[index], label, index + 1, m->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < m->nuser_data; n++) { if (0 == strcmp (m->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < m->nuser_data) { return cgi_add_posit((void *)&m->user_data[index], label, index + 1, m->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* BaseIterativeData_t */ else if (0 == strcmp (posit->label, "BaseIterativeData_t")) { cgns_biter *b = (cgns_biter *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < b->narrays; n++) { if (0 == strcmp (b->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->narrays) { return cgi_add_posit((void *)&b->array[index], label, index + 1, b->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < b->nuser_data; n++) { if (0 == strcmp (b->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nuser_data) { return cgi_add_posit((void *)&b->user_data[index], label, index + 1, b->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ZoneIterativeData_t */ else if (0 == strcmp (posit->label, "ZoneIterativeData_t")) { cgns_ziter *z = (cgns_ziter *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < z->narrays; n++) { if (0 == strcmp (z->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->narrays) { return cgi_add_posit((void *)&z->array[index], label, index + 1, z->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < z->nuser_data; n++) { if (0 == strcmp (z->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < z->nuser_data) { return cgi_add_posit((void *)&z->user_data[index], label, index + 1, z->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* UserDefinedData_t */ else if (0 == strcmp (posit->label, "UserDefinedData_t")) { cgns_user_data *u = (cgns_user_data *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < u->narrays; n++) { if (0 == strcmp (u->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < u->narrays) { return cgi_add_posit((void *)&u->array[index], label, index + 1, u->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < u->nuser_data; n++) { if (0 == strcmp (u->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < u->nuser_data) { return cgi_add_posit((void *)&u->user_data[index], label, index + 1, u->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Gravity_t */ else if (0 == strcmp (posit->label, "Gravity_t")) { cgns_gravity *g = (cgns_gravity *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < g->narrays; n++) { if (0 == strcmp (g->vector[n].name, name)) { index = n; break; } } } if (index >= 0 && index < g->narrays) { return cgi_add_posit((void *)&g->vector[index], label, index + 1, g->vector[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < g->nuser_data; n++) { if (0 == strcmp (g->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < g->nuser_data) { return cgi_add_posit((void *)&g->user_data[index], label, index + 1, g->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Axisymmetry_t */ else if (0 == strcmp (posit->label, "Axisymmetry_t")) { cgns_axisym *a = (cgns_axisym *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < a->narrays; n++) { if (0 == strcmp (a->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < a->narrays) { return cgi_add_posit((void *)&a->array[index], label, index + 1, a->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < a->nuser_data; n++) { if (0 == strcmp (a->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < a->nuser_data) { return cgi_add_posit((void *)&a->user_data[index], label, index + 1, a->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* RotatingCoordinates_t */ else if (0 == strcmp (posit->label, "RotatingCoordinates_t")) { cgns_rotating *r = (cgns_rotating *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < r->narrays; n++) { if (0 == strcmp (r->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < r->narrays) { return cgi_add_posit((void *)&r->array[index], label, index + 1, r->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < r->nuser_data; n++) { if (0 == strcmp (r->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < r->nuser_data) { return cgi_add_posit((void *)&r->user_data[index], label, index + 1, r->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* BCProperty_t */ else if (0 == strcmp (posit->label, "BCProperty_t")) { cgns_bprop *b = (cgns_bprop *)posit->posit; if (0 == strcmp (label, "WallFunction_t")) { if (b->bcwall && (index == 1 || 0 == strcmp (b->bcwall->name, name))) { return cgi_add_posit((void *)b->bcwall, label, 1, b->bcwall->id); } } else if (0 == strcmp (label, "Area_t")) { if (b->bcarea && (index == 1 || 0 == strcmp (b->bcarea->name, name))) { return cgi_add_posit((void *)b->bcarea, label, 1, b->bcarea->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < b->nuser_data; n++) { if (0 == strcmp (b->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < b->nuser_data) { return cgi_add_posit((void *)&b->user_data[index], label, index + 1, b->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* WallFunction_t */ else if (0 == strcmp (posit->label, "WallFunction_t")) { cgns_bcwall *w = (cgns_bcwall *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < w->nuser_data; n++) { if (0 == strcmp (w->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < w->nuser_data) { return cgi_add_posit((void *)&w->user_data[index], label, index + 1, w->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Area_t */ else if (0 == strcmp (posit->label, "Area_t")) { cgns_bcarea *a = (cgns_bcarea *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < a->narrays; n++) { if (0 == strcmp (a->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < a->narrays) { return cgi_add_posit((void *)&a->array[index], label, index + 1, a->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < a->nuser_data; n++) { if (0 == strcmp (a->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < a->nuser_data) { return cgi_add_posit((void *)&a->user_data[index], label, index + 1, a->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* GridConnectivityProperty_t */ else if (0 == strcmp (posit->label, "GridConnectivityProperty_t")) { cgns_cprop *c = (cgns_cprop *)posit->posit; if (0 == strcmp (label, "Periodic_t")) { if (c->cperio && (index == 1 || 0 == strcmp (c->cperio->name, name))) { return cgi_add_posit((void *)c->cperio, label, 1, c->cperio->id); } } else if (0 == strcmp (label, "AverageInterface_t")) { if (c->caverage && (index == 1 || 0 == strcmp (c->caverage->name, name))) { return cgi_add_posit((void *)c->caverage, label, 1, c->caverage->id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < c->nuser_data; n++) { if (0 == strcmp (c->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < c->nuser_data) { return cgi_add_posit((void *)&c->user_data[index], label, index + 1, c->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* Periodic_t */ else if (0 == strcmp (posit->label, "Periodic_t")) { cgns_cperio *p = (cgns_cperio *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < p->narrays; n++) { if (0 == strcmp (p->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < p->narrays) { return cgi_add_posit((void *)&p->array[index], label, index + 1, p->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < p->nuser_data; n++) { if (0 == strcmp (p->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < p->nuser_data) { return cgi_add_posit((void *)&p->user_data[index], label, index + 1, p->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* AverageInterface_t */ else if (0 == strcmp (posit->label, "AverageInterface_t")) { cgns_caverage *a = (cgns_caverage *)posit->posit; if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < a->nuser_data; n++) { if (0 == strcmp (a->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < a->nuser_data) { return cgi_add_posit((void *)&a->user_data[index], label, index + 1, a->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* ZoneSubRegion_t */ else if (0 == strcmp (posit->label, "ZoneSubRegion_t")) { cgns_subreg *r = (cgns_subreg *)posit->posit; if (0 == strcmp (label, "DataArray_t")) { if (--index < 0) { for (n = 0; n < r->narrays; n++) { if (0 == strcmp (r->array[n].name, name)) { index = n; break; } } } if (index >= 0 && index < r->narrays) { return cgi_add_posit((void *)&r->array[index], label, index + 1, r->array[index].id); } } else if (0 == strcmp (label, "UserDefinedData_t")) { if (--index < 0) { for (n = 0; n < r->nuser_data; n++) { if (0 == strcmp (r->user_data[n].name, name)) { index = n; break; } } } if (index >= 0 && index < r->nuser_data) { return cgi_add_posit((void *)&r->user_data[index], label, index + 1, r->user_data[index].id); } } else return CG_INCORRECT_PATH; } /* invalid */ else return CG_INCORRECT_PATH; return CG_NODE_NOT_FOUND; } int cgi_update_posit(int cnt, int *index, char **label) { int n, ierr; double pid, id; char lab[33], name[33]; if (posit == 0) { cgi_error("goto position not set"); return CG_ERROR; } for (n = 0; n < cnt; n++) { if (index[n] > 0) { strcpy(lab, label[n]); *name = 0; } else if (0 == strcmp(label[n], ".")) { continue; } else if (0 == strcmp(label[n], "..")) { if (posit_depth == 1) { cgi_error("can't go up beyond CGNSBase_t node"); posit = 0; return CG_ERROR; } if (0 == strcmp(posit->label, "Zone_t")) posit_zone = 0; posit_depth--; posit = &posit_stack[posit_depth-1]; continue; } else { if (cgi_posit_id (&pid)) { posit = 0; return CG_ERROR; } strcpy(name, label[n]); if (cgio_get_node_id(cg->cgio, pid, name, &id)) { posit = 0; cgi_error ("goto path not found"); return CG_NODE_NOT_FOUND; } if (cgio_get_label(cg->cgio, id, lab)) { posit = 0; cg_io_error("cgio_get_label"); return CG_ERROR; } } ierr = cgi_next_posit(lab, index[n], name); if (ierr) { if (ierr == CG_INCORRECT_PATH) { cgi_error("can't go to label '%s' under '%s'", lab, posit->label); } if (ierr == CG_NODE_NOT_FOUND) { if (index[n] > 0) cgi_error("index %d, label '%s' not a child of '%s'", index[n], lab, posit->label); else cgi_error("node '%s' not a child of '%s'", name, posit->label); } posit = 0; return ierr; } } return CG_OK; } int cgi_set_posit(int fn, int B, int n, int *index, char **label) { cgns_base *base; /* initialize */ posit = 0; posit_file = posit_base = posit_zone = posit_depth = 0; /* get file pointer */ cg = cgi_get_file(fn); if (cg == 0) return CG_OK; base = cgi_get_base(cg, B); if (base == 0) return CG_NODE_NOT_FOUND; posit_file = fn; posit_base = B; cgi_add_posit((void *)base, "CGNSBase_t", B, base->id); return cgi_update_posit(n, index, label); } int cgi_posit_id(double *posit_id) { /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); return CG_ERROR; } *posit_id = posit->id; return CG_OK; } cgns_posit *cgi_get_posit() { /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); return NULL; } return posit; } int cgi_posit_index_dim() { if (posit_base) { if (posit_zone) return cg->base[posit_base-1].zone[posit_zone-1].index_dim; return cg->base[posit_base-1].cell_dim; } return CG_OK; } /* All cgi_xxxxx_address functions return the memory address of the given *\ * xxxxx data structure, depending on the parent pointed to by cg_goto. * \* All possible parents of a given data structure must be represented. */ cgns_descr *cgi_descr_address(int local_mode, int given_no, char const *given_name, int *ier) { cgns_descr *descr=0; int n, allow_dup=0, error1=0, error2=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of Descriptor_t node: * CGNSBase_t, Zone_t, GridCoordinates_t, Elements_t, FlowSolution_t, * DiscreteData_t, ZoneGridConnectivity_t, GridConnectivity1to1_t, * GridConnectivity_t, OversetHoles_t, ZoneBC_t, BC_t, BCDataSet_t, * BCData_t, FlowEquationSet_t, GoverningEquations_t, GasModel_t, * ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * DataArray_t, Family_t, GeometryReference_t, RigidGridMotion_t, * ArbitraryGridMotion_t, BaseIterativeData_t, ZoneIterativeData_t, * UserDefinedData_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t, * BCProperty_t, WallFunction_t, Area_t, * GridConnectivityProperty_t, Periodic_t, AverageInterface_t * FamilyBCDataSet_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4MULTIPLE(cgns_base, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4MULTIPLE(cgns_zone, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GridCoordinates_t")==0) ADDRESS4MULTIPLE(cgns_zcoor, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Elements_t")==0) ADDRESS4MULTIPLE(cgns_section, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4MULTIPLE(cgns_sol, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4MULTIPLE(cgns_discrete, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ZoneGridConnectivity_t")==0) ADDRESS4MULTIPLE(cgns_zconn, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) ADDRESS4MULTIPLE(cgns_1to1, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GridConnectivity_t")==0) ADDRESS4MULTIPLE(cgns_conn, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"OversetHoles_t")==0) ADDRESS4MULTIPLE(cgns_hole, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ZoneBC_t")==0) ADDRESS4MULTIPLE(cgns_zboco, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4MULTIPLE(cgns_boco, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) ADDRESS4MULTIPLE(cgns_dataset, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"BCData_t")==0) ADDRESS4MULTIPLE(cgns_bcdata, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"FlowEquationSet_t")==0) ADDRESS4MULTIPLE(cgns_equations, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GoverningEquations_t")==0) ADDRESS4MULTIPLE(cgns_governing, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) ADDRESS4MULTIPLE(cgns_model, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ConvergenceHistory_t")==0) ADDRESS4MULTIPLE(cgns_converg, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"IntegralData_t")==0) ADDRESS4MULTIPLE(cgns_integral, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ReferenceState_t")==0) ADDRESS4MULTIPLE(cgns_state, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"DataArray_t")==0) ADDRESS4MULTIPLE(cgns_array, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Family_t")==0) ADDRESS4MULTIPLE(cgns_family, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GeometryReference_t")==0) ADDRESS4MULTIPLE(cgns_geo, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"RigidGridMotion_t")==0) ADDRESS4MULTIPLE(cgns_rmotion, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4MULTIPLE(cgns_amotion, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"BaseIterativeData_t")==0) ADDRESS4MULTIPLE(cgns_biter, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ZoneIterativeData_t")==0) ADDRESS4MULTIPLE(cgns_ziter, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4MULTIPLE(cgns_user_data, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Gravity_t")==0) ADDRESS4MULTIPLE(cgns_gravity, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Axisymmetry_t")==0) ADDRESS4MULTIPLE(cgns_axisym, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"RotatingCoordinates_t")==0) ADDRESS4MULTIPLE(cgns_rotating, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"BCProperty_t")==0) ADDRESS4MULTIPLE(cgns_bprop, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"WallFunction_t")==0) ADDRESS4MULTIPLE(cgns_bcwall, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Area_t")==0) ADDRESS4MULTIPLE(cgns_bcarea, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"GridConnectivityProperty_t")==0) ADDRESS4MULTIPLE(cgns_cprop, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"Periodic_t")==0) ADDRESS4MULTIPLE(cgns_cperio, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"AverageInterface_t")==0) ADDRESS4MULTIPLE(cgns_caverage, ndescr, descr, cgns_descr) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4MULTIPLE(cgns_subreg, ndescr, descr, cgns_descr) else { cgi_error("Descriptor_t node not supported under '%s' type node (cgi_descr_address)", posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } if (error2) { cgi_error("Descriptor number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, descr->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_descr(descr); } return descr; } char *cgi_famname_address(int local_mode, int *ier) { double *id, parent_id; char *family_name=0; int nnod; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of FamilyName_t node: * Zone_t, BC_t, ZoneSubRegion_t, UserDefinedData_t */ if (strcmp(posit->label,"Zone_t")==0) { cgns_zone *zone = (cgns_zone *)posit->posit; family_name = zone->family_name; parent_id = zone->id; } else if (strcmp(posit->label,"BC_t")==0) { cgns_boco *boco = (cgns_boco *)posit->posit; family_name = boco->family_name; parent_id = boco->id; } else if (strcmp(posit->label,"UserDefinedData_t")==0) { cgns_user_data *user_data = (cgns_user_data *)posit->posit; family_name = user_data->family_name; parent_id = user_data->id; } else if (strcmp(posit->label,"ZoneSubRegion_t")==0) { cgns_subreg *subreg = (cgns_subreg *)posit->posit; family_name = subreg->family_name; parent_id = subreg->id; } else { cgi_error("FamilyName_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (cg->mode == CG_MODE_MODIFY && local_mode == CG_MODE_WRITE) { if (cgi_get_nodes(parent_id, "FamilyName_t", &nnod, &id)) { *ier = CG_ERROR; return CG_OK; } if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } } return family_name; } cgns_famname *cgi_multfam_address(int local_mode, int given_no, char const *given_name, int *ier) { cgns_famname *famname=0; int n, allow_dup=0, error1=0, error2=0; double parent_id=0; if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } if (0 == strcmp(posit->label, "Zone_t")) ADDRESS4MULTIPLE(cgns_zone, nfamname, famname, cgns_famname) else if (0 == strcmp(posit->label, "BC_t")) ADDRESS4MULTIPLE(cgns_boco, nfamname, famname, cgns_famname) else if (0 == strcmp(posit->label, "ZoneSubRegion_t")) ADDRESS4MULTIPLE(cgns_subreg, nfamname, famname, cgns_famname) else if (0 == strcmp(posit->label, "UserDefinedData_t")) ADDRESS4MULTIPLE(cgns_user_data, nfamname, famname, cgns_famname) else { cgi_error("AdditionalFamilyName_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } if (error2) { cgi_error("AdditionalFamilyName index number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, famname->id)) { (*ier) = CG_ERROR; return CG_OK; } } return famname; } CGNS_ENUMV(DataClass_t) *cgi_dataclass_address(int local_mode, int *ier) { double *id, parent_id; CGNS_ENUMV( DataClass_t ) *data_class=0; int nnod; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of DataClass_t node: * CGNSBase_t, Zone_t, GridCoordinates_t, FlowSolution_t, DiscreteData_t, * ZoneBC_t, BC_t, BCDataSet_t, BCData_t, FlowEquationSet_t, GasModel_t, * ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * DataArray_t, RigidGridMotion_t, ArbitraryGridMotion_t, BaseIterativeData_t, * ZoneIterativeData_t, UserDefinedData_t, Gravity_t, Axisymmetry_t * RotatingCoordinates_t, Periodic_t, FamilyBCDataSet_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4SINGLE_ALLOC(cgns_base, data_class) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE_ALLOC(cgns_zone, data_class) else if (strcmp(posit->label,"GridCoordinates_t")==0) ADDRESS4SINGLE_ALLOC(cgns_zcoor, data_class) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4SINGLE_ALLOC(cgns_sol, data_class) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_discrete, data_class) else if (strcmp(posit->label,"ZoneBC_t")==0) ADDRESS4SINGLE_ALLOC(cgns_zboco, data_class) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE_ALLOC(cgns_boco, data_class) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) ADDRESS4SINGLE_ALLOC(cgns_dataset, data_class) else if (strcmp(posit->label,"BCData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_bcdata, data_class) else if (strcmp(posit->label,"FlowEquationSet_t")==0) ADDRESS4SINGLE_ALLOC(cgns_equations, data_class) else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) ADDRESS4SINGLE_ALLOC(cgns_model, data_class) else if (strcmp(posit->label,"ConvergenceHistory_t")==0) ADDRESS4SINGLE_ALLOC(cgns_converg, data_class) else if (strcmp(posit->label,"IntegralData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_integral, data_class) else if (strcmp(posit->label,"ReferenceState_t")==0) ADDRESS4SINGLE_ALLOC(cgns_state, data_class) else if (strcmp(posit->label,"DataArray_t")==0) ADDRESS4SINGLE_ALLOC(cgns_array, data_class) else if (strcmp(posit->label,"RigidGridMotion_t")==0) ADDRESS4SINGLE_ALLOC(cgns_rmotion, data_class) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4SINGLE_ALLOC(cgns_amotion, data_class) else if (strcmp(posit->label,"BaseIterativeData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_biter, data_class) else if (strcmp(posit->label,"ZoneIterativeData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_ziter, data_class) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_user_data, data_class) else if (strcmp(posit->label,"Gravity_t")==0) ADDRESS4SINGLE_ALLOC(cgns_gravity, data_class) else if (strcmp(posit->label,"Axisymmetry_t")==0) ADDRESS4SINGLE_ALLOC(cgns_axisym, data_class) else if (strcmp(posit->label,"RotatingCoordinates_t")==0) ADDRESS4SINGLE_ALLOC(cgns_rotating, data_class) else if (strcmp(posit->label,"Periodic_t")==0) ADDRESS4SINGLE_ALLOC(cgns_cperio, data_class) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4SINGLE_ALLOC(cgns_subreg, data_class) else { cgi_error("DataClass_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (cg->mode == CG_MODE_MODIFY && local_mode == CG_MODE_WRITE) { if (cgi_get_nodes(parent_id, "DataClass_t", &nnod, &id)) return CG_OK; if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } } return data_class; } cgns_units *cgi_units_address(int local_mode, int *ier) { cgns_units *units=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of DimensionalUnits_t node: * CGNSBase_t, Zone_t, GridCoordinates_t, FlowSolution_t, DiscreteData_t, * ZoneBC_t, BC_t, BCDataSet_t, BCData_t, FlowEquationSet_t, GasModel_t, * ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * DataArray_t, RigidGridMotion_t, ArbitraryGridMotion_t, BaseIterativeData_t, * ZoneIterativeData_t, UserDefinedData_t, Gravity_t, Axisymmetry_t * RotatingCoordinates_t, Periodic_t, FamilyBCDataSet_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4SINGLE(cgns_base, units, cgns_units, 1) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE(cgns_zone, units, cgns_units, 1) else if (strcmp(posit->label,"GridCoordinates_t")==0) ADDRESS4SINGLE(cgns_zcoor, units, cgns_units, 1) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4SINGLE(cgns_sol, units, cgns_units, 1) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4SINGLE(cgns_discrete, units, cgns_units, 1) else if (strcmp(posit->label,"ZoneBC_t")==0) ADDRESS4SINGLE(cgns_zboco, units, cgns_units, 1) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE(cgns_boco, units, cgns_units, 1) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) ADDRESS4SINGLE(cgns_dataset, units, cgns_units, 1) else if (strcmp(posit->label,"BCData_t")==0) ADDRESS4SINGLE(cgns_bcdata, units, cgns_units, 1) else if (strcmp(posit->label,"FlowEquationSet_t")==0) ADDRESS4SINGLE(cgns_equations, units, cgns_units, 1) else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) ADDRESS4SINGLE(cgns_model, units, cgns_units, 1) else if (strcmp(posit->label,"ConvergenceHistory_t")==0) ADDRESS4SINGLE(cgns_converg, units, cgns_units, 1) else if (strcmp(posit->label,"IntegralData_t")==0) ADDRESS4SINGLE(cgns_integral, units, cgns_units, 1) else if (strcmp(posit->label,"ReferenceState_t")==0) ADDRESS4SINGLE(cgns_state, units, cgns_units, 1) else if (strcmp(posit->label,"DataArray_t")==0) ADDRESS4SINGLE(cgns_array, units, cgns_units, 1) else if (strcmp(posit->label,"RigidGridMotion_t")==0) ADDRESS4SINGLE(cgns_rmotion, units, cgns_units, 1) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4SINGLE(cgns_amotion, units, cgns_units, 1) else if (strcmp(posit->label,"BaseIterativeData_t")==0) ADDRESS4SINGLE(cgns_biter, units, cgns_units, 1) else if (strcmp(posit->label,"ZoneIterativeData_t")==0) ADDRESS4SINGLE(cgns_ziter, units, cgns_units, 1) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4SINGLE(cgns_user_data, units, cgns_units, 1) else if (strcmp(posit->label,"Gravity_t")==0) ADDRESS4SINGLE(cgns_gravity, units, cgns_units, 1) else if (strcmp(posit->label,"Axisymmetry_t")==0) ADDRESS4SINGLE(cgns_axisym, units, cgns_units, 1) else if (strcmp(posit->label,"RotatingCoordinates_t")==0) ADDRESS4SINGLE(cgns_rotating, units, cgns_units, 1) else if (strcmp(posit->label,"Periodic_t")==0) ADDRESS4SINGLE(cgns_cperio, units, cgns_units, 1) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4SINGLE(cgns_subreg, units, cgns_units, 1) else { cgi_error("DimensionalUnits_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("DimensionalUnits_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!units && local_mode == CG_MODE_READ) { cgi_error("DimensionalUnits_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, units->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_units(units); } return units; } int *cgi_ordinal_address(int local_mode, int *ier) { double *id; int nnod; int *ordinal; double parent_id; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of Ordinal_t node: * Zone_t, GridConnectivity1to1_t, GridConnectivity_t, BC_t, Family_t, * UserDefinedData_t */ if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE_ALLOC(cgns_zone, ordinal) else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) ADDRESS4SINGLE_ALLOC(cgns_1to1, ordinal) else if (strcmp(posit->label,"GridConnectivity_t")==0) ADDRESS4SINGLE_ALLOC(cgns_conn, ordinal) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE_ALLOC(cgns_boco, ordinal) else if (strcmp(posit->label,"Family_t")==0) ADDRESS4SINGLE_ALLOC(cgns_family, ordinal) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_user_data, ordinal) else { cgi_error("Ordinal_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (cg->mode == CG_MODE_MODIFY && local_mode == CG_MODE_WRITE) { if (cgi_get_nodes(parent_id, "Ordinal_t", &nnod, &id)) return CG_OK; if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } } /* if ((*ordinal)==0) (*ier)= CG_NODE_NOT_FOUND;*/ return ordinal; } int *cgi_rind_address(int local_mode, int *ier) { int *rind_planes=0, nnod; double parent_id=0, *id; int error1=0, index_dim; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cgi_rind_address"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of Rind_t: * GridCoordinates_t, FlowSolution_t,DiscreteData_t, ArbitraryGridMotion_t */ if (strcmp(posit->label,"GridCoordinates_t")==0) ADDRESS4SINGLE(cgns_zcoor, rind_planes, int, 2*index_dim) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4SINGLE(cgns_sol, rind_planes, int, 2*index_dim) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4SINGLE(cgns_discrete, rind_planes, int, 2*index_dim) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4SINGLE(cgns_amotion, rind_planes, int, 2*index_dim) else if (strcmp(posit->label,"Elements_t")==0) ADDRESS4SINGLE(cgns_section, rind_planes, int, 2*index_dim) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4SINGLE(cgns_subreg, rind_planes, int, 2*index_dim) else { cgi_error("Rind_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } /* Corrected on July 27 2001 by Diane Poirier if (error1==1) { cgi_error("Rind_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } */ if (!rind_planes && local_mode == CG_MODE_READ) { cgi_error("Rind_t node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id && cg->mode==CG_MODE_MODIFY) { if (cgi_get_nodes(parent_id, "Rind_t", &nnod, &id)) return CG_OK; if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } } return rind_planes; } CGNS_ENUMT(GridLocation_t) *cgi_location_address(int local_mode, int *ier) { double *id, parent_id; CGNS_ENUMV( GridLocation_t ) *location=0; int nnod; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents for GridLocation_t: * FlowSolution_t, DiscreteData_t, GridConnectivity_t, OversetHoles_t, BC_t, * ArbitraryGridMotion_t, UserDefinedData_t */ if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4SINGLE_ALLOC(cgns_sol, location) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_discrete, location) else if (strcmp(posit->label,"GridConnectivity_t")==0) ADDRESS4SINGLE_ALLOC(cgns_conn, location) else if (strcmp(posit->label,"OversetHoles_t")==0) ADDRESS4SINGLE_ALLOC(cgns_hole, location) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE_ALLOC(cgns_boco, location) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4SINGLE_ALLOC(cgns_amotion, location) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4SINGLE_ALLOC(cgns_user_data, location) else if (strcmp(posit->label,"BCDataSet_t")==0) ADDRESS4SINGLE_ALLOC(cgns_dataset, location) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4SINGLE_ALLOC(cgns_subreg, location) else { cgi_error("GridLocation_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (cg->mode == CG_MODE_MODIFY && local_mode == CG_MODE_WRITE) { if (cgi_get_nodes(parent_id, "GridLocation_t", &nnod, &id)) return CG_OK; if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } } return location; } cgns_conversion *cgi_conversion_address(int local_mode, int *ier) { cgns_conversion *convert=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parent: DataArray_t */ if (strcmp(posit->label,"DataArray_t")==0) ADDRESS4SINGLE(cgns_array,convert, cgns_conversion, 1) else { cgi_error("DataConversion_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("DataConversion_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!convert && local_mode == CG_MODE_READ) { cgi_error("DataConversion_t node does not exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, convert->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_convert(convert); } return convert; } cgns_exponent *cgi_exponent_address(int local_mode, int *ier) { cgns_exponent *exponents=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parent: DataArray_t */ if (strcmp(posit->label,"DataArray_t")==0) ADDRESS4SINGLE(cgns_array, exponents, cgns_exponent, 1) else { cgi_error("DimensionalExponents_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("DimensionalExponents_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!exponents && local_mode == CG_MODE_READ) { cgi_error("DimensionalExponents_t node does not exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, exponents->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_exponents(exponents); } return exponents; } cgns_integral *cgi_integral_address(int local_mode, int given_no, char const *given_name, int *ier) { cgns_integral *integral=0; int n, allow_dup=0, error1=0, error2=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of IntegralData_t node: * CGNSBase_t, Zone_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4MULTIPLE(cgns_base, nintegrals, integral, cgns_integral) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4MULTIPLE(cgns_zone, nintegrals, integral, cgns_integral) else { cgi_error("IntegralData_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } if (error2) { cgi_error("IntegralData index number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, integral->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_integral(integral); } return integral; } cgns_equations *cgi_equations_address(int local_mode, int *ier) { cgns_equations *equations=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents: CGNSBase_t, Zone_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4SINGLE(cgns_base, equations, cgns_equations, 1) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE(cgns_zone, equations, cgns_equations, 1) else { cgi_error("FlowEquationSet_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("FlowEquationSet_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!equations && local_mode == CG_MODE_READ) { cgi_error("FlowEquationSet_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, equations->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_equations(equations); } return equations; } cgns_state *cgi_state_address(int local_mode, int *ier) { cgns_state *state=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents: CGNSBase_t, Zone_t, ZoneBC_t, BC_t * BCDataSet_t, FamilyBCDataSet_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4SINGLE(cgns_base, state, cgns_state, 1) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE(cgns_zone, state, cgns_state, 1) else if (strcmp(posit->label,"ZoneBC_t")==0) ADDRESS4SINGLE(cgns_zboco, state, cgns_state, 1) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE(cgns_boco, state, cgns_state, 1) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) ADDRESS4SINGLE(cgns_dataset, state, cgns_state, 1) else { cgi_error("ReferenceState_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("ReferenceState_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!state && local_mode == CG_MODE_READ) { cgi_error("ReferenceState_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, state->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_state(state); } return state; } cgns_converg *cgi_converg_address(int local_mode, int *ier) { cgns_converg *converg=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents for xxxConvergenceHistory_t node: CGNSBase_t, Zone_t */ if (strcmp(posit->label,"CGNSBase_t")==0) { ADDRESS4SINGLE(cgns_base, converg, cgns_converg, 1) if (local_mode==CG_MODE_WRITE) strcpy(converg->name,"GlobalConvergenceHistory"); } else if (strcmp(posit->label,"Zone_t")==0) { ADDRESS4SINGLE(cgns_zone, converg, cgns_converg, 1) if (local_mode==CG_MODE_WRITE) strcpy(converg->name,"ZoneConvergenceHistory"); } else { cgi_error("ConvergenceHistory_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("ConvergenceHistory_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!converg && local_mode == CG_MODE_READ) { cgi_error("ConvergenceHistory_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, converg->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_converg(converg); } return converg; } cgns_governing *cgi_governing_address(int local_mode, int *ier) { cgns_governing *governing; int error1=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents for GoverningEquations_t: FlowEquationSet_t */ if (strcmp(posit->label,"FlowEquationSet_t")==0) ADDRESS4SINGLE(cgns_equations, governing, cgns_governing,1) else { cgi_error("GoverningEquations_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("GoverningEquations_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!governing && local_mode == CG_MODE_READ) { cgi_error("ConvergenceHistory_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, governing->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_governing(governing); } return governing; } int *cgi_diffusion_address(int local_mode, int *ier) { int *diffusion_model=0, error1=0, nnod; double parent_id=0, *id; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* possible parents for DiffusionModel: GoverningEquations_t, TurbulenceModel_t */ if (strcmp(posit->label,"GoverningEquations_t")==0) ADDRESS4SINGLE(cgns_governing, diffusion_model, int, 6) else if (strcmp(posit->label,"TurbulenceModel_t")==0) ADDRESS4SINGLE(cgns_model, diffusion_model, int, 6) else { cgi_error("Diffusion Model node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("Diffusion Model already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!diffusion_model && local_mode == CG_MODE_READ) { cgi_error("Diffusion Model Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_get_nodes(parent_id, "\"int[1+...+IndexDimension]\"", &nnod, &id)) return CG_OK; if (nnod>0) { if (cgi_delete_node (parent_id, id[0])) { (*ier) = CG_ERROR; return CG_OK; } CGNS_FREE(id); } CGNS_FREE(diffusion_model); } return diffusion_model; } cgns_array *cgi_array_address(int local_mode, int allow_dup, int given_no, char const *given_name, int* have_dup, int *ier) { cgns_array *array=0, *coord=0; int n, error1=0, error2=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of DataArray_t node: * GridCoordinates_t, Elements_t, FlowSolution_t, DiscreteData_t, GridConnectivity_t, BC_t, * BCData_t, GasModel_t, ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * RigidGridMotion_t, ArbitraryGridMotion_t, BaseIterativeData_t, ZoneIterativeData_t, * UserDefinedData_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t * Area_t, Periodic_t, ZoneSubRegion_t */ /* 0,N DataArray_t under GridCoordinates_t */ if (strcmp(posit->label,"GridCoordinates_t")==0) { ADDRESS4MULTIPLE(cgns_zcoor, ncoords, coord, cgns_array) array = coord; /* 2 DataArray_t under Elements_t: connect and parent */ } else if (strcmp(posit->label,"Elements_t")==0) { cgns_section *section= (cgns_section *)posit->posit; if (local_mode==CG_MODE_WRITE) { if (strcmp(given_name,"ElementConnectivity") && strcmp(given_name,"ParentElements") && strcmp(given_name,"ParentElementsPosition") && strcmp(given_name,"ParentData")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (section->connect==0 && strcmp(given_name,"ElementConnectivity")==0) { section->connect = CGNS_NEW(cgns_array, 1); array = section->connect; } else if (section->parelem==0 && (strcmp(given_name,"ParentElements")==0 || 0 == strcmp(given_name, "ParentData"))) { section->parelem = CGNS_NEW(cgns_array, 1); array = section->parelem; } else if (section->parface==0 && strcmp(given_name,"ParentElementsPosition")==0) { section->parface = CGNS_NEW(cgns_array, 1); array = section->parface; } else { if (cg->mode == CG_MODE_WRITE) error1=1; else { parent_id = section->id; if (section->connect && strcmp(given_name,"ElementConnectivity")==0) array = section->connect; else if (section->parelem && (strcmp(given_name,"ParentElements")==0 || 0 == strcmp(given_name,"ParentData"))) array = section->parelem; else if (section->parface && strcmp(given_name,"ParentElementsPosition")==0) array = section->parface; } } } else if (local_mode == CG_MODE_READ) { if (section->connect && strcmp(given_name,"ElementConnectivity")==0) array = section->connect; else if (section->parelem && (strcmp(given_name,"ParentElements")==0 || 0 == strcmp(given_name,"ParentData"))) array = section->parelem; else if (section->parface && strcmp(given_name,"ParentElementsPosition")==0) array = section->parface; } /* 0,N DataArray_t under FlowSolution_t */ } else if (strcmp(posit->label,"FlowSolution_t")==0) { cgns_array *field; ADDRESS4MULTIPLE(cgns_sol, nfields, field, cgns_array) array = field; /* 0,N DataArray_t under DiscreteData_t */ } else if (strcmp(posit->label,"DiscreteData_t")==0) { ADDRESS4MULTIPLE(cgns_discrete, narrays, array, cgns_array) /* 0,1 DataArray_t under GridConnectivity_t */ } else if (strcmp(posit->label,"GridConnectivity_t")==0) { cgns_array *interpolants; if (local_mode==CG_MODE_WRITE && strcmp(given_name,"InterpolantsDonor")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4SINGLE(cgns_conn, interpolants, cgns_array, 1) array = interpolants; /* 0,1 DataArray_t (in SIDS is IndexArray_t) for InwardNormalList */ } else if (strcmp(posit->label,"BC_t")==0) { cgns_array *normal; ADDRESS4SINGLE(cgns_boco, normal, cgns_array, 1) array = normal; /* 0,N DataArray_t under BCData_t */ } else if (strcmp(posit->label,"BCData_t")==0) { ADDRESS4MULTIPLE(cgns_bcdata, narrays, array, cgns_array) /* 0,N DataArray_t under all Model_t */ } else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) { ADDRESS4MULTIPLE(cgns_model, narrays, array, cgns_array) /* 0,N DataArray_t under ConvergenceHistory_t */ } else if (strcmp(posit->label,"ConvergenceHistory_t")==0) { ADDRESS4MULTIPLE(cgns_converg, narrays, array, cgns_array) /* 0,N DataArray_t under IntegralData_t */ } else if (strcmp(posit->label,"IntegralData_t")==0) { ADDRESS4MULTIPLE(cgns_integral, narrays, array, cgns_array) /* 0,N DataArray_t under ReferenceState_t */ } else if (strcmp(posit->label,"ReferenceState_t")==0) { ADDRESS4MULTIPLE(cgns_state, narrays, array, cgns_array) /* 0,N DataArray_t under RigidGridMotion_t: */ } else if (strcmp(posit->label, "RigidGridMotion_t")==0) { ADDRESS4MULTIPLE(cgns_rmotion, narrays, array, cgns_array) /* 0,N DataArray_t under ArbitraryGridMotion_t: */ } else if (strcmp(posit->label, "ArbitraryGridMotion_t")==0) { ADDRESS4MULTIPLE(cgns_amotion, narrays, array, cgns_array) /* 0,N DataArray_t under BaseIterativeData_t: */ } else if (strcmp(posit->label, "BaseIterativeData_t")==0) { ADDRESS4MULTIPLE(cgns_biter, narrays, array, cgns_array) /* 0,N DataArray_t under ZoneIterativeData_t: */ } else if (strcmp(posit->label, "ZoneIterativeData_t")==0) { ADDRESS4MULTIPLE(cgns_ziter, narrays, array, cgns_array) /* 0,N DataArray_t under UserDefinedData_t: */ } else if (strcmp(posit->label, "UserDefinedData_t")==0) { ADDRESS4MULTIPLE(cgns_user_data, narrays, array, cgns_array) /* 0,1 DataArray_t for GravityVector */ } else if (strcmp(posit->label,"Gravity_t")==0) { cgns_array *vector; if (local_mode==CG_MODE_WRITE && strcmp(given_name,"GravityVector")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4SINGLE(cgns_gravity, vector, cgns_array, 1) array = vector; /* 2,4 DataArray_t for Axisymmetry_t */ } else if (strcmp(posit->label,"Axisymmetry_t")==0) { if (local_mode==CG_MODE_WRITE && strcmp(given_name,"AxisymmetryReferencePoint") && strcmp(given_name,"AxisymmetryAxisVector") && strcmp(given_name,"AxisymmetryAngle") && strcmp(given_name,"CoordinateNames")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4MULTIPLE(cgns_axisym, narrays, array, cgns_array) /* 2 DataArray_t for RotatingCoordinates_t */ } else if (strcmp(posit->label,"RotatingCoordinates_t")==0) { if (local_mode==CG_MODE_WRITE && strcmp(given_name,"RotationCenter") && strcmp(given_name,"RotationRateVector")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4MULTIPLE(cgns_rotating, narrays, array, cgns_array) /* 2 DataArray_t for Area_t: SurfaceArea, RegionName */ } else if (strcmp(posit->label,"Area_t")==0) { if (local_mode==CG_MODE_WRITE && strcmp(given_name,"SurfaceArea") && strcmp(given_name,"RegionName")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4MULTIPLE(cgns_bcarea, narrays, array, cgns_array) /* 3 DataArray_t for Periodic_t: RotationCenter, RotationAngle, Translation */ } else if (strcmp(posit->label,"Periodic_t")==0) { if (local_mode==CG_MODE_WRITE && strcmp(given_name,"RotationCenter") && strcmp(given_name,"RotationAngle") && strcmp(given_name,"Translation")) { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_ERROR; return CG_OK; } ADDRESS4MULTIPLE(cgns_cperio, narrays, array, cgns_array) /* 0,N DataArray_t under ZoneSubRegion_t */ } else if (strcmp(posit->label, "ZoneSubRegion_t")==0) { ADDRESS4MULTIPLE(cgns_subreg, narrays, array, cgns_array) } else { cgi_error("DataArray_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { *have_dup = 1; if (!allow_dup) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } } if (error2) { cgi_error("DataArray_t index number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id && !allow_dup) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, array->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_array(array); } return array; } cgns_model *cgi_model_address(int local_mode, char const *ModelLabel, int *ier) { cgns_model *model=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents for all xxxModel_t and TurbulenceClosure_t: FlowEquationSet_t */ if (strcmp(posit->label,"FlowEquationSet_t")==0) { if (strcmp(ModelLabel, "GasModel_t")==0) { cgns_model *gas; ADDRESS4SINGLE(cgns_equations, gas, cgns_model, 1) model = gas; } else if (strcmp(ModelLabel, "ViscosityModel_t")==0) { cgns_model *visc; ADDRESS4SINGLE(cgns_equations, visc, cgns_model, 1) model = visc; } else if (strcmp(ModelLabel, "ThermalConductivityModel_t")==0) { cgns_model *conduct; ADDRESS4SINGLE(cgns_equations, conduct, cgns_model, 1) model = conduct; } else if (strcmp(ModelLabel, "TurbulenceClosure_t")==0) { cgns_model *closure; ADDRESS4SINGLE(cgns_equations, closure, cgns_model, 1) model = closure; } else if (strcmp(ModelLabel, "TurbulenceModel_t")==0) { cgns_model *turbulence; ADDRESS4SINGLE(cgns_equations, turbulence, cgns_model, 1) model = turbulence; } else if (strcmp(ModelLabel, "ThermalRelaxationModel_t")==0) { cgns_model *relaxation; ADDRESS4SINGLE(cgns_equations, relaxation, cgns_model, 1) model = relaxation; } else if (strcmp(ModelLabel, "ChemicalKineticsModel_t")==0) { cgns_model *chemkin; ADDRESS4SINGLE(cgns_equations, chemkin, cgns_model, 1) model = chemkin; } else if (strcmp(ModelLabel, "EMElectricFieldModel_t")==0) { cgns_model *elecfield; ADDRESS4SINGLE(cgns_equations, elecfield, cgns_model, 1) model = elecfield; } else if (strcmp(ModelLabel, "EMMagneticFieldModel_t")==0) { cgns_model *magnfield; ADDRESS4SINGLE(cgns_equations, magnfield, cgns_model, 1) model = magnfield; } else if (strcmp(ModelLabel, "EMConductivityModel_t")==0) { cgns_model *emconduct; ADDRESS4SINGLE(cgns_equations, emconduct, cgns_model, 1) model = emconduct; } else { cgi_error("Incorrect model type %s",ModelLabel); (*ier) = CG_ERROR; return CG_OK; } } else { cgi_error("%s node not supported under '%s' type node",ModelLabel,posit->label); (*ier)=CG_INCORRECT_PATH; return CG_OK; } if (!model && local_mode == CG_MODE_READ) { cgi_error("%s node doesn't exist under %s",ModelLabel,posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (error1) { cgi_error("%s node already defined under %s",ModelLabel,posit->label); (*ier) = CG_ERROR; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, model->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_model(model); } return model; } cgns_user_data *cgi_user_data_address(int local_mode, int given_no, char const *given_name, int *ier) { cgns_user_data *user_data=0; int n, allow_dup=0, error1=0, error2=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of UserDefinedData_t node: * IntegralData_t, DiscreteData_t, ConvergenceHistory_t, ReferenceState_t, * xxxModel_t, GoverningEquations_t, FlowEquationSet_t, BCData_t, BCDataSet_t, * Elements_t, BC_t, ZoneBC_t, OversetHoles_t, GridConnectivity_t, * GridConnectivity1to1_t, ZoneGridConnectivity_t, FlowSolution_t, * GridCoordinates_t, RigidGridMotion_t, ArbitraryGridMotion_t, * ZoneIterativeData_t, BaseIterativeData_t, Zone_t, GeometryReference_t, * Family_t, CGNSBase_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t * BCProperty_t, WallFunction_t, Area_t, * GridConnectivityProperty_t, Periodic_t, AverageInterface_t, * UserDefinedData_t, ZoneSubRegion_t, FamilyBCDataSet_t */ if (strcmp(posit->label,"IntegralData_t")==0) ADDRESS4MULTIPLE(cgns_integral, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4MULTIPLE(cgns_discrete, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ConvergenceHistory_t")==0) ADDRESS4MULTIPLE(cgns_converg, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ReferenceState_t")==0) ADDRESS4MULTIPLE(cgns_state, nuser_data, user_data, cgns_user_data) else if ( (strcmp(posit->label,"GasModel_t")==0) || (strcmp(posit->label,"ViscosityModel_t")==0) || (strcmp(posit->label,"ThermalConductivityModel_t")==0) || (strcmp(posit->label,"TurbulenceModel_t")==0) || (strcmp(posit->label,"TurbulenceClosureModel_t")==0) || (strcmp(posit->label,"ThermalRelaxationModel_t")==0) || (strcmp(posit->label,"ChemicalKineticsModel_t")==0) || (strcmp(posit->label,"EMElectricFieldModel_t")==0) || (strcmp(posit->label,"EMMagneticFieldModel_t")==0) || (strcmp(posit->label,"EMConductivityModel_t")==0) ) ADDRESS4MULTIPLE(cgns_model, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GoverningEquations_t")==0) ADDRESS4MULTIPLE(cgns_governing, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"FlowEquationSet_t")==0) ADDRESS4MULTIPLE(cgns_equations, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"BCData_t")==0) ADDRESS4MULTIPLE(cgns_bcdata, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) ADDRESS4MULTIPLE(cgns_dataset, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Elements_t")==0) ADDRESS4MULTIPLE(cgns_section, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4MULTIPLE(cgns_boco, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ZoneBC_t")==0) ADDRESS4MULTIPLE(cgns_zboco, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"OversetHoles_t")==0) ADDRESS4MULTIPLE(cgns_hole, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GridConnectivity_t")==0) ADDRESS4MULTIPLE(cgns_conn, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) ADDRESS4MULTIPLE(cgns_1to1, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ZoneGridConnectivity_t")==0) ADDRESS4MULTIPLE(cgns_zconn, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4MULTIPLE(cgns_sol, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GridCoordinates_t")==0) ADDRESS4MULTIPLE(cgns_zcoor, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"RigidGridMotion_t")==0) ADDRESS4MULTIPLE(cgns_rmotion, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) ADDRESS4MULTIPLE(cgns_amotion, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ZoneIterativeData_t")==0) ADDRESS4MULTIPLE(cgns_ziter, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"BaseIterativeData_t")==0) ADDRESS4MULTIPLE(cgns_biter, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4MULTIPLE(cgns_zone, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GeometryReference_t")==0) ADDRESS4MULTIPLE(cgns_geo, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Family_t")==0) ADDRESS4MULTIPLE(cgns_family, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4MULTIPLE(cgns_base, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Gravity_t")==0) ADDRESS4MULTIPLE(cgns_gravity, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Axisymmetry_t")==0) ADDRESS4MULTIPLE(cgns_axisym, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"RotatingCoordinates_t")==0) ADDRESS4MULTIPLE(cgns_rotating, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"BCProperty_t")==0) ADDRESS4MULTIPLE(cgns_bprop, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"WallFunction_t")==0) ADDRESS4MULTIPLE(cgns_bcwall, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Area_t")==0) ADDRESS4MULTIPLE(cgns_bcarea, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"GridConnectivityProperty_t")==0) ADDRESS4MULTIPLE(cgns_cprop, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"Periodic_t")==0) ADDRESS4MULTIPLE(cgns_cperio, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"AverageInterface_t")==0) ADDRESS4MULTIPLE(cgns_caverage, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4MULTIPLE(cgns_user_data, nuser_data, user_data, cgns_user_data) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4MULTIPLE(cgns_subreg, nuser_data, user_data, cgns_user_data) else { cgi_error("UserDefinedData_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } if (error2) { cgi_error("UserDefinedData index number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, user_data->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_user_data(user_data); } return user_data; } cgns_rotating *cgi_rotating_address(int local_mode, int *ier) { cgns_rotating *rotating=0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents: CGNSBase_t, Zone_t, Family_t */ if (strcmp(posit->label,"CGNSBase_t")==0) ADDRESS4SINGLE(cgns_base, rotating, cgns_rotating, 1) else if (strcmp(posit->label,"Zone_t")==0) ADDRESS4SINGLE(cgns_zone, rotating, cgns_rotating, 1) else if (strcmp(posit->label,"Family_t")==0) ADDRESS4SINGLE(cgns_family, rotating, cgns_rotating, 1) else { cgi_error("RotatingCoordinates_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("RotatingCoordinates_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!rotating && local_mode == CG_MODE_READ) { cgi_error("RotatingCoordinates_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, rotating->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_rotating(rotating); } return rotating; } cgns_dataset *cgi_bcdataset_address(int local_mode, int given_no, char const *given_name, int *ier) { cgns_dataset *dataset=0; int n, allow_dup=0, error1=0, error2=0; double parent_id=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of FamilyBCDataSet_t node: * FamilyBC_t */ if (strcmp(posit->label,"FamilyBC_t")==0) ADDRESS4MULTIPLE(cgns_fambc, ndataset, dataset, cgns_dataset) else { cgi_error("FamilyBCDataSet_t node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1) { cgi_error("Duplicate child name found (%s) found under %s", given_name, posit->label); (*ier) = CG_ERROR; return CG_OK; } if (error2) { cgi_error("BCDataSet index number %d doesn't exist under %s", given_no, posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { /* parent_id!=0 only when overwriting */ if (cgi_delete_node (parent_id, dataset->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_dataset(dataset); } return dataset; } cgns_ptset *cgi_ptset_address(int local_mode, int *ier) { cgns_ptset *ptset = 0; double parent_id=0; int error1=0; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ier) = CG_ERROR; return CG_OK; } /* Possible parents of a PointSet (i.e., either an IndexArray_t or * IndexRange_t) node: * UserDefinedData_t, BCDataSet_t, BC_t, OversetHoles_t, GridConnectivity_t * GridConnectivity1to1_t */ if (strcmp(posit->label,"UserDefinedData_t")==0) ADDRESS4SINGLE(cgns_user_data, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"BCDataSet_t")==0) ADDRESS4SINGLE(cgns_dataset, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"BC_t")==0) ADDRESS4SINGLE(cgns_boco, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"OversetHoles_t")==0) ADDRESS4SINGLE(cgns_hole, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"GridConnectivity_t")==0) ADDRESS4SINGLE_ALLOC(cgns_conn, ptset) else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) ADDRESS4SINGLE_ALLOC(cgns_1to1, ptset) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) ADDRESS4SINGLE(cgns_subreg, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"FlowSolution_t")==0) ADDRESS4SINGLE(cgns_sol, ptset, cgns_ptset, 1) else if (strcmp(posit->label,"DiscreteData_t")==0) ADDRESS4SINGLE(cgns_discrete, ptset, cgns_ptset, 1) else { cgi_error("PointSet node not supported under '%s' type node",posit->label); (*ier) = CG_INCORRECT_PATH; return CG_OK; } if (error1==1) { cgi_error("IndexArray/Range_t already defined under %s",posit->label); (*ier) = CG_ERROR; return CG_OK; } if (!ptset && local_mode == CG_MODE_READ) { cgi_error("IndexArray/Range_t Node doesn't exist under %s",posit->label); (*ier) = CG_NODE_NOT_FOUND; return CG_OK; } if (parent_id) { if (cgi_delete_node (parent_id, ptset->id)) { (*ier) = CG_ERROR; return CG_OK; } cgi_free_ptset(ptset); } return ptset; } /***********************************************************************\ * Free memory * \***********************************************************************/ void cgi_free_file(cgns_file *cg) { int b; CGNS_FREE(cg->filename); if (cg->nbases) { for (b=0; bnbases; b++) cgi_free_base(&cg->base[b]); CGNS_FREE(cg->base); } } void cgi_free_base(cgns_base *base) { int n; if (base->nzones) { for (n=0; nnzones; n++) cgi_free_zone(&base->zone[n]); CGNS_FREE(base->zone); } if (base->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&base->descr[n]); CGNS_FREE(base->descr); } if (base->state) { cgi_free_state(base->state); CGNS_FREE(base->state); } if (base->units) { cgi_free_units(base->units); CGNS_FREE(base->units); } if (base->equations) { cgi_free_equations(base->equations); CGNS_FREE(base->equations); } if (base->converg) { cgi_free_converg(base->converg); CGNS_FREE(base->converg); } if (base->nintegrals) { for (n=0; nnintegrals; n++) cgi_free_integral(&base->integral[n]); CGNS_FREE(base->integral); } if (base->nfamilies) { for (n=0; nnfamilies; n++) cgi_free_family(&base->family[n]); CGNS_FREE(base->family); } if (base->biter) { cgi_free_biter(base->biter); CGNS_FREE(base->biter); } if (base->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&base->user_data[n]); CGNS_FREE(base->user_data); } if (base->gravity) { cgi_free_gravity(base->gravity); CGNS_FREE(base->gravity); } if (base->axisym) { cgi_free_axisym(base->axisym); CGNS_FREE(base->axisym); } if (base->rotating) { cgi_free_rotating(base->rotating); CGNS_FREE(base->rotating); } } void cgi_free_zone(cgns_zone *zone) { int n; if (zone->link) CGNS_FREE(zone->link); CGNS_FREE(zone->nijk); if (zone->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&zone->descr[n]); CGNS_FREE(zone->descr); } if (zone->nzcoor) { for (n=0; nnzcoor; n++) cgi_free_zcoor(&zone->zcoor[n]); CGNS_FREE(zone->zcoor); } if (zone->nsections) { for (n=0; nnsections; n++) cgi_free_section(&zone->section[n]); CGNS_FREE(zone->section); } if (zone->nsols) { for (n=0; nnsols; n++) cgi_free_sol(&zone->sol[n]); CGNS_FREE(zone->sol); } if (zone->ndiscrete) { for (n=0; nndiscrete; n++) cgi_free_discrete(&zone->discrete[n]); CGNS_FREE(zone->discrete); } if (zone->nintegrals) { for (n=0; nnintegrals; n++) cgi_free_integral(&zone->integral[n]); CGNS_FREE(zone->integral); } if (zone->nzconn) { for (n=0; nnzconn; n++) cgi_free_zconn(&zone->zconn[n]); CGNS_FREE(zone->zconn); } if (zone->zboco) { cgi_free_zboco(zone->zboco); CGNS_FREE(zone->zboco); } if (zone->state) { cgi_free_state(zone->state); CGNS_FREE(zone->state); } if (zone->units) { cgi_free_units(zone->units); CGNS_FREE(zone->units); } if (zone->equations) { cgi_free_equations(zone->equations); CGNS_FREE(zone->equations); } if (zone->converg) { cgi_free_converg(zone->converg); CGNS_FREE(zone->converg); } if (zone->nrmotions) { for (n=0; nnrmotions; n++) cgi_free_rmotion(&zone->rmotion[n]); CGNS_FREE(zone->rmotion); } if (zone->namotions) { for (n=0; nnamotions; n++) cgi_free_amotion(&zone->amotion[n]); CGNS_FREE(zone->amotion); } if (zone->ziter) { cgi_free_ziter(zone->ziter); CGNS_FREE(zone->ziter); } if (zone->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&zone->user_data[n]); CGNS_FREE(zone->user_data); } if (zone->rotating) { cgi_free_rotating(zone->rotating); CGNS_FREE(zone->rotating); } if (zone->nsubreg) { for (n=0; nnsubreg; n++) cgi_free_subreg(&zone->subreg[n]); CGNS_FREE(zone->subreg); } if (zone->nfamname) { for (n = 0; n < zone->nfamname; n++) cgi_free_famname(&zone->famname[n]); CGNS_FREE(zone->famname); } } void cgi_free_section(cgns_section *section) { int n; if (section->link) CGNS_FREE(section->link); if (section->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(§ion->descr[n]); CGNS_FREE(section->descr); } if (section->rind_planes) CGNS_FREE(section->rind_planes); if (section->connect) { cgi_free_array(section->connect); CGNS_FREE(section->connect); } if (section->connect_offset) { cgi_free_array(section->connect_offset); CGNS_FREE(section->connect_offset); } if (section->parelem) { cgi_free_array(section->parelem); CGNS_FREE(section->parelem); } if (section->parface) { cgi_free_array(section->parface); CGNS_FREE(section->parface); } if (section->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(§ion->user_data[n]); CGNS_FREE(section->user_data); } } void cgi_free_family(cgns_family *family) { int n; if (family->link) CGNS_FREE(family->link); if (family->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&family->descr[n]); CGNS_FREE(family->descr); } if (family->nfambc) { for (n=0; nnfambc; n++) cgi_free_fambc(&family->fambc[n]); CGNS_FREE(family->fambc); } if (family->ngeos) { for (n=0; nngeos; n++) cgi_free_geo(&family->geo[n]); CGNS_FREE(family->geo); } if (family->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&family->user_data[n]); CGNS_FREE(family->user_data); } if (family->rotating) { cgi_free_rotating(family->rotating); CGNS_FREE(family->rotating); } if (family->nfamname) { for (n = 0; n < family->nfamname; n++) cgi_free_famname(&family->famname[n]); CGNS_FREE(family->famname); } } void cgi_free_fambc(cgns_fambc *fambc) { if (fambc->link) CGNS_FREE(fambc->link); if (fambc->ndataset) { int n; for (n=0; nndataset; n++) cgi_free_dataset(&fambc->dataset[n]); CGNS_FREE(fambc->dataset); } } /* currently here only to support delete */ void cgi_free_famname(cgns_famname *famname) { famname->name[0] = 0; famname->family[0] = 0; } void cgi_free_geo(cgns_geo *geo) { int n; if (geo->link) CGNS_FREE(geo->link); if (geo->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&geo->descr[n]); CGNS_FREE(geo->descr); } if (geo->file) CGNS_FREE(geo->file); if (geo->npart) { for (n=0; nnpart; n++) cgi_free_part(&geo->part[n]); CGNS_FREE(geo->part); } if (geo->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&geo->user_data[n]); CGNS_FREE(geo->user_data); } } void cgi_free_part(cgns_part *part) { if (part->link) CGNS_FREE(part->link); } void cgi_free_zcoor(cgns_zcoor *zcoor) { int n; if (zcoor->link) CGNS_FREE(zcoor->link); if (zcoor->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&zcoor->descr[n]); CGNS_FREE(zcoor->descr); } if (zcoor->rind_planes) CGNS_FREE(zcoor->rind_planes); if (zcoor->ncoords) { for (n=0; nncoords; n++) cgi_free_array(&zcoor->coord[n]); CGNS_FREE(zcoor->coord); } if (zcoor->units) { cgi_free_units(zcoor->units); CGNS_FREE(zcoor->units); } if (zcoor->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&zcoor->user_data[n]); CGNS_FREE(zcoor->user_data); } } void cgi_free_zboco(cgns_zboco *zboco) { int n; if (zboco->link) CGNS_FREE(zboco->link); if (zboco->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&zboco->descr[n]); CGNS_FREE(zboco->descr); } if (zboco->nbocos) { for (n=0; nnbocos; n++) cgi_free_boco(&zboco->boco[n]); CGNS_FREE(zboco->boco); } if (zboco->state) { cgi_free_state(zboco->state); CGNS_FREE(zboco->state); } if (zboco->units) { cgi_free_units(zboco->units); CGNS_FREE(zboco->units); } if (zboco->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&zboco->user_data[n]); CGNS_FREE(zboco->user_data); } } void cgi_free_zconn(cgns_zconn *zconn) { int n; if (zconn->link) CGNS_FREE(zconn->link); if (zconn->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&zconn->descr[n]); CGNS_FREE(zconn->descr); } if (zconn->n1to1) { for (n=0; nn1to1; n++) cgi_free_1to1(&zconn->one21[n]); CGNS_FREE(zconn->one21); } if (zconn->nconns) { for (n=0; nnconns; n++) cgi_free_conn(&zconn->conn[n]); CGNS_FREE(zconn->conn); } if (zconn->nholes) { for (n=0; nnholes; n++) cgi_free_hole(&zconn->hole[n]); CGNS_FREE(zconn->hole); } if (zconn->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&zconn->user_data[n]); CGNS_FREE(zconn->user_data); } } void cgi_free_sol(cgns_sol *sol) { int n; if (sol->link) CGNS_FREE(sol->link); if (sol->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&sol->descr[n]); CGNS_FREE(sol->descr); } if (sol->nfields) { for (n=0; nnfields; n++) cgi_free_array(&sol->field[n]); CGNS_FREE(sol->field); } if (sol->rind_planes) CGNS_FREE(sol->rind_planes); if (sol->units) { cgi_free_units(sol->units); CGNS_FREE(sol->units); } if (sol->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&sol->user_data[n]); CGNS_FREE(sol->user_data); } if (sol->ptset) { cgi_free_ptset(sol->ptset); CGNS_FREE(sol->ptset); } } void cgi_free_1to1(cgns_1to1 *one21) { int n; if (one21->link) CGNS_FREE(one21->link); CGNS_FREE(one21->transform); if (one21->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&one21->descr[n]); CGNS_FREE(one21->descr); } if (one21->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&one21->user_data[n]); CGNS_FREE(one21->user_data); } if (one21->cprop) { cgi_free_cprop(one21->cprop); CGNS_FREE(one21->cprop); } } void cgi_free_hole(cgns_hole *hole) { int n; if (hole->link) CGNS_FREE(hole->link); if (hole->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&hole->descr[n]); CGNS_FREE(hole->descr); } if (hole->nptsets) { for (n=0; nnptsets; n++) cgi_free_ptset(&hole->ptset[n]); CGNS_FREE(hole->ptset); } if (hole->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&hole->user_data[n]); CGNS_FREE(hole->user_data); } } void cgi_free_conn(cgns_conn *conn) { int n; if (conn->link) CGNS_FREE(conn->link); if (conn->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&conn->descr[n]); CGNS_FREE(conn->descr); } if (conn->interpolants) { cgi_free_array(conn->interpolants); CGNS_FREE(conn->interpolants); } if (conn->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&conn->user_data[n]); CGNS_FREE(conn->user_data); } if (conn->cprop) { cgi_free_cprop(conn->cprop); CGNS_FREE(conn->cprop); } } void cgi_free_boco(cgns_boco *boco) { int n; if (boco->link) CGNS_FREE(boco->link); if (boco->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&boco->descr[n]); CGNS_FREE(boco->descr); } if (boco->ptset) { cgi_free_ptset(boco->ptset); CGNS_FREE(boco->ptset); } if (boco->Nindex) CGNS_FREE(boco->Nindex); if (boco->normal) { cgi_free_array(boco->normal); CGNS_FREE(boco->normal); } if (boco->ndataset) { for (n=0; nndataset; n++) { /* If dataset[n].ptset came from boco->ptset, don't want to * attempt to free it. This is stuff Ken put in here. I don't * think this every happens - but just in case */ if(boco->dataset[n].ptset == boco->ptset) boco->dataset[n].ptset = 0; cgi_free_dataset(&boco->dataset[n]); } CGNS_FREE(boco->dataset); } if (boco->state) { cgi_free_state(boco->state); CGNS_FREE(boco->state); } if (boco->units) { cgi_free_units(boco->units); CGNS_FREE(boco->units); } if (boco->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&boco->user_data[n]); CGNS_FREE(boco->user_data); } if (boco->bprop) { cgi_free_bprop(boco->bprop); CGNS_FREE(boco->bprop); } if (boco->nfamname) { for (n = 0; n < boco->nfamname; n++) cgi_free_famname(&boco->famname[n]); CGNS_FREE(boco->famname); } } void cgi_free_dataset(cgns_dataset *dataset) { int n; if (dataset->link) CGNS_FREE(dataset->link); if (dataset->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&dataset->descr[n]); CGNS_FREE(dataset->descr); } if (dataset->dirichlet) { cgi_free_bcdata(dataset->dirichlet); CGNS_FREE(dataset->dirichlet); } if (dataset->neumann) { cgi_free_bcdata(dataset->neumann); CGNS_FREE(dataset->neumann); } if (dataset->state) { cgi_free_state(dataset->state); CGNS_FREE(dataset->state); } if (dataset->units) { cgi_free_units(dataset->units); CGNS_FREE(dataset->units); } if (dataset->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&dataset->user_data[n]); CGNS_FREE(dataset->user_data); } if (dataset->ptset) { cgi_free_ptset(dataset->ptset); CGNS_FREE(dataset->ptset); } } void cgi_free_bcdata(cgns_bcdata *bcdata) { int n; if (bcdata->link) CGNS_FREE(bcdata->link); if (bcdata->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&bcdata->descr[n]); CGNS_FREE(bcdata->descr); } if (bcdata->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&bcdata->array[n]); CGNS_FREE(bcdata->array); } if (bcdata->units) { cgi_free_units(bcdata->units); CGNS_FREE(bcdata->units); } if (bcdata->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&bcdata->user_data[n]); CGNS_FREE(bcdata->user_data); } } void cgi_free_ptset(cgns_ptset *ptset) { if (ptset->link) CGNS_FREE(ptset->link); if (ptset->data) CGNS_FREE(ptset->data); } void cgi_free_equations(cgns_equations *equations) { int n; if (equations->link) CGNS_FREE(equations->link); if (equations->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&equations->descr[n]); CGNS_FREE(equations->descr); } if (equations->governing) { cgi_free_governing(equations->governing); CGNS_FREE(equations->governing); } if (equations->gas) { cgi_free_model(equations->gas); CGNS_FREE(equations->gas); } if (equations->visc) { cgi_free_model(equations->visc); CGNS_FREE(equations->visc); } if (equations->conduct) { cgi_free_model(equations->conduct); CGNS_FREE(equations->conduct); } if (equations->closure) { cgi_free_model(equations->closure); CGNS_FREE(equations->closure); } if (equations->turbulence) { if (equations->turbulence->diffusion_model) CGNS_FREE(equations->turbulence->diffusion_model); cgi_free_model(equations->turbulence); CGNS_FREE(equations->turbulence); } if (equations->relaxation) { cgi_free_model(equations->relaxation); CGNS_FREE(equations->relaxation); } if (equations->chemkin) { cgi_free_model(equations->chemkin); CGNS_FREE(equations->chemkin); } if (equations->units) { cgi_free_units(equations->units); CGNS_FREE(equations->units); } if (equations->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&equations->user_data[n]); CGNS_FREE(equations->user_data); } if (equations->elecfield) { cgi_free_model(equations->elecfield); CGNS_FREE(equations->elecfield); } if (equations->magnfield) { cgi_free_model(equations->magnfield); CGNS_FREE(equations->magnfield); } if (equations->emconduct) { cgi_free_model(equations->emconduct); CGNS_FREE(equations->emconduct); } } void cgi_free_governing(cgns_governing *governing) { int n; if (governing->link) CGNS_FREE(governing->link); if (governing->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&governing->descr[n]); CGNS_FREE(governing->descr); } if (governing->diffusion_model) CGNS_FREE(governing->diffusion_model); if (governing->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&governing->user_data[n]); CGNS_FREE(governing->user_data); } } void cgi_free_model(cgns_model *model) { int n; if (model->link) CGNS_FREE(model->link); if (model->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&model->descr[n]); CGNS_FREE(model->descr); } if (model->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&model->array[n]); CGNS_FREE(model->array); } if (model->units) { cgi_free_units(model->units); CGNS_FREE(model->units); } if (model->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&model->user_data[n]); CGNS_FREE(model->user_data); } } void cgi_free_state(cgns_state *state) { int n; if (state->link) CGNS_FREE(state->link); if (state->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&state->descr[n]); CGNS_FREE(state->descr); } if (state->StateDescription) { cgi_free_descr(state->StateDescription); CGNS_FREE(state->StateDescription); } if (state->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&state->array[n]); CGNS_FREE(state->array); } if (state->units) { cgi_free_units(state->units); CGNS_FREE(state->units); } if (state->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&state->user_data[n]); CGNS_FREE(state->user_data); } } void cgi_free_converg(cgns_converg *converg) { int n; if (converg->link) CGNS_FREE(converg->link); if (converg->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&converg->descr[n]); CGNS_FREE(converg->descr); } if (converg->NormDefinitions) { cgi_free_descr(converg->NormDefinitions); CGNS_FREE(converg->NormDefinitions); } if (converg->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&converg->array[n]); CGNS_FREE(converg->array); } if (converg->units) { cgi_free_units(converg->units); CGNS_FREE(converg->units); } if (converg->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&converg->user_data[n]); CGNS_FREE(converg->user_data); } } void cgi_free_discrete(cgns_discrete *discrete) { int n; if (discrete->link) CGNS_FREE(discrete->link); if (discrete->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&discrete->descr[n]); CGNS_FREE(discrete->descr); } if (discrete->rind_planes) CGNS_FREE(discrete->rind_planes); if (discrete->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&discrete->array[n]); CGNS_FREE(discrete->array); } if (discrete->units) { cgi_free_units(discrete->units); CGNS_FREE(discrete->units); } if (discrete->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&discrete->user_data[n]); CGNS_FREE(discrete->user_data); } if (discrete->ptset) { cgi_free_ptset(discrete->ptset); CGNS_FREE(discrete->ptset); } } void cgi_free_integral(cgns_integral *integral) { int n; if (integral->link) CGNS_FREE(integral->link); if (integral->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&integral->descr[n]); CGNS_FREE(integral->descr); } if (integral->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&integral->array[n]); CGNS_FREE(integral->array); } if (integral->units) { cgi_free_units(integral->units); CGNS_FREE(integral->units); } if (integral->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&integral->user_data[n]); CGNS_FREE(integral->user_data); } } void cgi_free_array(cgns_array *array) { int n; if (array->link) CGNS_FREE(array->link); if (array->data) CGNS_FREE(array->data); if (array->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&array->descr[n]); CGNS_FREE(array->descr); } if (array->units) { cgi_free_units(array->units); CGNS_FREE(array->units); } if (array->exponents) { cgi_free_exponents(array->exponents); CGNS_FREE(array->exponents); } if (array->convert) { cgi_free_convert(array->convert); CGNS_FREE(array->convert); } } void cgi_free_convert(cgns_conversion *convert) { if (convert->link) CGNS_FREE(convert->link); CGNS_FREE(convert->data); } void cgi_free_exponents(cgns_exponent *exponents) { if (exponents->link) CGNS_FREE(exponents->link); CGNS_FREE(exponents->data); } void cgi_free_units(cgns_units *units) { if (units->link) CGNS_FREE(units->link); } void cgi_free_descr(cgns_descr *descr) { if (descr->link) CGNS_FREE(descr->link); if (descr->text) CGNS_FREE(descr->text); } void cgi_free_rmotion(cgns_rmotion *rmotion) { int n; if (rmotion->link) CGNS_FREE(rmotion->link); if (rmotion->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&rmotion->descr[n]); CGNS_FREE(rmotion->descr); } if (rmotion->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&rmotion->array[n]); CGNS_FREE(rmotion->array); } if (rmotion->units) { cgi_free_units(rmotion->units); CGNS_FREE(rmotion->units); } if (rmotion->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&rmotion->user_data[n]); CGNS_FREE(rmotion->user_data); } } void cgi_free_amotion(cgns_amotion *amotion) { int n; if (amotion->link) CGNS_FREE(amotion->link); if (amotion->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&amotion->descr[n]); CGNS_FREE(amotion->descr); } if (amotion->rind_planes) CGNS_FREE(amotion->rind_planes); if (amotion->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&amotion->array[n]); CGNS_FREE(amotion->array); } if (amotion->units) { cgi_free_units(amotion->units); CGNS_FREE(amotion->units); } if (amotion->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&amotion->user_data[n]); CGNS_FREE(amotion->user_data); } } void cgi_free_biter(cgns_biter *biter) { int n; if (biter->link) CGNS_FREE(biter->link); if (biter->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&biter->descr[n]); CGNS_FREE(biter->descr); } if (biter->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&biter->array[n]); CGNS_FREE(biter->array); } if (biter->units) { cgi_free_units(biter->units); CGNS_FREE(biter->units); } if (biter->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&biter->user_data[n]); CGNS_FREE(biter->user_data); } } void cgi_free_ziter(cgns_ziter *ziter) { int n; if (ziter->link) CGNS_FREE(ziter->link); if (ziter->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&ziter->descr[n]); CGNS_FREE(ziter->descr); } if (ziter->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&ziter->array[n]); CGNS_FREE(ziter->array); } if (ziter->units) { cgi_free_units(ziter->units); CGNS_FREE(ziter->units); } if (ziter->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&ziter->user_data[n]); CGNS_FREE(ziter->user_data); } } void cgi_free_gravity(cgns_gravity *gravity) { int n; if (gravity->link) CGNS_FREE(gravity->link); if (gravity->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&gravity->descr[n]); CGNS_FREE(gravity->descr); } if (gravity->vector) { cgi_free_array(gravity->vector); CGNS_FREE(gravity->vector); } if (gravity->units) { cgi_free_units(gravity->units); CGNS_FREE(gravity->units); } if (gravity->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&gravity->user_data[n]); CGNS_FREE(gravity->user_data); } } void cgi_free_axisym(cgns_axisym *axisym) { int n; if (axisym->link) CGNS_FREE(axisym->link); if (axisym->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&axisym->descr[n]); CGNS_FREE(axisym->descr); } if (axisym->units) { cgi_free_units(axisym->units); CGNS_FREE(axisym->units); } if (axisym->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&axisym->array[n]); CGNS_FREE(axisym->array); } if (axisym->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&axisym->user_data[n]); CGNS_FREE(axisym->user_data); } } void cgi_free_rotating(cgns_rotating *rotating) { int n; if (rotating->link) CGNS_FREE(rotating->link); if (rotating->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&rotating->descr[n]); CGNS_FREE(rotating->descr); } if (rotating->units) { cgi_free_units(rotating->units); CGNS_FREE(rotating->units); } if (rotating->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&rotating->array[n]); CGNS_FREE(rotating->array); } if (rotating->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&rotating->user_data[n]); CGNS_FREE(rotating->user_data); } } void cgi_free_bprop(cgns_bprop *bprop) { int n; if (bprop->link) CGNS_FREE(bprop->link); if (bprop->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&bprop->descr[n]); CGNS_FREE(bprop->descr); } if (bprop->bcwall) { cgi_free_bcwall(bprop->bcwall); CGNS_FREE(bprop->bcwall); } if (bprop->bcarea) { cgi_free_bcarea(bprop->bcarea); CGNS_FREE(bprop->bcarea); } if (bprop->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&bprop->user_data[n]); CGNS_FREE(bprop->user_data); } } void cgi_free_cprop(cgns_cprop *cprop) { int n; if (cprop->link) CGNS_FREE(cprop->link); if (cprop->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&cprop->descr[n]); CGNS_FREE(cprop->descr); } if (cprop->cperio) { cgi_free_cperio(cprop->cperio); CGNS_FREE(cprop->cperio); } if (cprop->caverage) { cgi_free_caverage(cprop->caverage); CGNS_FREE(cprop->caverage); } if (cprop->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&cprop->user_data[n]); CGNS_FREE(cprop->user_data); } } void cgi_free_bcwall(cgns_bcwall *bcwall) { int n; if (bcwall->link) CGNS_FREE(bcwall->link); if (bcwall->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&bcwall->descr[n]); CGNS_FREE(bcwall->descr); } if (bcwall->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&bcwall->user_data[n]); CGNS_FREE(bcwall->user_data); } } void cgi_free_bcarea(cgns_bcarea *bcarea) { int n; if (bcarea->link) CGNS_FREE(bcarea->link); if (bcarea->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&bcarea->descr[n]); CGNS_FREE(bcarea->descr); } if (bcarea->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&bcarea->array[n]); CGNS_FREE(bcarea->array); } if (bcarea->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&bcarea->user_data[n]); CGNS_FREE(bcarea->user_data); } } void cgi_free_cperio(cgns_cperio *cperio) { int n; if (cperio->link) CGNS_FREE(cperio->link); if (cperio->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&cperio->descr[n]); CGNS_FREE(cperio->descr); } if (cperio->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&cperio->array[n]); CGNS_FREE(cperio->array); } if (cperio->units) { cgi_free_units(cperio->units); CGNS_FREE(cperio->units); } if (cperio->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&cperio->user_data[n]); CGNS_FREE(cperio->user_data); } } void cgi_free_caverage(cgns_caverage *caverage) { int n; if (caverage->link) CGNS_FREE(caverage->link); if (caverage->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&caverage->descr[n]); CGNS_FREE(caverage->descr); } if (caverage->nuser_data) { for (n=0; nnuser_data; n++) cgi_free_user_data(&caverage->user_data[n]); CGNS_FREE(caverage->user_data); } } void cgi_free_user_data(cgns_user_data *user_data) { int n; if (user_data->link) CGNS_FREE(user_data->link); if (user_data->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&user_data->descr[n]); CGNS_FREE(user_data->descr); } if (user_data->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&user_data->array[n]); CGNS_FREE(user_data->array); } if (user_data->ptset) { cgi_free_ptset(user_data->ptset); CGNS_FREE(user_data->ptset); } if (user_data->units) { cgi_free_units(user_data->units); CGNS_FREE(user_data->units); } if (user_data->nuser_data) { for (n=0; n < user_data->nuser_data; n++) cgi_free_user_data(&user_data->user_data[n]); CGNS_FREE(user_data->user_data); } if (user_data->nfamname) { for (n = 0; n < user_data->nfamname; n++) cgi_free_famname(&user_data->famname[n]); CGNS_FREE(user_data->famname); } } void cgi_free_subreg(cgns_subreg *subreg) { int n; if (subreg->link) CGNS_FREE(subreg->link); if (subreg->ndescr) { for (n=0; nndescr; n++) cgi_free_descr(&subreg->descr[n]); CGNS_FREE(subreg->descr); } if (subreg->narrays) { for (n=0; nnarrays; n++) cgi_free_array(&subreg->array[n]); CGNS_FREE(subreg->array); } if (subreg->ptset) { cgi_free_ptset(subreg->ptset); CGNS_FREE(subreg->ptset); } if (subreg->bcname) cgi_free_descr(subreg->bcname); if (subreg->gcname) cgi_free_descr(subreg->gcname); if (subreg->units) { cgi_free_units(subreg->units); CGNS_FREE(subreg->units); } if (subreg->rind_planes) CGNS_FREE(subreg->rind_planes); if (subreg->nuser_data) { for (n=0; n < subreg->nuser_data; n++) cgi_free_user_data(&subreg->user_data[n]); CGNS_FREE(subreg->user_data); } if (subreg->nfamname) { for (n = 0; n < subreg->nfamname; n++) cgi_free_famname(&subreg->famname[n]); CGNS_FREE(subreg->famname); } } /***********************************************************************\ * Return the string from enumeration * \***********************************************************************/ int cgi_GridLocation(char *LocationName, CGNS_ENUMT(GridLocation_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( GridLocationUserDefined ); cgi_warning("Unrecognized Grid Location Type '%s' replaced with 'UserDefined'",LocationName); return CG_OK; } cgi_error("Unrecognized GridLocation: %s", LocationName); return CG_ERROR; } int cgi_GridConnectivityType(char *GridConnectivityName, CGNS_ENUMT(GridConnectivityType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( GridConnectivityTypeUserDefined ); cgi_warning("Unrecognized Grid Connectivity Type '%s' replaced with 'UserDefined'",GridConnectivityName); return CG_OK; } cgi_error("Unrecognized GridConnectivityType: %s", GridConnectivityName); return CG_ERROR; } int cgi_PointSetType(char *PointSetName, CGNS_ENUMT(PointSetType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( PointSetTypeUserDefined ); cgi_warning("Unrecognized Point Set Type '%s' replaced with 'UserDefined'",PointSetName); return CG_OK; } cgi_error("Unrecognized PointSetType: %s", PointSetName); return CG_ERROR; } int cgi_BCType(char *BCName, CGNS_ENUMT(BCType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( BCTypeUserDefined ); cgi_warning("Unrecognized BCType '%s' replaced with 'UserDefined'",BCName); return CG_OK; } cgi_error("Unrecognized BCType: %s", BCName); return CG_ERROR; } int cgi_DataClass(char *Name, CGNS_ENUMT(DataClass_t) *data_class) { int i; for (i=0; iversion > CGNSLibVersion) { (*data_class) = CGNS_ENUMV( DataClassUserDefined ); cgi_warning("Unrecognized Data Class '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Data Class: %s",Name); return CG_ERROR; } int cgi_MassUnits(char *Name, CGNS_ENUMT(MassUnits_t) *mass_unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*mass_unit) = CGNS_ENUMV( MassUnitsUserDefined ); cgi_warning("Unrecognized Mass Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*mass_unit) = CGNS_ENUMV( MassUnitsNull ); cgi_error("Unrecognized Mass Units Name: %s", Name); return CG_ERROR; } int cgi_LengthUnits(char *Name, CGNS_ENUMT(LengthUnits_t) *length_unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*length_unit) = CGNS_ENUMV( LengthUnitsUserDefined ); cgi_warning("Unrecognized Length Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*length_unit) = CGNS_ENUMV( LengthUnitsNull ); cgi_error("Unrecognized Length Units Name: %s", Name); return CG_ERROR; } int cgi_TimeUnits(char *Name, CGNS_ENUMT(TimeUnits_t) *time_unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*time_unit) = CGNS_ENUMV( TimeUnitsUserDefined ); cgi_warning("Unrecognized Time Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*time_unit) = CGNS_ENUMV( TimeUnitsNull ); cgi_error("Unrecognized Time Units Name: %s", Name); return CG_ERROR; } int cgi_TemperatureUnits(char *Name, CGNS_ENUMT(TemperatureUnits_t) *temperature_unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; if (0 == strcmp(Name, "Celcius")) { *temperature_unit = CGNS_ENUMV( Celsius ); return CG_OK; } for (i=0; iversion > CGNSLibVersion) { (*temperature_unit) = CGNS_ENUMV( TemperatureUnitsUserDefined ); cgi_warning("Unrecognized Temperature Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*temperature_unit) = CGNS_ENUMV( TemperatureUnitsNull ); cgi_error("Unrecognized Temperature Units Name: %s", Name); return CG_ERROR; } int cgi_AngleUnits(char *Name, CGNS_ENUMT(AngleUnits_t) *angle_unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*angle_unit) = CGNS_ENUMV( AngleUnitsUserDefined ); cgi_warning("Unrecognized Angle Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*angle_unit) = CGNS_ENUMV( AngleUnitsNull ); cgi_error("Unrecognized Angle Units Name: %s", Name); return CG_ERROR; } int cgi_ElectricCurrentUnits(char *Name, CGNS_ENUMT(ElectricCurrentUnits_t) *unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*unit) = CGNS_ENUMV( ElectricCurrentUnitsUserDefined ); cgi_warning("Unrecognized ElectricCurrent Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*unit) = CGNS_ENUMV( ElectricCurrentUnitsNull ); cgi_error("Unrecognized ElectricCurrent Units Name: %s", Name); return CG_ERROR; } int cgi_SubstanceAmountUnits(char *Name, CGNS_ENUMT(SubstanceAmountUnits_t) *unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*unit) = CGNS_ENUMV( SubstanceAmountUnitsUserDefined ); cgi_warning("Unrecognized SubstanceAmount Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*unit) = CGNS_ENUMV( SubstanceAmountUnitsNull ); cgi_error("Unrecognized SubstanceAmount Units Name: %s", Name); return CG_ERROR; } int cgi_LuminousIntensityUnits(char *Name, CGNS_ENUMT(LuminousIntensityUnits_t) *unit) { int i; for (i=31; i>=0 && Name[i]==' '; i--); Name[i+1]='\0'; for (i=0; iversion > CGNSLibVersion) { (*unit) = CGNS_ENUMV( LuminousIntensityUnitsUserDefined ); cgi_warning("Unrecognized LuminousIntensity Unit '%s' replaced with 'UserDefined'",Name); return CG_OK; } (*unit) = CGNS_ENUMV( LuminousIntensityUnitsNull ); cgi_error("Unrecognized LuminousIntensity Units Name: %s", Name); return CG_ERROR; } int cgi_GoverningEquationsType(char *Name, CGNS_ENUMT(GoverningEquationsType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( GoverningEquationsUserDefined ); cgi_warning("Unrecognized Governing Equations Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Governing Equations Type: %s", Name); return CG_ERROR; } int cgi_ModelType(char *Name, CGNS_ENUMT(ModelType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( ModelTypeUserDefined ); cgi_warning("Unrecognized Model Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Model Type : %s", Name); return CG_ERROR; } int cgi_ZoneType(char *Name, CGNS_ENUMT(ZoneType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( ZoneTypeUserDefined ); cgi_warning("Unrecognized Zone Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Zone Type : %s", Name); return CG_ERROR; } int cgi_RigidGridMotionType(char *Name, CGNS_ENUMT(RigidGridMotionType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( RigidGridMotionTypeUserDefined ); cgi_warning("Unrecognized Rigid Grid Motion Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Rigid Grid Motion Type: %s", Name); return CG_ERROR; } int cgi_ArbitraryGridMotionType(char *Name, CGNS_ENUMT(ArbitraryGridMotionType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( ArbitraryGridMotionTypeUserDefined ); cgi_warning("Unrecognized Arbitrary Grid Motion Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Arbitrary Grid Motion Type: %s", Name); return CG_ERROR; } int cgi_SimulationType(char *Name, CGNS_ENUMT(SimulationType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( SimulationTypeUserDefined ); cgi_warning("Unrecognized Simulation Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Simulation Type: %s", Name); return CG_ERROR; } int cgi_WallFunctionType(char *Name, CGNS_ENUMT(WallFunctionType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( WallFunctionTypeUserDefined ); cgi_warning("Unrecognized Wall Function Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Wall Function Type: %s", Name); return CG_ERROR; } int cgi_AreaType(char *Name, CGNS_ENUMT(AreaType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( AreaTypeUserDefined ); cgi_warning("Unrecognized Area Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Area Type: %s", Name); return CG_ERROR; } int cgi_AverageInterfaceType(char *Name, CGNS_ENUMT(AverageInterfaceType_t) *type) { int i; for (i=0; iversion > CGNSLibVersion) { (*type) = CGNS_ENUMV( AverageInterfaceTypeUserDefined ); cgi_warning("Unrecognized Average Interface Type '%s' replaced with 'UserDefined'",Name); return CG_OK; } cgi_error("Unrecognized Average Interface Type: %s", Name); return CG_ERROR; } void cgi_array_print(char *routine, cgns_array *array) { int n; printf("In %s:\n", routine); printf("\t array->name='%s'\n",array->name); printf("\t array->dim_vals="); for (n=0; ndata_dim; n++) printf("%ld ",(long)array->dim_vals[n]); printf("\n"); printf("\t array->data_type='%s'\n",DataTypeName[cgi_datatype(array->data_type)]); printf("\t array->id=%13.6e\n",array->id); printf("\t array->ndescr=%d\n",array->ndescr); for (n=0; nndescr; n++) printf("%s\n",array->descr->text); if (array->data_class) printf("\t array->data_class=%s\n",DataClassName[array->data_class]); for (n=0; n<(array->dim_vals[0]*array->dim_vals[1]); n++) printf("%d ", *((int *)array->data+n)); return; } CGNS-3.4.0/src/cgns_io.c000066400000000000000000001604321343724673500146500ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ #ifndef __SUNPRO_C #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 #endif #endif #include #include #include #include #include #include #if defined(_WIN32) && !defined(__NUTC__) # include # define ACCESS _access # define UNLINK _unlink #else # include # define ACCESS access # define UNLINK unlink #endif #include #include "cgns_io.h" #include "cgnslib.h" #include "adf/ADF.h" #ifdef BUILD_HDF5 #include "adfh/ADFH.h" char hdf5_access[64] = "NATIVE"; #endif #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #ifdef BUILD_PARALLEL #include MPI_Comm pcg_mpi_comm=MPI_COMM_WORLD; int pcg_mpi_comm_size; int pcg_mpi_comm_rank; int pcg_mpi_initialized; MPI_Info pcg_mpi_info; #endif #if CG_HAVE_STAT64_STRUCT #ifdef _WIN32 #define stat _stat64 #else #define stat stat64 #endif #endif typedef struct { int type; int mode; double rootid; } cgns_io; static int num_open = 0; static int num_iolist = 0; static cgns_io *iolist; static char *cgio_ErrorMessage[] = { "no error", "invalid cgio index", "malloc/realloc failed", "unknown file open mode", "invalid file type", "filename is NULL or empty", "character string is too small", "file was not found", "pathname is NULL or empty", "no match for pathname", "error opening file for reading", "file opened in read-only mode", "NULL or empty string", "invalid configure option", "rename of tempfile file failed", "too many open files", "dimensions exceed that for a 32-bit integer", "file has the wrong specified type", "not a HDF5 file - required for parallel" }; #define CGIO_MAX_ERRORS (sizeof(cgio_ErrorMessage)/sizeof(char *)) #define get_error() last_err static int last_err = CGIO_ERR_NONE; static int last_type = CGIO_FILE_NONE; static int abort_on_error = 0; static int cgio_n_paths = 0; static char **cgio_paths = 0; /*========================================================= * support routines *=========================================================*/ static int set_error (int errcode) { last_err = errcode; if (last_err && abort_on_error) cgio_error_exit(NULL); return last_err; } static cgns_io *get_cgnsio (int cgio_num, int write) { if (--cgio_num < 0 || cgio_num >= num_iolist) { last_err = CGIO_ERR_BAD_CGIO; return NULL; } if (write && iolist[cgio_num].mode == CGIO_MODE_READ) { last_err = CGIO_ERR_READ_ONLY; return NULL; } last_type = iolist[cgio_num].type; last_err = CGIO_ERR_NONE; return &iolist[cgio_num]; } /*---------------------------------------------------------*/ static cglong_t compute_data_size (const char *data_type, int ndims, const cgsize_t *dims) { int size; cglong_t count; size = cgio_compute_data_size (data_type, ndims, dims, &count); return (cglong_t)size * count; } /*---------------------------------------------------------*/ static int recurse_nodes (int input, double InputID, int output, double OutputID, int follow_links, int depth) { int n, nchild, cnt, name_len, file_len; char name[CGIO_MAX_NAME_LENGTH+1]; char *link_name, *link_file; double childID, newID; /* Copy the data from the current input node to the output node */ if (depth && cgio_copy_node(input, InputID, output, OutputID)) return CG_ERROR; /* Loop through the children of the current node */ if (cgio_number_children(input, InputID, &nchild)) return CG_ERROR; for (n = 1; n <= nchild; n++) { if (cgio_children_ids(input, InputID, n, 1, &cnt, &childID) || cgio_get_name(input, childID, name) || cgio_is_link(input, childID, &name_len)) return CG_ERROR; if (name_len) { if (cgio_link_size(input, childID, &file_len, &name_len)) return CG_ERROR; } if (name_len && (file_len == 0 || follow_links == 0)) { link_file = (char *) malloc (file_len + name_len + 2); if (link_file == NULL) { set_error(CGIO_ERR_MALLOC); return CG_ERROR; } link_name = link_file + file_len + 1; if (cgio_get_link(input, childID, link_file, link_name)) { free (link_file); return CG_ERROR; } link_file[file_len] = 0; link_name[name_len] = 0; if (cgio_create_link(output, OutputID, name, link_file, link_name, &newID)) { free (link_file); return CG_ERROR; } free (link_file); } else { if (cgio_create_node(output, OutputID, name, &newID) || recurse_nodes(input, childID, output, newID, follow_links, ++depth)) return CG_ERROR; } } return CG_OK; } /*---------------------------------------------------------*/ static int rewrite_file (int cginp, const char *filename) { int cgout, ierr; cgns_io *input, *output; char *tmpfile, *linkfile = NULL; #ifdef S_IFLNK struct stat st; #endif input = get_cgnsio(cginp, 0); if (input->mode != CGIO_MODE_READ && cgio_flush_to_disk(cginp)) return get_error(); #ifdef S_IFLNK if (!lstat(filename, &st) && (st.st_mode & S_IFLNK) == S_IFLNK) { int len; linkfile = (char *)malloc(st.st_size + 1); if (linkfile == NULL) return set_error(CGIO_ERR_MALLOC); len = readlink(filename, linkfile, st.st_size + 1); if (len < 0 || len > st.st_size) { free(linkfile); linkfile = NULL; } else { linkfile[len] = 0; } } #endif if (linkfile == NULL) { tmpfile = (char *)malloc(strlen(filename) + 6); if (tmpfile == NULL) return set_error(CGIO_ERR_MALLOC); sprintf(tmpfile, "%s.temp", filename); } else { tmpfile = (char *)malloc(strlen(linkfile) + 6); if (tmpfile == NULL) { free(linkfile); return set_error(CGIO_ERR_MALLOC); } sprintf(tmpfile, "%s.temp", linkfile); } UNLINK(tmpfile); if (cgio_open_file(tmpfile, CGIO_MODE_WRITE, input->type, &cgout)) { UNLINK(tmpfile); free(tmpfile); if (linkfile != NULL) free(linkfile); return get_error(); } output = get_cgnsio(cgout, 0); ierr = recurse_nodes(cginp, input->rootid, cgout, output->rootid, 0, 0); cgio_close_file (cgout); if (ierr) { UNLINK(tmpfile); free(tmpfile); if (linkfile != NULL) free(linkfile); return set_error(ierr); } ierr = CGIO_ERR_NONE; cgio_close_file (cginp); if (linkfile == NULL) { UNLINK(filename); if (rename(tmpfile, filename)) ierr = CGIO_ERR_FILE_RENAME; } else { UNLINK(linkfile); if (rename(tmpfile, linkfile)) ierr = CGIO_ERR_FILE_RENAME; free(linkfile); } free(tmpfile); return set_error(ierr); } /*========================================================= * paths for searching for linked-to files *=========================================================*/ int cgio_path_add (const char *path) { if (path == NULL || !*path) return set_error(CGIO_ERR_NULL_FILE); if (cgio_n_paths) cgio_paths = (char **) realloc (cgio_paths, (cgio_n_paths+1) * sizeof(char *)); else cgio_paths = (char **) malloc (sizeof(char *)); if (cgio_paths == NULL) { cgio_n_paths = 0; return set_error(CGIO_ERR_MALLOC); } cgio_paths[cgio_n_paths] = (char *) malloc (strlen(path)+1); if (cgio_paths[cgio_n_paths] == NULL) return set_error(CGIO_ERR_MALLOC); strcpy(cgio_paths[cgio_n_paths], path); cgio_n_paths++; return set_error(CGIO_ERR_NONE); } /*---------------------------------------------------------*/ int cgio_path_delete (const char *path) { int n; if (cgio_n_paths == 0) { if (path != NULL) return set_error(CGIO_ERR_NO_MATCH); return set_error(CGIO_ERR_NONE); } if (path != NULL) { for (n = 0; n < cgio_n_paths; n++) { if (cgio_paths[n] != NULL && 0 == strcmp(path, cgio_paths[n])) { free(cgio_paths[n]); cgio_paths[n] = NULL; return set_error(CGIO_ERR_NONE); } } return set_error(CGIO_ERR_NO_MATCH); } for (n = 0; n < cgio_n_paths; n++) { if (cgio_paths[n] != NULL) free(cgio_paths[n]); } free(cgio_paths); cgio_n_paths = 0; cgio_paths = NULL; return set_error(CGIO_ERR_NONE); } /*---------------------------------------------------------*/ int cgio_find_file (const char *parentfile, const char *filename, int file_type, int max_path_len, char *pathname) { int n, size, len, type; char *p, *s; if (filename == NULL || !*filename) return set_error(CGIO_ERR_NULL_FILE); size = max_path_len - 1 - (int)strlen(filename); if (size < 0) return set_error(CGIO_ERR_TOO_SMALL); /* full path */ if (*filename == '/' #ifdef _WIN32 || *filename == '\\' || *(filename+1) == ':' #endif ) { if (cgio_check_file(filename, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) { strcpy(pathname, filename); return set_error(CGIO_ERR_NONE); } if (get_error() == CGIO_ERR_TOO_MANY) return CGIO_ERR_TOO_MANY; return set_error(CGIO_ERR_NOT_FOUND); } /* check relative to parent's directory */ if (parentfile != NULL && *parentfile && (int)strlen(parentfile) < max_path_len-1) { strcpy(pathname, parentfile); p = strrchr(pathname, '/'); #ifdef _WIN32 if (p == NULL) p = strrchr(pathname, '\\'); #endif if (p != NULL) { *++p = 0; if ((int)strlen(pathname) <= size) { strcpy(p, filename); if (cgio_check_file(pathname, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) return set_error(CGIO_ERR_NONE); } } } /* check current directory */ if (cgio_check_file(filename, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) { strcpy(pathname, filename); return set_error(CGIO_ERR_NONE); } if (get_error() == CGIO_ERR_TOO_MANY) return CGIO_ERR_TOO_MANY; size -= 1; /* check file type environment variable */ if (file_type == CGIO_FILE_ADF || file_type == CGIO_FILE_ADF2) p = getenv ("ADF_LINK_PATH"); #ifdef BUILD_HDF5 else if (file_type == CGIO_FILE_HDF5) p = getenv ("HDF5_LINK_PATH"); #endif else p = NULL; while (p != NULL && *p) { #ifdef _WIN32 if (NULL == (s = strchr (p, ';'))) #else if (NULL == (s = strchr (p, ':'))) #endif len = (int)strlen(p); else len = (int)(s++ - p); if (len) { if (len > size) return set_error(CGIO_ERR_TOO_SMALL); strncpy (pathname, p, len); #ifdef _WIN32 for (n = 0; n < len; n++) { if (*p == '\\') *p = '/'; } #endif p = pathname + len; if (*(p-1) != '/') *p++ = '/'; strcpy (p, filename); if (cgio_check_file(pathname, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) return set_error(CGIO_ERR_NONE); } p = s; } /* check $CGNS_LINK_PATH environment variable */ p = getenv ("CGNS_LINK_PATH"); while (p != NULL && *p) { #ifdef _WIN32 if (NULL == (s = strchr (p, ';'))) #else if (NULL == (s = strchr (p, ':'))) #endif len = (int)strlen(p); else len = (int)(s++ - p); if (len) { if (len > size) return set_error(CGIO_ERR_TOO_SMALL); strncpy (pathname, p, len); #ifdef _WIN32 for (n = 0; n < len; n++) { if (*p == '\\') *p = '/'; } #endif p = pathname + len; if (*(p-1) != '/') *p++ = '/'; strcpy (p, filename); if (cgio_check_file(pathname, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) return set_error(CGIO_ERR_NONE); } p = s; } /* check list of search paths */ for (n = 0; n < cgio_n_paths; n++) { for (p = cgio_paths[n]; p != NULL && *p; ) { #ifdef _WIN32 if (NULL == (s = strchr (p, ';'))) #else if (NULL == (s = strchr (p, ':'))) #endif len = (int)strlen(p); else len = (int)(s++ - p); if (len) { if (len > size) return set_error(CGIO_ERR_TOO_SMALL); strncpy (pathname, p, len); #ifdef _WIN32 for (n = 0; n < len; n++) { if (*p == '\\') *p = '/'; } #endif p = pathname + len; if (*(p-1) != '/') *p++ = '/'; strcpy (p, filename); if (cgio_check_file(pathname, &type) == CGIO_ERR_NONE && (file_type == CGIO_FILE_NONE || file_type == type)) return set_error(CGIO_ERR_NONE); } p = s; } } return set_error(CGIO_ERR_NOT_FOUND); } /*========================================================= * utility routines independent of open files *=========================================================*/ int cgio_is_supported (int file_type) { if (file_type == CGIO_FILE_ADF) return set_error(CGIO_ERR_NONE); #if CG_SIZEOF_SIZE == 32 if (file_type == CGIO_FILE_ADF2) return set_error(CGIO_ERR_NONE); #endif #ifdef BUILD_HDF5 if (file_type == CGIO_FILE_HDF5) return set_error(CGIO_ERR_NONE); #endif last_err = CGIO_ERR_FILE_TYPE; return last_err; } /*---------------------------------------------------------*/ int cgio_configure (int what, void *value) { int ierr = CGIO_ERR_BAD_OPTION; if (what > 200) { #ifdef BUILD_HDF5 ADFH_Configure(what-200, value, &ierr); #endif } /* nothing here yet else if (what > 100) { } */ return set_error(ierr); } /*---------------------------------------------------------*/ void cgio_cleanup () { if (num_open) { int n; num_open++; for (n = 0; n < num_iolist; n++) { if (iolist[n].type != CGIO_FILE_NONE) cgio_close_file(n + 1); } free(iolist); num_iolist = 0; num_open = 0; } cgio_path_delete(NULL); } /*---------------------------------------------------------*/ int cgio_check_file (const char *filename, int *file_type) { int n; char buf[32]; FILE *fp; static char *HDF5sig = "\211HDF\r\n\032\n"; struct stat st; int mpibuf[2], err = CGIO_ERR_NONE; if (ACCESS (filename, 0) || stat (filename, &st) || S_IFREG != (st.st_mode & S_IFREG)) { last_err = CGIO_ERR_NOT_FOUND; return last_err; } *file_type = CGIO_FILE_NONE; #ifdef BUILD_PARALLEL /* don't overload the file system by having all the processors doing a read */ if(pcg_mpi_comm_rank == 0) { #endif fp = fopen(filename, "rb"); if (NULL == fp) { if (errno == EMFILE) { err = set_error(CGIO_ERR_TOO_MANY); } else { err = set_error(CGIO_ERR_FILE_OPEN); } return err; } fread (buf, 1, sizeof(buf), fp); buf[sizeof(buf)-1] = 0; fclose (fp); /* check for ADF */ if (0 == strncmp (&buf[4], "ADF Database Version", 20)) { *file_type = CGIO_FILE_ADF; err = set_error(CGIO_ERR_NONE); } else { /* check for HDF5 */ for (n = 0; n < 8; n++) { if (buf[n] != HDF5sig[n]) break; } if (n == 8) { *file_type = CGIO_FILE_HDF5; err = set_error(CGIO_ERR_NONE); } } #ifdef BUILD_PARALLEL } if(pcg_mpi_initialized) { mpibuf[0] = err; mpibuf[1] = *file_type; MPI_Bcast(mpibuf, 2, MPI_INT, 0, pcg_mpi_comm); err = mpibuf[0]; *file_type = mpibuf[1]; } #endif if(err == set_error(CGIO_ERR_NONE)) return err; last_err = CGIO_ERR_FILE_TYPE; return last_err; } /*---------------------------------------------------------*/ int cgio_compute_data_size (const char *data_type, int ndims, const cgsize_t *dims, cglong_t *count) { if (ndims > 0) { int i; *count = (cglong_t)dims[0]; for (i = 1; i < ndims; i++) *count *= (cglong_t)dims[i]; } else { *count = 0; } switch (*data_type) { case 'B': case 'C': return CG_ERROR; case 'I': case 'U': if (data_type[1] == '4') return sizeof(int); if (data_type[1] == '8') return sizeof(cglong_t); break; case 'R': if (data_type[1] == '4') return sizeof(float); if (data_type[1] == '8') return sizeof(double); break; case 'X': if (data_type[1] == '4') return (2 * sizeof(float)); if (data_type[1] == '8') return (2 * sizeof(double)); break; } return CG_OK; } /*---------------------------------------------------------*/ int cgio_check_dimensions (int ndims, const cglong_t *dims) { int n; for (n = 0; n < ndims; n++) { if (dims[n] > CG_MAX_INT32) return set_error(CGIO_ERR_DIMENSIONS); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_copy_dimensions (int ndims, const cglong_t *dims64, cgsize_t *dims) { int n; #if CG_SIZEOF_SIZE == 32 if (cgio_check_dimensions(ndims, dims64)) return get_error(); #endif for (n = 0; n < ndims; n++) dims[n] = (cgsize_t)dims64[n]; return CGIO_ERR_NONE; } /*========================================================= * file operations *=========================================================*/ int cgio_open_file (const char *filename, int file_mode, int file_type, int *cgio_num) { int n, ierr; int type; char *fmode; double rootid; *cgio_num = 0; switch(file_mode) { case CGIO_MODE_READ: case 'r': case 'R': if (cgio_check_file(filename, &type)) return get_error(); #ifdef BUILD_PARALLEL if (file_type == CGIO_FILE_HDF5) { if (type != CGIO_FILE_HDF5) return set_error(CGIO_ERR_NOT_HDF5); } else #endif file_type = type; file_mode = CGIO_MODE_READ; fmode = "READ_ONLY"; break; case CGIO_MODE_WRITE: case 'w': case 'W': UNLINK(filename); type = file_type; file_mode = CGIO_MODE_WRITE; fmode = "NEW"; break; case CGIO_MODE_MODIFY: case 'm': case 'M': if (cgio_check_file(filename, &type)) return get_error(); #ifdef BUILD_PARALLEL if (file_type == CGIO_FILE_HDF5) { if (type != CGIO_FILE_HDF5) return set_error(CGIO_ERR_NOT_HDF5); } #endif file_type = type; file_mode = CGIO_MODE_MODIFY; fmode = "OLD"; break; default: return set_error(CGIO_ERR_FILE_MODE); } last_type = file_type; if (file_type == CGIO_FILE_NONE) { last_type = file_type = CGIO_FILE_ADF; ADF_Database_Open(filename, fmode, "NATIVE", &rootid, &ierr); if (ierr > 0) return set_error(ierr); } #if CG_SIZEOF_SIZE == 32 else if (file_type == CGIO_FILE_ADF || file_type == CGIO_FILE_ADF2) { ADF_Database_Open(filename, fmode, "LEGACY", &rootid, &ierr); if (ierr > 0) return set_error(ierr); } #else else if (file_type == CGIO_FILE_ADF) { ADF_Database_Open(filename, fmode, "NATIVE", &rootid, &ierr); if (ierr > 0) return set_error(ierr); } #endif #ifdef BUILD_HDF5 else if (file_type == CGIO_FILE_HDF5) { ADFH_Database_Open(filename, fmode, hdf5_access, &rootid, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } if (num_iolist == 0) { num_iolist = 5; iolist = (cgns_io *) malloc (num_iolist * sizeof(cgns_io)); if (iolist == NULL) { fprintf(stderr, "malloc failed for IO list\n"); exit(1); } for (n = 0; n < num_iolist; n++) iolist[n].type = CGIO_FILE_NONE; } for (n = 0; n < num_iolist; n++) { if (iolist[n].type == CGIO_FILE_NONE) break; } if (n == num_iolist) { num_iolist++; iolist = (cgns_io *) realloc (iolist, num_iolist * sizeof(cgns_io)); if (iolist == NULL) { fprintf(stderr, "realloc failed for IO list\n"); exit(1); } } iolist[n].type = file_type; iolist[n].mode = file_mode; iolist[n].rootid = rootid; *cgio_num = n + 1; num_open++; return set_error(CGIO_ERR_NONE); } /*---------------------------------------------------------*/ int cgio_close_file (int cgio_num) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Database_Close(cgio->rootid, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Database_Close(cgio->rootid, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } cgio->type = CGIO_FILE_NONE; if (--num_open == 0) { free(iolist); num_iolist = 0; } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_compress_file (int cgio_num, const char *filename) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { if (rewrite_file (cgio_num, filename)) { ierr = get_error(); cgio_close_file(cgio_num); return set_error(ierr); } } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { if (rewrite_file (cgio_num, filename)) { ierr = get_error(); cgio_close_file(cgio_num); return set_error(ierr); } } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_copy_file (int cgio_num_inp, int cgio_num_out, int follow_links) { cgns_io *input, *output; if ((input = get_cgnsio(cgio_num_inp, 0)) == NULL || (output = get_cgnsio(cgio_num_out, 1)) == NULL) return get_error(); if (input->mode != CGIO_MODE_READ && cgio_flush_to_disk(cgio_num_inp)) return get_error(); if (recurse_nodes(cgio_num_inp, input->rootid, cgio_num_out, output->rootid, follow_links, 0)) return get_error(); return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_flush_to_disk (int cgio_num) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->mode == CGIO_MODE_READ) return CGIO_ERR_NONE; if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Flush_to_Disk(cgio->rootid, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Flush_to_Disk(cgio->rootid, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*========================================================= * file information *=========================================================*/ int cgio_library_version (int cgio_num, char *version) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Library_Version(version, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Library_Version(version, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_file_version (int cgio_num, char *file_version, char *creation_date, char *modified_date) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Database_Version(cgio->rootid, file_version, creation_date, modified_date, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Database_Version(cgio->rootid, file_version, creation_date, modified_date, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_root_id (int cgio_num, double *rootid) { cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); *rootid = cgio->rootid; return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_file_type (int cgio_num, int *file_type) { cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); *file_type = cgio->type; return CGIO_ERR_NONE; } /*========================================================= * error handling *=========================================================*/ void cgio_error_code (int *errcode, int *file_type) { *errcode = last_err; if (last_err <= 0) *file_type = CGIO_FILE_NONE; else *file_type = last_type; } /*---------------------------------------------------------*/ int cgio_error_message (char *error_msg) { char msg[ADF_MAX_ERROR_STR_LENGTH+1]; if (last_err <= 0) { int errcode = -last_err; if (errcode >= CGIO_MAX_ERRORS) strcpy(msg, "unknown cgio error message"); else strcpy(msg, cgio_ErrorMessage[errcode]); } else if (last_type == CGIO_FILE_ADF || last_type == CGIO_FILE_ADF2) { ADF_Error_Message(last_err, msg); } #ifdef BUILD_HDF5 else if (last_type == CGIO_FILE_HDF5) { ADFH_Error_Message(last_err, msg); } #endif else { strcpy(msg, "unknown error message"); } strcpy(error_msg, msg); return last_err; } /*---------------------------------------------------------*/ void cgio_error_exit (const char *msg) { fflush(stdout); if (msg != NULL && *msg) fprintf(stderr, "%s:", msg); if (last_err) { char errmsg[81]; cgio_error_message(errmsg); fprintf(stderr, "%s", errmsg); } putc('\n', stderr); cgio_cleanup(); exit(abort_on_error ? abort_on_error : -1); } /*---------------------------------------------------------*/ void cgio_error_abort (int abort_flag) { abort_on_error = abort_flag; } /*========================================================= * basic node operations *=========================================================*/ int cgio_create_node (int cgio_num, double pid, const char *name, double *id) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Create(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Create(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_new_node (int cgio_num, double pid, const char *name, const char *label, const char *data_type, int ndims, const cgsize_t *dims, const void *data, double *id) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Create(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); ADF_Set_Label(*id, label, &ierr); if (ierr > 0) return set_error(ierr); if (data_type != NULL && strcmp(data_type, "MT")) { ADF_Put_Dimension_Information(*id, data_type, ndims, dims, &ierr); if (ierr > 0) return set_error(ierr); if (data != NULL) { ADF_Write_All_Data(*id, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } } } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Create(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); ADFH_Set_Label(*id, label, &ierr); if (ierr > 0) return set_error(ierr); if (data_type != NULL && strcmp(data_type, "MT")) { ADFH_Put_Dimension_Information(*id, data_type, ndims, dims, &ierr); if (ierr > 0) return set_error(ierr); if (data != NULL) { ADFH_Write_All_Data(*id, NULL, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } } } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_delete_node (int cgio_num, double pid, double id) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Delete(pid, id, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Delete(pid, id, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_move_node (int cgio_num, double pid, double id, double new_pid) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Move_Child(pid, id, new_pid, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Move_Child(pid, id, new_pid, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_copy_node (int cgio_num_inp, double id_inp, int cgio_num_out, double id_out) { cgns_io *input, *output; char label[CGIO_MAX_NAME_LENGTH+1]; char data_type[CGIO_MAX_NAME_LENGTH+1]; int ierr = 0, ndims; cgsize_t dims[CGIO_MAX_DIMENSIONS]; cglong_t data_size = 0; void *data = NULL; if ((input = get_cgnsio(cgio_num_inp, 0)) == NULL || (output = get_cgnsio(cgio_num_out, 1)) == NULL) return get_error(); /* read the input node data */ if (input->type == CGIO_FILE_ADF || input->type == CGIO_FILE_ADF2) { ADF_Get_Label(id_inp, label, &ierr); if (ierr > 0) return set_error(ierr); ADF_Get_Data_Type(id_inp, data_type, &ierr); if (ierr > 0) return set_error(ierr); ADF_Get_Number_of_Dimensions(id_inp, &ndims, &ierr); if (ierr > 0) return set_error(ierr); if (ndims > 0) { ADF_Get_Dimension_Values(id_inp, dims, &ierr); if (ierr > 0) return set_error(ierr); data_size = compute_data_size(data_type, ndims, dims); if (data_size) { data = malloc((size_t)data_size); if (data == NULL) return set_error(CGIO_ERR_MALLOC); ADF_Read_All_Data(id_inp, (char *)data, &ierr); if (ierr > 0) { free(data); return set_error(ierr); } } } } #ifdef BUILD_HDF5 else if (input->type == CGIO_FILE_HDF5) { ADFH_Get_Label(id_inp, label, &ierr); if (ierr > 0) return set_error(ierr); ADFH_Get_Data_Type(id_inp, data_type, &ierr); if (ierr > 0) return set_error(ierr); ADFH_Get_Number_of_Dimensions(id_inp, &ndims, &ierr); if (ierr > 0) return set_error(ierr); if (ndims > 0) { ADFH_Get_Dimension_Values(id_inp, dims, &ierr); if (ierr > 0) return set_error(ierr); data_size = compute_data_size(data_type, ndims, dims); if (data_size) { data = malloc((size_t)data_size); if (data == NULL) return set_error(CGIO_ERR_MALLOC); ADFH_Read_All_Data(id_inp, NULL, (char *)data, &ierr); if (ierr > 0) { free(data); return set_error(ierr); } } } } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } /* write data to output node */ if (output->type == CGIO_FILE_ADF || output->type == CGIO_FILE_ADF2) { ADF_Set_Label(id_out, label, &ierr); if (ierr <= 0) { ADF_Put_Dimension_Information(id_out, data_type, ndims, dims, &ierr); if (ierr <= 0 && data_size) ADF_Write_All_Data(id_out, (const char *)data, &ierr); } if (data_size) free(data); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (output->type == CGIO_FILE_HDF5) { ADFH_Set_Label(id_out, label, &ierr); if (ierr <= 0) { ADFH_Put_Dimension_Information(id_out, data_type, ndims, dims, &ierr); if (ierr <= 0 && data_size) ADFH_Write_All_Data(id_out, NULL, (const char *)data, &ierr); } if (data_size) free(data); if (ierr > 0) return set_error(ierr); } #endif else { if (data_size) free(data); set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_release_id (int cgio_num, double id) { #ifdef BUILD_HDF5 cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_HDF5) { ADFH_Release_ID(id); } #endif return CGIO_ERR_NONE; } /*========================================================= * links *=========================================================*/ int cgio_is_link (int cgio_num, double id, int *link_len) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Is_Link(id, link_len, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Is_Link(id, link_len, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_link_size (int cgio_num, double id, int *file_len, int *name_len) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Link_Size(id, file_len, name_len, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Link_Size(id, file_len, name_len, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_create_link (int cgio_num, double pid, const char *name, const char *filename, const char *name_in_file, double *id) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Link(pid, name, filename, name_in_file, id, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Link(pid, name, filename, name_in_file, id, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_link (int cgio_num, double id, char *filename, char *name_in_file) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Link_Path(id, filename, name_in_file, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Link_Path(id, filename, name_in_file, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*========================================================= * node children *=========================================================*/ int cgio_number_children (int cgio_num, double id, int *num_children) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Number_of_Children(id, num_children, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Number_of_Children(id, num_children, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_children_ids (int cgio_num, double pid, int start, int max_ret, int *num_ret, double *ids) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Children_IDs(pid, start, max_ret, num_ret, ids, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Children_IDs(pid, start, max_ret, num_ret, ids, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_children_names (int cgio_num, double pid, int start, int max_ret, int name_len, int *num_ret, char *names) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Children_Names(pid, start, max_ret, name_len-1, num_ret, names, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Children_Names(pid, start, max_ret, name_len, num_ret, names, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*========================================================= * read nodes *=========================================================*/ int cgio_get_node_id (int cgio_num, double pid, const char *name, double *id) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Node_ID(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Node_ID(pid, name, id, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_name (int cgio_num, double id, char *name) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Name(id, name, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Name(id, name, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_label (int cgio_num, double id, char *label) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Label(id, label, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Label(id, label, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_data_type (int cgio_num, double id, char *data_type) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Data_Type(id, data_type, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Data_Type(id, data_type, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_data_size (int cgio_num, double id, cglong_t *data_size) { int byte, ndims; cgsize_t dims[CGIO_MAX_DIMENSIONS]; char data_type[CGIO_MAX_NAME_LENGTH]; *data_size = 0; if (cgio_get_dimensions(cgio_num, id, &ndims, dims) || cgio_get_data_type(cgio_num, id, data_type)) return get_error(); byte = cgio_compute_data_size(data_type, ndims, dims, data_size); *data_size *= byte; return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_get_dimensions (int cgio_num, double id, int *num_dims, cgsize_t *dims) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Get_Number_of_Dimensions(id, num_dims, &ierr); if (NULL != dims && ierr <= 0 && *num_dims > 0) { ADF_Get_Dimension_Values(id, dims, &ierr); } if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Get_Number_of_Dimensions(id, num_dims, &ierr); if (NULL != dims && ierr <= 0 && *num_dims > 0) { ADFH_Get_Dimension_Values(id, dims, &ierr); } if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_read_all_data (int cgio_num, double id, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Read_All_Data(id, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Read_All_Data(id, NULL, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_read_all_data_type (int cgio_num, double id, const char *m_data_type, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { /* Changing type when reading is not supported with adf files. In practice, we convert first and call cgio_read_all_data */ return set_error(CGIO_ERR_NOT_HDF5); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Read_All_Data(id, m_data_type, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_read_block_data (int cgio_num, double id, cgsize_t b_start, cgsize_t b_end, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Read_Block_Data(id, b_start, b_end, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Read_Block_Data(id, b_start, b_end, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_read_data (int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride,int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Read_Data(id, s_start, s_end, s_stride, m_num_dims, m_dims, m_start, m_end, m_stride, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Read_Data(id, s_start, s_end, s_stride, NULL, m_num_dims, m_dims, m_start, m_end, m_stride, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_read_data_type (int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, const char *m_data_type, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { /* Changing type when reading is not supported with adf files. In practice, we convert first and call cgio_read_data */ return set_error(CGIO_ERR_NOT_HDF5); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Read_Data(id, s_start, s_end, s_stride, m_data_type, m_num_dims, m_dims, m_start, m_end, m_stride, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*========================================================= * write nodes *=========================================================*/ int cgio_set_name (int cgio_num, double pid, double id, const char *name) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Put_Name(pid, id, name, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Put_Name(pid, id, name, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_set_label (int cgio_num, double id, const char *label) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Set_Label(id, label, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Set_Label(id, label, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_set_dimensions (int cgio_num, double id, const char *data_type, int num_dims, const cgsize_t *dims) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Put_Dimension_Information(id, data_type, num_dims, dims, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Put_Dimension_Information(id, data_type, num_dims, dims, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_write_all_data (int cgio_num, double id, const void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Write_All_Data(id, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Write_All_Data(id, NULL, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_write_all_data_type (int cgio_num, double id, const char *m_data_type, const void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { /* Changing type when writing is not supported with adf files. In practice, we convert first and call cgio_write_all_data */ return set_error(CGIO_ERR_NOT_HDF5); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Write_All_Data(id, m_data_type, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_write_block_data (int cgio_num, double id, cgsize_t b_start, cgsize_t b_end, void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 0)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Write_Block_Data(id, b_start, b_end, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Write_Block_Data(id, b_start, b_end, (char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_write_data (int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, const void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { ADF_Write_Data(id, s_start, s_end, s_stride, m_num_dims, m_dims, m_start, m_end, m_stride, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Write_Data(id, s_start, s_end, s_stride, NULL, m_num_dims, m_dims, m_start, m_end, m_stride, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } /*---------------------------------------------------------*/ int cgio_write_data_type (int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, const char *m_data_type, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, const void *data) { int ierr; cgns_io *cgio; if ((cgio = get_cgnsio(cgio_num, 1)) == NULL) return get_error(); if (cgio->type == CGIO_FILE_ADF || cgio->type == CGIO_FILE_ADF2) { /* Changing type when writing is not supported with adf files. In practice, we convert first and call cgio_write_data */ return set_error(CGIO_ERR_NOT_HDF5); } #ifdef BUILD_HDF5 else if (cgio->type == CGIO_FILE_HDF5) { ADFH_Write_Data(id, s_start, s_end, s_stride, m_data_type, m_num_dims, m_dims, m_start, m_end, m_stride, (const char *)data, &ierr); if (ierr > 0) return set_error(ierr); } #endif else { return set_error(CGIO_ERR_FILE_TYPE); } return CGIO_ERR_NONE; } CGNS-3.4.0/src/cgns_io.h000066400000000000000000000232511343724673500146520ustar00rootroot00000000000000/* ------------------------------------------------------------------------- * * CGNS - CFD General Notation System (http://www.cgns.org) * * CGNS/MLL - Mid-Level Library header file * * Please see cgnsconfig.h file for this local installation configuration * * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. * ------------------------------------------------------------------------- */ #ifndef CGNS_IO_H #define CGNS_IO_H #include "cgnstypes.h" #if defined(_WIN32) && defined(BUILD_DLL) # define CGEXTERN extern __declspec(dllexport) #else # define CGEXTERN extern #endif /* these should be the same as in cgnslib.h but are included here for completeness */ #define CGIO_MODE_READ 0 #define CGIO_MODE_WRITE 1 #define CGIO_MODE_MODIFY 2 #define CGIO_FILE_NONE 0 #define CGIO_FILE_ADF 1 #define CGIO_FILE_HDF5 2 #define CGIO_FILE_ADF2 3 /* currently these are the same as for ADF */ #define CGIO_MAX_DATATYPE_LENGTH 2 #define CGIO_MAX_DIMENSIONS 12 #define CGIO_MAX_NAME_LENGTH 32 #define CGIO_MAX_LABEL_LENGTH 32 #define CGIO_MAX_VERSION_LENGTH 32 #define CGIO_MAX_DATE_LENGTH 32 #define CGIO_MAX_ERROR_LENGTH 80 #define CGIO_MAX_LINK_DEPTH 100 #define CGIO_MAX_FILE_LENGTH 1024 #define CGIO_MAX_LINK_LENGTH 4096 /* these are the cgio error codes */ #define CGIO_ERR_NONE 0 #define CGIO_ERR_BAD_CGIO -1 #define CGIO_ERR_MALLOC -2 #define CGIO_ERR_FILE_MODE -3 #define CGIO_ERR_FILE_TYPE -4 #define CGIO_ERR_NULL_FILE -5 #define CGIO_ERR_TOO_SMALL -6 #define CGIO_ERR_NOT_FOUND -7 #define CGIO_ERR_NULL_PATH -8 #define CGIO_ERR_NO_MATCH -9 #define CGIO_ERR_FILE_OPEN -10 #define CGIO_ERR_READ_ONLY -11 #define CGIO_ERR_NULL_STRING -12 #define CGIO_ERR_BAD_OPTION -13 #define CGIO_ERR_FILE_RENAME -14 #define CGIO_ERR_TOO_MANY -15 #define CGIO_ERR_DIMENSIONS -16 #define CGIO_ERR_BAD_TYPE -17 #define CGIO_ERR_NOT_HDF5 -18 #ifdef __cplusplus extern "C" { #endif /*---------------------------------------------------------*/ CGEXTERN int cgio_path_add ( const char *path ); CGEXTERN int cgio_path_delete ( const char *path ); CGEXTERN int cgio_find_file ( const char *parentfile, const char *filename, int file_type, int max_path_len, char *pathname ); /*---------------------------------------------------------*/ CGEXTERN int cgio_is_supported ( int file_type ); CGEXTERN int cgio_configure ( int what, void *value ); CGEXTERN void cgio_cleanup (); CGEXTERN int cgio_check_file ( const char *filename, int *file_type ); CGEXTERN int cgio_compute_data_size ( const char *data_type, int num_dims, const cgsize_t *dim_vals, cglong_t *count ); CGEXTERN int cgio_check_dimensions ( int ndims, const cglong_t *dims ); CGEXTERN int cgio_copy_dimensions ( int ndims, const cglong_t *dims64, cgsize_t *dims ); /*---------------------------------------------------------*/ CGEXTERN int cgio_open_file ( const char *filename, int file_mode, int file_type, int *cgio_num ); CGEXTERN int cgio_close_file ( int cgio_num ); CGEXTERN int cgio_compress_file ( int cgio_num, const char *filename ); CGEXTERN int cgio_copy_file ( int cgio_num_inp, int cgio_num_out, int follow_links ); CGEXTERN int cgio_flush_to_disk ( int cgio_num ); /*---------------------------------------------------------*/ CGEXTERN int cgio_library_version ( int cgio_num, char *version ); CGEXTERN int cgio_file_version ( int cgio_num, char *file_version, char *creation_date, char *modified_date ); CGEXTERN int cgio_get_root_id ( int cgio_num, double *rootid ); CGEXTERN int cgio_get_file_type ( int cgio_num, int *file_type ); /*---------------------------------------------------------*/ CGEXTERN void cgio_error_code ( int *errcode, int *file_type ); CGEXTERN int cgio_error_message ( char *error_msg ); CGEXTERN void cgio_error_exit ( const char *msg ); CGEXTERN void cgio_error_abort ( int abort_flag ); /*---------------------------------------------------------*/ CGEXTERN int cgio_create_node ( int cgio_num, double pid, const char *name, double *id ); CGEXTERN int cgio_new_node ( int cgio_num, double pid, const char *name, const char *label, const char *data_type, int ndims, const cgsize_t *dims, const void *data, double *id ); CGEXTERN int cgio_delete_node ( int cgio_num, double pid, double id ); CGEXTERN int cgio_move_node ( int cgio_num, double pid, double id, double new_pid ); CGEXTERN int cgio_copy_node ( int cgio_num_inp, double id_inp, int cgio_num_out, double id_out ); CGEXTERN int cgio_release_id ( int cgio_num, double id ); /*---------------------------------------------------------*/ CGEXTERN int cgio_is_link ( int cgio_num, double id, int *link_len ); CGEXTERN int cgio_link_size ( int cgio_num, double id, int *file_len, int *name_len ); CGEXTERN int cgio_create_link ( int cgio_num, double pid, const char *name, const char *filename, const char *name_in_file, double *id ); CGEXTERN int cgio_get_link ( int cgio_num, double id, char *filename, char *name_in_file ); /*---------------------------------------------------------*/ CGEXTERN int cgio_number_children ( int cgio_num, double id, int *num_children ); CGEXTERN int cgio_children_ids ( int cgio_num, double pid, int start, int max_ret, int *num_ret, double *ids ); CGEXTERN int cgio_children_names ( int cgio_num, double pid, int start, int max_ret, int name_len, int *num_ret, char *names ); /*---------------------------------------------------------*/ CGEXTERN int cgio_get_node_id ( int cgio_num, double pid, const char *name, double *id ); CGEXTERN int cgio_get_name ( int cgio_num, double id, char *name ); CGEXTERN int cgio_get_label ( int cgio_num, double id, char *label ); CGEXTERN int cgio_get_data_type ( int cgio_num, double id, char *data_type ); CGEXTERN int cgio_get_data_size ( int cgio_num, double id, cglong_t *data_size ); CGEXTERN int cgio_get_dimensions ( int cgio_num, double id, int *num_dims, cgsize_t *dims ); CGEXTERN int cgio_read_all_data ( int cgio_num, double id, void *data ); CGEXTERN int cgio_read_all_data_type ( int cgio_num, double id, const char *m_data_type, void *data ); CGEXTERN int cgio_read_block_data ( int cgio_num, double id, cgsize_t b_start, cgsize_t b_end, void *data ); CGEXTERN int cgio_read_data ( int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, void *data ); CGEXTERN int cgio_read_data_type ( int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, const char *m_data_type, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, void *data ); /*---------------------------------------------------------*/ CGEXTERN int cgio_set_name ( int cgio_num, double pid, double id, const char *name ); CGEXTERN int cgio_set_label ( int cgio_num, double id, const char *label ); CGEXTERN int cgio_set_dimensions ( int cgio_num, double id, const char *data_type, int num_dims, const cgsize_t *dims ); CGEXTERN int cgio_write_all_data ( int cgio_num, double id, const void *data ); CGEXTERN int cgio_write_all_data_type ( int cgio_num, double id, const char *m_data_type, const void *data ); CGEXTERN int cgio_write_block_data ( int cgio_num, double id, cgsize_t b_start, cgsize_t b_end, void *data ); CGEXTERN int cgio_write_data ( int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, const void *data ); CGEXTERN int cgio_write_data_type ( int cgio_num, double id, const cgsize_t *s_start, const cgsize_t *s_end, const cgsize_t *s_stride, const char *m_data_type, int m_num_dims, const cgsize_t *m_dims, const cgsize_t *m_start, const cgsize_t *m_end, const cgsize_t *m_stride, const void *data ); #ifdef __cplusplus } #endif #undef CGEXTERN #endif CGNS-3.4.0/src/cgns_io_f.h000066400000000000000000000051241343724673500151560ustar00rootroot00000000000000c * ------------------------------------------------------------------------- * c * CGNS - CFD General Notation System (http://www.cgns.org) * c * CGNS/MLL - Mid-Level Library header file * c * Please see cgnsconfig.h file for this local installation configuration * c * ------------------------------------------------------------------------- * c c * ------------------------------------------------------------------------- * c c This software is provided 'as-is', without any express or implied warranty. c In no event will the authors be held liable for any damages arising from c the use of this software. c c Permission is granted to anyone to use this software for any purpose, c including commercial applications, and to alter it and redistribute it c freely, subject to the following restrictions: c c 1. The origin of this software must not be misrepresented; you must not c claim that you wrote the original software. If you use this software c in a product, an acknowledgment in the product documentation would be c appreciated but is not required. c c 2. Altered source versions must be plainly marked as such, and must not c be misrepresented as being the original software. c c 3. This notice may not be removed or altered from any source distribution. c c * ------------------------------------------------------------------------- * c c c file open modes c integer CGIO_MODE_READ, CGIO_MODE_WRITE, CGIO_MODE_MODIFY parameter (CGIO_MODE_READ = 0) parameter (CGIO_MODE_WRITE = 1) parameter (CGIO_MODE_MODIFY = 2) c c database file types c integer CGIO_FILE_NONE, CGIO_FILE_ADF, CGIO_FILE_HDF5, & CGIO_FILE_ADF2 parameter (CGIO_FILE_NONE = 0) parameter (CGIO_FILE_ADF = 1) parameter (CGIO_FILE_HDF5 = 2) parameter (CGIO_FILE_ADF2 = 3) c c dimension limits c integer CGIO_MAX_DATATYPE_LENGTH, CGIO_MAX_DIMENSIONS, & CGIO_MAX_NAME_LENGTH, CGIO_MAX_LABEL_LENGTH, & CGIO_MAX_VERSION_LENGTH, CGIO_MAX_ERROR_LENGTH, & CGIO_MAX_LINK_DEPTH, CGIO_MAX_FILE_LENGTH, & CGIO_MAX_LINK_LENGTH parameter (CGIO_MAX_DATATYPE_LENGTH = 2) parameter (CGIO_MAX_DIMENSIONS = 12) parameter (CGIO_MAX_NAME_LENGTH = 32) parameter (CGIO_MAX_LABEL_LENGTH = 32) parameter (CGIO_MAX_VERSION_LENGTH = 32) parameter (CGIO_MAX_ERROR_LENGTH = 80) parameter (CGIO_MAX_LINK_DEPTH = 100) parameter (CGIO_MAX_FILE_LENGTH = 1024) parameter (CGIO_MAX_LINK_LENGTH = 4096) CGNS-3.4.0/src/cgnsconfig.h.in000066400000000000000000000046151343724673500157610ustar00rootroot00000000000000/* ------------------------------------------------------------------------- * * CGNS - CFD General Notation System (http://www.cgns.org) * * CGNS/MLL - Mid-Level Library header file * * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This file has been generated during the CGNS/MLL installation. This is a snapshot of the parameters used for CGNS/MLL production and some PATHS parameters (headers or shared libs) may change or disappear (for example in case of cross-compilation). * ------------------------------------------------------------------------- */ #ifndef CGNSCONFIG_H #define CGNSCONFIG_H #define CG_BUILD_HDF5 @BUILDHDF5@ #define CG_BUILD_DEBUG @BUILDDEBUG@ #define CG_BUILD_FORTRAN @BUILDFORTRAN@ #define CG_BUILD_PARALLEL @BUILDPARALLEL@ #define CG_BUILD_BASESCOPE @BUILDBASESCOPE@ #define HDF5_INCLUDE_PATH "@HDF5INC@" #define HDF5_LIBRARY "@HDF5LIB@" #define HDF5_NEED_MPI @H5NEEDMPI@ #define HDF5_NEED_SZIP @H5NEEDSZIP@ #define HDF5_NEED_ZLIB @H5NEEDZLIB@ #define MPI_INCLUDE_PATH "@MPIINC@" #define MPI_LIBRARY "@MPILIBS@" #define SZIP_LIBRARY "@SZIPLIB@" #define ZLIB_LIBRARY "@ZLIBLIB@" #define MPI_INC "@MPIINC@" #define MPI_LIBS "@MPILIBS@" #include "cgnstypes.h" #endif CGNS-3.4.0/src/cgnslib.c000066400000000000000000015336531343724673500146620ustar00rootroot00000000000000/*------------------------------------------------------------------------- This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------*/ /*********************************************************************** * Revisions: * ***********************************************************************/ #include #include #include #include #include #include #include #include #if defined(_WIN32) && !defined(__NUTC__) # include /* suggested by MTI */ # ifndef F_OK # define R_OK 004 /* Test for Read permission */ # define W_OK 002 /* Test for Write permission */ # define X_OK 001 /* Test for eXecute permission */ # define F_OK 000 /* Test for existence of File */ # endif # define ACCESS _access # define UNLINK _unlink #else # include # define ACCESS access # define UNLINK unlink #endif #include "cgnslib.h" #include "cgns_header.h" #include "cgns_io.h" /* to determine default file type */ #ifdef BUILD_HDF5 # include "hdf5.h" #endif /* fix for unresolved reference to __ftol2 when using VC7 with VC6 libs */ /* see http://www.manusoft.com/Resources/ARXTips/Main.stm */ #ifdef NEED_FTOL2 #ifdef __cplusplus extern "C" { #endif long _ftol(double); long _ftol2(double dValue) {return _ftol(dValue);} #ifdef __cplusplus } #endif #endif #ifdef MEM_DEBUG #include "cg_malloc.h" #endif #define IS_FIXED_SIZE(type) ((type >= CGNS_ENUMV(NODE) && \ type <= CGNS_ENUMV(HEXA_27)) || \ type == CGNS_ENUMV(PYRA_13) || \ (type >= CGNS_ENUMV(BAR_4) && \ type <= CGNS_ENUMV(HEXA_125))) #define CHECK_FILE_OPEN if (cg == NULL) {\ cgi_error("no current CGNS file open");\ return CG_ERROR;\ } /*********************************************************************** * external variable declarations ***********************************************************************/ cgns_file *cgns_files = NULL; cgns_file *cg = NULL; int n_cgns_files = 0; cgns_posit *posit = 0; int posit_file, posit_base, posit_zone; int CGNSLibVersion=CGNS_VERSION;/* Version of the CGNSLibrary*1000 */ int cgns_compress = 0; int cgns_filetype = CG_FILE_NONE; void* cgns_rindindex = CG_CONFIG_RIND_CORE; extern void (*cgns_error_handler)(int, char *); /*********************************************************************** * Name strings ***********************************************************************/ const char * MassUnitsName[NofValidMassUnits] = {"Null", "UserDefined", "Kilogram", "Gram", "Slug", "PoundMass" }; const char * LengthUnitsName[NofValidLengthUnits] = {"Null", "UserDefined", "Meter", "Centimeter", "Millimeter", "Foot", "Inch" }; const char * TimeUnitsName[NofValidTimeUnits] = {"Null", "UserDefined", "Second" }; const char * TemperatureUnitsName[NofValidTemperatureUnits] = {"Null", "UserDefined", "Kelvin", "Celsius", "Rankine", "Fahrenheit" }; const char * AngleUnitsName[NofValidAngleUnits] = {"Null", "UserDefined", "Degree", "Radian" }; const char * ElectricCurrentUnitsName[NofValidElectricCurrentUnits] = {"Null", "UserDefined", "Ampere", "Abampere", "Statampere", "Edison", "a.u." }; const char * SubstanceAmountUnitsName[NofValidSubstanceAmountUnits] = {"Null", "UserDefined", "Mole", "Entities", "StandardCubicFoot", "StandardCubicMeter" }; const char * LuminousIntensityUnitsName[NofValidLuminousIntensityUnits] = {"Null", "UserDefined", "Candela", "Candle", "Carcel", "Hefner", "Violle" }; const char * DataClassName[NofValidDataClass] = {"Null", "UserDefined", "Dimensional", "NormalizedByDimensional", "NormalizedByUnknownDimensional", "NondimensionalParameter", "DimensionlessConstant" }; const char * GridLocationName[NofValidGridLocation] = {"Null", "UserDefined", "Vertex", "CellCenter", "FaceCenter", "IFaceCenter", "JFaceCenter", "KFaceCenter", "EdgeCenter" }; const char * BCDataTypeName[NofValidBCDataTypes] = {"Null", "UserDefined", "Dirichlet", "Neumann" }; const char * GridConnectivityTypeName[NofValidGridConnectivityTypes] = {"Null", "UserDefined", "Overset", "Abutting", "Abutting1to1" }; const char * PointSetTypeName[NofValidPointSetTypes] = {"Null", "UserDefined", "PointList", "PointListDonor", "PointRange", "PointRangeDonor", "ElementRange", "ElementList", "CellListDonor" }; const char * GoverningEquationsTypeName[NofValidGoverningEquationsTypes]= {"Null", "UserDefined", "FullPotential", "Euler", "NSLaminar", "NSTurbulent", "NSLaminarIncompressible", "NSTurbulentIncompressible" }; const char * ModelTypeName[NofValidModelTypes]= {"Null", "UserDefined", "Ideal", "VanderWaals", "Constant", "PowerLaw", "SutherlandLaw", "ConstantPrandtl", "EddyViscosity", "ReynoldsStress", "ReynoldsStressAlgebraic", "Algebraic_BaldwinLomax", "Algebraic_CebeciSmith", "HalfEquation_JohnsonKing", "OneEquation_BaldwinBarth", "OneEquation_SpalartAllmaras", "TwoEquation_JonesLaunder", "TwoEquation_MenterSST", "TwoEquation_Wilcox", "CaloricallyPerfect", "ThermallyPerfect", "ConstantDensity", "RedlichKwong", "Frozen", "ThermalEquilib", "ThermalNonequilib", "ChemicalEquilibCurveFit", "ChemicalEquilibMinimization", "ChemicalNonequilib", "EMElectricField", "EMMagneticField", "EMConductivity", "Voltage", "Interpolated", "Equilibrium_LinRessler", "Chemistry_LinRessler" }; const char * BCTypeName[NofValidBCTypes] = {"Null", "UserDefined", "BCAxisymmetricWedge", "BCDegenerateLine", "BCDegeneratePoint", "BCDirichlet", "BCExtrapolate", "BCFarfield", "BCGeneral", "BCInflow", "BCInflowSubsonic", "BCInflowSupersonic", "BCNeumann", "BCOutflow", "BCOutflowSubsonic", "BCOutflowSupersonic", "BCSymmetryPlane", "BCSymmetryPolar", "BCTunnelInflow", "BCTunnelOutflow", "BCWall", "BCWallInviscid", "BCWallViscous", "BCWallViscousHeatFlux", "BCWallViscousIsothermal", "FamilySpecified" }; const char * DataTypeName[NofValidDataTypes] = {"Null", "UserDefined", "Integer", "RealSingle", "RealDouble", "Character", "LongInteger" }; const char * ElementTypeName[NofValidElementTypes] = {"Null", "UserDefined", "NODE", "BAR_2", "BAR_3", "TRI_3", "TRI_6", "QUAD_4", "QUAD_8", "QUAD_9", "TETRA_4", "TETRA_10", "PYRA_5", "PYRA_14", "PENTA_6", "PENTA_15", "PENTA_18", "HEXA_8", "HEXA_20", "HEXA_27", "MIXED", "PYRA_13", "NGON_n", "NFACE_n", "BAR_4", "TRI_9", "TRI_10", "QUAD_12", "QUAD_16", "TETRA_16", "TETRA_20", "PYRA_21", "PYRA_29", "PYRA_30", "PENTA_24", "PENTA_38", "PENTA_40", "HEXA_32", "HEXA_56", "HEXA_64", "BAR_5", "TRI_12", "TRI_15", "QUAD_P4_16", "QUAD_25", "TETRA_22", "TETRA_34", "TETRA_35", "PYRA_P4_29", "PYRA_50", "PYRA_55", "PENTA_33", "PENTA_66", "PENTA_75", "HEXA_44", "HEXA_98", "HEXA_125" }; const char * ZoneTypeName[NofValidZoneTypes] = {"Null", "UserDefined", "Structured", "Unstructured" }; const char * RigidGridMotionTypeName[NofValidRigidGridMotionTypes] = {"Null", "UserDefined", "ConstantRate", "VariableRate" }; const char * ArbitraryGridMotionTypeName[NofValidArbitraryGridMotionTypes] = {"Null", "UserDefined", "NonDeformingGrid", "DeformingGrid" }; const char * SimulationTypeName[NofValidSimulationTypes] = {"Null", "UserDefined", "TimeAccurate", "NonTimeAccurate" }; const char * WallFunctionTypeName[NofValidWallFunctionTypes] = {"Null", "UserDefined", "Generic" }; const char * AreaTypeName[NofValidAreaTypes] = {"Null", "UserDefined", "BleedArea", "CaptureArea" }; const char * AverageInterfaceTypeName[NofValidAverageInterfaceTypes] = {"Null", "UserDefined", "AverageAll", "AverageCircumferential", "AverageRadial", "AverageI", "AverageJ", "AverageK" }; /*********************************************************************** * global variable definitions ***********************************************************************/ int n_open = 0; int cgns_file_size = 0; int file_number_offset = 0; int VersionList[] = {3210, 3200, 3140, 3130, 3110, 3100, 3080, 3000, 2550, 2540, 2530, 2520, 2510, 2500, 2460, 2420, 2400, 2300, 2200, 2100, 2000, 1270, 1200, 1100, 1050}; #define nVersions (sizeof(VersionList)/sizeof(int)) #ifdef DEBUG_HDF5_OBJECTS_CLOSE void objlist_status(char *tag) { int n,sname; char oname[256]; hid_t o,idlist[1024]; H5O_info_t objinfo; n=H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ALL); printf("{%s} HDF5 OBJ COUNT [%d] \n",tag,n);fflush(stdout); n=H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_GROUP); printf("{%s} HDF5 GROUP [%d] \n",tag,n);fflush(stdout); n=H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATASET); printf("{%s} HDF5 DATASET [%d] \n",tag,n);fflush(stdout); n=H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATATYPE); printf("{%s} HDF5 DATATYPE [%d] \n",tag,n);fflush(stdout); n=H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ATTR); printf("{%s} HDF5 ATTR [%d] \n",tag,n);fflush(stdout); for (n=0;n<1024;n++) { idlist[n]=-1; } H5Fget_obj_ids(H5F_OBJ_ALL,H5F_OBJ_ALL,1024,idlist); for (n=0;n<1024;n++) { if (idlist[n]!=-1) { if (H5Iis_valid(idlist[n])) { printf("{%s} track %d INVALID\n",tag,idlist[n]); } else { H5Oget_info(idlist[n],&objinfo); memset(oname,'\0',256); sname=H5Iget_name(idlist[n],oname,0); sname=H5Iget_name(idlist[n],oname,sname+1); printf("{%s} track %d ALIVE (%s:%d)\n",tag,idlist[n],oname,objinfo.rc); } } } } #endif /*********************************************************************** * library functions ***********************************************************************/ /* check for a valid CGNS file */ int cg_is_cgns(const char *filename, int *file_type) { int cgio, ierr; double rootid, childid; *file_type = CG_FILE_NONE; if (cgio_open_file(filename, CG_MODE_READ, CG_FILE_NONE, &cgio)) return CG_ERROR; cgio_get_root_id(cgio, &rootid); cgio_get_file_type(cgio, file_type); ierr = cgio_get_node_id(cgio, rootid, "CGNSLibraryVersion", &childid); cgio_close_file(cgio); return ierr ? CG_ERROR : CG_OK; } /*********************************************************************** * cg_open(char *filename, int mode, int *file_number) * ***********************************************************************/ int cg_open(const char *filename, int mode, int *file_number) { int cgio, filetype; cgsize_t dim_vals; double dummy_id; float FileVersion; #ifdef __CG_MALLOC_H__ fprintf(stderr, "CGNS MEM_DEBUG: before open:files %d/%d: memory %d/%d: calls %d/%d\n", n_open, cgns_file_size, cgmemnow(), cgmemmax(), cgalloccalls(), cgfreecalls()); #endif /* check file mode */ switch(mode) { case CG_MODE_READ: case CG_MODE_MODIFY: if (ACCESS(filename, F_OK)) { cgi_error("Error opening file: '%s' not found!", filename); return CG_ERROR; } break; case CG_MODE_WRITE: /* unlink is now done in cgio_open_file */ break; default: cgi_error("Unknown opening file mode: %d ??",mode); return CG_ERROR; } /* set default file type if not done */ if (cgns_filetype == CG_FILE_NONE) cg_set_file_type(CG_FILE_NONE); /* Open CGNS file */ if (cgio_open_file(filename, mode, cgns_filetype, &cgio)) { cg_io_error("cgio_open_file"); return CG_ERROR; } n_open++; /* make sure there is enough space in the cgns_files array */ if (cgns_file_size == 0) { cgns_file_size = 1; cgns_files = CGNS_NEW(cgns_file,cgns_file_size); } else if (n_cgns_files == cgns_file_size) { cgns_file_size *= 2; cgns_files = CGNS_RENEW(cgns_file,cgns_file_size, cgns_files); } cg = &(cgns_files[n_cgns_files]); n_cgns_files++; (*file_number) = n_cgns_files + file_number_offset; if (cgio_get_file_type(cgio, &filetype)) { cg_io_error("cgio_get_file_type"); return CG_ERROR; } /* Keep in-memory copy of cgns file 'header' information */ cg->mode = mode; cg->filename = CGNS_NEW(char,strlen(filename) + 1); strcpy(cg->filename, filename); cg->filetype = filetype; cg->cgio = cgio; cgio_get_root_id(cgio, &cg->rootid); cg->file_number = (*file_number); cg->version = 0; cg->deleted = 0; cg->added = 0; /* CGNS-Library Version */ if (mode == CG_MODE_WRITE) { dim_vals = 1; /* FileVersion = (float) CGNS_DOTVERS; */ /* Jiao: Changed to use older compatible version */ if (filetype == CG_FILE_ADF2) { FileVersion = (float) CGNS_COMPATDOTVERS; cg->version = CGNS_COMPATVERSION; } else { FileVersion = (float) CGNS_DOTVERS; cg->version = CGNSLibVersion; } if (cgi_new_node(cg->rootid, "CGNSLibraryVersion", "CGNSLibraryVersion_t", &dummy_id, "R4", 1, &dim_vals, (void *)&FileVersion)) return CG_ERROR; } else { /* read file version from file and set cg->version = FileVersion*1000 */ if (cg_version(cg->file_number, &FileVersion)) return CG_ERROR; /* Check that the library version is at least as recent as the one used to create the file being read */ if (cg->version > CGNSLibVersion) { /* This code allows reading version newer than the lib, as long as the 1st digit of the versions are equal */ if ((cg->version / 1000) > (CGNSLibVersion / 1000)) { cgi_error("The file %s was written with a more recent version of the CGNS library. You must update your CGNS library before trying to read this file.",filename); return CG_ERROR; } /* warn only if different in second digit */ if ((cg->version / 100) > (CGNSLibVersion / 100)) { cgi_warning("The file being read is more recent that the CGNS library used"); } } #if CG_SIZEOF_SIZE == 32 if (mode == CG_MODE_MODIFY && cgns_filetype == CG_FILE_ADF2 && filetype == CG_FILE_ADF && cg->version < 3000) { filetype = cg->filetype = CG_FILE_ADF2; } #endif } /* Get ADF Database version & dates, and ADF Library version */ if (cgio_file_version(cg->cgio, cg->dtb_version, cg->creation_date, cg->modify_date)) { cg_io_error("cgio_file_version"); return CG_ERROR; } if (cgio_library_version(cg->cgio, cg->adf_lib_version)) { cg_io_error("cgio_library_version"); return CG_ERROR; } /* read CGNS file */ if (mode == CG_MODE_READ || mode == CG_MODE_MODIFY) { int nnod; double *id; if (cgi_read()) return CG_ERROR; /* update version number in modify mode */ if (cg->version < CGNSLibVersion && mode == CG_MODE_MODIFY && (cg->filetype != CG_FILE_ADF2 || cg->version < CGNS_COMPATVERSION)) { /* FileVersion = (float) CGNS_DOTVERS; */ /* Jiao: Changed to use older compatible version */ if (cg->filetype == CG_FILE_ADF2) { FileVersion = (float) CGNS_COMPATDOTVERS; cg->version = CGNS_COMPATVERSION; } else { FileVersion = (float) CGNS_DOTVERS; cg->version = CGNSLibVersion; } if (cgi_get_nodes(cg->rootid, "CGNSLibraryVersion_t", &nnod, &id)) return CG_ERROR; if (nnod) { if (cgio_write_all_data(cg->cgio, id[0], &FileVersion)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } free(id); } else { dim_vals = 1; if (cgi_new_node(cg->rootid, "CGNSLibraryVersion", "CGNSLibraryVersion_t", &dummy_id, "R4", 1, &dim_vals, (void *)&FileVersion)) return CG_ERROR; } } } else { cg->nbases=0; cg->base = 0; } #ifdef __CG_MALLOC_H__ fprintf(stderr, "CGNS MEM_DEBUG: after open:files %d/%d: memory %d/%d: calls %d/%d\n", n_open, cgns_file_size, cgmemnow(), cgmemmax(), cgalloccalls(), cgfreecalls()); #endif return CG_OK; } int cg_version(int file_number, float *FileVersion) { int nnod; double *id; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* if open in CG_MODE_WRITE */ if (cg->version) { (*FileVersion)=(float)(cg->version)/1000; return CG_OK; } /* if open in MODE_READ or MODE_MODIFY */ /* get number of CGNSLibraryVersion_t nodes and their ID */ if (cgi_get_nodes(cg->rootid, "CGNSLibraryVersion_t", &nnod, &id)) return CG_ERROR; if (nnod==0) { cg->version=1050; *FileVersion= (float) 1.05; } else if (nnod!=1) { cgi_error("More then one CGNSLibraryVersion_t node found under ROOT."); return CG_ERROR; } else { int vers, ndim, temp_version; cgsize_t dim_vals[12]; char_33 node_name; char_33 data_type; void *data; if (cgi_read_node(id[0], node_name, data_type, &ndim, dim_vals, &data, 1)) { cgi_error("Error reading CGNS-Library-Version"); return CG_ERROR; } /* check data type */ if (strcmp(data_type,"R4")!=0) { cgi_error("Unexpected data type for CGNS-Library-Version='%s'",data_type); return CG_ERROR; } /* check data dim */ if (ndim != 1 || (dim_vals[0]!=1)) { cgi_error("Wrong data dimension for CGNS-Library-Version"); return CG_ERROR; } /* save data */ *FileVersion = *((float *)data); free(data); cg->version = (int)(1000.0*(*FileVersion)+0.5); /* To prevent round off error in version number for file of older or current version */ temp_version = cg->version; /* cg->version = 0; Commented for fwd compatibility */ for (vers=0; vers (VersionList[vers]-2) && temp_version < (VersionList[vers]+2)) { cg->version = VersionList[vers]; break; } } if (cg->version == 0) { cgi_error("Error: Unable to determine the version number"); return CG_ERROR; } free(id); } #if DEBUG_VERSION printf("FileVersion=%f\n",*FileVersion); printf("cg->version=%d\n",cg->version); #endif return CG_OK; } int cg_precision(int file_number, int *precision) { int nb, nz; char_33 data_type; *precision = 0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* if open in CG_MODE_WRITE */ if (cg->mode == CG_MODE_WRITE) { *precision = CG_SIZEOF_SIZE; return CG_OK; } for (nb = 0; nb < cg->nbases; nb++) { for (nz = 0; nz < cg->base[nb].nzones; nz++) { if (0 == cgio_get_data_type (cg->cgio, cg->base[nb].zone[nz].id, data_type) && 0 == strcmp (data_type, "I8")) { *precision = 64; return CG_OK; } } } *precision = 32; return CG_OK; } int cg_close(int file_number) { cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; #ifdef __CG_MALLOC_H__ fprintf(stderr, "CGNS MEM_DEBUG: before close:files %d/%d: memory %d/%d: calls %d/%d\n", n_open, cgns_file_size, cgmemnow(), cgmemmax(), cgalloccalls(), cgfreecalls()); #endif if (cgns_compress && cg->mode == CG_MODE_MODIFY && (cg->deleted >= cgns_compress || cgns_compress < 0)) { if (cgio_compress_file (cg->cgio, cg->filename)) { cg_io_error("cgio_compress_file"); return CG_ERROR; } } else { if (cgio_close_file(cg->cgio)) { cg_io_error("cgio_close_file"); return CG_ERROR; } } n_open--; /* Free the in-memory copy of the CGNS file */ cgi_free_file(cg); cg->mode = CG_MODE_CLOSED; /* if all files are closed, free up memory */ if (n_open == 0) { file_number_offset = n_cgns_files; free (cgns_files); cg = NULL; cgns_files = NULL; cgns_file_size = 0; n_cgns_files = 0; } #ifdef __CG_MALLOC_H__ fprintf(stderr, "CGNS MEM_DEBUG: after close:files %d/%d: memory %d/%d: calls %d/%d\n", n_open, cgns_file_size, cgmemnow(), cgmemmax(), cgalloccalls(), cgfreecalls()); #endif #ifdef DEBUG_HDF5_OBJECTS_CLOSE objlist_status("close"); #endif return CG_OK; } int cg_save_as(int file_number, const char *filename, int file_type, int follow_links) { int output; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (file_type == CG_FILE_NONE) file_type = cgns_filetype; if (cgio_is_supported(file_type)) { cgi_error("file type unknown or not supported"); return CG_ERROR; } if (cgio_open_file(filename, CG_MODE_WRITE, file_type, &output)) { cg_io_error ("cgio_open_file"); return CG_ERROR; } if (cgio_copy_file(cg->cgio, output, follow_links)) { cg_io_error("cgio_copy_file"); return CG_ERROR; } if (cgio_close_file(output)) { cg_io_error("cgio_close_file"); return CG_ERROR; } return CG_OK; } int cg_set_file_type(int file_type) { if (file_type == CG_FILE_NONE) { char *type = getenv("CGNS_FILETYPE"); if (type == NULL || !*type) { #if defined(BUILD_HDF5) cgns_filetype = CG_FILE_HDF5; #else cgns_filetype = CG_FILE_ADF; #endif } #ifdef BUILD_HDF5 else if (*type == '2' || *type == 'h' || *type == 'H') { cgns_filetype = CG_FILE_HDF5; } #endif else if (*type == '3' || ((*type == 'a' || *type == 'A') && strchr(type, '2') != NULL)) { #if CG_SIZEOF_SIZE == 64 cgi_error("ADF2 not supported in 64-bit mode"); return CG_ERROR; #else cgns_filetype = CG_FILE_ADF2; #endif } else cgns_filetype = CG_FILE_ADF; } else { if (cgio_is_supported(file_type)) { cgi_error("file type unknown or not supported"); return CG_ERROR; } cgns_filetype = file_type; } return CG_OK; } int cg_get_file_type(int file_number, int *file_type) { cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgio_get_file_type(cg->cgio, file_type)) { cg_io_error("cgio_get_file_type"); return CG_ERROR; } return CG_OK; } int cg_root_id(int file_number, double *root_id) { cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgio_get_root_id(cg->cgio, root_id)) { cg_io_error("cgio_get_root_id"); return CG_ERROR; } return CG_OK; } int cg_get_cgio(int file_number, int *cgio_num) { cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; *cgio_num = cg->cgio; return CG_OK; } /* configure stuff */ int cg_configure(int what, void *value) { /* cgio options */ if (what > 100) { if (cgio_configure(what, value)) { cg_io_error("cgio_configure"); return CG_ERROR; } } /* error message handler */ else if (what == CG_CONFIG_ERROR) { cgns_error_handler = (void (*)(int, char *))value; } /* file compression */ else if (what == CG_CONFIG_COMPRESS) { cgns_compress = (int)((size_t)value); } /* initialize link search path */ else if (what == CG_CONFIG_SET_PATH) { return cg_set_path((const char *)value); } /* add to link search path */ else if (what == CG_CONFIG_ADD_PATH) { return cg_set_path((const char *)value); } /* default file type */ else if (what == CG_CONFIG_FILE_TYPE) { return cg_set_file_type((int)((size_t)value)); } /* allow pre v3.4 rind-plane indexing */ else if (what == CG_CONFIG_RIND_INDEX) { if (value != CG_CONFIG_RIND_ZERO && value != CG_CONFIG_RIND_CORE) { cgi_error("unknown config setting"); return CG_ERROR; } cgns_rindindex = value; } else { cgi_error("unknown config setting"); return CG_ERROR; } return CG_OK; } int cg_error_handler(void (*func)(int, char *)) { cgns_error_handler = func; return CG_OK; } int cg_set_compress(int compress) { cgns_compress = compress; return CG_OK; } int cg_get_compress(int *compress) { *compress = cgns_compress; return CG_OK; } int cg_set_path(const char *path) { cgio_path_delete(NULL); if (path && *path) { if (cgio_path_add(path)) { cg_io_error("cgio_path_add"); return CG_ERROR; } } return CG_OK; } int cg_add_path(const char *path) { if (cgio_path_add(path)) { cg_io_error("cgio_path_add"); return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * utility functions \*****************************************************************************/ /* get type name with bounds checking */ const char *cg_get_name(int nnames, const char **names, int type) { if (type < 0 || type >= nnames) return ""; return names[type]; } const char *cg_MassUnitsName(CGNS_ENUMT( MassUnits_t ) type) { return cg_get_name(NofValidMassUnits,MassUnitsName,(int)type); } const char *cg_LengthUnitsName(CGNS_ENUMT( LengthUnits_t ) type) { return cg_get_name(NofValidLengthUnits,LengthUnitsName,(int)type); } const char *cg_TimeUnitsName(CGNS_ENUMT( TimeUnits_t ) type) { return cg_get_name(NofValidTimeUnits,TimeUnitsName,(int)type); } const char *cg_TemperatureUnitsName(CGNS_ENUMT( TemperatureUnits_t ) type) { return cg_get_name(NofValidTemperatureUnits,TemperatureUnitsName,(int)type); } const char *cg_AngleUnitsName(CGNS_ENUMT( AngleUnits_t ) type) { return cg_get_name(NofValidAngleUnits,AngleUnitsName,(int)type); } const char *cg_ElectricCurrentUnitsName(CGNS_ENUMT( ElectricCurrentUnits_t ) type) { return cg_get_name(NofValidElectricCurrentUnits,ElectricCurrentUnitsName,(int)type); } const char *cg_SubstanceAmountUnitsName(CGNS_ENUMT( SubstanceAmountUnits_t ) type) { return cg_get_name(NofValidSubstanceAmountUnits,SubstanceAmountUnitsName,(int)type); } const char *cg_LuminousIntensityUnitsName(CGNS_ENUMT( LuminousIntensityUnits_t ) type) { return cg_get_name(NofValidLuminousIntensityUnits,LuminousIntensityUnitsName,(int)type); } const char *cg_DataClassName(CGNS_ENUMT( DataClass_t ) type) { return cg_get_name(NofValidDataClass,DataClassName,(int)type); } const char *cg_GridLocationName(CGNS_ENUMT( GridLocation_t ) type) { return cg_get_name(NofValidGridLocation,GridLocationName,(int)type); } const char *cg_BCDataTypeName(CGNS_ENUMT( BCDataType_t ) type) { return cg_get_name(NofValidBCDataTypes,BCDataTypeName,(int)type); } const char *cg_GridConnectivityTypeName(CGNS_ENUMT( GridConnectivityType_t ) type) { return cg_get_name(NofValidGridConnectivityTypes,GridConnectivityTypeName,(int)type); } const char *cg_PointSetTypeName(CGNS_ENUMT( PointSetType_t ) type) { return cg_get_name(NofValidPointSetTypes,PointSetTypeName,(int)type); } const char *cg_GoverningEquationsTypeName(CGNS_ENUMT( GoverningEquationsType_t ) type) { return cg_get_name(NofValidGoverningEquationsTypes,GoverningEquationsTypeName,(int)type); } const char *cg_ModelTypeName(CGNS_ENUMT( ModelType_t ) type) { return cg_get_name(NofValidModelTypes,ModelTypeName,(int)type); } const char *cg_BCTypeName(CGNS_ENUMT( BCType_t ) type) { return cg_get_name(NofValidBCTypes,BCTypeName,(int)type); } const char *cg_DataTypeName(CGNS_ENUMT( DataType_t ) type) { return cg_get_name(NofValidDataTypes,DataTypeName,(int)type); } const char *cg_ElementTypeName(CGNS_ENUMT( ElementType_t ) type) { return cg_get_name(NofValidElementTypes,ElementTypeName,(int)type); } const char *cg_ZoneTypeName(CGNS_ENUMT( ZoneType_t ) type) { return cg_get_name(NofValidZoneTypes,ZoneTypeName,(int)type); } const char *cg_RigidGridMotionTypeName(CGNS_ENUMT( RigidGridMotionType_t ) type) { return cg_get_name(NofValidRigidGridMotionTypes,RigidGridMotionTypeName,(int)type); } const char *cg_ArbitraryGridMotionTypeName(CGNS_ENUMT( ArbitraryGridMotionType_t ) type) { return cg_get_name(NofValidArbitraryGridMotionTypes,ArbitraryGridMotionTypeName,(int)type); } const char *cg_SimulationTypeName(CGNS_ENUMT( SimulationType_t ) type) { return cg_get_name(NofValidSimulationTypes,SimulationTypeName,(int)type); } const char *cg_WallFunctionTypeName(CGNS_ENUMT( WallFunctionType_t ) type) { return cg_get_name(NofValidWallFunctionTypes,WallFunctionTypeName,(int)type); } const char *cg_AreaTypeName(CGNS_ENUMT( AreaType_t ) type) { return cg_get_name(NofValidAreaTypes,AreaTypeName,(int)type); } const char *cg_AverageInterfaceTypeName(CGNS_ENUMT( AverageInterfaceType_t ) type) { return cg_get_name(NofValidAverageInterfaceTypes,AverageInterfaceTypeName,(int)type); } /*****************************************************************************\ * Read and Write CGNSBase_t Nodes \*****************************************************************************/ int cg_nbases(int file_number, int *nbases) { cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; *nbases = cg->nbases; return CG_OK; } int cg_base_read(int file_number, int B, char *basename, int *cell_dim, int *phys_dim) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *cell_dim = base->cell_dim; *phys_dim = base->phys_dim; strcpy(basename, base->name); return CG_OK; } int cg_base_id(int file_number, int B, double *base_id) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *base_id = base->id; return CG_OK; } int cg_cell_dim(int file_number, int B, int *cell_dim) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *cell_dim = base->cell_dim; return CG_OK; } int cg_base_write(int file_number, const char * basename, int cell_dim, int phys_dim, int *B) { cgns_base *base = NULL; int index; cgsize_t dim_vals; int data[2]; /* verify input */ if (cgi_check_strlen(basename)) return CG_ERROR; if (cell_dim<1 || cell_dim>3 || phys_dim<1 || phys_dim>3) { cgi_error("Invalid input: cell_dim=%d, phys_dim=%d",cell_dim,phys_dim); return CG_ERROR; } /* get memory address for base */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* Overwrite a CGNSBase_t Node: */ for (index=0; indexnbases; index++) { if (strcmp(basename, cg->base[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",basename); return CG_ERROR; } /* overwrite an existing base */ /* delete the existing base from file */ if (cgi_delete_node(cg->rootid, cg->base[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ base = &(cg->base[index]); /* free memory */ cgi_free_base(base); break; } } /* ... or add a CGNSBase_t Node: */ if (index==cg->nbases) { if (cg->nbases == 0) { cg->base = CGNS_NEW(cgns_base, cg->nbases+1); } else { cg->base = CGNS_RENEW(cgns_base, cg->nbases+1, cg->base); } base = &(cg->base[cg->nbases]); cg->nbases ++; } (*B) = index+1; /* save data in memory and initialize base data structure */ memset(base, 0, sizeof(cgns_base)); strcpy(base->name, basename); base->cell_dim = cell_dim; base->phys_dim = phys_dim; /* save data in file */ data[0] = cell_dim; data[1] = phys_dim; dim_vals=2; if (cgi_new_node(cg->rootid, base->name, "CGNSBase_t", &base->id, "I4", 1, &dim_vals, (void *)data)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and Write Zone_t Nodes \*****************************************************************************/ int cg_nzones(int file_number, int B, int *nzones) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *nzones = base->nzones; return CG_OK; } int cg_zone_type(int file_number, int B, int Z, CGNS_ENUMT(ZoneType_t) *type) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *type = zone->type; return CG_OK; } int cg_zone_read(int file_number, int B, int Z, char *zonename, cgsize_t *nijk) { cgns_zone *zone; int i; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; strcpy(zonename, zone->name); for (i=0; i<3*(zone->index_dim); i++) nijk[i] = zone->nijk[i]; return CG_OK; } int cg_zone_id(int file_number, int B, int Z, double *zone_id) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *zone_id = zone->id; return CG_OK; } int cg_index_dim(int file_number, int B, int Z, int *index_dim) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *index_dim = zone->index_dim; return CG_OK; } int cg_zone_write(int file_number, int B, const char *zonename, const cgsize_t * nijk, CGNS_ENUMT( ZoneType_t ) type, int *Z) { cgns_base *base; cgns_zone *zone = NULL; int index, i, index_dim; cgsize_t dim_vals[2]; double dummy_id; /* verify input */ if (cgi_check_strlen(zonename)) return CG_ERROR; /* get memory address file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* Set index dimension */ if (type == CGNS_ENUMV( Structured )) index_dim = base->cell_dim; else if (type == CGNS_ENUMV( Unstructured )) index_dim = 1; else { cgi_error("Invalid zone type - not Structured or Unstructured"); return CG_ERROR; } for (i=0; inzones; index++) { if (strcmp(zonename, base->zone[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",zonename); return CG_ERROR; } /* overwrite an existing zone */ /* delete the existing zone from file */ if (cgi_delete_node(base->id, base->zone[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ zone = &(base->zone[index]); /* free memory */ cgi_free_zone(zone); break; } } /* ... or add a Zone_t Node: */ if (index==base->nzones) { if (base->nzones == 0) { base->zone = CGNS_NEW(cgns_zone, base->nzones+1); } else { base->zone = CGNS_RENEW(cgns_zone, base->nzones+1, base->zone); } zone = &(base->zone[base->nzones]); base->nzones++; } (*Z) = index+1; /* save data to zone */ memset(zone, 0, sizeof(cgns_zone)); strcpy(zone->name,zonename); if ((zone->nijk = (cgsize_t *)malloc((size_t)(index_dim*3*sizeof(cgsize_t))))==NULL) { cgi_error("Error allocating zone->nijk"); return CG_ERROR; } for (i=0; i<3*index_dim; i++) zone->nijk[i] = nijk[i]; zone->index_dim = index_dim; zone->type = type; /* save data in file */ dim_vals[0]=zone->index_dim; dim_vals[1]=3; if (cgi_new_node(base->id, zone->name, "Zone_t", &zone->id, CG_SIZE_DATATYPE, 2, dim_vals, (void *)zone->nijk)) return CG_ERROR; dim_vals[0] = (cgsize_t)strlen(ZoneTypeName[type]); if (cgi_new_node(zone->id, "ZoneType", "ZoneType_t", &dummy_id, "C1", 1, dim_vals, ZoneTypeName[type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and Write Family_t Nodes \*****************************************************************************/ int cg_nfamilies(int file_number, int B, int *nfamilies) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *nfamilies = base->nfamilies; return CG_OK; } int cg_family_read(int file_number, int B, int F, char *family_name, int *nboco, int *ngeos) { cgns_family *family; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; strcpy(family_name, family->name); *nboco = family->nfambc; *ngeos = family->ngeos; return CG_OK; } int cg_family_write(int file_number, int B, const char * family_name, int *F) { int index; cgns_base *base; cgns_family *family = NULL; /* verify input */ if (cgi_check_strlen(family_name)) return CG_ERROR; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* Overwrite a Family_t Node: */ for (index=0; indexnfamilies; index++) { if (strcmp(family_name, base->family[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",family_name); return CG_ERROR; } /* overwrite an existing zone */ /* delete the existing zone from file */ if (cgi_delete_node(base->id, base->family[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ family = &(base->family[index]); /* free memory */ cgi_free_family(family); break; } } /* ... or add a Family_t Node: */ if (index==base->nfamilies) { if (base->nfamilies == 0) { base->family = CGNS_NEW(cgns_family, base->nfamilies+1); } else { base->family = CGNS_RENEW(cgns_family, base->nfamilies+1, base->family); } family = &(base->family[base->nfamilies]); base->nfamilies++; } (*F) = index+1; memset(family, 0, sizeof(cgns_family)); strcpy(family->name, family_name); /* save data in file */ if (cgi_new_node(base->id, family->name, "Family_t", &family->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_nfamily_names(int file_number, int B, int F, int *nnames) { cgns_family *fam; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; fam = cgi_get_family(cg, B, F); if (fam == 0) return CG_ERROR; *nnames = fam->nfamname; return CG_OK; } int cg_family_name_read(int file_number, int B, int F, int N, char *name, char *family) { cgns_family *fam; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; fam = cgi_get_family(cg, B, F); if (fam == 0) return CG_ERROR; if (N < 1 || N > fam->nfamname) { cgi_error("family name index out of range\n"); return CG_ERROR; } strcpy(name, fam->famname[N-1].name); strcpy(family, fam->famname[N-1].family); return CG_OK; } int cg_family_name_write(int file_number, int B, int F, const char *name, const char *family) { int index; cgsize_t dim; cgns_family *fam; cgns_famname *famname = 0; /* verify input */ if (cgi_check_strlen(name) || cgi_check_strlen(family)) return CG_ERROR; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; fam = cgi_get_family(cg, B, F); if (fam == 0) return CG_ERROR; for (index = 0; index < fam->nfamname; index++) { if (0 == strcmp(name, fam->famname[index].name)) { if (cg->mode == CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s", name); return CG_ERROR; } if (cgi_delete_node(fam->id, fam->famname[index].id)) return CG_ERROR; famname = &(fam->famname[index]); break; } } if (index == fam->nfamname) { if (0 == fam->nfamname) fam->famname = CGNS_NEW(cgns_famname, 1); else fam->famname = CGNS_RENEW(cgns_famname, fam->nfamname+1, fam->famname); famname = &fam->famname[fam->nfamname]; fam->nfamname++; } strcpy(famname->name, name); strcpy(famname->family, family); dim = (cgsize_t)strlen(famname->family); if (cgi_new_node(fam->id, famname->name, "FamilyName_t", &famname->id, "C1", 1, &dim, famname->family)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_fambc_read(int file_number, int B, int F, int BC, char *fambc_name, CGNS_ENUMT(BCType_t) *bocotype) { cgns_family *family; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; if (BC<=0 || BC>family->nfambc) { cgi_error("Invalid family b.c. number"); return CG_ERROR; } strcpy(fambc_name,family->fambc[BC-1].name); *bocotype = family->fambc[BC-1].type; return CG_OK; } int cg_fambc_write(int file_number, int B, int F, const char * fambc_name, CGNS_ENUMT( BCType_t ) bocotype, int *BC) { int index; cgsize_t length; cgns_family *family; cgns_fambc *fambc = NULL; /* verify input */ if (cgi_check_strlen(fambc_name)) return CG_ERROR; if (INVALID_ENUM(bocotype,NofValidBCTypes)) { cgi_error("Invalid BCType: %d",bocotype); return CG_ERROR; } cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for family */ family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; /* Overwrite a FamilyBC_t Node: */ for (index=0; indexnfambc; index++) { if (strcmp(fambc_name, family->fambc[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",fambc_name); return CG_ERROR; } /* overwrite an existing zone */ /* delete the existing fambc from file */ if (cgi_delete_node(family->id, family->fambc[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ fambc = &(family->fambc[index]); /* free memory */ cgi_free_fambc(fambc); break; } } /* ... or add a FamilyBC_t Node: */ if (index==family->nfambc) { if (family->nfambc == 0) { family->fambc = CGNS_NEW(cgns_fambc, family->nfambc+1); } else { family->fambc = CGNS_RENEW(cgns_fambc, family->nfambc+1, family->fambc); } fambc = &(family->fambc[family->nfambc]); family->nfambc++; } (*BC) = index+1; memset(fambc, 0, sizeof(cgns_fambc)); strcpy(fambc->name, fambc_name); fambc->type = bocotype; /* save data in file */ length = (cgsize_t)strlen(BCTypeName[bocotype]); if (cgi_new_node(family->id, fambc->name, "FamilyBC_t", &fambc->id, "C1", 1, &length, BCTypeName[bocotype])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_geo_read(int file_number, int B, int F, int G, char *geo_name, char **geo_file, char *CAD_name, int *npart) { cgns_family *family; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; if (G<=0 || G>family->ngeos) { cgi_error("Invalid geometry reference number"); return CG_ERROR; } strcpy(geo_name,family->geo[G-1].name); strcpy(CAD_name,family->geo[G-1].format); /* This string is not limited to 32 characters and can't be pre-allocated in the application */ geo_file[0]=CGNS_NEW(char,strlen(family->geo[G-1].file)+1); strcpy(geo_file[0],family->geo[G-1].file); *npart=family->geo[G-1].npart; return CG_OK; } int cg_geo_write(int file_number, int B, int F, const char * geo_name, const char * filename, const char * CADname, int *G) { int index; cgsize_t length; cgns_family *family; cgns_geo *geo = NULL; double dummy_id; /* verify input */ if (cgi_check_strlen(geo_name)) return CG_ERROR; if (cgi_check_strlen(CADname)) return CG_ERROR; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for family */ family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; /* Overwrite a GeometryReference_t Node: */ for (index=0; indexngeos; index++) { if (strcmp(geo_name, family->geo[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",geo_name); return CG_ERROR; } /* overwrite an existing zone */ /* delete the existing geo from file */ if (cgi_delete_node(family->id, family->geo[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ geo = &(family->geo[index]); /* free memory */ cgi_free_geo(geo); break; } } /* ... or add a GeometryReference_t Node: */ if (index==family->ngeos) { if (family->ngeos == 0) { family->geo = CGNS_NEW(cgns_geo, family->ngeos+1); } else { family->geo = CGNS_RENEW(cgns_geo, family->ngeos+1, family->geo); } geo = &(family->geo[family->ngeos]); family->ngeos++; } (*G) = index+1; memset(geo, 0, sizeof(cgns_geo)); strcpy(geo->name, geo_name); strcpy(geo->format, CADname); length = (int)strlen(filename); if (length<=0) { cgi_error("filename undefined for GeometryReference node!"); return CG_ERROR; } geo->file = (char *)malloc((size_t)((length+1)*sizeof(char))); if (geo->file == NULL) { cgi_error("Error allocation geo->file"); return CG_ERROR; } strcpy(geo->file, filename); /* save data in file */ if (cgi_new_node(family->id, geo->name, "GeometryReference_t", &geo->id, "MT", 0, 0, 0)) return CG_ERROR; length = (cgsize_t)strlen(geo->file); if (cgi_new_node(geo->id, "GeometryFile", "GeometryFile_t", &dummy_id, "C1", 1, &length, geo->file)) return CG_ERROR; length = (cgsize_t)strlen(geo->format); if (cgi_new_node(geo->id, "GeometryFormat", "GeometryFormat_t", &dummy_id, "C1", 1, &length, geo->format)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_part_read(int file_number, int B, int F, int G, int P, char *part_name) { cgns_family *family; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; if (P<=0 || P>family->geo[G-1].npart) { cgi_error("Invalid part number"); return CG_ERROR; } strcpy(part_name,family->geo[G-1].part[P-1].name); return CG_OK; } int cg_part_write(int file_number, int B, int F, int G, const char * part_name, int *P) { int index; cgns_geo *geo; cgns_part *part = NULL; cgns_family *family; /* verify input */ if (cgi_check_strlen(part_name)) return CG_ERROR; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for geo */ family = cgi_get_family(cg, B, F); if (family==0) return CG_ERROR; if (G > family->ngeos || G <=0) { cgi_error("Invalid index for GeometryEntity_t node"); return CG_ERROR; } geo = &family->geo[G-1]; /* Overwrite a GeometryEntity_t Node: */ for (index=0; indexnpart; index++) { if (strcmp(part_name, geo->part[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",part_name); return CG_ERROR; } /* overwrite an existing zone */ /* delete the existing geo from file */ if (cgi_delete_node(geo->id, geo->part[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ part = &(geo->part[index]); /* free memory */ cgi_free_part(part); break; } } /* ... or add a GeometryReference_t Node: */ if (index==geo->npart) { if (geo->npart == 0) { geo->part = CGNS_NEW(cgns_part, geo->npart+1); } else { geo->part = CGNS_RENEW(cgns_part, geo->npart+1, geo->part); } part = &(geo->part[geo->npart]); geo->npart++; } (*P) = index+1; memset(part, 0, sizeof(cgns_part)); strcpy(part->name, part_name); /* save data in file */ if (cgi_new_node(geo->id, part->name, "GeometryEntity_t", &part->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and Write DiscreteData_t Nodes \*****************************************************************************/ int cg_ndiscrete(int file_number, int B, int Z, int *ndiscrete) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; (*ndiscrete) = zone->ndiscrete; return CG_OK; } int cg_discrete_read(int file_number, int B, int Z, int D, char *discrete_name) { cgns_discrete *discrete; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; discrete = cgi_get_discrete(cg, B, Z, D); if (discrete==0) return CG_ERROR; strcpy(discrete_name, discrete->name); return CG_OK; } int cg_discrete_write(int file_number, int B, int Z, const char * discrete_name, int *D) { cgns_zone *zone; cgns_discrete *discrete = NULL; int index; /* verify input */ if (cgi_check_strlen(discrete_name)) return CG_ERROR; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a DiscreteData_t node: */ for (index=0; indexndiscrete; index++) { if (strcmp(discrete_name, zone->discrete[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",discrete_name); return CG_ERROR; } /* overwrite an existing solution */ /* delete the existing solution from file */ if (cgi_delete_node(zone->id, zone->discrete[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ discrete = &(zone->discrete[index]); /* free memory */ cgi_free_discrete(discrete); break; } } /* ... or add a FlowSolution_t Node: */ if (index==zone->ndiscrete) { if (zone->ndiscrete == 0) { zone->discrete = CGNS_NEW(cgns_discrete, zone->ndiscrete+1); } else { zone->discrete = CGNS_RENEW(cgns_discrete, zone->ndiscrete+1, zone->discrete); } discrete = &zone->discrete[zone->ndiscrete]; zone->ndiscrete++; } (*D) = index+1; /* save data in memory */ memset(discrete, 0, sizeof(cgns_discrete)); strcpy(discrete->name, discrete_name); discrete->location=CGNS_ENUMV(Vertex); /* save data in file */ if (cgi_new_node(zone->id, discrete->name, "DiscreteData_t", &discrete->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } int cg_discrete_size(int file_number, int B, int Z, int D, int *data_dim, cgsize_t *dim_vals) { cgns_discrete *discrete; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; discrete = cgi_get_discrete(cg, B, Z, D); if (discrete==0) return CG_ERROR; if (discrete->ptset == NULL) { cgns_zone *zone = &cg->base[B-1].zone[Z-1]; *data_dim = zone->index_dim; if (cgi_datasize(zone->index_dim, zone->nijk, discrete->location, discrete->rind_planes, dim_vals)) return CG_ERROR; } else { *data_dim = 1; dim_vals[0] = discrete->ptset->size_of_patch; } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_discrete_ptset_info(int fn, int B, int Z, int D, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts) { cgns_discrete *discrete; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; discrete = cgi_get_discrete(cg, B, Z, D); if (discrete==0) return CG_ERROR; if (discrete->ptset == NULL) { *ptset_type = CGNS_ENUMV(PointSetTypeNull); *npnts = 0; } else { *ptset_type = discrete->ptset->type; *npnts = discrete->ptset->npts; } return CG_OK; } int cg_discrete_ptset_read(int fn, int B, int Z, int D, cgsize_t *pnts) { int dim = 0; cgns_discrete *discrete; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; discrete = cgi_get_discrete(cg, B, Z, D); if (discrete==0) return CG_ERROR; if (discrete->ptset == 0 || discrete->ptset->npts <= 0) { cgi_error("PointSet not defined for Discrete node %d\n", D); return CG_ERROR; } cg_index_dim(fn, B, Z, &dim); if (cgi_read_int_data(discrete->ptset->id, discrete->ptset->data_type, discrete->ptset->npts * dim, pnts)) return CG_ERROR; return CG_OK; } int cg_discrete_ptset_write(int fn, int B, int Z, const char *discrete_name, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *D) { int i, index_dim = 0; cgsize_t cnt, dim_vals = 1; cgns_discrete *discrete; char_33 PointSetName; double id; /* verify input */ if (!((ptset_type == CGNS_ENUMV(PointList) && npnts > 0) || (ptset_type == CGNS_ENUMV(PointRange) && npnts == 2))) { cgi_error("Invalid input: npoint=%ld, point set type=%s", (long)npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } if (cg_index_dim(fn, B, Z, &index_dim)) return CG_ERROR; if (cgi_check_location(cg->base[B-1].cell_dim, cg->base[B-1].zone[Z-1].type, location)) return CG_ERROR; if (cg_discrete_write(fn, B, Z, discrete_name, D)) return CG_ERROR; discrete = cgi_get_discrete(cg, B, Z, *D); if (discrete == 0) return CG_ERROR; discrete->location = location; discrete->ptset = CGNS_NEW(cgns_ptset, 1); discrete->ptset->type = ptset_type; strcpy(discrete->ptset->data_type,CG_SIZE_DATATYPE); discrete->ptset->npts = npnts; if (ptset_type == CGNS_ENUMV(PointList)) { discrete->ptset->size_of_patch = npnts; } else { discrete->ptset->size_of_patch = 1; for (i = 0; i < index_dim; i++) { cnt = pnts[i+index_dim] - pnts[i]; if (cnt < 0) cnt = -cnt; discrete->ptset->size_of_patch *= (cnt + 1); } } strcpy(PointSetName, PointSetTypeName[ptset_type]); if (cgi_write_ptset(discrete->id, PointSetName, discrete->ptset, index_dim, (void *)pnts)) return CG_ERROR; if (location != CGNS_ENUMV(Vertex)) { dim_vals = (cgsize_t)strlen(GridLocationName[location]); if (cgi_new_node(discrete->id, "GridLocation", "GridLocation_t", &id, "C1", 1, &dim_vals, (void *)GridLocationName[location])) return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * Read and Write GridCoordinates_t Nodes \*****************************************************************************/ int cg_ngrids(int file_number, int B, int Z, int *ngrids) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; (*ngrids) = zone->nzcoor; return CG_OK; } int cg_grid_read(int file_number, int B, int Z, int G, char *gridname) { cgns_zcoor *zcoor; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for GridCoordinates_t node */ zcoor = cgi_get_zcoor(cg, B, Z, G); if (zcoor==0) return CG_ERROR; /* Return ADF name for the GridCoordinates_t node */ strcpy(gridname,zcoor->name); return CG_OK; } int cg_grid_write(int file_number, int B, int Z, const char * zcoorname, int *G) { cgns_zone *zone; cgns_zcoor *zcoor = NULL; int index, n, index_dim; /* verify input */ if (cgi_check_strlen(zcoorname)) return CG_ERROR; /* get memory address */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a GridCoordinates_t Node: */ for (index=0; indexnzcoor; index++) { if (strcmp(zcoorname, zone->zcoor[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",zcoorname); return CG_ERROR; } /* overwrite an existing GridCoordinates_t node */ /* delete the existing GridCoordinates_t from file */ if (cgi_delete_node(zone->id, zone->zcoor[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ zcoor = &(zone->zcoor[index]); /* free memory */ cgi_free_zcoor(zcoor); break; } } /* ... or add a GridCoordinates_t Node: */ if (index==zone->nzcoor) { if (zone->nzcoor == 0) { zone->zcoor = CGNS_NEW(cgns_zcoor, 1); } else { zone->zcoor = CGNS_RENEW(cgns_zcoor, zone->nzcoor+1, zone->zcoor); } zcoor = &(zone->zcoor[zone->nzcoor]); zone->nzcoor++; } (*G) = index+1; /* save data in memory */ memset(zcoor, 0, sizeof(cgns_zcoor)); strcpy(zcoor->name,zcoorname); index_dim = zone->index_dim; zcoor->rind_planes = (int *)malloc(index_dim*2*sizeof(int)); if (zcoor->rind_planes == NULL) { cgi_error("Error allocating zcoor->rind_plane."); return CG_ERROR; } for (n=0; nrind_planes[2*n]=zcoor->rind_planes[2*n+1]=0; /* save data in file */ if (cgi_new_node(zone->id, zcoor->name, "GridCoordinates_t", &zcoor->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and Write GridCoordinates_t/DataArray_t Nodes \*****************************************************************************/ int cg_ncoords(int file_number, int B, int Z, int *ncoords) { cgns_zcoor *zcoor; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor==0) *ncoords = 0; /* if ZoneGridCoordinates_t is undefined */ else *ncoords = zcoor->ncoords; return CG_OK; } int cg_coord_info(int file_number, int B, int Z, int C, CGNS_ENUMT(DataType_t) *type, char *coordname) { cgns_zcoor *zcoor; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor==0) return CG_ERROR; if (C>zcoor->ncoords || C<=0) { cgi_error("coord number %d invalid",C); return CG_ERROR; } *type = cgi_datatype(zcoor->coord[C-1].data_type); strcpy(coordname, zcoor->coord[C-1].name); return CG_OK; } int cg_coord_read(int file_number, int B, int Z, const char *coordname, CGNS_ENUMT(DataType_t) type, const cgsize_t *s_rmin, const cgsize_t *s_rmax, void *coord_ptr) { cgns_zone *zone; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; m_numdim = zone->index_dim; /* verify that range requested is not NULL */ if (s_rmin == NULL || s_rmax == NULL) { cgi_error("NULL range value."); return CG_ERROR; } cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; nfilename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor == 0) return CG_ERROR; /* find the coord address in the database */ coord = 0; for (c=0; cncoords; c++) { if (strcmp(zcoor->coord[c].name, coordname) == 0) { coord = &zcoor->coord[c]; break; } } if (coord==0) { cgi_error("Coordinate %s not found.",coordname); return CG_NODE_NOT_FOUND; } /* zcoor implies zone exists */ s_numdim = cg->base[B-1].zone[Z-1].index_dim; return cgi_array_general_read(coord, cgns_rindindex, zcoor->rind_planes, s_numdim, s_rmin, s_rmax, m_type, m_numdim, m_dimvals, m_rmin, m_rmax, coord_ptr); } int cg_coord_id(int file_number, int B, int Z, int C, double *coord_id) { cgns_zcoor *zcoor; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor==0) return CG_ERROR; if (C>zcoor->ncoords || C<=0) { cgi_error("coord number %d invalid",C); return CG_ERROR; } *coord_id = zcoor->coord[C-1].id; return CG_OK; } int cg_coord_write(int file_number, int B, int Z, CGNS_ENUMT(DataType_t) type, const char *coordname, const void *coord_ptr, int *C) { cgns_zone *zone; cgns_zcoor *zcoor; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; /* Get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor == 0) return CG_ERROR; m_numdim = zone->index_dim; cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; cgsize_t s_rmin[CGIO_MAX_DIMENSIONS], s_rmax[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; nnijk[n] + zcoor->rind_planes[2*n] + zcoor->rind_planes[2*n+1]; if (cgns_rindindex == CG_CONFIG_RIND_ZERO) { /* old obsolete behavior (versions < 3.4) */ s_rmin[n] = 1; } else { /* new behavior consitent with SIDS */ s_rmin[n] = 1 - zcoor->rind_planes[2*n]; } s_rmax[n] = s_rmin[n] + m_dimvals[n] - 1; m_rmin[n] = 1; m_rmax[n] = m_dimvals[n]; } return cg_coord_general_write(file_number, B, Z, coordname, type, s_rmin, s_rmax, type, m_numdim, m_dimvals, m_rmin, m_rmax, coord_ptr, C); } int cg_coord_partial_write(int file_number, int B, int Z, CGNS_ENUMT(DataType_t) type, const char *coordname, const cgsize_t *s_rmin, const cgsize_t *s_rmax, const void *coord_ptr, int *C) { cgns_zone *zone; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; m_numdim = zone->index_dim; if (s_rmin == NULL || s_rmax == NULL) { cgi_error("NULL range value."); return CG_ERROR; } cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; nfilename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; /* Get memory address for node "GridCoordinates" */ zcoor = cgi_get_zcoorGC(cg, B, Z); if (zcoor == 0) return CG_ERROR; cgsize_t s_dimvals[CGIO_MAX_DIMENSIONS]; s_numdim = zone->index_dim; for (n = 0; nnijk[n] + zcoor->rind_planes[2*n] + zcoor->rind_planes[2*n+1]; } /* Create GridCoordinates_t node if not already created */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (zcoor->id == 0) { if (cgi_new_node(zone->id, "GridCoordinates", "GridCoordinates_t", &zcoor->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(zcoor->id, hid); if (hid == 0) { if (cgi_new_node(zone->id, "GridCoordinates", "GridCoordinates_t", &zcoor->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } return cgi_array_general_write(zcoor->id, &(zcoor->ncoords), &(zcoor->coord), coordname, cgns_rindindex, zcoor->rind_planes, s_type, s_numdim, s_dimvals, s_rmin, s_rmax, m_type, m_numdim, m_dimvals, m_rmin, m_rmax, coord_ptr, C); } /*****************************************************************************\ * Read and Write Elements_t Nodes \*****************************************************************************/ static int adf2_check_elems(CGNS_ENUMT(ElementType_t) type, cgsize_t nelems, const cgsize_t *elems) { if (type < CGNS_ENUMV(NODE) || type > CGNS_ENUMV(MIXED)) { cgi_error("Element type %s not supported in ADF2.", cg_ElementTypeName(type)); return CG_ERROR; } if (type == CGNS_ENUMV(MIXED)) { int npe; cgsize_t n; for (n = 0; n < nelems; n++) { type = (CGNS_ENUMT(ElementType_t))*elems++; if (type < CGNS_ENUMV(NODE) || type >= CGNS_ENUMV(MIXED)) { cgi_error("Element type %s not supported in ADF2.", cg_ElementTypeName(type)); return CG_ERROR; } if (cg_npe(type, &npe) || npe <= 0) return CG_ERROR; elems += npe; } } return CG_OK; } static void free_element_data(cgns_section *section) { if (section->connect->data != NULL) { free(section->connect->data); section->connect->data = NULL; } } static int read_element_data(cgns_section *section) { if (section->connect->data == NULL) { cgsize_t cnt = section->connect->dim_vals[0]; section->connect->data = malloc(cnt * sizeof(cgsize_t)); if (section->connect->data == NULL) { cgi_error("malloc failed for element data"); return CG_ERROR; } if (cgi_read_int_data(section->connect->id, section->connect->data_type, cnt, section->connect->data)) { free_element_data(section); return CG_ERROR; } } return CG_OK; } static void free_offset_data(cgns_section *section) { if (section->connect_offset->data != NULL) { free(section->connect_offset->data); section->connect_offset->data = NULL; } } static int read_offset_data(cgns_section *section) { if (section->connect_offset->data == NULL) { cgsize_t cnt = section->connect_offset->dim_vals[0]; section->connect_offset->data = malloc(cnt * sizeof(cgsize_t)); if (section->connect_offset->data == NULL) { cgi_error("malloc failed for element connectivity offset data"); return CG_ERROR; } if (cgi_read_int_data(section->connect_offset->id, section->connect_offset->data_type, cnt, section->connect_offset->data)) { free_offset_data(section); return CG_ERROR; } } return CG_OK; } static void free_parent_data(cgns_section *section) { if (section->parelem && section->parelem->data != NULL) { free(section->parelem->data); section->parelem->data = NULL; } if (section->parface && section->parface->data != NULL) { free(section->parface->data); section->parface->data = NULL; } } static int read_parent_data(cgns_section *section) { cgsize_t cnt; if (0 == strcmp(section->parelem->name, "ParentData")) { if (section->parelem->data == NULL) { cnt = section->parelem->dim_vals[0] * 4; section->parelem->data = malloc(cnt * sizeof(cgsize_t)); if (section->parelem->data == NULL) { cgi_error("malloc failed for ParentData data"); return CG_ERROR; } if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, cnt, section->parelem->data)) { free_parent_data(section); return CG_ERROR; } } return CG_OK; } if (section->parelem->dim_vals[0] != section->parface->dim_vals[0] || section->parelem->dim_vals[1] != 2 || section->parface->dim_vals[1] != 2) { cgi_error("mismatch in ParentElements and ParentElementsPosition data sizes"); return CG_ERROR; } cnt = section->parelem->dim_vals[0] * 2; if (section->parelem->data == NULL) { section->parelem->data = malloc(cnt * sizeof(cgsize_t)); if (section->parelem->data == NULL) { cgi_error("malloc failed for ParentElements data"); return CG_ERROR; } if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, cnt, section->parelem->data)) { free_parent_data(section); return CG_ERROR; } } if (section->parface->data == NULL) { section->parface->data = malloc(cnt * sizeof(cgsize_t)); if (section->parface->data == NULL) { cgi_error("malloc failed for ParentElementsPosition data"); return CG_ERROR; } if (cgi_read_int_data(section->parface->id, section->parface->data_type, cnt, section->parface->data)) { free_parent_data(section); return CG_ERROR; } } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_nsections(int file_number, int B, int Z, int *nsections) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; (*nsections) = zone->nsections; return CG_OK; } int cg_section_read(int file_number, int B, int Z, int S, char *SectionName, CGNS_ENUMT(ElementType_t) *type, cgsize_t *start, cgsize_t *end, int *nbndry, int *parent_flag) { cgns_section *section; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; strcpy(SectionName, section->name); *type = section->el_type; *start = section->range[0]; *end = section->range[1]; *nbndry = section->el_bound; *parent_flag=0; if (section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData"))) *parent_flag=1; return CG_OK; } int cg_section_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t)type, cgsize_t start, cgsize_t end, int nbndry, const cgsize_t * elements, int *S) { cgns_zone *zone; cgns_section *section = NULL; int index; cgsize_t num, ElementDataSize=0; /* verify input */ if (cgi_check_strlen(SectionName)) return CG_ERROR; if (INVALID_ENUM(type,NofValidElementTypes)) { cgi_error("Invalid element type defined for section '%s'",SectionName); return CG_ERROR; } if (!IS_FIXED_SIZE(type)) { cgi_error("Element must be a fixed size"); return CG_ERROR; } num = end - start + 1; if (num <= 0) { cgi_error("Invalid element range defined for section '%s'",SectionName); return CG_ERROR; } if (nbndry > num) { cgi_error("Invalid boundary element number for section '%s'",SectionName); return CG_ERROR; } /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (cg->filetype == CG_FILE_ADF2 && adf2_check_elems(type, num, elements)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a Elements_t Node: */ for (index=0; indexnsections; index++) { if (strcmp(SectionName, zone->section[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",SectionName); return CG_ERROR; } /* overwrite an existing section */ /* delete the existing section from file */ if (cgi_delete_node(zone->id, zone->section[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ section = &(zone->section[index]); /* free memory */ cgi_free_section(section); break; } } /* ... or add a Elements_t Node: */ if (index==zone->nsections) { if (zone->nsections == 0) { zone->section = CGNS_NEW(cgns_section, zone->nsections+1); } else { zone->section = CGNS_RENEW(cgns_section, zone->nsections+1, zone->section); } section = &(zone->section[zone->nsections]); zone->nsections++; } (*S) = index+1; /* save data in memory */ memset(section, 0, sizeof(cgns_section)); strcpy(section->name, SectionName); section->el_type = type; section->range[0] = start; section->range[1] = end; section->el_bound = nbndry; /* Compute ElementDataSize */ ElementDataSize = cgi_element_data_size(type, num, elements, NULL); if (ElementDataSize < 0) return CG_ERROR; /* Write element connectivity in internal data structure */ section->connect = CGNS_NEW(cgns_array, 1); strcpy(section->connect->name,"ElementConnectivity"); strcpy(section->connect->data_type, CG_SIZE_DATATYPE); section->connect->data_dim=1; section->connect->dim_vals[0]=ElementDataSize; if (cgi_write_section(zone->id, section)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section->connect->id, elements)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } return CG_OK; } int cg_poly_section_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t)type, cgsize_t start, cgsize_t end, int nbndry, const cgsize_t * elements, const cgsize_t * connect_offset, int *S) { cgns_zone *zone; cgns_section *section = NULL; int index; cgsize_t num, ElementDataSize=0; /* verify input */ if (cgi_check_strlen(SectionName)) return CG_ERROR; if (INVALID_ENUM(type,NofValidElementTypes)) { cgi_error("Invalid element type defined for section '%s'",SectionName); return CG_ERROR; } num = end - start + 1; if (num <= 0) { cgi_error("Invalid element range defined for section '%s'",SectionName); return CG_ERROR; } if (nbndry > num) { cgi_error("Invalid boundary element number for section '%s'",SectionName); return CG_ERROR; } /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (cg->filetype == CG_FILE_ADF2 && adf2_check_elems(type, num, elements)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a Elements_t Node: */ for (index=0; indexnsections; index++) { if (strcmp(SectionName, zone->section[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",SectionName); return CG_ERROR; } /* overwrite an existing section */ /* delete the existing section from file */ if (cgi_delete_node(zone->id, zone->section[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ section = &(zone->section[index]); /* free memory */ cgi_free_section(section); break; } } /* ... or add a Elements_t Node: */ if (index==zone->nsections) { if (zone->nsections == 0) { zone->section = CGNS_NEW(cgns_section, zone->nsections+1); } else { zone->section = CGNS_RENEW(cgns_section, zone->nsections+1, zone->section); } section = &(zone->section[zone->nsections]); zone->nsections++; } (*S) = index+1; /* save data in memory */ memset(section, 0, sizeof(cgns_section)); strcpy(section->name, SectionName); section->el_type = type; section->range[0] = start; section->range[1] = end; section->el_bound = nbndry; /* Compute ElementDataSize */ ElementDataSize = cgi_element_data_size(type, num, elements, connect_offset); if (ElementDataSize < 0) return CG_ERROR; /* Write element connectivity in internal data structure */ section->connect = CGNS_NEW(cgns_array, 1); strcpy(section->connect->name,"ElementConnectivity"); strcpy(section->connect->data_type, CG_SIZE_DATATYPE); section->connect->data_dim=1; section->connect->dim_vals[0]=ElementDataSize; if (connect_offset && ! IS_FIXED_SIZE(type)) { /* Write element start offset connectivity in internal data structure */ section->connect_offset = CGNS_NEW(cgns_array, 1); strcpy(section->connect_offset->name,"ElementStartOffset"); strcpy(section->connect_offset->data_type, CG_SIZE_DATATYPE); section->connect_offset->data_dim=1; section->connect_offset->dim_vals[0] = end-start+2; } if (cgi_write_section(zone->id, section)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section->connect->id, elements)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } if (section->connect_offset) { if (cgio_write_all_data(cg->cgio, section->connect_offset->id, connect_offset)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } return CG_OK; } int cg_section_partial_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t) type, cgsize_t start, cgsize_t end, int nbndry, int *S) { cgns_zone *zone; cgns_section *section = NULL; int index, elemsize; cgsize_t num, ElementDataSize=0; /* verify input */ if (cgi_check_strlen(SectionName)) return CG_ERROR; if (INVALID_ENUM(type,NofValidElementTypes)) { cgi_error("Invalid element type defined for section '%s'",SectionName); return CG_ERROR; } num = end - start + 1; if (num <= 0) { cgi_error("Invalid element range defined for section '%s'",SectionName); return CG_ERROR; } if (nbndry > num) { cgi_error("Invalid boundary element number for section '%s'",SectionName); return CG_ERROR; } /* Compute ElementDataSize */ if (cg_npe(type, &elemsize)) return CG_ERROR; if (elemsize <= 0) elemsize = 2; ElementDataSize = num * elemsize; /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (cg->filetype == CG_FILE_ADF2 && type > CGNS_ENUMV(MIXED)) { /* Jiao: Changed to use older compatible version */ cgi_error("Element type %s not supported in ADF2.", cg_ElementTypeName(type)); return CG_ERROR; } zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a Elements_t Node: */ for (index=0; indexnsections; index++) { if (strcmp(SectionName, zone->section[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",SectionName); return CG_ERROR; } /* overwrite an existing section */ /* delete the existing section from file */ if (cgi_delete_node(zone->id, zone->section[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ section = &(zone->section[index]); /* free memory */ cgi_free_section(section); break; } } /* ... or add a Elements_t Node: */ if (index==zone->nsections) { if (zone->nsections == 0) { zone->section = CGNS_NEW(cgns_section, zone->nsections+1); } else { zone->section = CGNS_RENEW(cgns_section, zone->nsections+1, zone->section); } section = &(zone->section[zone->nsections]); zone->nsections++; } (*S) = index+1; /* initialize ... */ strcpy(section->name, SectionName); section->el_type = type; section->range[0] = start; section->range[1] = end; section->el_bound = nbndry; section->connect = CGNS_NEW(cgns_array, 1); section->connect->data = 0; strcpy(section->connect->name,"ElementConnectivity"); strcpy(section->connect->data_type,CG_SIZE_DATATYPE); section->connect->data_dim=1; section->connect->dim_vals[0]=ElementDataSize; section->id=0; section->link=0; section->ndescr=0; section->parelem = section->parface = NULL; section->nuser_data=0; section->rind_planes=0; section->connect_offset=0; /* initialize other fields */ section->connect->id=0; section->connect->link=0; section->connect->ndescr=0; section->connect->data_class=CGNS_ENUMV(DataClassNull); section->connect->units=0; section->connect->exponents=0; section->connect->convert=0; /* if not fixed element size, need to create valid data for sizing */ if (!IS_FIXED_SIZE(type)) { cgsize_t n, nn, *data = CGNS_NEW(cgsize_t, ElementDataSize); cgsize_t *data_connect = CGNS_NEW(cgsize_t, (size_t)(num+1)); cgsize_t val = (type == CGNS_ENUMV(MIXED) ? (cgsize_t)CGNS_ENUMV(NODE) : 0); for (nn = 0, n = 0; n < num; n++) { data[nn++] = val; data[nn++] = 0; } section->connect->data = (void *)data; section->connect_offset = CGNS_NEW(cgns_array, 1); section->connect_offset->data = 0; strcpy(section->connect_offset->name,"ElementStartOffset"); strcpy(section->connect_offset->data_type,CG_SIZE_DATATYPE); section->connect_offset->data_dim=1; section->connect_offset->dim_vals[0]=(num+1); section->connect_offset->id=0; section->connect_offset->link=0; section->connect_offset->ndescr=0; section->connect_offset->data_class=CGNS_ENUMV(DataClassNull); section->connect_offset->units=0; section->connect_offset->exponents=0; section->connect_offset->convert=0; data_connect[0] = 0; for (n = 0; n < num; n++) { data_connect[n+1] = data_connect[n]+2; } section->connect_offset->data = (void *) data_connect; } if (cgi_write_section(zone->id, section)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ /* This function was created for revision 1.2 to return the size of the connectivity vector, which can't be known without it when type=MIXED */ int cg_ElementDataSize(int file_number, int B, int Z, int S, cgsize_t *ElementDataSize) { cgns_section *section; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; *ElementDataSize = section->connect->dim_vals[0]; return CG_OK; } int cg_ElementPartialSize(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *ElementDataSize) { cgns_section *section; cgsize_t size, offset, *data, *offset_data; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; if (start > end || start < section->range[0] || end > section->range[1]) { cgi_error("Invalid range for section '%s'", section->name); return CG_ERROR; } if (start == section->range[0] && end == section->range[1]) { *ElementDataSize = section->connect->dim_vals[0]; return CG_OK; } if (IS_FIXED_SIZE(section->el_type)) { size = cgi_element_data_size(section->el_type, end - start + 1, NULL, NULL); if (size < 0) return CG_ERROR; *ElementDataSize = size; return CG_OK; } if (read_element_data(section)) return CG_ERROR; if (read_offset_data(section)) return CG_ERROR; data = (cgsize_t *)section->connect->data; offset_data = (cgsize_t *)section->connect_offset->data; offset = cgi_element_data_size(section->el_type, start - section->range[0], data, offset_data); if (offset < 0) return CG_ERROR; size = offset_data[end] - offset_data[start-1]; if (size < 0) return CG_ERROR; *ElementDataSize = size; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_elements_read(int file_number, int B, int Z, int S, cgsize_t *elements, cgsize_t *parent_data) { cgns_section *section; cgsize_t count, num, ElementDataSize=0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; if (!IS_FIXED_SIZE(section->el_type)) { cgi_error("element must be a fixed size"); return CG_ERROR; } /* cgns_internals takes care of adjusting for version */ ElementDataSize = section->connect->dim_vals[0]; num = section->range[1] - section->range[0] +1; count = cgi_element_data_size(section->el_type, num, section->connect->data, NULL); if (count < 0) return CG_ERROR; if (count && count != ElementDataSize) { cgi_error("Error in recorded element connectivity array..."); return CG_ERROR; } if (section->connect->data && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { memcpy(elements, section->connect->data, (size_t)(ElementDataSize*sizeof(cgsize_t))); } else { if (cgi_read_int_data(section->connect->id, section->connect->data_type, ElementDataSize, elements)) return CG_ERROR; } if (parent_data && section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData"))) { if (0 == strcmp(section->parelem->name, "ParentData")) { if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, num << 2, parent_data)) return CG_ERROR; } else { if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, num << 1, parent_data) || cgi_read_int_data(section->parface->id, section->parface->data_type, num << 1, &parent_data[num << 1])) return CG_ERROR; } } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_poly_elements_read(int file_number, int B, int Z, int S, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent_data) { cgns_section *section; cgsize_t count, num, ElementDataSize=0, ConnectOffsetSize=0; cgsize_t *offset_data=0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; /* cgns_internals takes care of adjusting for version */ ElementDataSize = section->connect->dim_vals[0]; /* Double check ElementDataSize (not necessary) */ if (section->connect_offset) { offset_data = section->connect_offset->data; } num = section->range[1] - section->range[0] +1; count = cgi_element_data_size(section->el_type, num, section->connect->data, offset_data); if (count < 0) return CG_ERROR; if (count && count != ElementDataSize) { cgi_error("Error in recorded element connectivity array..."); return CG_ERROR; } if (section->connect->data && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { memcpy(elements, section->connect->data, (size_t)(ElementDataSize*sizeof(cgsize_t))); } else { if (cgi_read_int_data(section->connect->id, section->connect->data_type, ElementDataSize, elements)) return CG_ERROR; } if (connect_offset && section->connect_offset) { ConnectOffsetSize = section->connect_offset->dim_vals[0]; if (section->connect_offset->data && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { memcpy(connect_offset, section->connect_offset->data, (size_t)(ConnectOffsetSize*sizeof(cgsize_t))); } else { if (cgi_read_int_data(section->connect_offset->id, section->connect_offset->data_type, ConnectOffsetSize, connect_offset)) return CG_ERROR; } } if (parent_data && section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData"))) { if (0 == strcmp(section->parelem->name, "ParentData")) { if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, num << 2, parent_data)) return CG_ERROR; } else { if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, num << 1, parent_data) || cgi_read_int_data(section->parface->id, section->parface->data_type, num << 1, &parent_data[num << 1])) return CG_ERROR; } } return CG_OK; } int cg_elements_partial_read(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *elements, cgsize_t *parent_data) { cgns_section *section; cgsize_t offset, size, n; cgsize_t i, j, nn, *data; cgsize_t s_start[2], s_end[2], s_stride[2]; cgsize_t m_start[2], m_end[2], m_stride[2], m_dim[2]; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; if (!IS_FIXED_SIZE(section->el_type)) { cgi_error("Element must be a fixed size"); return CG_ERROR; } /* check the requested element range against the stored element range, * and the validity of the requested range */ if(start > end || start < section->range[0] || end > section->range[1]) { cgi_error("Error in requested element data range."); return CG_ERROR; } /* if the elements are fixed size, read directly into user memory */ if (section->connect->data == 0 && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { size = cgi_element_data_size(section->el_type, end - start + 1, NULL, NULL); if (size < 0) return CG_ERROR; s_start[0] = cgi_element_data_size(section->el_type, start - section->range[0], NULL, NULL) + 1; s_end[0] = cgi_element_data_size(section->el_type, end - section->range[0] + 1, NULL, NULL); s_stride[0] = 1; m_start[0] = 1; m_end[0] = size; m_stride[0] = 1; m_dim[0] = size; if (cgio_read_data(cg->cgio, section->connect->id, s_start, s_end, s_stride, 1, m_dim, m_start, m_end, m_stride, elements)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } else { /* need to get the elements to compute locations */ if (read_element_data(section)) return CG_ERROR; data = (cgsize_t *)section->connect->data; offset = cgi_element_data_size(section->el_type, start - section->range[0], data, NULL); size = cgi_element_data_size(section->el_type, end - start + 1, &data[offset], NULL); memcpy(elements, &data[offset], (size_t)(size*sizeof(cgsize_t))); } if (parent_data && section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData"))) { offset = start - section->range[0]; size = section->range[1] - section->range[0] + 1; /* read from ParentData */ if (0 == strcmp(section->parelem->name, "ParentData")) { if (0 == strcmp(CG_SIZE_DATATYPE, section->parelem->data_type)) { s_start[0] = start - section->range[0] + 1; s_end[0] = end - section->range[0] + 1; s_stride[0]= 1; s_start[1] = 1; s_end[1] = 4; s_stride[1]= 1; m_start[0] = 1; m_end[0] = end - start + 1; m_stride[0]= 1; m_start[1] = 1; m_end[1] = 4; m_stride[1]= 1; m_dim[0] = m_end[0]; m_dim[1] = 4; if (cgio_read_data(cg->cgio, section->parelem->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } else { nn = section->parelem->dim_vals[0] * 4; data = (cgsize_t *)malloc((size_t)(nn * sizeof(cgsize_t))); if (data == NULL) { cgi_error("malloc failed for tempory ParentData array"); return CG_ERROR; } if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, nn, data)) { free(data); return CG_ERROR; } for (n = 0, j = 0; j < 4; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } free(data); } } /* read from ParentElements and ParentElementsPosition */ else if (0 == strcmp(CG_SIZE_DATATYPE, section->parelem->data_type) && 0 == strcmp(CG_SIZE_DATATYPE, section->parface->data_type)) { s_start[0] = start - section->range[0] + 1; s_end[0] = end - section->range[0] + 1; s_stride[0]= 1; s_start[1] = 1; s_end[1] = 2; s_stride[1]= 1; m_start[0] = 1; m_end[0] = end - start + 1; m_stride[0]= 1; m_start[1] = 1; m_end[1] = 2; m_stride[1]= 1; m_dim[0] = m_end[0]; m_dim[1] = 4; if (cgio_read_data(cg->cgio, section->parelem->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } m_start[1] = 3; m_end[1] = 4; if (cgio_read_data(cg->cgio, section->parface->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } /* read into memory and copy */ else { if (read_parent_data(section)) return CG_ERROR; n = 0; data = (cgsize_t *)section->parelem->data; for (j = 0; j < 2; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } data = (cgsize_t *)section->parface->data; for (j = 0; j < 2; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } } } return CG_OK; } int cg_poly_elements_partial_read(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent_data) { cgns_section *section; cgsize_t offset, size, n; cgsize_t i, j, nn, *data; cgsize_t s_start[2], s_end[2], s_stride[2]; cgsize_t m_start[2], m_end[2], m_stride[2], m_dim[2]; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; /* check the requested element range against the stored element range, * and the validity of the requested range */ if(start > end || start < section->range[0] || end > section->range[1]) { cgi_error("Error in requested element data range."); return CG_ERROR; } /* if the elements are fixed size, read directly into user memory */ if (IS_FIXED_SIZE(section->el_type)) { if (section->connect->data == 0 && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { size = cgi_element_data_size(section->el_type, end - start + 1, NULL, NULL); if (size < 0) return CG_ERROR; s_start[0] = cgi_element_data_size(section->el_type, start - section->range[0], NULL, NULL) + 1; s_end[0] = cgi_element_data_size(section->el_type, end - section->range[0] + 1, NULL, NULL); s_stride[0] = 1; m_start[0] = 1; m_end[0] = size; m_stride[0] = 1; m_dim[0] = size; if (cgio_read_data(cg->cgio, section->connect->id, s_start, s_end, s_stride, 1, m_dim, m_start, m_end, m_stride, elements)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } else { /* need to get the elements to compute locations */ if (read_element_data(section)) return CG_ERROR; data = (cgsize_t *)section->connect->data; offset = cgi_element_data_size(section->el_type, start - section->range[0], data, NULL); size = cgi_element_data_size(section->el_type, end - start + 1, &data[offset], NULL); memcpy(elements, &data[offset], (size_t)(size*sizeof(cgsize_t))); } } else { /* need to get the connectivity offset to compute locations */ if (read_offset_data(section)) return CG_ERROR; cgsize_t *tmp_connect_offset = (cgsize_t *) section->connect_offset->data; offset = tmp_connect_offset[start - section->range[0]]; size = tmp_connect_offset[end-section->range[0]+1] - offset; if (section->connect->data == 0 && 0 == strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { s_start[0] = offset+1; s_end[0] = tmp_connect_offset[end-section->range[0]+1]; s_stride[0] = 1; m_start[0] = 1; m_end[0] = size; m_stride[0] = 1; m_dim[0] = size; if (cgio_read_data(cg->cgio, section->connect->id, s_start, s_end, s_stride, 1, m_dim, m_start, m_end, m_stride, elements)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } else { /* need to get the elements */ if (read_element_data(section)) return CG_ERROR; data = (cgsize_t *)section->connect->data; memcpy(elements, &data[offset], (size_t)(size*sizeof(cgsize_t))); } if (connect_offset == 0) { cgi_error("missing connectivity offset for reading"); return CG_ERROR; } memcpy(connect_offset, &tmp_connect_offset[start-section->range[0]],(size_t)((end-start+2)*sizeof(cgsize_t))); offset = connect_offset[0]; for (n=0; n< (end-start+2); n++) { connect_offset[n] -= offset; } } if (parent_data && section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData"))) { offset = start - section->range[0]; size = section->range[1] - section->range[0] + 1; /* read from ParentData */ if (0 == strcmp(section->parelem->name, "ParentData")) { if (0 == strcmp(CG_SIZE_DATATYPE, section->parelem->data_type)) { s_start[0] = start - section->range[0] + 1; s_end[0] = end - section->range[0] + 1; s_stride[0]= 1; s_start[1] = 1; s_end[1] = 4; s_stride[1]= 1; m_start[0] = 1; m_end[0] = end - start + 1; m_stride[0]= 1; m_start[1] = 1; m_end[1] = 4; m_stride[1]= 1; m_dim[0] = m_end[0]; m_dim[1] = 4; if (cgio_read_data(cg->cgio, section->parelem->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } else { nn = section->parelem->dim_vals[0] * 4; data = (cgsize_t *)malloc((size_t)(nn * sizeof(cgsize_t))); if (data == NULL) { cgi_error("malloc failed for tempory ParentData array"); return CG_ERROR; } if (cgi_read_int_data(section->parelem->id, section->parelem->data_type, nn, data)) { free(data); return CG_ERROR; } for (n = 0, j = 0; j < 4; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } free(data); } } /* read from ParentElements and ParentElementsPosition */ else if (0 == strcmp(CG_SIZE_DATATYPE, section->parelem->data_type) && 0 == strcmp(CG_SIZE_DATATYPE, section->parface->data_type)) { s_start[0] = start - section->range[0] + 1; s_end[0] = end - section->range[0] + 1; s_stride[0]= 1; s_start[1] = 1; s_end[1] = 2; s_stride[1]= 1; m_start[0] = 1; m_end[0] = end - start + 1; m_stride[0]= 1; m_start[1] = 1; m_end[1] = 2; m_stride[1]= 1; m_dim[0] = m_end[0]; m_dim[1] = 4; if (cgio_read_data(cg->cgio, section->parelem->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } m_start[1] = 3; m_end[1] = 4; if (cgio_read_data(cg->cgio, section->parface->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_read_data"); return CG_ERROR; } } /* read into memory and copy */ else { if (read_parent_data(section)) return CG_ERROR; n = 0; data = (cgsize_t *)section->parelem->data; for (j = 0; j < 2; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } data = (cgsize_t *)section->parface->data; for (j = 0; j < 2; j++) { nn = j * size + offset; for (i = start; i <= end; i++) parent_data[n++] = data[nn++]; } } } return CG_OK; } int cg_elements_partial_write(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *elements) { cgns_section *section; CGNS_ENUMT(ElementType_t) type; int i, elemsize; cgsize_t oldsize; cgsize_t num, size, offset; cgsize_t n, j, newsize, ElementDataSize; cgsize_t *oldelems, *newelems; double id; /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0 || section->connect == 0) return CG_ERROR; num = end - start + 1; type = section->el_type; if (!IS_FIXED_SIZE(type)) { cgi_error("Element must be a fixed size"); return CG_ERROR; } /* check input range */ if (num <= 0) { cgi_error("Invalid element range for section '%s' elements", section->name); return CG_ERROR; } if (strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { cgi_error("element data type %s does not match stored value %s", CG_SIZE_DATATYPE, section->connect->data_type); return CG_ERROR; } if (cg->filetype == CG_FILE_ADF2 && adf2_check_elems(type, num, elements)) return CG_ERROR; /* get fill-in element type */ if (cg_npe(type, &elemsize)) return CG_ERROR; if (elemsize <= 0) elemsize = 2; offset = start < section->range[0] ? section->range[0] - start : 0; oldsize = section->range[1] - section->range[0] + 1; ElementDataSize = cgi_element_data_size(type, end - start + 1, elements, NULL); if (ElementDataSize < 0) return CG_ERROR; /* can we just use the user's data ? */ if (start >= section->range[0] && end <= section->range[1] && section->connect->data == 0) { cgsize_t s_start, s_end, s_stride; cgsize_t m_start, m_end, m_stride, m_dim; s_start = cgi_element_data_size(type, start - section->range[0], 0, 0) + 1; s_end = cgi_element_data_size(type, end - section->range[0] + 1, 0, 0); s_stride = 1; m_start = 1; m_end = ElementDataSize; m_dim = ElementDataSize; m_stride = 1; if (cgio_write_data(cg->cgio, section->connect->id, &s_start, &s_end, &s_stride, 1, &m_dim, &m_start, &m_end, &m_stride, elements)) { cg_io_error("cgio_write_data"); return CG_ERROR; } } else { /* got to do it in memory */ if (read_element_data(section)) return CG_ERROR; oldelems = (cgsize_t *)section->connect->data; oldsize = section->connect->dim_vals[0]; newsize = ElementDataSize; if (end < section->range[0]) { newsize += oldsize; num = section->range[0] - end - 1; if (num > 0) newsize += (elemsize * num); } else if (start > section->range[1]) { newsize += oldsize; num = start - section->range[1] - 1; if (num > 0) newsize += (elemsize * num); } else { /* overlap */ if (start >= section->range[0]) { num = start - section->range[0]; size = cgi_element_data_size(type, num, oldelems, NULL); if (size < 0) return CG_ERROR; newsize += size; } if (end <= section->range[1]) { num = end - section->range[0] + 1; offset = cgi_element_data_size(type, num, oldelems, NULL); if (offset < 0) return CG_ERROR; size = oldsize - offset; newsize += size; } } /* create new element connectivity array */ newelems = (cgsize_t *) malloc ((size_t)(newsize * sizeof(cgsize_t))); if (NULL == newelems) { cgi_error("Error allocating new connectivity data"); return CG_ERROR; } n = 0; if (start <= section->range[0]) { memcpy(newelems, elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); n += ElementDataSize; if (end < section->range[0]) { num = section->range[0] - end - 1; while (num-- > 0) { for (i = 0; i < elemsize; i++) newelems[n++] = 0; } memcpy(&newelems[n], oldelems, (size_t)(oldsize*sizeof(cgsize_t))); n += oldsize; } else if (end < section->range[1]) { num = end - section->range[0] + 1; offset = cgi_element_data_size(type, num, oldelems, NULL); if (offset < 0) return CG_ERROR; size = oldsize - offset; memcpy(&newelems[n], &oldelems[offset], (size_t)(size*sizeof(cgsize_t))); n += size; } } else if (start > section->range[1]) { memcpy(newelems, oldelems, (size_t)(oldsize*sizeof(cgsize_t))); n += oldsize; num = start - section->range[1] - 1; while (num-- > 0) { for (i = 0; i < elemsize; i++) newelems[n++] = 0; } memcpy(&newelems[n], elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); n += ElementDataSize; } else { num = start - section->range[0]; size = cgi_element_data_size(type, num, oldelems, NULL); memcpy(newelems, oldelems, (size_t)(size*sizeof(cgsize_t))); n += size; memcpy(&newelems[n], elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); n += ElementDataSize; if (end < section->range[1]) { num = end - section->range[0] + 1; offset = cgi_element_data_size(type, num, oldelems, NULL); if (offset < 0) { free(newelems); return CG_ERROR; } size = oldsize - offset; memcpy(&newelems[n], &oldelems[offset], (size_t)(size*sizeof(cgsize_t))); n += size; } } if (n != newsize) { free(newelems); cgi_error("my counting is off !!!\n"); return CG_ERROR; } /* save these before updating for parent data */ offset = start < section->range[0] ? section->range[0] - start : 0; oldsize = section->range[1] - section->range[0] + 1; free(section->connect->data); section->connect->dim_vals[0] = newsize; section->connect->data = newelems; /* update ranges */ if (start < section->range[0]) section->range[0] = start; if (end > section->range[1]) section->range[1] = end; /* update ElementRange */ if (cgio_get_node_id(cg->cgio, section->id, "ElementRange", &id)) { cg_io_error("cgio_get_node_id"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, id, section->range)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } /* update ElementConnectivity */ if (cgio_set_dimensions(cg->cgio, section->connect->id, section->connect->data_type, 1, section->connect->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->connect->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } /* update the parent data array if it exists */ newsize = section->range[1] - section->range[0] + 1; if (section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData")) && newsize != section->parelem->dim_vals[0]) { int cnt = section->parelem->dim_vals[1]; if (read_parent_data(section)) return CG_ERROR; newelems = (cgsize_t *)malloc((size_t)(cnt * newsize * sizeof(cgsize_t))); if (NULL == newelems) { cgi_error("Error alocating new ParentElements data"); return CG_ERROR; } offset = start - section->range[0]; for (n = 0; n < cnt*newsize; n++) newelems[n] = 0; oldelems = (cgsize_t *)section->parelem->data; for (num = 0, i = 0; i < cnt; i++) { j = i * newsize + offset; for (n = 0; n < oldsize; n++) newelems[j++] = oldelems[num++]; } for (i = 0; i < cnt; i++) { j = i * newsize + offset; for (n = start; n <= end; n++) newelems[j++] = 0; } free(section->parelem->data); section->parelem->data = newelems; section->parelem->dim_vals[0] = newsize; if (cgio_set_dimensions(cg->cgio, section->parelem->id, section->parelem->data_type, 2, section->parelem->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->parelem->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } if (0 == strcmp(section->parelem->name, "ParentData")) return CG_OK; for (n = 0; n < 2*newsize; n++) newelems[n] = 0; oldelems = (cgsize_t *)section->parface->data; for (num = 0, i = 0; i < 2; i++) { j = i * newsize + offset; for (n = 0; n < oldsize; n++) newelems[j++] = oldelems[num++]; } for (i = 0; i < 2; i++) { j = i * newsize + offset; for (n = start; n <= end; n++) newelems[j++] = 0; } free(section->parface->data); section->parface->data = newelems; section->parface->dim_vals[0] = newsize; if (cgio_set_dimensions(cg->cgio, section->parface->id, section->parface->data_type, 2, section->parface->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->parface->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } return CG_OK; } int cg_poly_elements_partial_write(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *elements, const cgsize_t *connect_offset) { cgns_section *section; CGNS_ENUMT(ElementType_t) type; int i, elemsize; cgsize_t oldsize; cgsize_t num, size, offset; cgsize_t n, j, newsize, ElementDataSize; cgsize_t *oldelems, *newelems; double id; /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0 || section->connect == 0) return CG_ERROR; num = end - start + 1; type = section->el_type; if (IS_FIXED_SIZE(type)) { cgi_error("element data type should not be of fixed size"); return CG_ERROR; } /* check input range */ if (num <= 0) { cgi_error("Invalid element range for section '%s' elements", section->name); return CG_ERROR; } if (strcmp(CG_SIZE_DATATYPE, section->connect->data_type)) { cgi_error("element data type %s does not match stored value %s", CG_SIZE_DATATYPE, section->connect->data_type); return CG_ERROR; } if (cg->filetype == CG_FILE_ADF2 && adf2_check_elems(type, num, elements)) return CG_ERROR; /* get fill-in element type */ if (cg_npe(type, &elemsize)) return CG_ERROR; if (elemsize <= 0) elemsize = 2; offset = start < section->range[0] ? section->range[0] - start : 0; oldsize = section->range[1] - section->range[0] + 1; ElementDataSize = cgi_element_data_size(type, end - start + 1, elements, connect_offset); if (ElementDataSize < 0) return CG_ERROR; /* NOT FIXED SIZE: NGON_n, NFACE_n, MIXED */ if (connect_offset == NULL){ cgi_error("element offsets not provided for partial write\n"); return CG_ERROR; } if (section->connect_offset == NULL){ cgi_error("missing offsets in section\n"); return CG_ERROR; } if (strcmp(CG_SIZE_DATATYPE, section->connect_offset->data_type)) { cgi_error("element offsets data type %s does not match stored value %s", CG_SIZE_DATATYPE, section->connect_offset->data_type); return CG_ERROR; } if (read_offset_data(section)) return CG_ERROR; cgsize_t s_conn_size, m_conn_size; cgsize_t *section_offset = section->connect_offset->data; int do_it_in_memory = 1; if (start >= section->range[0] && end <= section->range[1]) { s_conn_size = section_offset[end - section->range[0] + 1] - section_offset[start - section->range[0]]; m_conn_size = connect_offset[end - start + 1] - connect_offset[0]; /* use user data */ if (section->connect->data == 0 && (s_conn_size == m_conn_size)){ /* connectivity is of same size */ cgsize_t s_start, s_end, s_stride; cgsize_t m_start, m_end, m_stride, m_dim; cgsize_t ii; s_start = section_offset[start - section->range[0]]; s_end = section_offset[end - section->range[0] + 1] - 1; s_stride = 1; m_start = 1; m_end = m_conn_size; m_dim = m_conn_size; m_stride = 1; if (cgio_write_data(cg->cgio, section->connect->id, &s_start, &s_end, &s_stride, 1, &m_dim, &m_start, &m_end, &m_stride, elements)) { cg_io_error("cgio_write_data"); return CG_ERROR; } /* update offset */ /* memcpy(§ion_offset[start-section->range[0]], connect_offset, (size_t)(end-start+1)*sizeof(cgsize_t)); */ j = start-section->range[0]; for (ii=0; iicgio, section->connect_offset->id, section->connect_offset)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } do_it_in_memory = 0; } } if (do_it_in_memory) { cgsize_t *newoffsets; cgsize_t elemcount; cgsize_t ii; /* got to do it in memory */ if (read_element_data(section)) return CG_ERROR; oldelems = (cgsize_t *)section->connect->data; oldsize = section->connect->dim_vals[0]; newsize = ElementDataSize; elemcount = end-start+1; if (end < section->range[0]) { newsize += oldsize; elemcount += (section->range[1]-section->range[0]+1); num = section->range[0] - end - 1; if (num > 0){ newsize += (elemsize * num); elemcount += num; } } else if (start > section->range[1]) { newsize += oldsize; elemcount += (section->range[1]-section->range[0]+1); num = start - section->range[1] - 1; if (num > 0){ newsize += (elemsize * num); elemcount += num; } } else { /* overlap */ if (start >= section->range[0]) { num = start - section->range[0]; size = section_offset[num] - section_offset[0]; if (size < 0) return CG_ERROR; newsize += size; elemcount += num; } if (end <= section->range[1]) { num = end - section->range[0] + 1; size = section_offset[section->range[1]-section->range[0]+1] - section_offset[num]; if (size < 0) return CG_ERROR; newsize += size; elemcount += (section->range[1] - end); } } /* create new element connectivity array and offsets*/ newelems = (cgsize_t *) malloc ((size_t)(newsize * sizeof(cgsize_t))); newoffsets = (cgsize_t *) malloc((size_t)((elemcount+1) * sizeof(cgsize_t))); if (NULL == newelems) { cgi_error("Error allocating new connectivity data"); return CG_ERROR; } if (NULL == newoffsets) { cgi_error("Error allocating new connectivity offset data"); return CG_ERROR; } newoffsets[0] = 0; n = 0; j = 0; if (start <= section->range[0]) { memcpy(newelems, elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); memcpy(newoffsets, connect_offset, (size_t)((end-start+2)*sizeof(cgsize_t))); j += (end-start+1); n += ElementDataSize; if (end < section->range[0]) { num = section->range[0] - end - 1; cgsize_t val = (type == CGNS_ENUMV(MIXED) ? (cgsize_t)CGNS_ENUMV(NODE) : 0); while (num-- > 0) { newelems[n++] = val; newelems[n++] = 0; newoffsets[j+1] = newoffsets[j] + 2; j++; n++; } memcpy(&newelems[n], oldelems, (size_t)(oldsize*sizeof(cgsize_t))); n += oldsize; for (ii=0; ii<(section->range[1]-section->range[0]+1); ii++) { newoffsets[j+1] = (section_offset[ii+1] - section_offset[ii]) + newoffsets[j]; j++; } } else if (end < section->range[1]) { num = end - section->range[0] + 1; offset = section_offset[end - section->range[0] + 1]; if (offset < 0) return CG_ERROR; size = section_offset[section->range[1]-section->range[0]+1] - section_offset[num]; memcpy(&newelems[n], &oldelems[offset], (size_t)(size*sizeof(cgsize_t))); n += size; for (ii=num; ii<(section->range[1]-section->range[0]+1); ii++) { newoffsets[j+1] = (section_offset[ii+1] - section_offset[ii]) + newoffsets[j]; j++; } } } else if (start > section->range[1]) { cgsize_t ii; memcpy(newelems, oldelems, (size_t)(oldsize*sizeof(cgsize_t))); memcpy(newoffsets, section_offset, (size_t)((section->range[1]-section->range[0]+2)*sizeof(cgsize_t))); n += oldsize; j += section->range[1]-section->range[0]+1; num = start - section->range[1] - 1; cgsize_t val = (type == CGNS_ENUMV(MIXED) ? (cgsize_t)CGNS_ENUMV(NODE) : 0); while (num-- > 0) { newelems[n++] = val; newelems[n++] = 0; newoffsets[j+1] = newoffsets[j] + 2; j++; n++; } memcpy(&newelems[n], elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); n += ElementDataSize; for (ii=0; ii<(end-start+1); ii++) { newoffsets[j+1] = (connect_offset[ii+1] - connect_offset[ii]) + newoffsets[j]; j++; } } else { cgsize_t ii; num = start - section->range[0]; size = section_offset[num]; memcpy(newelems, oldelems, (size_t)(size*sizeof(cgsize_t))); memcpy(newoffsets, section_offset, (size_t)(num+1)*sizeof(cgsize_t)); n += size; j += num; memcpy(&newelems[n], elements, (size_t)(ElementDataSize*sizeof(cgsize_t))); for (ii=0; ii<(end-start+1); ii++) { newoffsets[j+1] = (connect_offset[ii+1] - connect_offset[ii]) + newoffsets[j]; j++; } n += ElementDataSize; if (end < section->range[1]) { num = end - section->range[0] + 1; offset = section_offset[num]; if (offset < 0) { free(newelems); free(newoffsets); return CG_ERROR; } size = oldsize - offset; memcpy(&newelems[n], &oldelems[offset], (size_t)(size*sizeof(cgsize_t))); n += size; for (ii=num; ii<(section->range[1]-section->range[0]+1); ii++) { newoffsets[j+1] = (section_offset[ii+1] - section_offset[ii]) + newoffsets[j]; j++; } } } if (n != newsize) { free(newelems); free(newoffsets); cgi_error("my counting is off !!!\n"); return CG_ERROR; } free(section->connect->data); free(section->connect_offset->data); section->connect->dim_vals[0] = newsize; section->connect->data = newelems; section->connect_offset->dim_vals[0] = elemcount+1; section->connect_offset->data = newoffsets; /* update ranges */ if (start < section->range[0]) section->range[0] = start; if (end > section->range[1]) section->range[1] = end; /* update ElementRange */ if (cgio_get_node_id(cg->cgio, section->id, "ElementRange", &id)) { cg_io_error("cgio_get_node_id"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, id, section->range)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } /* update Offsets */ if (cgio_set_dimensions(cg->cgio, section->connect_offset->id, section->connect_offset->data_type, 1, section->connect_offset->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->connect_offset->id, newoffsets)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } /* update ElementConnectivity */ if (cgio_set_dimensions(cg->cgio, section->connect->id, section->connect->data_type, 1, section->connect->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->connect->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } /* update the parent data array if it exists */ newsize = section->range[1] - section->range[0] + 1; if (section->parelem && (section->parface || 0 == strcmp(section->parelem->name, "ParentData")) && newsize != section->parelem->dim_vals[0]) { int cnt = section->parelem->dim_vals[1]; if (read_parent_data(section)) return CG_ERROR; newelems = (cgsize_t *)malloc((size_t)(cnt * newsize * sizeof(cgsize_t))); if (NULL == newelems) { cgi_error("Error alocating new ParentElements data"); return CG_ERROR; } offset = start - section->range[0]; for (n = 0; n < cnt*newsize; n++) newelems[n] = 0; oldelems = (cgsize_t *)section->parelem->data; for (num = 0, i = 0; i < cnt; i++) { j = i * newsize + offset; for (n = 0; n < oldsize; n++) newelems[j++] = oldelems[num++]; } for (i = 0; i < cnt; i++) { j = i * newsize + offset; for (n = start; n <= end; n++) newelems[j++] = 0; } free(section->parelem->data); section->parelem->data = newelems; section->parelem->dim_vals[0] = newsize; if (cgio_set_dimensions(cg->cgio, section->parelem->id, section->parelem->data_type, 2, section->parelem->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->parelem->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } if (0 == strcmp(section->parelem->name, "ParentData")) return CG_OK; for (n = 0; n < 2*newsize; n++) newelems[n] = 0; oldelems = (cgsize_t *)section->parface->data; for (num = 0, i = 0; i < 2; i++) { j = i * newsize + offset; for (n = 0; n < oldsize; n++) newelems[j++] = oldelems[num++]; } for (i = 0; i < 2; i++) { j = i * newsize + offset; for (n = start; n <= end; n++) newelems[j++] = 0; } free(section->parface->data); section->parface->data = newelems; section->parface->dim_vals[0] = newsize; if (cgio_set_dimensions(cg->cgio, section->parface->id, section->parface->data_type, 2, section->parface->dim_vals)) { cg_io_error("cgio_set_dimensions"); return CG_ERROR; } if (cgio_write_all_data(cg->cgio, section->parface->id, newelems)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_parent_data_write(int file_number, int B, int Z, int S, const cgsize_t * parent_data) { cgns_section *section; cgsize_t num; /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; num = section->range[1]-section->range[0]+1; if (section->parelem) { if (cg->mode==CG_MODE_WRITE) { cgi_error("ParentElements is already defined under Elements_t '%s'", section->name); return CG_ERROR; } if (cgi_delete_node(section->id, section->parelem->id)) return CG_ERROR; cgi_free_array(section->parelem); memset(section->parelem, 0, sizeof(cgns_array)); } else { section->parelem = CGNS_NEW(cgns_array, 1); } strcpy(section->parelem->data_type, CG_SIZE_DATATYPE); section->parelem->data_dim =2; section->parelem->dim_vals[0]=num; if (cg->filetype == CG_FILE_ADF2) { strcpy(section->parelem->name, "ParentData"); section->parelem->dim_vals[1]=4; } else { strcpy(section->parelem->name, "ParentElements"); section->parelem->dim_vals[1]=2; } if (cgi_write_array(section->id, section->parelem)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section->parelem->id, parent_data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } if (cg->filetype == CG_FILE_ADF2) { if (section->parface) { if (cgi_delete_node(section->id, section->parface->id)) return CG_ERROR; cgi_free_array(section->parface); CGNS_FREE(section->parface); section->parface = NULL; } return CG_OK; } if (section->parface) { if (cg->mode==CG_MODE_WRITE) { cgi_error("ParentElementsPosition is already defined under Elements_t '%s'", section->name); return CG_ERROR; } if (cgi_delete_node(section->id, section->parface->id)) return CG_ERROR; cgi_free_array(section->parface); memset(section->parface, 0, sizeof(cgns_array)); } else { section->parface = CGNS_NEW(cgns_array, 1); } strcpy(section->parface->data_type, CG_SIZE_DATATYPE); strcpy(section->parface->name, "ParentElementsPosition"); section->parface->data_dim =2; section->parface->dim_vals[0]=num; section->parface->dim_vals[1]=2; if (cgi_write_array(section->id, section->parface)) return CG_ERROR; if (cgio_write_all_data(cg->cgio, section->parface->id, &parent_data[num<<1])) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } return CG_OK; } int cg_parent_data_partial_write(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *parent_data) { cgns_section *section; cgsize_t *data, i, j, n; cgsize_t num, size, offset; /* get file and check mode */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; section = cgi_get_section(cg, B, Z, S); if (section == 0) return CG_ERROR; /* check input range */ if (start < section->range[0] || end > section->range[1] || start > end) { cgi_error("Invalid element range for section '%s' parent data", section->name); return CG_ERROR; } size = section->range[1] - section->range[0] + 1; offset = start - section->range[0]; /* create the parent data if it doesn't exist already */ if (section->parelem == 0) { section->parelem = CGNS_NEW(cgns_array, 1); strcpy(section->parelem->data_type, CG_SIZE_DATATYPE); section->parelem->data_dim =2; section->parelem->dim_vals[0]=size; if (cg->filetype == CG_FILE_ADF2) { strcpy(section->parelem->name, "ParentData"); section->parelem->dim_vals[1]=4; } else { strcpy(section->parelem->name, "ParentElements"); section->parelem->dim_vals[1]=2; } if (cgi_write_array(section->id, section->parelem)) return CG_ERROR; } else if (strcmp(CG_SIZE_DATATYPE, section->parelem->data_type)) { cgi_error("ParentElements data type %s does not match stored value %s", CG_SIZE_DATATYPE, section->parelem->data_type); return CG_ERROR; } if (size != section->parelem->dim_vals[0]) { cgi_error("internal errror - invalid ParentElements data size !!!"); return CG_ERROR; } if (strcmp(section->parelem->name, "ParentData")) { if (section->parface == 0) { section->parface = CGNS_NEW(cgns_array, 1); strcpy(section->parface->data_type, CG_SIZE_DATATYPE); strcpy(section->parface->name, "ParentElementsPosition"); section->parface->data_dim =2; section->parface->dim_vals[0]=size; section->parface->dim_vals[1]=2; if (cgi_write_array(section->id, section->parface)) return CG_ERROR; } else if (strcmp(CG_SIZE_DATATYPE, section->parface->data_type)) { cgi_error("ParentElementsPosition data type %s does not match stored value %s", CG_SIZE_DATATYPE, section->parface->data_type); return CG_ERROR; } if (size != section->parface->dim_vals[0]) { cgi_error("internal errror - invalid ParentElementsPosition data size !!!"); return CG_ERROR; } } if (start >= section->range[0] && end <= section->range[1]) { cgsize_t s_start[2], s_end[2], s_stride[2]; cgsize_t m_start[2], m_end[2], m_stride[2], m_dim[2]; s_start[0] = start - section->range[0] + 1; s_end[0] = end - section->range[0] + 1; s_stride[0]= 1; s_start[1] = 1; s_end[1] = section->parelem->dim_vals[1]; s_stride[1]= 1; m_start[0] = 1; m_end[0] = end - start + 1; m_stride[0]= 1; m_start[1] = 1; m_end[1] = section->parelem->dim_vals[1]; m_stride[1]= 1; m_dim[0] = m_end[0]; m_dim[1] = 4; if (cgio_write_data(cg->cgio, section->parelem->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_write_data"); return CG_ERROR; } if (strcmp(section->parelem->name, "ParentData")) { m_start[1] = 3; m_end[1] = 4; if (cgio_write_data(cg->cgio, section->parface->id, s_start, s_end, s_stride, 2, m_dim, m_start, m_end, m_stride, parent_data)) { cg_io_error("cgio_write_data"); return CG_ERROR; } } free_parent_data(section); } else { int cnt = section->parelem->dim_vals[1]; if (read_parent_data(section)) return CG_ERROR; data = (cgsize_t *)section->parelem->data; for (i = 0, num = 0; num < cnt; num++) { j = num * size + offset; for (n = start; n <= end; n++) data[j++] = parent_data[i++]; } if (cgio_write_all_data(cg->cgio, section->parelem->id, data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } if (strcmp(section->parelem->name, "ParentData")) { data = (cgsize_t *)section->parface->data; for (i = 0, num = 2; num < 4; num++) { j = num * size + offset; for (n = start; n <= end; n++) data[j++] = parent_data[i++]; } if (cgio_write_all_data(cg->cgio, section->parface->id, data)) { cg_io_error("cgio_write_all_data"); return CG_ERROR; } } } return CG_OK; } /*****************************************************************************\ * Read and Write FlowSolution_t Nodes \*****************************************************************************/ int cg_nsols(int file_number, int B, int Z, int *nsols) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *nsols = zone->nsols; return CG_OK; } int cg_sol_info(int file_number, int B, int Z, int S, char *solname, CGNS_ENUMT(GridLocation_t) *location) { cgns_sol *sol; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; strcpy(solname, sol->name); *location = sol->location; return CG_OK; } int cg_sol_id(int file_number, int B, int Z, int S, double *sol_id) { cgns_sol *sol; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; *sol_id = sol->id; return CG_OK; } int cg_sol_write(int file_number, int B, int Z, const char * solname, CGNS_ENUMT(GridLocation_t) location, int *S) { cgns_zone *zone; cgns_sol *sol = NULL; int index, n, index_dim; /* verify input */ if (cgi_check_strlen(solname)) return CG_ERROR; if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(CellCenter) && location != CGNS_ENUMV(IFaceCenter) && location != CGNS_ENUMV(JFaceCenter) && location != CGNS_ENUMV(KFaceCenter)) { cgi_error("Given grid location not supported for FlowSolution_t"); return CG_ERROR; } /* if (INVALID_ENUM(location,NofValidGridLocation)) { cgi_error("Invalid input: GridLocation=%d ?",location); return CG_ERROR; } */ /* get memory address for FlowSolution node */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; if (zone->type != CGNS_ENUMV(Structured) && (location == CGNS_ENUMV(IFaceCenter) || location == CGNS_ENUMV(JFaceCenter) || location == CGNS_ENUMV(KFaceCenter))) { cgi_error ("GridLocation [IJK]FaceCenter only valid for Structured grid"); return CG_ERROR; } /* Overwrite a FlowSolution_t Node: */ for (index=0; indexnsols; index++) { if (strcmp(solname, zone->sol[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",solname); return CG_ERROR; } /* overwrite an existing solution */ /* delete the existing solution from file */ if (cgi_delete_node(zone->id, zone->sol[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ sol = &(zone->sol[index]); /* free memory */ cgi_free_sol(sol); break; } } /* ... or add a FlowSolution_t Node: */ if (index==zone->nsols) { if (zone->nsols == 0) { zone->sol = CGNS_NEW(cgns_sol, zone->nsols+1); } else { zone->sol = CGNS_RENEW(cgns_sol, zone->nsols+1, zone->sol); } sol = &(zone->sol[zone->nsols]); zone->nsols++; } (*S) = index+1; /* save data in memory */ memset(sol, 0, sizeof(cgns_sol)); strcpy(sol->name,solname); sol->location = location; index_dim = zone->index_dim; sol->rind_planes = (int *)malloc(index_dim*2*sizeof(int)); if (sol->rind_planes == NULL) { cgi_error("Error allocating sol->rind_plane."); return CG_ERROR; } for (n=0; nrind_planes[2*n]=sol->rind_planes[2*n+1]=0; /* save data in file */ if (cgi_new_node(zone->id, sol->name, "FlowSolution_t", &sol->id, "MT", 0, 0, 0)) return CG_ERROR; if (sol->location != CGNS_ENUMV(Vertex)) { cgsize_t length = (cgsize_t)strlen(GridLocationName[sol->location]); double GL_id; if (cgi_new_node(sol->id, "GridLocation", "GridLocation_t", &GL_id, "C1", 1, &length, (void *)GridLocationName[sol->location])) return CG_ERROR; } return CG_OK; } int cg_sol_size(int file_number, int B, int Z, int S, int *data_dim, cgsize_t *dim_vals) { cgns_sol *sol; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; if (sol->ptset == NULL) { cgns_zone *zone = &cg->base[B-1].zone[Z-1]; *data_dim = zone->index_dim; if (cgi_datasize(zone->index_dim, zone->nijk, sol->location, sol->rind_planes, dim_vals)) return CG_ERROR; } else { *data_dim = 1; dim_vals[0] = sol->ptset->size_of_patch; } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_sol_ptset_info(int fn, int B, int Z, int S, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts) { cgns_sol *sol; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; if (sol->ptset == NULL) { *ptset_type = CGNS_ENUMV(PointSetTypeNull); *npnts = 0; } else { *ptset_type = sol->ptset->type; *npnts = sol->ptset->npts; } return CG_OK; } int cg_sol_ptset_read(int fn, int B, int Z, int S, cgsize_t *pnts) { int dim = 0; cgns_sol *sol; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; if (sol->ptset == 0 || sol->ptset->npts <= 0) { cgi_error("PointSet not defined for FlowSolution node %d\n", S); return CG_ERROR; } cg_index_dim(fn, B, Z, &dim); if (cgi_read_int_data(sol->ptset->id, sol->ptset->data_type, sol->ptset->npts * dim, pnts)) return CG_ERROR; return CG_OK; } int cg_sol_ptset_write(int fn, int B, int Z, const char *solname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *S) { int i, index_dim = 0; cgsize_t cnt, dim_vals = 1; cgns_sol *sol; char_33 PointSetName; double id; /* verify input */ if (!((ptset_type == CGNS_ENUMV(PointList) && npnts > 0) || (ptset_type == CGNS_ENUMV(PointRange) && npnts == 2))) { cgi_error("Invalid input: npoint=%ld, point set type=%s", (long)npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } if (cg_index_dim(fn, B, Z, &index_dim)) return CG_ERROR; if (cgi_check_location(cg->base[B-1].cell_dim, cg->base[B-1].zone[Z-1].type, location)) return CG_ERROR; if (cg_sol_write(fn, B, Z, solname, CGNS_ENUMV(Vertex), S)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, *S); if (sol == 0) return CG_ERROR; sol->location = location; sol->ptset = CGNS_NEW(cgns_ptset, 1); sol->ptset->type = ptset_type; strcpy(sol->ptset->data_type,CG_SIZE_DATATYPE); sol->ptset->npts = npnts; if (ptset_type == CGNS_ENUMV(PointList)) { sol->ptset->size_of_patch = npnts; } else { sol->ptset->size_of_patch = 1; for (i = 0; i < index_dim; i++) { cnt = pnts[i+index_dim] - pnts[i]; if (cnt < 0) cnt = -cnt; sol->ptset->size_of_patch *= (cnt + 1); } } strcpy(PointSetName, PointSetTypeName[ptset_type]); if (cgi_write_ptset(sol->id, PointSetName, sol->ptset, index_dim, (void *)pnts)) return CG_ERROR; if (location != CGNS_ENUMV(Vertex)) { dim_vals = (cgsize_t)strlen(GridLocationName[location]); if (cgi_new_node(sol->id, "GridLocation", "GridLocation_t", &id, "C1", 1, &dim_vals, (void *)GridLocationName[location])) return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * Read and Write flow field DataArray_t Nodes \*****************************************************************************/ int cg_nfields(int file_number, int B, int Z, int S, int *nfields) { cgns_sol *sol; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; sol = cgi_get_sol(cg, B, Z, S); if (sol==0) return CG_ERROR; *nfields = sol->nfields; return CG_OK; } int cg_field_info(int file_number, int B, int Z, int S, int F, CGNS_ENUMT(DataType_t) *type, char *fieldname) { cgns_array *field; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; field = cgi_get_field(cg, B, Z, S, F); if (field==0) return CG_ERROR; strcpy(fieldname, field->name); *type = cgi_datatype(field->data_type); return CG_OK; } int cg_field_read(int file_number, int B, int Z, int S, const char *fieldname, CGNS_ENUMT(DataType_t) type, const cgsize_t *s_rmin, const cgsize_t *s_rmax, void *field_ptr) { cgns_sol *sol; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* get memory address for solution */ sol = cgi_get_sol(cg, B, Z, S); if (sol == 0) return CG_ERROR; if (sol->ptset == NULL) /* sol implies zone exists */ m_numdim = cg->base[B-1].zone[Z-1].index_dim; else m_numdim = 1; /* verify that range requested does not exceed range stored */ if (s_rmin == NULL || s_rmax == NULL) { cgi_error("NULL range value."); return CG_ERROR; } cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; nfilename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for solution */ sol = cgi_get_sol(cg, B, Z, S); if (sol == 0) return CG_ERROR; /* find the field address in the database */ field = 0; for (f=0; fnfields; f++) { if (strcmp(sol->field[f].name, fieldname) == 0) { field = cgi_get_field(cg, B, Z, S, f+1); if (field == 0) return CG_ERROR; break; } } if (field == 0) { cgi_error("Flow solution array %s not found",fieldname); return CG_NODE_NOT_FOUND; } if (sol->ptset == NULL) s_numdim = cg->base[B-1].zone[Z-1].index_dim; else s_numdim = 1; return cgi_array_general_read(field, cgns_rindindex, sol->rind_planes, s_numdim, s_rmin, s_rmax, m_type, m_numdim, m_dimvals, m_rmin, m_rmax, field_ptr); } int cg_field_id(int file_number, int B, int Z, int S, int F, double *field_id) { cgns_array *field; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; field = cgi_get_field(cg, B, Z, S, F); if (field==0) return CG_ERROR; *field_id = field->id; return CG_OK; } int cg_field_write(int file_number, int B, int Z, int S, CGNS_ENUMT(DataType_t) type, const char *fieldname, const void *field_ptr, int *F) { cgns_zone *zone; cgns_sol *sol; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; /* get memory address for solution */ sol = cgi_get_sol(cg, B, Z, S); if (sol == 0) return CG_ERROR; /* dimension is dependent on multidim or ptset */ cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; if (sol->ptset == NULL) { m_numdim = zone->index_dim; if (cgi_datasize(m_numdim, zone->nijk, sol->location, sol->rind_planes, m_dimvals)) return CG_ERROR; } else { m_numdim = 1; m_dimvals[0] = sol->ptset->size_of_patch; } cgsize_t s_rmin[CGIO_MAX_DIMENSIONS], s_rmax[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; n < m_numdim; n++) { if (cgns_rindindex == CG_CONFIG_RIND_ZERO) { /* old obsolete behavior (versions < 3.4) */ s_rmin[n] = 1; } else { /* new behavior consitent with SIDS */ s_rmin[n] = 1 - sol->rind_planes[2*n]; } s_rmax[n] = s_rmin[n] + m_dimvals[n] - 1; m_rmin[n] = 1; m_rmax[n] = m_dimvals[n]; } return cg_field_general_write(file_number, B, Z, S, fieldname, type, s_rmin, s_rmax, type, m_numdim, m_dimvals, m_rmin, m_rmax, field_ptr, F); } int cg_field_partial_write(int file_number, int B, int Z, int S, CGNS_ENUMT( DataType_t ) type, const char *fieldname, const cgsize_t *s_rmin, const cgsize_t *s_rmax, const void *field_ptr, int *F) { cgns_zone *zone; cgns_sol *sol; int n, m_numdim; /* get memory addresses */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; /* get memory address for solution */ sol = cgi_get_sol(cg, B, Z, S); if (sol == 0) return CG_ERROR; /* dimension is dependent on multidim or ptset */ if (sol->ptset == NULL) { m_numdim = zone->index_dim; } else { m_numdim = 1; } if (s_rmin == NULL || s_rmax == NULL) { cgi_error("NULL range value."); return CG_ERROR; } cgsize_t m_dimvals[CGIO_MAX_DIMENSIONS]; cgsize_t m_rmin[CGIO_MAX_DIMENSIONS], m_rmax[CGIO_MAX_DIMENSIONS]; for (n = 0; nfilename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone == 0) return CG_ERROR; /* get memory address for solution */ sol = cgi_get_sol(cg, B, Z, S); if (sol == 0) return CG_ERROR; /* file dimension is dependent on multidim or ptset */ cgsize_t s_dimvals[CGIO_MAX_DIMENSIONS]; if (sol->ptset == NULL) { s_numdim = zone->index_dim; if (cgi_datasize(s_numdim, zone->nijk, sol->location, sol->rind_planes, s_dimvals)) return CG_ERROR; } else { s_numdim = 1; s_dimvals[0] = sol->ptset->size_of_patch; } return cgi_array_general_write(sol->id, &(sol->nfields), &(sol->field), fieldname, cgns_rindindex, sol->rind_planes, s_type, s_numdim, s_dimvals, s_rmin, s_rmax, m_type, m_numdim, m_dimvals, m_rmin, m_rmax, field_ptr, F); } /*************************************************************************\ * Read and write ZoneSubRegion_t Nodes * \*************************************************************************/ int cg_nsubregs(int fn, int B, int Z, int *nsubreg) { cgns_zone *zone; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; (*nsubreg) = zone->nsubreg; return CG_OK; } static cgns_subreg *cg_subreg_read(int fn, int B, int Z, int S) { cg = cgi_get_file(fn); if (cg == 0) return NULL; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return NULL; return cgi_get_subreg(cg, B, Z, S); } int cg_subreg_info(int fn, int B, int Z, int S, char *name, int *dimension, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, int *bcname_len, int *gcname_len) { cgns_subreg *subreg = cg_subreg_read(fn, B, Z, S); if (subreg == NULL) return CG_ERROR; strcpy(name,subreg->name); *dimension = subreg->reg_dim; *location = subreg->location; if (subreg->ptset) { *ptset_type = subreg->ptset->type; *npnts = subreg->ptset->npts; } else { *ptset_type = CGNS_ENUMV(PointSetTypeNull); *npnts = 0; } if (subreg->bcname) { *bcname_len = (int)strlen(subreg->bcname->text); } else { *bcname_len = 0; } if (subreg->gcname) { *gcname_len = (int)strlen(subreg->gcname->text); } else { *gcname_len = 0; } return CG_OK; } int cg_subreg_ptset_read(int fn, int B, int Z, int S, cgsize_t *pnts) { int dim = 0; cgns_subreg *subreg = cg_subreg_read(fn, B, Z, S); if (subreg == NULL) return CG_ERROR; if (subreg->ptset == 0 || subreg->ptset->npts <= 0) { cgi_error("PointSet not defined for ZoneSubRegion node %d\n", S); return CG_ERROR; } cg_index_dim(fn, B, Z, &dim); if (cgi_read_int_data(subreg->ptset->id, subreg->ptset->data_type, subreg->ptset->npts * dim, pnts)) return CG_ERROR; return CG_OK; } int cg_subreg_bcname_read(int fn, int B, int Z, int S, char *bcname) { cgns_subreg *subreg = cg_subreg_read(fn, B, Z, S); if (subreg == NULL) return CG_ERROR; if (subreg->bcname == 0) { cgi_error("BCRegionName not defined for ZoneSubRegion node %d\n", S); return CG_ERROR; } strcpy(bcname, subreg->bcname->text); return CG_OK; } int cg_subreg_gcname_read(int fn, int B, int Z, int S, char *gcname) { cgns_subreg *subreg = cg_subreg_read(fn, B, Z, S); if (subreg == NULL) return CG_ERROR; if (subreg->gcname == 0) { cgi_error("GridConnectivityRegionName not defined for ZoneSubRegion node %d\n", S); return CG_ERROR; } strcpy(gcname, subreg->gcname->text); return CG_OK; } static cgns_subreg *cg_subreg_write(int fn, int B, int Z, const char *name, int dimension, int *S) { cgns_zone *zone; cgns_subreg *subreg = NULL; int index, cell_dim; /* verify input */ if (cgi_check_strlen(name)) return NULL; if (cg_cell_dim(fn, B, &cell_dim)) return NULL; if (dimension < 1 || dimension > cell_dim) { cgi_error("invalid RegionCellDimension for ZoneSubRegion %s", name); return NULL; } /* get memory address */ cg = cgi_get_file(fn); if (cg == NULL) return NULL; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return NULL; zone = cgi_get_zone(cg, B, Z); if (zone == NULL) return NULL; /* Overwrite a ZoneSubRegion_t Node: */ for (index = 0; index < zone->nsubreg; index++) { if (0 == strcmp(name, zone->subreg[index].name)) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode == CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",name); return NULL; } /* overwrite an existing ZoneGridConnectivity_t node */ /* delete the existing ZoneGridConnectivity_t from file */ if (cgi_delete_node(zone->id, zone->subreg[index].id)) return NULL; /* save the old in-memory address to overwrite */ subreg = &(zone->subreg[index]); /* free memory */ cgi_free_subreg(subreg); break; } } /* ... or add a ZoneGridConnectivity_t Node: */ if (index == zone->nsubreg) { if (zone->nsubreg == 0) { zone->subreg = CGNS_NEW(cgns_subreg, 1); } else { zone->subreg = CGNS_RENEW(cgns_subreg, zone->nsubreg+1, zone->subreg); } subreg = &(zone->subreg[zone->nsubreg]); zone->nsubreg++; } (*S) = index+1; memset(subreg, 0, sizeof(cgns_subreg)); strcpy(subreg->name, name); subreg->reg_dim = dimension; return subreg; } int cg_subreg_ptset_write(int fn, int B, int Z, const char *name, int dimension, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *S) { int i, index_dim = 0; cgsize_t cnt, dim_vals = 1; cgns_zone *zone; cgns_subreg *subreg; char_33 PointSetName; double id; /* verify input */ if (!((ptset_type == CGNS_ENUMV(PointList) && npnts > 0) || (ptset_type == CGNS_ENUMV(PointRange) && npnts == 2))) { cgi_error("Invalid input: npoint=%ld, point set type=%s", (long)npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } if (cg_index_dim(fn, B, Z, &index_dim)) return CG_ERROR; if (cgi_check_location(dimension+1, cg->base[B-1].zone[Z-1].type, location)) return CG_ERROR; subreg = cg_subreg_write(fn, B, Z, name, dimension, S); if (subreg == NULL) return CG_ERROR; subreg->location = location; subreg->ptset = CGNS_NEW(cgns_ptset, 1); subreg->ptset->type = ptset_type; strcpy(subreg->ptset->data_type,CG_SIZE_DATATYPE); subreg->ptset->npts = npnts; if (ptset_type == CGNS_ENUMV(PointList)) { subreg->ptset->size_of_patch = npnts; } else { subreg->ptset->size_of_patch = 1; for (i = 0; i < index_dim; i++) { cnt = pnts[i+index_dim] - pnts[i]; if (cnt < 0) cnt = -cnt; subreg->ptset->size_of_patch *= (cnt + 1); } } /* save data in file */ zone = cgi_get_zone(cg, B, Z); if (cgi_new_node(zone->id, subreg->name, "ZoneSubRegion_t", &subreg->id, "I4", 1, &dim_vals, &subreg->reg_dim)) return CG_ERROR; strcpy(PointSetName, PointSetTypeName[subreg->ptset->type]); if (cgi_write_ptset(subreg->id, PointSetName, subreg->ptset, index_dim, (void *)pnts)) return CG_ERROR; if (location != CGNS_ENUMV(Vertex)) { dim_vals = (cgsize_t)strlen(GridLocationName[location]); if (cgi_new_node(subreg->id, "GridLocation", "GridLocation_t", &id, "C1", 1, &dim_vals, (void *)GridLocationName[location])) return CG_ERROR; } return CG_OK; } int cg_subreg_bcname_write(int fn, int B, int Z, const char *name, int dimension, const char *bcname, int *S) { cgsize_t dim_vals = 1; cgns_zone *zone; cgns_subreg *subreg; if (bcname == NULL || !*bcname) { cgi_error("BCRegionName not given"); return CG_ERROR; } subreg = cg_subreg_write(fn, B, Z, name, dimension, S); if (subreg == NULL) return CG_ERROR; subreg->bcname = CGNS_NEW(cgns_descr, 1); strcpy(subreg->bcname->name, "BCRegionName"); subreg->bcname->text = (char *)malloc(strlen(bcname)+1); if (subreg->bcname->text == NULL) { cgi_error("malloc failed for BCRegionName name"); return CG_ERROR; } strcpy(subreg->bcname->text, bcname); /* save data in file */ zone = cgi_get_zone(cg, B, Z); if (cgi_new_node(zone->id, subreg->name, "ZoneSubRegion_t", &subreg->id, "I4", 1, &dim_vals, &subreg->reg_dim)) return CG_ERROR; if (cgi_write_descr(subreg->id, subreg->bcname)) return CG_ERROR; return CG_OK; } int cg_subreg_gcname_write(int fn, int B, int Z, const char *name, int dimension, const char *gcname, int *S) { cgsize_t dim_vals = 1; cgns_zone *zone; cgns_subreg *subreg; if (gcname == NULL || !*gcname) { cgi_error("GridConnectivityRegionName not given"); return CG_ERROR; } subreg = cg_subreg_write(fn, B, Z, name, dimension, S); if (subreg == NULL) return CG_ERROR; subreg->gcname = CGNS_NEW(cgns_descr, 1); strcpy(subreg->gcname->name, "GridConnectivityRegionName"); subreg->gcname->text = (char *)malloc(strlen(gcname)+1); if (subreg->gcname->text == NULL) { cgi_error("malloc failed for GridConnectivityRegionName name"); return CG_ERROR; } strcpy(subreg->gcname->text, gcname); /* save data in file */ zone = cgi_get_zone(cg, B, Z); if (cgi_new_node(zone->id, subreg->name, "ZoneSubRegion_t", &subreg->id, "I4", 1, &dim_vals, &subreg->reg_dim)) return CG_ERROR; if (cgi_write_descr(subreg->id, subreg->gcname)) return CG_ERROR; return CG_OK; } /*************************************************************************\ * Read and write ZoneGridConnectivity_t Nodes * \*************************************************************************/ int cg_nzconns(int fn, int B, int Z, int *nzconns) { cgns_zone *zone; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; (*nzconns) = zone->nzconn; return CG_OK; } int cg_zconn_read(int fn, int B, int Z, int C, char *name) { cgns_zconn *zconn; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* Get memory address for ZoneGridConnectivity_t node */ /* cgi_get_zconnZC() also sets active ZoneGridConnectivity_t node */ zconn = cgi_get_zconnZC(cg, B, Z, C); if (zconn==0) return CG_ERROR; /* Return name for the ZoneGridConnectivity_t node */ strcpy(name,zconn->name); return CG_OK; } int cg_zconn_write(int fn, int B, int Z, const char *name, int *C) { cgns_zone *zone; cgns_zconn *zconn = NULL; int index; /* verify input */ if (cgi_check_strlen(name)) return CG_ERROR; /* get memory address */ cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a ZoneGridConnectivity_t Node: */ for (index = 0; index < zone->nzconn; index++) { if (0 == strcmp(name, zone->zconn[index].name)) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode == CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",name); return CG_ERROR; } /* overwrite an existing ZoneGridConnectivity_t node */ /* delete the existing ZoneGridConnectivity_t from file */ if (cgi_delete_node(zone->id, zone->zconn[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ zconn = &(zone->zconn[index]); /* free memory */ cgi_free_zconn(zconn); break; } } /* ... or add a ZoneGridConnectivity_t Node: */ if (index == zone->nzconn) { if (zone->nzconn == 0) { zone->zconn = CGNS_NEW(cgns_zconn, 1); } else { zone->zconn = CGNS_RENEW(cgns_zconn, zone->nzconn+1, zone->zconn); } zconn = &(zone->zconn[zone->nzconn]); zone->nzconn++; } (*C) = index+1; zone->active_zconn = *C; memset(zconn, 0, sizeof(cgns_zconn)); strcpy(zconn->name,name); /* save data in file */ if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } int cg_zconn_get(int fn, int B, int Z, int *C) { cgns_zone *zone; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; /* Get memory address for zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; if (zone->nzconn <= 0) { *C = 0; cgi_error("no ZoneGridConnectivity_t node found."); return CG_NODE_NOT_FOUND; } if (zone->active_zconn <= 0 || zone->active_zconn > zone->nzconn) zone->active_zconn = 1; *C = zone->active_zconn; return CG_OK; } int cg_zconn_set(int fn, int B, int Z, int C) { cgns_zconn *zconn; cg = cgi_get_file(fn); if (cg == 0) return CG_ERROR; /* Get memory address for ZoneGridConnectivity_t node */ /* cgi_get_zconnZC() also sets active ZoneGridConnectivity_t node */ zconn = cgi_get_zconnZC(cg, B, Z, C); if (zconn==0) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and Write OversetHoles_t Nodes \*****************************************************************************/ int cg_nholes(int file_number, int B, int Z, int *nholes) { cgns_zconn *zconn; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) *nholes = 0; /* if ZoneGridConnectivity_t is undefined */ else *nholes = zconn->nholes; return CG_OK; } int cg_hole_info(int file_number, int B, int Z, int I, char *holename, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, int *nptsets, cgsize_t *npnts) { cgns_hole *hole; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; hole = cgi_get_hole(cg, B, Z, I); if (hole==0) return CG_ERROR; strcpy(holename, hole->name); *location = hole->location; *ptset_type = hole->nptsets ? hole->ptset[0].type : CGNS_ENUMV(PointSetTypeNull); *nptsets = hole->nptsets; /* if multiple pointsets are defined, only PointRange is allowed */ if (hole->nptsets==1) *npnts = hole->ptset[0].npts; else *npnts = 2*hole->nptsets; return CG_OK; } int cg_hole_read(int file_number, int B, int Z, int I, cgsize_t *pnts) { cgns_hole *hole; int set, index_dim; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; hole = cgi_get_hole(cg, B, Z, I); if (hole==0) return CG_ERROR; index_dim = cg->base[B-1].zone[Z-1].index_dim; /* read point-set directly from ADF file */ if (hole->nptsets > 1) { for (set = 0; set < hole->nptsets; set++) { if (hole->ptset[set].npts > 0) { if (cgi_read_int_data(hole->ptset[set].id, hole->ptset[set].data_type, 2*index_dim, &pnts[2*index_dim*set])) return CG_ERROR; } else { cgi_warning("Overset hole #%d set %d, of zone #%d, base #%d, contains no points", I, set, Z, B); } } } else if (hole->nptsets == 1) { if (hole->ptset[0].npts > 0) { if (cgi_read_int_data(hole->ptset[0].id, hole->ptset[0].data_type, hole->ptset[0].npts*index_dim, pnts)) return CG_ERROR; } else { cgi_warning("Overset hole #%d, of zone #%d, base #%d, contains no points", I, Z, B); } } else { cgi_warning("Overset hole #%d, of zone #%d, base #%d, contains no data", I, Z, B); } return CG_OK; } int cg_hole_id(int file_number, int B, int Z, int I, double *hole_id) { cgns_hole *hole; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; hole = cgi_get_hole(cg, B, Z, I); if (hole==0) return CG_ERROR; *hole_id = hole->id; return CG_OK; } int cg_hole_write(int file_number, int B, int Z, const char * holename, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, int nptsets, cgsize_t npnts, const cgsize_t * pnts, int *I) { cgns_zone *zone; cgns_zconn *zconn; cgns_hole *hole = NULL; cgns_ptset *ptset; char_33 PointSetName; int index, set; int i, index_dim; /* verify input */ if (cgi_check_strlen(holename)) return CG_ERROR; if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(CellCenter)) { cgi_error("cg_hole_write: GridLocation not Vertex or CellCenter"); return CG_ERROR; } if (ptset_type != CGNS_ENUMV(PointList) && ptset_type != CGNS_ENUMV(PointRange)) { cgi_error("Invalid input: ptset_type=%d ?",ptset_type); return CG_ERROR; } if (!(ptset_type == CGNS_ENUMV(PointRange) && npnts == 2*nptsets && nptsets > 0) && !(ptset_type == CGNS_ENUMV(PointList) && npnts >= 0 && nptsets == 1)) { cgi_error("Invalid input: nptsets=%d, npoint=%d, point set type=%s", nptsets, npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Allocate ZoneGridConnectivity data struct. if not already created */ if (zone->nzconn == 0) { zone->nzconn = zone->active_zconn = 1; zone->zconn = CGNS_NEW(cgns_zconn, 1); strcpy(zone->zconn->name,"ZoneGridConnectivity"); } zconn = cgi_get_zconn(cg, B, Z); if (zconn == 0) return CG_ERROR; index_dim = zone->index_dim; /* Overwrite an OversetHoles_t Node: */ for (index=0; indexnholes; index++) { if (strcmp(holename, zconn->hole[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",holename); return CG_ERROR; } /* overwrite an existing Overset Hole */ /* delete the existing Overset hole from file */ if (cgi_delete_node(zconn->id, zconn->hole[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ hole = &(zconn->hole[index]); cgi_free_hole(hole); break; } } /* ... or add an OversetHoles_t Node: */ if (index==zconn->nholes) { if (zconn->nholes == 0) { zconn->hole = CGNS_NEW(cgns_hole, zconn->nholes+1); } else { zconn->hole = CGNS_RENEW(cgns_hole, zconn->nholes+1, zconn->hole); } hole = &(zconn->hole[zconn->nholes]); zconn->nholes++; } (*I) = index+1; /* write hole info to internal memory */ memset(hole, 0, sizeof(cgns_hole)); strcpy(hole->name,holename); hole->location = location; hole->nptsets = nptsets; hole->ptset = CGNS_NEW(cgns_ptset, nptsets); for (set=0; setptset[set]; ptset->type = ptset_type; strcpy(ptset->data_type,CG_SIZE_DATATYPE); if (ptset_type == CGNS_ENUMV(PointRange)) ptset->npts = 2; else ptset->npts = npnts; /* Record the number of nodes or elements in the point set */ if (ptset_type==CGNS_ENUMV( PointList )) ptset->size_of_patch=npnts; else if (ptset_type==CGNS_ENUMV( PointRange )) { ptset->size_of_patch = 1; for (i=0; isize_of_patch *= (pnts[i+index_dim]-pnts[i]+1); } } if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (zconn->id==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(zconn->id, hid); if (hid==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } if (cgi_new_node(zconn->id, hole->name, "OversetHoles_t", &hole->id, "MT", 0, 0, 0)) return CG_ERROR; if (hole->location != CGNS_ENUMV(Vertex)) { double GL_id; cgsize_t length = (cgsize_t)strlen(GridLocationName[hole->location]); if (cgi_new_node(hole->id, "GridLocation", "GridLocation_t", &GL_id, "C1", 1, &length, GridLocationName[hole->location])) return CG_ERROR; } for (set=0; setptset[set]; if (ptset->npts > 0) { /* Create Point Set node on disk */ if (ptset->type == CGNS_ENUMV(PointRange)) sprintf(PointSetName, "PointRange%d",set+1); else sprintf(PointSetName, "%s", PointSetTypeName[ptset->type]); if (cgi_write_ptset(hole->id, PointSetName, ptset, index_dim, (void *)&pnts[2*index_dim*set])) return CG_ERROR; } } return CG_OK; } /*****************************************************************************\ * Read and Write GridConnectivity_t Nodes \*****************************************************************************/ int cg_nconns(int file_number, int B, int Z, int *nconns) { cgns_zconn *zconn; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) *nconns = 0; /* if ZoneGridConnectivity_t is undefined */ else *nconns = zconn->nconns; return CG_OK; } /* in cg_conn_info, donor_datatype is useless starting with version 1.27, because it's always I4. Howver this arg. is left for backward compatibility of API and to be able to read old files */ int cg_conn_info(int file_number, int B, int Z, int I, char *connectname, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(GridConnectivityType_t) *type, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, char *donorname, CGNS_ENUMT(ZoneType_t) *donor_zonetype, CGNS_ENUMT(PointSetType_t) *donor_ptset_type, CGNS_ENUMT(DataType_t) *donor_datatype, cgsize_t *ndata_donor) { int dZ; cgns_conn *conn; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_ERROR; strcpy(connectname, conn->name); *type = conn->type; *location = conn->location; *ptset_type = conn->ptset.type; *npnts = conn->ptset.npts; /* information relative to donor */ strcpy(donorname, conn->donor); *donor_datatype = cgi_datatype(conn->dptset.data_type); *ndata_donor = conn->dptset.npts; *donor_ptset_type = conn->dptset.type; /* Find ZoneType_t of DonorZone given its name */ *donor_zonetype = CGNS_ENUMV( ZoneTypeNull ); for (dZ=0; dZbase[B-1].nzones; dZ++) { if (strcmp(cg->base[B-1].zone[dZ].name,donorname)==0) { *donor_zonetype = cg->base[B-1].zone[dZ].type; break; } } if (*donor_zonetype == 0) { cgi_error("cg_conn_info:donor zone %s does not exist",donorname); return CG_ERROR; } return CG_OK; } /* in cg_conn_read, donor_datatype is useless starting with version 1.27, because it's always I4. However this arg. is left for backward compatibility of API and to be able to read old files */ int cg_conn_read(int file_number, int B, int Z, int I, cgsize_t *pnts, CGNS_ENUMT(DataType_t) donor_datatype, cgsize_t *donor_data) { cgns_conn *conn; int n, cell_dim, index_dim; cgsize_t size; #if 0 /* verify input */ if (donor_data != NULL && donor_datatype != CGNS_ENUMV(Integer)) { cgi_error("Invalid datatype requested for donor data: %d", donor_datatype); return CG_ERROR; } #endif /* Find address */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_ERROR; cell_dim = cg->base[B-1].cell_dim; index_dim = cg->base[B-1].zone[Z-1].type == CGNS_ENUMV(Structured) ? cell_dim : 1; size = index_dim*conn->ptset.npts; /* read point-set of current zone from ADF file */ if (conn->ptset.npts > 0) { if (cgi_read_int_data(conn->ptset.id, conn->ptset.data_type, size, pnts)) return CG_ERROR; } else { cgi_warning("Interface receiver patch #%d of zone #%d, base #%d, contains no points", I, Z, B); } if (donor_data == NULL) return CG_OK; /* read donor points from ADF file - data_type may be I4, R4 or R8 */ if (conn->dptset.npts > 0) { cgns_ptset dptset = conn->dptset; int index_dim = 0; for (n=0; nbase[B-1].nzones; n++) { if (strcmp(cg->base[B-1].zone[n].name,conn->donor)==0) { index_dim = cg->base[B-1].zone[n].type == CGNS_ENUMV(Structured) ? cell_dim : 1; break; } } if (index_dim == 0) { cgi_error("cg_conn_read:donor zone %s does not exist",conn->donor); return CG_ERROR; } size = index_dim*dptset.npts; if (cgi_read_int_data(conn->dptset.id, conn->dptset.data_type, size, donor_data)) return CG_ERROR; } else { cgi_warning("Interface donor patch #%d of zone #%d, base #%d, contains no points", I, Z, B); } return CG_OK; } int cg_conn_read_short(int file_number, int B, int Z, int I, cgsize_t *pnts) { return cg_conn_read(file_number, B, Z, I, pnts, CGNS_ENUMV(DataTypeNull), NULL); } int cg_conn_id(int file_number, int B, int Z, int I, double *conn_id) { cgns_conn *conn; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_ERROR; *conn_id = conn->id; return CG_OK; } int cg_conn_write(int file_number, int B, int Z, const char * connectname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(GridConnectivityType_t) type, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, const char * donorname, CGNS_ENUMT(ZoneType_t) donor_zonetype, CGNS_ENUMT(PointSetType_t) donor_ptset_type, CGNS_ENUMT(DataType_t) donor_datatype, cgsize_t ndata_donor, const cgsize_t * donor_data, int *I) { cgns_zone *zone; cgns_zconn *zconn; cgns_conn *conn = NULL; cgns_ptset *dptset; int i; cgsize_t size_of_zone, length; cgsize_t PointListSize; int cell_dim; int index, index_dim, index_dim_donor; double GL_id, C_id; /* verify input */ if (cgi_check_strlen(connectname)) return CG_ERROR; if (cgi_check_strlen(donorname)) return CG_ERROR; if (INVALID_ENUM(type,NofValidGridConnectivityTypes)) { cgi_error("Invalid input: GridConnectivityType=%d ?",type); return CG_ERROR; } if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(CellCenter) && location != CGNS_ENUMV(FaceCenter) && location != CGNS_ENUMV(IFaceCenter) && location != CGNS_ENUMV(JFaceCenter) && location != CGNS_ENUMV(KFaceCenter)) { cgi_error("Invalid input: GridLocation=%d ?",location); return CG_ERROR; } if (type == CGNS_ENUMV(Overset) && location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(CellCenter)) { cgi_error("GridLocation must be Vertex or CellCenter for Overset"); return CG_ERROR; } if (ptset_type != CGNS_ENUMV(PointList) && ptset_type != CGNS_ENUMV(PointRange)) { cgi_error("Invalid input: ptset_type=%d ?",ptset_type); return CG_ERROR; } if (!(ptset_type==CGNS_ENUMV(PointRange) && npnts==2) && !(ptset_type==CGNS_ENUMV(PointList) && npnts>0)) { cgi_error("Invalid input: npoint=%d, point set type=%s", npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } if (ndata_donor) { if (NULL == donor_data) { cgi_error("Invalid input: number of donor points given but data is NULL"); return CG_ERROR; } if (donor_ptset_type!=CGNS_ENUMV(CellListDonor) && donor_ptset_type!=CGNS_ENUMV(PointListDonor)) { cgi_error("Invalid point set type for donor %s",donorname); return CG_ERROR; } #if 0 if (donor_datatype != CGNS_ENUMV(Integer)) { cgi_error("Invalid datatype for donor %s",donorname); return CG_ERROR; } if (donor_zonetype==CGNS_ENUMV( Unstructured ) && (donor_ptset_type!=CGNS_ENUMV( CellListDonor ) && donor_ptset_type!=PointListDonor)) { cgi_error("Invalid point set type for Unstructured donor %s",donorname); return CG_ERROR; } if (donor_zonetype==CGNS_ENUMV( Unstructured ) && donor_datatype != Integer) { cgi_error("Invalid datatype for Unstructured donor %s",donorname); return CG_ERROR; } if (donor_zonetype==CGNS_ENUMV( Structured ) && donor_ptset_type!=CGNS_ENUMV( PointListDonor )) { cgi_error("Invalid point set type for Structured donor %s",donorname); return CG_ERROR; } if (donor_datatype!=CGNS_ENUMV( RealSingle ) && donor_datatype!=CGNS_ENUMV( Integer ) && donor_datatype!=CGNS_ENUMV( RealDouble )) { cgi_error("Invalid data type for donor_data: %d",donor_datatype); return CG_ERROR; } #endif } else { donor_ptset_type = CGNS_ENUMV(PointSetTypeNull); } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; if ((location == CGNS_ENUMV(IFaceCenter) || location == CGNS_ENUMV(JFaceCenter) || location == CGNS_ENUMV(KFaceCenter)) && zone->type != CGNS_ENUMV(Structured)) { cgi_error("GridLocation [IJK]FaceCenter only valid for Structured grids"); return CG_ERROR; } /* Allocate ZoneGridConnectivity data struct. if not already created */ if (zone->nzconn == 0) { zone->nzconn = zone->active_zconn = 1; zone->zconn = CGNS_NEW(cgns_zconn, 1); strcpy(zone->zconn->name,"ZoneGridConnectivity"); } zconn = cgi_get_zconn(cg, B, Z); if (zconn == 0) return CG_ERROR; /* IndexDimension & CellDimension */ index_dim = zone->index_dim; cell_dim=cg->base[B-1].cell_dim; /* verify input */ size_of_zone = 1; for (i=0; inijk[i]; if (npnts<0 || npnts>size_of_zone) { cgi_error("Inconsistent number of points in point set"); return CG_ERROR; } #if 0 /* causes problems when grid is unstructured */ if (ptset_type==CGNS_ENUMV( PointRange )) { if (location == CGNS_ENUMV( Vertex )) { for (i=0; izone->nijk[i]) { cgi_error("Invalid input range: %d->%d",pnts[i], pnts[i+index_dim]); return CG_ERROR; } } } else if (location == CGNS_ENUMV( CellCenter )) { for (i=0; izone->nijk[i+index_dim]) { cgi_error("Invalid input range: %d->%d",pnts[i], pnts[i+index_dim]); return CG_ERROR; } } } } #endif /* Compute PointListSize */ if (ptset_type==CGNS_ENUMV(PointRange)) { PointListSize = 1; for (i=0; inconns; index++) { if (strcmp(connectname, zconn->conn[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",connectname); return CG_ERROR; } /* overwrite an existing GridConnectivity_t Node */ /* delete the existing GridConnectivity_t Node from file */ if (cgi_delete_node(zconn->id, zconn->conn[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ conn = &(zconn->conn[index]); cgi_free_conn(conn); break; } } /* ... or add a GridConnectivity_t Node: */ if (index==zconn->nconns) { if (zconn->nconns == 0) { zconn->conn = CGNS_NEW(cgns_conn, zconn->nconns+1); } else { zconn->conn = CGNS_RENEW(cgns_conn, zconn->nconns+1, zconn->conn); } conn = &(zconn->conn[zconn->nconns]); zconn->nconns++; } (*I) = index+1; /* write conn info to internal memory */ memset(conn, 0, sizeof(cgns_conn)); strcpy(conn->name,connectname); conn->type = type; conn->location = location; conn->ptset.id = 0; conn->ptset.link = 0; conn->ptset.type = ptset_type; strcpy(conn->ptset.data_type,CG_SIZE_DATATYPE); conn->ptset.npts = npnts; conn->ptset.size_of_patch = PointListSize; /* ... donor: */ strcpy(conn->donor,donorname); conn->interpolants = 0; dptset = &conn->dptset; dptset->id = 0; dptset->link = 0; strcpy(dptset->name,PointSetTypeName[donor_ptset_type]); dptset->type = donor_ptset_type; strcpy(dptset->data_type, CG_SIZE_DATATYPE); dptset->npts = ndata_donor; dptset->size_of_patch = ndata_donor; if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { /* Create node ZoneGridConnectivity_t node, if not yet created */ if (zconn->id==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(zconn->id, hid); if (hid==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create node GridConnectivity_t node */ length = (cgsize_t)strlen(conn->donor); if (cgi_new_node(zconn->id, conn->name, "GridConnectivity_t", &conn->id, "C1", 1, &length, conn->donor)) return CG_ERROR; /* Create node GridConnectivityType_t */ length = (cgsize_t)strlen(GridConnectivityTypeName[conn->type]); if (cgi_new_node(conn->id,"GridConnectivityType","GridConnectivityType_t", &C_id, "C1", 1, &length, GridConnectivityTypeName[conn->type])) return CG_ERROR; /* write GridLocation */ if (conn->location != CGNS_ENUMV( Vertex )) { length = (cgsize_t)strlen(GridLocationName[conn->location]); if (cgi_new_node(conn->id, "GridLocation", "GridLocation_t", &GL_id, "C1", 1, &length, GridLocationName[conn->location])) return CG_ERROR; } /* Write Point Sets to disk */ if (npnts>0) { char_33 PointSetName; strcpy (PointSetName, PointSetTypeName[conn->ptset.type]); if (cgi_write_ptset(conn->id, PointSetName, &conn->ptset, index_dim, (void *)pnts)) return CG_ERROR; /* Write pointset of donor */ if (ndata_donor) { if (donor_zonetype==CGNS_ENUMV(Structured)) index_dim_donor = cell_dim; else index_dim_donor=1; strcpy (PointSetName, PointSetTypeName[donor_ptset_type]); if (cgi_write_ptset(conn->id, PointSetName, dptset, index_dim_donor, (void *)donor_data)) return CG_ERROR; } } return CG_OK; } int cg_conn_write_short(int file_number, int B, int Z, const char * connectname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(GridConnectivityType_t) type, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, const char * donorname, int *I) { return cg_conn_write (file_number, B, Z, connectname, location, type, ptset_type, npnts, pnts, donorname, CGNS_ENUMV(ZoneTypeNull), CGNS_ENUMV(PointSetTypeNull), CGNS_ENUMV(DataTypeNull), 0, NULL, I); } /*****************************************************************************\ * Read and write GridConnectivity1to1_t Nodes \*****************************************************************************/ int cg_n1to1(int file_number, int B, int Z, int *n1to1) { cgns_zconn *zconn; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) *n1to1 = 0; /* if ZoneGridConnectivity_t is undefined */ else *n1to1 = zconn->n1to1; return CG_OK; } int cg_n1to1_global(int file_number, int B, int *n1to1_global) { cgns_base *base; cgns_zone *zone; cgns_zconn *zconn; int Z, I, D; cgint3_t transform; cgsize_t donor_range[6], range[6]; char_33 connectname, donorname; /* added for zones interfacing themselves (C-topology) */ int ndouble=0; char_33 *Dzonename = 0; cgsize6_t *Drange = 0, *Ddonor_range = 0; int index_dim; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *n1to1_global = 0; for (Z=1; Z<=base->nzones; Z++) { zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; index_dim = zone->index_dim; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) continue; /* if ZoneGridConnectivity_t is undefined */ if (zconn->n1to1 ==0) continue; for (I=1; I<=zconn->n1to1; I++) { if (cg_1to1_read(file_number, B, Z, I, connectname, donorname, range, donor_range, transform)) return CG_ERROR; if (cgi_zone_no(base, donorname, &D)) return CG_ERROR; /* count each interface only once */ if (Zname, range, donor_range, index_dim, &ndouble, &Dzonename, &Drange, &Ddonor_range)) { (*n1to1_global)++; } } } /* loop through interfaces of a zone */ } /* loop through zones */ if (Dzonename) free(Dzonename); if (Drange) free(Drange); if (Ddonor_range) free(Ddonor_range); return CG_OK; } int cg_1to1_read(int file_number, int B, int Z, int I, char *connectname, char *donorname, cgsize_t *range, cgsize_t *donor_range, int *transform) { cgns_1to1 *one21; int i, index_dim; /* in 2D, range[0], range[1] = imin, jmin range[2], range[3] = imax, jmax in 3D, range[0], range[1], range[2] = imin, jmin, kmin range[3], range[4], range[5] = imax, jmax, kmax */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; one21 = cgi_get_1to1(cg, B, Z, I); if (one21==0) return CG_ERROR; index_dim = cg->base[B-1].zone[Z-1].index_dim; /* read pointset from ADF file */ if (one21->ptset.npts > 0) { if (cgi_read_int_data(one21->ptset.id, one21->ptset.data_type, one21->ptset.npts * index_dim, range)) return CG_ERROR; } else { cgi_warning("1to1 interface %d (receiver side) for zone %d base % is undefined", I,Z,B); } /* read donor pointset from ADF file */ if (one21->dptset.npts > 0) { if (cgi_read_int_data(one21->dptset.id, one21->dptset.data_type, one21->dptset.npts * index_dim, donor_range)) return CG_ERROR; } else { cgi_warning("1to1 interface %d (donor side) for zone %d base % is undefined", I,Z,B); } /* read transform from internal database */ for (i=0; itransform[i]; strcpy(connectname, one21->name); strcpy(donorname, one21->donor); return CG_OK; } int cg_1to1_read_global(int file_number, int B, char **connectname, char **zonename, char **donorname, cgsize_t **range, cgsize_t **donor_range, int **transform) { cgns_base *base; cgns_zone *zone; cgns_zconn *zconn; int Z, I, D, n=0, j, index_dim; char connect[33], donor[33]; cgsize_t rang[6], drang[6]; int trans[3]; /* added for zones interfacing themselves (C-topology) */ int ndouble=0; char_33 *Dzonename = 0; cgsize6_t *Drange = 0, *Ddonor_range = 0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; for (Z=1; Z<=base->nzones; Z++) { zone = cgi_get_zone(cg, B, Z); if (zone->type==CGNS_ENUMV( Unstructured )) { cgi_error("GridConnectivity1to1 is only applicable to structured zones."); return CG_ERROR; } index_dim = zone->index_dim; zconn = cgi_get_zconn(cg, B, Z); if (zconn==0) continue; /* if ZoneGridConnectivity_t is undefined */ if (zconn->n1to1 ==0) continue; for (I=1; I<=zconn->n1to1; I++) { if (cg_1to1_read(file_number, B, Z, I, connect, donor, rang, drang, trans)) return CG_ERROR; if (cgi_zone_no(base, donor, &D)) return CG_ERROR; /* count each interface only once */ if (Zname, rang, drang, index_dim, &ndouble, &Dzonename, &Drange, &Ddonor_range))) { strcpy(connectname[n], connect); strcpy(zonename[n],zone->name); strcpy(donorname[n], donor); for (j=0; jfilename, cg->mode, CG_MODE_READ)) return CG_ERROR; one21 = cgi_get_1to1(cg, B, Z, I); if (one21==0) return CG_ERROR; *one21_id = one21->id; return CG_OK; } int cg_1to1_write(int file_number, int B, int Z, const char * connectname, const char * donorname, const cgsize_t * range, const cgsize_t * donor_range, const int * transform, int *I) { cgns_zone *zone; cgns_zconn *zconn; cgns_1to1 *one21 = NULL; int index, i, j; cgsize_t index_dim, length; double T_id; /* verify input */ if (cgi_check_strlen(connectname)) return CG_ERROR; #ifdef CG_BUILD_BASESCOPE if (cgi_check_strlen_x2(donorname)) return CG_ERROR; #else if (cgi_check_strlen(donorname)) return CG_ERROR; #endif /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Allocate ZoneGridConnectivity data struct. if not already created */ if (zone->nzconn == 0) { zone->nzconn = zone->active_zconn = 1; zone->zconn = CGNS_NEW(cgns_zconn, 1); strcpy(zone->zconn->name,"ZoneGridConnectivity"); } zconn = cgi_get_zconn(cg, B, Z); if (zconn == 0) return CG_ERROR; /* verify input */ index_dim = zone->index_dim; for (i=0; izone->nijk[i]) { cgi_error("Invalid input range: %d->%d",range[i], range[i+index_dim]); return CG_ERROR; } if (abs(transform[i])<0 || abs(transform[i])>index_dim) { cgi_error("Invalid transformation index: %d. The indices must all be between 1 and %d",i, index_dim); return CG_ERROR; } if (abs(transform[i])>0) { cgsize_t dr, ddr; j = abs(transform[i])-1; dr = range[i+index_dim] - range[i]; ddr = donor_range[j+index_dim] - donor_range[j]; if (dr != ddr && dr != -ddr) { cgi_error("Invalid input: range = %d->%d and donor_range = %d->%d", range[i], range[i+index_dim], donor_range[j], donor_range[j+index_dim]); return CG_ERROR; } } } /* Overwrite a GridConnectivity1to1_t Node: */ for (index=0; indexn1to1; index++) { if (strcmp(connectname, zconn->one21[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",connectname); return CG_ERROR; } /* overwrite an existing GridConnectivity1to1_t Node */ /* delete the existing GridConnectivity1to1_t Node from file */ if (cgi_delete_node(zconn->id, zconn->one21[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ one21 = &(zconn->one21[index]); /* free memory */ cgi_free_1to1(one21); break; } } /* ... or add a GridConnectivity1to1_t Node: */ if (index==zconn->n1to1) { if (zconn->n1to1 == 0) { zconn->one21 = CGNS_NEW(cgns_1to1, zconn->n1to1+1); } else { zconn->one21 = CGNS_RENEW(cgns_1to1, zconn->n1to1+1, zconn->one21); } one21 = &(zconn->one21[zconn->n1to1]); zconn->n1to1++; } (*I) = index+1; memset(one21, 0, sizeof(cgns_1to1)); /* allocate memory */ if ((one21->transform = (int *)malloc((size_t)(index_dim*sizeof(int))))==NULL) { cgi_error("Error allocating memory in cg_1to1_write"); return CG_ERROR; } /* write 1to1 info to internal memory */ strcpy(one21->name,connectname); one21->ptset.type = CGNS_ENUMV(PointRange); strcpy(one21->ptset.data_type,CG_SIZE_DATATYPE); one21->ptset.npts = 2; /* ... donor: */ strcpy(one21->donor,donorname); one21->dptset.type = CGNS_ENUMV(PointRangeDonor); strcpy(one21->dptset.data_type,CG_SIZE_DATATYPE); one21->dptset.npts = 2; /* ... transform: */ memcpy((void *)one21->transform, (void *)transform, (size_t)(index_dim*sizeof(int))); /* Create node ZoneGridConnectivity_t node, if not yet created */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (zconn->id==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(zconn->id, hid); if (hid==0) { if (cgi_new_node(zone->id, zconn->name, "ZoneGridConnectivity_t", &zconn->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the node */ length = (cgsize_t)strlen(one21->donor); if (cgi_new_node(zconn->id, one21->name, "GridConnectivity1to1_t", &one21->id, "C1", 1, &length, one21->donor)) return CG_ERROR; /* Create transform node */ if (cgi_new_node(one21->id, "Transform", "\"int[IndexDimension]\"", &T_id, "I4", 1, &index_dim, (void *)one21->transform)) return CG_ERROR; /* Create RECEIVER Point Set node on disk */ if (cgi_write_ptset(one21->id, "PointRange", &one21->ptset, (int)index_dim, (void *)range)) return CG_ERROR; /* Create DONOR Point Set node on disk */ if (cgi_write_ptset(one21->id, "PointRangeDonor", &one21->dptset, (int)index_dim, (void *)donor_range)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and write BC_t Nodes \*****************************************************************************/ int cg_nbocos(int file_number, int B, int Z, int *nbocos) { cgns_zboco *zboco; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zboco = cgi_get_zboco(cg, B, Z); if (zboco==0) *nbocos = 0; /* if ZoneBC_t is undefined */ else *nbocos = zboco->nbocos; return CG_OK; } int cg_boco_info(int file_number, int B, int Z, int BC, char *boconame, CGNS_ENUMT(BCType_t) *bocotype, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, int *NormalIndex, cgsize_t *NormalListSize, CGNS_ENUMT(DataType_t) *NormalDataType, int *ndataset) { cgns_boco *boco; int n, index_dim; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; strcpy(boconame,boco->name); *bocotype = boco->type; if (boco->ptset) { *ptset_type = boco->ptset->type; *npnts = boco->ptset->npts; } else { *ptset_type = CGNS_ENUMV(PointSetTypeNull); *npnts = 0; } index_dim = cg->base[B-1].zone[Z-1].index_dim; if (NormalIndex) { if (boco->Nindex) { for (n=0; nNindex[n]; } else { for (n=0; nnormal && boco->ptset) { *NormalListSize = boco->ptset->size_of_patch*cg->base[B-1].phys_dim; *NormalDataType = cgi_datatype(boco->normal->data_type); } else { *NormalListSize = 0; *NormalDataType = CGNS_ENUMV(DataTypeNull); } *ndataset = boco->ndataset; return CG_OK; } int cg_boco_read(int file_number, int B, int Z, int BC, cgsize_t *pnts, void *NormalList) { cgns_boco *boco; int dim = 0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; /* Read point-set directly from ADF-file */ if (boco->ptset && boco->ptset->npts > 0) { cg_index_dim(file_number, B, Z, &dim); if (cgi_read_int_data(boco->ptset->id, boco->ptset->data_type, boco->ptset->npts * dim, pnts)) return CG_ERROR; } else { cgi_warning("B.C. patch %d of zone %d base %d is undefined", BC, Z, B); } /* if it exists, read NormalList */ dim = cg->base[B-1].phys_dim; if (NormalList && boco->normal && boco->ptset && boco->ptset->npts>0) { memcpy(NormalList, boco->normal->data, (size_t)(boco->ptset->size_of_patch*dim*size_of(boco->normal->data_type))); } return CG_OK; } int cg_boco_id(int file_number, int B, int Z, int BC, double *boco_id) { cgns_boco *boco; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; *boco_id = boco->id; return CG_OK; } int cg_boco_gridlocation_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(GridLocation_t) *location) { cgns_boco *boco; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; *location = boco->location; return CG_OK; } int cg_boco_write(int file_number, int B, int Z, const char * boconame, CGNS_ENUMT(BCType_t) bocotype, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, int *BC) { cgns_zone *zone; cgns_zboco *zboco; cgns_boco *boco = NULL; int index, i, index_dim; CGNS_ENUMT(PointSetType_t) ptype; CGNS_ENUMT(GridLocation_t) location; cgsize_t length; /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of zone */ zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* verify input */ if (cgi_check_strlen(boconame)) return CG_ERROR; ptype = ptset_type; location = CGNS_ENUMV(Vertex); if (ptset_type == CGNS_ENUMV(ElementList) || ptset_type == CGNS_ENUMV(ElementRange)) { if (cg->filetype != CG_FILE_ADF2) { if (ptset_type == CGNS_ENUMV(ElementList)) ptype = CGNS_ENUMV(PointList); else ptype = CGNS_ENUMV(PointRange); if (cg->base[B-1].cell_dim == 1) location = CGNS_ENUMV(Vertex); else if (cg->base[B-1].cell_dim == 2) location = CGNS_ENUMV(EdgeCenter); else location = CGNS_ENUMV(FaceCenter); } } else { if (ptset_type != CGNS_ENUMV(PointList) && ptset_type != CGNS_ENUMV(PointRange)) { cgi_error("Invalid point set type: %d...?",ptset_type); return CG_ERROR; } } if (((ptype == CGNS_ENUMV(PointList) || ptype == CGNS_ENUMV(ElementList)) && npnts <= 0) || ((ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(ElementRange)) && npnts != 2)) { cgi_error("Invalid input: npoint=%d, point set type=%s", npnts, PointSetTypeName[ptype]); return CG_ERROR; } if (INVALID_ENUM(bocotype,NofValidBCTypes)) { cgi_error("Invalid BCType: %d",bocotype); return CG_ERROR; } if (cgi_check_location(cg->base[B-1].cell_dim, cg->base[B-1].zone[Z-1].type, location)) return CG_ERROR; #ifdef CG_FIX_BC_CELL_CENTER if (location == CGNS_ENUMV(CellCenter)) { cgi_error("GridLocation CellCenter not valid - use Edge/FaceCenter"); return CG_ERROR; } #endif /* Allocate ZoneBC data struct. if not already created */ if (zone->zboco == 0) { zone->zboco = CGNS_NEW(cgns_zboco, 1); zboco = zone->zboco; strcpy(zboco->name,"ZoneBC"); } else zboco = zone->zboco; /* Overwrite a BC_t Node: */ for (index=0; indexnbocos; index++) { if (strcmp(boconame, zboco->boco[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",boconame); return CG_ERROR; } /* overwrite an existing BC_t Node */ /* delete the existing BC_t Node from file */ if (cgi_delete_node(zboco->id, zboco->boco[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ boco = &(zboco->boco[index]); cgi_free_boco(boco); break; } } /* ... or add a BC_t Node: */ if (index==zboco->nbocos) { if (zboco->nbocos == 0) { zboco->boco = CGNS_NEW(cgns_boco, zboco->nbocos+1); } else { zboco->boco = CGNS_RENEW(cgns_boco, zboco->nbocos+1, zboco->boco); } boco = &(zboco->boco[zboco->nbocos]); zboco->nbocos++; } (*BC) = index+1; /* write boco info to internal memory */ memset(boco, 0, sizeof(cgns_boco)); strcpy(boco->name, boconame); boco->type = bocotype; boco->location = location; boco->ptset = CGNS_NEW(cgns_ptset,1); boco->ptset->type = ptype; strcpy(boco->ptset->data_type,CG_SIZE_DATATYPE); boco->ptset->npts = npnts; /* Record the number of nodes or elements in the point set */ index_dim = zone->index_dim; if (boco->ptset->type == CGNS_ENUMV(PointList)) boco->ptset->size_of_patch=npnts; else { boco->ptset->size_of_patch = 1; for (i=0; iptset->size_of_patch = boco->ptset->size_of_patch * (pnts[i+index_dim]-pnts[i]+1); } /* Create ZoneBC_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (zboco->id==0) { if (cgi_new_node(zone->id, "ZoneBC", "ZoneBC_t", &zboco->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(zboco->id, hid); if (hid==0) { if (cgi_new_node(zone->id, "ZoneBC", "ZoneBC_t", &zboco->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the BC_t Node */ length = (cgsize_t)strlen(BCTypeName[boco->type]); if (cgi_new_node(zboco->id, boco->name, "BC_t", &boco->id, "C1", 1, &length, BCTypeName[boco->type])) return CG_ERROR; /* Save Point-Set on Disk */ if (npnts > 0) { char_33 PointSetName; strcpy(PointSetName, PointSetTypeName[boco->ptset->type]); if (cgi_write_ptset(boco->id, PointSetName, boco->ptset, index_dim, (void *)pnts)) return CG_ERROR; } if (boco->location != CGNS_ENUMV(Vertex)) { double dummy_id; length = (cgsize_t)strlen(GridLocationName[boco->location]); if (cgi_new_node(boco->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &length, GridLocationName[boco->location])) return CG_ERROR; } return CG_OK; } int cg_boco_gridlocation_write(int file_number, int B, int Z, int BC, CGNS_ENUMT(GridLocation_t) location) { cgns_boco *boco; cgsize_t dim_vals; double dummy_id; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; if (cgi_check_location(cg->base[B-1].cell_dim, cg->base[B-1].zone[Z-1].type, location)) return CG_ERROR; #ifdef CG_FIX_BC_CELL_CENTER if (location == CGNS_ENUMV(CellCenter)) { cgi_error("GridLocation CellCenter not valid - use Edge/FaceCenter"); return CG_ERROR; } #endif boco->location = location; dim_vals = (cgsize_t)strlen(GridLocationName[location]); if (cgi_new_node(boco->id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[location])) return CG_ERROR; return CG_OK; } int cg_boco_normal_write(int file_number, int B, int Z, int BC, const int * NormalIndex, int NormalListFlag, CGNS_ENUMT(DataType_t) NormalDataType, const void * NormalList) { cgns_boco *boco; int n, phys_dim; cgsize_t npnts, index_dim; /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; npnts = boco->ptset->size_of_patch; phys_dim=cg->base[B-1].phys_dim; if (NormalListFlag && npnts) { cgns_array *normal; if (boco->normal) { if (cg->mode==CG_MODE_WRITE) { cgi_error("InwardNormalList is already defined under BC_t '%s'", boco->name); return CG_ERROR; } if (cgi_delete_node(boco->id, boco->normal->id)) return CG_ERROR; cgi_free_array(boco->normal); memset(boco->normal, 0, sizeof(cgns_array)); } else { boco->normal = CGNS_NEW(cgns_array, 1); } normal = boco->normal; strcpy(normal->data_type, cgi_adf_datatype(NormalDataType)); normal->data = (void *)malloc((size_t)(npnts*phys_dim*size_of(normal->data_type))); if (normal->data == NULL) { cgi_error("Error allocating normal->data"); return CG_ERROR; } memcpy(normal->data, NormalList, (size_t)(npnts*phys_dim*size_of(normal->data_type))); strcpy(normal->name, "InwardNormalList"); normal->data_dim =2; normal->dim_vals[0]=phys_dim; normal->dim_vals[1]=npnts; if (cgi_new_node(boco->id, "InwardNormalList", "IndexArray_t", &normal->id, normal->data_type, 2, normal->dim_vals, (void *)normal->data)) return CG_ERROR; } if (boco->Nindex) { if (cg->mode==CG_MODE_WRITE) { cgi_error("InwardNormalIndex is already defined under BC_t '%s'", boco->name); return CG_ERROR; } else { if (cgi_delete_node(boco->id, boco->index_id)) return CG_ERROR; free(boco->Nindex); boco->Nindex = 0; } } if (NormalIndex && cg->base[B-1].zone[Z-1].type == CGNS_ENUMV( Structured )) { index_dim=cg->base[B-1].zone[Z-1].index_dim; boco->Nindex = CGNS_NEW(int, index_dim); for (n=0; nNindex[n]=NormalIndex[n]; if (cgi_new_node(boco->id, "InwardNormalIndex", "\"int[IndexDimension]\"", &boco->index_id, "I4", 1, &index_dim, (void *)NormalIndex)) return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * Read and write BCDataSet_t Nodes \*****************************************************************************/ int cg_dataset_read(int file_number, int B, int Z, int BC, int DSet, char *name, CGNS_ENUMT(BCType_t) *BCType, int *DirichletFlag, int *NeumannFlag) { cgns_dataset *dataset; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; dataset = cgi_get_dataset(cg, B, Z, BC, DSet); if (dataset==0) return CG_ERROR; strcpy(name, dataset->name); *BCType = dataset->type; if (dataset->dirichlet) *DirichletFlag=1; else *DirichletFlag=0; if (dataset->neumann) *NeumannFlag=1; else *NeumannFlag=0; return CG_OK; } int cg_dataset_write(int file_number, int B, int Z, int BC, const char * name, CGNS_ENUMT( BCType_t ) BCType, int *Dset) { cgns_boco *boco; cgns_dataset *dataset = NULL; int index; cgsize_t length; /* verify input */ if (INVALID_ENUM(BCType,NofValidBCTypes)) { cgi_error("Invalid BCType: %d",BCType); return CG_ERROR; } if (cgi_check_strlen(name)) return CG_ERROR; /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; /* Overwrite a BCDataSet_t node : */ for (index=0; indexndataset; index++) { if (strcmp(name, boco->dataset[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",name); return CG_ERROR; } /* overwrite an existing solution */ /* delete the existing dataset from file */ if (cgi_delete_node(boco->id, boco->dataset[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ dataset = &(boco->dataset[index]); /* free memory */ cgi_free_dataset(dataset); break; } } /* ... or add a BCDataSet_t Node: */ if (index==boco->ndataset) { if (boco->ndataset == 0) boco->dataset = CGNS_NEW(cgns_dataset, boco->ndataset+1); else boco->dataset= CGNS_RENEW(cgns_dataset, boco->ndataset+1, boco->dataset); dataset= &boco->dataset[boco->ndataset]; boco->ndataset++; } (*Dset) = index+1; /* save data in memory */ memset(dataset, 0, sizeof(cgns_dataset)); dataset->type = BCType; strcpy(dataset->name, name); dataset->location = CGNS_ENUMV(Vertex); /* save data in file */ length = (cgsize_t)strlen(BCTypeName[dataset->type]); if (cgi_new_node(boco->id, dataset->name, "BCDataSet_t", &dataset->id, "C1", 1, &length, (void *)BCTypeName[dataset->type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * write BCdata_t Nodes \*****************************************************************************/ int cg_bcdata_write(int file_number, int B, int Z, int BC, int Dset, CGNS_ENUMT(BCDataType_t) BCDataType) { cgns_dataset *dataset; cgns_bcdata *bcdata; /* verify input */ if (INVALID_ENUM(BCDataType,NofValidBCDataTypes)) { cgi_error("BCDataType %d not valid",BCDataType); return CG_ERROR; } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; dataset = cgi_get_dataset(cg, B, Z, BC, Dset); if (dataset==0) return CG_ERROR; if (BCDataType==CGNS_ENUMV( Dirichlet )) { if (dataset->dirichlet) { if (cg->mode == CG_MODE_WRITE) { cgi_error("Dirichlet data already defined under BCDataSet_t '%s'", dataset->name); return CG_ERROR; } if (cgi_delete_node(dataset->id, dataset->dirichlet->id)) return CG_ERROR; cgi_free_bcdata(dataset->dirichlet); memset(dataset->dirichlet, 0, sizeof(cgns_bcdata)); } else { dataset->dirichlet = CGNS_NEW(cgns_bcdata,1); } strcpy(dataset->dirichlet->name, "DirichletData"); bcdata = dataset->dirichlet; } else { if (dataset->neumann) { if (cg->mode == CG_MODE_WRITE) { cgi_error("Neumann data already defined under BCDataSet_t '%s'", dataset->name); return CG_ERROR; } if (cgi_delete_node(dataset->id, dataset->neumann->id)) return CG_ERROR; cgi_free_bcdata(dataset->neumann); memset(dataset->neumann, 0, sizeof(cgns_bcdata)); } else { dataset->neumann = CGNS_NEW(cgns_bcdata,1); } strcpy(dataset->neumann->name, "NeumannData"); bcdata = dataset->neumann; } if (cgi_new_node(dataset->id, bcdata->name, "BCData_t", &bcdata->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and write RigidGridMotion_t Nodes \*****************************************************************************/ int cg_n_rigid_motions(int file_number, int B, int Z, int *n_rigid_motions) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *n_rigid_motions = zone->nrmotions; return CG_OK; } int cg_rigid_motion_read(int file_number, int B, int Z, int R, char *name, CGNS_ENUMT(RigidGridMotionType_t) *type) { cgns_rmotion *rmotion; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; rmotion = cgi_get_rmotion(cg, B, Z, R); if (rmotion==0) return CG_ERROR; strcpy(name, rmotion->name); *type = rmotion->type; return CG_OK; } int cg_rigid_motion_write(int file_number, int B, int Z, const char * rmotionname, CGNS_ENUMT(RigidGridMotionType_t) type, int *R) { cgns_zone *zone; cgns_rmotion *rmotion = NULL; int index; cgsize_t length; /* verify input */ if (cgi_check_strlen(rmotionname)) return CG_ERROR; if (INVALID_ENUM(type,NofValidRigidGridMotionTypes)) { cgi_error("Invalid input: RigidGridMotionType=%d ?",type); return CG_ERROR; } /* get memory address for RigidGridMotion_t node */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a RigidGridMotion_t Node: */ for (index=0; indexnrmotions; index++) { if (strcmp(rmotionname, zone->rmotion[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",rmotionname); return CG_ERROR; } /* overwrite an existing rmotion */ /* delete the existing rmotion from file */ if (cgi_delete_node(zone->id, zone->rmotion[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ rmotion = &(zone->rmotion[index]); /* free memory */ cgi_free_rmotion(rmotion); break; } } /* ... or add a new RigidGridMotion_t Node: */ if (index==zone->nrmotions) { if (zone->nrmotions == 0) { zone->rmotion = CGNS_NEW(cgns_rmotion, 1); } else { zone->rmotion = CGNS_RENEW(cgns_rmotion, zone->nrmotions+1, zone->rmotion); } rmotion = &(zone->rmotion[zone->nrmotions]); zone->nrmotions++; } (*R) = index+1; /* save data for cgns_rmotion *rmotion */ memset(rmotion, 0, sizeof(cgns_rmotion)); strcpy(rmotion->name,rmotionname); rmotion->type = type; /* Create node RigidGridMotion_t */ length = (cgsize_t)strlen(RigidGridMotionTypeName[rmotion->type]); if (cgi_new_node(zone->id, rmotion->name, "RigidGridMotion_t", &rmotion->id, "C1", 1, &length, (void *)RigidGridMotionTypeName[rmotion->type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and write ArbitraryGridMotion_t Nodes \*****************************************************************************/ int cg_n_arbitrary_motions(int file_number, int B, int Z, int *n_arbitrary_motions) { cgns_zone *zone; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; *n_arbitrary_motions = zone->namotions; return CG_OK; } int cg_arbitrary_motion_read(int file_number, int B, int Z, int A, char *name, CGNS_ENUMT(ArbitraryGridMotionType_t) *type) { cgns_amotion *amotion; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; amotion = cgi_get_amotion(cg, B, Z, A); if (amotion==0) return CG_ERROR; strcpy(name, amotion->name); *type = amotion->type; return CG_OK; } int cg_arbitrary_motion_write(int file_number, int B, int Z, const char * amotionname, CGNS_ENUMT(ArbitraryGridMotionType_t) type, int *A) { cgns_zone *zone; cgns_amotion *amotion = NULL; int index; cgsize_t length; /* verify input */ if (cgi_check_strlen(amotionname)) return CG_ERROR; if (INVALID_ENUM(type,NofValidArbitraryGridMotionTypes)) { cgi_error("Invalid input: ArbitraryGridMotionType=%d ?",type); return CG_ERROR; } /* get memory address for ArbitraryGridMotion_t node */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite a ArbitraryGridMotion_t Node: */ for (index=0; indexnamotions; index++) { if (strcmp(amotionname, zone->amotion[index].name)==0) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Duplicate child name found: %s",amotionname); return CG_ERROR; } /* overwrite an existing amotion */ /* delete the existing amotion from file */ if (cgi_delete_node(zone->id, zone->amotion[index].id)) return CG_ERROR; /* save the old in-memory address to overwrite */ amotion = &(zone->amotion[index]); /* free memory */ cgi_free_amotion(amotion); break; } } /* ... or add a new ArbitraryGridMotion_t Node: */ if (index==zone->namotions) { if (zone->namotions == 0) { zone->amotion = CGNS_NEW(cgns_amotion, 1); } else { zone->amotion = CGNS_RENEW(cgns_amotion, zone->namotions+1, zone->amotion); } amotion = &(zone->amotion[zone->namotions]); zone->namotions++; } (*A) = index+1; /* save data for cgns_amotion *amotion */ memset(amotion, 0, sizeof(cgns_amotion)); strcpy(amotion->name,amotionname); amotion->type = type; amotion->location = CGNS_ENUMV(Vertex); /* Create node ArbitraryGridMotion_t */ length = (cgsize_t)strlen(ArbitraryGridMotionTypeName[amotion->type]); if (cgi_new_node(zone->id, amotion->name, "ArbitraryGridMotion_t", &amotion->id, "C1", 1, &length, (void *)ArbitraryGridMotionTypeName[amotion->type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Read and write SimulationType_t Node \*****************************************************************************/ int cg_simulation_type_read(int file_number, int B, CGNS_ENUMT(SimulationType_t) *type) { cgns_base *base; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; *type = base->type; return CG_OK; } int cg_simulation_type_write(int file_number, int B, CGNS_ENUMT(SimulationType_t) type) { cgns_base *base; cgsize_t length; /* check input */ if (INVALID_ENUM(type,NofValidSimulationTypes)) { cgi_error("Invalid input: SimulationType=%d ?",type); return CG_ERROR; } /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for CGNSBase_t node */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* write or overwrite SimulationType_t to Base */ if (base->type) { if (cg->mode==CG_MODE_WRITE) { cgi_error("Simulation type already defined under CGNSBase_t '%s'", base->name); return CG_ERROR; } if (cgi_delete_node(base->id, base->type_id)) return CG_ERROR; } base->type = type; base->type_id = 0; /* save data in file */ length = (cgsize_t)strlen(SimulationTypeName[type]); if (cgi_new_node(base->id, "SimulationType", "SimulationType_t", &base->type_id, "C1", 1, &length, (void *)SimulationTypeName[type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write BaseIterativeData_t Node \*****************************************************************************/ int cg_biter_read(int file_number, int B, char *bitername, int *nsteps) { cgns_biter *biter; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; biter = cgi_get_biter(cg, B); if (biter==0) return CG_NODE_NOT_FOUND; *nsteps = biter->nsteps; strcpy(bitername,biter->name); return CG_OK; } int cg_biter_write(int file_number, int B, const char * bitername, int nsteps) { cgns_base *base; cgns_biter *biter; cgsize_t length=1; /* verify input */ if (nsteps<=0) { cgi_error("Invalid input: The number of steps must be a positive integer!"); return CG_ERROR; } /* get memory address for BaseIterativeData_t node */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* If BaseIterativeData_t already exist: */ if (base->biter) { if (cg->mode==CG_MODE_WRITE) { cgi_error("Error: BaseIterativeData_t already defined"); return CG_ERROR; } /* overwrite an existing rmotion */ /* delete the existing biter from file */ if (cgi_delete_node(base->id, base->biter->id)) return CG_ERROR; /* save the old in-memory address to overwrite */ biter = base->biter; /* free memory */ cgi_free_biter(biter); /* ... or add a new BaseIterativeData_t Node: */ } else { base->biter = CGNS_NEW(cgns_biter, 1); biter = base->biter; } /* save data for cgns_biter *biter */ memset(biter, 0, sizeof(cgns_biter)); strcpy(biter->name,bitername); biter->nsteps = nsteps; /* Create node BaseIterativeData_t */ if (cgi_new_node(base->id, biter->name, "BaseIterativeData_t", &biter->id, "I4", 1, &length, (void *)&nsteps)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write ZoneIterativeData_t Node \*****************************************************************************/ int cg_ziter_read(int file_number, int B, int Z, char *zitername) { cgns_ziter *ziter; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; ziter = cgi_get_ziter(cg, B, Z); if (ziter==0) return CG_NODE_NOT_FOUND; strcpy(zitername, ziter->name); return CG_OK; } int cg_ziter_write(int file_number, int B, int Z, const char * zitername) { cgns_zone *zone; cgns_ziter *ziter; /* verify input */ if (cgi_check_strlen(zitername)) return CG_ERROR; /* get memory address for ZoneIterativeData_t node */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; zone = cgi_get_zone(cg, B, Z); if (zone==0) return CG_ERROR; /* Overwrite the ZoneIterativeData_t Node: */ if (zone->ziter) { if (cg->mode==CG_MODE_WRITE) { cgi_error("Error: ZoneIterativeData_t already defined"); return CG_ERROR; } /* overwrite an existing ZoneIterativeData_t Node */ /* delete the existing ziter from file */ if (cgi_delete_node(zone->id, zone->ziter->id)) return CG_ERROR; /* save the old in-memory address to overwrite */ ziter = zone->ziter; /* free memory */ cgi_free_ziter(ziter); } else { zone->ziter = CGNS_NEW(cgns_ziter, 1); ziter = zone->ziter; } /* save data for cgns_ziter *ziter */ memset(ziter, 0, sizeof(cgns_ziter)); strcpy(ziter->name,zitername); /* Create node ZoneIterativeData_t */ if (cgi_new_node(zone->id, ziter->name, "ZoneIterativeData_t", &ziter->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write Gravity_t Node \*****************************************************************************/ int cg_gravity_read(int file_number, int B, float *gravity_vector) { cgns_base *base; cgns_gravity *gravity; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address for gravity */ gravity = cgi_get_gravity(cg, B); if (gravity==0) return CG_NODE_NOT_FOUND; memcpy(gravity_vector, gravity->vector->data, base->phys_dim*sizeof(float)); return CG_OK; } int cg_gravity_write(int file_number, int B, float const *gravity_vector) { cgns_base *base; cgns_gravity *gravity; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; if (base->gravity) { if (cg->mode==CG_MODE_WRITE) { cgi_error("Gravity is already defined under CGNSBase_t '%s'", base->name); return CG_ERROR; } if (cgi_delete_node(base->id, base->gravity->id)) return CG_ERROR; cgi_free_gravity(base->gravity); memset(base->gravity, 0, sizeof(cgns_gravity)); } else { base->gravity = CGNS_NEW(cgns_gravity, 1); } gravity = base->gravity; gravity->vector = CGNS_NEW(cgns_array, 1); /* initialize other fields of gravity */ strcpy(gravity->name, "Gravity"); /* Create DataArray_t GravityVector under gravity */ strcpy(gravity->vector->data_type, "R4"); gravity->vector->data = (void *)malloc(base->phys_dim*sizeof(float)); if (gravity->vector->data == NULL) { cgi_error("Error allocating gravity->vector->data"); return CG_ERROR; } memcpy(gravity->vector->data, gravity_vector, base->phys_dim*sizeof(float)); strcpy(gravity->vector->name, "GravityVector"); gravity->vector->data_dim=1; gravity->vector->dim_vals[0]=base->phys_dim; /* Write to disk */ if (cgi_write_gravity(base->id, gravity)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write Axisymmetry_t Node \*****************************************************************************/ int cg_axisym_read(int file_number, int B, float *ref_point, float *axis) { int n; cgns_base *base; cgns_axisym *axisym; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for base (for base->phys_dim) */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address for axisym */ axisym = cgi_get_axisym(cg, B); if (axisym==0) return CG_NODE_NOT_FOUND; for (n=0; nnarrays; n++) { if (strcmp(axisym->array[n].name,"AxisymmetryReferencePoint")==0) memcpy(ref_point, axisym->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(axisym->array[n].name,"AxisymmetryAxisVector")==0) memcpy(axis, axisym->array[n].data, base->phys_dim*sizeof(float)); } return CG_OK; } int cg_axisym_write(int file_number, int B, float const *ref_point, float const *axis) { int n; cgns_base *base; cgns_axisym *axisym; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* Verify that this is a bidimensional base */ if (base->phys_dim != 2) { cgi_error("Error: Axisymmetry_t can only be specified for bidimensional bases"); return CG_ERROR; } if (base->axisym) { if (cg->mode==CG_MODE_WRITE) { cgi_error("Axisymmetry is already defined under CGNSBase_t '%s'", base->name); return CG_ERROR; } if (cgi_delete_node(base->id, base->axisym->id)) return CG_ERROR; cgi_free_axisym(base->axisym); memset(base->axisym, 0, sizeof(cgns_axisym)); } else { base->axisym = CGNS_NEW(cgns_axisym, 1); } axisym = base->axisym; strcpy(axisym->name, "Axisymmetry"); axisym->array = CGNS_NEW(cgns_array, 2); axisym->narrays=2; /* Create DataArray_t AxisymmetryReferencePoint & AxisymmetryAxisVector under axisym */ for (n=0; nnarrays; n++) { strcpy(axisym->array[n].data_type, "R4"); axisym->array[n].data = (void *)malloc(base->phys_dim*sizeof(float)); if (axisym->array[n].data == NULL) { cgi_error("Error allocating axisym->array[n].data"); return CG_ERROR; } axisym->array[n].data_dim=1; axisym->array[n].dim_vals[0]=base->phys_dim; } memcpy(axisym->array[0].data, ref_point, base->phys_dim*sizeof(float)); memcpy(axisym->array[1].data, axis, base->phys_dim*sizeof(float)); strcpy(axisym->array[0].name, "AxisymmetryReferencePoint"); strcpy(axisym->array[1].name, "AxisymmetryAxisVector"); /* Write to disk */ if (cgi_write_axisym(base->id, axisym)) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write BCProperty_t Node \*****************************************************************************/ int cg_bc_wallfunction_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(WallFunctionType_t) *WallFunctionType) { cgns_bprop *bprop; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for bprop */ bprop = cgi_get_bprop(cg, B, Z, BC); if (bprop==0) return CG_NODE_NOT_FOUND; if (bprop->bcwall==0) { cgi_error("BCProperty_t/WallFunction_t node doesn't exist under BC_t %d",BC); return CG_NODE_NOT_FOUND; } *WallFunctionType = bprop->bcwall->type; return CG_OK; } int cg_bc_wallfunction_write(int file_number, int B, int Z, int BC, CGNS_ENUMT(WallFunctionType_t) WallFunctionType) { cgns_bprop *bprop; cgns_bcwall *bcwall; cgns_boco *boco; cgsize_t length; double dummy_id; /* verify input */ if (INVALID_ENUM(WallFunctionType,NofValidWallFunctionTypes)) { cgi_error("Invalid WallFunctionType: %d",WallFunctionType); return CG_ERROR; } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of BC_t node */ boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; /* Allocate BCProperty_t data struct. if not already created */ if (boco->bprop == 0) { boco->bprop = CGNS_NEW(cgns_bprop, 1); bprop = boco->bprop; strcpy(bprop->name,"BCProperty"); } else bprop = boco->bprop; /* Overwrite a WallFunction_t Node: */ if (bprop->bcwall) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("WallFunction_t already defined under BCProperty_t."); return CG_ERROR; } /* overwrite an existing WallFunction_t Node */ /* delete the existing WallFunction_t Node from file */ if (cgi_delete_node(bprop->id, bprop->bcwall->id)) return CG_ERROR; cgi_free_bcwall(bprop->bcwall); memset(bprop->bcwall, 0, sizeof(cgns_bcwall)); } else { bprop->bcwall = CGNS_NEW(cgns_bcwall, 1); } bcwall = bprop->bcwall; /* write bcwall info to internal memory */ bcwall->type = WallFunctionType; strcpy(bcwall->name,"WallFunction"); /* Create BCProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (bprop->id==0) { if (cgi_new_node(boco->id, "BCProperty", "BCProperty_t", &bprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(bprop->id, hid); if (hid==0) { if (cgi_new_node(boco->id, "BCProperty", "BCProperty_t", &bprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the WallFunction_t Node */ if (cgi_new_node(bprop->id, "WallFunction", "WallFunction_t", &bcwall->id, "MT", 0, 0, 0)) return CG_ERROR; /* WallFunction_t/WallFunctionType_t */ length = (cgsize_t)strlen(WallFunctionTypeName[bcwall->type]); if (cgi_new_node(bcwall->id, "WallFunctionType", "WallFunctionType_t", &dummy_id, "C1", 1, &length, (void *)WallFunctionTypeName[bcwall->type])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_bc_area_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(AreaType_t) *AreaType, float *SurfaceArea, char *RegionName) { int n; cgns_bprop *bprop; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for bprop */ bprop = cgi_get_bprop(cg, B, Z, BC); if (bprop==0) return CG_NODE_NOT_FOUND; if (bprop->bcarea==0) { cgi_error("BCProperty_t/Area_t node doesn't exist under BC_t %d",BC); return CG_NODE_NOT_FOUND; } *AreaType = bprop->bcarea->type; for (n=0; nbcarea->narrays; n++) { if (strcmp("SurfaceArea",bprop->bcarea->array[n].name)==0) memcpy(SurfaceArea, bprop->bcarea->array[n].data, sizeof(float)); else if (strcmp("RegionName",bprop->bcarea->array[n].name)==0) { memcpy(RegionName, bprop->bcarea->array[n].data, 32*sizeof(char)); RegionName[32]='\0'; } } return CG_OK; } int cg_bc_area_write(int file_number, int B, int Z, int BC, CGNS_ENUMT( AreaType_t ) AreaType, float SurfaceArea, const char *RegionName) { cgns_boco *boco; cgns_bprop *bprop; cgns_bcarea *bcarea; int n; cgsize_t len; char *RegionName32; double dummy_id; /* verify input */ if (INVALID_ENUM(AreaType,NofValidAreaTypes)) { cgi_error("Invalid AreaType: %d",AreaType); return CG_ERROR; } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of BC_t node */ boco = cgi_get_boco(cg, B, Z, BC); if (boco==0) return CG_ERROR; /* Allocate BCProperty_t data struct. if not already created */ if (boco->bprop == 0) { boco->bprop = CGNS_NEW(cgns_bprop, 1); bprop = boco->bprop; strcpy(bprop->name,"BCProperty"); } else bprop = boco->bprop; /* Overwrite a Area_t Node: */ if (bprop->bcarea) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Area_t already defined under BCProperty_t."); return CG_ERROR; } /* overwrite an existing Area_t Node */ /* delete the existing Area_t Node from file */ if (cgi_delete_node(bprop->id, bprop->bcarea->id)) return CG_ERROR; cgi_free_bcarea(bprop->bcarea); memset(bprop->bcarea, 0, sizeof(cgns_bcarea)); } else { bprop->bcarea = CGNS_NEW(cgns_bcarea, 1); } bcarea = bprop->bcarea; /* write bcarea info to internal memory */ bcarea->type = AreaType; strcpy(bcarea->name,"Area"); bcarea->narrays = 2; /* Create DataArray_t SurfaceArea & RegionName under Area_t */ bcarea->array = CGNS_NEW(cgns_array, 2); strcpy(bcarea->array[0].data_type, "R4"); bcarea->array[0].data = (void *)malloc(sizeof(float)); if (bcarea->array[0].data == NULL) { cgi_error("Error allocating bcarea->array[0].data"); return CG_ERROR; } memcpy(bcarea->array[0].data, &SurfaceArea, sizeof(float)); /* *((float *)bcarea->array[0].data) = SurfaceArea; */ strcpy(bcarea->array[0].name, "SurfaceArea"); bcarea->array[0].data_dim=1; bcarea->array[0].dim_vals[0]=1; strcpy(bcarea->array[1].data_type, "C1"); bcarea->array[1].data = (void *)malloc(32*sizeof(char)); if (bcarea->array[1].data == NULL) { cgi_error("Error allocating bcarea->array[1].data"); return CG_ERROR; } /* check length of RegionName and fill in with blanks */ RegionName32 = (char *)bcarea->array[1].data; len = (int)strlen(RegionName); for (n=0; n<(int)len; n++) RegionName32[n]=RegionName[n]; for (n=(int)len; n<32; n++) RegionName32[n]=' '; strcpy(bcarea->array[1].name, "RegionName"); bcarea->array[1].data_dim=1; bcarea->array[1].dim_vals[0]=32; /* Create BCProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (bprop->id==0) { if (cgi_new_node(boco->id, "BCProperty", "BCProperty_t", &bprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(bprop->id, hid); if (hid==0) { if (cgi_new_node(boco->id, "BCProperty", "BCProperty_t", &bprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the Area_t Node */ if (cgi_new_node(bprop->id, "Area", "Area_t", &bcarea->id, "MT", 0, 0, 0)) return CG_ERROR; /* Area_t/AreaType_t */ len = (cgsize_t)strlen(AreaTypeName[bcarea->type]); if (cgi_new_node(bcarea->id, "AreaType", "AreaType_t", &dummy_id, "C1", 1, &len, (void *)AreaTypeName[bcarea->type])) return CG_ERROR; /* Area_t/DataArray_t: SurfaceArea & RegionName */ for (n=0; nnarrays; n++) if (cgi_write_array(bcarea->id, &bcarea->array[n])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * read and write GridConnectivityProperty_t Node \*****************************************************************************/ int cg_conn_periodic_read(int file_number, int B, int Z, int I, float *RotationCenter, float *RotationAngle, float *Translation) { int n; cgns_base *base; cgns_cprop *cprop; cgns_cperio *cperio; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for base (for base->phys_dim) */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address for cprop */ cprop = cgi_get_cprop(cg, B, Z, I); if (cprop==0) return CG_NODE_NOT_FOUND; if (cprop->cperio == 0) { cgi_error("GridConnectivityProperty_t/Periodic_t node doesn't exist under GridConnectivity_t %d",I); return CG_NODE_NOT_FOUND; } cperio = cprop->cperio; /* Copy data to be returned */ for (n=0; nnarrays; n++) { if (strcmp(cperio->array[n].name,"RotationCenter")==0) memcpy(RotationCenter, cperio->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(cperio->array[n].name,"RotationAngle")==0) memcpy(RotationAngle, cperio->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(cperio->array[n].name,"Translation")==0) memcpy(Translation, cperio->array[n].data, base->phys_dim*sizeof(float)); } return CG_OK; } int cg_conn_periodic_write(int file_number, int B, int Z, int I, float const *RotationCenter, float const *RotationAngle, float const *Translation) { cgns_base *base; cgns_conn *conn; cgns_cprop *cprop; cgns_cperio *cperio; int n; /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address of GridConnectivity_t node */ conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_ERROR; /* Allocate GridConnectivityProperty_t data struct. if not already created */ if (conn->cprop == 0) { conn->cprop = CGNS_NEW(cgns_cprop, 1); cprop = conn->cprop; strcpy(cprop->name,"GridConnectivityProperty"); } else cprop = conn->cprop; /* Overwrite a Periodic_t Node: */ if (cprop->cperio) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Periodic_t already defined under GridConnectivityProperty_t."); return CG_ERROR; } /* overwrite an existing Periodic_t Node */ /* delete the existing Periodic_t Node from file */ if (cgi_delete_node(cprop->id, cprop->cperio->id)) return CG_ERROR; cgi_free_cperio(cprop->cperio); memset(cprop->cperio, 0, sizeof(cgns_cperio)); } else { cprop->cperio = CGNS_NEW(cgns_cperio, 1); } cperio = cprop->cperio; /* write cperio info to internal memory */ strcpy(cperio->name,"Periodic"); cperio->narrays = 3; /* Create DataArray_t RotationCenter, RotationAngle, & Translation under Periodic_t */ cperio->array = CGNS_NEW(cgns_array, 3); for (n=0; nnarrays; n++) { strcpy(cperio->array[n].data_type, "R4"); cperio->array[n].data = (void *)malloc(base->phys_dim*sizeof(float)); if (cperio->array[n].data == NULL) { cgi_error("Error allocating cperio->array[n].data"); return CG_ERROR; } cperio->array[n].data_dim=1; cperio->array[n].dim_vals[0]=base->phys_dim; } memcpy(cperio->array[0].data,RotationCenter,base->phys_dim*sizeof(float)); memcpy(cperio->array[1].data,RotationAngle,base->phys_dim*sizeof(float)); memcpy(cperio->array[2].data,Translation,base->phys_dim*sizeof(float)); strcpy(cperio->array[0].name,"RotationCenter"); strcpy(cperio->array[1].name,"RotationAngle"); strcpy(cperio->array[2].name,"Translation"); /* Create GridConnectivityProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (cprop->id==0) { if (cgi_new_node(conn->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(cprop->id, hid); if (hid==0) { if (cgi_new_node(conn->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the Periodic_t Node */ if (cgi_new_node(cprop->id, "Periodic", "Periodic_t", &cperio->id, "MT", 0, 0, 0)) return CG_ERROR; /* Periodic_t/DataArray_t: RotationCenter, RotationAngle, Translation */ for (n=0; nnarrays; n++) if (cgi_write_array(cperio->id, &cperio->array[n])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_conn_average_read(int file_number, int B, int Z, int I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType) { cgns_cprop *cprop; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for cprop */ cprop = cgi_get_cprop(cg, B, Z, I); if (cprop==0) return CG_NODE_NOT_FOUND; if (cprop->caverage == 0) { cgi_error("GridConnectivityProperty_t/AverageInterface_t node doesn't exist under GridConnectivity_t %d",I); return CG_NODE_NOT_FOUND; } *AverageInterfaceType = cprop->caverage->type; return CG_OK; } int cg_conn_average_write(int file_number, int B, int Z, int I, CGNS_ENUMT(AverageInterfaceType_t) AverageInterfaceType) { cgns_cprop *cprop; cgns_caverage *caverage; cgns_conn *conn; cgsize_t length; double dummy_id; /* verify input */ if (INVALID_ENUM(AverageInterfaceType,NofValidAverageInterfaceTypes)) { cgi_error("Invalid AverageInterfaceType: %d",AverageInterfaceType); return CG_ERROR; } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of GridConnectivity_t node */ conn = cgi_get_conn(cg, B, Z, I); if (conn==0) return CG_ERROR; /* Allocate GridConnectivityProperty_t data struct. if not already created */ if (conn->cprop == 0) { conn->cprop = CGNS_NEW(cgns_cprop, 1); cprop = conn->cprop; strcpy(cprop->name,"GridConnectivityProperty"); } else cprop = conn->cprop; /* Overwrite an AverageInterface_t Node: */ if (cprop->caverage) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("AverageInterface_t already defined under GridConnectivityProperty_t"); return CG_ERROR; } /* overwrite an existing AverageInterface_t Node */ /* delete the existing AverageInterface_t Node from file */ if (cgi_delete_node(cprop->id, cprop->caverage->id)) return CG_ERROR; cgi_free_caverage(cprop->caverage); memset(cprop->caverage, 0, sizeof(cgns_caverage)); } else { cprop->caverage = CGNS_NEW(cgns_caverage, 1); } caverage = cprop->caverage; /* write caverage info to internal memory */ caverage->type = AverageInterfaceType; strcpy(caverage->name,"AverageInterface"); /* Create GridConnectivityProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (cprop->id==0) { if (cgi_new_node(conn->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(cprop->id, hid); if (hid==0) { if (cgi_new_node(conn->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the AverageInterface_t Node */ if (cgi_new_node(cprop->id, "AverageInterface", "AverageInterface_t", &caverage->id, "MT", 0, 0, 0)) return CG_ERROR; /* AverageInterface_t/AverageInterfaceType_t */ length = (cgsize_t)strlen(AverageInterfaceTypeName[caverage->type]); if (cgi_new_node(caverage->id, "AverageInterfaceType", "AverageInterfaceType_t", &dummy_id, "C1", 1, &length, (void *)AverageInterfaceTypeName[caverage->type])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_1to1_periodic_read(int file_number, int B, int Z, int I, float *RotationCenter, float *RotationAngle, float *Translation) { int n; cgns_base *base; cgns_cprop *cprop; cgns_cperio *cperio; cgns_1to1 *one21; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for base (for base->phys_dim) */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address for cprop from one21->cprop */ one21 = cgi_get_1to1(cg, B, Z, I); if (one21==0) return CG_ERROR; cprop = one21->cprop; if (cprop == 0 || cprop->cperio == 0) { cgi_error("GridConnectivityProperty_t/Periodic_t node doesn't exist under GridConnectivity1to1_t %d",I); return CG_NODE_NOT_FOUND; } cperio = cprop->cperio; /* Copy data to be returned */ for (n=0; nnarrays; n++) { if (strcmp(cperio->array[n].name,"RotationCenter")==0) memcpy(RotationCenter, cperio->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(cperio->array[n].name,"RotationAngle")==0) memcpy(RotationAngle, cperio->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(cperio->array[n].name,"Translation")==0) memcpy(Translation, cperio->array[n].data, base->phys_dim*sizeof(float)); } return CG_OK; } int cg_1to1_periodic_write(int file_number, int B, int Z, int I, float const *RotationCenter, float const *RotationAngle, float const *Translation) { cgns_base *base; cgns_1to1 *one21; cgns_cprop *cprop; cgns_cperio *cperio; int n; /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address for base */ base = cgi_get_base(cg, B); if (base==0) return CG_ERROR; /* get memory address of GridConnectivity1to1_t node */ one21 = cgi_get_1to1(cg, B, Z, I); if (one21 == 0) return CG_ERROR; /* Allocate GridConnectivityProperty_t data struct. if not already created */ if (one21->cprop == 0) { one21->cprop = CGNS_NEW(cgns_cprop, 1); cprop = one21->cprop; strcpy(cprop->name,"GridConnectivityProperty"); } else cprop = one21->cprop; /* Overwrite a Periodic_t Node: */ if (cprop->cperio) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("Periodic_t already defined under GridConnectivityProperty_t."); return CG_ERROR; } /* overwrite an existing Periodic_t Node */ else if (cg->mode==CG_MODE_MODIFY) { /* delete the existing Periodic_t Node from file */ if (cgi_delete_node(cprop->id, cprop->cperio->id)) return CG_ERROR; cgi_free_cperio(cprop->cperio); memset(cprop->cperio, 0, sizeof(cgns_cperio)); } } else cprop->cperio = CGNS_NEW(cgns_cperio, 1); cperio = cprop->cperio; /* write cperio info to internal memory */ strcpy(cperio->name,"Periodic"); cperio->narrays = 3; /* Create DataArray_t RotationCenter, RotationAngle, & Translation under Periodic_t */ cperio->array = CGNS_NEW(cgns_array, 3); for (n=0; nnarrays; n++) { strcpy(cperio->array[n].data_type, "R4"); cperio->array[n].data = (void *)malloc(base->phys_dim*sizeof(float)); if (cperio->array[n].data == NULL) { cgi_error("Error allocating cperio->array[n].data"); return CG_ERROR; } cperio->array[n].data_dim=1; cperio->array[n].dim_vals[0]=base->phys_dim; } memcpy(cperio->array[0].data,RotationCenter,base->phys_dim*sizeof(float)); memcpy(cperio->array[1].data,RotationAngle,base->phys_dim*sizeof(float)); memcpy(cperio->array[2].data,Translation,base->phys_dim*sizeof(float)); strcpy(cperio->array[0].name,"RotationCenter"); strcpy(cperio->array[1].name,"RotationAngle"); strcpy(cperio->array[2].name,"Translation"); /* Create GridConnectivityProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (cprop->id==0) { if (cgi_new_node(one21->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(cprop->id, hid); if (hid==0) { if (cgi_new_node(one21->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the Periodic_t Node */ if (cgi_new_node(cprop->id, "Periodic", "Periodic_t", &cperio->id, "MT", 0, 0, 0)) return CG_ERROR; /* Periodic_t/DataArray_t: RotationCenter, RotationAngle, Translation */ for (n=0; nnarrays; n++) if (cgi_write_array(cperio->id, &cperio->array[n])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_1to1_average_read(int file_number, int B, int Z, int I, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType) { cgns_cprop *cprop; cgns_1to1 *one21; /* get memory address for file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* get memory address for cprop from one21->cprop */ one21 = cgi_get_1to1(cg, B, Z, I); if (one21==0) return CG_ERROR; cprop = one21->cprop; if (cprop == 0 || cprop->caverage == 0) { cgi_error("GridConnectivityProperty_t/AverageInterface_t node doesn't exist under GridConnectivity1to1_t %d",I); return CG_NODE_NOT_FOUND; } *AverageInterfaceType = cprop->caverage->type; return CG_OK; } int cg_1to1_average_write(int file_number, int B, int Z, int I, CGNS_ENUMT(AverageInterfaceType_t) AverageInterfaceType) { cgns_cprop *cprop; cgns_caverage *caverage; cgns_1to1 *one21; cgsize_t length; double dummy_id; /* verify input */ if (INVALID_ENUM(AverageInterfaceType,NofValidAverageInterfaceTypes)) { cgi_error("Invalid AverageInterfaceType: %d",AverageInterfaceType); return CG_ERROR; } /* get memory address of file */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; /* get memory address of GridConnectivity_t node */ one21 = cgi_get_1to1(cg, B, Z, I); if (one21 == 0) return CG_ERROR; /* Allocate GridConnectivityProperty_t data struct. if not already created */ if (one21->cprop == 0) { one21->cprop = CGNS_NEW(cgns_cprop, 1); cprop = one21->cprop; strcpy(cprop->name,"GridConnectivityProperty"); } else cprop = one21->cprop; /* Overwrite an AverageInterface_t Node: */ if (cprop->caverage) { /* in CG_MODE_WRITE, children names must be unique */ if (cg->mode==CG_MODE_WRITE) { cgi_error("AverageInterface_t already defined under GridConnectivityProperty_t"); return CG_ERROR; } /* overwrite an existing AverageInterface_t Node */ else if (cg->mode==CG_MODE_MODIFY) { /* delete the existing AverageInterface_t Node from file */ if (cgi_delete_node(cprop->id, cprop->caverage->id)) return CG_ERROR; cgi_free_caverage(cprop->caverage); memset(cprop->caverage, 0, sizeof(cgns_caverage)); } } else cprop->caverage = CGNS_NEW(cgns_caverage, 1); caverage = cprop->caverage; /* write caverage info to internal memory */ caverage->type = AverageInterfaceType; /* initialize other fields */ strcpy(caverage->name,"AverageInterface"); /* Create GridConnectivityProperty_t node if it doesn't yet exist */ if (cg->filetype == CGIO_FILE_ADF || cg->filetype == CGIO_FILE_ADF2) { if (cprop->id==0) { if (cgi_new_node(one21->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #ifdef BUILD_HDF5 else if (cg->filetype == CGIO_FILE_HDF5) { hid_t hid; to_HDF_ID(cprop->id, hid); if (hid==0) { if (cgi_new_node(one21->id, "GridConnectivityProperty", "GridConnectivityProperty_t", &cprop->id, "MT", 0, 0, 0)) return CG_ERROR; } } #endif else { return CG_ERROR; } /* Create the AverageInterface_t Node */ if (cgi_new_node(cprop->id, "AverageInterface", "AverageInterface_t", &caverage->id, "MT", 0, 0, 0)) return CG_ERROR; /* AverageInterface_t/AverageInterfaceType_t */ length = (cgsize_t)strlen(AverageInterfaceTypeName[caverage->type]); if (cgi_new_node(caverage->id, "AverageInterfaceType", "AverageInterfaceType_t", &dummy_id, "C1", 1, &length, (void *)AverageInterfaceTypeName[caverage->type])) return CG_ERROR; return CG_OK; } /*****************************************************************************\ * Go - To Function \*****************************************************************************/ int vcg_goto(int file_number, int B, va_list ap) { int n; int index[CG_MAX_GOTO_DEPTH]; char *label[CG_MAX_GOTO_DEPTH]; /* initialize */ posit = 0; /* set global variable cg */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; /* read variable argument list */ for (n = 0; n < CG_MAX_GOTO_DEPTH; n++) { label[n] = va_arg(ap,char *); if (label[n] == NULL || label[n][0] == 0) break; if (strcmp("end",label[n])==0 || strcmp("END",label[n])==0) break; index[n] = va_arg(ap, int); } return cgi_set_posit(file_number, B, n, index, label); } int cg_goto(int file_number, int B, ...) { va_list ap; int status; va_start(ap, B); status = vcg_goto(file_number, B, ap); va_end(ap); return status; } /*----------------------------------------------------------------------- * F2008 C-FORTRAN INTERFACE ROUTINE * * cg_goto function which is compatible with F2008 and TS 29113 * "Further Interoperability of Fortran with C WG5/N1942" and * allows optional function parameters to be passed to a C function * which has variable number of arguments. This function is * directly callable from FORTRAN. * */ int cg_goto_f08(int file_number, int B, ...) { int n; va_list ap; int index[CG_MAX_GOTO_DEPTH]; char *label[CG_MAX_GOTO_DEPTH]; /* initialize */ posit = 0; /* set global variable cg */ cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; va_start(ap, B); /* read variable argument list */ for (n = 0; n < CG_MAX_GOTO_DEPTH; n++) { label[n] = va_arg(ap,char *); if (label[n] == NULL || label[n][0] == 0) break; if (strcmp("end",label[n])==0 || strcmp("END",label[n])==0) break; index[n] = (int)*va_arg(ap, int *); } va_end(ap); return cgi_set_posit(file_number, B, n, index, label); } /*-----------------------------------------------------------------------*/ int vcg_gorel(int file_number, va_list ap) { int n = 0; int index[CG_MAX_GOTO_DEPTH]; char *label[CG_MAX_GOTO_DEPTH]; if (posit == 0) { cgi_error ("position not set with cg_goto"); return CG_ERROR; } if (file_number != posit_file) { cgi_error("current position is in the wrong file"); return CG_ERROR; } for (n = 0; n < CG_MAX_GOTO_DEPTH; n++) { label[n] = va_arg(ap, char *); if (label[n] == NULL || label[n][0] == 0) break; if (strcmp("end",label[n])==0 || strcmp("END",label[n])==0) break; index[n] = va_arg(ap, int); } return cgi_update_posit(n, index, label); } int cg_gorel(int file_number, ...) { va_list ap; int status; va_start (ap, file_number); status = vcg_gorel(file_number, ap); va_end(ap); return status; } /*----------------------------------------------------------------------- * F2008 C-FORTRAN INTERFACE ROUTINE * * cg_gorel function which is compatible with F2008 and TS 29113 * "Further Interoperability of Fortran with C WG5/N1942" and * allows optional function parameters to be passed to a C function * which has variable number of arguments. This function is * directly callable from FORTRAN. * */ int cg_gorel_f08(int file_number, ...) { int n = 0; int index[CG_MAX_GOTO_DEPTH]; char *label[CG_MAX_GOTO_DEPTH]; va_list ap; if (posit == 0) { cgi_error ("position not set with cg_goto"); return CG_ERROR; } if (file_number != posit_file) { cgi_error("current position is in the wrong file"); return CG_ERROR; } va_start (ap, file_number); for (n = 0; n < CG_MAX_GOTO_DEPTH; n++) { label[n] = va_arg(ap, char *); if (label[n] == NULL || label[n][0] == 0) break; if (strcmp("end",label[n])==0 || strcmp("END",label[n])==0) break; index[n] = (int)*va_arg(ap, int *); } va_end(ap); return cgi_update_posit(n, index, label); } /*-----------------------------------------------------------------------*/ int cg_gopath(int file_number, const char *path) { int n, len; const char *p = path, *s; int index[CG_MAX_GOTO_DEPTH]; char label[CG_MAX_GOTO_DEPTH][33]; char *lab[CG_MAX_GOTO_DEPTH]; if (p == 0 || !*p) { cgi_error("path not given"); return CG_ERROR; } /* absolute path */ if (*p == '/') { int ierr, B = 0; posit = 0; while (*++p && *p == '/') ; if (!*p) { cgi_error("base name not given"); return CG_ERROR; } s = strchr(p, '/'); if (s == 0) len = (int)strlen(p); else len = (int)(s - p); if (len > 32) { cgi_error("base name in path is too long"); return CG_ERROR; } strncpy(label[0], p, len); label[0][len] = 0; cg = cgi_get_file(file_number); if (cg == 0) return CG_ERROR; for (n = 0; n < cg->nbases; n++) { if (0 == strcmp(label[0], cg->base[n].name)) { B = n + 1; break; } } if (B == 0) { cgi_error("base '%s' not found", label[0]); return CG_ERROR; } ierr = cgi_set_posit(file_number, B, 0, index, lab); if (ierr != CG_OK) return ierr; if (s == 0) return CG_OK; p = s; } /* relative path */ else { if (posit == 0) { cgi_error("position not set with cg_goto"); return CG_ERROR; } if (file_number != posit_file) { cgi_error("current position is in the wrong file"); return CG_ERROR; } } n = 0; while (p && *p) { while (*p && *p == '/') p++; if (!*p) break; s = strchr(p, '/'); if (s == 0) len = (int)strlen(p); else len = (int)(s - p); if (len > 32) { posit = 0; cgi_error("node name in path is too long"); return CG_ERROR; } if (n == CG_MAX_GOTO_DEPTH) { posit = 0; cgi_error("path is too deep"); return CG_ERROR; } strncpy(label[n], p, len); label[n][len] = 0; lab[n] = label[n]; index[n++] = 0; p = s; } return cgi_update_posit(n, index, lab); } /*-----------------------------------------------------------------------*/ int cg_golist(int file_number, int B, int depth, char **label, int *index) { if (depth >= CG_MAX_GOTO_DEPTH) { cgi_error("path is too deep"); return CG_ERROR; } return cgi_set_posit(file_number, B, depth, index, label); } /*-----------------------------------------------------------------------*/ int cg_where(int *file_number, int *B, int *depth, char **label, int *num) { int n; if (posit == 0) { cgi_error ("position not set with cg_goto"); return CG_ERROR; } *file_number = posit_file; *B = posit_base; /* first entry is base */ *depth = posit_depth > 1 ? posit_depth - 1 : 0; if (NULL != label) { for (n = 1; n < posit_depth; n++) strcpy(label[n-1], posit_stack[n].label); } if (NULL != num) { for (n = 1; n < posit_depth; n++) num[n-1] = posit_stack[n].index; } return CG_OK; } /*****************************************************************************\ * Read and write Multiple path nodes \*****************************************************************************/ int cg_famname_read(char *family_name) { char *famname; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; famname = cgi_famname_address(CG_MODE_READ, &ier); if (famname==0) return ier; strcpy(family_name,famname); if (!strlen(famname)) return CG_NODE_NOT_FOUND; return CG_OK; } int cg_famname_write(const char * family_name) { char *famname; int ier=0; cgsize_t dim_vals; double posit_id, dummy_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (cgi_check_strlen(family_name)) return CG_ERROR; famname = cgi_famname_address(CG_MODE_WRITE, &ier); if (famname==0) return ier; strcpy(famname, family_name); /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; dim_vals = (cgsize_t)strlen(family_name); if (cgi_new_node(posit_id, "FamilyName", "FamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)family_name)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_nmultifam(int *nfams) { CHECK_FILE_OPEN /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*nfams) = 0; return CG_ERROR; } if (0 == strcmp(posit->label,"Zone_t")) { cgns_zone *zone= (cgns_zone *)posit->posit; (*nfams) = zone->nfamname; } else if (0 == strcmp(posit->label,"BC_t")) { cgns_boco *boco = (cgns_boco *)posit->posit; (*nfams) = boco->nfamname; } else if (strcmp(posit->label,"ZoneSubRegion_t")==0) { cgns_subreg *subreg = (cgns_subreg *)posit->posit; (*nfams) = subreg->nfamname; } else if (strcmp(posit->label,"UserDefinedData_t")==0) { cgns_user_data *user_data = (cgns_user_data *)posit->posit; (*nfams) = user_data->nfamname; } else { cgi_error("AdditionalFamilyName_t node not supported under '%s' type node",posit->label); (*nfams) = 0; return CG_INCORRECT_PATH; } return CG_OK; } int cg_multifam_read(int N, char *name, char *family) { cgns_famname *famname; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; famname = cgi_multfam_address(CG_MODE_READ, N, "", &ier); if (famname==0) return ier; strcpy(name, famname->name); strcpy(family, famname->family); return CG_OK; } int cg_multifam_write(const char *name, const char *family) { cgns_famname *famname; int ier=0; cgsize_t dim_vals; double posit_id, dummy_id; CHECK_FILE_OPEN if (cgi_check_strlen(name) || cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; #ifdef CG_BUILD_BASESCOPE if (cgi_check_strlen_x2(family)) return CG_ERROR; #else if (cgi_check_strlen(family)) return CG_ERROR; #endif famname = cgi_multfam_address(CG_MODE_WRITE, 0, name, &ier); if (famname == 0) return ier; strcpy(famname->name, name); strcpy(famname->family, family); if (cgi_posit_id(&posit_id)) return CG_ERROR; dim_vals = (cgsize_t)strlen(family); if (cgi_new_node(posit_id, name, "AdditionalFamilyName_t", &dummy_id, "C1", 1, &dim_vals, (void *)family)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_convergence_read(int *iterations, char **NormDefinitions) { cgns_converg *converg; cgns_descr *descr; int ier=0; CHECK_FILE_OPEN /* verify input (cg set in cg_goto) */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; converg = cgi_converg_address(CG_MODE_READ, &ier); if (converg==0) return ier; (*iterations) = converg->iterations; if (converg->NormDefinitions==0) { NormDefinitions[0] = CGNS_NEW(char, 1); NormDefinitions[0][0]='\0'; } else { descr = converg->NormDefinitions; NormDefinitions[0] = CGNS_NEW(char, strlen(descr->text)+1); strcpy(NormDefinitions[0], descr->text); } return CG_OK; } int cg_convergence_write(int iterations, const char * NormDefinitions) { cgns_converg *converg; int ier=0; cgsize_t dim_vals; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; converg = cgi_converg_address(CG_MODE_WRITE, &ier); if (converg==0) return ier; /* initialize new ConvergenceHistory_t node */ converg->iterations=0; converg->id = 0; converg->link=0; converg->ndescr=0; converg->NormDefinitions = 0; converg->narrays=0; converg->data_class=CGNS_ENUMV( DataClassNull ); converg->units=0; converg->nuser_data=0; /* save data in memory */ converg->iterations = iterations; if (NormDefinitions && strlen(NormDefinitions)) { converg->NormDefinitions=CGNS_NEW(cgns_descr, 1); converg->NormDefinitions->id=0; converg->NormDefinitions->link=0; converg->NormDefinitions->text = CGNS_NEW(char, strlen(NormDefinitions)+1); strcpy(converg->NormDefinitions->text, NormDefinitions); strcpy(converg->NormDefinitions->name, "NormDefinitions"); } /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; dim_vals=1; if (cgi_new_node(posit_id, converg->name, "ConvergenceHistory_t", &converg->id, "I4", 1, &dim_vals, (void *)&converg->iterations)) return CG_ERROR; /* write NormDefinitions */ if (converg->NormDefinitions && cgi_write_descr(converg->id, converg->NormDefinitions)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_state_read(char **StateDescription) { cgns_state *state; cgns_descr *descr; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; state = cgi_state_address(CG_MODE_READ, &ier); if (state==0) return ier; if (state->StateDescription == 0) { StateDescription[0]=CGNS_NEW(char, 1); StateDescription[0][0]='\0'; } else { descr = state->StateDescription; StateDescription[0]=CGNS_NEW(char, strlen(descr->text)+1); strcpy(StateDescription[0], descr->text); } return CG_OK; } int cg_state_write(const char * StateDescription) { cgns_state *state; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; state = cgi_state_address(CG_MODE_WRITE, &ier); if (state==0) return ier; /* initialize state */ strcpy(state->name,"ReferenceState"); state->id = 0; state->link=0; state->ndescr=0; state->narrays=0; state->data_class=CGNS_ENUMV( DataClassNull ); state->units=0; state->StateDescription=0; state->nuser_data=0; /* Save data in memory */ if (StateDescription && strlen(StateDescription)) { state->StateDescription=CGNS_NEW(cgns_descr, 1); state->StateDescription->id = 0; state->StateDescription->link = 0; state->StateDescription->text = CGNS_NEW(char, strlen(StateDescription)+1); strcpy(state->StateDescription->text, StateDescription); strcpy(state->StateDescription->name, "ReferenceStateDescription"); } /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; /* ReferenceState_t */ if (cgi_new_node(posit_id, state->name, "ReferenceState_t", &state->id, "MT", 0, 0, 0)) return CG_ERROR; /* ReferenceStateDescription */ if (state->StateDescription && cgi_write_descr(state->id, state->StateDescription)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_equationset_read(int *EquationDimension, int *GoverningEquationsFlag, int *GasModelFlag, int *ViscosityModelFlag, int *ThermalConductivityModelFlag, int *TurbulenceClosureFlag, int *TurbulenceModelFlag) { cgns_equations *eq; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; eq = cgi_equations_address(CG_MODE_READ, &ier); if (eq==0) return ier; (*EquationDimension) = eq->equation_dim; if (eq->governing) (*GoverningEquationsFlag)=1; else (*GoverningEquationsFlag)=0; if (eq->gas) (*GasModelFlag)=1; else (*GasModelFlag)=0; if (eq->visc) (*ViscosityModelFlag)=1; else (*ViscosityModelFlag)=0; if (eq->conduct) (*ThermalConductivityModelFlag)=1; else (*ThermalConductivityModelFlag)=0; if (eq->closure) (*TurbulenceClosureFlag)=1; else (*TurbulenceClosureFlag)=0; if (eq->turbulence) (*TurbulenceModelFlag)=1; else (*TurbulenceModelFlag)=0; /* Version 2.1 chemistry extensions get their own read routine ** for backward compatability. */ return CG_OK; } int cg_equationset_chemistry_read(int *ThermalRelaxationFlag, int *ChemicalKineticsFlag) { cgns_equations *eq; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; eq = cgi_equations_address(CG_MODE_READ, &ier); if (eq==0) return ier; if (eq->relaxation) (*ThermalRelaxationFlag)=1; else (*ThermalRelaxationFlag)=0; if (eq->chemkin) (*ChemicalKineticsFlag)=1; else (*ChemicalKineticsFlag)=0; return CG_OK; } int cg_equationset_elecmagn_read(int *ElecFldModelFlag, int *MagnFldModelFlag, int *ConductivityModelFlag) { cgns_equations *eq; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; eq = cgi_equations_address(CG_MODE_READ, &ier); if (eq==0) return ier; if (eq->elecfield) (*ElecFldModelFlag)=1; else (*ElecFldModelFlag)=0; if (eq->magnfield) (*MagnFldModelFlag)=1; else (*MagnFldModelFlag)=0; if (eq->emconduct) (*ConductivityModelFlag)=1; else (*ConductivityModelFlag)=0; return CG_OK; } int cg_equationset_write(int EquationDimension) { cgns_equations *equations; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; equations=cgi_equations_address(CG_MODE_WRITE, &ier); if (equations==0) return ier; /* Save data */ equations->equation_dim=EquationDimension; /* initialize other fields */ strcpy(equations->name, "FlowEquationSet"); equations->id=0; equations->link=0; equations->ndescr=0; equations->governing=0; equations->gas=0; equations->visc=0; equations->conduct=0; equations->closure=0; equations->turbulence=0; equations->relaxation=0; equations->chemkin=0; equations->data_class=CGNS_ENUMV( DataClassNull ); equations->units=0; equations->nuser_data=0; equations->elecfield = 0; equations->magnfield = 0; equations->emconduct = 0; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_equations(posit_id, equations)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_governing_read(CGNS_ENUMT(GoverningEquationsType_t) *EquationsType) { cgns_governing *governing; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; governing = cgi_governing_address(CG_MODE_READ, &ier); if (governing==0) return ier; (*EquationsType) = governing->type; return CG_OK; } int cg_governing_write(CGNS_ENUMT(GoverningEquationsType_t) Equationstype) { cgns_governing *governing; int ier=0, index_dim; cgsize_t dim_vals; double posit_id; CHECK_FILE_OPEN /* verify input */ if (INVALID_ENUM(Equationstype,NofValidGoverningEquationsTypes)) { cgi_error("Invalid Governing Equations Type: %d",Equationstype); return CG_ERROR; } if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; governing = cgi_governing_address(CG_MODE_WRITE, &ier); if (governing==0) return ier; /* Save data */ governing->type=Equationstype; /* initialize other fields */ strcpy(governing->name, "GoverningEquations"); governing->id=0; governing->link=0; governing->ndescr=0; governing->diffusion_model=0; governing->nuser_data=0; if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; /* If defined under CGNSBase_t node */ } else if (posit_base) { index_dim = cg->base[posit_base-1].cell_dim; } else { cgi_error("Can't find IndexDimension in cg_governing_write."); return CG_NO_INDEX_DIM; } if (index_dim==1) governing->dim_vals=1; else if (index_dim==2) governing->dim_vals=3; else if (index_dim==3) governing->dim_vals=6; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; dim_vals = (cgsize_t)strlen(GoverningEquationsTypeName[governing->type]); if (cgi_new_node(posit_id, "GoverningEquations", "GoverningEquations_t", &governing->id, "C1", 1, &dim_vals, GoverningEquationsTypeName[governing->type])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_diffusion_read(int *diffusion_model) { int n, ndata, ier=0; int *diffusion, index_dim; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; diffusion = cgi_diffusion_address(CG_MODE_READ, &ier); if (diffusion==0) return ier; if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; /* If defined under CGNSBase_t node */ } else if (posit_base) { index_dim = cg->base[posit_base-1].cell_dim; } else { cgi_error("Can't find IndexDimension in cg_diffusion_read."); return CG_NO_INDEX_DIM; } if (index_dim==1) ndata=1; else if (index_dim==2) ndata=3; else if (index_dim==3) ndata=6; else { cgi_error("invalid value for IndexDimension"); return CG_ERROR; } for (n=0; nfilename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; diffusion = cgi_diffusion_address(CG_MODE_WRITE, &ier); if (diffusion==0) return ier; /* Save data */ if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; /* If defined under CGNSBase_t node */ } else if (posit_base) { index_dim = cg->base[posit_base-1].cell_dim; } else { cgi_error("Can't find IndexDimension in cg_diffusion_write."); return CG_NO_INDEX_DIM; } if (index_dim==1) ndata=1; else if (index_dim==2) ndata=3; else if (index_dim==3) ndata=6; else { cgi_error("invalid value for IndexDimension"); return CG_ERROR; } for (n=0; nfilename, cg->mode, CG_MODE_READ)) return CG_ERROR; model = cgi_model_address(CG_MODE_READ, ModelLabel, &ier); if (model==0) return ier; (*ModelType) = model->type; return CG_OK; } int cg_model_write(const char * ModelLabel, CGNS_ENUMT(ModelType_t) ModelType) { cgns_model *model; char ModelName[33]; int ier=0, index_dim; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (INVALID_ENUM(ModelType,NofValidModelTypes)) { cgi_error("Invalid %s Type: %d",ModelLabel,ModelType); return CG_ERROR; } /* Validate enums for each model type. */ if (strcmp(ModelLabel, "GasModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Ideal ) && ModelType!=CGNS_ENUMV( VanderWaals ) && ModelType!=CGNS_ENUMV( CaloricallyPerfect ) && ModelType!=CGNS_ENUMV( ThermallyPerfect ) && ModelType!=CGNS_ENUMV( ConstantDensity ) && ModelType!=CGNS_ENUMV( RedlichKwong )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "ViscosityModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Constant ) && ModelType!=CGNS_ENUMV( PowerLaw ) && ModelType!=CGNS_ENUMV( SutherlandLaw )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "ThermalConductivityModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( PowerLaw ) && ModelType!=CGNS_ENUMV( SutherlandLaw ) && ModelType!=CGNS_ENUMV( ConstantPrandtl )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "TurbulenceModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Algebraic_BaldwinLomax )&& ModelType!=CGNS_ENUMV( Algebraic_CebeciSmith )&& ModelType!=CGNS_ENUMV( HalfEquation_JohnsonKing )&& ModelType!=CGNS_ENUMV( OneEquation_BaldwinBarth )&& ModelType!=CGNS_ENUMV( OneEquation_SpalartAllmaras )&& ModelType!=CGNS_ENUMV( TwoEquation_JonesLaunder )&& ModelType!=CGNS_ENUMV( TwoEquation_MenterSST )&& ModelType!=CGNS_ENUMV( TwoEquation_Wilcox )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "TurbulenceClosure_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( EddyViscosity ) && ModelType!=CGNS_ENUMV( ReynoldsStress ) && ModelType!=CGNS_ENUMV( ReynoldsStressAlgebraic )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "ThermalRelaxationModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Frozen ) && ModelType!=CGNS_ENUMV( ThermalEquilib ) && ModelType!=CGNS_ENUMV( ThermalNonequilib )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "ChemicalKineticsModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Frozen ) && ModelType!=CGNS_ENUMV( ChemicalEquilibCurveFit ) && ModelType!=CGNS_ENUMV( ChemicalEquilibMinimization ) && ModelType!=CGNS_ENUMV( ChemicalNonequilib )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "EMElectricFieldModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Frozen ) && ModelType!=CGNS_ENUMV( Voltage ) && ModelType!=CGNS_ENUMV( Interpolated ) && ModelType!=CGNS_ENUMV( Constant )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "EMMagneticFieldModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Frozen ) && ModelType!=CGNS_ENUMV( Interpolated ) && ModelType!=CGNS_ENUMV( Constant )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } else if (strcmp(ModelLabel, "EMConductivityModel_t")==0) { if (ModelType!=CGNS_ENUMV( ModelTypeNull ) && ModelType!=CGNS_ENUMV( ModelTypeUserDefined ) && ModelType!=CGNS_ENUMV( Frozen ) && ModelType!=CGNS_ENUMV( Constant ) && ModelType!=CGNS_ENUMV( Equilibrium_LinRessler ) && ModelType!=CGNS_ENUMV( Chemistry_LinRessler )) { cgi_error("Model Type '%s' is not supported for %s", ModelTypeName[ModelType],ModelLabel); return CG_ERROR; } } if (strcmp(ModelLabel, "ChemicalKineticsModel_t") && strcmp(ModelLabel, "ThermalRelaxationModel_t") && strcmp(ModelLabel, "TurbulenceClosure_t") && strcmp(ModelLabel, "TurbulenceModel_t") && strcmp(ModelLabel, "ThermalConductivityModel_t") && strcmp(ModelLabel, "ViscosityModel_t") && strcmp(ModelLabel, "EMElectricFieldModel_t") && strcmp(ModelLabel, "EMMagneticFieldModel_t") && strcmp(ModelLabel, "EMConductivityModel_t") && strcmp(ModelLabel, "GasModel_t")) { cgi_error("Invalid Model Label: %s",ModelLabel); return CG_ERROR; } /* get address */ model = cgi_model_address(CG_MODE_WRITE, ModelLabel, &ier); if (model==0) return ier; /* Save data */ model->type = ModelType; strcpy(ModelName,ModelLabel); ModelName[strlen(ModelLabel)-2]='\0'; strcpy(model->name, ModelName); /* initialize other fields */ model->id=0; model->link=0; model->ndescr=0; model->narrays=0; model->data_class=CGNS_ENUMV( DataClassNull ); model->units=0; model->diffusion_model=0; model->dim_vals=0; model->nuser_data=0; if (strcmp(ModelLabel, "TurbulenceModel_t")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; /* For TurbulenceModel_t defined under CGNSBase_t */ } else if (posit_base) { index_dim = cg->base[posit_base-1].cell_dim; } else { cgi_error("Can't find IndexDimension in cg_model_write."); return CG_NO_INDEX_DIM; } if (index_dim==1) model->dim_vals=1; else if (index_dim==2) model->dim_vals=3; else if (index_dim==3) model->dim_vals=6; else { cgi_error("invalid value for IndexDimension"); return CG_ERROR; } } /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_model(posit_id, model)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_narrays(int *narrays) { /* Possible parents: * GridCoordinates_t, FlowSolution_t, DiscreteData_t, BC_t, * BCData_t, GasModel_t, ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, EMConductivityModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * RigidGridMotion_t, ArbitraryGridMotion_t, BaseIterativeData_t, ZoneIterativeData_t * GridConnectivity_t, UserDefinedData_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t, * Area_t, Periodic_t, ZoneSubRegion_t */ CHECK_FILE_OPEN /* verify input */ /* if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR;*/ /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*narrays) = 0; return CG_ERROR; } if (strcmp(posit->label,"GridCoordinates_t")==0) { cgns_zcoor *zcoor= (cgns_zcoor *)posit->posit; (*narrays) = zcoor->ncoords; } else if (strcmp(posit->label,"FlowSolution_t")==0) { cgns_sol *sol = (cgns_sol *)posit->posit; (*narrays) = sol->nfields; } else if (strcmp(posit->label,"DiscreteData_t")==0) { cgns_discrete *discrete = (cgns_discrete *)posit->posit; (*narrays) = discrete->narrays; } else if (strcmp(posit->label,"GridConnectivity_t")==0) { cgns_conn *conn = (cgns_conn *)posit->posit; (*narrays) = conn->narrays; } else if (strcmp(posit->label,"BC_t")==0) { /*cgns_boco *boco = (cgns_boco *)posit->posit;*/ (*narrays) = 1; /* Always supports exactly 1. */ } else if (strcmp(posit->label,"BCData_t")==0) { cgns_bcdata *bcdata = (cgns_bcdata *)posit->posit; (*narrays) = bcdata->narrays; } else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) { cgns_model *model = (cgns_model *)posit->posit; (*narrays) = model->narrays; } else if (strcmp(posit->label,"ConvergenceHistory_t")==0) { cgns_converg *converg = (cgns_converg *)posit->posit; (*narrays) = converg->narrays; } else if (strcmp(posit->label,"IntegralData_t")==0) { cgns_integral *integral = (cgns_integral *)posit->posit; (*narrays) = integral->narrays; } else if (strcmp(posit->label,"ReferenceState_t")==0) { cgns_state *state = (cgns_state *)posit->posit; (*narrays) = state->narrays; } else if (strcmp(posit->label,"RigidGridMotion_t")==0) { cgns_rmotion *rmotion = (cgns_rmotion *)posit->posit; (*narrays) = rmotion->narrays; } else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) { cgns_amotion *amotion = (cgns_amotion *)posit->posit; (*narrays) = amotion->narrays; } else if (strcmp(posit->label,"BaseIterativeData_t")==0) { cgns_biter *biter = (cgns_biter *)posit->posit; (*narrays) = biter->narrays; } else if (strcmp(posit->label,"ZoneIterativeData_t")==0) { cgns_ziter *ziter = (cgns_ziter *)posit->posit; (*narrays) = ziter->narrays; } else if (strcmp(posit->label,"UserDefinedData_t")==0) { cgns_user_data *user_data = (cgns_user_data *)posit->posit; (*narrays) = user_data->narrays; } else if (strcmp(posit->label,"Gravity_t")==0) { cgns_gravity *gravity = (cgns_gravity *)posit->posit; (*narrays) = gravity->narrays; } else if (strcmp(posit->label,"Axisymmetry_t")==0) { cgns_axisym *axisym = (cgns_axisym *)posit->posit; (*narrays) = axisym->narrays; } else if (strcmp(posit->label,"RotatingCoordinates_t")==0) { cgns_rotating *rotating = (cgns_rotating *)posit->posit; (*narrays) = rotating->narrays; } else if (strcmp(posit->label,"Area_t")==0) { cgns_bcarea *bcarea = (cgns_bcarea *)posit->posit; (*narrays) = bcarea->narrays; } else if (strcmp(posit->label,"Periodic_t")==0) { cgns_cperio *cperio = (cgns_cperio *)posit->posit; (*narrays) = cperio->narrays; } else if (strcmp(posit->label,"ZoneSubRegion_t")==0) { cgns_subreg *subreg = (cgns_subreg *)posit->posit; (*narrays) = subreg->narrays; } else { cgi_error("User defined DataArray_t node not supported under '%s' type node",posit->label); (*narrays) = 0; return CG_INCORRECT_PATH; } return CG_OK; } int cg_array_info(int A, char *ArrayName, CGNS_ENUMT(DataType_t) *DataType, int *DataDimension, cgsize_t *DimensionVector) { cgns_array *array; int n, ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; int have_dup = 0; array = cgi_array_address(CG_MODE_READ, 0, A, "dummy", &have_dup, &ier); if (array==0) return ier; strcpy(ArrayName, array->name); (*DataType) = cgi_datatype(array->data_type); (*DataDimension) = array->data_dim; for (n=0; ndata_dim; n++) DimensionVector[n] = array->dim_vals[n]; return CG_OK; } int cg_array_read(int A, void *Data) { cgns_array *array; int n, ier=0; cgsize_t num = 1; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; int have_dup = 0; array = cgi_array_address(CG_MODE_READ, 0, A, "dummy", &have_dup, &ier); if (array==0) return ier; for (n=0; ndata_dim; n++) num *= array->dim_vals[n]; if (array->data) memcpy(Data, array->data, (size_t)(num*size_of(array->data_type))); else { if (cgio_read_all_data(cg->cgio, array->id, Data)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } } return CG_OK; } int cg_array_read_as(int A, CGNS_ENUMT(DataType_t) type, void *Data) { cgns_array *array; int n, ier=0; cgsize_t num = 1; void *array_data; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; int have_dup = 0; array = cgi_array_address(CG_MODE_READ, 0, A, "dummy", &have_dup, &ier); if (array==0) return ier; for (n=0; ndata_dim; n++) num *= array->dim_vals[n]; /* Special for Character arrays */ if ((type == CGNS_ENUMV(Character) && cgi_datatype(array->data_type) != CGNS_ENUMV(Character)) || (type != CGNS_ENUMV(Character) && cgi_datatype(array->data_type) == CGNS_ENUMV(Character))) { cgi_error("Error exit: Character array can only be read as character"); return CG_ERROR; } if (type==CGNS_ENUMV(Character)) { if (array->data) memcpy(Data, array->data, (size_t)(num*size_of(array->data_type))); else { if (cgio_read_all_data(cg->cgio, array->id, Data)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } } return CG_OK; } /* All numerical data types: */ if (array->data) array_data = array->data; else { array_data = malloc((size_t)(num*size_of(array->data_type))); if (array_data == NULL) { cgi_error("Error allocating array_data"); return CG_ERROR; } if (cgio_read_all_data(cg->cgio, array->id, array_data)) { cg_io_error("cgio_read_all_data"); return CG_ERROR; } } ier = cgi_convert_data(num, cgi_datatype(array->data_type), array_data, type, Data); if (array_data != array->data) free(array_data); return ier ? CG_ERROR : CG_OK; } int cg_array_general_read(int A, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, void *data) { /* s_ prefix is file space, m_ prefix is memory space */ cgns_array *array; int s_numdim, ier = CG_OK; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* find address */ int have_dup = 0; array = cgi_array_address(CG_MODE_READ, 0, A, "dummy", &have_dup, &ier); if (array == 0) return ier; s_numdim = array->data_dim; /* special for Character arrays */ if ((m_type != CGNS_ENUMV(Character) && cgi_datatype(array->data_type) == CGNS_ENUMV(Character))) { cgi_error("Error exit: Character array can only be read as character"); return CG_ERROR; } /* do we have rind planes? */ int *rind_planes = cgi_rind_address(CG_MODE_READ, &ier); if (ier != CG_OK) rind_planes = NULL; return cgi_array_general_read(array, cgns_rindindex, rind_planes, s_numdim, s_rmin, s_rmax, m_type, m_numdim, m_dimvals, m_rmin, m_rmax, data); } int cg_array_write(const char * ArrayName, CGNS_ENUMT(DataType_t) DataType, int DataDimension, const cgsize_t * DimensionVector, const void * Data) { cgns_array *array; int n, ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_strlen(ArrayName)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (DataType != CGNS_ENUMV(RealSingle) && DataType != CGNS_ENUMV(RealDouble) && DataType != CGNS_ENUMV(Integer) && DataType != CGNS_ENUMV(LongInteger) && DataType != CGNS_ENUMV(Character)) { cgi_error("Invalid datatype for data array: %d", DataType); return CG_ERROR; } if (DataDimension>12) { cgi_error("Data arrays are limited to 12 dimensions"); return CG_ERROR; } for (n=0; nname, ArrayName); strcpy(array->data_type, cgi_adf_datatype(DataType)); array->data_dim = DataDimension; for (n=0; ndim_vals[n]=DimensionVector[n]; /* initialize other fields */ array->link=0; array->ndescr=0; array->data_class=CGNS_ENUMV(DataClassNull); array->units=0; array->exponents=0; array->convert=0; array->data=0; /* write to disk */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_new_node(posit_id, array->name, "DataArray_t", &array->id, array->data_type, array->data_dim, array->dim_vals, Data)) return CG_ERROR; return CG_OK; } int cg_array_general_write(const char *arrayname, CGNS_ENUMT(DataType_t) s_type, int s_numdim, const cgsize_t *s_dimvals, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t* m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, const void *data) { /* s_ prefix is file space, m_ prefix is memory space */ int n, ier = CG_OK; CHECK_FILE_OPEN /* verify input */ if (cgi_check_strlen(arrayname)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (s_type != CGNS_ENUMV(RealSingle) && s_type != CGNS_ENUMV(RealDouble) && s_type != CGNS_ENUMV(Integer) && s_type != CGNS_ENUMV(LongInteger) && s_type != CGNS_ENUMV(Character)) { cgi_error("Invalid file data type for data array: %d", s_type); return CG_ERROR; } if (m_type != CGNS_ENUMV(RealSingle) && m_type != CGNS_ENUMV(RealDouble) && m_type != CGNS_ENUMV(Integer) && m_type != CGNS_ENUMV(LongInteger) && m_type != CGNS_ENUMV(Character)) { cgi_error("Invalid input data type for data array: %d", m_type); return CG_ERROR; } /*** verfication for dataset in file */ /* verify the rank and dimensions of the file-space array */ if (s_numdim <= 0 || s_numdim > CGIO_MAX_DIMENSIONS) { cgi_error("Data arrays are limited to %d dimensions in file", CGIO_MAX_DIMENSIONS); return CG_ERROR; } if (s_dimvals == NULL) { cgi_error("NULL dimension value"); return CG_ERROR; } for (n=0; nfilename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*nintegrals) = 0; return CG_ERROR; } if (strcmp(posit->label,"CGNSBase_t")==0) { cgns_base *base= (cgns_base *)posit->posit; (*nintegrals) = base->nintegrals; } else if (strcmp(posit->label,"Zone_t")==0) { cgns_zone *zone = (cgns_zone *)posit->posit; (*nintegrals) = zone->nintegrals; } else { cgi_error("IntegralData_t node not supported under '%s' type node",posit->label); (*nintegrals) = 0; return CG_INCORRECT_PATH; } return CG_OK; } int cg_integral_read(int IntegralDataIndex, char *IntegralDataName) { int ier=0; cgns_integral *integral; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; integral = cgi_integral_address(CG_MODE_READ, IntegralDataIndex, "dummy", &ier); if (integral==0) return ier; strcpy(IntegralDataName, integral->name); return CG_OK; } int cg_integral_write(const char * IntegralDataName) { cgns_integral *integral; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_strlen(IntegralDataName)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; integral = cgi_integral_address(CG_MODE_WRITE, 0, IntegralDataName, &ier); if (integral==0) return ier; strcpy(integral->name, IntegralDataName); /* initialize other fields */ integral->id=0; integral->link=0; integral->ndescr=0; integral->narrays=0; integral->data_class=CGNS_ENUMV( DataClassNull ); integral->units=0; integral->nuser_data=0; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_new_node(posit_id, integral->name, "IntegralData_t", &integral->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_rind_read(int *RindData) { int n, ier=0; int *rind, index_dim; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; rind = cgi_rind_address(CG_MODE_READ, &ier); if (rind==0) return ier; if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_rind_read."); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) RindData[n] = rind[n]; return CG_OK; } int cg_rind_write(const int * RindData) { int n, ier=0; int *rind, index_dim, narrays; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; rind = cgi_rind_address(CG_MODE_WRITE, &ier); if (rind==0) return ier; if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_rind_write."); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) rind[n]=RindData[n]; /* save data in file & if different from default (6*0) */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_rind(posit_id, rind, index_dim)) return CG_ERROR; /* Writing rind planes invalidates dimensions of existing arrays. The rind planes are still written but an error is returned */ ier = cg_narrays(&narrays); if (ier == CG_OK && narrays > 0) { cgi_error("Writing rind planes invalidates dimensions of exisitng " "array(s)."); return CG_ERROR; } return CG_OK; } /*----------------------------------------------------------------------*/ int cg_ndescriptors(int *ndescriptors) { /* Possible parents of Descriptor_t node: * CGNSBase_t, Zone_t, GridCoordinates_t, Elements_t, FlowSolution_t, * DiscreteData_t, ZoneGridConnectivity_t, GridConnectivity1to1_t, * GridConnectivity_t, OversetHoles_t, ZoneBC_t, BC_t, BCDataSet_t, * BCData_t, FlowEquationSet_t, GoverningEquations_t, GasModel_t, * ViscosityModel_t, ThermalConductivityModel_t, TurbulenceClosure_t, * TurbulenceModel_t, ThermalRelaxationModel_t, ChemicalKineticsModel_t, * EMElectricFieldModel_t, EMMagneticFieldModel_t, EMConductivityModel_t, * ConvergenceHistory_t, IntegralData_t, ReferenceState_t, * DataArray_t, Family_t, GeometryReference_t, RigidGridMotion_t, * ArbitraryGridMotion_t, BaseIterativeData_t, ZoneIterativeData_t, * UserDefinedData_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t, * BCProperty_t, WallFunction_t, Area_t, ZoneSubRegion_t, * GridConnectivityProperty_t, Periodic_t, AverageInterface_t * FamilyBCDataSet_t */ CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*ndescriptors)=0; return CG_ERROR; } if (strcmp(posit->label,"CGNSBase_t")==0) NDESCRIPTOR(cgns_base) else if (strcmp(posit->label,"Zone_t")==0) NDESCRIPTOR(cgns_zone) else if (strcmp(posit->label,"GridCoordinates_t")==0) NDESCRIPTOR(cgns_zcoor) else if (strcmp(posit->label,"Elements_t")==0) NDESCRIPTOR(cgns_section) else if (strcmp(posit->label,"FlowSolution_t")==0) NDESCRIPTOR(cgns_sol) else if (strcmp(posit->label,"DiscreteData_t")==0) NDESCRIPTOR(cgns_discrete) else if (strcmp(posit->label,"ZoneGridConnectivity_t")==0) NDESCRIPTOR(cgns_zconn) else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) NDESCRIPTOR(cgns_1to1) else if (strcmp(posit->label,"GridConnectivity_t")==0) NDESCRIPTOR(cgns_conn) else if (strcmp(posit->label,"OversetHoles_t")==0) NDESCRIPTOR(cgns_hole) else if (strcmp(posit->label,"ZoneBC_t")==0) NDESCRIPTOR(cgns_zboco) else if (strcmp(posit->label,"BC_t")==0) NDESCRIPTOR(cgns_boco) else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) NDESCRIPTOR(cgns_dataset) else if (strcmp(posit->label,"BCData_t")==0) NDESCRIPTOR(cgns_bcdata) else if (strcmp(posit->label,"FlowEquationSet_t")==0) NDESCRIPTOR(cgns_equations) else if (strcmp(posit->label,"GoverningEquations_t")==0) NDESCRIPTOR(cgns_governing) else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) NDESCRIPTOR(cgns_model) else if (strcmp(posit->label,"ConvergenceHistory_t")==0) NDESCRIPTOR(cgns_converg) else if (strcmp(posit->label,"IntegralData_t")==0) NDESCRIPTOR(cgns_integral) else if (strcmp(posit->label,"ReferenceState_t")==0) NDESCRIPTOR(cgns_state) else if (strcmp(posit->label,"DataArray_t")==0) NDESCRIPTOR(cgns_array) else if (strcmp(posit->label,"Family_t")==0) NDESCRIPTOR(cgns_family) else if (strcmp(posit->label,"GeometryReference_t")==0) NDESCRIPTOR(cgns_geo) else if (strcmp(posit->label,"RigidGridMotion_t")==0) NDESCRIPTOR(cgns_rmotion) else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) NDESCRIPTOR(cgns_amotion) else if (strcmp(posit->label,"BaseIterativeData_t")==0) NDESCRIPTOR(cgns_biter) else if (strcmp(posit->label,"ZoneIterativeData_t")==0) NDESCRIPTOR(cgns_ziter) else if (strcmp(posit->label,"UserDefinedData_t")==0) NDESCRIPTOR(cgns_user_data) else if (strcmp(posit->label,"Gravity_t")==0) NDESCRIPTOR(cgns_gravity) else if (strcmp(posit->label,"Axisymmetry_t")==0) NDESCRIPTOR(cgns_axisym) else if (strcmp(posit->label,"RotatingCoordinates_t")==0) NDESCRIPTOR(cgns_rotating) else if (strcmp(posit->label,"BCProperty_t")==0) NDESCRIPTOR(cgns_bprop) else if (strcmp(posit->label,"WallFunction_t")==0) NDESCRIPTOR(cgns_bcwall) else if (strcmp(posit->label,"Area_t")==0) NDESCRIPTOR(cgns_bcarea) else if (strcmp(posit->label,"GridConnectivityProperty_t")==0) NDESCRIPTOR(cgns_cprop) else if (strcmp(posit->label,"Periodic_t")==0) NDESCRIPTOR(cgns_cperio) else if (strcmp(posit->label,"AverageInterface_t")==0) NDESCRIPTOR(cgns_caverage) else if (strcmp(posit->label,"ZoneSubRegion_t")==0) NDESCRIPTOR(cgns_subreg) else { cgi_error("Descriptor_t node not supported under '%s' type node",posit->label); (*ndescriptors)=0; return CG_INCORRECT_PATH; } return CG_OK; } int cg_descriptor_read(int descr_no, char *descr_name, char **descr_text) { cgns_descr *descr; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; /* common part */ descr = cgi_descr_address(CG_MODE_READ, descr_no, "dummy", &ier); if (descr==0) return ier; /* return Descriptor text and name */ descr_text[0]=CGNS_NEW(char, strlen(descr->text)+1); strcpy(descr_text[0], descr->text); strcpy(descr_name, descr->name); return CG_OK; } int cg_descriptor_write(const char * descr_name, const char * descr_text) { cgns_descr *descr; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_strlen(descr_name)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; descr = cgi_descr_address(CG_MODE_WRITE, 0, descr_name, &ier); if (descr==0) return ier; /* Save Descriptor_t data */ strcpy(descr->name, descr_name); if ((descr->text = (char *)malloc((strlen(descr_text)+1)*sizeof(char)))==NULL) { cgi_error("Error allocating memory for Descriptor..."); return CG_ERROR; } strcpy(descr->text, descr_text); /* initialize other fields */ descr->id=0; descr->link=0; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_descr(posit_id, descr)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_nunits(int *nunits) { cgns_units *units; int ier=0; CHECK_FILE_OPEN *nunits = 0; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; units = cgi_units_address(CG_MODE_READ, &ier); if (units==0) return ier; *nunits = units->nunits; return CG_OK; } int cg_units_read(CGNS_ENUMT(MassUnits_t) *mass, CGNS_ENUMT(LengthUnits_t) *length, CGNS_ENUMT(TimeUnits_t) *time, CGNS_ENUMT(TemperatureUnits_t) *temperature, CGNS_ENUMT(AngleUnits_t) *angle) { cgns_units *units; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; units = cgi_units_address(CG_MODE_READ, &ier); if (units==0) return ier; (*mass) = units->mass; (*length) = units->length; (*time) = units->time; (*temperature) = units->temperature; (*angle) = units->angle; return CG_OK; } int cg_units_write(CGNS_ENUMT(MassUnits_t) mass, CGNS_ENUMT(LengthUnits_t) length, CGNS_ENUMT(TimeUnits_t) time, CGNS_ENUMT(TemperatureUnits_t) temperature, CGNS_ENUMT(AngleUnits_t) angle) { int ier=0; cgns_units *units; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (INVALID_ENUM(mass,NofValidMassUnits)) { cgi_error("Invalid input: mass unit %d not supported",mass); return CG_ERROR; } if (INVALID_ENUM(length,NofValidLengthUnits)) { cgi_error("Invalid input: length unit %d not supported", length); return CG_ERROR; } if (INVALID_ENUM(time,NofValidTimeUnits)) { cgi_error("Invalid input: time unit %d not supported", time); return CG_ERROR; } if (INVALID_ENUM(temperature,NofValidTemperatureUnits)) { cgi_error("Invalid input: temperature unit %d not supported", temperature); return CG_ERROR; } if (INVALID_ENUM(angle,NofValidAngleUnits)) { cgi_error("Invalid input: angle unit %d not supported", angle); return CG_ERROR; } /* get address */ units = cgi_units_address(CG_MODE_WRITE, &ier); if (units==0) return ier; /* save data in memory */ units->mass = mass; units->length = length; units->time = time; units->temperature = temperature; units->angle = angle; /* initialize other fields */ strcpy(units->name, "DimensionalUnits"); units->id = 0; units->link=0; units->nunits = 5; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_units(posit_id, units)) return CG_ERROR; return CG_OK; } int cg_unitsfull_read(CGNS_ENUMT(MassUnits_t) *mass, CGNS_ENUMT(LengthUnits_t) *length, CGNS_ENUMT(TimeUnits_t) *time, CGNS_ENUMT(TemperatureUnits_t) *temperature, CGNS_ENUMT(AngleUnits_t) *angle, CGNS_ENUMT(ElectricCurrentUnits_t) *current, CGNS_ENUMT(SubstanceAmountUnits_t) *amount, CGNS_ENUMT(LuminousIntensityUnits_t) *intensity) { cgns_units *units; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; units = cgi_units_address(CG_MODE_READ, &ier); if (units==0) return ier; (*mass) = units->mass; (*length) = units->length; (*time) = units->time; (*temperature) = units->temperature; (*angle) = units->angle; (*current) = units->current; (*amount) = units->amount; (*intensity) = units->intensity; return CG_OK; } int cg_unitsfull_write(CGNS_ENUMT(MassUnits_t) mass, CGNS_ENUMT(LengthUnits_t) length, CGNS_ENUMT(TimeUnits_t) time, CGNS_ENUMT(TemperatureUnits_t) temperature, CGNS_ENUMT(AngleUnits_t) angle, CGNS_ENUMT(ElectricCurrentUnits_t) current, CGNS_ENUMT(SubstanceAmountUnits_t) amount, CGNS_ENUMT(LuminousIntensityUnits_t) intensity) { int ier=0; cgns_units *units; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (INVALID_ENUM(mass,NofValidMassUnits)) { cgi_error("Invalid input: mass unit %d not supported",mass); return CG_ERROR; } if (INVALID_ENUM(length,NofValidLengthUnits)) { cgi_error("Invalid input: length unit %d not supported", length); return CG_ERROR; } if (INVALID_ENUM(time,NofValidTimeUnits)) { cgi_error("Invalid input: time unit %d not supported", time); return CG_ERROR; } if (INVALID_ENUM(temperature,NofValidTemperatureUnits)) { cgi_error("Invalid input: temperature unit %d not supported", temperature); return CG_ERROR; } if (INVALID_ENUM(angle,NofValidAngleUnits)) { cgi_error("Invalid input: angle unit %d not supported", angle); return CG_ERROR; } if (INVALID_ENUM(current,NofValidElectricCurrentUnits)) { cgi_error("Invalid input: electric current unit %d not supported", current); return CG_ERROR; } if (INVALID_ENUM(amount,NofValidSubstanceAmountUnits)) { cgi_error("Invalid input: substance amount unit %d not supported", amount); return CG_ERROR; } if (INVALID_ENUM(intensity,NofValidLuminousIntensityUnits)) { cgi_error("Invalid input: luminous intensity unit %d not supported", intensity); return CG_ERROR; } /* get address */ units = cgi_units_address(CG_MODE_WRITE, &ier); if (units==0) return ier; /* save data in memory */ units->mass = mass; units->length = length; units->time = time; units->temperature = temperature; units->angle = angle; units->current = current; units->amount = amount; units->intensity = intensity; /* initialize other fields */ strcpy(units->name, "DimensionalUnits"); units->id = 0; units->link=0; units->nunits = 8; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_units(posit_id, units)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_exponents_info(CGNS_ENUMT(DataType_t) *DataType) { cgns_exponent *exponent; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_READ, &ier); if (exponent==0) return ier; (*DataType) = cgi_datatype(exponent->data_type); return CG_OK; } int cg_nexponents(int *numexp) { cgns_exponent *exponent; int ier=0; CHECK_FILE_OPEN *numexp = 0; /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_READ, &ier); if (exponent==0) return ier; *numexp = exponent->nexps; return CG_OK; } int cg_exponents_read(void *exponents) { cgns_exponent *exponent; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_READ, &ier); if (exponent==0) return ier; if (cgi_datatype(exponent->data_type)==CGNS_ENUMV( RealSingle )) { (*((float *)exponents+0)) = (*((float *) exponent->data+0)); (*((float *)exponents+1)) = (*((float *) exponent->data+1)); (*((float *)exponents+2)) = (*((float *) exponent->data+2)); (*((float *)exponents+3)) = (*((float *) exponent->data+3)); (*((float *)exponents+4)) = (*((float *) exponent->data+4)); } else if (cgi_datatype(exponent->data_type)==CGNS_ENUMV( RealDouble )) { (*((double *)exponents+0)) = (*((double *) exponent->data+0)); (*((double *)exponents+1)) = (*((double *) exponent->data+1)); (*((double *)exponents+2)) = (*((double *) exponent->data+2)); (*((double *)exponents+3)) = (*((double *) exponent->data+3)); (*((double *)exponents+4)) = (*((double *) exponent->data+4)); } return CG_OK; } int cg_exponents_write(CGNS_ENUMT(DataType_t) DataType, const void * exponents) { cgns_exponent *exponent; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_WRITE, &ier); if (exponent==0) return ier; /* Save Data */ strcpy(exponent->data_type, cgi_adf_datatype(DataType)); exponent->data = (void *)malloc(5*size_of(exponent->data_type)); if (exponent->data == NULL) { cgi_error("Error allocating exponent->data"); return CG_ERROR; } if (DataType==CGNS_ENUMV( RealSingle )) { (*((float *)exponent->data+0)) = (*((float *) exponents+0)); (*((float *)exponent->data+1)) = (*((float *) exponents+1)); (*((float *)exponent->data+2)) = (*((float *) exponents+2)); (*((float *)exponent->data+3)) = (*((float *) exponents+3)); (*((float *)exponent->data+4)) = (*((float *) exponents+4)); } else if (DataType==CGNS_ENUMV( RealDouble )) { (*((double *)exponent->data+0)) = (*((double *) exponents+0)); (*((double *)exponent->data+1)) = (*((double *) exponents+1)); (*((double *)exponent->data+2)) = (*((double *) exponents+2)); (*((double *)exponent->data+3)) = (*((double *) exponents+3)); (*((double *)exponent->data+4)) = (*((double *) exponents+4)); } /* initialize other fields */ strcpy(exponent->name, "DimensionalExponents"); exponent->id = 0; exponent->link = 0; exponent->nexps = 5; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_exponents(posit_id, exponent)) return CG_ERROR; return CG_OK; } int cg_expfull_read(void *exponents) { cgns_exponent *exponent; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_READ, &ier); if (exponent==0) return ier; /* don't fail - just return 0's for last 3 if(exponent->nexps != 8) { cgi_error("Full set of exponents not written, use cg_exponents_read."); return CG_ERROR; }*/ if (cgi_datatype(exponent->data_type)==CGNS_ENUMV( RealSingle )) { (*((float *)exponents+0)) = (*((float *) exponent->data+0)); (*((float *)exponents+1)) = (*((float *) exponent->data+1)); (*((float *)exponents+2)) = (*((float *) exponent->data+2)); (*((float *)exponents+3)) = (*((float *) exponent->data+3)); (*((float *)exponents+4)) = (*((float *) exponent->data+4)); if (exponent->nexps == 8) { (*((float *)exponents+5)) = (*((float *) exponent->data+5)); (*((float *)exponents+6)) = (*((float *) exponent->data+6)); (*((float *)exponents+7)) = (*((float *) exponent->data+7)); } else { (*((float *)exponents+5)) = (float)0.0; (*((float *)exponents+6)) = (float)0.0;; (*((float *)exponents+7)) = (float)0.0;; } } else if (cgi_datatype(exponent->data_type)==CGNS_ENUMV( RealDouble )) { (*((double *)exponents+0)) = (*((double *) exponent->data+0)); (*((double *)exponents+1)) = (*((double *) exponent->data+1)); (*((double *)exponents+2)) = (*((double *) exponent->data+2)); (*((double *)exponents+3)) = (*((double *) exponent->data+3)); (*((double *)exponents+4)) = (*((double *) exponent->data+4)); if (exponent->nexps == 8) { (*((double *)exponents+5)) = (*((double *) exponent->data+5)); (*((double *)exponents+6)) = (*((double *) exponent->data+6)); (*((double *)exponents+7)) = (*((double *) exponent->data+7)); } else { (*((double *)exponents+5)) = (double)0.0; (*((double *)exponents+6)) = (double)0.0;; (*((double *)exponents+7)) = (double)0.0;; } } return CG_OK; } int cg_expfull_write(CGNS_ENUMT(DataType_t) DataType, const void * exponents) { cgns_exponent *exponent; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; exponent = cgi_exponent_address(CG_MODE_WRITE, &ier); if (exponent==0) return ier; /* Save Data */ strcpy(exponent->data_type, cgi_adf_datatype(DataType)); exponent->data = (void *)malloc(8*size_of(exponent->data_type)); if (exponent->data == NULL) { cgi_error("Error allocating exponent->data"); return CG_ERROR; } if (DataType==CGNS_ENUMV( RealSingle )) { (*((float *)exponent->data+0)) = (*((float *) exponents+0)); (*((float *)exponent->data+1)) = (*((float *) exponents+1)); (*((float *)exponent->data+2)) = (*((float *) exponents+2)); (*((float *)exponent->data+3)) = (*((float *) exponents+3)); (*((float *)exponent->data+4)) = (*((float *) exponents+4)); (*((float *)exponent->data+5)) = (*((float *) exponents+5)); (*((float *)exponent->data+6)) = (*((float *) exponents+6)); (*((float *)exponent->data+7)) = (*((float *) exponents+7)); } else if (DataType==CGNS_ENUMV( RealDouble )) { (*((double *)exponent->data+0)) = (*((double *) exponents+0)); (*((double *)exponent->data+1)) = (*((double *) exponents+1)); (*((double *)exponent->data+2)) = (*((double *) exponents+2)); (*((double *)exponent->data+3)) = (*((double *) exponents+3)); (*((double *)exponent->data+4)) = (*((double *) exponents+4)); (*((double *)exponent->data+5)) = (*((double *) exponents+5)); (*((double *)exponent->data+6)) = (*((double *) exponents+6)); (*((double *)exponent->data+7)) = (*((double *) exponents+7)); } /* initialize other fields */ strcpy(exponent->name, "DimensionalExponents"); exponent->id = 0; exponent->link = 0; exponent->nexps = 8; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_exponents(posit_id, exponent)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_conversion_info(CGNS_ENUMT(DataType_t) *DataType) { cgns_conversion *conversion; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; conversion = cgi_conversion_address(CG_MODE_READ, &ier); if (conversion==0) return ier; (*DataType) = cgi_datatype(conversion->data_type); return CG_OK; } int cg_conversion_read(void *ConversionFactors) { cgns_conversion *conversion; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; conversion = cgi_conversion_address(CG_MODE_READ, &ier); if (conversion==0) return ier; if (cgi_datatype(conversion->data_type)==CGNS_ENUMV( RealSingle )) { *((float *)ConversionFactors+0) = *((float *) conversion->data+0); *((float *)ConversionFactors+1) = *((float *) conversion->data+1); } else if (cgi_datatype(conversion->data_type)==CGNS_ENUMV( RealDouble )) { *((double *)ConversionFactors+0) = *((double *) conversion->data+0); *((double *)ConversionFactors+1) = *((double *) conversion->data+1); } return CG_OK; } int cg_conversion_write(CGNS_ENUMT(DataType_t) DataType, const void * ConversionFactors) { cgns_conversion *conversion; int ier=0; cgsize_t dim_vals=2; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; conversion = cgi_conversion_address(CG_MODE_WRITE, &ier); if (conversion==0) return ier; /* Save data */ strcpy(conversion->data_type, cgi_adf_datatype(DataType)); conversion->data = (void *)malloc(2*size_of(conversion->data_type)); if (conversion->data == NULL) { cgi_error("Error allocating conversion->data"); return CG_ERROR; } if (DataType==CGNS_ENUMV( RealSingle )) { *((float *) conversion->data+0) = *((float *)ConversionFactors+0); *((float *) conversion->data+1) = *((float *)ConversionFactors+1); } else if (DataType==CGNS_ENUMV( RealDouble )) { *((double *) conversion->data+0) = *((double *)ConversionFactors+0); *((double *) conversion->data+1) = *((double *)ConversionFactors+1); } /* initialize other fields */ strcpy(conversion->name, "DataConversion"); conversion->id=0; conversion->link=0; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_new_node(posit_id, "DataConversion", "DataConversion_t", &conversion->id, conversion->data_type, 1, &dim_vals, conversion->data)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_dataclass_read(CGNS_ENUMT(DataClass_t) *dataclass) { CGNS_ENUMT(DataClass_t) *DataClass; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; DataClass = cgi_dataclass_address(CG_MODE_READ, &ier); if (DataClass==0) return ier; if (*DataClass==CGNS_ENUMV( DataClassNull )) return CG_NODE_NOT_FOUND; (*dataclass) = (*DataClass); return CG_OK; } int cg_dataclass_write(CGNS_ENUMT(DataClass_t) dataclass) { CGNS_ENUMT(DataClass_t) *DataClass; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; DataClass = cgi_dataclass_address(CG_MODE_WRITE, &ier); if (DataClass==0) return ier; (*DataClass) = dataclass; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_dataclass(posit_id, dataclass)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_gridlocation_read(CGNS_ENUMT(GridLocation_t) *GridLocation) { CGNS_ENUMT(GridLocation_t) *location; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; location = cgi_location_address(CG_MODE_READ, &ier); if (location==0) return ier; #ifdef CG_FIX_BC_CELL_CENTER /* convert old BC_t CellCenter values */ if (*location == CGNS_ENUMV(CellCenter) && 0 == strcmp(posit->label, "BC_t")) { int dim = cg->base[posit_base-1].cell_dim; if (dim == 1) *GridLocation = CGNS_ENUMV(Vertex); else if (dim == 2) *GridLocation = CGNS_ENUMV(EdgeCenter); else *GridLocation = CGNS_ENUMV(FaceCenter); return CG_OK; } #endif (*GridLocation) = (*location); return CG_OK; } int cg_gridlocation_write(CGNS_ENUMT(GridLocation_t) GridLocation) { CGNS_ENUMT(GridLocation_t) *location; int ier=0; cgsize_t dim_vals; double posit_id, dummy_id; int cell_dim = 0; CGNS_ENUMT(ZoneType_t) type = CGNS_ENUMV(ZoneTypeNull); CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; location = cgi_location_address(CG_MODE_WRITE, &ier); if (location==0) return ier; if (posit_base) { cell_dim = cg->base[posit_base-1].cell_dim; if (posit_zone) type = cg->base[posit_base-1].zone[posit_zone-1].type; } if ((GridLocation == CGNS_ENUMV(IFaceCenter) || GridLocation == CGNS_ENUMV(JFaceCenter) || GridLocation == CGNS_ENUMV(KFaceCenter)) && type != CGNS_ENUMV(Structured)) { cgi_error("GridLocation [IJK]FaceCenter only valid for Structured Grid"); return CG_ERROR; } ier = 0; if (strcmp(posit->label,"FlowSolution_t")==0 || strcmp(posit->label,"DiscreteData_t")== 0) { if (cgi_check_location(cell_dim, type, GridLocation)) return CG_ERROR; } else if (strcmp(posit->label,"ArbitraryGridMotion_t")== 0 || strcmp(posit->label,"GridConnectivity_t")==0) { if (GridLocation != CGNS_ENUMV(Vertex) && GridLocation != CGNS_ENUMV(CellCenter) && GridLocation != CGNS_ENUMV(FaceCenter) && GridLocation != CGNS_ENUMV(IFaceCenter) && GridLocation != CGNS_ENUMV(JFaceCenter) && GridLocation != CGNS_ENUMV(KFaceCenter)) ier = 1; } else if (strcmp(posit->label,"OversetHoles_t")==0) { if (GridLocation != CGNS_ENUMV(Vertex) && GridLocation != CGNS_ENUMV(CellCenter)) ier = 1; } else if (strcmp(posit->label,"BC_t")==0) { if (cgi_check_location(cell_dim, type, GridLocation)) return CG_ERROR; #ifdef CG_FIX_BC_CELL_CENTER if (GridLocation == CGNS_ENUMV(CellCenter)) { if (cell_dim == 1) GridLocation = CGNS_ENUMV(Vertex); else if (cell_dim == 2) GridLocation = CGNS_ENUMV(EdgeCenter); else GridLocation = CGNS_ENUMV(FaceCenter); cgi_warning("GridLocation CellCenter for BC_t is deprecated" " - changed to %s", GridLocationName[GridLocation]); } #endif } else { if (INVALID_ENUM(GridLocation,NofValidGridLocation)) ier = 1; } if (ier) { cgi_error("GridLocation %d not valid for %s", GridLocation, posit->label); return CG_ERROR; } (*location) = GridLocation; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; dim_vals = (cgsize_t)strlen(GridLocationName[GridLocation]); if (cgi_new_node(posit_id, "GridLocation", "GridLocation_t", &dummy_id, "C1", 1, &dim_vals, (void *)GridLocationName[GridLocation])) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_ordinal_read(int *Ordinal) { int *ordinal; int ier=0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; ordinal = cgi_ordinal_address(CG_MODE_READ, &ier); if (ordinal==0) return ier; (*Ordinal) = (*ordinal); return CG_OK; } int cg_ordinal_write(int Ordinal) { int *ordinal; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; ordinal = cgi_ordinal_address(CG_MODE_WRITE, &ier); if (ordinal==0) return ier; (*ordinal) = Ordinal; /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_ordinal(posit_id, Ordinal)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_is_link(int *path_length) { double posit_id; *path_length = 0; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgio_is_link(cg->cgio, posit_id, path_length)) { cg_io_error("cgio_is_link"); return CG_ERROR; } return CG_OK; } int cg_link_read(char **filename, char **link_path) { int name_len, file_len; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgio_link_size(cg->cgio, posit_id, &file_len, &name_len)) { cg_io_error("cgio_link_size"); return CG_ERROR; } *filename = CGNS_NEW(char, file_len + 1); *link_path = CGNS_NEW(char, name_len + 1); if (cgio_get_link(cg->cgio, posit_id, *filename, *link_path)) { CGNS_FREE(*filename); CGNS_FREE(*link_path); *filename = *link_path = 0; cg_io_error("cgio_get_link"); return CG_ERROR; } return CG_OK; } int cg_link_write(const char * nodename, const char * filename, const char * name_in_file) { double posit_id, link_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; if (cgi_posit_id(&posit_id)) return CG_ERROR; /* check for valid posit */ if (strcmp(posit->label,"DataArray_t") && strcmp(posit->label,"UserDefinedData_t") && strcmp(posit->label,"IntegralData_t") && strcmp(posit->label,"DiscreteData_t") && strcmp(posit->label,"ConvergenceHistory_t") && strcmp(posit->label,"ReferenceState_t") && strcmp(posit->label,"GasModel_t") && strcmp(posit->label,"ViscosityModel_t") && strcmp(posit->label,"ThermalConductivityModel_t") && strcmp(posit->label,"TurbulenceModel_t") && strcmp(posit->label,"TurbulenceClosure_t") && strcmp(posit->label,"ThermalRelaxationModel_t") && strcmp(posit->label,"ChemicalKineticsModel_t") && strcmp(posit->label,"EMElectricFieldModel_t") && strcmp(posit->label,"EMMagneticFieldModel_t") && strcmp(posit->label,"EMConductivityModel_t") && strcmp(posit->label,"GoverningEquations_t") && strcmp(posit->label,"BCData_t") && strcmp(posit->label,"BCDataSet_t") && strcmp(posit->label,"FamilyBCDataSet_t") && strcmp(posit->label,"Elements_t") && strcmp(posit->label,"BC_t") && strcmp(posit->label,"ZoneBC_t") && strcmp(posit->label,"OversetHoles_t") && strcmp(posit->label,"GridConnectivity_t") && strcmp(posit->label,"GridConnectivity1to1_t") && strcmp(posit->label,"ZoneGridConnectivity_t") && strcmp(posit->label,"FlowSolution_t") && strcmp(posit->label,"GridCoordinates_t") && strcmp(posit->label,"RigidGridMotion_t") && strcmp(posit->label,"ArbitraryGridMotion_t") && strcmp(posit->label,"ZoneIterativeData_t") && strcmp(posit->label,"BaseIterativeData_t") && strcmp(posit->label,"Zone_t") && strcmp(posit->label,"ZoneSubRegion_t") && strcmp(posit->label,"GeometryReference_t ") && strcmp(posit->label,"Family_t") && strcmp(posit->label,"CGNSBase_t") && strcmp(posit->label,"Gravity_t") && strcmp(posit->label,"Axisymmetry_t") && strcmp(posit->label,"RotatingCoordinates_t") && strcmp(posit->label,"BCProperty_t") && strcmp(posit->label,"WallFunction_t") && strcmp(posit->label,"Area_t") && strcmp(posit->label,"GridConnectivityProperty_t") && strcmp(posit->label,"Periodic_t") && strcmp(posit->label,"AverageInterface_t")) { cgi_error("Links not supported under '%s' type node",posit->label); return CG_INCORRECT_PATH; } #if DEBUG_LINKS printf("Modify link %s -> \"%s>%s\"\n", nodename, filename, name_in_file); #endif /* Create the ADF link. */ /* If a node already exists by that name, this will fail. */ /* Need to fix this to allow modifying an existing node */ /* but that's going to take a bit of work to keep the */ /* in-core information current */ if (cgio_create_link(cg->cgio, posit_id, nodename, filename, name_in_file, &link_id)) { cg_io_error("cgio_create_link"); return CG_ERROR; } (cg->added)++; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_nuser_data(int *nuser_data) { /* Possible parents of UserDefinedData_t node: * IntegralData_t, DiscreteData_t, ConvergenceHistory_t, ReferenceState_t, * xxxModel_t, GoverningEquations_t, FlowEquationSet_t, BCData_t, BCDataSet_t, * Elements_t, BC_t, ZoneBC_t, OversetHoles_t, GridConnectivity_t, * GridConnectivity1to1_t, ZoneGridConnectivity_t, FlowSolution_t, * GridCoordinates_t, RigidGridMotion_t, ArbitraryGridMotion_t, * ZoneIterativeData_t, BaseIterativeData_t, Zone_t, GeometryReference_t, * Family_t, CGNSBase_t, Gravity_t, Axisymmetry_t, RotatingCoordinates_t, * BCProperty_t, WallFunction_t, Area_t, UserDefinedData_t, * GridConnectivityProperty_t, Periodic_t, AverageInterface_t * FamilyBCDataSet_t */ /* This is valid and used during write as well as read mode. */ CHECK_FILE_OPEN /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*nuser_data) = 0; return CG_ERROR; } if (strcmp(posit->label,"IntegralData_t")==0) (*nuser_data) = ((cgns_integral *)posit->posit)->nuser_data; else if (strcmp(posit->label,"DiscreteData_t")==0) (*nuser_data) = ((cgns_discrete *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ConvergenceHistory_t")==0) (*nuser_data) = ((cgns_converg *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ReferenceState_t")==0) (*nuser_data) = ((cgns_state *)posit->posit)->nuser_data; else if ( (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) ) (*nuser_data) = ((cgns_model *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GoverningEquations_t")==0) (*nuser_data) = ((cgns_governing *)posit->posit)->nuser_data; else if (strcmp(posit->label,"FlowEquationSet_t")==0) (*nuser_data) = ((cgns_equations *)posit->posit)->nuser_data; else if (strcmp(posit->label,"BCData_t")==0) (*nuser_data) = ((cgns_bcdata *)posit->posit)->nuser_data; else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) (*nuser_data) = ((cgns_dataset *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Elements_t")==0) (*nuser_data) = ((cgns_section *)posit->posit)->nuser_data; else if (strcmp(posit->label,"BC_t")==0) (*nuser_data) = ((cgns_boco *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ZoneBC_t")==0) (*nuser_data) = ((cgns_zboco *)posit->posit)->nuser_data; else if (strcmp(posit->label,"OversetHoles_t")==0) (*nuser_data) = ((cgns_hole *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GridConnectivity_t")==0) (*nuser_data) = ((cgns_conn *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) (*nuser_data) = ((cgns_1to1 *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ZoneGridConnectivity_t")==0) (*nuser_data) = ((cgns_zconn *)posit->posit)->nuser_data; else if (strcmp(posit->label,"FlowSolution_t")==0) (*nuser_data) = ((cgns_sol *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GridCoordinates_t")==0) (*nuser_data) = ((cgns_zcoor *)posit->posit)->nuser_data; else if (strcmp(posit->label,"RigidGridMotion_t")==0) (*nuser_data) = ((cgns_rmotion *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) (*nuser_data) = ((cgns_amotion *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ZoneIterativeData_t")==0) (*nuser_data) = ((cgns_ziter *)posit->posit)->nuser_data; else if (strcmp(posit->label,"BaseIterativeData_t")==0) (*nuser_data) = ((cgns_biter *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Zone_t")==0) (*nuser_data) = ((cgns_zone *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GeometryReference_t")==0) (*nuser_data) = ((cgns_geo *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Family_t")==0) (*nuser_data) = ((cgns_family *)posit->posit)->nuser_data; else if (strcmp(posit->label,"CGNSBase_t")==0) (*nuser_data) = ((cgns_base *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Gravity_t")==0) (*nuser_data) = ((cgns_gravity *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Axisymmetry_t")==0) (*nuser_data) = ((cgns_axisym *)posit->posit)->nuser_data; else if (strcmp(posit->label,"RotatingCoordinates_t")==0) (*nuser_data) = ((cgns_rotating *)posit->posit)->nuser_data; else if (strcmp(posit->label,"BCProperty_t")==0) (*nuser_data) = ((cgns_bprop *)posit->posit)->nuser_data; else if (strcmp(posit->label,"WallFunction_t")==0) (*nuser_data) = ((cgns_bcwall *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Area_t")==0) (*nuser_data) = ((cgns_bcarea *)posit->posit)->nuser_data; else if (strcmp(posit->label,"UserDefinedData_t")==0) (*nuser_data) = ((cgns_user_data *)posit->posit)->nuser_data; else if (strcmp(posit->label,"GridConnectivityProperty_t")==0) (*nuser_data) = ((cgns_cprop *)posit->posit)->nuser_data; else if (strcmp(posit->label,"Periodic_t")==0) (*nuser_data) = ((cgns_cperio *)posit->posit)->nuser_data; else if (strcmp(posit->label,"AverageInterface_t")==0) (*nuser_data) = ((cgns_caverage *)posit->posit)->nuser_data; else if (strcmp(posit->label,"ZoneSubRegion_t")==0) (*nuser_data) = ((cgns_subreg *)posit->posit)->nuser_data; else { cgi_error("UserDefinedData_t node not supported under '%s' type node",posit->label); (*nuser_data) = 0; return CG_INCORRECT_PATH; } return CG_OK; } int cg_user_data_read(int Index, char *UserDataName) { int ier=0; cgns_user_data *user_data; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; user_data = cgi_user_data_address(CG_MODE_READ, Index, "dummy", &ier); if (user_data==0) return ier; strcpy(UserDataName, user_data->name); return CG_OK; } int cg_user_data_write(const char * UserDataName) { cgns_user_data *user_data; int ier=0; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_strlen(UserDataName)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; user_data = cgi_user_data_address(CG_MODE_WRITE, 0, UserDataName, &ier); if (user_data==0) return ier; memset(user_data, 0, sizeof(cgns_user_data)); strcpy(user_data->name, UserDataName); /* initialize other fields */ user_data->data_class=CGNS_ENUMV( DataClassNull ); user_data->location = CGNS_ENUMV( Vertex ); /* save data in file */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_new_node(posit_id, user_data->name, "UserDefinedData_t", &user_data->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_rotating_read(float *rot_rate, float *rot_center) { cgns_rotating *rotating; cgns_base *base; int ier=0, n; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; rotating = cgi_rotating_address(CG_MODE_READ, &ier); if (rotating==0) return ier; if (posit_base) { base = &cg->base[posit_base-1]; } else { cgi_error("Can't find the base"); return CG_ERROR; } for (n=0; nnarrays; n++) { if (strcmp(rotating->array[n].name,"RotationCenter")==0) memcpy(rot_center, rotating->array[n].data, base->phys_dim*sizeof(float)); else if (strcmp(rotating->array[n].name,"RotationRateVector")==0) memcpy(rot_rate, rotating->array[n].data, base->phys_dim*sizeof(float)); } return CG_OK; } int cg_rotating_write(float const *rot_rate, float const *rot_center) { cgns_rotating *rotating; cgns_base *base; int ier=0, n; double posit_id; CHECK_FILE_OPEN /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; rotating=cgi_rotating_address(CG_MODE_WRITE, &ier); if (rotating==0) return ier; if (posit_base) { base = &cg->base[posit_base-1]; } else { cgi_error("Can't find the base"); return CG_ERROR; } rotating->array = CGNS_NEW(cgns_array, 2); rotating->narrays=2; /* Create DataArray_t RotationCenter & RotationRateVector under rotating */ for (n=0; nnarrays; n++) { strcpy(rotating->array[n].data_type, "R4"); rotating->array[n].data = (void *)malloc(base->phys_dim*sizeof(float)); if (rotating->array[n].data == NULL) { cgi_error("Error allocating rotating->array[n].data"); return CG_ERROR; } rotating->array[n].data_dim=1; rotating->array[n].dim_vals[0]=base->phys_dim; } memcpy(rotating->array[0].data, rot_center, base->phys_dim*sizeof(float)); memcpy(rotating->array[1].data, rot_rate, base->phys_dim*sizeof(float)); strcpy(rotating->array[0].name, "RotationCenter"); strcpy(rotating->array[1].name, "RotationRateVector"); /* initialize other fields of rotating->array[n] */ for (n=0; nnarrays; n++) { rotating->array[n].id=0; rotating->array[n].link=0; rotating->array[n].ndescr=0; rotating->array[n].data_class=CGNS_ENUMV( DataClassNull ); rotating->array[n].units=0; rotating->array[n].exponents=0; rotating->array[n].convert=0; } /* initialize other fields of rotating */ strcpy(rotating->name, "RotatingCoordinates"); rotating->id=0; rotating->link=0; rotating->ndescr=0; rotating->data_class=CGNS_ENUMV( DataClassNull ); rotating->units=0; rotating->nuser_data=0; /* Write to disk */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_rotating(posit_id, rotating)) return CG_ERROR; return CG_OK; } /*----------------------------------------------------------------------*/ int cg_ptset_info(CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts) { cgns_ptset *ptset; int ier=0; CHECK_FILE_OPEN if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; ptset = cgi_ptset_address(CG_MODE_READ, &ier); if (ptset == 0) return ier; *ptset_type = ptset->type; *npnts = ptset->npts; return CG_OK; } int cg_ptset_read(cgsize_t *pnts) { cgns_ptset *ptset; cgsize_t size; int ier=0; CHECK_FILE_OPEN if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; ptset = cgi_ptset_address(CG_MODE_READ, &ier); if (ptset == 0) return ier; if (ptset->npts <= 0) return CG_OK; size = ptset->size_of_patch; if (posit_base && posit_zone) { size *= cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can not properly resolve IndexDimension unless under a Zone_t node."); return CG_NO_INDEX_DIM; } if (cgi_read_int_data(ptset->id, ptset->data_type, size, pnts)) return CG_ERROR; return CG_OK; } int cg_ptset_write(CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts) { cgns_ptset *ptset = 0; int i, index_dim; int ier=0; CHECK_FILE_OPEN /* verify input */ if(npnts == 0 || pnts == NULL) { cgi_error("Invalid input: npoint=%d, point set type=%s", npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } if (ptset_type == CGNS_ENUMV(PointList)) { if (npnts <= 0) { cgi_error("Invalid input: npoint=%d, point set type=%s", npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } } else if (ptset_type == CGNS_ENUMV(PointRange)) { if (npnts != 2) { cgi_error("Invalid input: npoint=%d, point set type=%s", npnts, PointSetTypeName[ptset_type]); return CG_ERROR; } } else { cgi_error("Invalid point set type: %d...?",ptset_type); return CG_ERROR; } if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can not properly resolve IndexDimension unless under a Zone_t node."); return CG_NO_INDEX_DIM; } /* verify input */ if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; ptset = cgi_ptset_address(CG_MODE_WRITE, &ier); if (ptset==0) return ier; /* set these with the provided argument data */ ptset->type = ptset_type; ptset->npts = npnts; if (ptset_type == CGNS_ENUMV(PointList)) { ptset->size_of_patch = npnts; } else { ptset->size_of_patch = 1; for (i=0; i < index_dim; i++) ptset->size_of_patch = ptset->size_of_patch * (pnts[i+index_dim] - pnts[i]+1); } /* initialize the following to default values */ ptset->id = 0; ptset->link = 0; strcpy(ptset->name, PointSetTypeName[ptset->type]); strcpy(ptset->data_type,CG_SIZE_DATATYPE); /* Save Point-Set on Disk */ if (ptset->npts > 0) { double posit_id; /* write to disk */ if (cgi_posit_id(&posit_id)) return CG_ERROR; if (cgi_write_ptset(posit_id, ptset->name, ptset, index_dim, (void *)pnts)) return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * Read and write FamilyBCDataSet_t nodes \*****************************************************************************/ int cg_bcdataset_info(int *n_dataset) { CHECK_FILE_OPEN /* check for valid posit */ if (posit == 0) { cgi_error("No current position set by cg_goto\n"); (*n_dataset) = 0; return CG_ERROR; } if(strcmp(posit->label,"FamilyBC_t") ==0) { cgns_fambc *fambc = (cgns_fambc *)posit->posit; *n_dataset = fambc->ndataset; } else { *n_dataset = 0; cgi_error("FamilyBC_t node not supported under '%s' type node", posit->label); return CG_INCORRECT_PATH; } return CG_OK; } int cg_bcdataset_read(int index, char *name, CGNS_ENUMT(BCType_t) *BCType, int *DirichletFlag, int *NeumannFlag) { cgns_dataset *dataset; int ier = 0; CHECK_FILE_OPEN if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_READ)) return CG_ERROR; dataset = cgi_bcdataset_address(CG_MODE_READ, index, NULL, &ier); if (dataset==0) return CG_ERROR; strcpy(name, dataset->name); *BCType = dataset->type; if (dataset->dirichlet) *DirichletFlag=1; else *DirichletFlag=0; if (dataset->neumann) *NeumannFlag=1; else *NeumannFlag=0; return CG_OK; } int cg_bcdataset_write(const char *name, CGNS_ENUMT(BCType_t) BCType, CGNS_ENUMT(BCDataType_t) BCDataType) { cgns_fambc *fambc; cgns_dataset *dataset = NULL; cgns_bcdata *bcdata = NULL; cgsize_t length; int index, ierr=0; double posit_id; CHECK_FILE_OPEN if (posit == 0) { cgi_error("No current position set by cg_goto\n"); return CG_ERROR; } if (strcmp(posit->label, "FamilyBC_t")) { cgi_error("FamilyBCDataSet_t node not supported under '%s' type node", posit->label); return CG_INCORRECT_PATH; } /* verify input */ if (INVALID_ENUM(BCType,NofValidBCTypes)) { cgi_error("Invalid BCType: %d",BCType); return CG_ERROR; } if (INVALID_ENUM(BCDataType,NofValidBCDataTypes)) { cgi_error("BCDataType %d not valid",BCDataType); return CG_ERROR; } if (cgi_check_strlen(name)) return CG_ERROR; if (cgi_check_mode(cg->filename, cg->mode, CG_MODE_WRITE)) return CG_ERROR; fambc = (cgns_fambc *)posit->posit; for (index = 0; index < fambc->ndataset; index++) { if (0 == strcmp(name, fambc->dataset[index].name)) { dataset = &fambc->dataset[index]; break; } } if (dataset != NULL) { /* Overwrite a BCDataSet_t node : */ if (dataset->dirichlet && BCDataType == CGNS_ENUMV(Dirichlet)) { if (cg->mode == CG_MODE_WRITE) { cgi_error("Dirichlet data already defined under FamilyBCDataSet_t '%s'", dataset->name); return CG_ERROR; } if (cgi_delete_node(dataset->id, dataset->dirichlet->id)) return CG_ERROR; cgi_free_bcdata(dataset->dirichlet); dataset->dirichlet = NULL; } else if (dataset->neumann && BCDataType == CGNS_ENUMV(Neumann)) { if (cg->mode == CG_MODE_WRITE) { cgi_error("Neumann data already defined under FamilyBCDataSet_t '%s'", dataset->name); return CG_ERROR; } if (cgi_delete_node(dataset->id, dataset->neumann->id)) return CG_ERROR; cgi_free_bcdata(dataset->neumann); dataset->neumann = NULL; } } else { /* get memory address for FamilyBCDataSet_t node */ dataset = cgi_bcdataset_address(CG_MODE_WRITE, 0, name, &ierr); if (dataset == 0) return ierr; /* save data in memory */ memset(dataset, 0, sizeof(cgns_dataset)); dataset->type = BCType; strcpy(dataset->name, name); /* write to disk */ if (cgi_posit_id(&posit_id)) return CG_ERROR; /* save data in file */ length = (cgsize_t)strlen(BCTypeName[dataset->type]); if (cg->filetype == CG_FILE_ADF2) { if (cgi_new_node(posit_id, dataset->name, "BCDataSet_t", &dataset->id, "C1", 1, &length, (void *)BCTypeName[dataset->type])) return CG_ERROR; } else { if (cgi_new_node(posit_id, dataset->name, "FamilyBCDataSet_t", &dataset->id, "C1", 1, &length, (void *)BCTypeName[dataset->type])) return CG_ERROR; } } if (BCDataType == CGNS_ENUMV(Dirichlet)) { if ( !dataset->dirichlet) dataset->dirichlet = CGNS_NEW(cgns_bcdata,1); strcpy(dataset->dirichlet->name, "DirichletData"); bcdata = dataset->dirichlet; } else if(BCDataType == CGNS_ENUMV(Neumann)){ if ( !dataset->neumann) dataset->neumann = CGNS_NEW(cgns_bcdata,1); strcpy(dataset->neumann->name, "NeumannData"); bcdata = dataset->neumann; } else { cgi_error("BCDataType is not Dirichlet or Neumann"); return CG_ERROR; } if (cgi_new_node(dataset->id, bcdata->name, "BCData_t", &bcdata->id, "MT", 0, 0, 0)) return CG_ERROR; return CG_OK; } /****************************************************************************/ /* the index in this list IS the cgnslib.h/ElementType_t index */ int cg_npe(CGNS_ENUMT( ElementType_t ) type, int *npe) { static int el_size[NofValidElementTypes] = { 0, /* ElementTypeNull */ 0, /* ElementTypeUserDefined */ #ifdef CGNS_SCOPE_ENUMS CG_NPE_NODE, /* NODE */ CG_NPE_BAR_2, /* BAR_2 */ CG_NPE_BAR_3, /* BAR_3 */ CG_NPE_TRI_3, /* TRI_3 */ CG_NPE_TRI_6, /* TRI_6 */ CG_NPE_QUAD_4, /* QUAD_4 */ CG_NPE_QUAD_8, /* QUAD_8 */ CG_NPE_QUAD_9, /* QUAD_9 */ CG_NPE_TETRA_4, /* TETRA_4 */ CG_NPE_TETRA_10, /* TETRA_10 */ CG_NPE_PYRA_5, /* PYRA_5 */ CG_NPE_PYRA_14, /* PYRA_14 */ CG_NPE_PENTA_6, /* PENTA_6 */ CG_NPE_PENTA_15, /* PENTA_15 */ CG_NPE_PENTA_18, /* PENTA_18 */ CG_NPE_HEXA_8, /* HEXA_8 */ CG_NPE_HEXA_20, /* HEXA_20 */ CG_NPE_HEXA_27, /* HEXA_27 */ CG_NPE_MIXED, /* MIXED */ CG_NPE_PYRA_13, /* PYRA_13 */ CG_NPE_NGON_n, /* NGON_n */ CG_NPE_NFACE_n, /* NFACE_n */ CG_NPE_BAR_4, CG_NPE_TRI_9, CG_NPE_TRI_10, CG_NPE_QUAD_12, CG_NPE_QUAD_16, CG_NPE_TETRA_16, CG_NPE_TETRA_20, CG_NPE_PYRA_21, CG_NPE_PYRA_29, CG_NPE_PYRA_30, CG_NPE_PENTA_24, CG_NPE_PENTA_38, CG_NPE_PENTA_40, CG_NPE_HEXA_32, CG_NPE_HEXA_56, CG_NPE_HEXA_64, CG_NPE_BAR_5, CG_NPE_TRI_12, CG_NPE_TRI_15, CG_NPE_QUAD_P4_16, CG_NPE_QUAD_25, CG_NPE_TETRA_22, CG_NPE_TETRA_34, CG_NPE_TETRA_35, CG_NPE_PYRA_P4_29, CG_NPE_PYRA_50, CG_NPE_PYRA_55, CG_NPE_PENTA_33, CG_NPE_PENTA_66, CG_NPE_PENTA_75, CG_NPE_HEXA_44, CG_NPE_HEXA_98, CG_NPE_HEXA_125 #else NPE_NODE, /* NODE */ NPE_BAR_2, /* BAR_2 */ NPE_BAR_3, /* BAR_3 */ NPE_TRI_3, /* TRI_3 */ NPE_TRI_6, /* TRI_6 */ NPE_QUAD_4, /* QUAD_4 */ NPE_QUAD_8, /* QUAD_8 */ NPE_QUAD_9, /* QUAD_9 */ NPE_TETRA_4, /* TETRA_4 */ NPE_TETRA_10, /* TETRA_10 */ NPE_PYRA_5, /* PYRA_5 */ NPE_PYRA_14, /* PYRA_14 */ NPE_PENTA_6, /* PENTA_6 */ NPE_PENTA_15, /* PENTA_15 */ NPE_PENTA_18, /* PENTA_18 */ NPE_HEXA_8, /* HEXA_8 */ NPE_HEXA_20, /* HEXA_20 */ NPE_HEXA_27, /* HEXA_27 */ NPE_MIXED, /* MIXED */ NPE_PYRA_13, /* PYRA_13 */ NPE_NGON_n, /* NGON_n */ NPE_NFACE_n, /* NFACE_n */ NPE_BAR_4, NPE_TRI_9, NPE_TRI_10, NPE_QUAD_12, NPE_QUAD_16, NPE_TETRA_16, NPE_TETRA_20, NPE_PYRA_21, NPE_PYRA_29, NPE_PYRA_30, NPE_PENTA_24, NPE_PENTA_38, NPE_PENTA_40, NPE_HEXA_32, NPE_HEXA_56, NPE_HEXA_64, NPE_BAR_5, NPE_TRI_12, NPE_TRI_15, NPE_QUAD_P4_16, NPE_QUAD_25, NPE_TETRA_22, NPE_TETRA_34, NPE_TETRA_35, NPE_PYRA_P4_29, NPE_PYRA_50, NPE_PYRA_55, NPE_PENTA_33, NPE_PENTA_66, NPE_PENTA_75, NPE_HEXA_44, NPE_HEXA_98, NPE_HEXA_125 #endif }; if (INVALID_ENUM(type,NofValidElementTypes)) { *npe = -1; cgi_error("Invalid element type"); return CG_ERROR; } (*npe) = el_size[type]; return CG_OK; } /*****************************************************************************\ * General Delete Function \*****************************************************************************/ int cg_delete_node(const char *node_name) { int n, m, index_dim; double posit_id, node_id; char_33 node_label; CHECK_FILE_OPEN /* verify input */ if (cg->mode != CG_MODE_MODIFY) { cgi_error("File %s must be opened in mode modify to delete a node", cg->filename); return CG_ERROR; } /* ADF ID of parent = posit_id */ if (cgi_posit_id(&posit_id)) return CG_ERROR; /* ADF ID of node */ if (cgio_get_node_id(cg->cgio, posit_id, node_name, &node_id)) { cg_io_error("cgio_get_node_id"); return CG_ERROR; } /* Get label of node to be deleted */ if (cgio_get_label(cg->cgio, node_id, node_label)) { cg_io_error("cgio_get_label"); return CG_ERROR; } /* Nodes that can't be deleted */ if ( (strcmp(posit->label,"Zone_t")==0 && strcmp(node_label,"ZoneType_t")==0 ) || (strcmp(posit->label,"ZoneSubRegion_t")==0 && (strcmp(node_name,"BCRegionName")==0 || strcmp(node_name,"GridConnectivityRegionName")==0 || strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0) ) || (strcmp(posit->label,"GridConnectivity1to1_t")==0 && (strcmp(node_name,"PointRange")==0 || strcmp(node_name,"PointRangeDonor")==0) ) || (strcmp(posit->label,"OversetHoles_t")==0 && (strcmp(node_label,"IndexRange_t")==0 || strcmp(node_name,"PointList")==0) ) || (strcmp(posit->label,"GridConnectivity_t")==0 && (strcmp(node_name,"PointRange")==0 || strcmp(node_name,"PointList")==0 || strcmp(node_name,"CellListDonor")==0 || strcmp(node_name,"PointListDonor")==0 || strcmp(node_name,"InterpolantsDonor")==0) ) || (strcmp(posit->label,"BC_t")==0 && (strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0 || strcmp(node_name,"ElementList")==0 || strcmp(node_name,"ElementRange")==0) ) || (strcmp(posit->label,"GeometryReference_t")==0 && (strcmp(node_name,"GeometryFile")==0 || strcmp(node_name,"GeometryFormat")==0) ) || (strcmp(posit->label,"Elements_t")==0 && (strcmp(node_name,"ElementRange")==0 || strcmp(node_name,"ElementConnectivity")==0) ) || (strcmp(posit->label,"Gravity_t")==0 && strcmp(node_name,"GravityVector")==0) || (strcmp(posit->label,"Axisymmetry_t")==0 && (strcmp(node_name,"AxisymmetryReferencePoint")==0 || strcmp(node_name,"AxisymmetryAxisVector")==0) ) || (strcmp(posit->label,"RotatingCoordinates_t")==0 && (strcmp(node_name,"RotationCenter")==0 || strcmp(node_name,"RotationRateVector")==0) ) || (strcmp(posit->label,"WallFunction_t")==0 && strcmp(node_label,"WallFunctionType_t")==0) || (strcmp(posit->label,"Area_t")==0 && (strcmp(node_label,"AreaType_t")==0 || strcmp(node_label,"DataArray_t")==0) ) || (strcmp(posit->label,"Periodic_t")==0 && strcmp(node_label,"DataArray_t")==0) || (strcmp(posit->label,"AverageInterface_t")==0 && strcmp(node_label,"AverageInterfaceType_t")==0) ) { cgi_error("Node '%s' under '%s' can not be deleted",node_name,posit->label); return CG_ERROR; } /* Delete node_id under posit_id */ if (cgi_delete_node(posit_id, node_id)) { /*printf("posit->label=%s, node_name=%s\n",posit->label,node_name);*/ return CG_ERROR; } /* Remove from internal database */ /* Children of CGNSBase_t */ if (strcmp(posit->label,"CGNSBase_t")==0) { cgns_base *parent = (cgns_base *)posit->posit; /* Case 1: node_label = can have multiple occurence: */ if (strcmp(node_label,"Zone_t")==0) CGNS_DELETE_SHIFT(nzones, zone, cgi_free_zone) else if (strcmp(node_label,"Family_t")==0) CGNS_DELETE_SHIFT(nfamilies, family, cgi_free_family) else if (strcmp(node_label,"IntegralData_t")==0) CGNS_DELETE_SHIFT(nintegrals, integral, cgi_free_integral) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) /* Case 2: node_label = can only occur once under parent: */ else if (strcmp(node_name,"SimulationType")==0) { parent->type = CGNS_ENUMV( SimulationTypeNull ); parent->type_id = 0; } else if (strcmp(node_label,"BaseIterativeData_t")==0) CGNS_DELETE_CHILD(biter, cgi_free_biter) else if (strcmp(node_name,"GlobalConvergenceHistory")==0) CGNS_DELETE_CHILD(converg, cgi_free_converg) else if (strcmp(node_name,"FlowEquationSet")==0) CGNS_DELETE_CHILD(equations, cgi_free_equations) else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"ReferenceState")==0) CGNS_DELETE_CHILD(state, cgi_free_state) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"Gravity")==0) CGNS_DELETE_CHILD(gravity, cgi_free_gravity) else if (strcmp(node_name,"Axisymmetry")==0) CGNS_DELETE_CHILD(axisym, cgi_free_axisym) else if (strcmp(node_name,"RotatingCoordinates")==0) CGNS_DELETE_CHILD(rotating, cgi_free_rotating) /* Children of Zone_t */ } else if (strcmp(posit->label,"Zone_t")==0) { cgns_zone *parent = (cgns_zone *)posit->posit; if (strcmp(node_label,"GridCoordinates_t")==0) CGNS_DELETE_SHIFT(nzcoor, zcoor, cgi_free_zcoor) else if (strcmp(node_label,"DiscreteData_t")==0) CGNS_DELETE_SHIFT(ndiscrete, discrete, cgi_free_discrete) else if (strcmp(node_label,"Elements_t")==0) CGNS_DELETE_SHIFT(nsections, section, cgi_free_section) else if (strcmp(node_label,"FlowSolution_t")==0) CGNS_DELETE_SHIFT(nsols, sol, cgi_free_sol) else if (strcmp(node_label,"RigidGridMotion_t")==0) CGNS_DELETE_SHIFT(nrmotions, rmotion, cgi_free_rmotion) else if (strcmp(node_label,"ArbitraryGridMotion_t")==0) CGNS_DELETE_SHIFT(namotions, amotion, cgi_free_amotion) else if (strcmp(node_label,"IntegralData_t")==0) CGNS_DELETE_SHIFT(nintegrals, integral, cgi_free_integral) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"AdditionalFamilyName_t")==0) CGNS_DELETE_SHIFT(nfamname, famname, cgi_free_famname) else if (strcmp(node_label,"ZoneGridConnectivity_t")==0) CGNS_DELETE_SHIFT(nzconn, zconn, cgi_free_zconn) else if (strcmp(node_label,"ZoneSubRegion_t")==0) CGNS_DELETE_SHIFT(nsubreg, subreg, cgi_free_subreg) else if (strcmp(node_name,"ZoneBC")==0) CGNS_DELETE_CHILD(zboco, cgi_free_zboco) else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; else if (strcmp(node_label,"ZoneIterativeData_t")==0) CGNS_DELETE_CHILD(ziter, cgi_free_ziter) else if (strcmp(node_name,"ReferenceState")==0) CGNS_DELETE_CHILD(state, cgi_free_state) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"FamilyName")==0) parent->family_name[0]='\0'; else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"FlowEquationSet")==0) CGNS_DELETE_CHILD(equations, cgi_free_equations) else if (strcmp(node_name,"ZoneConvergenceHistory")==0) CGNS_DELETE_CHILD(converg, cgi_free_converg) else if (strcmp(node_name,"RotatingCoordinates")==0) CGNS_DELETE_CHILD(rotating, cgi_free_rotating) /* ZoneType can not be deleted */ /* Children of ZoneSubRegion_t */ } else if (strcmp(posit->label,"ZoneSubRegion_t")==0) { cgns_subreg *parent = (cgns_subreg *)posit->posit; if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_label,"AdditionalFamilyName_t")==0) CGNS_DELETE_SHIFT(nfamname, famname, cgi_free_famname) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"FamilyName")==0) parent->family_name[0]='\0'; else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } /* Children of GridCoordinates_t */ } else if (strcmp(posit->label,"GridCoordinates_t")==0) { cgns_zcoor *parent = (cgns_zcoor *)posit->posit; if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(ncoords, coord, cgi_free_array) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of DataArray_t */ } else if (strcmp(posit->label,"DataArray_t")==0) { cgns_array *parent = (cgns_array *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalExponents")==0) CGNS_DELETE_CHILD(exponents, cgi_free_exponents) else if (strcmp(node_name,"DataConversion")==0) CGNS_DELETE_CHILD(convert, cgi_free_convert) else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of FlowSolution_t */ } else if (strcmp(posit->label,"FlowSolution_t")==0) { cgns_sol *parent = (cgns_sol *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(nfields, field, cgi_free_array) else if (strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0) CGNS_DELETE_CHILD(ptset, cgi_free_ptset) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } /* Children of ZoneGridConnectivity_t */ } else if (strcmp(posit->label,"ZoneGridConnectivity_t")==0) { cgns_zconn *parent = (cgns_zconn *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"GridConnectivity1to1_t")==0) CGNS_DELETE_SHIFT(n1to1, one21, cgi_free_1to1) else if (strcmp(node_label,"GridConnectivity_t")==0) CGNS_DELETE_SHIFT(nconns, conn, cgi_free_conn) else if (strcmp(node_label,"OversetHoles_t")==0) CGNS_DELETE_SHIFT(nholes, hole, cgi_free_hole) /* Children of OversetHoles_t */ } else if (strcmp(posit->label,"OversetHoles_t")==0) { cgns_hole *parent = (cgns_hole *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); /* IndexRange_t & IndexArray_t can't be deleted */ /* Children of GridConnectivity_t */ } else if (strcmp(posit->label,"GridConnectivity_t")==0) { cgns_conn *parent = (cgns_conn *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"InterpolantsDonor")==0) { if (parent->dptset.type==CGNS_ENUMV( CellListDonor )) { cgi_error("Node '%s' under '%s' can not be deleted", node_name,posit->label); return CG_ERROR; } else { CGNS_DELETE_SHIFT(narrays, interpolants, cgi_free_array) } } else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; else if (strcmp(node_name,"GridConnectivityType")==0) parent->type=CGNS_ENUMV( GridConnectivityTypeNull ); else if (strcmp(node_name,"GridConnectivityProperty")==0) CGNS_DELETE_CHILD(cprop, cgi_free_cprop) /* IndexArray_t & IndexRange_t can't be deleted */ /* Children of GridConnectivity1to1_t */ } else if (strcmp(posit->label,"GridConnectivity1to1_t")==0) { cgns_1to1 *parent = (cgns_1to1 *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; else if (strcmp(node_name,"GridConnectivityProperty")==0) CGNS_DELETE_CHILD(cprop, cgi_free_cprop) /* PointRange, PointRangeDonor, Transform can't be deleted */ /* Children of ZoneBC_t */ } else if (strcmp(posit->label,"ZoneBC_t")==0) { cgns_zboco *parent = (cgns_zboco *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"BC_t")==0) CGNS_DELETE_SHIFT(nbocos, boco, cgi_free_boco) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"ReferenceState")==0) CGNS_DELETE_CHILD(state, cgi_free_state) /* Children of BC_t */ } else if (strcmp(posit->label,"BC_t")==0) { cgns_boco *parent = (cgns_boco *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"AdditionalFamilyName_t")==0) CGNS_DELETE_SHIFT(nfamname, famname, cgi_free_famname) else if (strcmp(node_label,"BCDataSet_t")==0) { #if 0 CGNS_DELETE_SHIFT(ndataset, dataset, cgi_free_dataset) #else for (n = 0; n < parent->ndataset && strcmp(parent->dataset[n].name, node_name); n++); if (n == parent->ndataset) { cgi_error("Error in cg_delete: Can't find node '%s'",node_name); return CG_ERROR; } if (parent->dataset[n].ptset == parent->ptset) parent->dataset[n].ptset = 0; cgi_free_dataset(&parent->dataset[n]); for (m = n+1; m < parent->ndataset; m++) parent->dataset[m-1] = parent->dataset[m]; if (--parent->ndataset == 0) { free(parent->dataset); parent->dataset = 0; } #endif } else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"InwardNormalIndex")==0) { if (parent->Nindex) free(parent->Nindex); parent->Nindex=0; } else if (strcmp(node_name,"InwardNormalList")==0) CGNS_DELETE_CHILD(normal, cgi_free_array) else if (strcmp(node_name,"ReferenceState")==0) CGNS_DELETE_CHILD(state, cgi_free_state) else if (strcmp(node_name,"FamilyName")==0) parent->family_name[0]='\0'; else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; else if (strcmp(node_name,"BCProperty")==0) CGNS_DELETE_CHILD(bprop, cgi_free_bprop) /* IndexRange_t PointRange & IndexArray_t PointList can't be deleted */ /* Children of BCDataSet_t or FamilyBCDataSet_t */ } else if (strcmp(posit->label,"BCDataSet_t")==0 || strcmp(posit->label,"FamilyBCDataSet_t")==0) { cgns_dataset *parent = (cgns_dataset *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0) CGNS_DELETE_CHILD(ptset, cgi_free_ptset) else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"DirichletData")==0) CGNS_DELETE_CHILD(dirichlet, cgi_free_bcdata) else if (strcmp(node_name,"NeumannData")==0) CGNS_DELETE_CHILD(neumann, cgi_free_bcdata) else if (strcmp(node_name,"ReferenceState")==0) CGNS_DELETE_CHILD(state, cgi_free_state) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); /* IndexRange_t PointRange & IndexArray_t PointList can't be deleted */ /* Children of BCData_t */ } else if (strcmp(posit->label,"BCData_t")==0) { cgns_bcdata *parent = (cgns_bcdata *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of DiscreteData_t */ } else if (strcmp(posit->label,"DiscreteData_t")==0) { cgns_discrete *parent = (cgns_discrete *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0) CGNS_DELETE_CHILD(ptset, cgi_free_ptset) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } /* Children of FlowEquationSet_t */ } else if (strcmp(posit->label,"FlowEquationSet_t")==0) { cgns_equations *parent = (cgns_equations *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GoverningEquations")==0) CGNS_DELETE_CHILD(governing, cgi_free_governing) else if (strcmp(node_name,"GasModel")==0) CGNS_DELETE_CHILD(gas, cgi_free_model) else if (strcmp(node_name,"ViscosityModel")==0) CGNS_DELETE_CHILD(visc, cgi_free_model) else if (strcmp(node_name,"ThermalRelaxationModel")==0) CGNS_DELETE_CHILD(relaxation, cgi_free_model) else if (strcmp(node_name,"ThermalConductivityModel")==0) CGNS_DELETE_CHILD(conduct, cgi_free_model) else if (strcmp(node_name,"ChemicalKineticsModel")==0) CGNS_DELETE_CHILD(chemkin, cgi_free_model) else if (strcmp(node_name,"EMElectricFieldModel")==0) CGNS_DELETE_CHILD(elecfield, cgi_free_model) else if (strcmp(node_name,"EMMagneticFieldModel")==0) CGNS_DELETE_CHILD(magnfield, cgi_free_model) else if (strcmp(node_name,"EMConductivityModel")==0) CGNS_DELETE_CHILD(emconduct, cgi_free_model) else if (strcmp(node_name,"TurbulenceModel")==0) { if (parent->turbulence) { if (parent->turbulence->diffusion_model) free(parent->turbulence->diffusion_model); cgi_free_model(parent->turbulence); free(parent->turbulence); } parent->turbulence=0; } else if (strcmp(node_name,"TurbulenceClosure")==0) CGNS_DELETE_CHILD(closure, cgi_free_model) else if (strcmp(node_name,"EquationDimension")==0) parent->equation_dim=0; /* Children of GoverningEquations_t */ } else if (strcmp(posit->label,"GoverningEquations_t")==0) { cgns_governing *parent = (cgns_governing *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"DiffusionModel")==0) { if (parent->diffusion_model) free(parent->diffusion_model); parent->diffusion_model=0; } /* Children of xxxModel_t */ } else if (strcmp(posit->label,"GasModel_t")==0 || strcmp(posit->label,"ViscosityModel_t")==0 || strcmp(posit->label,"ThermalConductivityModel_t")==0 || strcmp(posit->label,"TurbulenceModel_t")==0 || strcmp(posit->label,"TurbulenceClosure_t")==0 || strcmp(posit->label,"ThermalRelaxationModel_t")==0 || strcmp(posit->label,"ChemicalKineticsModel_t")==0 || strcmp(posit->label,"EMElectricFieldModel_t")==0 || strcmp(posit->label,"EMMagneticFieldModel_t")==0 || strcmp(posit->label,"EMConductivityModel_t")==0) { cgns_model *parent = (cgns_model *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(posit->label,"TurbulenceModel_t")==0 && strcmp(node_name,"DiffusionModel")==0) { if (parent->diffusion_model) free(parent->diffusion_model); parent->diffusion_model=0; } /* Children of ConvergenceHistory_t */ } else if (strcmp(posit->label,"ConvergenceHistory_t")==0) { cgns_converg *parent = (cgns_converg *)posit->posit; if (strcmp(node_name,"NormDefinitions")==0) CGNS_DELETE_CHILD(NormDefinitions, cgi_free_descr) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of IntegralData_t */ } else if (strcmp(posit->label,"IntegralData_t")==0) { cgns_integral *parent = (cgns_integral *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of ReferenceState_t */ } else if (strcmp(posit->label,"ReferenceState_t")==0) { cgns_state *parent = (cgns_state *)posit->posit; if (strcmp(node_name,"ReferenceStateDescription")==0) CGNS_DELETE_CHILD(StateDescription, cgi_free_descr) else if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of Family_t */ } else if (strcmp(posit->label,"Family_t")==0) { cgns_family *parent = (cgns_family *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"GeometryReference_t")==0) CGNS_DELETE_SHIFT(ngeos, geo, cgi_free_geo) else if (strcmp(node_label,"FamilyBC_t")==0) CGNS_DELETE_SHIFT(nfambc, fambc, cgi_free_fambc) else if (strcmp(node_label,"FamilyName_t")==0) CGNS_DELETE_SHIFT(nfamname, famname, cgi_free_famname) else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; else if (strcmp(node_name,"RotatingCoordinates")==0) CGNS_DELETE_CHILD(rotating, cgi_free_rotating) /* Children of FamilyBC_t */ } else if (strcmp(posit->label,"FamilyBC_t")==0) { cgns_fambc *parent = (cgns_fambc *)posit->posit; if (strcmp(node_label,"FamilyBCDataSet_t")==0 || strcmp(node_label,"BCDataSet_t")==0) CGNS_DELETE_SHIFT(ndataset, dataset, cgi_free_dataset) /* Children of GeometryReference_t */ } else if (strcmp(posit->label,"GeometryReference_t")==0) { cgns_geo *parent = (cgns_geo *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"GeometryEntity_t")==0) CGNS_DELETE_SHIFT(npart, part, cgi_free_part) /* GeometryFile and GeometryFormat can not be deleted */ /* Children of Elements_t */ } else if (strcmp(posit->label,"Elements_t")==0) { cgns_section *parent = (cgns_section *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"ParentElements")==0) CGNS_DELETE_CHILD(parelem, cgi_free_array) else if (strcmp(node_name,"ParentElementsPosition")==0) CGNS_DELETE_CHILD(parface, cgi_free_array) else if (strcmp(node_name,"ParentData")==0) { CGNS_DELETE_CHILD(parelem, cgi_free_array) CGNS_DELETE_CHILD(parface, cgi_free_array) } else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } /* ElementRange and ElementConnectivity can not be deleted */ /* Children of RigidGridMotion_t */ } else if (strcmp(posit->label,"RigidGridMotion_t")==0) { cgns_rmotion *parent = (cgns_rmotion *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of ArbitraryGridMotion_t */ } else if (strcmp(posit->label,"ArbitraryGridMotion_t")==0) { cgns_amotion *parent = (cgns_amotion *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"Rind")==0) { if (posit_base && posit_zone) { index_dim = cg->base[posit_base-1].zone[posit_zone-1].index_dim; } else { cgi_error("Can't find IndexDimension in cg_delete"); return CG_NO_INDEX_DIM; } for (n=0; n<2*index_dim; n++) parent->rind_planes[n] = 0; } /* Children of BaseIterativeData_t */ } else if (strcmp(posit->label,"BaseIterativeData_t")==0) { cgns_biter *parent = (cgns_biter *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of ZoneIterativeData_t */ } else if (strcmp(posit->label,"ZoneIterativeData_t")==0) { cgns_ziter *parent = (cgns_ziter *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of UserDefinedData_t */ } else if (strcmp(posit->label,"UserDefinedData_t")==0) { cgns_user_data *parent = (cgns_user_data *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_label,"AdditionalFamilyName_t")==0) CGNS_DELETE_SHIFT(nfamname, famname, cgi_free_famname) else if (strcmp(node_name,"PointList")==0 || strcmp(node_name,"PointRange")==0) CGNS_DELETE_CHILD(ptset, cgi_free_ptset) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"GridLocation")==0) parent->location=CGNS_ENUMV( GridLocationNull ); else if (strcmp(node_name,"FamilyName")==0) parent->family_name[0]='\0'; else if (strcmp(node_name,"Ordinal")==0) parent->ordinal=0; /* IndexRange_t PointRange & IndexArray_t PointList can't be deleted */ /* Children of Gravity_t */ } else if (strcmp(posit->label,"Gravity_t")==0) { cgns_gravity *parent = (cgns_gravity *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* Children of Axisymmetry_t */ } else if (strcmp(posit->label,"Axisymmetry_t")==0) { cgns_axisym *parent = (cgns_axisym *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* RotatingCoordinates_t */ } else if (strcmp(posit->label,"RotatingCoordinates_t")==0) { cgns_rotating *parent = (cgns_rotating *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_label,"DataArray_t")==0) CGNS_DELETE_SHIFT(narrays, array, cgi_free_array) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* BCProperty_t */ } else if (strcmp(posit->label,"BCProperty_t")==0) { cgns_bprop *parent = (cgns_bprop *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"WallFunction")==0) CGNS_DELETE_CHILD(bcwall, cgi_free_bcwall) else if (strcmp(node_name,"Area")==0) CGNS_DELETE_CHILD(bcarea, cgi_free_bcarea) /* WallFunction_t */ } else if (strcmp(posit->label,"WallFunction_t")==0) { cgns_bcwall *parent = (cgns_bcwall *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) /* node WallFunctionType can't be deleted */ /* Area_t */ } else if (strcmp(posit->label,"Area_t")==0) { cgns_bcarea *parent = (cgns_bcarea *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) /* nodes AreaType, SurfaceArea and RegionName can't be deleted */ /* GridConnectivityProperty_t */ } else if (strcmp(posit->label,"GridConnectivityProperty_t")==0) { cgns_cprop *parent = (cgns_cprop *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"Periodic")==0) CGNS_DELETE_CHILD(cperio, cgi_free_cperio) else if (strcmp(node_name,"AverageInterface")==0) CGNS_DELETE_CHILD(caverage, cgi_free_caverage) /* Periodic_t */ } else if (strcmp(posit->label,"Periodic_t")==0) { cgns_cperio *parent = (cgns_cperio *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) else if (strcmp(node_name,"DataClass")==0) parent->data_class = CGNS_ENUMV( DataClassNull ); else if (strcmp(node_name,"DimensionalUnits")==0) CGNS_DELETE_CHILD(units, cgi_free_units) /* RotationCenter, RotationAngle and Translation can't be deleted */ /* AverageInterface_t */ } else if (strcmp(posit->label,"AverageInterface_t")==0) { cgns_caverage *parent = (cgns_caverage *)posit->posit; if (strcmp(node_label,"Descriptor_t")==0) CGNS_DELETE_SHIFT(ndescr, descr, cgi_free_descr) else if (strcmp(node_label,"UserDefinedData_t")==0) CGNS_DELETE_SHIFT(nuser_data, user_data, cgi_free_user_data) /* AverageInterfaceType can't be deleted */ } else { cgi_error("Unrecognized label: '%s'",posit->label); return CG_ERROR; } return CG_OK; } /*****************************************************************************\ * Free library malloced memory \*****************************************************************************/ int cg_free(void *data) { if (data != NULL) { CGNS_FREE (data); return CG_OK; } return CG_ERROR; } CGNS-3.4.0/src/cgnslib.h000066400000000000000000002033221343724673500146510ustar00rootroot00000000000000/* ------------------------------------------------------------------------- * * CGNS - CFD General Notation System (http://www.cgns.org) * * CGNS/MLL - Mid-Level Library header file * * Please see cgnsconfig.h file for this local installation configuration * * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. * ------------------------------------------------------------------------- * * DEVELOPER'S NOTE: * When adding a defined constant to this file, also add the same defined * constant to cgns_f.F90 * * ------------------------------------------------------------------------- */ #ifndef CGNSLIB_H #define CGNSLIB_H #define CGNS_VERSION 3400 #define CGNS_DOTVERS 3.40 #define CGNS_COMPATVERSION 2540 #define CGNS_COMPATDOTVERS 2.54 #include "cgnstypes.h" #if CG_BUILD_SCOPE # ifndef CGNS_SCOPE_ENUMS # define CGNS_SCOPE_ENUMS # endif #else # ifdef CGNS_SCOPE_ENUMS # undef CGNS_SCOPE_ENUMS # endif #endif #ifndef CGNSDLL # ifdef _WIN32 # if defined(BUILD_DLL) # define CGNSDLL __declspec(dllexport) # elif defined(USE_DLL) # define CGNSDLL __declspec(dllimport) # else # define CGNSDLL # endif # else # define CGNSDLL # endif #endif #ifdef CGNS_SCOPE_ENUMS /* set scope prefix for values only */ #define CGNS_ENUMV( e ) CG_ ## e /* set scope prefix for types */ #define CGNS_ENUMT( e ) CG_ ## e /* set scope prefix for defines */ #define CGNS_ENUMD( e ) CG_ ## e /* set scope prefix for variables (lowercase same as functions) */ #define CGNS_ENUMF( e ) cg_ ## e #else #define CGNS_ENUMV( e ) e #define CGNS_ENUMT( e ) e #define CGNS_ENUMD( e ) e #define CGNS_ENUMF( e ) e #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * modes for cgns file * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #define CG_MODE_READ 0 #define CG_MODE_WRITE 1 #define CG_MODE_MODIFY 2 #define CG_MODE_CLOSED 3 /* file types */ #define CG_FILE_NONE 0 #define CG_FILE_ADF 1 #define CG_FILE_HDF5 2 #define CG_FILE_ADF2 3 /* function return codes */ #define CG_OK 0 #define CG_ERROR 1 #define CG_NODE_NOT_FOUND 2 #define CG_INCORRECT_PATH 3 #define CG_NO_INDEX_DIM 4 /* Null and UserDefined enums */ #define CG_Null 0 #define CG_UserDefined 1 /* max goto depth */ #define CG_MAX_GOTO_DEPTH 20 /* configuration options */ #define CG_CONFIG_ERROR 1 #define CG_CONFIG_COMPRESS 2 #define CG_CONFIG_SET_PATH 3 #define CG_CONFIG_ADD_PATH 4 #define CG_CONFIG_FILE_TYPE 5 #define CG_CONFIG_RIND_INDEX 6 #define CG_CONFIG_HDF5_COMPRESS 201 #define CG_CONFIG_HDF5_MPI_COMM 202 /* note: CG_CONFIG_RIND_ZERO is obsolete and considered a bug. Users are given * the option only for backwards compatibilty */ #define CG_CONFIG_RIND_ZERO (void*)0 #define CG_CONFIG_RIND_CORE (void*)1 #ifdef __cplusplus extern "C" { #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Enumerations: if any of this enumerations need to be modified, * * the corresponding namelist must also be updated. * * * * Any addition to an enum should be done as an addition at end of list * * with an explicit declaration of the corresponding integer. * * This is required for enums stored as integers in the CGNS file or * * used in applications. * * * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Dimensional Units * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( MassUnitsNull ) =CG_Null, CGNS_ENUMV( MassUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Kilogram ) =2, CGNS_ENUMV( Gram ) =3, CGNS_ENUMV( Slug ) =4, CGNS_ENUMV( PoundMass ) =5 } CGNS_ENUMT( MassUnits_t ); typedef enum { CGNS_ENUMV( LengthUnitsNull ) =CG_Null, CGNS_ENUMV( LengthUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Meter ) =2, CGNS_ENUMV( Centimeter ) =3, CGNS_ENUMV( Millimeter ) =4, CGNS_ENUMV( Foot ) =5, CGNS_ENUMV( Inch ) =6 } CGNS_ENUMT( LengthUnits_t ); typedef enum { CGNS_ENUMV( TimeUnitsNull ) =CG_Null, CGNS_ENUMV( TimeUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Second ) =2 } CGNS_ENUMT( TimeUnits_t ); typedef enum { CGNS_ENUMV( TemperatureUnitsNull ) =CG_Null, CGNS_ENUMV( TemperatureUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Kelvin ) =2, CGNS_ENUMV( Celsius ) =3, CGNS_ENUMV( Rankine ) =4, CGNS_ENUMV( Fahrenheit ) =5 } CGNS_ENUMT( TemperatureUnits_t ); typedef enum { CGNS_ENUMV( AngleUnitsNull ) =CG_Null, CGNS_ENUMV( AngleUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Degree ) =2, CGNS_ENUMV( Radian ) =3 } CGNS_ENUMT( AngleUnits_t ); typedef enum { CGNS_ENUMV( ElectricCurrentUnitsNull ) =CG_Null, CGNS_ENUMV( ElectricCurrentUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Ampere ) =2, CGNS_ENUMV( Abampere ) =3, CGNS_ENUMV( Statampere ) =4, CGNS_ENUMV( Edison ) =5, CGNS_ENUMV( auCurrent ) =6 } CGNS_ENUMT( ElectricCurrentUnits_t ); typedef enum { CGNS_ENUMV( SubstanceAmountUnitsNull ) =CG_Null, CGNS_ENUMV( SubstanceAmountUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Mole ) =2, CGNS_ENUMV( Entities ) =3, CGNS_ENUMV( StandardCubicFoot ) =4, CGNS_ENUMV( StandardCubicMeter ) =5 } CGNS_ENUMT( SubstanceAmountUnits_t ); typedef enum { CGNS_ENUMV( LuminousIntensityUnitsNull ) =CG_Null, CGNS_ENUMV( LuminousIntensityUnitsUserDefined )=CG_UserDefined, CGNS_ENUMV( Candela ) =2, CGNS_ENUMV( Candle ) =3, CGNS_ENUMV( Carcel ) =4, CGNS_ENUMV( Hefner ) =5, CGNS_ENUMV( Violle ) =6 } CGNS_ENUMT( LuminousIntensityUnits_t ); #define NofValidMassUnits 6 #define NofValidLengthUnits 7 #define NofValidTimeUnits 3 #define NofValidTemperatureUnits 6 #define NofValidAngleUnits 4 #define NofValidElectricCurrentUnits 7 #define NofValidSubstanceAmountUnits 6 #define NofValidLuminousIntensityUnits 7 extern CGNSDLL const char * MassUnitsName[NofValidMassUnits]; extern CGNSDLL const char * LengthUnitsName[NofValidLengthUnits]; extern CGNSDLL const char * TimeUnitsName[NofValidTimeUnits]; extern CGNSDLL const char * TemperatureUnitsName[NofValidTemperatureUnits]; extern CGNSDLL const char * AngleUnitsName[NofValidAngleUnits]; extern CGNSDLL const char * ElectricCurrentUnitsName[NofValidElectricCurrentUnits]; extern CGNSDLL const char * SubstanceAmountUnitsName[NofValidSubstanceAmountUnits]; extern CGNSDLL const char * LuminousIntensityUnitsName[NofValidLuminousIntensityUnits]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Data Class * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( DataClassNull ) =CG_Null, CGNS_ENUMV( DataClassUserDefined ) =CG_UserDefined, CGNS_ENUMV( Dimensional ) =2, CGNS_ENUMV( NormalizedByDimensional ) =3, CGNS_ENUMV( NormalizedByUnknownDimensional ) =4, CGNS_ENUMV( NondimensionalParameter ) =5, CGNS_ENUMV( DimensionlessConstant ) =6 } CGNS_ENUMT( DataClass_t ); #define NofValidDataClass 7 extern CGNSDLL const char * DataClassName[NofValidDataClass]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Location \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( GridLocationNull ) =CG_Null, CGNS_ENUMV( GridLocationUserDefined ) =CG_UserDefined, CGNS_ENUMV( Vertex ) =2, CGNS_ENUMV( CellCenter ) =3, CGNS_ENUMV( FaceCenter ) =4, CGNS_ENUMV( IFaceCenter ) =5, CGNS_ENUMV( JFaceCenter ) =6, CGNS_ENUMV( KFaceCenter ) =7, CGNS_ENUMV( EdgeCenter ) =8 } CGNS_ENUMT( GridLocation_t ); #define NofValidGridLocation 9 extern CGNSDLL const char * GridLocationName[NofValidGridLocation]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * BCData Types: Can not add types and stay forward compatible * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( BCDataTypeNull ) =CG_Null, CGNS_ENUMV( BCDataTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Dirichlet ) =2, CGNS_ENUMV( Neumann ) =3 } CGNS_ENUMT( BCDataType_t ); #define NofValidBCDataTypes 4 extern CGNSDLL const char * BCDataTypeName[NofValidBCDataTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Connectivity Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( GridConnectivityTypeNull ) =CG_Null, CGNS_ENUMV( GridConnectivityTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Overset ) =2, CGNS_ENUMV( Abutting ) =3, CGNS_ENUMV( Abutting1to1 ) =4 } CGNS_ENUMT( GridConnectivityType_t ); #define NofValidGridConnectivityTypes 5 extern CGNSDLL const char * GridConnectivityTypeName[NofValidGridConnectivityTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Point Set Types: Can't add types and stay forward compatible \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( PointSetTypeNull ) =CG_Null, CGNS_ENUMV( PointSetTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( PointList ) =2, CGNS_ENUMV( PointListDonor ) =3, CGNS_ENUMV( PointRange ) =4, CGNS_ENUMV( PointRangeDonor ) =5, CGNS_ENUMV( ElementRange ) =6, CGNS_ENUMV( ElementList ) =7, CGNS_ENUMV( CellListDonor ) =8 } CGNS_ENUMT( PointSetType_t ); #define NofValidPointSetTypes 9 extern CGNSDLL const char * PointSetTypeName[NofValidPointSetTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Governing Equations and Physical Models Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( GoverningEquationsNull ) =CG_Null, CGNS_ENUMV( GoverningEquationsUserDefined ) =CG_UserDefined, CGNS_ENUMV( FullPotential ) =2, CGNS_ENUMV( Euler ) =3, CGNS_ENUMV( NSLaminar ) =4, CGNS_ENUMV( NSTurbulent ) =5, CGNS_ENUMV( NSLaminarIncompressible ) =6, CGNS_ENUMV( NSTurbulentIncompressible ) =7 } CGNS_ENUMT( GoverningEquationsType_t ); /* Any model type will accept both ModelTypeNull and ModelTypeUserDefined. ** The following models will accept these values as vaild... ** ** GasModel_t: Ideal, VanderWaals, CaloricallyPerfect, ThermallyPerfect, ** ConstantDensity, RedlichKwong ** ** ViscosityModel_t: Constant, PowerLaw, SutherlandLaw ** ** ThermalConductivityModel_t: PowerLaw, SutherlandLaw, ConstantPrandtl ** ** TurbulenceModel_t: Algebraic_BaldwinLomax, Algebraic_CebeciSmith, ** HalfEquation_JohnsonKing, OneEquation_BaldwinBarth, ** OneEquation_SpalartAllmaras, TwoEquation_JonesLaunder, ** TwoEquation_MenterSST,TwoEquation_Wilcox ** ** TurbulenceClosure_t: EddyViscosity, ReynoldsStress, ReynoldsStressAlgebraic ** ** ThermalRelaxationModel_t: Frozen, ThermalEquilib, ThermalNonequilib ** ** ChemicalKineticsModel_t: Frozen, ChemicalEquilibCurveFit, ** ChemicalEquilibMinimization, ChemicalNonequilib ** ** EMElectricFieldModel_t: Voltage, Interpolated, Constant, Frozen ** ** EMMagneticFieldModel_t: Interpolated, Constant, Frozen ** ** EMConductivityModel_t: Constant, Frozen, Equilibrium_LinRessler, ** Chemistry_LinRessler */ typedef enum { CGNS_ENUMV( ModelTypeNull ) =CG_Null, CGNS_ENUMV( ModelTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Ideal ) =2, CGNS_ENUMV( VanderWaals ) =3, CGNS_ENUMV( Constant ) =4, CGNS_ENUMV( PowerLaw ) =5, CGNS_ENUMV( SutherlandLaw ) =6, CGNS_ENUMV( ConstantPrandtl ) =7, CGNS_ENUMV( EddyViscosity ) =8, CGNS_ENUMV( ReynoldsStress ) =9, CGNS_ENUMV( ReynoldsStressAlgebraic ) =10, CGNS_ENUMV( Algebraic_BaldwinLomax ) =11, CGNS_ENUMV( Algebraic_CebeciSmith ) =12, CGNS_ENUMV( HalfEquation_JohnsonKing ) =13, CGNS_ENUMV( OneEquation_BaldwinBarth ) =14, CGNS_ENUMV( OneEquation_SpalartAllmaras ) =15, CGNS_ENUMV( TwoEquation_JonesLaunder ) =16, CGNS_ENUMV( TwoEquation_MenterSST ) =17, CGNS_ENUMV( TwoEquation_Wilcox ) =18, CGNS_ENUMV( CaloricallyPerfect ) =19, CGNS_ENUMV( ThermallyPerfect ) =20, CGNS_ENUMV( ConstantDensity ) =21, CGNS_ENUMV( RedlichKwong ) =22, CGNS_ENUMV( Frozen ) =23, CGNS_ENUMV( ThermalEquilib ) =24, CGNS_ENUMV( ThermalNonequilib ) =25, CGNS_ENUMV( ChemicalEquilibCurveFit ) =26, CGNS_ENUMV( ChemicalEquilibMinimization ) =27, CGNS_ENUMV( ChemicalNonequilib ) =28, CGNS_ENUMV( EMElectricField ) =29, CGNS_ENUMV( EMMagneticField ) =30, CGNS_ENUMV( EMConductivity ) =31, CGNS_ENUMV( Voltage ) =32, CGNS_ENUMV( Interpolated ) =33, CGNS_ENUMV( Equilibrium_LinRessler ) =34, CGNS_ENUMV( Chemistry_LinRessler ) =35 } CGNS_ENUMT( ModelType_t ); #define NofValidGoverningEquationsTypes 8 #define NofValidModelTypes 36 extern CGNSDLL const char * GoverningEquationsTypeName[NofValidGoverningEquationsTypes]; extern CGNSDLL const char * ModelTypeName[NofValidModelTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Boundary Condition Types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( BCTypeNull ) =CG_Null, CGNS_ENUMV( BCTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( BCAxisymmetricWedge ) =2, CGNS_ENUMV( BCDegenerateLine ) =3, CGNS_ENUMV( BCDegeneratePoint ) =4, CGNS_ENUMV( BCDirichlet ) =5, CGNS_ENUMV( BCExtrapolate ) =6, CGNS_ENUMV( BCFarfield ) =7, CGNS_ENUMV( BCGeneral ) =8, CGNS_ENUMV( BCInflow ) =9, CGNS_ENUMV( BCInflowSubsonic ) =10, CGNS_ENUMV( BCInflowSupersonic ) =11, CGNS_ENUMV( BCNeumann ) =12, CGNS_ENUMV( BCOutflow ) =13, CGNS_ENUMV( BCOutflowSubsonic ) =14, CGNS_ENUMV( BCOutflowSupersonic ) =15, CGNS_ENUMV( BCSymmetryPlane ) =16, CGNS_ENUMV( BCSymmetryPolar ) =17, CGNS_ENUMV( BCTunnelInflow ) =18, CGNS_ENUMV( BCTunnelOutflow ) =19, CGNS_ENUMV( BCWall ) =20, CGNS_ENUMV( BCWallInviscid ) =21, CGNS_ENUMV( BCWallViscous ) =22, CGNS_ENUMV( BCWallViscousHeatFlux ) =23, CGNS_ENUMV( BCWallViscousIsothermal ) =24, CGNS_ENUMV( FamilySpecified ) =25 } CGNS_ENUMT( BCType_t ); #define NofValidBCTypes 26 extern CGNSDLL const char * BCTypeName[NofValidBCTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Data types: Can not add data types and stay forward compatible * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( DataTypeNull ) =CG_Null, CGNS_ENUMV( DataTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Integer ) =2, CGNS_ENUMV( RealSingle ) =3, CGNS_ENUMV( RealDouble ) =4, CGNS_ENUMV( Character ) =5, CGNS_ENUMV( LongInteger ) =6 } CGNS_ENUMT( DataType_t ); #define NofValidDataTypes 7 extern CGNSDLL const char * DataTypeName[NofValidDataTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Element types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* PLEASE ALSO UPDATE the cgnslib.h/el_size static table */ typedef enum { CGNS_ENUMV( ElementTypeNull ) =CG_Null, CGNS_ENUMV( ElementTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( NODE ) =2, CGNS_ENUMV( BAR_2 ) =3, CGNS_ENUMV( BAR_3 ) =4, CGNS_ENUMV( TRI_3 ) =5, CGNS_ENUMV( TRI_6 ) =6, CGNS_ENUMV( QUAD_4 ) =7, CGNS_ENUMV( QUAD_8 ) =8, CGNS_ENUMV( QUAD_9 ) =9, CGNS_ENUMV( TETRA_4 ) =10, CGNS_ENUMV( TETRA_10 ) =11, CGNS_ENUMV( PYRA_5 ) =12, CGNS_ENUMV( PYRA_14 ) =13, CGNS_ENUMV( PENTA_6 ) =14, CGNS_ENUMV( PENTA_15 ) =15, CGNS_ENUMV( PENTA_18 ) =16, CGNS_ENUMV( HEXA_8 ) =17, CGNS_ENUMV( HEXA_20 ) =18, CGNS_ENUMV( HEXA_27 ) =19, CGNS_ENUMV( MIXED ) =20, CGNS_ENUMV( PYRA_13 ) =21, CGNS_ENUMV( NGON_n ) =22, CGNS_ENUMV( NFACE_n ) =23, CGNS_ENUMV( BAR_4 ) =24, CGNS_ENUMV( TRI_9 ) =25, CGNS_ENUMV( TRI_10 ) =26, CGNS_ENUMV( QUAD_12 ) =27, CGNS_ENUMV( QUAD_16 ) =28, CGNS_ENUMV( TETRA_16 ) =29, CGNS_ENUMV( TETRA_20 ) =30, CGNS_ENUMV( PYRA_21 ) =31, CGNS_ENUMV( PYRA_29 ) =32, CGNS_ENUMV( PYRA_30 ) =33, CGNS_ENUMV( PENTA_24 ) =34, CGNS_ENUMV( PENTA_38 ) =35, CGNS_ENUMV( PENTA_40 ) =36, CGNS_ENUMV( HEXA_32 ) =37, CGNS_ENUMV( HEXA_56 ) =38, CGNS_ENUMV( HEXA_64 ) =39, CGNS_ENUMV( BAR_5 )=40, CGNS_ENUMV( TRI_12 )=41, CGNS_ENUMV( TRI_15 )=42, CGNS_ENUMV( QUAD_P4_16 )=43, CGNS_ENUMV( QUAD_25 )=44, CGNS_ENUMV( TETRA_22 )=45, CGNS_ENUMV( TETRA_34 )=46, CGNS_ENUMV( TETRA_35 )=47, CGNS_ENUMV( PYRA_P4_29 )=48, CGNS_ENUMV( PYRA_50 )=49, CGNS_ENUMV( PYRA_55 )=50, CGNS_ENUMV( PENTA_33 )=51, CGNS_ENUMV( PENTA_66 )=52, CGNS_ENUMV( PENTA_75 )=53, CGNS_ENUMV( HEXA_44 )=54, CGNS_ENUMV( HEXA_98 )=55, CGNS_ENUMV( HEXA_125 )=56 } CGNS_ENUMT( ElementType_t ); #define NofValidElementTypes 57 extern CGNSDLL const char * ElementTypeName[NofValidElementTypes]; #ifdef CGNS_SCOPE_ENUMS #define CG_NPE_NODE 1 #define CG_NPE_BAR_2 2 #define CG_NPE_BAR_3 3 #define CG_NPE_TRI_3 3 #define CG_NPE_TRI_6 6 #define CG_NPE_QUAD_4 4 #define CG_NPE_QUAD_8 8 #define CG_NPE_QUAD_9 9 #define CG_NPE_TETRA_4 4 #define CG_NPE_TETRA_10 10 #define CG_NPE_PYRA_5 5 #define CG_NPE_PYRA_13 13 #define CG_NPE_PYRA_14 14 #define CG_NPE_PENTA_6 6 #define CG_NPE_PENTA_15 15 #define CG_NPE_PENTA_18 18 #define CG_NPE_HEXA_8 8 #define CG_NPE_HEXA_20 20 #define CG_NPE_HEXA_27 27 #define CG_NPE_MIXED 0 #define CG_NPE_NGON_n 0 #define CG_NPE_NFACE_n 0 #define CG_NPE_BAR_4 4 #define CG_NPE_TRI_9 9 #define CG_NPE_TRI_10 10 #define CG_NPE_QUAD_12 12 #define CG_NPE_QUAD_16 16 #define CG_NPE_TETRA_16 16 #define CG_NPE_TETRA_20 20 #define CG_NPE_PYRA_21 21 #define CG_NPE_PYRA_29 29 #define CG_NPE_PYRA_30 30 #define CG_NPE_PENTA_24 24 #define CG_NPE_PENTA_38 38 #define CG_NPE_PENTA_40 40 #define CG_NPE_HEXA_32 32 #define CG_NPE_HEXA_56 56 #define CG_NPE_HEXA_64 64 #define CG_NPE_BAR_5 5 #define CG_NPE_TRI_12 12 #define CG_NPE_TRI_15 15 #define CG_NPE_QUAD_P4_16 16 #define CG_NPE_QUAD_25 25 #define CG_NPE_TETRA_22 22 #define CG_NPE_TETRA_34 34 #define CG_NPE_TETRA_35 35 #define CG_NPE_PYRA_P4_29 29 #define CG_NPE_PYRA_50 50 #define CG_NPE_PYRA_55 55 #define CG_NPE_PENTA_33 33 #define CG_NPE_PENTA_66 66 #define CG_NPE_PENTA_75 75 #define CG_NPE_HEXA_44 44 #define CG_NPE_HEXA_98 98 #define CG_NPE_HEXA_125 125 #else #define NPE_NODE 1 #define NPE_BAR_2 2 #define NPE_BAR_3 3 #define NPE_TRI_3 3 #define NPE_TRI_6 6 #define NPE_QUAD_4 4 #define NPE_QUAD_8 8 #define NPE_QUAD_9 9 #define NPE_TETRA_4 4 #define NPE_TETRA_10 10 #define NPE_PYRA_5 5 #define NPE_PYRA_13 13 #define NPE_PYRA_14 14 #define NPE_PENTA_6 6 #define NPE_PENTA_15 15 #define NPE_PENTA_18 18 #define NPE_HEXA_8 8 #define NPE_HEXA_20 20 #define NPE_HEXA_27 27 #define NPE_MIXED 0 #define NPE_NGON_n 0 #define NPE_NFACE_n 0 #define NPE_BAR_4 4 #define NPE_TRI_9 9 #define NPE_TRI_10 10 #define NPE_QUAD_12 12 #define NPE_QUAD_16 16 #define NPE_TETRA_16 16 #define NPE_TETRA_20 20 #define NPE_PYRA_21 21 #define NPE_PYRA_29 29 #define NPE_PYRA_30 30 #define NPE_PENTA_24 24 #define NPE_PENTA_38 38 #define NPE_PENTA_40 40 #define NPE_HEXA_32 32 #define NPE_HEXA_56 56 #define NPE_HEXA_64 64 #define NPE_BAR_5 5 #define NPE_TRI_12 12 #define NPE_TRI_15 15 #define NPE_QUAD_P4_16 16 #define NPE_QUAD_25 25 #define NPE_TETRA_22 22 #define NPE_TETRA_34 34 #define NPE_TETRA_35 35 #define NPE_PYRA_P4_29 29 #define NPE_PYRA_50 50 #define NPE_PYRA_55 55 #define NPE_PENTA_33 33 #define NPE_PENTA_66 66 #define NPE_PENTA_75 75 #define NPE_HEXA_44 44 #define NPE_HEXA_98 98 #define NPE_HEXA_125 125 #endif /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Zone types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( ZoneTypeNull ) =CG_Null, CGNS_ENUMV( ZoneTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Structured ) =2, CGNS_ENUMV( Unstructured ) =3 } CGNS_ENUMT( ZoneType_t ); #define NofValidZoneTypes 4 extern CGNSDLL const char * ZoneTypeName[NofValidZoneTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Rigid Grid Motion types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( RigidGridMotionTypeNull ) =CG_Null, CGNS_ENUMV( RigidGridMotionTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( ConstantRate ) =2, CGNS_ENUMV( VariableRate ) =3 } CGNS_ENUMT( RigidGridMotionType_t ); #define NofValidRigidGridMotionTypes 4 extern CGNSDLL const char * RigidGridMotionTypeName[NofValidRigidGridMotionTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Arbitrary Grid Motion types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( ArbitraryGridMotionTypeNull ) =CG_Null, CGNS_ENUMV( ArbitraryGridMotionTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( NonDeformingGrid ) =2, CGNS_ENUMV( DeformingGrid ) =3 } CGNS_ENUMT( ArbitraryGridMotionType_t ); #define NofValidArbitraryGridMotionTypes 4 extern CGNSDLL const char * ArbitraryGridMotionTypeName[NofValidArbitraryGridMotionTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Simulation types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( SimulationTypeNull ) =CG_Null, CGNS_ENUMV( SimulationTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( TimeAccurate ) =2, CGNS_ENUMV( NonTimeAccurate ) =3 } CGNS_ENUMT( SimulationType_t ); #define NofValidSimulationTypes 4 extern CGNSDLL const char * SimulationTypeName[NofValidSimulationTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * BC Property types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( WallFunctionTypeNull ) =CG_Null, CGNS_ENUMV( WallFunctionTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( Generic ) =2 } CGNS_ENUMT( WallFunctionType_t ); typedef enum { CGNS_ENUMV( AreaTypeNull ) =CG_Null, CGNS_ENUMV( AreaTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( BleedArea ) =2, CGNS_ENUMV( CaptureArea ) =3 } CGNS_ENUMT( AreaType_t ); #define NofValidWallFunctionTypes 3 #define NofValidAreaTypes 4 extern CGNSDLL const char * WallFunctionTypeName[NofValidWallFunctionTypes]; extern CGNSDLL const char * AreaTypeName[NofValidAreaTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Grid Connectivity Property types * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ typedef enum { CGNS_ENUMV( AverageInterfaceTypeNull ) =CG_Null, CGNS_ENUMV( AverageInterfaceTypeUserDefined ) =CG_UserDefined, CGNS_ENUMV( AverageAll ) =2, CGNS_ENUMV( AverageCircumferential ) =3, CGNS_ENUMV( AverageRadial ) =4, CGNS_ENUMV( AverageI ) =5, CGNS_ENUMV( AverageJ ) =6, CGNS_ENUMV( AverageK ) =7 } CGNS_ENUMT( AverageInterfaceType_t ); #define NofValidAverageInterfaceTypes 8 extern CGNSDLL const char * AverageInterfaceTypeName[NofValidAverageInterfaceTypes]; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * LIBRARY FUNCTIONS * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_is_cgns(const char *filename, int *file_type); CGNSDLL int cg_open(const char * filename, int mode, int *fn); CGNSDLL int cg_version(int fn, float *FileVersion); CGNSDLL int cg_precision(int fn, int *precision); CGNSDLL int cg_close(int fn); CGNSDLL int cg_save_as(int fn, const char *filename, int file_type, int follow_links); CGNSDLL int cg_set_file_type(int file_type); CGNSDLL int cg_get_file_type(int fn, int *file_type); CGNSDLL int cg_root_id(int fn, double *rootid); CGNSDLL int cg_get_cgio(int fn, int *cgio_num); CGNSDLL int cg_configure(int what, void *value); CGNSDLL int cg_error_handler(void (*)(int, char *)); CGNSDLL int cg_set_compress(int compress); CGNSDLL int cg_get_compress(int *compress); CGNSDLL int cg_set_path(const char *path); CGNSDLL int cg_add_path(const char *path); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * typedef names * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #undef type CGNSDLL const char *cg_get_name(int nnames, const char **names, int type); CGNSDLL const char *cg_MassUnitsName(CGNS_ENUMT( MassUnits_t ) type); CGNSDLL const char *cg_LengthUnitsName(CGNS_ENUMT( LengthUnits_t ) type); CGNSDLL const char *cg_TimeUnitsName(CGNS_ENUMT( TimeUnits_t ) type); CGNSDLL const char *cg_TemperatureUnitsName(CGNS_ENUMT( TemperatureUnits_t ) type); CGNSDLL const char *cg_AngleUnitsName(CGNS_ENUMT( AngleUnits_t ) type); CGNSDLL const char *cg_ElectricCurrentUnitsName(CGNS_ENUMT( ElectricCurrentUnits_t ) type); CGNSDLL const char *cg_SubstanceAmountUnitsName(CGNS_ENUMT( SubstanceAmountUnits_t ) type); CGNSDLL const char *cg_LuminousIntensityUnitsName(CGNS_ENUMT( LuminousIntensityUnits_t ) type); CGNSDLL const char *cg_DataClassName(CGNS_ENUMT( DataClass_t ) type); CGNSDLL const char *cg_GridLocationName(CGNS_ENUMT( GridLocation_t ) type); CGNSDLL const char *cg_BCDataTypeName(CGNS_ENUMT( BCDataType_t ) type); CGNSDLL const char *cg_GridConnectivityTypeName(CGNS_ENUMT( GridConnectivityType_t ) type); CGNSDLL const char *cg_PointSetTypeName(CGNS_ENUMT( PointSetType_t ) type); CGNSDLL const char *cg_GoverningEquationsTypeName(CGNS_ENUMT( GoverningEquationsType_t ) type); CGNSDLL const char *cg_ModelTypeName(CGNS_ENUMT( ModelType_t ) type); CGNSDLL const char *cg_BCTypeName(CGNS_ENUMT( BCType_t ) type); CGNSDLL const char *cg_DataTypeName(CGNS_ENUMT( DataType_t ) type); CGNSDLL const char *cg_ElementTypeName(CGNS_ENUMT( ElementType_t ) type); CGNSDLL const char *cg_ZoneTypeName(CGNS_ENUMT( ZoneType_t ) type); CGNSDLL const char *cg_RigidGridMotionTypeName(CGNS_ENUMT( RigidGridMotionType_t ) type); CGNSDLL const char *cg_ArbitraryGridMotionTypeName(CGNS_ENUMT( ArbitraryGridMotionType_t ) type); CGNSDLL const char *cg_SimulationTypeName(CGNS_ENUMT( SimulationType_t ) type); CGNSDLL const char *cg_WallFunctionTypeName(CGNS_ENUMT( WallFunctionType_t ) type); CGNSDLL const char *cg_AreaTypeName(CGNS_ENUMT( AreaType_t ) type); CGNSDLL const char *cg_AverageInterfaceTypeName(CGNS_ENUMT( AverageInterfaceType_t ) type); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write CGNSBase_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nbases(int fn, int *nbases); CGNSDLL int cg_base_read(int file_number, int B, char *basename, int *cell_dim, int *phys_dim); CGNSDLL int cg_base_id(int fn, int B, double *base_id); CGNSDLL int cg_base_write(int file_number, const char * basename, int cell_dim, int phys_dim, int *B); CGNSDLL int cg_cell_dim(int fn, int B, int *cell_dim); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Zone_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nzones(int fn, int B, int *nzones); CGNSDLL int cg_zone_read(int fn, int B, int Z, char *zonename, cgsize_t *size); CGNSDLL int cg_zone_type(int file_number, int B, int Z, CGNS_ENUMT(ZoneType_t) *type); CGNSDLL int cg_zone_id(int fn, int B, int Z, double *zone_id); CGNSDLL int cg_zone_write(int fn, int B, const char * zonename, const cgsize_t * size, CGNS_ENUMT(ZoneType_t) type, int *Z); CGNSDLL int cg_index_dim(int fn, int B, int Z, int *index_dim); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Family_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nfamilies(int file_number, int B, int *nfamilies); CGNSDLL int cg_family_read(int file_number, int B, int F, char *family_name, int *nboco, int *ngeos); CGNSDLL int cg_family_write(int file_number, int B, const char * family_name, int *F); CGNSDLL int cg_nfamily_names(int file_number, int B, int F, int *nnames); CGNSDLL int cg_family_name_read(int file_number, int B, int F, int N, char *name, char *family); CGNSDLL int cg_family_name_write(int file_number, int B, int F, const char *name, const char *family); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FamilyName_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_famname_read(char *family_name); CGNSDLL int cg_famname_write(const char * family_name); CGNSDLL int cg_nmultifam(int *nfams); CGNSDLL int cg_multifam_read(int N, char *name, char *family); CGNSDLL int cg_multifam_write(const char *name, const char *family); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FamilyBC_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_fambc_read(int file_number, int B, int F, int BC, char *fambc_name, CGNS_ENUMT(BCType_t) *bocotype); CGNSDLL int cg_fambc_write(int file_number, int B, int F, const char * fambc_name, CGNS_ENUMT(BCType_t) bocotype, int *BC); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GeometryReference_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_geo_read(int file_number, int B, int F, int G, char *geo_name, char **geo_file, char *CAD_name, int *npart); CGNSDLL int cg_geo_write(int file_number, int B, int F, const char * geo_name, const char * filename, const char * CADname, int *G); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GeometryEntity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_part_read(int file_number, int B, int F, int G, int P, char *part_name); CGNSDLL int cg_part_write(int file_number, int B, int F, int G, const char * part_name, int *P); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridCoordinates_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ngrids(int file_number, int B, int Z, int *ngrids); CGNSDLL int cg_grid_read(int file_number, int B, int Z, int G, char *gridname); CGNSDLL int cg_grid_write(int file_number, int B, int Z, const char * zcoorname, int *G); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridCoordinates_t/DataArray_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ncoords(int fn, int B, int Z, int *ncoords); CGNSDLL int cg_coord_info(int fn, int B, int Z, int C, CGNS_ENUMT(DataType_t) *type, char *coordname); CGNSDLL int cg_coord_read(int fn, int B, int Z, const char * coordname, CGNS_ENUMT(DataType_t) type, const cgsize_t * rmin, const cgsize_t * rmax, void *coord); CGNSDLL int cg_coord_general_read(int fn, int B, int Z, const char * coordname, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, void *coord_ptr); CGNSDLL int cg_coord_id(int fn, int B, int Z, int C, double *coord_id); CGNSDLL int cg_coord_write(int fn, int B, int Z, CGNS_ENUMT(DataType_t) type, const char * coordname, const void * coord_ptr, int *C); CGNSDLL int cg_coord_partial_write(int fn, int B, int Z, CGNS_ENUMT(DataType_t) type, const char * coordname, const cgsize_t *rmin, const cgsize_t *rmax, const void * coord_ptr, int *C); CGNSDLL int cg_coord_general_write(int fn, int B, int Z, const char *coordname, CGNS_ENUMT(DataType_t) s_type, const cgsize_t *rmin, const cgsize_t *rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dims, const cgsize_t *m_rmin, const cgsize_t *m_rmax, const void *coord_ptr, int *C); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Elements_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nsections(int file_number, int B, int Z, int *nsections); CGNSDLL int cg_section_read(int file_number, int B, int Z, int S, char *SectionName, CGNS_ENUMT(ElementType_t) *type, cgsize_t *start, cgsize_t *end, int *nbndry, int *parent_flag); CGNSDLL int cg_elements_read(int file_number, int B, int Z, int S, cgsize_t *elements, cgsize_t *parent_data); CGNSDLL int cg_poly_elements_read(int file_number, int B, int Z, int S, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent_data); CGNSDLL int cg_section_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t) type, cgsize_t start, cgsize_t end, int nbndry, const cgsize_t * elements, int *S); CGNSDLL int cg_poly_section_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t) type, cgsize_t start, cgsize_t end, int nbndry, const cgsize_t * elements, const cgsize_t * connect_offset, int *S); CGNSDLL int cg_parent_data_write(int file_number, int B, int Z, int S, const cgsize_t * parent_data); CGNSDLL int cg_npe( CGNS_ENUMT(ElementType_t) type, int *npe); CGNSDLL int cg_ElementDataSize(int file_number, int B, int Z, int S, cgsize_t *ElementDataSize); CGNSDLL int cg_section_partial_write(int file_number, int B, int Z, const char * SectionName, CGNS_ENUMT(ElementType_t) type, cgsize_t start, cgsize_t end, int nbndry, int *S); CGNSDLL int cg_elements_partial_write(int fn, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *elements); CGNSDLL int cg_poly_elements_partial_write(int fn, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *elements, const cgsize_t *connect_offset); CGNSDLL int cg_parent_data_partial_write(int fn, int B, int Z, int S, cgsize_t start, cgsize_t end, const cgsize_t *ParentData); CGNSDLL int cg_elements_partial_read(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *elements, cgsize_t *parent_data); CGNSDLL int cg_poly_elements_partial_read(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *elements, cgsize_t *connect_offset, cgsize_t *parent_data); CGNSDLL int cg_ElementPartialSize(int file_number, int B, int Z, int S, cgsize_t start, cgsize_t end, cgsize_t *ElementDataSize); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FlowSolution_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nsols(int fn, int B, int Z, int *nsols); CGNSDLL int cg_sol_info(int fn, int B, int Z, int S, char *solname, CGNS_ENUMT(GridLocation_t) *location); CGNSDLL int cg_sol_id(int fn, int B, int Z,int S, double *sol_id); CGNSDLL int cg_sol_write(int fn, int B, int Z, const char * solname, CGNS_ENUMT(GridLocation_t) location, int *S); CGNSDLL int cg_sol_size(int fn, int B, int Z, int S, int *data_dim, cgsize_t *dim_vals); CGNSDLL int cg_sol_ptset_info(int fn, int B, int Z, int S, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts); CGNSDLL int cg_sol_ptset_read(int fn, int B, int Z, int S, cgsize_t *pnts); CGNSDLL int cg_sol_ptset_write(int fn, int B, int Z, const char *solname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *S); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write solution DataArray_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nfields(int fn, int B, int Z, int S, int *nfields); CGNSDLL int cg_field_info(int fn,int B,int Z,int S, int F, CGNS_ENUMT(DataType_t) *type, char *fieldname); CGNSDLL int cg_field_read(int fn, int B, int Z, int S, const char *fieldname, CGNS_ENUMT(DataType_t) type, const cgsize_t *rmin, const cgsize_t *rmax, void *field_ptr); CGNSDLL int cg_field_general_read(int fn, int B, int Z, int S, const char *fieldname, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, void *field_ptr); CGNSDLL int cg_field_id(int fn, int B, int Z,int S, int F, double *field_id); CGNSDLL int cg_field_write(int fn,int B,int Z,int S, CGNS_ENUMT(DataType_t) type, const char * fieldname, const void * field_ptr, int *F); CGNSDLL int cg_field_partial_write(int fn, int B, int Z, int S, CGNS_ENUMT(DataType_t) type, const char * fieldname, const cgsize_t *rmin, const cgsize_t *rmax, const void * field_ptr, int *F); CGNSDLL int cg_field_general_write(int fn, int B, int Z, int S, const char * fieldname, CGNS_ENUMT(DataType_t) s_type, const cgsize_t *rmin, const cgsize_t *rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dims, const cgsize_t *m_rmin, const cgsize_t *m_rmax, const void *field_ptr, int *F); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneSubRegion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nsubregs(int fn, int B, int Z, int *nsubreg); CGNSDLL int cg_subreg_info(int fn, int B, int Z, int S, char *regname, int *dimension, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, int *bcname_len, int *gcname_len); CGNSDLL int cg_subreg_ptset_read(int fn, int B, int Z, int S, cgsize_t *pnts); CGNSDLL int cg_subreg_bcname_read(int fn, int B, int Z, int S, char *bcname); CGNSDLL int cg_subreg_gcname_read(int fn, int B, int Z, int S, char *gcname); CGNSDLL int cg_subreg_ptset_write(int fn, int B, int Z, const char *regname, int dimension, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *S); CGNSDLL int cg_subreg_bcname_write(int fn, int B, int Z, const char *regname, int dimension, const char *bcname, int *S); CGNSDLL int cg_subreg_gcname_write(int fn, int B, int Z, const char *regname, int dimension, const char *gcname, int *S); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneGridConnectivity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nzconns(int fn, int B, int Z, int *nzconns); CGNSDLL int cg_zconn_read(int fn, int B, int Z, int C, char *name); CGNSDLL int cg_zconn_write(int fn, int B, int Z, const char *name, int *C); CGNSDLL int cg_zconn_get(int fn, int B, int Z, int *C); CGNSDLL int cg_zconn_set(int fn, int B, int Z, int C); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write OversetHoles_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nholes(int fn, int B, int Z, int *nholes); CGNSDLL int cg_hole_info(int fn, int B, int Z, int Ii, char *holename, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(PointSetType_t) *ptset_type, int *nptsets, cgsize_t *npnts); CGNSDLL int cg_hole_read(int fn, int B, int Z, int Ii, cgsize_t *pnts); CGNSDLL int cg_hole_id(int fn, int B, int Z, int Ii, double *hole_id); CGNSDLL int cg_hole_write(int fn, int B, int Z, const char * holename, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, int nptsets, cgsize_t npnts, const cgsize_t * pnts, int *Ii); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nconns(int fn, int B, int Z, int *nconns); CGNSDLL int cg_conn_info(int file_number, int B, int Z, int Ii, char *connectname, CGNS_ENUMT(GridLocation_t) *location, CGNS_ENUMT(GridConnectivityType_t) *type, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, char *donorname, CGNS_ENUMT(ZoneType_t) *donor_zonetype, CGNS_ENUMT(PointSetType_t) *donor_ptset_type, CGNS_ENUMT(DataType_t) *donor_datatype, cgsize_t *ndata_donor); CGNSDLL int cg_conn_read(int file_number, int B, int Z, int Ii, cgsize_t *pnts, CGNS_ENUMT(DataType_t) donor_datatype, cgsize_t *donor_data); CGNSDLL int cg_conn_id(int fn, int B, int Z, int Ii, double *conn_id); CGNSDLL int cg_conn_write(int file_number, int B, int Z, const char * connectname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(GridConnectivityType_t) type, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, const char * donorname, CGNS_ENUMT(ZoneType_t) donor_zonetype, CGNS_ENUMT(PointSetType_t) donor_ptset_type, CGNS_ENUMT(DataType_t) donor_datatype, cgsize_t ndata_donor, const cgsize_t *donor_data, int *Ii); CGNSDLL int cg_conn_write_short(int file_number, int B, int Z, const char * connectname, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(GridConnectivityType_t) type, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, const char * donorname, int *Ii); CGNSDLL int cg_conn_read_short(int file_number, int B, int Z, int Ii, cgsize_t *pnts); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivity1to1_t Nodes in a zone * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_n1to1(int fn, int B, int Z, int *n1to1); CGNSDLL int cg_1to1_read(int fn, int B, int Z, int Ii, char *connectname, char *donorname, cgsize_t *range, cgsize_t *donor_range, int *transform); CGNSDLL int cg_1to1_id(int fn, int B, int Z, int Ii, double *one21_id); CGNSDLL int cg_1to1_write(int fn, int B, int Z, const char * connectname, const char * donorname, const cgsize_t * range, const cgsize_t * donor_range, const int * transform, int *Ii); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read all GridConnectivity1to1_t Nodes of a base * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_n1to1_global(int fn, int B, int *n1to1_global); CGNSDLL int cg_1to1_read_global(int fn, int B, char **connectname, char **zonename, char **donorname, cgsize_t **range, cgsize_t **donor_range, int **transform); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BC_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nbocos(int fn, int B, int Z, int *nbocos); CGNSDLL int cg_boco_info(int fn, int B, int Z, int BC, char *boconame, CGNS_ENUMT(BCType_t) *bocotype, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts, int *NormalIndex, cgsize_t *NormalListSize, CGNS_ENUMT(DataType_t) *NormalDataType, int *ndataset); CGNSDLL int cg_boco_read(int fn, int B, int Z, int BC, cgsize_t *pnts, void *NormalList); CGNSDLL int cg_boco_id(int fn, int B, int Z, int BC, double *boco_id); CGNSDLL int cg_boco_write(int file_number, int B, int Z, const char * boconame, CGNS_ENUMT(BCType_t) bocotype, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t * pnts, int *BC); CGNSDLL int cg_boco_normal_write(int file_number, int B, int Z, int BC, const int * NormalIndex, int NormalListFlag, CGNS_ENUMT(DataType_t) NormalDataType, const void * NormalList); CGNSDLL int cg_boco_gridlocation_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(GridLocation_t) *location); CGNSDLL int cg_boco_gridlocation_write(int file_number, int B, int Z, int BC, CGNS_ENUMT(GridLocation_t) location); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCDataSet_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_dataset_read(int fn, int B, int Z, int BC, int DS, char *name, CGNS_ENUMT(BCType_t) *BCType, int *DirichletFlag, int *NeumannFlag); CGNSDLL int cg_dataset_write(int file_number, int B, int Z, int BC, const char * name, CGNS_ENUMT(BCType_t) BCType, int *Dset); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FamilyBCDataSet_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_bcdataset_write(const char *name, CGNS_ENUMT(BCType_t) BCType, CGNS_ENUMT(BCDataType_t) BCDataType); CGNSDLL int cg_bcdataset_info(int *n_dataset); CGNSDLL int cg_bcdataset_read(int index, char *name, CGNS_ENUMT(BCType_t) *BCType, int *DirichletFlag, int *NeumannFlag); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_bcdata_write(int file_number, int B, int Z, int BC, int Dset, CGNS_ENUMT(BCDataType_t) BCDataType); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DiscreteData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ndiscrete(int file_number, int B, int Z, int *ndiscrete); CGNSDLL int cg_discrete_read(int file_number, int B, int Z, int D, char *discrete_name); CGNSDLL int cg_discrete_write(int file_number, int B, int Z, const char * discrete_name, int *D); CGNSDLL int cg_discrete_size(int fn, int B, int Z, int D, int *data_dim, cgsize_t *dim_vals); CGNSDLL int cg_discrete_ptset_info(int fn, int B, int Z, int D, CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts); CGNSDLL int cg_discrete_ptset_read(int fn, int B, int Z, int D, cgsize_t *pnts); CGNSDLL int cg_discrete_ptset_write(int fn, int B, int Z, const char *discrete_name, CGNS_ENUMT(GridLocation_t) location, CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts, int *D); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write RigidGridMotion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_n_rigid_motions(int file_number, int B, int Z, int *n_rigid_motions); CGNSDLL int cg_rigid_motion_read(int file_number, int B, int Z, int R, char *name, CGNS_ENUMT(RigidGridMotionType_t) *type); CGNSDLL int cg_rigid_motion_write(int file_number, int B, int Z, const char * name, CGNS_ENUMT(RigidGridMotionType_t) type, int *R); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ArbitraryGridMotion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_n_arbitrary_motions(int file_number, int B, int Z, int *n_arbitrary_motions); CGNSDLL int cg_arbitrary_motion_read(int file_number, int B, int Z, int A, char *name, CGNS_ENUMT(ArbitraryGridMotionType_t) *type); CGNSDLL int cg_arbitrary_motion_write(int file_number, int B, int Z, const char * amotionname, CGNS_ENUMT(ArbitraryGridMotionType_t) type, int *A); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write SimulationType_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_simulation_type_read(int file_number, int B, CGNS_ENUMT(SimulationType_t) *type); CGNSDLL int cg_simulation_type_write(int file_number, int B, CGNS_ENUMT(SimulationType_t) type); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BaseIterativeData_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_biter_read(int file_number, int B, char *bitername, int *nsteps); CGNSDLL int cg_biter_write(int file_number, int B, const char * bitername, int nsteps); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ZoneIterativeData_t Node * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ziter_read(int file_number, int B, int Z, char *zitername); CGNSDLL int cg_ziter_write(int file_number, int B, int Z, const char * zitername); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Gravity_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_gravity_read(int file_number, int B, float *gravity_vector); CGNSDLL int cg_gravity_write(int file_number, int B, float const *gravity_vector); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Axisymmetry_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_axisym_read(int file_number, int B, float *ref_point, float *axis); CGNSDLL int cg_axisym_write(int file_number, int B, float const *ref_point, float const *axis); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write RotatingCoordinates_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_rotating_read(float *rot_rate, float *rot_center); CGNSDLL int cg_rotating_write(float const *rot_rate, float const *rot_center); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCProperty_t/WallFunction_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_bc_wallfunction_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(WallFunctionType_t) *WallFunctionType); CGNSDLL int cg_bc_wallfunction_write(int file_number, int B, int Z, int BC, CGNS_ENUMT(WallFunctionType_t) WallFunctionType); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write BCProperty_t/Area_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_bc_area_read(int file_number, int B, int Z, int BC, CGNS_ENUMT(AreaType_t) *AreaType, float *SurfaceArea, char *RegionName); CGNSDLL int cg_bc_area_write(int file_number, int B, int Z, int BC, CGNS_ENUMT(AreaType_t) AreaType, float SurfaceArea, const char *RegionName); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivityProperty_t/Periodic_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_conn_periodic_read(int file_number, int B, int Z, int Ii, float *RotationCenter, float *RotationAngle, float *Translation); CGNSDLL int cg_conn_periodic_write(int file_number, int B, int Z, int Ii, float const *RotationCenter, float const *RotationAngle, float const *Translation); CGNSDLL int cg_1to1_periodic_write(int file_number, int B, int Z, int Ii, float const *RotationCenter, float const *RotationAngle, float const *Translation); CGNSDLL int cg_1to1_periodic_read(int file_number, int B, int Z, int Ii, float *RotationCenter, float *RotationAngle, float *Translation); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridConnectivityProperty_t/AverageInterface_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_conn_average_read(int file_number, int B, int Z, int Ii, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType); CGNSDLL int cg_conn_average_write(int file_number, int B, int Z, int Ii, CGNS_ENUMT(AverageInterfaceType_t) AverageInterfaceType); CGNSDLL int cg_1to1_average_write(int file_number, int B, int Z, int Ii, CGNS_ENUMT(AverageInterfaceType_t) AverageInterfaceType); CGNSDLL int cg_1to1_average_read(int file_number, int B, int Z, int Ii, CGNS_ENUMT(AverageInterfaceType_t) *AverageInterfaceType); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Variable Argument List Functions * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_goto(int file_number, int B, ...); CGNSDLL int cg_goto_f08(int file_number, int B, ...); CGNSDLL int cg_gorel(int file_number, ...); CGNSDLL int cg_gorel_f08(int file_number, ...); CGNSDLL int cg_gopath(int file_number, const char *path); CGNSDLL int cg_golist(int file_number, int B, int depth, char **label, int *num); CGNSDLL int cg_where(int *file_number, int *B, int *depth, char **label, int *num); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ConvergenceHistory_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_convergence_read(int *iterations, char **NormDefinitions); CGNSDLL int cg_convergence_write(int iterations, const char * NormDefinitions); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write ReferenceState_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_state_read(char **StateDescription); CGNSDLL int cg_state_write(const char * StateDescription); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write FlowEquationSet_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_equationset_read(int *EquationDimension, int *GoverningEquationsFlag, int *GasModelFlag, int *ViscosityModelFlag, int *ThermalConductivityModelFlag, int *TurbulenceClosureFlag, int *TurbulenceModelFlag); CGNSDLL int cg_equationset_chemistry_read(int *ThermalRelaxationFlag, int *ChemicalKineticsFlag); CGNSDLL int cg_equationset_elecmagn_read(int *ElecFldModelFlag, int *MagnFldModelFlag, int *ConductivityModelFlag); CGNSDLL int cg_equationset_write(int EquationDimension); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GoverningEquations_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_governing_read(CGNS_ENUMT(GoverningEquationsType_t) *EquationsType); CGNSDLL int cg_governing_write(CGNS_ENUMT(GoverningEquationsType_t) Equationstype); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Diffusion Model Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_diffusion_read(int *diffusion_model); CGNSDLL int cg_diffusion_write(const int * diffusion_model); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GasModel_t, ViscosityModel_t, * * ThermalConductivityModel_t, TurbulenceClosure_t, * * TurbulenceModel_t, ThermalRelaxationModel_t, * * ChemicalKineticsModel_t, EMElectricFieldModel_t, * * EMMagneticFieldModel_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_model_read(const char *ModelLabel, CGNS_ENUMT(ModelType_t) *ModelType); CGNSDLL int cg_model_write(const char * ModelLabel, CGNS_ENUMT(ModelType_t) ModelType); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DataArray_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_narrays(int *narrays); CGNSDLL int cg_array_info(int A, char *ArrayName, CGNS_ENUMT(DataType_t) *DataType, int *DataDimension, cgsize_t *DimensionVector); CGNSDLL int cg_array_read(int A, void *Data); CGNSDLL int cg_array_read_as(int A, CGNS_ENUMT(DataType_t) type, void *Data); CGNSDLL int cg_array_general_read(int A, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, void *data); CGNSDLL int cg_array_write(const char * ArrayName, CGNS_ENUMT(DataType_t) DataType, int DataDimension, const cgsize_t * DimensionVector, const void * Data); CGNSDLL int cg_array_general_write(const char *arrayname, CGNS_ENUMT(DataType_t) s_type, int s_numdim, const cgsize_t *s_dimvals, const cgsize_t *s_rmin, const cgsize_t *s_rmax, CGNS_ENUMT(DataType_t) m_type, int m_numdim, const cgsize_t *m_dimvals, const cgsize_t *m_rmin, const cgsize_t *m_rmax, const void *data); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write UserDefinedData_t Nodes - new in version 2.1 * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nuser_data(int *nuser_data); CGNSDLL int cg_user_data_read(int Index, char *user_data_name); CGNSDLL int cg_user_data_write(const char * user_data_name); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write IntegralData_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nintegrals(int *nintegrals); CGNSDLL int cg_integral_read(int IntegralDataIndex, char *IntegralDataName); CGNSDLL int cg_integral_write(const char * IntegralDataName); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Rind_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_rind_read(int *RindData); CGNSDLL int cg_rind_write(const int * RindData); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Descriptor_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ndescriptors(int *ndescriptors); CGNSDLL int cg_descriptor_read(int descr_no, char *descr_name, char **descr_text); CGNSDLL int cg_descriptor_write(const char * descr_name, const char * descr_text); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DimensionalUnits_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_nunits(int *nunits); CGNSDLL int cg_units_read (CGNS_ENUMT(MassUnits_t) *mass, CGNS_ENUMT(LengthUnits_t) *length, CGNS_ENUMT(TimeUnits_t) *time, CGNS_ENUMT(TemperatureUnits_t) *temperature, CGNS_ENUMT(AngleUnits_t) *angle); CGNSDLL int cg_units_write (CGNS_ENUMT(MassUnits_t) mass, CGNS_ENUMT(LengthUnits_t) length, CGNS_ENUMT(TimeUnits_t) time, CGNS_ENUMT(TemperatureUnits_t) temperature, CGNS_ENUMT(AngleUnits_t) angle); CGNSDLL int cg_unitsfull_read (CGNS_ENUMT(MassUnits_t) *mass, CGNS_ENUMT(LengthUnits_t) *length, CGNS_ENUMT(TimeUnits_t) *time, CGNS_ENUMT(TemperatureUnits_t) *temperature, CGNS_ENUMT(AngleUnits_t) *angle, CGNS_ENUMT(ElectricCurrentUnits_t) *current, CGNS_ENUMT(SubstanceAmountUnits_t) *amount, CGNS_ENUMT(LuminousIntensityUnits_t) *intensity); CGNSDLL int cg_unitsfull_write(CGNS_ENUMT(MassUnits_t) mass, CGNS_ENUMT(LengthUnits_t) length, CGNS_ENUMT(TimeUnits_t) time, CGNS_ENUMT(TemperatureUnits_t) temperature, CGNS_ENUMT(AngleUnits_t) angle, CGNS_ENUMT(ElectricCurrentUnits_t) current, CGNS_ENUMT(SubstanceAmountUnits_t) amount, CGNS_ENUMT(LuminousIntensityUnits_t) intensity); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DimensionalExponents_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_exponents_info(CGNS_ENUMT(DataType_t) *DataType); CGNSDLL int cg_nexponents(int *numexp); CGNSDLL int cg_exponents_read(void *exponents); CGNSDLL int cg_exponents_write(CGNS_ENUMT(DataType_t) DataType, const void * exponents); CGNSDLL int cg_expfull_read(void *exponents); CGNSDLL int cg_expfull_write(CGNS_ENUMT(DataType_t) DataType, const void * exponents); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DataConversion_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_conversion_info(CGNS_ENUMT(DataType_t) *DataType); CGNSDLL int cg_conversion_read(void *ConversionFactors); CGNSDLL int cg_conversion_write(CGNS_ENUMT(DataType_t) DataType, const void * ConversionFactors); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write DataClass_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_dataclass_read(CGNS_ENUMT(DataClass_t) *dataclass); CGNSDLL int cg_dataclass_write(CGNS_ENUMT(DataClass_t) dataclass); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write GridLocation_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_gridlocation_read(CGNS_ENUMT(GridLocation_t) *GridLocation); CGNSDLL int cg_gridlocation_write(CGNS_ENUMT(GridLocation_t) GridLocation); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write Ordinal_t Nodes * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ordinal_read(int *Ordinal); CGNSDLL int cg_ordinal_write(int Ordinal); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Read and write IndexArray/Range_t Nodes - new in version 2.4 * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_ptset_info(CGNS_ENUMT(PointSetType_t) *ptset_type, cgsize_t *npnts); CGNSDLL int cg_ptset_write(CGNS_ENUMT(PointSetType_t) ptset_type, cgsize_t npnts, const cgsize_t *pnts); CGNSDLL int cg_ptset_read(cgsize_t *pnts); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Link Handling Functions - new in version 2.1 * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_is_link(int *path_length); CGNSDLL int cg_link_read(char **filename, char **link_path); CGNSDLL int cg_link_write(const char * nodename, const char * filename, const char * name_in_file); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * General Delete Function * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_delete_node(const char *node_name); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Free library malloced memory * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL int cg_free(void *data); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\ * Error Handling Functions * \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ CGNSDLL const char *cg_get_error(void); CGNSDLL void cg_error_exit(void); CGNSDLL void cg_error_print(void); #ifdef __cplusplus } #endif #endif CGNS-3.4.0/src/cgnstools/000077500000000000000000000000001343724673500150705ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/CMakeLists.txt000066400000000000000000000050341343724673500176320ustar00rootroot00000000000000############# # cgnstools # ############# # get X11 in case it is not in a standard location if (NOT WIN32) include(FindX11) # Xmu doesn't appear to be included in FindX11 find_library(X11_Xmu_LIB Xmu) if (X11_Xmu_LIB) mark_as_advanced(FORCE X11_Xmu_LIB) endif (X11_Xmu_LIB) endif (NOT WIN32) if (WIN32) include(FindHTMLHelp) endif (WIN32) include(FindTCL) include(FindOpenGL) set(Missing "") if (TCL_FOUND) mark_as_advanced(FORCE TCL_INCLUDE_PATH TCL_LIBRARY) else (TCL_FOUND) mark_as_advanced(CLEAR TCL_INCLUDE_PATH TCL_LIBRARY) list(APPEND Missing "TCL") endif (TCL_FOUND) if (TK_FOUND) mark_as_advanced(FORCE TK_INCLUDE_PATH TK_LIBRARY) else (TK_FOUND) mark_as_advanced(CLEAR TK_INCLUDE_PATH TK_LIBRARY) list(APPEND Missing "TK") endif (TK_FOUND) if (OPENGL_FOUND) mark_as_advanced(FORCE OPENGL_INCLUDE_PATH OPENGL_gl_LIBRARY) else (OPENGL_FOUND) mark_as_advanced(CLEAR OPENGL_INCLUDE_PATH OPENGL_gl_LIBRARY) list(APPEND Missing "OPENGL_gl") endif (OPENGL_FOUND) if (OPENGL_GLU_FOUND) mark_as_advanced(FORCE OPENGL_glu_LIBRARY) else (OPENGL_GLU_FOUND) mark_as_advanced(CLEAR OPENGL_glu_LIBRARY) list(APPEND Missing "OPENGL_glu") endif (OPENGL_GLU_FOUND) if (Missing) message(SEND_ERROR "The path and library needs to be defined for: ${Missing}") else (Missing) add_subdirectory(cgnsview) add_subdirectory(calclib) add_subdirectory(cgnscalc) add_subdirectory(cgnsplot) add_subdirectory(common) add_subdirectory(tkogl) add_subdirectory(utilities) endif (Missing) if (WIN32) file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX} WIN_INSTALL_DIR) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cgconfig.bat "set CG_BIN_DIR=${WIN_INSTALL_DIR}\\bin set CG_LIB_DIR=${WIN_INSTALL_DIR}\\share ") # don't need this since dll is put in the bin directory # if (CGNS_USE_SHARED) # file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/cgconfig.bat # "set PATH=${WIN_INSTALL_DIR}\\lib;%PATH%" # ) # endif (CGNS_USE_SHARED) # add Tcl path for dll's if (TK_WISH) get_filename_component(TK_DLL ${TK_WISH} PATH) file(TO_NATIVE_PATH ${TK_DLL} TK_DLL_DIR) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/cgconfig.bat "set PATH=${TK_DLL_DIR};%PATH%" ) endif (TK_WISH) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/cgconfig.bat DESTINATION bin) else (WIN32) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cgconfig "CG_BIN_DIR=${CMAKE_INSTALL_PREFIX}/bin; export CG_BIN_DIR CG_LIB_DIR=${CMAKE_INSTALL_PREFIX}/share/cgnstools; export CG_LIB_DIR ") install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/cgconfig DESTINATION bin) endif (WIN32) CGNS-3.4.0/src/cgnstools/LICENSE000066400000000000000000000014651343724673500161030ustar00rootroot00000000000000This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. CGNS-3.4.0/src/cgnstools/Makefile.in000066400000000000000000000042301343724673500171340ustar00rootroot00000000000000# makefile to build CGNS tools include make.defs DOMAKE=$(MAKE) -f Makefile.unix # if OGL was not found, cgnsplot will not be included in the # default build, otherwise this target is the same as for all default : @PROGLIST@ install : @INSTLIST@ all : cgnsview cgnscalc cgnsplot utilities install-all : install-cgnsview install-cgnscalc install-cgnsplot \ install-utilities clean : @for d in cgnsview cgnscalc cgnsplot utilities calclib tkogl ; do \ echo "----- $$d -----"; \ cd $$d; $(DOMAKE) clean; cd ..; \ done; allclean : distclean distclean : clean -@$(RM) config.* -@$(RM) make.defs Makefile cgconfig cgnsview : prog-cgnsview cgnscalc : prog-cgnscalc cgnsplot : prog-cgnsplot utilities : prog-utilities uninstall : @for d in cgnsview cgnscalc cgnsplot utilities ; do \ echo "----- $$d -----"; \ cd $$d; $(DOMAKE) uninstall; cd ..; \ done; @if [ -f $(EXE_INSTALL_DIR)/cgconfig ] ; then \ /bin/rm -f $(EXE_INSTALL_DIR)/cgconfig; \ fi; -@if [ -d $(WSH_INSTALL_DIR) ] ; then \ rmdir $(WSH_INSTALL_DIR); \ fi; -@if [ -d $(EXE_INSTALL_DIR) -a \ ! $(EXE_INSTALL_DIR) = $(BIN_INSTALL_DIR) ] ; then \ rmdir $(EXE_INSTALL_DIR); \ fi; -@if [ -d $(LIB_INSTALL_DIR)/help ] ; then \ rmdir $(LIB_INSTALL_DIR)/help; \ fi; -@if [ -d $(LIB_INSTALL_DIR) ] ; then \ rmdir $(LIB_INSTALL_DIR); \ fi; prog-cgnsview : @echo "----- cgnsview -----" @cd cgnsview && $(DOMAKE) prog-cgnscalc : lib-calclib @echo "----- cgnscalc -----" @cd cgnscalc && $(DOMAKE) prog-cgnsplot : lib-tkogl @echo "----- cgnsplot -----" @cd cgnsplot && $(DOMAKE) prog-utilities : lib-calclib @echo "----- utilities -----" @cd utilities && $(DOMAKE) lib-calclib : @echo "----- calclib -----" @cd calclib && $(DOMAKE) lib-tkogl : @echo "----- tkogl -----" @cd tkogl && $(DOMAKE) install-cgnsview : @echo "----- cgnsview -----" @cd cgnsview && $(DOMAKE) install install-cgnscalc : lib-calclib @echo "----- cgnscalc -----" @cd cgnscalc && $(DOMAKE) install install-cgnsplot : lib-tkogl @echo "----- cgnsplot -----" @cd cgnsplot && $(DOMAKE) install install-utilities : lib-calclib @echo "----- utilities -----" @cd utilities && $(DOMAKE) install CGNS-3.4.0/src/cgnstools/calclib/000077500000000000000000000000001343724673500164615ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/calclib/CMakeLists.txt000066400000000000000000000002141343724673500212160ustar00rootroot00000000000000########### # calclib # ########### set(calclib_FILES calc.c vec.c vecsym.c) add_library(calclib STATIC ${calclib_FILES}) # Add test CGNS-3.4.0/src/cgnstools/calclib/Makefile.unix000066400000000000000000000016501343724673500211050ustar00rootroot00000000000000# Makefile for Unix/Linux include ../make.defs CALCLIB = libcgnscalc.$(A) COPTS = $(CFLAGS) $(CALCOPTS) -I$(CGNSDIR) lib : $(CALCLIB) all : $(CALCLIB) calctest$(EXE) install : $(CALCLIB) #---------------------------------------------------- $(CALCLIB) : calc.$(O) vec.$(O) vecsym.$(O) $(AR) $@ calc.$(O) vec.$(O) vecsym.$(O) $(RANLIB) $@ #---------------------------------------------------- calctest$(EXE) : calctest.$(O) $(CALCLIB) $(CC) $(LDFLAGS) -o $@ calctest.$(O) $(CALCLIB) \ $(CGNSLIB) $(BUILDLIBS) -lm $(STRIP) $@ calctest.$(O) : calctest.c #--------------------------------------------------- calc.$(O) : calc.c calc.h vecerr.h vec.$(O) : vec.c vec.h vecsym.h vecerr.h vecsym.$(O) : vecsym.c vec.h vecsym.h calc.h : vecsym.h vecsym.h : vec.h #--------------------------------------------------------------- .c.$(O) : $(CC) $(COPTS) -c $< clean: -$(RM) $(CALCLIB) *.$(O) *~ *.bak calctest$(EXE) CGNS-3.4.0/src/cgnstools/calclib/Makefile.win000066400000000000000000000017431343724673500207220ustar00rootroot00000000000000include ..\make.win CALCLIB = cgnscalc.lib COPTS = $(CFLAGS) -I$(CGNSDIR) READ_NODE = -DREAD_NODE lib : $(CALCLIB) all : $(CALCLIB) calctest.exe install : $(CALCLIB) #-------------------------------------------------- $(CALCLIB) : calc.obj vec.obj vecsym.obj $(LINK) /lib /out:$@ calc.obj vec.obj vecsym.obj #-------------------------------------------------- calctest.exe : calctest.obj $(CALCLIB) $(LINK) $(LFLAGS) /out:$@ calctest.obj $(CALCLIB) \ $(CGNSLIB) $(BUILDLIBS) $(CLIBS) calctest.obj : calctest.c #-------------------------------------------------- vec.obj : vec.c vec.h vecsym.h vecerr.h $(CC) $(COPTS) $(MATHERR) -c vec.c vecsym.obj : vecsym.c vec.h vecsym.h calc.obj : calc.c calc.h vecerr.h $(CC) $(COPTS) $(READ_NODE) -c calc.c calc.h : vecsym.h vecsym.h : vec.h #-------------------------------------------------- .c.obj : $(CC) $(COPTS) -Fo$@ -c $< clean: -$(RM) *.obj -$(RM) *.lib -$(RM) *.pdb -$(RM) *.ilk -$(RM) *.bak -$(RM) *.exe CGNS-3.4.0/src/cgnstools/calclib/calc.c000066400000000000000000001144131343724673500175330ustar00rootroot00000000000000#include #include #include #include #include #include "cgnslib.h" #include "calc.h" #include "vecerr.h" #if CGNS_VERSION < 3000 # define Celsius Celcius #endif #ifndef CG_MODE_READ # define CG_MODE_READ MODE_READ # define CG_MODE_MODIFY MODE_MODIFY #endif #ifdef READ_NODE #include "cgns_header.h" #include "cgns_io.h" #endif #ifndef CGNSTYPES_H # define cgsize_t int # define cglong_t long # define cgulong_t unsigned long #endif #ifndef CGNS_ENUMT # define CGNS_ENUMT(e) e # define CGNS_ENUMV(e) e #endif #ifndef CG_MAX_INT32 # define CG_MAX_INT32 0x7FFFFFFF #endif int cgnsFile = 0; /*--- base data ---*/ int NumBases = 0; int cgnsBase; char BaseName[33]; int CellDim, PhyDim; int BaseClass, BaseUnits[5]; /*--- zone data ---*/ int NumZones = 0; int cgnsZone; char ZoneName[33]; int ZoneType; int ZoneDims[6]; int ZoneClass, ZoneUnits[5]; int GridClass, GridUnits[5]; /*--- solution data ---*/ int NumSolns = 0; int cgnsSoln; char SolnName[33]; int SolnLocation; int SolnDims[3], SolnRind[6]; int SolnClass, SolnUnits[5]; /*--- field data ---*/ int NumReference = 0; Variable *reference; int NumCoordinates = 0; Variable *coordinates; int NumVariables = 0; Variable *variables; /*--- local variables ---*/ static int cmdstrlen = 0; static char *cmdstr; static int VectorLen = 100; /* unit specifications */ typedef struct { char *name; int type; int value; } UnitSpec; static UnitSpec unitspec[] = { {"cel", 3, CGNS_ENUMV(Celsius}), {"cen", 1, CGNS_ENUMV(Centimeter}), {"cm", 1, CGNS_ENUMV(Centimeter}), {"c", 3, CGNS_ENUMV(Celsius}), {"d", 4, CGNS_ENUMV(Degree}), {"fa", 3, CGNS_ENUMV(Fahrenheit}), {"fo", 1, CGNS_ENUMV(Foot}), {"ft", 1, CGNS_ENUMV(Foot}), {"f", 3, CGNS_ENUMV(Fahrenheit}), {"g", 0, CGNS_ENUMV(Gram}), {"in", 1, CGNS_ENUMV(Inch}), {"ke", 3, CGNS_ENUMV(Kelvin}), {"ki", 0, CGNS_ENUMV(Kilogram}), {"kg", 0, CGNS_ENUMV(Kilogram}), {"k", 3, CGNS_ENUMV(Kelvin}), {"lb", 0, CGNS_ENUMV(PoundMass}), {"me", 1, CGNS_ENUMV(Meter}), {"mi", 1, CGNS_ENUMV(Millimeter}), {"mm", 1, CGNS_ENUMV(Millimeter}), {"m", 1, CGNS_ENUMV(Meter}), {"p", 0, CGNS_ENUMV(PoundMass}), {"rad", 4, CGNS_ENUMV(Radian}), {"ran", 3, CGNS_ENUMV(Rankine}), {"r", 3, CGNS_ENUMV(Rankine}), {"se", 2, CGNS_ENUMV(Second}), {"sl", 0, CGNS_ENUMV(Slug}), {"s", 2, CGNS_ENUMV(Second}) }; #define NUM_UNITSPEC (sizeof(unitspec)/sizeof(UnitSpec)) /*---------- read_node --------------------------------------------- * read a node from the CGNS file *------------------------------------------------------------------*/ #ifdef READ_NODE static VECDATA *read_node (char *nodename) { cgns_file *cgfile; int n, bytes, dt, cgio; int ndim; cgsize_t np, dims[CGIO_MAX_DIMENSIONS]; char *values; char type[CGIO_MAX_DATATYPE_LENGTH+1]; char errmsg[CGIO_MAX_ERROR_LENGTH+1]; double rootid, nodeid; VECDATA *vd; static struct dataTypes { char *name; int bytes; } data_types[6] = { {"I4", 4}, {"I8", 8}, {"U4", 4}, {"U8", 8}, {"R4", 4}, {"R8", 8} }; /* get node ID for node */ cgfile = cgi_get_file (cgnsFile); cgio = cgfile->cgio; rootid = cgfile->rootid; if (cgio_get_node_id (cgio, rootid, nodename, &nodeid)) { cgio_error_message (errmsg); cgnsCalcFatal (errmsg); } /* get the type of data */ if (cgio_get_data_type (cgio, nodeid, type)) { cgio_error_message (errmsg); cgnsCalcFatal (errmsg); } for (n = 0; n < CGIO_MAX_DATATYPE_LENGTH && type[n]; n++) { if (islower (type[n])) type[n] = toupper (type[n]); } for (bytes = 0, dt = 0; dt < 6; dt++) { if (0 == strncmp (type, data_types[dt].name, 2)) { bytes = data_types[dt].bytes; break; } } if (bytes == 0) { sprintf (errmsg, "can't handle data type %s", type); cgnsCalcFatal (errmsg); } /* get data dimensions */ if (cgio_get_dimensions (cgio, nodeid, &ndim, dims)) { cgio_error_message (errmsg); cgnsCalcFatal (errmsg); } np = 0; if (ndim > 0) { for (np = 1, n = 0; n < ndim; n++) np *= dims[n]; } if (np == 0) cgnsCalcFatal ("no data for node"); if (np > CG_MAX_INT32) cgnsCalcFatal ("exceeded 32-bit integer"); /* read the data */ values = (char *) malloc ((size_t)(np * bytes)); if (NULL == values) cgnsCalcFatal ("malloc failed for node data"); if (cgio_read_all_data (cgio, nodeid, values)) { cgio_error_message (errmsg); cgnsCalcFatal (errmsg); } if (np == 1) { vd = vec_create (VEC_VALUE, 0, 1); if (dt == 0) { int *data = (int *)values; vd->f.val = (VECFLOAT)*data; } else if (dt == 1) { cglong_t *data = (cglong_t *)values; vd->f.val = (VECFLOAT)*data; } else if (dt == 2) { unsigned int *data = (unsigned int *)values; vd->f.val = (VECFLOAT)*data; } else if (dt == 3) { cgulong_t *data = (cgulong_t *)values; vd->f.val = (VECFLOAT)*data; } else if (dt == 4) { float *data = (float *)values; vd->f.val = (VECFLOAT)*data; } else { double *data = (double *)values; vd->f.val = (VECFLOAT)*data; } } else { vd = vec_create (VEC_VECTOR, (int)np, 1); if (dt == 0) { int *data = (int *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } else if (dt == 1) { cglong_t *data = (cglong_t *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } else if (dt == 2) { unsigned int *data = (unsigned int *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } else if (dt == 3) { cgulong_t *data = (cgulong_t *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } else if (dt == 4) { float *data = (float *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } else { double *data = (double *)values; for (n = 0; n < np; n++) vd->f.vec[n] = (VECFLOAT)data[n]; } } free (values); return vd; } #endif /*---------- read_units ----------------------------------------------- * read unit specifications *---------------------------------------------------------------------*/ static int read_units (int units[5]) { int n; CGNS_ENUMT(MassUnits_t) mass; CGNS_ENUMT(LengthUnits_t) length; CGNS_ENUMT(TimeUnits_t) time; CGNS_ENUMT(TemperatureUnits_t) temp; CGNS_ENUMT(AngleUnits_t) angle; if (cg_units_read (&mass, &length, &time, &temp, &angle)) { for (n = 0; n < 5; n++) units[n] = 0; return 0; } units[0] = mass; units[1] = length; units[2] = time; units[3] = temp; units[4] = angle; return 1; } /*---------- read_class ----------------------------------------------- * get data class, units and conversion factors *---------------------------------------------------------------------*/ static void read_class (Variable *var, int dataclass, int units[5]) { int i; CGNS_ENUMT(DataType_t) datatype; if (cg_dataclass_read ((CGNS_ENUMT(DataClass_t) *)&var->dataclass)) var->dataclass = dataclass; var->hasunits = read_units (var->units); if (!var->hasunits) { for (i = 0; i < 5; i++) var->units[i] = units[i]; } if (cg_conversion_info (&datatype) || (datatype != CGNS_ENUMV(RealSingle) && datatype != CGNS_ENUMV(RealDouble))) { var->hasconv = 0; var->dataconv[0] = 1.0; var->dataconv[1] = 0.0; } else { var->hasconv = datatype; if (datatype == CGNS_ENUMV(RealSingle)) { float conv[2]; if (cg_conversion_read (conv)) cgnsCalcFatal ((char *)cg_get_error()); for (i = 0; i < 2; i++) var->dataconv[i] = conv[i]; } else { if (cg_conversion_read (var->dataconv)) cgnsCalcFatal ((char *)cg_get_error()); } } if (cg_exponents_info (&datatype) || (datatype != CGNS_ENUMV(RealSingle) && datatype != CGNS_ENUMV(RealDouble))) { var->hasexp = 0; for (i = 0; i < 5; i++) var->exponent[i] = 0.0; } else { var->hasexp = datatype; if (datatype == CGNS_ENUMV(RealSingle)) { float exp[5]; if (cg_exponents_read (exp)) cgnsCalcFatal ((char *)cg_get_error()); for (i = 0; i < 5; i++) var->exponent[i] = exp[i]; } else { if (cg_exponents_read (var->exponent)) cgnsCalcFatal ((char *)cg_get_error()); } } } /*---------- read_reference -------------------------------------------- * read reference conditions *----------------------------------------------------------------------*/ static void read_reference (void) { int n, narrays, na, dim; cgsize_t vec[12]; CGNS_ENUMT(DataType_t) datatype; char name[33]; NumReference = 0; if (cg_goto (cgnsFile, cgnsBase, "ReferenceState_t", 1, "end") || cg_narrays (&narrays) || narrays < 1) return; for (na = 1; na <= narrays; na++) { if (cg_array_info (na, name, &datatype, &dim, vec)) cgnsCalcFatal ((char *)cg_get_error()); if (datatype != CGNS_ENUMV(Character) && dim >= 1 && vec[0] >= 1) NumReference++; } if (!NumReference) return; reference = (Variable *) malloc (NumReference * sizeof(Variable)); if (NULL == reference) cgnsCalcFatal ("malloc failed for reference variables"); for (n = 0, na = 1; na <= narrays; na++) { if (cg_array_info (na, name, &datatype, &dim, vec)) cgnsCalcFatal ((char *)cg_get_error()); if (datatype != CGNS_ENUMV(Character) && dim >= 1 && vec[0] >= 1) { dim *= vec[0]; strcpy (reference[n].name, name); reference[n].type = 0; reference[n].id = na; reference[n].len = dim; reference[n].valid = 1; reference[n].datatype = datatype; if (dim == 1) { reference[n].vd = vec_create (VEC_VALUE, 0, 0); if (cg_array_read_as (na, CGNS_ENUMV(RealDouble), &reference[n].vd->f.val)) cgnsCalcFatal ((char *)cg_get_error()); } else { reference[n].vd = vec_create (VEC_VECTOR, dim, 0); if (cg_array_read_as (na, CGNS_ENUMV(RealDouble), reference[n].vd->f.vec)) cgnsCalcFatal ((char *)cg_get_error()); } if (cg_goto (cgnsFile, cgnsBase, "ReferenceState_t", 1, "DataArray_t", na, "end")) cgnsCalcFatal ((char *)cg_get_error()); read_class (&reference[n], BaseClass, BaseUnits); cg_goto (cgnsFile, cgnsBase, "ReferenceState_t", 1, "end"); n++; } } } /*---------- get_variable ---------------------------------------------- * return variable data - read if neccessary *----------------------------------------------------------------------*/ static VECDATA *get_variable (Variable *var) { if (var->vd == NULL) { int n; cgsize_t min[3], max[3]; for (n = 0; n < 3; n++) { min[n] = 1; max[n] = SolnDims[n]; } var->vd = vec_create (VEC_VECTOR, var->len, 0); if (cg_field_read (cgnsFile, cgnsBase, cgnsZone, cgnsSoln, var->name, CGNS_ENUMV(RealDouble), min, max, var->vd->f.vec)) cgnsCalcFatal ((char *)cg_get_error()); } return var->vd; } /*---------- get_coordinate -------------------------------------------- * return coordinate data - read if neccessary *----------------------------------------------------------------------*/ static VECDATA *get_coordinate (Variable *var) { if (var->vd == NULL) { int n; cgsize_t min[3], max[3]; for (n = 0; n < 3; n++) { min[n] = 1; max[n] = ZoneDims[n]; } var->vd = vec_create (VEC_VECTOR, var->len, 0); if (cg_coord_read (cgnsFile, cgnsBase, cgnsZone, var->name, CGNS_ENUMV(RealDouble), min, max, var->vd->f.vec)) cgnsCalcFatal ((char *)cg_get_error()); } return var->vd; } /*---------- print_error --------------------------------------------- * print error message on parsing error *--------------------------------------------------------------------*/ static void print_error (int errnum, char *errmsg, int pos, char *str) { printf (errnum < 0 ? "FATAL:" : "ERROR:"); if (NULL != str) { printf ("%s\n ", str); while (pos-- > 0) putchar ('-'); putchar ('^'); } printf ("%s\n", errmsg); } /*---------- get_name ----------------------------------------------- * get symbol name from string *-------------------------------------------------------------------*/ static char *get_name (char **str) { int n; char *p = *str; static char name[SYMNAME_MAXLEN+1]; if (*p == '"') { for (++p, n = 0; n < SYMNAME_MAXLEN && *p; n++) { if (*p == '"') break; name[n] = *p++; } if (*p++ != '"') return NULL; } else if (!isalpha (*p) && *p != '_') return (NULL); else { for (n = 0; n < SYMNAME_MAXLEN && *p; n++) { if (!isalnum(*p) && *p != '_') break; name[n] = *p++; } } name[n] = 0; *str = p; return name; } /*---------- print_symbols ------------------------------------------ * print symbol names *-------------------------------------------------------------------*/ static int print_symbols (VECSYM *sym, void *data) { FILE *fp = (FILE *)data; if (VECSYM_EQUSTR == vecsym_type(sym)) fprintf (fp, "%s{%d}\n", vecsym_name(sym), vecsym_nargs(sym)); else if (VECSYM_MACRO == vecsym_type(sym)) fprintf (fp, "%s<%d>\n", vecsym_name(sym), vecsym_nargs(sym)); else if (VECSYM_FUNC == vecsym_type(sym)) { if (vecsym_nargs(sym) < 0) fprintf (fp, "%s(...)\n", vecsym_name(sym)); else fprintf (fp, "%s(%d)\n", vecsym_name(sym), vecsym_nargs(sym)); } else if (VECSYM_VECTOR == vecsym_type(sym)) fprintf (fp, "%s[%ld]\n", vecsym_name(sym), (long)vecsym_veclen(sym)); else fprintf (fp, "%s\n", vecsym_name(sym)); return 0; } /*---------- delete_units ------------------------------------------- * called when symbol deleted *-------------------------------------------------------------------*/ static void delete_units (VECSYM *sym) { if (vecsym_user(sym) != NULL) free (vecsym_user(sym)); } /*---------- callback ----------------------------------------------- * callback function for vector parser *-------------------------------------------------------------------*/ static VECDATA *callback (int check, char **pp, char **err) { int n, type = 0; char *p = *pp, *name; /* check for reading node data */ #ifdef READ_NODE if (*p == '{') { char nodename[257]; for (n = 0; n < 256; n++) { if (!*++p || *p == '}') break; nodename[n] = *p; } if (n == 256) { *err = "internal node name length exceeded"; return NULL; } if (!n || *p != '}') { *err = "incomplete node name specification"; return NULL; } *pp = ++p; return read_node (nodename); } #endif /* check for reference or coordinate data */ if (*p == '~' || *p == '\'') type = *p++; /* get name */ if ((name = get_name (&p)) != NULL) { /* check for variable */ if (!type) { for (n = 0; n < NumVariables; n++) { if (0 == strcmp (variables[n].name, name)) { *pp = p; return get_variable (&variables[n]); } } } /* check for grid coordinates */ if (type != '~') { for (n = 0; n < NumCoordinates; n++) { if (0 == strcmp (coordinates[n].name, name)) { *pp = p; return get_coordinate (&coordinates[n]); } } } /* check for reference quantity */ if (type != '\'') { for (n = 0; n < NumReference; n++) { if (0 == strcmp (reference[n].name, name)) { *pp = p; return reference[n].vd; } } } } return (NULL); } /*---------- parse_units ------------------------------------------- * get unit specification *------------------------------------------------------------------*/ static Units *parse_units (char **pp) { int n, par, div; char *p = *pp, name[33]; float exp; Units units, *u; UnitSpec *us; for (n = 0; n < 5; n++) { units.units[n] = 0; units.exps[n] = 0.0; } par = div = 0; while (1) { while (*p && isspace (*p)) p++; if (*p == '*' || *p == '-') { p++; continue; } if (*p == '/') { div++; p++; continue; } if (*p == '(') { par++; p++; continue; } if (*p == ')') { if (!par--) return NULL; if (div) div--; p++; continue; } n = 0; while (*p && isalpha (*p)) { if (n < 32) name[n++] = tolower (*p); p++; } if (!n) break; name[n] = 0; for (n = 0; n < NUM_UNITSPEC; n++) { if (name[0] == unitspec[n].name[0]) break; } us = NULL; while (n < NUM_UNITSPEC) { if (name[0] != unitspec[n].name[0]) break; if (!strncmp (name, unitspec[n].name, strlen(unitspec[n].name))) { us = &unitspec[n]; break; } n++; } if (us == NULL) return NULL; while (*p && isspace (*p)) p++; if (*p == '^') { if (1 != sscanf (++p, "%f%n", &exp, &n)) return NULL; for (p += n; *p && isspace(*p); p++) ; } else exp = 1.0; units.units[us->type] = us->value; if (div) { units.exps[us->type] -= exp; if (*p != '-' && div > par) div--; } else units.exps[us->type] += exp; } u = (Units *) malloc (sizeof(Units)); if (u == NULL) cgnsCalcFatal ("malloc failed for unit specification"); for (n = 0; n < 5; n++) { u->units[n] = units.units[n]; u->exps[n] = units.exps[n]; } *pp = p; return u; } /*---------- free_all ---------------------------------------------- * free all data *------------------------------------------------------------------*/ static void free_all (void) { int n; if (NumReference) { for (n = 0; n < NumReference; n++) vec_destroy (reference[n].vd); free (reference); NumReference = 0; } if (NumCoordinates) { for (n = 0; n < NumCoordinates; n++) vec_destroy (coordinates[n].vd); free (coordinates); NumCoordinates = 0; } if (NumVariables) { for (n = 0; n < NumVariables; n++) vec_destroy (variables[n].vd); free (variables); NumVariables = 0; } } /*---------- cgnsCalcFatal ----------------------------------------- * terminate with error message *------------------------------------------------------------------*/ void cgnsCalcFatal (char *errmsg) { cgnsCalcDone (); if (NULL != errmsg && *errmsg) { if (NULL == vec_errhandler) print_error (-1, errmsg, 0, NULL); else (*vec_errhandler) (-1, errmsg, 0, NULL); } exit (-1); } /*---------- cgnsCalcError ----------------------------------------- * print error message *------------------------------------------------------------------*/ void cgnsCalcError (char *errmsg) { if (NULL != errmsg && *errmsg) { if (NULL == vec_errhandler) print_error (0, errmsg, 0, NULL); else (*vec_errhandler) (0, errmsg, 0, NULL); } } /*---------- cgnsCalcReset ----------------------------------------- * reset calculator (symbol table) *------------------------------------------------------------------*/ void cgnsCalcReset (void) { sym_free (); #ifdef EXTERN_FUNCS add_funcs (); #endif VectorLen = 100; } /*---------- cgnsCalcInit ------------------------------------------ * load CGNS file and initialize *------------------------------------------------------------------*/ int cgnsCalcInit (char *cgnsfile, int modify, void (*errhandler)(int,char *,int,char *)) { cgnsCalcDone (); /* set up error handler */ if (NULL == errhandler) vec_errhandler = print_error; else vec_errhandler = errhandler; /* callback to delete unit data */ sym_delfunc = delete_units; /* open CGNS file */ if (modify) { if (cg_open (cgnsfile, CG_MODE_MODIFY, &cgnsFile)) cgnsCalcFatal ("couldn't open file in modify mode"); } else { if (cg_open (cgnsfile, CG_MODE_READ, &cgnsFile)) cgnsCalcFatal ("couldn't open file in read mode"); } if (cg_nbases (cgnsFile, &NumBases)) cgnsCalcFatal ((char *)cg_get_error()); if (NumBases < 1) cgnsCalcFatal ("no bases found in CGNS file"); cgnsCalcBase (1); /* return number of bases */ return NumBases; } /*---------- cgnsCalcDone ------------------------------------------ * close CGNS file *------------------------------------------------------------------*/ void cgnsCalcDone (void) { if (cgnsFile) { cg_close (cgnsFile); cgnsFile = 0; } free_all (); cgnsBase = NumBases = 0; cgnsZone = NumZones = 0; cgnsSoln = NumSolns = 0; } /*---------- cgnsCalcBase ------------------------------------------ * set base for calculations *------------------------------------------------------------------*/ int cgnsCalcBase (int base) { if (base < 1 || base > NumBases) cgnsCalcFatal ("invalid base specified"); if (cg_base_read (cgnsFile, base, BaseName, &CellDim, &PhyDim)) cgnsCalcFatal ((char *)cg_get_error()); free_all (); cgnsBase = base; cgnsZone = NumZones = 0; cgnsSoln = NumSolns = 0; /* read base class and units */ if (cg_goto (cgnsFile, cgnsBase, "end")) cgnsCalcFatal ((char *)cg_get_error()); if (cg_dataclass_read ((CGNS_ENUMT(DataClass_t) *)&BaseClass)) BaseClass = 0; read_units (BaseUnits); /* read reference conditions */ read_reference (); /* get number of zones and initilize */ if (cg_nzones (cgnsFile, cgnsBase, &NumZones)) cgnsCalcFatal ((char *)cg_get_error()); if (NumZones) cgnsCalcZone (1); return NumZones; } /*---------- cgnsCalcZone ------------------------------------------ * set zone for calculations *------------------------------------------------------------------*/ int cgnsCalcZone (int zone) { int n, nc, size = 1; cgsize_t dims[9]; CGNS_ENUMT(DataType_t) datatype; char name[33]; if (zone < 1 || zone > NumZones) cgnsCalcFatal ("invalid zone specified"); if (cg_zone_read (cgnsFile, cgnsBase, zone, ZoneName, dims) || cg_zone_type (cgnsFile, cgnsBase, zone, (CGNS_ENUMT(ZoneType_t) *)&ZoneType)) cgnsCalcFatal ((char *)cg_get_error()); cgnsZone = zone; cgnsSoln = NumSolns = 0; for (n = 0; n < 6; n++) ZoneDims[n] = 1; if (ZoneType == CGNS_ENUMV(Structured)) { for (n = 0; n < CellDim; n++) { ZoneDims[n] = dims[n]; ZoneDims[n+3] = dims[n+CellDim]; size *= dims[n]; } } else if (ZoneType == CGNS_ENUMV(Unstructured)) { ZoneDims[0] = dims[0]; ZoneDims[3] = dims[1]; size = dims[0]; } else cgnsCalcFatal ("invalid zone type"); VectorLen = size; /* free-up previous data */ if (NumCoordinates) { for (n = 0; n < NumCoordinates; n++) vec_destroy (coordinates[n].vd); free (coordinates); NumCoordinates = 0; } if (NumVariables) { for (n = 0; n < NumVariables; n++) vec_destroy (variables[n].vd); free (variables); NumVariables = 0; } /* read zone class and units */ if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "end")) cgnsCalcFatal ((char *)cg_get_error()); if (cg_dataclass_read ((CGNS_ENUMT(DataClass_t) *)&ZoneClass)) ZoneClass = BaseClass; if (!read_units (ZoneUnits)) { for (n = 0; n < 5; n++) ZoneUnits[n] = BaseUnits[n]; } GridClass = ZoneClass; for (n = 0; n < 5; n++) GridUnits[n] = ZoneUnits[n]; /* get coordinate info */ if (cg_ncoords (cgnsFile, cgnsBase, cgnsZone, &nc)) cgnsCalcFatal ((char *)cg_get_error()); if (nc > 0) { /* read grid class and units */ if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "GridCoordinates_t", 1, "end")) cgnsCalcFatal ((char *)cg_get_error()); if (cg_dataclass_read ((CGNS_ENUMT(DataClass_t) *)&GridClass)) GridClass = ZoneClass; if (!read_units (GridUnits)) { for (n = 0; n < 5; n++) GridUnits[n] = ZoneUnits[n]; } /* read coordinates */ NumCoordinates = nc; coordinates = (Variable *) malloc (NumCoordinates * sizeof(Variable)); if (NULL == coordinates) cgnsCalcFatal ("malloc failed for coordinate info"); for (n = 0; n < NumCoordinates; n++) { if (cg_coord_info (cgnsFile, cgnsBase, cgnsZone, n+1, &datatype, name)) cgnsCalcFatal ((char *)cg_get_error()); strcpy (coordinates[n].name, name); coordinates[n].type = 1; coordinates[n].id = n + 1; coordinates[n].len = size; coordinates[n].valid = 1; coordinates[n].datatype = datatype; if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "GridCoordinates_t", 1, "DataArray_t", n+1, "end")) cgnsCalcFatal ((char *)cg_get_error()); read_class (&coordinates[n], GridClass, GridUnits); coordinates[n].vd = NULL; } } /* get number of solutions and initilize */ if (cg_nsols (cgnsFile, cgnsBase, cgnsZone, &NumSolns)) cgnsCalcFatal ((char *)cg_get_error()); if (NumSolns) cgnsCalcSoln (1); return NumSolns; } /*---------- cgnsCalcSoln ------------------------------------------ * set solution for calculations *------------------------------------------------------------------*/ int cgnsCalcSoln (int soln) { int i, n, size, nflds; CGNS_ENUMT(DataType_t) datatype; char name[33]; if (soln < 1 || soln > NumSolns) cgnsCalcFatal ("invalid solution specified"); if (cg_sol_info (cgnsFile, cgnsBase, cgnsZone, soln, SolnName, (CGNS_ENUMT(GridLocation_t) *)&SolnLocation)) cgnsCalcFatal ((char *)cg_get_error()); cgnsSoln = soln; for (n = 0; n < 3; n++) SolnDims[n] = 1; if (ZoneType == CGNS_ENUMV(Structured)) { size = 1; if (SolnLocation == CGNS_ENUMV(CellCenter)) { if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "FlowSolution_t", cgnsSoln, "end")) cgnsCalcFatal ((char *)cg_get_error()); if (cg_rind_read (SolnRind)) { for (n = 0; n < 6; n++) SolnRind[n] = 0; } for (i = 0, n = 0; n < CellDim; n++, i += 2) { SolnDims[n] = ZoneDims[n] - 1 + SolnRind[i] + SolnRind[i+1]; size *= SolnDims[n]; } } else { for (n = 0; n < 6; n++) SolnRind[n] = 0; for (n = 0; n < CellDim; n++) { SolnDims[n] = ZoneDims[n]; size *= SolnDims[n]; } } } else { for (n = 0; n < 6; n++) SolnRind[n] = 0; size = SolnLocation == CGNS_ENUMV(CellCenter) ? ZoneDims[3] : ZoneDims[0]; SolnDims[0] = size; } VectorLen = size; /* free-up previous data */ if (NumVariables) { for (n = 0; n < NumVariables; n++) vec_destroy (variables[n].vd); free (variables); NumVariables = 0; } /* read solution class and units */ if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "FlowSolution_t", cgnsSoln, "end")) cgnsCalcFatal ((char *)cg_get_error()); if (cg_dataclass_read ((CGNS_ENUMT(DataClass_t) *)&SolnClass)) SolnClass = ZoneClass; if (!read_units (SolnUnits)) { for (n = 0; n < 5; n++) SolnUnits[n] = ZoneUnits[n]; } /* get field info */ if (cg_nfields (cgnsFile, cgnsBase, cgnsZone, cgnsSoln, &nflds)) cgnsCalcFatal ((char *)cg_get_error()); if (nflds > 0) { NumVariables = nflds; variables = (Variable *) malloc (NumVariables * sizeof(Variable)); if (NULL == variables) cgnsCalcFatal ("malloc failed for field info"); for (n = 0; n < NumVariables; n++) { if (cg_field_info (cgnsFile, cgnsBase, cgnsZone, cgnsSoln, n+1, &datatype, name)) cgnsCalcFatal ((char *)cg_get_error()); strcpy (variables[n].name, name); variables[n].type = 2; variables[n].id = n + 1; variables[n].len = size; variables[n].valid = 1; variables[n].datatype = datatype; if (cg_goto (cgnsFile, cgnsBase, "Zone_t", cgnsZone, "FlowSolution_t", cgnsSoln, "DataArray_t", n+1, "end")) cgnsCalcFatal ((char *)cg_get_error()); read_class (&variables[n], SolnClass, SolnUnits); variables[n].vd = NULL; } } return NumVariables; } /*---------- cgnsCalcCheck ----------------------------------------- * check expression *------------------------------------------------------------------*/ int cgnsCalcCheck (char *expression) { int length = (int)strlen (expression); char *p, *cmd, *name; Units *units; if (length > cmdstrlen) { if (cmdstrlen == 0) { cmdstrlen = length > 256 ? length : 256; cmdstr = (char *) malloc (cmdstrlen + 1); } else { cmdstrlen = length + 32; cmdstr = (char *) realloc (cmdstr, cmdstrlen + 1); } if (cmdstr == NULL) cgnsCalcFatal ("malloc failed for cmdstr"); } cmd = strcpy (cmdstr, expression); for (p = cmd + strlen(cmd) - 1; p >= cmd && isspace(*p); p--) ; *++p = 0; while (*cmd && isspace(*cmd)) cmd++; if (!*cmd) return (0); p = cmd; if ((name = get_name (&p)) != NULL) { int nargs = -1; char *equ; for (equ = p; *equ && isspace(*equ); equ++) ; /* check for units */ if ('[' == *equ) { equ++; units = parse_units (&equ); if (units == NULL || *equ != ']') { cgnsCalcError ("bad units specification"); if (units != NULL) free (units); return 0; } free (units); while (*++equ && isspace (*equ)) ; if (!*equ) { if (find_symbol (name, 0) != NULL) return 1; } } /* check for equation */ if ('(' == *equ) { char *arg = equ; while (*++arg && (isspace (*arg) || isdigit(*arg))) ; if (')' == *arg) { nargs = atoi (equ + 1); for (equ = arg+1; *equ && isspace (*equ); equ++) ; } } if ('=' == *equ && '=' != *++equ) { for (cmd = equ; *cmd && isspace(*cmd); cmd++) ; if (nargs > 9) { cgnsCalcError ("invalid number of equation arguments"); return 0; } } } return vec_check (cmd, VectorLen, callback); } /*---------- cgnsCalcCommand --------------------------------------- * parse expression and return results *------------------------------------------------------------------*/ VECSYM *cgnsCalcCommand (char *expression) { int n, length = (int)strlen (expression); char *p, *cmd, *name, sym[SYMNAME_MAXLEN+1]; VECDATA *vd; Units *units = NULL; if (length > cmdstrlen) { if (cmdstrlen == 0) { cmdstrlen = length > 256 ? length : 256; cmdstr = (char *) malloc (cmdstrlen + 1); } else { cmdstrlen = length + 32; cmdstr = (char *) realloc (cmdstr, cmdstrlen + 1); } if (cmdstr == NULL) cgnsCalcFatal ("malloc failed for cmdstr"); } cmd = strcpy (cmdstr, expression); /* skip leading and trailing space */ for (p = cmd + strlen(cmd) - 1; p >= cmd && isspace(*p); p--) ; *++p = 0; while (*cmd && isspace(*cmd)) cmd++; /* empty string */ if (!*cmd) return (NULL); /* check for defining a new symbol */ p = cmd; strcpy (sym, "_temp_"); if ((name = get_name (&p)) != NULL) { int nargs = -1; char *equ; for (equ = p; *equ && isspace(*equ); equ++) ; /* check for units */ if ('[' == *equ) { equ++; units = parse_units (&equ); if (units == NULL || *equ != ']') { cgnsCalcError ("bad units specification"); if (units != NULL) free (units); return (NULL); } while (*++equ && isspace (*equ)) ; if (!*equ) { VECSYM *symbol = find_symbol (name, 0); if (symbol != NULL) { if (vecsym_user(symbol) != NULL) free (vecsym_user(symbol)); vecsym_user(symbol) = units; return (symbol); } } } /* check for equation */ if ('(' == *equ) { char *arg = equ; while (*++arg && (isspace (*arg) || isdigit(*arg))) ; if (')' == *arg) { nargs = atoi (equ + 1); for (equ = arg+1; *equ && isspace (*equ); equ++) ; } } if ('=' == *equ && '=' != *++equ) { strcpy (sym, name); for (cmd = equ; *cmd && isspace(*cmd); cmd++) ; /* add equation as string */ if (nargs >= 0) { if (nargs > 9) { cgnsCalcError ("invalid number of equation arguments"); return (NULL); } n = sym_addequ (sym, nargs, cmd, units); if (n) { cgnsCalcError (sym_errmsg (n)); return (NULL); } return (find_symbol (sym, 1)); } } } vd = vec_parse (cmd, VectorLen, callback); if (NULL == vd) { if (NULL != units) free (units); return (NULL); } /* add to symbol table */ if (VEC_VALUE == vd->type) n = sym_addval (sym, vd->f.val, units); else n = sym_addvec (sym, vd->len, vd->f.vec, units); vec_destroy (vd); if (!n) return (find_symbol (sym, 0)); cgnsCalcError (sym_errmsg (n)); return (NULL); } /*---------- cgnsCalcVarGet ---------------------------------------- * return a variable *------------------------------------------------------------------*/ Variable *cgnsCalcVarGet (char *varname) { int n, type = 0; char *name = varname; if (name == NULL || !*name) return NULL; if (*name == '~' || *name == '\'') type = *name++; /* check for variable */ if (!type) { for (n = 0; n < NumVariables; n++) { if (0 == strcmp (variables[n].name, name)) return &variables[n]; } } /* check for grid coordinates */ if (type != '~') { for (n = 0; n < NumCoordinates; n++) { if (0 == strcmp (coordinates[n].name, name)) return &coordinates[n]; } } /* check for reference quantity */ if (type != '\'') { for (n = 0; n < NumReference; n++) { if (0 == strcmp (reference[n].name, name)) return &reference[n]; } } return NULL; } /*---------- cgnsCalcVarList --------------------------------------- * print variables *------------------------------------------------------------------*/ void cgnsCalcVarList (FILE *fp) { int n; if (NULL == fp) fp = stdout; if (NumReference) { fprintf (fp, "=== Reference ===\n"); for (n = 0; n < NumReference; n++) { if (reference[n].len > 1) fprintf (fp, "~%s[%d]\n", reference[n].name, reference[n].len); else fprintf (fp, "~%s\n", reference[n].name); } } if (NumCoordinates) { fprintf (fp, "=== Coordinates ===\n"); for (n = 0; n < NumCoordinates; n++) fprintf (fp, "'%s[%d]\n", coordinates[n].name, coordinates[n].len); } if (NumVariables) { fprintf (fp, "=== Solution ===\n"); for (n = 0; n < NumVariables; n++) fprintf (fp, "%s[%d]\n", variables[n].name, variables[n].len); } } /*---------- cgnsCalcSymList --------------------------------------- * print list of symbols *------------------------------------------------------------------*/ void cgnsCalcSymList (FILE *fp) { if (NULL == fp) fp = stdout; fprintf (fp, "=== Symbols ===\n"); sym_list (0, print_symbols, fp); } CGNS-3.4.0/src/cgnstools/calclib/calc.h000066400000000000000000000057171343724673500175460ustar00rootroot00000000000000#ifndef _CALC_H_ #define _CALC_H_ #include #include "vecsym.h" extern int cgnsFile; /*--- base data ---*/ extern int NumBases, cgnsBase; extern char BaseName[33]; extern int CellDim, PhyDim; extern int BaseClass, BaseUnits[5]; /*--- zone data ---*/ extern int NumZones, cgnsZone; extern char ZoneName[33]; extern int ZoneType, ZoneDims[6]; extern int ZoneClass, ZoneUnits[5]; extern int GridClass, GridUnits[5]; /*--- solution data ---*/ extern int NumSolns, cgnsSoln; extern char SolnName[33]; extern int SolnLocation; extern int SolnDims[3], SolnRind[6]; extern int SolnClass, SolnUnits[5]; /*--- solution field data ---*/ typedef struct { int units[5]; float exps[5]; } Units; typedef struct { char name[33]; int type; int id; int valid; int len; int datatype; int dataclass; int hasunits; int units[5]; int hasconv; double dataconv[2]; int hasexp; double exponent[5]; VECDATA *vd; } Variable; /*----- variables -----*/ extern Variable *variables; extern int NumVariables; /*----- reference conditions -----*/ extern Variable *reference; extern int NumReference; /*----- mesh -----*/ extern Variable *coordinates; extern int NumCoordinates; /*----- external functions -----*/ #ifdef EXTERN_FUNCS extern void add_funcs ( void ); #endif /*----- functions -----*/ void cgnsCalcFatal ( /* terminate with error message */ char *errmsg /* error message */ ); void cgnsCalcError ( /* print error message */ char *errmsg /* error message */ ); void cgnsCalcReset ( /* reset calculator (symbol table) */ void ); int cgnsCalcInit ( /* load CGNS file and initialize */ char *cgnsfile, /* CGNS file */ int modify, /* set for modify mode */ void (*errhandler)( /* calculator error callback */ int errnum, /* error number */ char *errmsg, /* error message */ int pos, /* location in string */ char *str /* string being parsed */ ) ); void cgnsCalcDone ( /* close CGNS file */ void ); int cgnsCalcBase ( /* set base for calculations */ int base /* base number */ ); int cgnsCalcZone ( /* set zone for calculations */ int zone /* zone number */ ); int cgnsCalcSoln ( /* set solution for calculations */ int soln /* solution number */ ); int cgnsCalcCheck ( /* parse command and check for errors */ char *expression /* expression to be parsed */ ); VECSYM *cgnsCalcCommand (/* parse command string and return results */ char *expression /* expression to be parsed */ ); Variable *cgnsCalcVarGet (/* return a variable */ char *varname ); void cgnsCalcVarList ( /* print variables */ FILE *fp /* output file (NULL gives stdout) */ ); void cgnsCalcSymList ( /* print list of symbols */ FILE *fp /* output file (NULL gives stdout) */ ); #endif /* _CALC_H_ */ CGNS-3.4.0/src/cgnstools/calclib/calctest.c000066400000000000000000000251401343724673500204310ustar00rootroot00000000000000#include #include #include #include #include #include "calc.h" static int verbose = 0; static int recurs = 0; static char buff[1025]; static char errmsg[513]; /*===================================================================== * main *=====================================================================*/ #define PROMPT "\n$ " static char *commands[] = { "cmd = execute command 'cmd'", "> cmd = execute command 'cmd' with output", "< cmdfile = read command file 'cmdfile'", "& cgnsfile = load CGNS file 'cgnsfile'", "%> = turn on output", "%< = turn off output", "%% = reset calculator", "%b base = set base number 'base'", "%z zone = set zone number 'zone'", "%s soln = set solution number 'soln'", "?n = list number of bases,zones and solutions", "?[rcvsi] = list Reference,Coordinates,Variables,Symbols,Intrinsics", "?% = show base,zone,solution and output state", "** = exit", NULL }; /*---------- next_line ---------------------------------------------- * return next input line, handling blanks, comments and continuations *-------------------------------------------------------------------*/ static char *next_line (FILE *fp) { int n = 0, len; char *p, line[257]; while (fgets (line, sizeof(line), fp) != NULL) { line[sizeof(line)-1] = 0; p = line + strlen(line); while (--p >= line && isspace(*p)) ; *++p = 0; for (p = line; *p && isspace(*p); p++) ; if (!*p) continue; strcpy (buff, p); n = strlen (buff); while (buff[n-1] == '\\') { for (n -= 2; n >= 0 && isspace(buff[n]); n--) ; buff[++n] = 0; if (fgets (line, sizeof(line), fp) == NULL) break; line[sizeof(line)-1] = 0; p = line + strlen(line); while (--p >= line && isspace(*p)) ; *++p = 0; for (p = line; *p && isspace(*p); p++) ; if (!*p) break; len = strlen (p); if (n + len >= sizeof(buff)) cgnsCalcFatal ("internal command buffer length exceeded"); strcpy (&buff[n], p); n += len; } if ((p = strchr (buff, '#')) != NULL) *p = 0; for (p = buff+strlen(buff)-1; p >= buff && isspace(*p); p--) ; *++p = 0; for (p = buff; *p && isspace(*p); p++) ; if (*p) return (p); } return (NULL); } /*---------- process_command --------------------------------------- * extract prefix/suffix and process command *------------------------------------------------------------------*/ static void process_command (char *expression) { int echo = verbose; char *p, *cmd = expression; VECSYM *sym; /* skip leading and trailing space */ for (p = cmd + strlen(cmd) - 1; p >= cmd && isspace(*p); p--) ; *++p = 0; while (*cmd && isspace(*cmd)) cmd++; if (!*cmd) return; /* check for echo */ if (*cmd == '>') { echo = 1; while (*++cmd && isspace (*cmd)) ; } /* empty string */ if (!*cmd) { if (echo) putchar ('\n'); return; } /* evaluate the expression */ if (NULL == (sym = cgnsCalcCommand (cmd)) || !echo) return; /* value */ if (vecsym_type(sym) == VECSYM_VALUE) { printf ("%s = %g\n", vecsym_name(sym), vecsym_value(sym)); return; } /* vector */ if (vecsym_type(sym) == VECSYM_VECTOR) { int n, len = vecsym_veclen(sym); VECFLOAT vmin, vmax, *vec = vecsym_vector(sym); vmin = vmax = *vec; for (n = 1; n < len; n++) { if (vmin > vec[n]) vmin = vec[n]; if (vmax < vec[n]) vmax = vec[n]; } printf ("%s = %d:%g->%g\n", vecsym_name(sym), len, vmin, vmax); return; } /* equation or macro */ if (vecsym_type(sym) == VECSYM_EQUSTR || vecsym_type(sym) == VECSYM_MACRO) { printf ("%s(%d) %s %s\n", vecsym_name(sym), vecsym_nargs(sym), vecsym_type(sym) == VECSYM_MACRO ? ":=" : "=", vecsym_equstr(sym)); } } /*---------- parse_commands --------------------------------------------- * process command lines *-----------------------------------------------------------------------*/ static void parse_commands (FILE *fp, char *pmt) { int n, len; char *p; if (++recurs == 10) cgnsCalcFatal ("too many recursions"); while (1) { if (NULL != pmt && *pmt) printf (pmt); if ((p = next_line (fp)) == NULL) break; /* quit */ if (*p == '*') { if (*++p == '*') { cgnsCalcDone (); exit (0); } continue; } /* set output */ else if (*p == '%') { switch (*++p) { case '>': verbose = 1; break; case '<': verbose = 0; break; case '%': cgnsCalcReset (); break; case 'b': n = atoi (++p); if (n < 1 || n > NumBases) { sprintf (errmsg, "base %d invalid\n", n); cgnsCalcError (errmsg); } else cgnsCalcBase (n); break; case 'z': n = atoi (++p); if (n < 1 || n > NumZones) { sprintf (errmsg, "zone %d invalid\n", n); cgnsCalcError (errmsg); } else cgnsCalcZone (n); break; case 's': n = atoi (++p); if (n < 1 || n > NumSolns) { sprintf (errmsg, "solution %d invalid\n", n); cgnsCalcError (errmsg); } else cgnsCalcSoln (n); break; } continue; } /* help */ if (*p == '?') { if (!*++p) { for (n = 0; commands[n] != NULL; n++) printf ("%s\n", commands[n]); continue; } while (*p) { switch (*p) { case 'n': printf ("number of bases = %d\n", NumBases); printf (" zones = %d\n", NumZones); printf (" solns = %d\n", NumSolns); break; case 'r': printf ("=== Reference ===\n"); for (n = 0; n < NumReference; n++) { if (reference[n].len > 1) printf ("%s[%d]\n", reference[n].name, reference[n].len); else printf ("%s\n", reference[n].name); } break; case 'c': printf ("=== Coordinates ===\n"); for (n = 0; n < NumCoordinates; n++) printf ("%s[%d]\n", coordinates[n].name, coordinates[n].len); break; case 'v': printf ("=== Solution ===\n"); for (n = 0; n < NumVariables; n++) printf ("%s[%d]\n", variables[n].name, variables[n].len); break; case 'i': { char **in = vec_list (); printf ("=== Intrinsics ===\n"); for (n = 0; in[n] != NULL; n++) printf ("%s\n", in[n]); break; } case 's': cgnsCalcSymList (stdout); break; case '%': printf ("current base = %d\n", cgnsBase); printf (" zone = %d\n", cgnsZone); printf (" soln = %d\n", cgnsSoln); printf ("output is %s\n", verbose ? "on" : "off"); break; default: break; } p++; } continue; } /* load CGNS file */ if (*p == '&') { while (*++p && isspace(*p)) ; if (!*p) continue; if (access (p, 0)) { sprintf (errmsg, "results file <%s> does not exist", p); cgnsCalcError (errmsg); } else cgnsCalcInit (p, 0, NULL); continue; } /* load command file */ if (*p == '<') { FILE *file; while (*++p && isspace (*p)) ; if (!*p) continue; if (access (p, 0)) { sprintf (errmsg, "command file <%s> does not exist", p); cgnsCalcError (errmsg); } else if ((file = fopen (p, "r")) == NULL) { sprintf (errmsg, "couldn't open command file <%s>", p); cgnsCalcError (errmsg); } else { parse_commands (file, NULL); fclose (file); } continue; } /* process command */ process_command (p); } recurs--; } /*================================================================*/ int main (int argc, char *argv[]) { int n = 1; if (n < argc) { cgnsCalcInit (argv[n++], 0, NULL); if (n < argc) { FILE *fp = fopen (argv[n], "r"); if (NULL == fp) { sprintf (errmsg, "couldn't open command file <%s>", argv[n]); cgnsCalcFatal (errmsg); } parse_commands (fp, NULL); } } if (isatty(fileno(stdin)) && isatty(fileno(stdout))) { putchar ('\n'); for (n = 0; commands[n] != NULL; n++) printf ("%s\n", commands[n]); parse_commands (stdin, PROMPT); } else parse_commands (stdin, NULL); cgnsCalcDone (); return 0; } CGNS-3.4.0/src/cgnstools/calclib/vec.c000066400000000000000000002030331343724673500174030ustar00rootroot00000000000000/* * vec.c - array processor for an equation */ #include #include #include #include #include #include #include #include #include "vec.h" #include "vecsym.h" #define INCLUDE_ERRDATA #include "vecerr.h" /*----- machine dependent defines -----*/ #ifndef SIGNAL #define SIGNAL void #endif /* #ifndef sgi #define USE_MATHERR #endif */ #ifndef SIG_ERR # ifdef BADSIG # define SIG_ERR BADSIG # else # define SIG_ERR ((SIGNAL (*)())-1) # endif #endif /*----- defined data values -----*/ #define STACK_INC 50 /* amount to increase size of op stack */ #define MAX_ARGS 9 /* maximum function arguments */ #define E 2.71828182845904523536 #ifndef PI # define PI 3.14159265358979323846 #endif #define TOLERANCE 0.0000000001 #define OPERATORS "^*/%+-<>=!&|?:),]" enum Tokens { /* operation tokens */ OP_NEGATE = 1, OP_POWER, OP_MULTIPLY, OP_DIVIDE, OP_MODULUS, OP_PLUS, OP_MINUS, OP_LESS, OP_LESS_EQ, OP_GREATER, OP_GREATER_EQ, OP_EQUALS, OP_NOT_EQUAL, OP_AND, OP_OR, OP_NOT, OP_IF, OP_ELSE, OP_ENDIF, OP_BEGIN_FUNC, OP_NOP, OP_VECTOR, OP_NUMBER, OP_INTEGER, OP_INDEX, OP_COUNTER, /* function tokens */ FUNC_ABS, FUNC_ACOS, FUNC_ACOSH, FUNC_ASIN, FUNC_ASINH, FUNC_ATAN, FUNC_ATAN2, FUNC_ATANH, FUNC_CEIL, FUNC_COS, FUNC_COSH, FUNC_DEG, FUNC_EXP, FUNC_FACT, FUNC_FLOOR, FUNC_LOG, FUNC_LOG10, FUNC_MOD, FUNC_POW, FUNC_POW10, FUNC_RAD, FUNC_RAND, FUNC_ROUND, FUNC_SIN, FUNC_SINH, FUNC_SQR, FUNC_SQRT, FUNC_TAN, FUNC_TANH, FUNC_AVG, FUNC_MAX, FUNC_MIN, FUNC_SUM, FUNC_SIZE, FUNC_LEN }; /*----- operation stack -----*/ struct op_stack_ { int op; size_t len; union { int ival; double num; VECFLOAT *vec; } op_val; }; static struct op_stack_ *op_start; /* operation stack */ static int op_size = 0; /* current size of operation stack */ static int op_pos; /* current position in stack */ static int op_index; /* counter for processing */ /*----- variable stack -----*/ static double *var_stack; /* processing stack */ static int var_size = 0; /* size of processing stack */ static int var_pos; /* current position in stack */ /*----- constant values -----*/ static double constants[] = { #define CONSTANT_E 0 E, #define CONSTANT_PI 1 PI, #define CONSTANT_TOL 2 TOLERANCE }; #define CONSTANT_DIM 3 /*----- intrinsic symbol table -----*/ #define VEC_ACROSS 0 #define VEC_ALONG 1 #define VEC_VARIABLE 2 static struct intrinsic_ { char *name; int type; int nargs; int op; } intrinsics[] = { {"abs", VEC_ACROSS, 1, FUNC_ABS }, {"acos", VEC_ACROSS, 1, FUNC_ACOS }, {"acosh", VEC_ACROSS, 1, FUNC_ACOSH }, {"asin", VEC_ACROSS, 1, FUNC_ASIN }, {"asinh", VEC_ACROSS, 1, FUNC_ASINH }, {"atan", VEC_ACROSS, 1, FUNC_ATAN }, {"atan2", VEC_ACROSS, 2, FUNC_ATAN2 }, {"atanh", VEC_ACROSS, 1, FUNC_ATANH }, {"avg", VEC_ALONG, 1, FUNC_AVG }, {"ceil", VEC_ACROSS, 1, FUNC_CEIL }, {"cos", VEC_ACROSS, 1, FUNC_COS }, {"cosh", VEC_ACROSS, 1, FUNC_COSH }, {"deg", VEC_ACROSS, 1, FUNC_DEG }, {"dim", CONSTANT_DIM, 0, OP_NUMBER }, {"e", CONSTANT_E, 0, OP_NUMBER }, {"exp", VEC_ACROSS, 1, FUNC_EXP }, {"fact", VEC_ACROSS, 1, FUNC_FACT }, {"floor", VEC_ACROSS, 1, FUNC_FLOOR }, {"index", VEC_VARIABLE, 0, OP_COUNTER }, {"len", VEC_ALONG, 1, FUNC_LEN }, {"log", VEC_ACROSS, 1, FUNC_LOG }, {"log10", VEC_ACROSS, 1, FUNC_LOG10 }, {"mag", VEC_ALONG, 1, FUNC_SIZE }, {"max", VEC_ALONG, 1, FUNC_MAX }, {"min", VEC_ALONG, 1, FUNC_MIN }, {"mod", VEC_ACROSS, 2, FUNC_MOD }, {"pi", CONSTANT_PI, 0, OP_NUMBER }, {"pow", VEC_ACROSS, 2, FUNC_POW }, {"pow10", VEC_ACROSS, 1, FUNC_POW10 }, {"rad", VEC_ACROSS, 1, FUNC_RAD }, {"rand", VEC_ACROSS, 0, FUNC_RAND }, {"round", VEC_ACROSS, 1, FUNC_ROUND }, {"sin", VEC_ACROSS, 1, FUNC_SIN }, {"sinh", VEC_ACROSS, 1, FUNC_SINH }, {"sqr", VEC_ACROSS, 1, FUNC_SQR }, {"sqrt", VEC_ACROSS, 1, FUNC_SQRT }, {"sum", VEC_ALONG, 1, FUNC_SUM }, {"tan", VEC_ACROSS, 1, FUNC_TAN }, {"tanh", VEC_ACROSS, 1, FUNC_TANH }, {"tol", CONSTANT_TOL, 0, OP_NUMBER } }; #define NUM_INTRINSICS sizeof(intrinsics)/sizeof(struct intrinsic_) /*----- list of intrinsics -----*/ static char *in_list[] = { "Intrinsic operators in order of precedence:", "Operator Type Operators", "-------------------------", "Expression () const func()", "Unary - !", "Exponential ^ **", "Multiplicative * / %", "Additive + -", "Relational < <= > >= == !=", "Logical &[&] |[|] ?:", "", "Defined constants:", "Name Value", "---------------------", "pi 3.14159265358979323846", "e 2.71828182845904523536", "tol 0.0000000001", "index current array index", "dim minimum array len", " any constant", "", "Defined functions:", "Name Operation", "-------------------------", "abs() absolute value", "acos() arc cosine (radians)", "acosh() arc hyperbolic cosine", "asin() arc sine (radians)", "asinh() arc hyperbolic sine", "atan() arc tangent (radians)", "atanh() arc hyperbolic tangent", "avg() average value in a vector", "ceil() next largest integer", "cos() cosine (radians)", "cosh() hyperbolic cosine", "deg() convert from radians to degrees", "exp() power of e", "fact() factorial of a number", "floor() next smallest integer", "len() length of a vector", "log() natural log", "log10() base 10 log", "size() magnitude of a vector", "max() maximum value in a vector", "min() minimum value in a vector", "pow10() power of 10", "rad() convert from degrees to radians", "rand() random number between 0 and 1", "round() round a number to integer", "sin() sine (radians)", "sinh() hyperbolic sine", "sqr() square a number", "sqrt() take square root of a number", "sum() sum of values in a vector", "tan() tangent (radians)", "tanh() hyperbolic tangent", NULL }; /*----- error handling -----*/ int vec_maxerr = VECERR_INVALID; int vec_errnum = 0; void (*vec_errhandler)(int,char *,int,char *) = NULL; typedef SIGNAL (*SIGHANDLER)(int); /*----- temporary vectors -----*/ typedef struct veclist_ { VECDATA *v; struct veclist_ *prev; } VECLIST; static VECLIST *veclist = NULL; /*----- defined macros -----*/ #define advance(amt) exp_ptr+=(amt) #define skip_space(p) while(*(p) && isspace(*(p)))(p)++ #define skip_int(p) while(*(p) && isdigit(*(p)))(p)++ /*----- parsing data -----*/ static int num_calls = 0; /* recursion counter */ static int max_calls = VEC_MAXCALLS;/* maximum recursive calls */ static size_t max_len = 0; /* maximum vector length */ static size_t counter_len = 0; /* min length of counter */ static VECCALL usr_func; /* pointer to user supplied function */ static char *exp_start = NULL; /* start of string being parsed */ static char *exp_ptr; /* location in string being parsed */ static SIGHANDLER old_fpe_sig; /* old SIGFPE handler */ static jmp_buf env_ptr; /* enviroment for return from longjmp() */ static int nest_level; /* nesting count for if-then-else */ static int vec_op; /* doing operations on array lengths */ static int num_args = 0; /* number arguments for equation */ static VECDATA *arglist[MAX_ARGS];/* equation argument list */ static int checking = 0; /* set if checking equation only */ /*----- function prototypes -----*/ static VECDATA *parse(); static void *handle_error(); static void clean_up(); static int do_intrinsic(); static int do_symbol(); static int get_args(); static void chk_index(); static void add_op(); static void logical(); static void relational(); static void additive(); static void multiplicative(); static void exponential(); static void unary(); static void expression(); static void push_var(); static void pop_var(); static double process_op(); static SIGNAL fpe_err (int signum); /*================================================================== * user callable routines *==================================================================*/ /*---------- vec_create -------------------------------------------- * creates a vector data structure *------------------------------------------------------------------*/ VECDATA *vec_create (int type, size_t len, int temp) { VECDATA *vdata; if (type == VEC_VECTOR) { if (len < 1 && temp >= 0) return (handle_error (VECERR_ZEROLEN)); } else if (type == VEC_VALUE) len = 0; else return (handle_error (VECERR_VECTYPE)); vdata = (VECDATA *) calloc (1, sizeof(VECDATA)); if (vdata == NULL) return (handle_error (VECERR_MALLOC)); if (len && temp >= 0) { vdata->f.vec = (VECFLOAT *) calloc (len, sizeof(VECFLOAT)); if (vdata->f.vec == NULL) { free (vdata); return (handle_error (VECERR_MALLOC)); } } else vdata->f.vec = NULL; vdata->type = type; vdata->len = len; /* add to temporary list */ if (temp) { VECLIST *vl = (VECLIST *) malloc (sizeof(VECLIST)); if (vl == NULL) { if (len) free (vdata->f.vec); free (vdata); return (handle_error (VECERR_MALLOC)); } vl->v = vdata; vl->prev = veclist; veclist = vl; } return (vdata); } /*---------- vec_destroy ------------------------------------------- * destroys a vector data structure *------------------------------------------------------------------*/ void vec_destroy (VECDATA *vdata) { if (vdata != NULL) { vec_remove (vdata); if (vdata->type == VEC_VECTOR && vdata->f.vec != NULL) free (vdata->f.vec); free (vdata); } } /*---------- vec_add ----------------------------------------------- * add vector to temporary vector list *------------------------------------------------------------------*/ int vec_add (VECDATA *vd) { VECLIST *vl = veclist; if (vd == NULL) return (0); /* check if already in list */ while (vl != NULL) { if (vl->v == vd) return (1); vl = vl->prev; } /* it's not, so add it */ if ((vl = (VECLIST *) malloc (sizeof(VECLIST))) == NULL) return (0); vl->v = vd; vl->prev = veclist; veclist = vl; return (1); } /*---------- vec_remove -------------------------------------------- * remove temporary vector from list *------------------------------------------------------------------*/ void vec_remove (VECDATA *vd) { VECLIST *prev, *vlist = veclist; if (vd == NULL || vlist == NULL) return; if (vlist->v == vd) { veclist = vlist->prev; free (vlist); return; } prev = vlist->prev; while (prev != NULL) { if (prev->v == vd) { vlist->prev = prev->prev; free (prev); return; } vlist = prev; prev = vlist->prev; } } /*---------- vec_free ---------------------------------------------- * releases internal resources *------------------------------------------------------------------*/ void vec_free (void) { /* free operation stack */ if (op_size) { op_size = 0; free (op_start); } /* free variable stack */ if (var_size) { var_size = 0; free (var_stack); } } /*---------- vec_maxcalls ------------------------------------------ * sets maximum recursive calls *------------------------------------------------------------------*/ void vec_maxcalls (int val) { max_calls = val > 0 ? val : VEC_MAXCALLS; } /*---------- vec_errmsg -------------------------------------------- * returns error message *------------------------------------------------------------------*/ char *vec_errmsg (void) { if (vec_errnum < 0 || vec_errnum >= VECERR_INVALID) vec_errnum = VECERR_INVALID; return (err_msg[vec_errnum]); } /*---------- vec_list ---------------------------------------------- * return list of intrinsics *------------------------------------------------------------------*/ char **vec_list (void) { return (in_list); } /*---------- vec_parse --------------------------------------------- * parse and process equation string *------------------------------------------------------------------*/ VECDATA *vec_parse (char *str, int min_len, VECCALL func) { VECDATA *vd; size_t old_len = counter_len; VECCALL old_func = usr_func; char *old_ptr = exp_ptr; char *old_start = exp_start; /* is there a string ? */ exp_start = NULL; if (str != NULL) skip_space (str); if (str == NULL || !*str) return (handle_error (VECERR_NOEXPR)); /* create operation stack if not done */ if (op_size == 0) { op_start = (struct op_stack_ *) malloc (STACK_INC * sizeof(struct op_stack_)); if (op_start == NULL) return (handle_error (VECERR_OP_STK)); op_size = STACK_INC; } /* create processing stack if not already done */ if (var_size == 0) { var_stack = (double *) malloc (STACK_INC * sizeof(double)); if (var_stack == NULL) return (handle_error (VECERR_VAR_STK)); var_size = STACK_INC; } /* install the SIGFPE handler */ if (num_calls == 0) { checking = op_pos = var_pos = op_index = 0; max_len = 0; old_fpe_sig = signal (SIGFPE, fpe_err); vec_randinit ((int) time (NULL)); /* jump here on parsing error */ vec_errnum = setjmp (env_ptr); if (vec_errnum != 0) { clean_up (); return (handle_error (vec_errnum)); } } usr_func = func; exp_ptr = str; exp_start = str; counter_len = min_len > 0 ? min_len : 1; vd = parse (); if (*exp_ptr) longjmp (env_ptr, VECERR_MISSING); vec_remove (vd); if (num_calls == 0) clean_up (); else { counter_len = old_len; usr_func = old_func; exp_ptr = old_ptr; exp_start = old_start; } return (vd); } /*---------- vec_check --------------------------------------------- * parse equation string and check for errors *------------------------------------------------------------------*/ size_t vec_check (char *str, int min_len, VECCALL func) { VECDATA *vd; size_t len; size_t old_len = counter_len; VECCALL old_func = usr_func; char *old_ptr = exp_ptr; char *old_start = exp_start; /* is there a string ? */ exp_start = NULL; if (str != NULL) skip_space (str); if (str == NULL || !*str) { handle_error (VECERR_NOEXPR); return (0); } /* create operation stack if not done */ if (op_size == 0) { op_start = (struct op_stack_ *) malloc (STACK_INC * sizeof(struct op_stack_)); if (op_start == NULL) { handle_error (VECERR_OP_STK); return (0); } op_size = STACK_INC; } /* create processing stack if not already done */ if (var_size == 0) { var_stack = (double *) malloc (STACK_INC * sizeof(double)); if (var_stack == NULL) { handle_error (VECERR_VAR_STK); return (0); } var_size = STACK_INC; } /* install the SIGFPE handler */ if (num_calls == 0) { checking = 1; max_len = op_pos = var_pos = op_index = 0; old_fpe_sig = signal (SIGFPE, fpe_err); vec_randinit ((int) time (NULL)); /* jump here on parsing error */ vec_errnum = setjmp (env_ptr); if (vec_errnum != 0) { clean_up (); handle_error (vec_errnum); return (0); } } usr_func = func; exp_ptr = str; exp_start = str; counter_len = min_len > 0 ? min_len : 1; vd = parse (); if (*exp_ptr) longjmp (env_ptr, VECERR_MISSING); len = vd->len ? vd->len : 1; if (num_calls == 0) clean_up (); else { counter_len = old_len; usr_func = old_func; exp_ptr = old_ptr; exp_start = old_start; } return (len); } /*=================================================================== * support routines callable by user *===================================================================*/ /*---------- vec_number -------------------------------------------- * gets a double and advances string pointer * This is similar to 'strtod, but I know what it's doing * Expects a number of the form : * [whitespace][{+|-}][digits][.digits][{d|D|e|E}[sign]digits] *------------------------------------------------------------------*/ int vec_number (double *dval, char **sp) { register char *p, c; char *start; int point = 0; p = start = *sp; *dval = 0.0; /* skip whitespace */ while (*p && isspace (*p)) p++; /* get to first required digit */ if (*p == '-' || *p == '+') p++; if (*p == '.') { point++; p++; } /* next character needs to be digit */ if (!*p || !isdigit (*p)) return (0); /* get past the number */ while (*p && (isdigit (*p) || *p == '.')) { if (*p == '.') { if (point) { *p = 0; *dval = (double) atof (*sp); *p = '.'; *sp = p; return (1); } point++; } p++; } *sp = p; /* check for an exponent */ if (*p == 'd' || *p == 'D' || *p == 'e' || *p == 'E') { if (*++p == '+' || *p == '-') p++; if (isdigit (*p)) { while (*++p && isdigit (*p)) ; *sp = p; } } c = **sp; **sp = 0; *dval = atof (start); **sp = c; return (1); } /*------------------------------------------------------------------- * system independent random number generator from Kluth *-------------------------------------------------------------------*/ #define MBIG 1000000000 #define MSEED 161803398 static int Rand_ext = 0; static int Rand_extp = 31; static long Rand_ma[56] = { 0,473269125,708359770,742015427, 65602533,275831218, 24831226, 897336983,199633574,555982024,514994949,279315436,156002375,334914356, 270182445,993586635,796323046,222779050,530019863,240216188,246247465, 251350083, 27923555, 17362715,286349234,561741882, 61883183, 25293241, 182316584,384320687, 97284929,343171996,939345275,385350967,340911449, 606343026,885561620,105803147,288011295,407490891,632823362,921005485, 393546951,638589878,430524660, 1651896,884594510,251198018,883223679, 254238950,266438063,664142955,409571047,306976444,378529592,649134132 }; /*---------- vec_randinit ------------------------------------------- * initialize the random number generator *-------------------------------------------------------------------*/ void vec_randinit (int seed) { int i, k; long mj, mk; mj = MSEED - (seed < 0 ? -seed : seed); mj %= MBIG; Rand_ma[55] = mj; mk = 1; for (i = 1; i <= 54; i++) { k = (21 * i) % 55; Rand_ma[k] = mk; mk = mj - mk; if (mk < 0) mk += MBIG; mj = Rand_ma[k]; } for (k = 1; k <= 4; k++) { for (i = 1; i <= 55; i++) { Rand_ma[i] -= Rand_ma[1+(i+30) % 55]; if (Rand_ma[i] < 0) Rand_ma[i] += MBIG; } } Rand_ext = 0; Rand_extp = 31; } /*---------- vec_rand ----------------------------------------------- * return random number between 0 and 1 *-------------------------------------------------------------------*/ double vec_rand (void) { long mj; if (++Rand_ext == 56) Rand_ext = 1; if (++Rand_extp == 56) Rand_extp = 1; mj = Rand_ma[Rand_ext] - Rand_ma[Rand_extp]; if (mj < 0) mj += MBIG; Rand_ma[Rand_ext] = mj; return ((double) mj / (double) MBIG); } /*================================================================== * parsing routines *==================================================================*/ /*---------- parse -------------------------------------------------- * does the parsing and evaluation of the string *-------------------------------------------------------------------*/ static VECDATA *parse () { size_t n; size_t cur_len = max_len; int cur_op = op_pos; int cur_index = op_index; int cur_var = var_pos; VECDATA *vd; if (++num_calls == max_calls) longjmp (env_ptr, VECERR_CALLS); max_len = 0; logical (); skip_space (exp_ptr); if (checking) { if (max_len == 1) vd = vec_create (VEC_VALUE, 0, -1); else vd = vec_create (VEC_VECTOR, max_len, -1); } else { vd = vec_create (VEC_VECTOR, max_len, 1); /* process the variables */ for (n = 0; n < max_len; n++) { var_pos = cur_var; op_index = cur_op; nest_level = vec_op = 0; vd->f.vec[n] = (VECFLOAT)process_op (n); } if (max_len == 1) { VECFLOAT f = vd->f.vec[0]; free (vd->f.vec); vd->type = VEC_VALUE; vd->len = 0; vd->f.val = f; } } max_len = cur_len; op_pos = cur_op; op_index = cur_index; var_pos = cur_var; num_calls--; return (vd); } /*---------- handle_error ------------------------------------------- * handle error message *-------------------------------------------------------------------*/ static void *handle_error (err) int err; { int pos = -1; char *str = exp_start; if (num_calls) longjmp (env_ptr, vec_errnum); if (err < 0 || err >= VECERR_INVALID) vec_errnum = VECERR_INVALID; else vec_errnum = err; exp_start = NULL; if (str != NULL) { pos = (int) (exp_ptr - str); if (pos < 0 || pos > (int)strlen (str)) { pos = -1; str = NULL; } } if (vec_errhandler != NULL) (*vec_errhandler) (vec_errnum, err_msg[vec_errnum], pos, str); else { if (str != NULL) { fprintf (stderr, "%s\n", str); while (pos-- > 0) putc ('-', stderr); putc ('^', stderr); } fprintf (stderr, "%s\n", err_msg[vec_errnum]); } return (NULL); } /*---------- reset_recurs ------------------------------------------ * reset recursion flags for equation symbols - called from sym_list *------------------------------------------------------------------*/ static int reset_recurs (VECSYM *sym, void *userdata) { if (vecsym_nargs(sym) < 0) vecsym_nargs(sym) = 0; return (0); } /*---------- clean_up ---------------------------------------------- * clean up on error or parsing completion *------------------------------------------------------------------*/ static void clean_up () { VECLIST *prev; if (old_fpe_sig != SIG_ERR) signal (SIGFPE, old_fpe_sig); (void) sym_list (VECSYM_EQUSTR, reset_recurs, NULL); while (veclist != NULL) { prev = veclist->prev; if (veclist->v->type == VEC_VECTOR && veclist->v->f.vec != NULL) free (veclist->v->f.vec); free (veclist->v); free (veclist); veclist = prev; } num_calls = num_args = 0; } /*---------- do_intrinsic ------------------------------------------ * process an intrinsic variable *------------------------------------------------------------------*/ static int do_intrinsic () { char c, *p = exp_ptr; int lo, hi, n, m; struct intrinsic_ *ins; if (!isalpha (*p)) return (0); while (*++p && (isalnum (*p) || *p == '_')) ; c = *p; *p = 0; lo = 0; hi = NUM_INTRINSICS - 1; n = hi / 2; ins = &intrinsics[n]; while (1) { if ((m = strcmp (exp_ptr, ins->name)) == 0) break; if (lo >= hi) break; if (m < 0) hi = n - 1; else lo = n + 1; n = (lo + hi) / 2; ins = &intrinsics[n]; } *p = c; if (m) return (0); exp_ptr = p; if (ins->op == OP_NUMBER) { if (ins->type == CONSTANT_DIM) { double dval = counter_len; add_op (OP_NUMBER, &dval); } else add_op (OP_NUMBER, &constants[ins->type]); } else if (ins->type == VEC_VARIABLE) add_op (ins->op, NULL); else if (ins->type == VEC_ALONG) { size_t msave = max_len; add_op (OP_BEGIN_FUNC, NULL); (void) get_args (ins->nargs); add_op (ins->op, NULL); max_len = msave ? msave : 1; } else { (void) get_args (ins->nargs); add_op (ins->op, NULL); } return (1); } /*---------- get_args ---------------------------------------------- * extracts arguments for intrinsic function *------------------------------------------------------------------*/ static int get_args (nargs) int nargs; { int n = 0; skip_space (exp_ptr); if (*exp_ptr != '(') longjmp (env_ptr, VECERR_FUNC); advance (1); skip_space (exp_ptr); if (*exp_ptr == ')') { if (nargs > 0) longjmp (env_ptr, VECERR_ARGS); advance (1); return (0); } while (1) { skip_space (exp_ptr); logical (); n++; skip_space (exp_ptr); if (*exp_ptr == ')') break; if (*exp_ptr == ',') { if (n == nargs) longjmp (env_ptr, VECERR_ARGS); if (n == FUNC_MAXARGS) longjmp (env_ptr, VECERR_MAXARGS); advance (1); } else longjmp (env_ptr, VECERR_ARGS); } if (nargs > 0 && n != nargs) longjmp (env_ptr, VECERR_ARGS); advance (1); return (n); } /*---------- do_symbol --------------------------------------------- * processes a user symbol *------------------------------------------------------------------*/ static int do_symbol () { int c, is_func; char symname[SYMNAME_MAXLEN+2], *p = exp_ptr; VECSYM *sym; /* check for replaceable argument */ if (*p == '$') { if (*++p && isdigit (*p)) { c = *p - '1'; if (c < 0 || c >= num_args) longjmp (env_ptr, VECERR_EQUARG); exp_ptr = p; advance (1); if (arglist[c]->type == VEC_VALUE) { double dval = arglist[c]->f.val; add_op (OP_NUMBER, &dval); } else if (arglist[c]->type == VEC_VECTOR) add_op (OP_VECTOR, arglist[c]); else longjmp (env_ptr, VECERR_VECTYPE); return (1); } return (0); } /* get symbol name */ if (*p == '\\') p++; if (!*p || (!isalpha (*p) && *p != '_' && *p != '"')) return (0); symname[0] = '.'; if (*p == '"') { for (++p, c = 1; c <= SYMNAME_MAXLEN; c++) { if (!*p || *p == '"') break; symname[c] = *p++; } if (*p++ != '"') return 0; } else { for (c = 1; c <= SYMNAME_MAXLEN; c++) { symname[c] = *p++; if (!*p || (!isalnum (*p) && *p != '_')) break; } } if (c > SYMNAME_MAXLEN) return (0); symname[++c] = 0; /* check if function */ while (*p && isspace (*p)) p++; is_func = *p == '('; /* find symbol */ if (*exp_ptr == '\\' || (sym = find_symbol (symname, is_func)) == NULL) sym = find_symbol (&symname[1], is_func); /*--- symbol not found ---*/ if (sym == NULL) return (0); /*--- value ---*/ if (vecsym_type(sym) == VECSYM_VALUE) { double val = vecsym_value(sym); add_op (OP_NUMBER, &val); exp_ptr = p; return (1); } /*--- vector ---*/ if (vecsym_type(sym) == VECSYM_VECTOR) { VECDATA vdat; exp_ptr = p; vdat.len = vecsym_veclen(sym); vdat.f.vec = vecsym_vector(sym); chk_index (&vdat); return (1); } /*--- equation ---*/ if (vecsym_type(sym) == VECSYM_EQUSTR) { char *s; int nargs = 0; VECDATA *vd[9], *vtmp; if (vecsym_nargs(sym) < 0) longjmp (env_ptr, VECERR_RECURSE); if (vecsym_nargs(sym) == 0) { vecsym_nargs(sym) = -1; if (is_func) { p++; skip_space (p); if (*p != ')') longjmp (env_ptr, VECERR_PAREN); p++; } } else { exp_ptr = p; if (*exp_ptr++ != '(') longjmp (env_ptr, VECERR_FUNC); skip_space (exp_ptr); while (*exp_ptr && *exp_ptr != ')') { if (nargs == vecsym_nargs(sym)) longjmp (env_ptr, VECERR_MAXARGS); vd[nargs++] = parse (); if (*exp_ptr == ',') advance (1); skip_space (exp_ptr); } if (*exp_ptr != ')' || nargs != vecsym_nargs(sym)) longjmp (env_ptr, VECERR_ARGS); advance (1); p = exp_ptr; } for (c = 0; c < 9; c++) { vtmp = arglist[c]; arglist[c] = vd[c]; vd[c] = vtmp; } c = nargs; nargs = num_args; num_args = c; s = exp_start; exp_start = exp_ptr = vecsym_equstr(sym); logical (); if (*exp_ptr) longjmp (env_ptr, VECERR_MISSING); if (vecsym_nargs(sym) < 0) vecsym_nargs(sym) = 0; exp_start = s; exp_ptr = p; num_args = nargs; for (c = 0; c < num_args; c++) arglist[c] = vd[c]; return (1); } /*--- function ---*/ if (vecsym_type(sym) == VECSYM_FUNC) { int nargs = 0; VECDATA *vd[FUNC_MAXARGS+1]; exp_ptr = p; if (*exp_ptr++ != '(') longjmp (env_ptr, VECERR_FUNC); skip_space (exp_ptr); if (*exp_ptr != ')') { while (1) { vd[nargs] = parse (); if (++nargs > FUNC_MAXARGS) longjmp (env_ptr, VECERR_MAXARGS); if (*exp_ptr == ',') advance (1); else if (*exp_ptr != ')') longjmp (env_ptr, VECERR_ARGS); else break; } } advance (1); if (vecsym_nargs(sym) >= 0 && vecsym_nargs(sym) != nargs) longjmp (env_ptr, VECERR_ARGS); p = NULL; vd[nargs] = (*vecsym_func(sym)) (checking, nargs, vd, &p); if (vd[nargs] == NULL) { if (p == NULL || !*p) longjmp (env_ptr, VECERR_SYMBOL); else { err_msg[VECERR_USER] = p; longjmp (env_ptr, VECERR_USER); } } if (vd[nargs]->type == VEC_VALUE) { double dval = vd[nargs]->f.val; add_op (OP_NUMBER, &dval); } else if (vd[nargs]->type == VEC_VECTOR) add_op (OP_VECTOR, vd[nargs]); else longjmp (env_ptr, VECERR_VECTYPE); for (c = 0; c < nargs; c++) vec_destroy (vd[c]); return (1); } /*--- unknown ---*/ return (0); } /*---------- chk_index --------------------------------------------- * check for a vector index *------------------------------------------------------------------*/ static void chk_index (vdata) VECDATA *vdata; { if (*exp_ptr == '[') { advance (1); logical (); skip_space (exp_ptr); if (*exp_ptr != ']') longjmp (env_ptr, VECERR_BRACKET); advance (1); add_op (OP_INDEX, NULL); if (max_len <= 1) { add_op (OP_VECTOR, vdata); max_len = 1; return; } } add_op (OP_VECTOR, vdata); } /*---------- do_userfunc ------------------------------------------- * call user routine *------------------------------------------------------------------*/ static int do_userfunc () { char *p, *s; double dval; VECDATA *vd; if (usr_func == NULL) return (0); p = exp_ptr; s = NULL; if ((vd = (*usr_func) (checking, &p, &s)) == NULL) { if (s == NULL || !*s) return (0); err_msg[VECERR_USER] = s; longjmp (env_ptr, VECERR_USER); } if (p <= exp_ptr) longjmp (env_ptr, VECERR_POINTER); exp_ptr = p; if (vd->type == VEC_VALUE) { dval = vd->f.val; add_op (OP_NUMBER, (void *)&dval); } else if (vd->type == VEC_VECTOR) { skip_space (exp_ptr); chk_index (vd); } else longjmp (env_ptr, VECERR_VECTYPE); return (1); } /*---------- add_op ------------------------------------------------ * adds operation to the stack *------------------------------------------------------------------*/ static void add_op (op, op_val) int op; void *op_val; { if (op_pos >= op_size) { op_size += STACK_INC; op_start = (struct op_stack_ *) realloc (op_start, op_size * sizeof(struct op_stack_)); if (op_start == NULL) longjmp (env_ptr, VECERR_OP_STK); } switch (op) { case OP_INTEGER: op_start[op_pos].len = 1; op_start[op_pos].op_val.ival = *((int *)op_val); break; case OP_NUMBER: op_start[op_pos].len = 1; op_start[op_pos].op_val.num = *((double *)op_val); break; case OP_VECTOR: { VECDATA *vdat = (VECDATA *)op_val; op_start[op_pos].len = vdat->len; op_start[op_pos].op_val.vec = vdat->f.vec; /* if (counter_len < vdat->len)*/ counter_len = vdat->len; break; } case OP_INDEX: case FUNC_RAND: op_start[op_pos].len = 1; break; case OP_COUNTER: op_start[op_pos].len = counter_len; break; default: op_start[op_pos].len = 0; break; } op_start[op_pos].op = op; if (max_len < op_start[op_pos].len) max_len = op_start[op_pos].len; op_pos++; } /*---------- logical ----------------------------------------------- * evaluates logical operations *------------------------------------------------------------------*/ static void logical () { relational (); while (1) { skip_space (exp_ptr); if (*exp_ptr == '?') { advance (1); add_op (OP_IF, NULL); logical (); skip_space (exp_ptr); if (*exp_ptr != ':') longjmp (env_ptr, VECERR_IFELSE); advance (1); add_op (OP_ELSE, NULL); logical (); add_op (OP_ENDIF, NULL); } else if (*exp_ptr == '&') { advance (1); if (*exp_ptr == '&') advance (1); relational (); add_op (OP_AND, NULL); } else if (*exp_ptr == '|') { advance (1); if (*exp_ptr == '|') advance (1); relational (); add_op (OP_OR, NULL); } else break; } } /*---------- relational -------------------------------------------- * evaluates relational operators *------------------------------------------------------------------*/ static void relational () { additive (); while (1) { skip_space (exp_ptr); if (*exp_ptr == '<') { advance (1); if (*exp_ptr == '=') { advance (1); additive (); add_op (OP_LESS_EQ, NULL); } else { additive (); add_op (OP_LESS, NULL); } } else if (*exp_ptr == '>') { advance (1); if (*exp_ptr == '=') { advance (1); additive (); add_op (OP_GREATER_EQ, NULL); } else { additive (); add_op (OP_GREATER, NULL); } } else if (*exp_ptr == '=') { advance (1); if (*exp_ptr != '=') longjmp (env_ptr, VECERR_EQUALS); advance (1); additive (); add_op (OP_EQUALS, NULL); } else if (*exp_ptr == '!') { advance (1); if (*exp_ptr != '=') longjmp (env_ptr, VECERR_NOTEQS); advance (1); additive (); add_op (OP_NOT_EQUAL, NULL); } else break; } } /*---------- additive ---------------------------------------------- * evaluates additive operators *------------------------------------------------------------------*/ static void additive () { multiplicative (); while (1) { skip_space (exp_ptr); if (*exp_ptr == '+') { advance (1); multiplicative (); add_op (OP_PLUS, NULL); } else if (*exp_ptr == '-') { advance (1); multiplicative (); add_op (OP_MINUS, NULL); } else break; } } /*---------- multiplicative ---------------------------------------- * evaluates multiplicative operators *------------------------------------------------------------------*/ static void multiplicative () { exponential (); while (1) { skip_space (exp_ptr); if (*exp_ptr == '*') { advance (1); exponential (); add_op (OP_MULTIPLY, NULL); } else if (*exp_ptr == '/') { advance (1); exponential (); add_op (OP_DIVIDE, NULL); } else if (*exp_ptr == '%') { advance (1); exponential (); add_op (OP_MODULUS, NULL); } else if (strchr (OPERATORS, *exp_ptr) == NULL) { exponential (); add_op (OP_MULTIPLY, NULL); } else break; } } /*---------- exponential ------------------------------------------- * evaluates exponential operators *------------------------------------------------------------------*/ static void exponential () { unary (); while (1) { skip_space (exp_ptr); if (*exp_ptr == '^') { advance (1); unary (); add_op (OP_POWER, NULL); } else if (*exp_ptr == '*' && *(exp_ptr+1) == '*') { advance (2); unary (); add_op (OP_POWER, NULL); } else break; } } /*---------- unary ------------------------------------------------- * evaluates unary operations *------------------------------------------------------------------*/ static void unary () { skip_space (exp_ptr); if (*exp_ptr == '-') { advance (1); expression (); add_op (OP_NEGATE, NULL); } else if (*exp_ptr == '!') { advance (1); expression (); add_op (OP_NOT, NULL); } else expression (); } /*---------- expression -------------------------------------------- * evaluates an expression *------------------------------------------------------------------*/ static void expression () { char *p; int i; size_t ii; double dval; VECDATA *vd; skip_space (exp_ptr); if (*exp_ptr == '(') { advance (1); logical (); skip_space (exp_ptr); if (*exp_ptr != ')') longjmp (env_ptr, VECERR_PAREN); advance (1); } else if (*exp_ptr == '[') { advance (1); p = exp_ptr; i = 0; while (*exp_ptr && *exp_ptr != ']' && vec_number (&dval, &exp_ptr)) { i++; skip_space (exp_ptr); if (*exp_ptr == ',') advance(1); } if (!i || *exp_ptr != ']') longjmp (env_ptr, VECERR_BADVEC); advance (1); vd = vec_create (VEC_VECTOR, i, 1); for (ii = 0; ii < vd->len; ii++) { vec_number (&dval, &p); vd->f.vec[ii] = (VECFLOAT)dval; skip_space (p); if (*p == ',') p++; } add_op (OP_VECTOR, (void *)vd); } else if (isdigit (*exp_ptr) || *exp_ptr == '.') { if (!vec_number (&dval, &exp_ptr)) longjmp (env_ptr, VECERR_BADNUM); add_op (OP_NUMBER, (void *)&dval); } else if (*exp_ptr == '\\') { advance (1); if (!do_userfunc() && !do_symbol() && !do_intrinsic()) longjmp (env_ptr, VECERR_SYMBOL); } else if (!do_intrinsic() && !do_symbol() && !do_userfunc()) longjmp (env_ptr, VECERR_SYMBOL); } /*================================================================== * processing routines *==================================================================*/ /*---------- push_var ---------------------------------------------- * push a variable on the stack *------------------------------------------------------------------*/ static void push_var (v) double v; { if (var_pos >= var_size) { var_size += STACK_INC; var_stack = (double *) realloc (var_stack, var_size * sizeof(double)); if (var_stack == NULL) longjmp (env_ptr, VECERR_PUSH); } var_stack[var_pos++] = v; } /*---------- pop_var ------------------------------------------------ * pop a variable from the stack *------------------------------------------------------------------*/ static void pop_var (v) double *v; { if (--var_pos < 0) longjmp (env_ptr, VECERR_POP); *v = var_stack[var_pos]; } /*---------- process_op -------------------------------------------- * processes the operation stack for given variables *------------------------------------------------------------------*/ static double process_op (n) int n; { int m, done = 0, level, index = 0; long j; struct op_stack_ *op; double f1, f2; while (op_index < op_pos && !done) { op = &op_start[op_index++]; switch (op->op) { case OP_NOP: case OP_BEGIN_FUNC: break; case OP_INTEGER: push_var ((double)op->op_val.ival); break; case OP_COUNTER: push_var ((double)(n + 1)); break; case OP_INDEX: pop_var (&f1); index = (int)(f1 + TOLERANCE); if (index < 1) longjmp (env_ptr, VECERR_BADINDX); if (op_index == op_pos) longjmp (env_ptr, VECERR_POP); op = &op_start[op_index++]; if (op->op != OP_VECTOR) longjmp (env_ptr, VECERR_INDEX); case OP_VECTOR: { VECFLOAT *vec = op->op_val.vec; if (!index) index = n + 1; if (--index < 0 || index >= (int)op->len) longjmp (env_ptr, VECERR_BADINDX); push_var ((double)(vec[index])); index = 0; break; } case OP_NUMBER: push_var (op->op_val.num); break; /* unary operations */ case OP_NEGATE: pop_var (&f1); push_var (-f1); break; case OP_NOT: pop_var (&f1); push_var ((double)(f1 == 0.0 ? 1 : 0)); break; /* arithmetic operations */ case OP_POWER: pop_var (&f2); pop_var (&f1); push_var (pow (f1, f2)); break; case OP_MULTIPLY: pop_var (&f2); pop_var (&f1); push_var (f1 * f2); break; case OP_DIVIDE: pop_var (&f2); pop_var (&f1); if (f2 == 0.0) longjmp (env_ptr, VECERR_DIVIDE); push_var (f1 / f2); break; case OP_MODULUS: pop_var (&f2); pop_var (&f1); push_var (fmod (f1, f2)); break; case OP_PLUS: pop_var (&f2); pop_var (&f1); push_var (f1 + f2); break; case OP_MINUS: pop_var (&f2); pop_var (&f1); push_var (f1 - f2); break; /* comparisons */ case OP_LESS: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 < f2 ? 1 : 0)); break; case OP_LESS_EQ: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 <= f2 ? 1 : 0)); break; case OP_GREATER: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 > f2 ? 1 : 0)); break; case OP_GREATER_EQ: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 >= f2 ? 1 : 0)); break; case OP_EQUALS: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 == f2 ? 1 : 0)); break; case OP_NOT_EQUAL: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 != f2 ? 1 : 0)); break; case OP_AND: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 && f2 ? 1 : 0)); break; case OP_OR: pop_var (&f2); pop_var (&f1); push_var ((double)(f1 || f2 ? 1 : 0)); break; /* if-then operation */ case OP_IF: level = ++nest_level; pop_var (&f1); if (f1 == 0.0) { /* skip if(TRUE) operations */ while (1) { op = &op_start[op_index++]; if (op->op == OP_ELSE) { if (level == nest_level) break; level--; } else if (op->op == OP_IF) level++; } } push_var (process_op (n)); nest_level--; break; case OP_ELSE: level = nest_level; while (1) { op = &op_start[op_index++]; if (op->op == OP_ENDIF) { if (level == nest_level) break; level--; } else if (op->op == OP_IF) level++; } case OP_ENDIF: if (nest_level) done = 1; break; /* functions which operate on the vectors */ case FUNC_MAX: case FUNC_MIN: case FUNC_SUM: case FUNC_AVG: case FUNC_SIZE: case FUNC_LEN: /* if currently processing vector, return */ if (vec_op) { done = 1; break; } /* else, first time here - find start of operations */ /* also check that all vectors are the same length */ index = op_index - 1; level = m = 0; while (op_start[--op_index].op != OP_BEGIN_FUNC) { if (op_start[op_index].op == OP_VECTOR) { if (!level) level = op_start[op_index].len; else if (level != op_start[op_index].len) longjmp (env_ptr, VECERR_VECLEN); } else if (op_start[op_index].op == OP_COUNTER) m = op_start[op_index].len; } if (!level && m) level = m; /* set BEGIN_FUNC op to NOP and set start of processing */ op_start[op_index].op = OP_NOP; vec_op = ++op_index; /* evaluate intrinsic function */ pop_var (&f1); if (op->op == FUNC_LEN) f1 = level ? level : 1; else { for (m = 1; m < level; m++) { op_index = vec_op; f2 = process_op (m); switch (op->op) { case FUNC_MAX: if (f1 < f2) f1 = f2; break; case FUNC_MIN: if (f1 > f2) f1 = f2; break; case FUNC_AVG: case FUNC_SUM: f1 += f2; break; case FUNC_SIZE: f1 += (f2 * f2); break; } } if (op->op == FUNC_AVG) f1 /= (double)(level ? level : 1); else if (op->op == FUNC_SIZE) f1 = sqrt (f1); } /* set stack ops to NOP */ for (m = vec_op; m < index; m++) op_start[m].op = OP_NOP; op = &op_start[index]; op_index = index + 1; vec_op = index = 0; /* put final result on stack */ op->op = OP_NUMBER; op->op_val.num = f1; push_var (f1); break; /* function operations */ case FUNC_ABS: pop_var (&f1); push_var (fabs (f1)); break; case FUNC_ACOS: pop_var (&f1); push_var (acos (f1)); break; case FUNC_ACOSH: pop_var (&f1); if (f1 < 1.0) longjmp (env_ptr, VECERR_ACOSH); push_var (log (f1 + sqrt (f1 * f1 - 1.0))); break; case FUNC_ASIN: pop_var (&f1); push_var (asin (f1)); break; case FUNC_ASINH: pop_var (&f1); push_var (log (f1 + sqrt (f1 * f1 + 1.0))); break; case FUNC_ATAN: pop_var (&f1); push_var (atan (f1)); break; case FUNC_ATAN2: pop_var (&f2); pop_var (&f1); push_var (atan2 (f1, f2)); break; case FUNC_ATANH: pop_var (&f1); if (f1 <= -1.0 || f1 >= 1.0) longjmp (env_ptr, VECERR_ATANH); push_var (0.5 * log ((1.0 + f1) / (1.0 - f1))); break; case FUNC_CEIL: pop_var (&f1); push_var (ceil (f1)); break; case FUNC_COSH: pop_var (&f1); push_var (cosh (f1)); break; case FUNC_COS: pop_var (&f1); push_var (cos (f1)); break; case FUNC_DEG: pop_var (&f1); push_var (f1 * 180.0 / PI); break; case FUNC_EXP: pop_var (&f1); push_var (exp (f1)); break; case FUNC_FACT: pop_var (&f1); j = (int)f1; f2 = j; if (j == 0) f2 = 1; else if (j > 0) { while (--j) f2 *= (double)j; } else { while (++j) f2 *= (double)j; } push_var (f2); break; case FUNC_FLOOR: pop_var (&f1); push_var (floor (f1)); break; case FUNC_LOG10: pop_var (&f1); push_var (log10 (f1)); break; case FUNC_LOG: pop_var (&f1); push_var (log (f1)); break; case FUNC_MOD: pop_var (&f2); pop_var (&f1); push_var (fmod (f1, f2)); break; case FUNC_POW: pop_var (&f2); pop_var (&f1); push_var (pow (f1, f2)); break; case FUNC_POW10: pop_var (&f1); push_var (pow (10.0, f1)); break; case FUNC_RAD: pop_var (&f1); push_var (f1 * PI / 180.0); break; case FUNC_RAND: push_var (vec_rand ()); break; case FUNC_ROUND: pop_var (&f1); if (fmod (f1, 1.0) >= 0.5) push_var (ceil (f1)); else push_var (floor (f1)); break; case FUNC_SINH: pop_var (&f1); push_var (sinh (f1)); break; case FUNC_SIN: pop_var (&f1); push_var (sin (f1)); break; case FUNC_SQRT: pop_var (&f1); push_var (sqrt (f1)); break; case FUNC_SQR: pop_var (&f1); push_var (f1 * f1); break; case FUNC_TANH: pop_var (&f1); push_var (tanh (f1)); break; case FUNC_TAN: pop_var (&f1); push_var (tan (f1)); break; default: longjmp (env_ptr, VECERR_OPERR); } } pop_var (&f1); return (f1); } /*=================================================================== * math exception handling *===================================================================*/ #ifdef _WIN32 #include #endif /*---------- fpe_err ----------------------------------------------- * signal handler for arithmetic exceptions *------------------------------------------------------------------*/ static SIGNAL fpe_err (int signum) { strcpy (err_msg[VECERR_MATH], "arithmetic exception (SIGFPE)"); #if defined(__MSDOS__) || defined(MSDOS) || defined(_WIN32) _fpreset (); #endif longjmp (env_ptr, VECERR_MATH); } #ifdef USE_MATHERR #ifdef _WIN32 #define matherr _matherr #define exception _exception #endif /*---------- matherr ----------------------------------------------- * use this math error handler, instead of library * This handles errors generated by math function calls *------------------------------------------------------------------*/ int matherr (e) struct exception *e; { switch (e->type) { case DOMAIN: sprintf (err_msg[VECERR_MATH], "%s : argument domain error", e->name); break; case SING: sprintf (err_msg[VECERR_MATH], "%s : argument singularity", e->name); break; case OVERFLOW: sprintf (err_msg[VECERR_MATH], "%s : overflow range error", e->name); break; case UNDERFLOW: sprintf (err_msg[VECERR_MATH], "%s : underflow range error", e->name); break; case PLOSS: sprintf (err_msg[VECERR_MATH], "%s : partial loss of significance", e->name); break; case TLOSS: sprintf (err_msg[VECERR_MATH], "%s : total loss of significance", e->name); break; default: sprintf (err_msg[VECERR_MATH], "%s : unknown error", e->name); break; } longjmp (env_ptr, VECERR_MATH); return (0); /* quite compiler */ } #endif /* USE_MATHERR */ /*========== print_op ============================================== * debug print out of operation stack *==================================================================*/ #ifdef VEC_DEBUG static char HEADER1[] = "op code pop push stack\n"; static char HEADER2[] = "------- --- ---- -----\n"; static char FORMAT[] = "%-20s%7d%7d%10d\n"; static char NUMFORM[] = "%-20.3g%7d%7d%10d\n"; void print_op (fp) FILE *fp; { int m, push, pop, stack_size = 0; char *opname; struct op_stack_ *op; if (op_size == 0) fprintf (fp, "OP STACK not created\n"); else if (op_pos == 0) fprintf (fp, "OP STACK is empty\n"); else { fprintf (fp, HEADER1); fprintf (fp, HEADER2); op_index = 0; while (op_index < op_pos) { op = &op_start[op_index++]; push = pop = 1; switch (op->op) { case OP_NOP: push = pop = 0; opname = "nop"; break; case OP_BEGIN_FUNC: push = pop = 0; opname = "beginfunc"; break; case OP_INTEGER: pop = 0; opname = "integer"; break; case OP_COUNTER: pop = 0; opname = "counter"; break; case OP_INDEX: push = 0; opname = "index"; break; case OP_VECTOR: pop = 0; opname = "vector"; break; case OP_NUMBER: pop = 0; opname = "number"; break; /* unary operations */ case OP_NEGATE: opname = "negate"; break; case OP_NOT: opname = "not"; break; /* arithmetic operations */ case OP_POWER: pop = 2; opname = "power"; break; case OP_MULTIPLY: pop = 2; opname = "multiply"; break; case OP_DIVIDE: pop = 2; opname = "divide"; break; case OP_MODULUS: pop = 2; opname = "modulus"; break; case OP_PLUS: pop = 2; opname = "plus"; break; case OP_MINUS: pop = 2; opname = "minus"; break; /* comparisons */ case OP_LESS: pop = 2; opname = "<"; break; case OP_LESS_EQ: pop = 2; opname = "<="; break; case OP_GREATER: pop = 2; opname = ">"; break; case OP_GREATER_EQ: pop = 2; opname = ">="; break; case OP_EQUALS: pop = 2; opname = "=="; break; case OP_NOT_EQUAL: pop = 2; opname = "!="; break; case OP_AND: pop = 2; opname = "and"; break; case OP_OR: pop = 2; opname = "or"; break; /* if-then operation */ case OP_IF: opname = "if"; break; case OP_ELSE: push = pop = 0; opname = "else"; break; case OP_ENDIF: push = pop = 0; opname = "endif"; break; /* functions which operate on the vectors */ case FUNC_MAX: opname = "max()"; break; case FUNC_MIN: opname = "min()"; break; case FUNC_SUM: opname = "sum()"; break; case FUNC_AVG: opname = "avg()"; break; case FUNC_SIZE: opname = "size()"; break; case FUNC_LEN: opname = "len()"; break; /* function operations */ case FUNC_ABS: opname = "abs()"; break; case FUNC_ACOS: opname = "acos()"; break; case FUNC_ACOSH: opname = "acosh()"; break; case FUNC_ASIN: opname = "asin()"; break; case FUNC_ASINH: opname = "asinh()"; break; case FUNC_ATAN: opname = "atan()"; break; case FUNC_ATANH: opname = "atanh()"; break; case FUNC_CEIL: opname = "ceil()"; break; case FUNC_COSH: opname = "cosh()"; break; case FUNC_COS: opname = "cos()"; break; case FUNC_DEG: opname = "deg()"; break; case FUNC_EXP: opname = "exp()"; break; case FUNC_FACT: opname = "fact()"; break; case FUNC_FLOOR: opname = "floor()"; break; case FUNC_LOG10: opname = "log10()"; break; case FUNC_LOG: opname = "log()"; break; case FUNC_POW10: opname = "pow10()"; break; case FUNC_RAD: opname = "rad()"; break; case FUNC_RAND: pop = 0; opname = "rand()"; break; case FUNC_ROUND: opname = "round()"; break; case FUNC_SINH: opname = "sinh()"; break; case FUNC_SIN: opname = "sin()"; break; case FUNC_SQRT: opname = "sqrt()"; break; case FUNC_SQR: opname = "sqr()"; break; case FUNC_TANH: opname = "tanh()"; break; case FUNC_TAN: opname = "tan()"; break; default: fprintf (fp, "UNREGOGNIZED op code\n"); return; } stack_size += (push - pop); fprintf (fp, FORMAT, opname, pop, push, stack_size); } fprintf (fp, FORMAT, "RESULT", 1, 0, --stack_size); } if (veclist == NULL) fprintf (fp, "Vector list is clear\n"); else { VECLIST *vl = veclist; m = 0; while (vl != NULL) { m++; vl = vl->prev; } fprintf (fp, "%d Vectors in vector list\n"); } } #endif /* VEC_DEBUG */ CGNS-3.4.0/src/cgnstools/calclib/vec.h000066400000000000000000000053111343724673500174070ustar00rootroot00000000000000/* * vec.h */ #ifndef _VEC_H_ #define _VEC_H_ #define VEC_MAXCALLS 10 /* max recursive calls */ /*----- vector data structure -----*/ #define VEC_VALUE 0 #define VEC_VECTOR 1 #define VEC_COMPLEX 2 typedef double VECFLOAT; typedef struct { int type; /* type of data */ size_t len; /* length of vector */ union { VECFLOAT val; /* single data value */ VECFLOAT *vec; /* vector data */ } f; } VECDATA; /*--- function prototypes ---*/ #ifdef __cplusplus extern "C" { #endif typedef VECDATA *(*VECFUNC)( int checking, /* set if checking string instead of parsing */ int nv, /* number of arguments */ VECDATA **v, /* arguments */ char **errmsg /* returned error message */ ); typedef VECDATA *(*VECCALL)( int checking, /* set if checking string instead of parsing */ char **pos, /* pointer to position in equation string */ char **errmsg /* returned error message */ ); VECDATA *vec_create ( /* create a vector data structure */ int type, /* type of data */ size_t len, /* length of vector */ int temp /* set if temporary */ ); void vec_destroy ( /* destroy a vector data structure */ VECDATA *vdata /* structure to destroy */ ); int vec_add ( /* add vector to temporary list */ VECDATA *vdata /* data to add */ ); void vec_remove ( /* remove vector from temporary list */ VECDATA *vdata /* data to remove */ ); void vec_free ( /* free internal memory */ void ); void vec_maxcalls ( /* sets maximum number recursive calls */ int maxcalls /* max recursive calls */ ); char *vec_errmsg ( /* returns error messages */ void ); char **vec_list ( /* return list of intrinsics */ void ); VECDATA *vec_parse ( /* parse and process equation */ char *str, /* equation string */ int min_len, /* minimum length of vector for counter */ VECCALL func /* user call-back for unknown symbols */ ); size_t vec_check ( /* parse equation and check for errors */ char *str, /* equation string */ int min_len, /* minimum length of vector for counter */ VECCALL func /* user call-back for unknown symbols */ ); int vec_number ( /* get floating point number from string */ double *dval, /* returned number */ char **sp /* updated string pointer */ ); void vec_randinit ( /* initialize random number generator */ int seed /* initialization seed */ ); double vec_rand ( /* return random floating point number */ void ); #ifdef __cplusplus } #endif #endif /* _VEC_H_ */ CGNS-3.4.0/src/cgnstools/calclib/vecerr.h000066400000000000000000000074551343724673500201330ustar00rootroot00000000000000#ifndef _VECERR_H_ #define _VECERR_H_ extern int vec_maxerr; /* max error code */ extern int vec_errnum; /* error number */ /*----- user error handler -----*/ extern void (*vec_errhandler) ( /* user error handler */ int errnum, /* error number */ char *errmsg, /* error message */ int offset, /* offset in parse string */ char *exp /* expression being parsed */ ); /*----- error codes -----*/ enum VecErrors { VECERR_NOERR=0, /* sucessfull evaluation */ VECERR_SYMBOL, /* unrecognized or invalid symbol */ VECERR_BADEXPR, /* bad expression */ VECERR_NOEXPR, /* NULL or blank expression string argument */ VECERR_FUNC, /* function name not followed by '(' */ VECERR_DIVIDE, /* math error: divide by 0 */ VECERR_PAREN, /* '(' without ')' */ VECERR_IFELSE, /* if (?) without else (:) */ VECERR_EQUALS, /* '=' instead of '==' */ VECERR_NOTEQS, /* '!' instead of '!=' */ VECERR_MATH, /* general math error */ VECERR_MISSING, /* missing operator */ VECERR_POINTER, /* user function did not update pointer */ VECERR_CALLS, /* too many recursive calls */ VECERR_BADNUM, /* single '.' not preceeded/followed by digit */ VECERR_RECURSE, /* recursion in expression detected */ VECERR_ARGS, /* function argument list error */ VECERR_MAXARGS, /* user function has too many arguments */ VECERR_MALLOC, /* malloc failed */ VECERR_OPERR, /* internal error - op code */ VECERR_PUSH, /* out of space for variable stack */ VECERR_POP, /* tried to pop empty variable stack */ VECERR_OP_STK, /* couldn't malloc/realloc operation stack */ VECERR_VAR_STK, /* couldn't malloc variable stack */ VECERR_BRACKET, /* '[' without ']' */ VECERR_NOVECT, /* couldn't malloc vector data */ VECERR_VECLEN, /* vector lengths not the same */ VECERR_INDEX, /* index not associated with a variable */ VECERR_BADINDX, /* index out of range of vector data */ VECERR_VECTYPE, /* bad vector data type */ VECERR_ZEROLEN, /* vector len < 1 */ VECERR_EQUARG, /* equation argument out of range */ VECERR_ACOSH, /* argument to acosh < 1 */ VECERR_ATANH, /* argument to atanh <= -1 or >= 1 */ VECERR_BADVEC, /* bad vector specification */ VECERR_USER, /* user call-back function error */ VECERR_INVALID /* invalid error message number */ }; #ifdef INCLUDE_ERRDATA /*----- error messages -----*/ static char *err_msg[] = { "sucessfull evaluation", "unrecognized or invalid symbol", "bad expression", "NULL or blank expression string argument", "function name not followed by '('", "math error: divide by 0", "'(' without ')'", "if (?) without else (:)", "'=' instead of '=='", "'!' instead of '!='", " ", "missing operator", "user function did not update pointer", "too many recursive calls", "single '.' not preceeded or followed by digit", "recursion in expression detected", "function argument list error", "user function has too many arguments", "malloc failed", "internal error - op code", "out of space for variable stack", "tried to pop empty variable stack", "couldn't malloc/realloc operation stack", "couldn't malloc variable stack", "'[' without ']'", "couldn't malloc vector data", "vector lengths not the same", "index not associated with a variable", "index out of range of vector data", "bad vector data type", "vector len < 1", "equation argument out of range", "argument to acosh() < 1", "argument to atanh() <= -1 or >= 1", "bad vector specification", NULL, "invalid error message number" }; #endif /* INCLUDE_ERRDATA */ #endif /* _VECERR_H_ */ CGNS-3.4.0/src/cgnstools/calclib/vecsym.c000066400000000000000000000361021343724673500201350ustar00rootroot00000000000000/* * vecsym.c - symbol table for vector processor */ #include #include #include #include #include "vecsym.h" #define HASH_SIZE 127 /* size of hash table */ static VECSYM *hash_table[HASH_SIZE];/* user symbol hash table */ static int num_symbols = 0; /* number symbols in hash table */ static int max_namelen = 0; /* max length of user symbol name */ /*----- error mesages -----*/ static char *errmsg[] = { "no error", "NULL or blank symbol name", "NULL or blank equation string", "failed to add new symbol to symbol table", "malloc failed - out of space", "NULL funtion pointer", "user function has too many arguments", "0 length or NULL vector", "symbol name too long", "invalid error code" }; /*----- callback for deleting symbol -----*/ void (*sym_delfunc) (struct symbol_ *) = NULL; /*----- local functions -----*/ static void init_hash(void); static int hash_name(char *name); static VECSYM *add_symbol(char *name); /*================================================================== * these routines are needed by vec.c *==================================================================*/ /*---------- find_symbol ------------------------------------------- * find a symbol in the hash table *------------------------------------------------------------------*/ VECSYM *find_symbol (char *name, int is_func) { VECSYM *sym; if (!num_symbols) return (NULL); sym = hash_table[hash_name (name)]; while (sym != NULL) { if (strcmp (name, vecsym_name(sym)) == 0) { if (vecsym_type(sym) == VECSYM_FUNC) return (is_func ? sym : NULL); if (vecsym_type(sym) == VECSYM_EQUSTR || vecsym_type(sym) == VECSYM_MACRO) { if (vecsym_nargs(sym) > 0) return (is_func ? sym : NULL); return (sym); } return (is_func ? NULL : sym); } sym = sym->next; } return (NULL); } /*================================================================== * hashing routines for user symbols *==================================================================*/ /*---------- init_hash --------------------------------------------- * initialize hash table *------------------------------------------------------------------*/ static void init_hash (void) { int n; for (n = 0; n < HASH_SIZE; n++) hash_table[n] = NULL; } /*---------- hash_name --------------------------------------------- * hashing routine *------------------------------------------------------------------*/ static int hash_name (char *name) { unsigned long hash = 0; while (*name) hash += *name++; return ((int)(hash % HASH_SIZE)); } /*---------- add_symbol -------------------------------------------- * add a symbol to the hash table *------------------------------------------------------------------*/ static VECSYM *add_symbol (char *name) { int hash = hash_name (name); VECSYM *sym = hash_table[hash]; while (sym != NULL) { if (strcmp (name, vecsym_name(sym)) == 0) { if (vecsym_type(sym) == VECSYM_EQUSTR) free (vecsym_equstr(sym)); else if (vecsym_type(sym) == VECSYM_MACRO) free (vecsym_macro(sym)); else if (vecsym_type(sym) == VECSYM_VECTOR) free (vecsym_vector(sym)); return (sym); } sym = sym->next; } sym = (VECSYM *) malloc (sizeof(VECSYM)); if (sym != NULL) { int len = (int)strlen (name); strcpy (vecsym_name(sym), name); sym->next = hash_table[hash]; hash_table[hash] = sym; num_symbols++; if (max_namelen < len) max_namelen = len; } return (sym); } /*---------- sym_free ---------------------------------------------- * free symbol table resources *------------------------------------------------------------------*/ void sym_free (void) { int n; VECSYM *sym, *next; if (!num_symbols) return; for (n = 0; n < HASH_SIZE; n++) { sym = hash_table[n]; while (sym != NULL) { next = sym->next; if (sym_delfunc != NULL) (*sym_delfunc) (sym); if (vecsym_type(sym) == VECSYM_EQUSTR) free (vecsym_equstr(sym)); else if (vecsym_type(sym) == VECSYM_MACRO) free (vecsym_macro(sym)); else if (vecsym_type(sym) == VECSYM_VECTOR) free (vecsym_vector(sym)); free (sym); sym = next; } hash_table[n] = NULL; } num_symbols = 0; max_namelen = 0; } /*---------- sym_errmsg --------------------------------------------- * returns error message *-------------------------------------------------------------------*/ char *sym_errmsg (int errnum) { if (errnum >= 0 && errnum < SYMERR_INVALID) return (errmsg[errnum]); return (errmsg[SYMERR_INVALID]); } /*---------- sym_addval -------------------------------------------- * adds a value to user symbol table *------------------------------------------------------------------*/ int sym_addval (char *name, VECFLOAT val, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_type(sym) = VECSYM_VALUE; vecsym_nargs(sym) = 0; vecsym_veclen(sym) = 0; vecsym_value(sym) = val; vecsym_user(sym) = user; return (0); } /*---------- sym_addvec -------------------------------------------- * adds a vector to user symbol table *------------------------------------------------------------------*/ int sym_addvec (char *name, size_t len, VECFLOAT *vec, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (len < 1 || vec == NULL) return (SYMERR_NOVEC); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_vector(sym) = (VECFLOAT *) malloc (len * sizeof(VECFLOAT)); if (vecsym_vector(sym) == NULL) { vecsym_type(sym) = VECSYM_VALUE; sym_delsym (name); return (SYMERR_MALLOC); } vecsym_type(sym) = VECSYM_VECTOR; vecsym_nargs(sym) = 0; vecsym_veclen(sym) = len; vecsym_user(sym) = user; memcpy (vecsym_vector(sym), vec, len * sizeof(VECFLOAT)); return (0); } /*---------- sym_addequ -------------------------------------------- * adds an equation to user symbol table *------------------------------------------------------------------*/ int sym_addequ (char *name, int nargs, char *equ, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (equ == NULL) return (SYMERR_NOEXPR); while (*equ && isspace (*equ)) equ++; if (!*equ) return (SYMERR_NOEXPR); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_equstr(sym) = (char *) malloc (strlen (equ) + 1); if (vecsym_equstr(sym) == NULL) { vecsym_type(sym) = VECSYM_VALUE; sym_delsym (name); return (SYMERR_MALLOC); } vecsym_type(sym) = VECSYM_EQUSTR; vecsym_nargs(sym) = nargs; vecsym_user(sym) = user; strcpy (vecsym_equstr(sym), equ); return (0); } /*---------- sym_addfunc ------------------------------------------- * adds a function to user symbol table *------------------------------------------------------------------*/ int sym_addfunc (char *name, int nargs, VECFUNC func, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (func == NULL) return (SYMERR_NOFUNC); if (nargs > FUNC_MAXARGS) return (SYMERR_MAXARGS); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_type(sym) = VECSYM_FUNC; vecsym_nargs(sym) = nargs; vecsym_func(sym) = func; vecsym_user(sym) = user; return (0); } /*---------- sym_addmacro ------------------------------------------ * adds a macro to user symbol table *------------------------------------------------------------------*/ int sym_addmacro (char *name, int nargs, char *macro, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (macro == NULL) return (SYMERR_NOEXPR); while (*macro && isspace (*macro)) macro++; if (!*macro) return (SYMERR_NOEXPR); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_macro(sym) = (char *) malloc (strlen (macro) + 1); if (vecsym_macro(sym) == NULL) { vecsym_type(sym) = VECSYM_VALUE; sym_delsym (name); return (SYMERR_MALLOC); } vecsym_type(sym) = VECSYM_MACRO; vecsym_nargs(sym) = nargs; vecsym_user(sym) = user; strcpy (vecsym_macro(sym), macro); return (0); } /*---------- sym_adddata ------------------------------------------- * adds user data to user symbol table *------------------------------------------------------------------*/ int sym_adddata (char *name, void *data, void *user) { VECSYM *sym; if (name == NULL || !*name) return (SYMERR_NONAME); if (strlen (name) > SYMNAME_MAXLEN) return (SYMERR_TOOLONG); if (!num_symbols) init_hash (); if ((sym = add_symbol (name)) == NULL) return (SYMERR_SYMTABLE); vecsym_type(sym) = VECSYM_DATA; vecsym_nargs(sym) = 0; vecsym_data(sym) = data; vecsym_user(sym) = user; return (0); } /*---------- sym_delsym ---------------------------------------------- * delete a symbol from the symbol table *--------------------------------------------------------------------*/ void sym_delsym (char *name) { VECSYM *sym, *prev; int hash; if (!num_symbols || name == NULL || !*name) return; hash = hash_name (name); if ((prev = hash_table[hash]) == NULL) return; if (strcmp (name, vecsym_name(prev)) == 0) { hash_table[hash] = prev->next; if (sym_delfunc != NULL) (*sym_delfunc) (prev); if (vecsym_type(prev) == VECSYM_EQUSTR) free (vecsym_equstr(prev)); else if (vecsym_type(prev) == VECSYM_MACRO) free (vecsym_macro(prev)); else if (vecsym_type(prev) == VECSYM_VECTOR) free (vecsym_vector(prev)); free (prev); return; } sym = prev->next; while (sym != NULL) { if (strcmp (name, vecsym_name(sym)) == 0) { prev->next = sym->next; if (sym_delfunc != NULL) (*sym_delfunc) (sym); if (vecsym_type(sym) == VECSYM_EQUSTR) free (vecsym_equstr(sym)); else if (vecsym_type(sym) == VECSYM_MACRO) free (vecsym_macro(sym)); else if (vecsym_type(sym) == VECSYM_VECTOR) free (vecsym_vector(sym)); free (sym); return; } prev = sym; sym = prev->next; } } /*---------- sym_count --------------------------------------------- * return number of symbols of given type *------------------------------------------------------------------*/ int sym_count (int type) { int n, cnt = 0; VECSYM *sym; if (num_symbols) { for (n = 0; n < HASH_SIZE; n++) { sym = hash_table[n]; while (sym != NULL) { if (!type || vecsym_type(sym) == type) cnt++; sym = sym->next; } } } return (cnt); } /*---------- sym_names --------------------------------------------- * return list of symbol names *------------------------------------------------------------------*/ char **sym_names (int type) { int n, cnt = sym_count (type); VECSYM *sym; char **names = NULL; if (cnt) { names = (char **) malloc ((cnt+1) * sizeof(char *)); if (NULL == names) return (NULL); for (n = 0, cnt = 0; n < HASH_SIZE; n++) { sym = hash_table[n]; while (sym != NULL) { if (!type || vecsym_type(sym) == type) names[cnt++] = vecsym_name(sym); sym = sym->next; } } names[cnt] = NULL; } return (names); } /*---------- sym_list ---------------------------------------------- * lists symbols *------------------------------------------------------------------*/ int sym_list (int type, int (*func)(struct symbol_ *, void *), void *userdata) { int n, cnt = 0; VECSYM *sym; if (num_symbols && NULL != func) { for (n = 0; n < HASH_SIZE; n++) { sym = hash_table[n]; while (sym != NULL) { if (!type || vecsym_type(sym) == type) cnt += (*func) (sym, userdata); sym = sym->next; } } } return (cnt); } /*---------- sym_print --------------------------------------------- * print symbol list *------------------------------------------------------------------*/ void sym_print (FILE *fp) { int i, fld; VECSYM *sym; if (!num_symbols) { fprintf (fp, "\nNo Symbols defined\n"); return; } fld = max_namelen > 5 ? max_namelen : 5; fprintf (fp, "Defined Symbols:\n"); fprintf (fp, "%-*s Type Nargs/Expression/Value/Length\n", fld, "Name"); i = fld + 43; while (i--) putc ('-', fp); putc ('\n', fp); for (i = 0; i < HASH_SIZE; i++) { sym = hash_table[i]; while (sym != NULL) { fprintf (fp, "%-*.*s ", fld, fld, vecsym_name(sym)); if (vecsym_type(sym) == VECSYM_VALUE) fprintf (fp, "value %g\n", vecsym_value(sym)); else if (vecsym_type(sym) == VECSYM_VECTOR) fprintf (fp, "vector %ld\n", (long)vecsym_veclen(sym)); else if (vecsym_type(sym) == VECSYM_EQUSTR) fprintf (fp, "equation %s\n", vecsym_equstr(sym)); else if (vecsym_type(sym) == VECSYM_MACRO) fprintf (fp, "macro %s\n", vecsym_macro(sym)); else if (vecsym_type(sym) == VECSYM_FUNC) { fprintf (fp, "function "); if (vecsym_nargs(sym) < 0) fprintf (fp, "variable\n"); else fprintf (fp, "%d\n", vecsym_nargs(sym)); } else if (vecsym_type(sym) == VECSYM_DATA) fprintf (fp, "user data\n"); else fprintf (fp, "unknown type\n"); sym = sym->next; } } } CGNS-3.4.0/src/cgnstools/calclib/vecsym.h000066400000000000000000000113651343724673500201460ustar00rootroot00000000000000/* * vecsym.h - symbol table interface for vec.c */ #ifndef _VECSYM_H_ #define _VECSYM_H_ /*=================================================================== * none of this is used directly by vec.c * The symbol structure is used indirectly, however, through * the macros defined below *===================================================================*/ #include #ifndef _VEC_H_ #include "vec.h" /* for definition of VECDATA */ #endif /*----- error return codes -----*/ enum SymErrors { SYMERR_NOERR=0, /* no error */ SYMERR_NONAME, /* NULL or blank symbol name */ SYMERR_NOEXPR, /* NULL or blank equation string */ SYMERR_SYMTABLE,/* failed to add new symbol to symbol table */ SYMERR_MALLOC, /* malloc failed - out of space */ SYMERR_NOFUNC, /* NULL function pointer */ SYMERR_MAXARGS, /* user function has too many arguments */ SYMERR_NOVEC, /* 0 length or NULL vector */ SYMERR_TOOLONG, /* symbol name too long */ SYMERR_INVALID /* invalid error code */ }; /*----- symbol table structure -----*/ #define SYMNAME_MAXLEN 32 struct symbol_ { char name[SYMNAME_MAXLEN+1]; int type; int nargs; size_t len; union { VECFLOAT val; VECFLOAT *vec; char *equ; VECFUNC func; void *data; } op; void *user; struct symbol_ *next; }; /*----- callback for deleting a symbol -----*/ extern void (*sym_delfunc) (struct symbol_ *); /*----- function prototypes -----*/ void sym_free (void); /* free symbol table */ char *sym_errmsg ( /* get error message */ int errnum /* error number */ ); int sym_addval ( /* add value symbol */ char *name, /* symbol name */ VECFLOAT val, /* symbol value */ void *user /* user data */ ); int sym_addvec ( /* add vector symbol */ char *name, /* symbol name */ size_t len, /* vector length */ VECFLOAT *vec, /* vector */ void *user /* user data */ ); int sym_addequ ( /* add equation symbol */ char *name, /* symbol name */ int nargs, /* number of arguments */ char *equ, /* equation string */ void *user /* user data */ ); int sym_addfunc ( /* add function symbol */ char *name, /* symbol name */ int nargs, /* number of arguments */ VECFUNC func, /* function pointer */ void *user /* user data */ ); int sym_addmacro ( /* add macro symbol */ char *name, /* symbol name */ int nargs, /* number of arguments */ char *equ, /* macro string */ void *user /* user data */ ); int sym_adddata ( /* add user data symbol */ char *name, /* symbol name */ void *data, /* symbol data */ void *user /* user data */ ); void sym_delsym ( /* remove symbol */ char *name /* symbol name */ ); int sym_count ( /* count number of symbols */ int type /* symbol type (0 for all) */ ); char **sym_names ( /* return NULL terminated list of symbol names */ int type /* symbol type (0 for all) */ ); int sym_list ( /* list symbols */ int type, /* symbol type (0 for all) */ int (*func) ( /* callback function for list */ struct symbol_ *, /* symbol */ void * /* user data */ ), void *userdata /* user data */ ); void sym_print ( /* print list of symbols */ FILE *fp /* where output goes */ ); /*=================================================================== * the following need to be defined for use by vec.c *===================================================================*/ /*----- symbol definition -----*/ typedef struct symbol_ VECSYM; /*----- maximum arguments to a function -----*/ #define FUNC_MAXARGS 5 /*----- symbol types -----*/ #define VECSYM_VALUE 1 /* constant value */ #define VECSYM_VECTOR 2 /* vector */ #define VECSYM_EQUSTR 3 /* equation string */ #define VECSYM_FUNC 4 /* user function */ #define VECSYM_MACRO 5 /* macro string */ #define VECSYM_DATA 6 /* user data */ /*----- macros for accessing symbols -----*/ #define vecsym_name(SYM) ((SYM)->name) #define vecsym_type(SYM) ((SYM)->type) #define vecsym_user(SYM) ((SYM)->user) #define vecsym_value(SYM) ((SYM)->op.val) #define vecsym_veclen(SYM) ((SYM)->len) #define vecsym_vector(SYM) ((SYM)->op.vec) #define vecsym_nargs(SYM) ((SYM)->nargs) #define vecsym_equstr(SYM) ((SYM)->op.equ) #define vecsym_macro(SYM) ((SYM)->op.equ) #define vecsym_func(SYM) ((SYM)->op.func) #define vecsym_data(SYM) ((SYM)->op.data) /*----- function prototypes -----*/ VECSYM *find_symbol ( /* find a symbol */ char *name, /* symbol name */ int is_func /* non-zero if symbol is a function */ ); #endif /* _VECSYM_H_ */ CGNS-3.4.0/src/cgnstools/cgconfig.in000066400000000000000000000023631343724673500172030ustar00rootroot00000000000000#--------------------------------------------------------------------- # this is where the executables and tcl scripts # may be found after installation #--------------------------------------------------------------------- CG_BIN_DIR=@CG_BIN_DIR@; export CG_BIN_DIR CG_LIB_DIR=@CG_LIB_DIR@; export CG_LIB_DIR #--------------------------------------------------------------------- # you may need to set the paths to the Tcl/Tk scripts # if the system can't find them. If using shared libraries, # you may also need to modify LD_LIBRARY_PATH to include # the directories where libtcl.so and libtk.so are located # # for example, if Tcl/Tk built locally under Unix/Linux # using shared libraries, then set # # TCL_ROOT=$HOME/tcl8.3 # TK_ROOT=$HOME/tk8.3 # export TCL_LIBRARY=$TCL_ROOT/library # export TK_LIBRARY=$TK_ROOT/library # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TCL_ROOT/unix:$TK_ROOT/unix # # running under Cygwin, may need (assuming Tcl/Tk 8.0) # # sharedir=`cygpath -m /usr/share` # export TCL_LIBRARY=$sharedir/tcl8.0 # export TK_LIBRARY=$sharedir/tk8.0 # # under SGI, may need LD_LIBRARYN32_PATH instead #---------------------------------------------------------------------- @TCL_LIBRARY_SPEC@ @TK_LIBRARY_SPEC@ @LIBRARY_PATH_SPEC@ CGNS-3.4.0/src/cgnstools/cgnscalc/000077500000000000000000000000001343724673500166455ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/cgnscalc/CMakeLists.txt000066400000000000000000000043111343724673500214040ustar00rootroot00000000000000############ # cgnscalc # ############ include_directories(${TCL_INCLUDE_PATH} ${TK_INCLUDE_PATH}) include_directories(../calclib) link_directories(.) if (CGNS_USE_SHARED) link_libraries(cgns_shared) else (CGNS_USE_SHARED) link_libraries(cgns_static) endif (CGNS_USE_SHARED) link_libraries(calclib ${TCL_LIBRARY} ${TK_LIBRARY}) if (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) link_libraries(${HDF5_LIBRARY}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) link_libraries(${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) link_libraries(${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) link_libraries(${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) if (WIN32) if (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) add_definitions(-DUSE_HTMLHELP) include_directories(${HTML_HELP_INCLUDE_PATH}) link_libraries(${HTML_HELP_LIBRARY}) set(cgnscalc_FILES calctcl.c winmain.c ../common/winhtml.c) else (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) set(cgnscalc_FILES calctcl.c winmain.c) endif (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) else (WIN32) include_directories(${X11_X11_INCLUDE_PATH}) link_libraries(${X11_X11_LIB} m) set(cgnscalc_FILES calctcl.c calcwish.c) endif (WIN32) add_executable(calcwish ${cgnscalc_FILES}) add_dependencies(calcwish calclib cgns_static) if (WIN32) set_target_properties(calcwish PROPERTIES LINK_FLAGS /subsystem:windows) endif (WIN32) if (WIN32) install(TARGETS calcwish RUNTIME DESTINATION bin) install(PROGRAMS cgnscalc.bat unitconv.bat DESTINATION bin) install(FILES cgnscalc.tcl unitconv.tcl cgnscalc.ico cgnscalc.png cgnscalc-icon.xbm cgnscalc-mask.xbm unitconv.ico unitconv.png unitconv.xbm DESTINATION share) else (WIN32) install(TARGETS calcwish RUNTIME DESTINATION bin/cgnstools) install(PROGRAMS cgnscalc.sh DESTINATION bin RENAME cgnscalc) install(PROGRAMS unitconv.sh DESTINATION bin RENAME unitconv) install(FILES cgnscalc.tcl unitconv.tcl cgnscalc.ico cgnscalc.png cgnscalc-icon.xbm cgnscalc-mask.xbm unitconv.ico unitconv.png unitconv.xbm DESTINATION share/cgnstools) endif (WIN32) CGNS-3.4.0/src/cgnstools/cgnscalc/Makefile.unix000066400000000000000000000052461343724673500212760ustar00rootroot00000000000000# Makefile for Unix/Linux include ../make.defs CALCDIR = ../calclib CALCLIB = $(CALCDIR)/libcgnscalc.$(A) COPTS = $(CFLAGS) -I$(CGNSDIR) -I$(CALCDIR) $(TKINCS) LDLIST = $(CALCLIB) $(CGNSLIB) $(BUILDLIBS) $(TKLIBS) $(X11LIBS) $(CLIBS) #-------------------------------------------------- calcwish$(EXE) : calcwish.$(O) calctcl.$(O) $(CALCLIB) $(CC) $(LDFLAGS) -o $@ calcwish.$(O) calctcl.$(O) $(LDLIST) $(STRIP) $@ calcwish.$(O) : calcwish.c calctcl.$(O) : calctcl.c $(CALCLIB) : cd $(CALCDIR) && $(MAKE) #--------------------------------------------------------------- SCRIPTS = cgnscalc.tcl unitconv.tcl ICONS = cgnscalc.ico cgnscalc.png cgnscalc-icon.xbm cgnscalc-mask.xbm \ unitconv.ico unitconv.png unitconv.xbm install : install-dirs install-prog install-wish install-script install-dirs : @for d in \ $(BIN_INSTALL_DIR) \ $(EXE_INSTALL_DIR) \ $(WSH_INSTALL_DIR) \ $(LIB_INSTALL_DIR) ; do \ if [ ! -d $$d ] ; then \ echo "Making directory $$d"; \ mkdir -p $$d; \ chmod 755 $$d; \ fi; \ done; install-prog : @echo "installing cgnscalc shell scripts to $(BIN_INSTALL_DIR)" @$(INSTALL_PROG) cgnscalc.sh $(BIN_INSTALL_DIR)/cgnscalc @chmod +x $(BIN_INSTALL_DIR)/cgnscalc @$(INSTALL_PROG) unitconv.sh $(BIN_INSTALL_DIR)/unitconv @chmod +x $(BIN_INSTALL_DIR)/unitconv @if [ ! -f $(EXE_INSTALL_DIR)/cgconfig ] ; then \ echo "installing configuration file to $(EXE_INSTALL_DIR)"; \ $(INSTALL_DATA) ../cgconfig $(EXE_INSTALL_DIR)/cgconfig; \ fi; install-wish : calcwish$(EXE) @echo "installing calcwish executable to $(WSH_INSTALL_DIR)" @$(INSTALL_PROG) calcwish$(EXE) $(WSH_INSTALL_DIR) install-script : @echo "installing tcl scripts to $(LIB_INSTALL_DIR)" @for i in $(SCRIPTS) ; do \ $(INSTALL_DATA) $$i $(LIB_INSTALL_DIR); \ done; @echo "installing icons to $(LIB_INSTALL_DIR)" @for i in $(ICONS) ; do \ $(INSTALL_DATA) $$i $(LIB_INSTALL_DIR); \ done; uninstall : @echo "uninstalling cgnscalc executables" @for i in cgnscalc unitconv ; do \ if [ -f $(BIN_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(BIN_INSTALL_DIR)/$$i; \ fi; \ done; @if [ -f $(WSH_INSTALL_DIR)/calcwish$(EXE) ] ; then \ /bin/rm -f $(WSH_INSTALL_DIR)/calcwish$(EXE); \ fi; @echo "uninstalling cgnscalc tcl scripts" @for i in $(SCRIPTS) ; do \ if [ -f $(LIB_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/$$i; \ fi; \ done; @echo "uninstalling cgnscalc icons" @for i in $(ICONS) ; do \ if [ -f $(LIB_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/$$i; \ fi; \ done; #--------------------------------------------------------------- .c.$(O) : $(CC) $(COPTS) -c $< clean: -$(RM) *.$(O) *~ *.bak calcwish$(EXE) CGNS-3.4.0/src/cgnstools/cgnscalc/Makefile.win000066400000000000000000000032441343724673500211040ustar00rootroot00000000000000include ..\make.win CALCDIR = ..\calclib CALCLIB = $(CALCDIR)\cgnscalc.lib COPTS = $(CFLAGS) -I$(CGNSDIR) -I$(CALCDIR) $(TCLINC) #-------------------------------------------------- all : calcwish.exe dll : calctcl.dll install : calcwish.exe $(BINDIR) $(SHAREDIR) -$(INSTALL) cgnscalc.bat $(BINDIR) -$(INSTALL) calcwish.exe $(BINDIR) -$(INSTALL) unitconv.bat $(BINDIR) -$(INSTALL) cgnscalc.tcl $(SHAREDIR) -$(INSTALL) unitconv.tcl $(SHAREDIR) -$(INSTALL) *.ico $(SHAREDIR) $(BINDIR) : $(INSTALLDIR) -mkdir $(BINDIR) $(SHAREDIR) : $(INSTALLDIR) -mkdir $(SHAREDIR) $(INSTALLDIR) : -mkdir $(INSTALLDIR) #-------------------------------------------------- calcwish.exe : winmain.obj calctcl.obj $(CALCLIB) $(WINHTML_OBJ) $(LINK) $(LFLAGS) /nodefaultlib /subsystem:windows \ -out:$@ winmain.obj calctcl.obj $(WINHTML_OBJ) $(CALCLIB) \ $(CGNSLIB) $(BUILDLIBS) $(CLIBS) $(TCLLIB) $(TKLIB) \ $(guilibs) $(WINHTML_LIB) calctcl.obj : calctcl.c winmain.obj : winmain.c $(CC) $(COPTS) $(WINHTML_OPT) -c winmain.c #-------------------------------------------------- calctcl.dll : calctcl-dll.obj $(CALCLIB) $(CGNSLIB) $(LINK) -dll -out:calctcl.dll calctcl-dll.obj \ $(CALCLIB) $(CGNSLIB) $(BUILDLIBS) $(CLIBS) $(TCLLIB) $(TKLIB) $(dlllibs) calctcl-dll.obj : calctcl.c $(CC) $(COPTS) -DBUILD_DLL -Fo$@ -c calctcl.c #-------------------------------------------------- winhtml.obj : ..\common\winhtml.c $(CC) $(COPTS) $(WINHTML_INC) -Fowinhtml.obj -c ..\common\winhtml.c #-------------------------------------------------- .c.obj : $(CC) $(COPTS) -Fo$@ -c $< clean: -$(RM) *.obj -$(RM) *.lib -$(RM) *.exp -$(RM) *.exe -$(RM) *.pdb -$(RM) *.ilk -$(RM) *.dll -$(RM) *.bak CGNS-3.4.0/src/cgnstools/cgnscalc/calctcl.c000066400000000000000000000631721343724673500204270ustar00rootroot00000000000000#include #include #include #include #include #include "tcl.h" #include "calc.h" #include "cgnslib.h" #ifndef CONST # define CONST #endif static Tcl_Interp *global_interp; static char message[1024] = ""; /*---------- get_error ----------------------------------------------- * gets error message on parsing error *--------------------------------------------------------------------*/ static void get_error (int errnum, char *errmsg, int pos, char *str) { char *p = message; if (errnum < 0) { sprintf (message, "error_exit {%s}", errmsg); Tcl_Eval (global_interp, message); } if (NULL != str) { sprintf (p, "%s\n", str); p += strlen (p); while (pos-- > 0) *p++ = '-'; *p++ = '^'; } strcpy (p, errmsg); } /*---------- get_names ---------------------------------------------- * collect symbol names into Tcl interp result *-------------------------------------------------------------------*/ static int get_names (VECSYM *sym, void *data) { Tcl_Interp *interp = (Tcl_Interp *)data; if (VECSYM_EQUSTR == vecsym_type(sym)) { if (vecsym_nargs(sym) > 0) sprintf (message, "%s(%d)", vecsym_name(sym), vecsym_nargs(sym)); else strcpy (message, vecsym_name(sym)); } else if (VECSYM_FUNC == vecsym_type(sym)) { if (vecsym_nargs(sym) < 0) sprintf (message, "%s(...)", vecsym_name(sym)); else sprintf (message, "%s(%d)", vecsym_name(sym), vecsym_nargs(sym)); } else if (VECSYM_VECTOR == vecsym_type(sym)) sprintf (message, "%s[%ld]", vecsym_name(sym), (long)vecsym_veclen(sym)); else strcpy (message, vecsym_name(sym)); Tcl_AppendElement (interp, message); return 0; } /*---------- CalcReset --------------------------------------------- * reset calculator (symbol table) *------------------------------------------------------------------*/ static int CalcReset (ClientData data, Tcl_Interp *interp, int argc, char **argv) { cgnsCalcReset (); return TCL_OK; } /*---------- CalcInit ---------------------------------------------- * load CGNS file and initialize *------------------------------------------------------------------*/ static int CalcInit (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int nb, idum, modify = 0; char name[33]; Tcl_ResetResult (interp); if (argc != 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " mode CGNSfile\"", NULL); return TCL_ERROR; } if (argv[1][0] == 'w' || argv[1][0] == 'm') modify = 1; cgnsCalcInit (argv[2], modify, get_error); for (nb = 1; nb <= NumBases; nb++) { if (cg_base_read (cgnsFile, nb, name, &idum, &idum)) cgnsCalcFatal ((char *)cg_get_error()); Tcl_AppendElement (interp, name); } return TCL_OK; } /*---------- CalcDone ---------------------------------------------- * close CGNS file *------------------------------------------------------------------*/ static int CalcDone (ClientData data, Tcl_Interp *interp, int argc, char **argv) { cgnsCalcDone (); return TCL_OK; } /*---------- CalcBase ---------------------------------------------- * set base for calculations *------------------------------------------------------------------*/ static int CalcBase (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int nb, nz; cgsize_t sizes[9]; char name[33]; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " base\"", NULL); return TCL_ERROR; } nb = atoi (argv[1]); if (nb < 1 || nb > NumBases) { sprintf (message, "base number %d out of range", nb); Tcl_SetResult (interp, message, TCL_STATIC); return TCL_ERROR; } if (nb != cgnsBase) cgnsCalcBase (nb); for (nz = 1; nz <= NumZones; nz++) { if (cg_zone_read (cgnsFile, cgnsBase, nz, name, sizes)) cgnsCalcFatal ((char *)cg_get_error()); Tcl_AppendElement (interp, name); } return TCL_OK; } /*---------- CalcBaseInfo ------------------------------------------ * get current base information *------------------------------------------------------------------*/ static int CalcBaseInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *p = message; Tcl_ResetResult (interp); if (!cgnsBase) return TCL_OK; sprintf (p, "Name : %s\n", BaseName); p += strlen (p); sprintf (p, "Phy Dim : %d\nCell Dim : %d\n", PhyDim, CellDim); p += strlen (p); sprintf (p, "Zones : %d\nRef Values: %d\n", NumZones, NumReference); p += strlen (p); #if CGNS_VERSION >= 2500 sprintf (p, "Data Class: %s\n", cg_DataClassName(BaseClass)); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", cg_MassUnitsName(BaseUnits[0]), cg_LengthUnitsName(BaseUnits[1]), cg_TimeUnitsName(BaseUnits[2]), cg_TemperatureUnitsName(BaseUnits[3]), cg_AngleUnitsName(BaseUnits[4])); #else sprintf (p, "Data Class: %s\n", DataClassName[BaseClass]); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", MassUnitsName[BaseUnits[0]], LengthUnitsName[BaseUnits[1]], TimeUnitsName[BaseUnits[2]], TemperatureUnitsName[BaseUnits[3]], AngleUnitsName[BaseUnits[4]]); #endif Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcZone ---------------------------------------------- * set zone for calculations *------------------------------------------------------------------*/ static int CalcZone (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int nz, ns; char name[33]; CGNS_ENUMT(GridLocation_t) location; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " zone\"", NULL); return TCL_ERROR; } nz = atoi (argv[1]); if (nz < 1 || nz > NumZones) { sprintf (message, "zone number %d out of range", nz); Tcl_SetResult (interp, message, TCL_STATIC); return TCL_ERROR; } if (nz != cgnsZone) cgnsCalcZone (nz); for (ns = 1; ns <= NumSolns; ns++) { if (cg_sol_info (cgnsFile, cgnsBase, cgnsZone, ns, name, &location)) cgnsCalcFatal ((char *)cg_get_error()); Tcl_AppendElement (interp, name); } return TCL_OK; } /*---------- CalcZoneInfo ------------------------------------------ * get current zone information *------------------------------------------------------------------*/ static int CalcZoneInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *p = message; int n, dim; Tcl_ResetResult (interp); if (!cgnsZone) return TCL_OK; sprintf (p, "Name : %s\nType : %s\n", ZoneName, #if CGNS_VERSION >= 2500 cg_ZoneTypeName(ZoneType)); #else ZoneTypeName[ZoneType]); #endif p += strlen (p); dim = ZoneType == CGNS_ENUMV(Structured) ? CellDim : 1; sprintf (p, "Dimensions: %d", ZoneDims[0]); p += strlen(p); for (n = 1; n < dim; n++) { sprintf (p, " x %d", ZoneDims[n]); p += strlen(p); } sprintf (p, "\nCoords : %d\nSolutions : %d\n", NumCoordinates, NumSolns); p += strlen (p); #if CGNS_VERSION >= 2500 sprintf (p, "Data Class: %s\n", cg_DataClassName(ZoneClass)); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", cg_MassUnitsName(ZoneUnits[0]), cg_LengthUnitsName(ZoneUnits[1]), cg_TimeUnitsName(ZoneUnits[2]), cg_TemperatureUnitsName(ZoneUnits[3]), cg_AngleUnitsName(ZoneUnits[4])); #else sprintf (p, "Data Class: %s\n", DataClassName[ZoneClass]); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", MassUnitsName[ZoneUnits[0]], LengthUnitsName[ZoneUnits[1]], TimeUnitsName[ZoneUnits[2]], TemperatureUnitsName[ZoneUnits[3]], AngleUnitsName[ZoneUnits[4]]); #endif Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcSoln ---------------------------------------------- * set solution for calculations *------------------------------------------------------------------*/ static int CalcSoln (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int ns, nv; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " soln\"", NULL); return TCL_ERROR; } ns = atoi (argv[1]); if (ns < 1 || ns > NumSolns) { sprintf (message, "solution number %d out of range", ns); Tcl_SetResult (interp, message, TCL_STATIC); return TCL_ERROR; } if (ns != cgnsSoln) cgnsCalcSoln (ns); for (nv = 0; nv < NumVariables; nv++) Tcl_AppendElement (interp, variables[nv].name); return TCL_OK; } /*---------- CalcSolnInfo ------------------------------------------ * get current solution information *------------------------------------------------------------------*/ static int CalcSolnInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *p = message; int n; Tcl_ResetResult (interp); if (!cgnsSoln) return TCL_OK; sprintf (p, "Name : %s\nLocation : %s\n", SolnName, #if CGNS_VERSION >= 2500 cg_GridLocationName(SolnLocation)); #else GridLocationName[SolnLocation]); #endif p += strlen (p); if (ZoneType == CGNS_ENUMV(Structured)) { sprintf (p, "Dimensions: %d", SolnDims[0]); p += strlen(p); for (n = 1; n < CellDim; n++) { sprintf (p, " x %d", SolnDims[n]); p += strlen(p); } sprintf (p, "\nRind Cells: %d %d %d %d %d %d\n", SolnRind[0], SolnRind[1], SolnRind[2], SolnRind[3], SolnRind[4], SolnRind[5]); } else sprintf (p, "Dimensions: %d\n", SolnDims[0]); p += strlen (p); sprintf (p, "Fields : %d\n", NumVariables); p += strlen (p); #if CGNS_VERSION >= 2500 sprintf (p, "Data Class: %s\n", cg_DataClassName(SolnClass)); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", cg_MassUnitsName(SolnUnits[0]), cg_LengthUnitsName(SolnUnits[1]), cg_TimeUnitsName(SolnUnits[2]), cg_TemperatureUnitsName(SolnUnits[3]), cg_AngleUnitsName(SolnUnits[4])); #else sprintf (p, "Data Class: %s\n", DataClassName[SolnClass]); p += strlen (p); sprintf (p, "Units : %s %s %s %s %s", MassUnitsName[SolnUnits[0]], LengthUnitsName[SolnUnits[1]], TimeUnitsName[SolnUnits[2]], TemperatureUnitsName[SolnUnits[3]], AngleUnitsName[SolnUnits[4]]); #endif Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcRegList ------------------------------------------- * return list of regions *------------------------------------------------------------------*/ static int CalcRegList (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, dim; char *p = message; Tcl_ResetResult (interp); if (!NumZones || !cgnsZone) return TCL_OK; dim = ZoneType == CGNS_ENUMV(Structured) ? CellDim : 1; sprintf (p, "[%d", ZoneDims[0]); p += strlen(p); for (n = 1; n < dim; n++) { sprintf (p, ",%d", ZoneDims[n]); p += strlen(p); } strcpy (p, "]"); Tcl_AppendElement (interp, message); return TCL_OK; } /*---------- CalcRegInfo ------------------------------------------- * return region information *------------------------------------------------------------------*/ static int CalcRegInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { Tcl_ResetResult (interp); return TCL_OK; } /*---------- CalcVarList ------------------------------------------- * return list of variables *------------------------------------------------------------------*/ static int CalcVarList (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, i; Tcl_ResetResult (interp); #if 0 for (n = 0; n < NumCoordinates; n++) { for (i = 0; i < NumVariables; i++) { if (0 == strcmp (coordinates[n].name, variables[i].name)) break; } if (i < NumVariables) sprintf (message, "'%s[%d]", coordinates[n].name, coordinates[n].len); else sprintf (message, "%s[%d]", coordinates[n].name, coordinates[n].len); Tcl_AppendElement (interp, message); } for (n = 0; n < NumVariables; n++) { sprintf (message, "%s[%d]", variables[n].name, variables[n].len); Tcl_AppendElement (interp, message); } for (n = 0; n < NumReference; n++) { if (reference[n].len > 1) sprintf (message, "~%s[%d]", reference[n].name, reference[n].len); else sprintf (message, "~%s", reference[n].name); Tcl_AppendElement (interp, message); } #else for (n = 0; n < NumCoordinates; n++) { for (i = 0; i < NumVariables; i++) { if (0 == strcmp (coordinates[n].name, variables[i].name)) break; } if (i < NumVariables) { sprintf (message, "'%s", coordinates[n].name); Tcl_AppendElement (interp, message); } else Tcl_AppendElement (interp, coordinates[n].name); } for (n = 0; n < NumVariables; n++) Tcl_AppendElement (interp, variables[n].name); for (n = 0; n < NumReference; n++) { sprintf (message, "~%s", reference[n].name); Tcl_AppendElement (interp, message); } #endif return TCL_OK; } /*---------- CalcVarInfo ------------------------------------------- * return variable information *------------------------------------------------------------------*/ static int CalcVarInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *p = message; Variable *var; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " varname\"", NULL); return TCL_ERROR; } var = cgnsCalcVarGet (argv[1]); if (var == NULL) { Tcl_AppendResult (interp, "variable \"", argv[1], "\" not found", NULL); return TCL_ERROR; } sprintf (p, "Name : %s\n", var->name); p += strlen (p); if (var->type == 0) { sprintf (p, "Type : Reference\n"); p += strlen(p); if (var->len > 1) sprintf (p, "Size : %d\n", var->len); else sprintf (p, "Value : %g\n", var->vd->f.val); } else if (var->type == 1 || SolnLocation == CGNS_ENUMV(Vertex)) { sprintf (p, "Type : %s\nLocation : Vertex\n", var->type == 1 ? "Coordinate" : "Solution"); p += strlen (p); if (ZoneType == CGNS_ENUMV(Structured)) sprintf (p, "Size : %d (%d x %d x %d)\n", var->len, ZoneDims[0], ZoneDims[1], ZoneDims[2]); else sprintf (p, "Size : %d\n", var->len); } else { sprintf (p, "Type : Solution\nLocation : %s\n", #if CGNS_VERSION >= 2500 cg_GridLocationName(SolnLocation)); #else GridLocationName[SolnLocation]); #endif p += strlen (p); if (ZoneType == CGNS_ENUMV(Structured)) { sprintf (p, "Size : %d (%d x %d x %d)\n", var->len, SolnDims[0], SolnDims[1], SolnDims[2]); p += strlen (p); sprintf (p, "Rind Cells: %d %d %d %d %d %d\n", SolnRind[0], SolnRind[1], SolnRind[2], SolnRind[3], SolnRind[4], SolnRind[5]); } else sprintf (p, "Size : %d\n", var->len); } p += strlen (p); sprintf (p, "Data Class: %s\nData Type : %s\n", #if CGNS_VERSION >= 2500 cg_DataClassName(var->dataclass), cg_DataTypeName(var->datatype)); #else DataClassName[var->dataclass], DataTypeName[var->datatype]); #endif p += strlen (p); if (var->hasunits) sprintf (p, "Units : %s %s %s %s %s\n", #if CGNS_VERSION >= 2500 cg_MassUnitsName(var->units[0]), cg_LengthUnitsName(var->units[1]), cg_TimeUnitsName(var->units[2]), cg_TemperatureUnitsName(var->units[3]), cg_AngleUnitsName(var->units[4])); #else MassUnitsName[var->units[0]], LengthUnitsName[var->units[1]], TimeUnitsName[var->units[2]], TemperatureUnitsName[var->units[3]], AngleUnitsName[var->units[4]]); #endif else sprintf (p, "Units : not specified\n"); p += strlen (p); if (var->hasexp) sprintf (p, "Exponents : %g %g %g %g %g\n", var->exponent[0], var->exponent[1], var->exponent[2], var->exponent[3], var->exponent[4]); else sprintf (p, "Exponents : not specified\n"); p += strlen (p); if (var->hasconv) sprintf (p, "Conversion: %g %g", var->dataconv[0], var->dataconv[1]); else sprintf (p, "Conversion: not specified"); Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcSymList ------------------------------------------- * return list of symbols *------------------------------------------------------------------*/ static int CalcSymList (ClientData data, Tcl_Interp *interp, int argc, char **argv) { Tcl_ResetResult (interp); sym_list (0, get_names, interp); return TCL_OK; } /*---------- CalcSymInfo ------------------------------------------- * return symbol information *------------------------------------------------------------------*/ static int CalcSymInfo (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *p = message; VECSYM *sym; Units *units; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " symname\"", NULL); return TCL_ERROR; } sym = find_symbol (argv[1], 0); if (sym == NULL) { sym = find_symbol (argv[1], 1); if (sym == NULL) { Tcl_AppendResult (interp, "symbol \"", argv[1], "\" not found", NULL); return TCL_ERROR; } } sprintf (p, "Name : %s\n", vecsym_name(sym)); p += strlen (p); if (vecsym_type(sym) == VECSYM_EQUSTR) { sprintf (p, "Type : equation\n"); p += strlen(p); if (vecsym_nargs(sym) > 0) sprintf (p, "Arguments : %d", vecsym_nargs(sym)); else sprintf (p, "Arguments : none"); } else if (vecsym_type(sym) == VECSYM_FUNC) { sprintf (p, "Type : function\n"); p += strlen(p); if (vecsym_nargs(sym) < 0) sprintf (p, "Arguments : variable"); else sprintf (p, "Arguments : %d", vecsym_nargs(sym)); } else if (vecsym_type(sym) == VECSYM_VECTOR) sprintf (p, "Type : vector\nSize : %ld", (long)vecsym_veclen(sym)); else sprintf (p, "Type : value\nValue : %g", vecsym_value(sym)); if (vecsym_user(sym) != NULL) { units = (Units *)vecsym_user(sym); p += strlen(p); sprintf (p, "\nUnits : %s %s %s %s %s\n", #if CGNS_VERSION >= 2500 cg_MassUnitsName(units->units[0]), cg_LengthUnitsName(units->units[1]), cg_TimeUnitsName(units->units[2]), cg_TemperatureUnitsName(units->units[3]), cg_AngleUnitsName(units->units[4])); #else MassUnitsName[units->units[0]], LengthUnitsName[units->units[1]], TimeUnitsName[units->units[2]], TemperatureUnitsName[units->units[3]], AngleUnitsName[units->units[4]]); #endif p += strlen(p); sprintf (p, "Exponents : %g %g %g %g %g", units->exps[0], units->exps[1], units->exps[2], units->exps[3], units->exps[4]); } Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcCommand ------------------------------------------- * parse expression and return results *------------------------------------------------------------------*/ static int CalcCommand (ClientData data, Tcl_Interp *interp, int argc, char **argv) { size_t n; VECFLOAT *f, fmin, fmax; VECSYM *sym; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " command\"", NULL); return TCL_ERROR; } sym = cgnsCalcCommand (argv[1]); if (NULL == sym) { Tcl_SetResult (interp, message, TCL_STATIC); return TCL_ERROR; } if (VECSYM_EQUSTR == vecsym_type(sym)) { if (vecsym_nargs(sym) > 0) sprintf (message, "%s(%d)", vecsym_name(sym), vecsym_nargs(sym)); else strcpy (message, vecsym_name(sym)); } else if (VECSYM_FUNC == vecsym_type(sym)) { if (vecsym_nargs(sym) < 0) sprintf (message, "%s(...)", vecsym_name(sym)); else sprintf (message, "%s(%d)", vecsym_name(sym), vecsym_nargs(sym)); } else if (VECSYM_VALUE == vecsym_type(sym)) sprintf (message, "%s = %g", vecsym_name(sym), vecsym_value(sym)); else if (VECSYM_VECTOR == vecsym_type(sym)) { f = vecsym_vector(sym); fmin = fmax = f[0]; for (n = 1; n < vecsym_veclen(sym); n++) { if (fmin > f[n]) fmin = f[n]; if (fmax < f[n]) fmax = f[n]; } sprintf (message, "%s -> len = %ld, min = %g, max = %g", vecsym_name(sym), (long)vecsym_veclen(sym), fmin, fmax); } else strcpy (message, vecsym_name(sym)); Tcl_SetResult (interp, message, TCL_STATIC); return TCL_OK; } /*---------- CalcDelete -------------------------------------------- * delete symbols *------------------------------------------------------------------*/ static int CalcDelete (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int i, n, nargs; CONST char **args; for (n = 1; n < argc; n++) { if (TCL_OK == Tcl_SplitList (interp, argv[n], &nargs, &args)) { for (i = 0; i < nargs; i++) sym_delsym ((char *)args[i]); Tcl_Free ((char *)args); } else sym_delsym (argv[n]); } return TCL_OK; } /*---------- CalcSave ---------------------------------------------- * save computed variables to results file *------------------------------------------------------------------*/ static int CalcSave (ClientData data, Tcl_Interp *interp, int argc, char **argv) { Tcl_SetResult (interp, "not implemented yet", TCL_STATIC); return TCL_ERROR; } /*---------- ADFtcl_Init --------------------------------------- * Initialize and create the commands *--------------------------------------------------------------*/ #if defined(_WIN32) && defined(BUILD_DLL) __declspec(dllexport) #endif int Calctcl_Init(Tcl_Interp *interp) { global_interp = interp; Tcl_CreateCommand (interp, "CalcReset", (Tcl_CmdProc *)CalcReset, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcInit", (Tcl_CmdProc *)CalcInit, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcDone", (Tcl_CmdProc *)CalcDone, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcBase", (Tcl_CmdProc *)CalcBase, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcBaseInfo", (Tcl_CmdProc *)CalcBaseInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcZone", (Tcl_CmdProc *)CalcZone, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcZoneInfo", (Tcl_CmdProc *)CalcZoneInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcSoln", (Tcl_CmdProc *)CalcSoln, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcSolnInfo", (Tcl_CmdProc *)CalcSolnInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcRegList", (Tcl_CmdProc *)CalcRegList, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcRegInfo", (Tcl_CmdProc *)CalcRegInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcVarList", (Tcl_CmdProc *)CalcVarList, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcVarInfo", (Tcl_CmdProc *)CalcVarInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcSymList", (Tcl_CmdProc *)CalcSymList, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcSymInfo", (Tcl_CmdProc *)CalcSymInfo, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcCommand", (Tcl_CmdProc *)CalcCommand, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcDelete", (Tcl_CmdProc *)CalcDelete, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CalcSave", (Tcl_CmdProc *)CalcSave, (ClientData)0, (Tcl_CmdDeleteProc *)0); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnscalc/calcwish.c000066400000000000000000000100421343724673500206030ustar00rootroot00000000000000/* * tkAppInit.c -- * * Provides a default version of the Tcl_AppInit procedure for * use in wish and similar Tk-based applications. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include "tk.h" #include "locale.h" #ifdef TK_TEST extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* TK_TEST */ extern int Calctcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); /* *---------------------------------------------------------------------- * * main -- * * This is the main program for the application. * * Results: * None: Tk_Main never returns here, so this procedure never * returns either. * * Side effects: * Whatever the application does. * *---------------------------------------------------------------------- */ int main(argc, argv) int argc; /* Number of command-line arguments. */ char **argv; /* Values of command-line arguments. */ { /* * The following #if block allows you to change the AppInit * function by using a #define of TCL_LOCAL_APPINIT instead * of rewriting this entire file. The #if checks for that * #define and uses Tcl_AppInit if it doesn't exist. */ #ifndef TK_LOCAL_APPINIT #define TK_LOCAL_APPINIT Tcl_AppInit #endif extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp)); /* * The following #if block allows you to change how Tcl finds the startup * script, prime the library or encoding paths, fiddle with the argv, * etc., without needing to rewrite Tk_Main() */ #ifdef TK_LOCAL_MAIN_HOOK extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); TK_LOCAL_MAIN_HOOK(&argc, &argv); #endif Tk_Main(argc, argv, TK_LOCAL_APPINIT); return 0; /* Needed only to prevent compiler warning. */ } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); #ifdef TK_TEST if (Tcltest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, (Tcl_PackageInitProc *) NULL); if (Tktest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tktest", Tktest_Init, (Tcl_PackageInitProc *) NULL); #endif /* TK_TEST */ /* * Call the init procedures for included packages. Each call should * look like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. */ if (Calctcl_Init(interp) == TCL_ERROR) return TCL_ERROR; /* * Call Tcl_CreateCommand for application-specific commands, if * they weren't already created by the init procedures called above. */ /* * Specify a user-specific startup file to invoke if the application * is run interactively. Typically the startup file is "~/.apprc" * where "app" is the name of the application. If this line is deleted * then no user-specific startup file will be run under any conditions. */ Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc-icon.xbm000066400000000000000000000016171343724673500220650ustar00rootroot00000000000000#define cgnscalc-icon_width 32 #define cgnscalc-icon_height 32 static unsigned char cgnscalc-icon_bits[] = { 0x03, 0x00, 0x00, 0xff, 0xfb, 0xff, 0x7f, 0xfe, 0xfb, 0xff, 0x7f, 0xfd, 0xfb, 0xdf, 0x73, 0xfb, 0xfb, 0xcf, 0x6d, 0xf7, 0xab, 0xd8, 0x6f, 0xef, 0xdb, 0xdf, 0x73, 0xc0, 0xdb, 0xd8, 0x3d, 0xd4, 0xab, 0x5f, 0xe1, 0xce, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0x7c, 0xd1, 0xfb, 0x7f, 0x3b, 0xd7, 0xab, 0x78, 0x7b, 0xdb, 0xab, 0x4f, 0x7b, 0xdb, 0xab, 0x78, 0x7b, 0xdb, 0xdb, 0xff, 0x6c, 0xdb, 0xdb, 0xff, 0xff, 0xdf, 0xeb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0x8f, 0xcd, 0xd7, 0xfb, 0xef, 0xb4, 0xd3, 0x8b, 0xc8, 0xbd, 0xd7, 0xbb, 0xbf, 0xcd, 0xd7, 0xeb, 0xb8, 0xf5, 0xd7, 0x8b, 0xcf, 0x85, 0xd6, 0xfb, 0xff, 0xff, 0xdf, 0xfb, 0xff, 0xff, 0xdf, 0x03, 0x00, 0x00, 0xc0}; CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc-mask.xbm000066400000000000000000000016171343724673500220700ustar00rootroot00000000000000#define cgnscalc-mask_width 32 #define cgnscalc-mask_height 32 static unsigned char cgnscalc-mask_bits[] = { 0xfc, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f}; CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc.bat000066400000000000000000000015721343724673500211170ustar00rootroot00000000000000@echo off setlocal set dir=%~dps0 if exist %dir%cgconfig.bat ( call %dir%cgconfig.bat goto getwish ) if exist %dir%..\cgconfig.bat call %dir%..\cgconfig.bat :getwish if "%CG_BIN_DIR%" == "" set CG_BIN_DIR=%dir% if exist %dir%calcwish.exe ( set wish=%dir%calcwish.exe goto getscript ) if exist %dir%cgnstools\calcwish.exe ( set wish=%dir%cgnstools\calcwish.exe goto getscript ) echo calcwish.exe not found pause goto done :getscript if exist %dir%cgnscalc.tcl ( set script=%dir%cgnscalc.tcl goto run ) if not "%CG_LIB_DIR%" == "" ( if exist %CG_LIB_DIR%\cgnscalc.tcl ( set script=%CG_LIB_DIR%\cgnscalc.tcl goto run ) ) if exist %dir%..\share\cgnscalc.tcl ( if "%CG_LIB_DIR%" == "" set CG_LIB_DIR=%dir%..\share set script=%dir%..\share\cgnscalc.tcl goto run ) echo cgnscalc.tcl not found pause goto done :run start /b %wish% %script% %1 :done endlocal CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc.ico000066400000000000000000000020661343724673500211220ustar00rootroot00000000000000 &(( @?( CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc.png000066400000000000000000000005341343724673500211320ustar00rootroot00000000000000PNG  IHDR szzsBIT|dIDATX zͺdxY.NѿfT37l-C4"$Ep}x1 Y1a@1;V'aOPhdrQ zmJm̤R\JoZt %z"0+uDl|V!@v)| pMEp%S)nMɼ/QSE䃫nPP1(LQ T:V_dx IENDB`CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc.sh000066400000000000000000000022361343724673500207610ustar00rootroot00000000000000#!/bin/sh # sh script to launch CGNS calculator dir=`dirname $0` # source the setup script for d in $dir $dir/cgnstools $dir/.. ; do if test -f $d/cgconfig ; then . $d/cgconfig break fi done # get the calcwish executable calcwish="" for d in $CG_BIN_DIR $dir $dir/cgnstools $dir/cgnscalc \ /usr/local/bin /usr/local/bin/cgnstools ; do if test -x $d/calcwish ; then calcwish=$d/calcwish break fi if test -x $d/cgnswish/calcwish ; then calcwish=$d/cgnswish/calcwish break fi done if test -z "$calcwish" ; then echo "Error: calcwish executable not found" exit 1 fi # find the cgnscalc tcl script cgnscalc="" for d in $CG_LIB_DIR $dir $dir/cgnstools $dir/cgnscalc \ /usr/local/share /usr/local/share/cgnstools ; do if test -f $d/cgnscalc.tcl ; then cgnscalc=$d/cgnscalc.tcl break fi done if test -z "$cgnscalc" ; then echo "Error: cgnscalc.tcl script not found" exit 1 fi # check that display is set #if test -z "$DISPLAY" ; then # echo "Error: DISPLAY environment variable not set" # exit 1 #fi # execute if test "$#" = 0 ; then exec $calcwish $cgnscalc else exec $calcwish $cgnscalc "$@" fi CGNS-3.4.0/src/cgnstools/cgnscalc/cgnscalc.tcl000066400000000000000000000764601343724673500211430ustar00rootroot00000000000000#!/bin/sh # the next line restarts using wish \ exec calcwish -f "$0" "$@" proc error_exit {msg} { wm withdraw . tk_dialog .error Error $msg error 0 Exit exit 1 } if {[catch {package require Tk 8.0} msg]} { error_exit $msg } #----- get startup directory and name set cmd_name [file tail $argv0] set cmd_dir [file dirname $argv0] if {![file exists $argv0] || [file isdirectory $argv0]} { if {$tcl_platform(platform) == "windows"} { set sep ";" } else { set sep ":" } foreach i [split $env(PATH) $sep] { if {$sep == ";"} { set i [join [split $i \\] /] } if {[file exists $i/$cmd_name] && ![file isdirectory $i/$cmd_name]} { set cmd_dir $i break; } } } set curdir [pwd] if ![catch {cd $cmd_dir}] { set cmd_dir [pwd] cd $curdir } if {$tcl_platform(platform) == "windows"} { set cmd_dir [file attributes $cmd_dir -shortname] } #----- set path to tcl scripts set auto_path "$cmd_dir $cmd_dir/../common $auto_path" if {[info exists env(TCL_PROC_DIR)]} { set auto_path "$env(TCL_PROC_DIR) $auto_path" } #---------- initialize if {$tcl_platform(platform) == "windows"} { set vers [join [split $tcl_version .] {}] if {[info commands CalcInit] == {}} { if {[catch {load calctcl$vers} msg]} { error_exit $msg } } catch {load tclreg$vers registry} if {[info exists env(USERPROFILE)]} { set home [join [split $env(USERPROFILE) \\] /] } elseif {[info exists env(HOME)]} { set home [join [split $env(HOME) \\] /] } else { set home ~ } set InitCmds "$home/_cgnsCalc.clc" } else { if {[info commands CalcInit] == {}} { error_exit "need to run script with calcwish" } set InitCmds "~/.cgnsCalc.clc" } if [catch {config_defaults 1} msg] {error_exit $msg} set butw 5 #----- initialize set Prefix "" set Suffix "" set Count 0 set Index 0 set History(-1) "" array set ProgData { CMDfile {} CGNSfile {} base "" zone "" solution "" regs "" vars "" syms "" cmds "" symlist {} readonly 0 reg,file ".cgnstools" reg,base "HKEY_CURRENT_USER/Software/CGNS" reg,key "CGNScalc" reg,vals {CMDfile CGNSfile} } if {[tclreg_init -base $ProgData(reg,base) -fname $ProgData(reg,file)]} { foreach i $ProgData(reg,vals) { if {![catch {tclreg_get $ProgData(reg,key) $i} val] && $val != ""} { set ProgData($i) $val } } catch units_read } #----- window title wm title . "CGNScalc" wm protocol . WM_DELETE_WINDOW do_quit bind . {select_history -1} bind . {select_history +1} bind . delete_symbol #----- pull-down menu menubar_create {File Options Commands Plot Help} # file menu set m [menubar_get File] $m add command -label "Load CGNS File..." -command {load_cgns ""} $m add command -label "Save Variables..." -command save_cgns \ -state disabled $m add command -label "Edit File..." -command {do_edit ""} $m add separator $m add command -label "Quit" -command do_quit # options menu set m [menubar_get Options] $m add command -label "Delete Symbols" -command delete_symbol $m add command -label "Reset Calculator" -command do_reset # commands menu set m [menubar_get Commands] $m add command -label "Command History..." -command do_history $m add separator $m add command -label "Load Command File..." -command {do_load ""} $m add cascade -label "Save Command File..." -command do_save # plot menu # help menu set m [menubar_get Help] $m add command -label "CGNScalc Help..." \ -command {help_show cgnstools/cgnscalc/index.html} $m add command -label "CGNS Help..." -command {help_show} $m add separator $m add command -label "Configure Help..." -command help_setup $m add separator $m add command -label "Unit Conversions..." -command units_convert $m add command -label "About..." -underline 0 -command do_about image create photo img_about -data {\ R0lGODlhIAAgALMAAAAAAP///8DAwP//////////////////////////////////////////\ /////////yH5BAEAAAIALAAAAAAgACAAAASoUAhAq70YyM1n+GAoilTHAWOaoprpqQEKUvPX\ dvKay/xssrEYLUiyhW6S3igntGVORqGS6KSxoMAiq1JzQmHg5TdMjo3LYCQTrVKXhzWuOzyF\ XzfALXNK5GGpTn1HUW55cIJdfnhRbUqOX2tsPouRkjZnliSYmZNJMFx9a3eebTNZO6MeclY7\ g3FjlY6iZpSmrUGxtJ6gpnFyRnOcmovCw0kZyMkVEhEAADs=} proc do_about {} { global ProgData dialog .about -1 -1 "About CGNScalc" \ "CGNScalc Version 1.1 Bruce Wedan leavingdust@gmail.com" img_about 0 Close } #---------- toolbar frame .toolbar pack .toolbar -side top -pady 2 -fill x set f [frame .toolbar.but] pack $f -side left #--- image create photo img_open -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQ4EMlJKwJvZcC7BxdnSV04nCgKjtR6vZgmZ49L\ bmlus7xV9j4QQPYRtWbI3RCXU10WgKaTVPQAexEAOw==} image create photo img_save -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwQ90MlJqwRjgM13BpeGjOSIgQ6mdYCphW1Jtugp\ z2/6sVye8rwLMKiL3Tiwm6smUp5Cmaj0A+Utq6yrZTuJAAA7} image create photo img_edit -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwRT0DkwK6VSHsR7H8sAjMdjnigCEMxTouOpZiXw\ 2Ph9S8SLpiNG72cCPUSYjWc5y9hKUNeORgQ6WEpmZ/Vg+KrI1RdlHBwo2c9oTa2ampK1XJ5x\ RAAAOw==} set b [frame $f.b1] pack $b -side left -padx 5 button $b.open -image img_open -command {load_cgns ""} set_balloon $b.open "Open a CGNS File..." button $b.save -image img_save -command save_cgns -state disabled set_balloon $b.save "Save Selected Results to CGNS File..." button $b.edit -image img_edit -command {do_edit ""} set_balloon $b.edit "Edit a File..." pack $b.open $b.save $b.edit -side left -padx 1 #--- image create photo img_delete -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQoEMlJqwVYZqv3phjAXSE5IuWYgmfbiSq4ojAX\ fup9zjjda5WazWWJAAA7} image create photo img_reset -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQwEMlJqwUY24mT91rVfV/IkShAAWirSmxLvkgs\ g+eNw/rO3zSYbRYUpoqrDHLDbDIjADs=} set b [frame $f.b2] pack $b -side left -padx 5 button $b.delete -image img_delete -command delete_symbol set_balloon $b.delete "Delete Selected Symbols" button $b.reset -image img_reset -command do_reset set_balloon $b.reset "Reset Calculator" pack $b.delete $b.reset -side left -padx 1 #--- image create photo img_history -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQeEMlJq7046827/xogjqRIleSFltXKTi6golk8\ glIEADs=} image create photo img_read -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAAARBEMgJnL0XjMNHpUi2dRVWOtqgehgqrmwmWdoU\ Z6J9tig19xNeC/Ao/oSoBzGIJBaNyOREGXU+d0OlhNp8Qps+QAQAOw==} image create photo img_write -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAAAQ/EEjpqr0OvE3zRJYmdmG4nQCWVqN4TezJqeb0\ rFgs4/nksz5Sb3AoDngqohH5GjidzNATmpNOjlXWUYLNBiURADs=} set b [frame $f.b3] pack $b -side left -padx 5 button $b.history -image img_history -command do_history set_balloon $b.history "Command History..." button $b.read -image img_read -command {do_load ""} set_balloon $b.read "Read a Command File..." button $b.write -image img_write -command do_save set_balloon $b.write "Write Commands to File..." pack $b.history $b.read $b.write -side left -padx 1 #--- image create photo img_plot -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQyEMlJq70W4KsvQwnVVUwZTiN5otsqpZT7Wow8\ Ix+e5JVW1juMJkHc3IwogHLJhCGflggAOw==} button $f.plot -image img_plot -state disabled set_balloon $f.plot "Plot Data..." pack $f.plot -side left -padx 6 #--- image create photo img_convert -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwQt0MlJq70VSO349B0ghhwYntuIXZ7YUmaWxeu3\ 3eTb4Sld8yngztYDuYbC3yQCADs=} button $f.convert -image img_convert -command "units_convert $f.convert" set_balloon $f.convert "Unit Conversions..." pack $f.convert -side left -padx 6 #--- image create photo img_help -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQiEMlJq50kX5kJ1hvShd+4mSJ4qmTrXl28ehw7\ t+j75joVAQA7} button $f.help -image img_help \ -command {help_show cgnstools/cgnscalc/index.html} set_balloon $f.help "CGNScalc Help..." pack $f.help -side left -padx 6 frame .toolsep -bd 1 -height 2 -relief sunken pack .toolsep -side top -fill x #----- base/zone/solution selection frame .loc pack .loc -side top -fill x -expand 1 -pady 3 foreach i {Base Zone Solution} { set j [string tolower $i] set f [frame .loc.$j] pack $f -side left -fill x -expand 1 -padx 5 label $f.lab -text $i pack $f.lab -side left set ProgData($j) [ComboboxCreate $f.cb -width 10 -edit 0 -command "set_$j"] pack $f.cb -side left -fill x -expand 1 bind $f.cb.ent "location_info $i $f.cb.ent" } proc location_info {type w} { global Font if {$type == "Solution"} { set msg [CalcSolnInfo] } else { set msg [Calc${type}Info] } if {$msg != ""} { popup_message $msg -parent $w -font $Font(fixed) -wrap 0 } } frame .locsep -bd 1 -height 2 -relief sunken pack .locsep -side top -fill x #----- top panel set top [frame .top] pack $top -side top -fill x -anchor n #----- create region list set list [frame $top.regs] pack $list -side left -fill both -expand 1 -padx 2 -pady 2 label $list.lab -text "Regions" pack $list.lab -side top -fill x scrollbar $list.vs -relief sunken -command "$list.list yview" pack $list.vs -side right -fill y scrollbar $list.hs -relief sunken -command "$list.list xview" -orient horiz pack $list.hs -side bottom -fill x set ProgData(regs) [listbox $list.list -relief sunken -width 15 -height 5 \ -exportselection 0 -yscroll "$list.vs set" -xscroll "$list.hs set"] pack $list.list -side left -fill both -expand 1 bind $list.list load_variables bind $list.list {region_properties %W %X %y} proc load_regions {} { global ProgData set sel [$ProgData(regs) curselection] if {$sel != ""} { set sel [$ProgData(regs) get $sel] } set index "" $ProgData(regs) delete 0 end set n 0 foreach v [CalcRegList] { $ProgData(regs) insert end $v if {$v == $sel} { set index $n } incr n } if {$index != ""} { $ProgData(regs) selection set $index $index $ProgData(regs) see $index } } proc region_properties {w x y} { global Font set reg [lindex [split [$w get [$w nearest $y]] "\["] 0] if {$reg == ""} return set msg [CalcRegInfo $reg] if {$msg != ""} { incr y [winfo rooty $w] popup_message $msg -parent $w -position "$x $y" -font $Font(fixed) -wrap 0 } } #----- create variable list set list [frame $top.vars] pack $list -side left -fill both -expand 1 -padx 2 -pady 2 label $list.lab -text "Variables" pack $list.lab -side top -fill x scrollbar $list.vs -relief sunken -command "$list.list yview" pack $list.vs -side right -fill y scrollbar $list.hs -relief sunken -command "$list.list xview" -orient horiz pack $list.hs -side bottom -fill x set ProgData(vars) [listbox $list.list -relief sunken -width 15 -height 5 \ -exportselection 0 -yscroll "$list.vs set" -xscroll "$list.hs set"] pack $list.list -side left -fill both -expand 1 bind $list.list add_variable bind $list.list {variable_properties %W %X %y} proc load_variables {} { global ProgData set sel [$ProgData(vars) curselection] if {$sel != ""} { set sel [$ProgData(vars) get $sel] } set index "" $ProgData(vars) delete 0 end set n 0 foreach v [CalcVarList] { $ProgData(vars) insert end $v if {$v == $sel} { set index $n } incr n } if {$index != ""} { $ProgData(vars) selection set $index $index $ProgData(vars) see $index } } proc variable_properties {w x y} { global Font set var [lindex [split [$w get [$w nearest $y]] "\["] 0] if {$var == ""} return set msg [CalcVarInfo $var] if {$msg != ""} { incr y [winfo rooty $w] popup_message $msg -parent $w -position "$x $y" -font $Font(fixed) -wrap 0 } } #----- symbol list set list [frame $top.syms] pack $list -side left -fill both -expand 1 -padx 2 -pady 2 label $list.lab -text "Symbols" pack $list.lab -side top -fill x scrollbar $list.vs -relief sunken -command "$list.list yview" pack $list.vs -side right -fill y scrollbar $list.hs -relief sunken -command "$list.list xview" -orient horiz pack $list.hs -side bottom -fill x set ProgData(syms) [listbox $list.list -relief sunken -width 15 -height 5 \ -exportselection 0 -yscroll "$list.vs set" -xscroll "$list.hs set"] pack $list.list -side left -fill both -expand 1 bind $list.list { set n [%W curselection] if {$n != ""} {add_symbol [%W get $n]} } bind $list.list {symbol_properties %W %X %y} proc sort_symbols {sym1 sym2} { if {[string first "(" $sym1] >= 0} { if {[string first "(" $sym2] >= 0} { return [string compare $sym1 $sym2] } return 1 } if {[string first "\[" $sym1] >= 0} { if {[string first "(" $sym2] >= 0} { return -1 } if {[string first "\[" $sym2] >= 0} { return [string compare $sym1 $sym2] } return 1 } if {[string first "(" $sym2] >= 0 || [string first "\[" $sym2] >= 0} { return -1 } return [string compare $sym1 $sym2] } proc load_symbols {} { global ProgData $ProgData(syms) delete 0 end set ProgData(symlist) [list] foreach s [lsort -command sort_symbols [CalcSymList]] { $ProgData(syms) insert end $s lappend ProgData(symlist) [lindex [split $s "\["] 0] } } proc delete_symbol {} { global ProgData set syms {} foreach i [$ProgData(syms) curselection] { lappend syms [lindex [split [lindex \ [split [$ProgData(syms) get $i] "\("] 0] "\["] 0] } if {$syms != {}} { if {![dialog .delsym . {} "Delete Symbols" \ "Delete the symbols:\n$syms" question 0 Yes No]} { catch {CalcDelete $syms} load_symbols } } } proc symbol_properties {w x y} { global Font set sym [lindex [split [lindex \ [split [$w get [$w nearest $y]] "\("] 0] "\["] 0] if {$sym == ""} return set msg [CalcSymInfo $sym] if {$msg != ""} { incr y [winfo rooty $w] popup_message $msg -parent $w -position "$x $y" -font $Font(fixed) -wrap 0 } } #----- create function buttons set func [frame $top.func] pack $func -side right -padx 2 -pady 2 set f [frame $func.s] pack $f -side top -fill x -padx 2 -pady 2 label $f.lab -text "Scalar Functions" pack $f.lab -side top -fill x foreach s {avg sum min max len mag} { button $f.$s -relief raised -text $s -width $butw \ -command "add_function $s" pack $f.$s -side left -expand 1 } set f [frame $func.v] pack $f -side top -fill x -padx 2 -pady 2 label $f.lab -text "Vector Functions" pack $f.lab -side top -fill x set i 0 set j 0 foreach v { \ {deg deg add_function} \ {arc a set_prefix} \ {exp exp add_function} \ {rad rad add_function} \ {hyp h set_suffix} \ {log log add_function} \ {abs abs add_function} \ {sin sin add_trigfunc} \ {pow10 pow10 add_function} \ {round round add_function} \ {cos cos add_trigfunc} \ {log10 log10 add_function} \ {ceil ceil add_function} \ {tan tan add_trigfunc} \ {sqr sqr add_function} \ {floor floor add_function} \ {fact fact add_function} \ {sqrt sqrt add_function}} { if !$i { incr j 1 set ff [frame $f.$j] pack $ff -side left -fill y } incr i 1 button $ff.$i -relief raised -text [lindex $v 0] -width $butw \ -command "[lindex $v 2] [lindex $v 1]" pack $ff.$i -side top -fill x -expand 1 if {$i == 3} { set i 0 } } #----- intrinsic constants set f [frame $func.c] pack $f -side top -fill x -padx 2 -pady 2 label $f.lab -text "Intrinsic Constants" pack $f.lab -side top -fill x set n 0 foreach b { \ {PI pi} \ {E e} \ {TOL tol} \ {DIM dim} \ {index index} \ {rand rand()}} { incr n 1 button $f.$n -relief raised -text [lindex $b 0] -width $butw \ -command "add_name [lindex $b 1]" pack $f.$n -side left -expand 1 } #----- create operator buttons set oper [frame .oper] pack $oper -side top -fill x -padx 2 -pady 2 -anchor n set f [frame $oper.but] pack $f -side left -fill both -expand 1 button $f.1 -relief raised -text "Bksp" -width 4 -command command_backspace button $f.2 -relief raised -text "Clear" -width 4 -command command_clear pack $f.1 $f.2 -side top -fill x -expand 1 set operators { {0 5} {1 6} {2 7} {3 8} {4 9} {" " .} {= ,} {+ -} {* /} {^ **} {! %} {\( \)} {\[ \]} {< >} {<= >=} {== !=} {& |} {? :} {\" ~} } set n 0 foreach o $operators { incr n 1 set f [frame $oper.$n] pack $f -side left -fill both -expand 1 button $f.1 -relief raised -text [lindex $o 0] -width 1 \ -command "add_name {[lindex $o 0]}" button $f.2 -relief raised -text [lindex $o 1] -width 1 \ -command "add_name {[lindex $o 1]}" pack $f.1 $f.2 -side top -fill x -expand 1 } #----- command input line image create bitmap dnimage -foreground $fgColor(button) -data " \#define down_width 16 \#define down_height 16 static char down_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0xfc, 0x3f, 0xf8, 0x1f, 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; " image create bitmap upimage -foreground $fgColor(button) -data " \#define up_width 16 \#define up_height 16 static char up_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf8, 0x1f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; " set com [frame .com] pack $com -side top -fill x -padx 2 -pady 2 -anchor n button $com.but -text "Command" -command do_command pack $com.but -side left -anchor w button $com.down -image dnimage -state disabled \ -command {select_history +1} pack $com.down -side right -fill y button $com.up -image upimage -state disabled \ -command {select_history -1} pack $com.up -side right -fill y set ProgData(cmds) [entry $com.e -relief sunken] pack $com.e -side left -anchor w -fill x -expand 1 -padx 2 bind $com.e {do_command} bind $com.e {%W delete 0 end} bind $com.e add_variable #focus $com.e #----- output window set msg [frame .msg -relief groove -bd 3] pack $msg -side top -fill both -expand 1 -padx 2 -pady 2 scrollbar $msg.scroll -relief sunken -command "$msg.text yview" pack $msg.scroll -side right -fill y text $msg.text -height 10 -yscroll "$msg.scroll set" -cursor {} pack $msg.text -side left -fill both -expand 1 bind $msg.text "focus $com.e" #----- help proc help_menu {} { if [help_valid] { menubar_state Help normal 0 menubar_state Help normal 1 .toolbar.but.help configure -state normal } else { menubar_state Help disabled 0 menubar_state Help disabled 1 .toolbar.but.help configure -state disabled } } help_init #----- procedures proc command_insert {text} { global ProgData if {[$ProgData(cmds) selection present]} { set first [$ProgData(cmds) index sel.first] set last [$ProgData(cmds) index sel.last] $ProgData(cmds) selection clear $ProgData(cmds) delete $first $last $ProgData(cmds) icursor $first } $ProgData(cmds) insert insert $text focus $ProgData(cmds) } proc command_clear {} { global ProgData if {[$ProgData(cmds) selection present]} { set first [$ProgData(cmds) index sel.first] set last [$ProgData(cmds) index sel.last] $ProgData(cmds) selection clear $ProgData(cmds) delete $first $last $ProgData(cmds) icursor $first } else { $ProgData(cmds) delete 0 end } } proc command_backspace {} { global ProgData set n [$ProgData(cmds) index insert] if {$n > 0} { $ProgData(cmds) delete [expr $n - 1] $n } } proc writemsg {msg} { .msg.text insert end "$msg\n" .msg.text yview -pickplace end update idletasks } proc add_variable {} { global ProgData set n [$ProgData(vars) curselection] if {$n == ""} return set name [lindex [split [$ProgData(vars) get $n] "\["] 0] if {[lsearch -exact $ProgData(symlist) $name] >= 0} { add_name "\\$name" } else { add_name $name } } proc add_name {name} { set_prefix "" set_suffix "" command_insert "$name" } proc add_function {name} { set_prefix "" set_suffix "" command_insert "$name\(" } proc add_symbol {sym} { if {[string first \[ $sym] != -1} { add_name [lindex [split $sym \[] 0] } elseif {[string first \( $sym] != -1} { if [string match "*(0)" $sym] { add_name "[lindex [split $sym \(] 0]\(\)" } else { add_function [lindex [split $sym \(] 0] } } else { add_name $sym } } proc set_prefix {p} { global Prefix if {$p != "" && $p == $Prefix} {set p ""} if {$p == ""} { .top.func.v.1.2 configure -relief raised } else { .top.func.v.1.2 configure -relief sunken } set Prefix $p } proc set_suffix {s} { global Suffix if {$s != "" && $s == $Suffix} {set s ""} if {$s == ""} { .top.func.v.2.2 configure -relief raised } else { .top.func.v.2.2 configure -relief sunken } set Suffix $s } proc add_trigfunc {name} { global Prefix Suffix command_insert "$Prefix$name$Suffix\(" set_prefix "" set_suffix "" } proc do_quit {} { global ProgData CalcDone foreach i $ProgData(reg,vals) { catch {tclreg_set $ProgData(reg,key) $i $ProgData($i)} } catch units_write catch tclreg_close destroy . exit 0 } #----- reset calculator proc do_reset {} { global ProgData if [dialog .reset $ProgData(vars) {} Reset \ "This will delete all symbols and clear the output window. Do you wish to proceed ?" question 0 Yes No] return CalcReset $ProgData(cmds) delete 0 end .msg.text delete 1.0 end load_symbols clear_history } #----- command history proc update_history {} { global Index Count if {$Index <= 0} { .com.up configure -state disabled } else { .com.up configure -state normal } if {$Index >= $Count} { .com.down configure -state disabled } else { .com.down configure -state normal } } proc add_history {cmd} { global Index Count History set History($Count) $cmd incr Count set Index $Count if {[winfo exists .histlist]} { .histlist.top.list insert end $cmd .histlist.top.list selection clear 0 end .histlist.top.list see end } update_history } proc clear_history {} { global Index Count History set Index 0 set Count 0 catch {array unset History} set History(-1) "" if {[winfo exists .histlist]} { .histlist.top.list delete 0 end } update_history } proc select_history {dir} { global ProgData Index Count History set n [expr $Index$dir] if {$n >= 0 && $n <= $Count} { set Index $n $ProgData(cmds) delete 0 end if {$Index < $Count} { command_insert $History($Index) } if {[winfo exists .histlist]} { .histlist.top.list selection clear 0 end if {$Index < $Count} { .histlist.top.list selection set $Index } } update_history } } proc set_history {} { global ProgData Index Count History set n [.histlist.top.list curselection] if {$n != ""} { set Index $n $ProgData(cmds) delete 0 end command_insert $History($Index) update_history } } proc do_history {} { global Index Count History set w .histlist if {[winfo exists $w]} { wm deiconify $w focus $w return } toplevel $w wm title $w "Command History" frame $w.top pack $w.top -fill both -padx 2 -pady 2 -expand 1 scrollbar $w.top.ys -command "$w.top.list yview" pack $w.top.ys -side right -fill y scrollbar $w.top.xs -orient horizontal -command "$w.top.list xview" pack $w.top.xs -side bottom -fill x listbox $w.top.list -width 40 -height 10 -selectmode single \ -exportselection 0 -xscroll "$w.top.xs set" -yscroll "$w.top.ys set" pack $w.top.list -side left -fill both for {set n 0} {$n < $Count} {incr n} { $w.top.list insert end $History($n) } if {$Index >= 0 && $Index < $Count} { $w.top.list selection set $Index $w.top.list see $Index } else { $w.top.list see end } bind $w.top.list set_history frame $w.but pack $w.but -side bottom -fill x button $w.but.select -text Select -width 8 -command set_history button $w.but.clear -text Clear -width 8 -command clear_history button $w.but.close -text Close -width 8 -command "destroy $w" pack $w.but.select $w.but.clear $w.but.close -side left \ -padx 5 -pady 2 -expand 1 center_window $w . focus $w } #----- process command proc is_equation {cmd} { regsub -all "\[ \t\]+" $cmd {} newcmd set s [split $newcmd "="] if {[llength $s] > 1 && [lindex $s 1] != "" && [string match "\[_a-zA-Z\]*\(\[0-9\]\)" [lindex $s 0]]} { return 1 } return 0 } proc do_command {} { global ProgData set cmd [string trim [$ProgData(cmds) get]] set n [string first "\#" $cmd] if {$n >= 0} { if {$n == 0} { set cmd "" } else { incr n -1 set cmd [string trim [string range $cmd 0 $n]] } } if {$cmd == ""} return if {[string first @ $cmd] > 0} { set l [split $cmd @] set cmd [string trim [lindex $l 0]] set reg "@[string trim [lindex $l 1]]" } else { set regnum [$ProgData(regs) curselection] if {$regnum != "" && $regnum > 0 && ![is_equation $cmd]} { set regname [$ProgData(regs) get $regnum] set n [string last "\[" $regname] if {$n < 0} { set n [string last "\{" $regname] } set reg "@[string range $regname 0 [expr $n - 1]]" } else { set reg "" } } writemsg "\nCOMMAND: $cmd$reg" add_history $cmd if [catch {CalcCommand $cmd$reg} result] { foreach line [split $result '\n'] { writemsg "ERROR : $line" } } else { writemsg "RESULT : $result" $ProgData(cmds) delete 0 end load_symbols } } #----- load/save command file proc do_load {filename} { global ProgData if {$filename == {}} { set filename [FileOpen "Load Command File" $ProgData(CMDfile) . \ {{{CMD Files} {.clc .cmd}} {{All Files} {*}}}] } if {$filename == ""} return update if {![file isfile $filename]} { errormsg "$filename is not a regular file" return } if [catch {open $filename r} f] { errormsg $f return } writemsg "LOADING: $filename" set region "" while {[gets $f cmd] >= 0} { while (1) { set n [expr [string length $cmd] - 1] if {[string index $cmd $n] != "\\"} break set cmd [string trim [string range $cmd 0 [expr $n - 1]]] if {[gets $f str] < 0} break append cmd [string trim $str] } set n [string first "\#" $cmd] if {$n >= 0} { if {$n == 0} { set cmd "" } else { incr n -1 set cmd [string trim [string range $cmd 0 $n]] } } else { set cmd [string trim $cmd] } switch [string index $cmd 0] { "%" continue "?" continue "*" continue "@" { set region [string trim [string range $cmd 1 end]] continue } "&" { set cgnsfile [string trim [string range $cmd 1 end]] if {$cgnsfile != ""} { load_cgns $cgnsfile } } "<" { set cmdfile [string trim [string range $cmd 1 end]] if {$cmdfile != ""} { do_load $cmdfile } } ">" {set cmd [string trim [string range $cmd 1 end]]} } if {$cmd != ""} { add_history $cmd if {$region != "" && [string first "@" $cmd] < 0} { append cmd "@$region" } writemsg "\nCOMMAND: $cmd" if [catch {CalcCommand $cmd} result] { foreach line [split $result '\n'] { writemsg "ERROR : $line" } } else { writemsg "RESULT : $result" } } } close $f load_symbols set ProgData(CMDfile) $filename } proc do_save {} { global ProgData set filename [FileSave "Save Command File" $ProgData(CMDfile) . \ {{{Command Files} {.clc .cmd .cnv}} {{All Files} {*}}}] if {$filename == ""} return if [catch {open $filename w+} f] { errormsg $f return } writemsg "\nSAVING : $filename" set cmd "" foreach line [split [.msg.text get 1.0 end] "\n"] { if {$line == ""} { set cmd "" puts $f "" } else { puts $f "\#$line" set prompt [string range $line 0 7] if {$prompt == "COMMAND:"} { set cmd [string trim [string range $line 8 end]] } elseif {$prompt == "RESULT :"} { if {$cmd != ""} { puts $f $cmd set cmd "" } } else { set cmd "" } } } close $f set ProgData(CMDfile) $filename } #----- set base, zone and solution proc set_base {w base} { global ProgData foreach f {regs vars} { $ProgData($f) delete 0 end } ComboboxConfig $ProgData(solution) -values {} if {[catch {CalcBase [expr $base + 1]} zones]} { errormsg $zones set zones "" } else { ComboboxConfig $w -index $base } ComboboxConfig $ProgData(zone) -values $zones if {$zones == ""} { load_variables } else { set_zone $ProgData(zone) 0 } return "" } proc set_zone {w zone} { global ProgData foreach f {regs vars} { $ProgData($f) delete 0 end } if {[catch {CalcZone [expr $zone + 1]} solns]} { errormsg $solns set solns "" } else { ComboboxConfig $w -index $zone } ComboboxConfig $ProgData(solution) -values $solns load_regions if {$solns == ""} { load_variables } else { set_solution $ProgData(solution) 0 } return "" } proc set_solution {w soln} { global ProgData $ProgData(vars) delete 0 end if {[catch {CalcSoln [expr $soln + 1]} vars] || $vars == ""} { errormsg $vars } else { ComboboxConfig $w -index $soln } load_variables return "" } #----- load/save CGNS file proc load_cgns {fname} { global ProgData if {$fname == ""} { set fname [FileOpen "Load CGNS File" $ProgData(CGNSfile) . \ {{{CGNS Files} {.cgns .cga .cgh .cgx}} {{All Files} *}}] if {$fname == ""} return } if {![file isfile $fname]} { errormsg "$fname is not a regular file" return } foreach f {regs vars syms} { $ProgData($f) delete 0 end } foreach i {base zone solution} { ComboboxConfig $ProgData($i) -values {} } if 0 { if {[file writable $fname]} { set ProgData(readonly) 0 set mode w } else { set ProgData(readonly) 1 set mode r } } else { set ProgData(readonly) 1 set mode r } dialog .open -1 -1 "Opening..." \ "Opening and reading [file tail $fname]" hourglass 0 {} .open configure -cursor watch . configure -cursor watch update if {[catch {CalcInit $mode $fname} bases]} { set msg $bases } else { set msg "" } destroy .open . configure -cursor {} if {$msg != ""} { errormsg $bases return } if {$bases == ""} { errormsg "no bases defined in CGNS file" return } if {$ProgData(readonly)} { wm title . "CGNScalc : [file tail $fname] (read only)" } else { wm title . "CGNScalc : [file tail $fname]" } set ProgData(CGNSfile) $fname ComboboxConfig $ProgData(base) -values $bases set_base $ProgData(base) 0 } proc save_cgns {} { } wm withdraw . update idletasks wm minsize . [winfo reqwidth .] [winfo reqheight .] catch { config_icon . [list cgnscalc cgns] \ [list $cmd_dir $cmd_dir/images $cmd_dir/../common] } focus $ProgData(cmds) wm deiconify . if {$argc} { set file [lindex $argv [expr $argc - 1]] if {[string index $file 0] != "-" && [file exists $file]} { load_cgns $file } } if {[file exists $InitCmds] && [file readable $InitCmds]} { do_load $InitCmds } CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.bat000066400000000000000000000021651343724673500212060ustar00rootroot00000000000000@echo off setlocal rem the standard wish command will work for this rem set wish=c:\progra~1\tcl\bin\wish83.exe set dir=%~dps0 if exist %dir%cgconfig.bat ( call %dir%cgconfig.bat goto getwish ) if exist %dir%..\cgconfig.bat call %dir%..\cgconfig.bat :getwish if not "%wish%" == "" goto getscript if exist %dir%calcwish.exe ( set wish=%dir%calcwish.exe goto getscript ) if exist %dir%cgnstools\calcwish.exe ( set wish=%dir%cgnstools\calcwish.exe goto getscript ) if exist %dir%cgiowish.exe ( set wish=%dir%cgiowish.exe goto getscript ) if exist %dir%cgnstools\cgiowish.exe ( set wish=%dir%cgnstools\cgiowish.exe goto getscript ) echo calcwish.exe or cgiowish.exe not found pause goto done :getscript if exist %dir%unitconv.tcl ( set script=%dir%unitconv.tcl goto run ) if not "%CG_LIB_DIR%" == "" ( if exist %CG_LIB_DIR%\unitconv.tcl ( set script=%CG_LIB_DIR%\unitconv.tcl goto run ) ) if exist %dir%..\share\unitconv.tcl ( set CG_LIB_DIR=%dir%..\share set script=%dir%..\share\unitconv.tcl goto run ) echo unitconv.tcl not found pause goto done :run start /b %wish% %script% %1 :done endlocal CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.ico000066400000000000000000000020661343724673500212120ustar00rootroot00000000000000 &(( @( CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.png000066400000000000000000000004171343724673500212220ustar00rootroot00000000000000PNG  IHDR szzsBIT|dIDATXW ^_0ZW@17tnR>f&vzC*$=XEa_V)&i ň1@<$mB>P+5/@vÑr^RqS yck#h'mDQMD6`Q70?d n ZHw~Im8IENDB`CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.sh000077500000000000000000000022261343724673500210530ustar00rootroot00000000000000#!/bin/sh # sh script to launch unit convertor dir=`dirname $0` # source the setup script for d in $dir $dir/cgnstools $dir/.. ; do if test -f $d/cgconfig ; then . $d/cgconfig break fi done # The normal wish will work here, but calcwish should # be available, and may also be used calcwish="" for d in $CG_BIN_DIR $dir $dir/cgnstools $dir/cgnscalc \ /usr/local/bin /usr/local/bin/cgnstools ; do if test -x $d/calcwish ; then calcwish=$d/calcwish break fi if test -x $d/cgnswish/calcwish ; then calcwish=$d/cgnswish/calcwish break fi done if test -z "$calcwish" ; then echo "Error: calcwish executable not found" exit 1 fi # find the unitconv tcl script unitconv="" for d in $CG_LIB_DIR $dir $dir/cgnstools $dir/cgnscalc \ /usr/local/share /usr/local/share/cgnstools ; do if test -f $d/unitconv.tcl ; then unitconv=$d/unitconv.tcl break fi done if test -z "$unitconv" ; then echo "Error: unitconv.tcl script not found" exit 1 fi # check that display is set if test -z "$DISPLAY" ; then echo "Error: DISPLAY environment variable not set" exit 1 fi # execute exec $calcwish $unitconv CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.tcl000066400000000000000000000027271343724673500212260ustar00rootroot00000000000000#!/bin/sh # the next line restarts using wish \ exec wish -f "$0" "$@" proc error_exit {msg} { wm withdraw . tk_dialog .error Error $msg error 0 Exit exit 1 } if {[catch {package require Tk 8.0} msg]} { error_exit $msg } #----- get startup directory and name set cmd_name [file tail $argv0] set cmd_dir [file dirname $argv0] if {![file exists $argv0] || [file isdirectory $argv0]} { if {$tcl_platform(platform) == "windows"} { set sep ";" } else { set sep ":" } foreach i [split $env(PATH) $sep] { if {$sep == ";"} { set i [join [split $i \\] /] } if {[file exists $i/$cmd_name] && ![file isdirectory $i/$cmd_name]} { set cmd_dir $i break; } } } set curdir [pwd] if ![catch {cd $cmd_dir}] { set cmd_dir [pwd] cd $curdir } if {$tcl_platform(platform) == "windows"} { set cmd_dir [file attributes $cmd_dir -shortname] } #----- set path to tcl scripts set auto_path "$cmd_dir $cmd_dir/../common $auto_path" if {[info exists env(TCL_PROC_DIR)]} { set auto_path "$env(TCL_PROC_DIR) $auto_path" } #---------- initialize if [catch {config_defaults 1} msg] {error_exit $msg} if {$tcl_platform(platform) == "windows"} { set vers [join [split $tcl_version .] {}] catch {load tclreg$vers registry} } if {[tclreg_init -base "HKEY_CURRENT_USER/Software/CGNS" \ -fname ".cgnstools"]} { units_read } units:create . catch { config_icon . [list unitconv cgns] \ [list $cmd_dir $cmd_dir/images $cmd_dir/../common] } CGNS-3.4.0/src/cgnstools/cgnscalc/unitconv.xbm000066400000000000000000000016001343724673500212170ustar00rootroot00000000000000#define unitconv_width 32 #define unitconv_height 32 static unsigned char unitconv_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3c, 0x00, 0x00, 0xf8, 0x7f, 0xf0, 0x07, 0x0c, 0xc3, 0xf0, 0x0f, 0x0c, 0xc3, 0xf0, 0x0f, 0x0c, 0xc3, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0x3f, 0x0c, 0xc3, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x80, 0x0f, 0x03, 0x30, 0xc0, 0x0f, 0x03, 0xfc, 0xc0, 0x00, 0x03, 0xfc, 0xc0, 0x00, 0x03, 0x30, 0xc0, 0xc0, 0x3f, 0x30, 0xc0, 0xcf, 0x3f, 0xf0, 0xcf, 0x0f, 0x03, 0xf0, 0xcf, 0x00, 0x03, 0xe0, 0xcf, 0x00, 0x03, 0x00, 0xc0, 0x00, 0x03, 0x00, 0xc0, 0x00, 0x3f, 0x00, 0xc0, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CGNS-3.4.0/src/cgnstools/cgnscalc/winmain.c000066400000000000000000000203611343724673500204550ustar00rootroot00000000000000/* * winMain.c -- * * Main entry point for wish and other Tk-based applications. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include #include "tkWinInt.h" #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include #include extern int Calctcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); #ifdef USE_HTMLHELP extern int WinHtml_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* * Forward declarations for procedures defined later in this file: */ static void setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr)); static void WishPanic _ANSI_ARGS_(TCL_VARARGS(char *,format)); static int Proc_LoadIcon _ANSI_ARGS_((ClientData data, Tcl_Interp *interp, int argc, char **argv)); static HINSTANCE myInstance; /* *---------------------------------------------------------------------- * * WinMain -- * * Main entry point from Windows. * * Results: * Returns false if initialization fails, otherwise it never * returns. * * Side effects: * Just about anything, since from here we call arbitrary Tcl code. * *---------------------------------------------------------------------- */ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { char **argv; int argc; char buffer[MAX_PATH+1]; char *p; Tcl_SetPanicProc((Tcl_PanicProc *)WishPanic); /* * Increase the application queue size from default value of 8. * At the default value, cross application SendMessage of WM_KILLFOCUS * will fail because the handler will not be able to do a PostMessage! * This is only needed for Windows 3.x, since NT dynamically expands * the queue. */ SetMessageQueue(64); /* * Set up the default locale to be standard "C" locale so parsing * is performed correctly. */ setlocale(LC_ALL, "C"); setargv(&argc, &argv); /* * Replace argv[0] with full pathname of executable, and forward * slashes substituted for backslashes. */ GetModuleFileName(NULL, buffer, sizeof(buffer)); argv[0] = buffer; for (p = buffer; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } myInstance = hInstance; Tk_Main(argc, argv, Tcl_AppInit); return 1; } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(Tcl_Interp *interp) { if (Tcl_Init(interp) == TCL_ERROR) { goto error; } if (Tk_Init(interp) == TCL_ERROR) { goto error; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); if (Calctcl_Init(interp) == TCL_ERROR) goto error; #ifdef USE_HTMLHELP if (WinHtml_Init(interp) == TCL_ERROR) goto error; #endif Tcl_CreateCommand (interp, "LoadIcon", (Tcl_CmdProc *)Proc_LoadIcon, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_SetVar(interp, "tcl_rcFileName", "~/wishrc.tcl", TCL_GLOBAL_ONLY); return TCL_OK; error: MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); ExitProcess(1); /* we won't reach this, but we need the return */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * WishPanic -- * * Display a message and exit. * * Results: * None. * * Side effects: * Exits the program. * *---------------------------------------------------------------------- */ void WishPanic TCL_VARARGS_DEF(char *,arg1) { va_list argList; char buf[1024]; char *format; format = TCL_VARARGS_START(char *,arg1,argList); vsprintf(buf, format, argList); MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, buf, "Fatal Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); #ifdef _MSC_VER DebugBreak(); #endif ExitProcess(1); } /* *------------------------------------------------------------------------- * * setargv -- * * Parse the Windows command line string into argc/argv. Done here * because we don't trust the builtin argument parser in crt0. * Windows applications are responsible for breaking their command * line into arguments. * * 2N backslashes + quote -> N backslashes + begin quoted string * 2N + 1 backslashes + quote -> literal * N backslashes + non-quote -> literal * quote + quote in a quoted string -> single quote * quote + quote not in quoted string -> empty string * quote -> begin quoted string * * Results: * Fills argcPtr with the number of arguments and argvPtr with the * array of arguments. * * Side effects: * Memory allocated. * *-------------------------------------------------------------------------- */ static void setargv(int *argcPtr, char ***argvPtr) { char *cmdLine, *p, *arg, *argSpace; char **argv; int argc, size, inquote, copy, slashes; cmdLine = GetCommandLine(); /* INTL: BUG */ /* * Precompute an overly pessimistic guess at the number of arguments * in the command line by counting non-space spans. */ size = 2; for (p = cmdLine; *p != '\0'; p++) { if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ size++; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } } } argSpace = (char *) Tcl_Alloc( (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1)); argv = (char **) argSpace; argSpace += size * sizeof(char *); size--; p = cmdLine; for (argc = 0; argc < size; argc++) { argv[argc] = arg = argSpace; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } inquote = 0; slashes = 0; while (1) { copy = 1; while (*p == '\\') { slashes++; p++; } if (*p == '"') { if ((slashes & 1) == 0) { copy = 0; if ((inquote) && (p[1] == '"')) { p++; copy = 1; } else { inquote = !inquote; } } slashes >>= 1; } while (slashes) { *arg = '\\'; arg++; slashes--; } if ((*p == '\0') || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */ break; } if (copy != 0) { *arg = *p; arg++; } p++; } *arg = '\0'; argSpace = arg + 1; } argv[argc] = NULL; *argcPtr = argc; *argvPtr = argv; } /*---------------------------------------------------------------------- * set the toplevel window icon *----------------------------------------------------------------------*/ typedef struct TkWmInfo { TkWindow *winPtr; HWND hwnd; } WmInfo; static int Proc_LoadIcon(ClientData data, Tcl_Interp *interp, int argc, char **argv) { TkWindow *winPtr; HANDLE hIcon; HWND hwnd = NULL; if (2 != argc) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " iconname\"", (char *) NULL); return TCL_ERROR; } winPtr = (TkWindow *) Tk_MainWindow (interp); if (NULL != winPtr && NULL != winPtr->wmInfoPtr) hwnd = winPtr->wmInfoPtr->hwnd; if (!hwnd) { Tcl_SetResult (interp, "toplevel window has not been created/mapped", TCL_STATIC); return TCL_ERROR; } if (argv[1][0] == '@') hIcon = LoadImage (NULL, &argv[1][1], IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); else hIcon = (HANDLE) LoadIcon (myInstance, argv[1]); if (!hIcon) { Tcl_SetResult (interp, "icon not found", TCL_STATIC); return TCL_ERROR; } SetClassLongPtr (hwnd, GCLP_HICON, (LONG_PTR)hIcon); Tcl_ResetResult (interp); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsplot/000077500000000000000000000000001343724673500167215ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/cgnsplot/CMakeLists.txt000066400000000000000000000042211343724673500214600ustar00rootroot00000000000000############ # cgnsplot # ############ include_directories(${TCL_INCLUDE_PATH} ${TK_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR}) include_directories(../common) link_directories(. ../tkogl) if (CGNS_USE_SHARED) link_libraries(cgns_shared) else (CGNS_USE_SHARED) link_libraries(cgns_static) endif (CGNS_USE_SHARED) link_libraries(tkogl ${TCL_LIBRARY} ${TK_LIBRARY} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) if (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) link_libraries(${HDF5_LIBRARY}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) link_libraries(${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) link_libraries(${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) link_libraries(${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5 AND HDF5_LIBRARY) if (WIN32) if (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) add_definitions(-DUSE_HTMLHELP) include_directories(${HTML_HELP_INCLUDE_PATH}) link_libraries(${HTML_HELP_LIBRARY}) set(cgnsplot_FILES cgnstcl.c winmain.c ../common/hash.c ../common/winhtml.c) else (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) set(cgnsplot_FILES cgnstcl.c winmain.c ../common/hash.c) endif (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) else (WIN32) include_directories(${X11_X11_INCLUDE_PATH}) link_libraries(${X11_X11_LIB} ${X11_Xmu_LIB} m) set(cgnsplot_FILES cgnstcl.c plotwish.c ../common/hash.c) endif (WIN32) add_executable(plotwish ${cgnsplot_FILES}) add_dependencies(plotwish cgns_static tkogl) if (WIN32) set_target_properties(plotwish PROPERTIES LINK_FLAGS /subsystem:windows) endif (WIN32) if (WIN32) install(TARGETS plotwish RUNTIME DESTINATION bin) install(PROGRAMS cgnsplot.bat DESTINATION bin) install(FILES cgnsplot.tcl cgnsplot.ico cgnsplot.png cgnsplot-icon.xbm cgnsplot-mask.xbm DESTINATION share) else (WIN32) install(TARGETS plotwish RUNTIME DESTINATION bin/cgnstools) install(PROGRAMS cgnsplot.sh DESTINATION bin RENAME cgnsplot) install(FILES cgnsplot.tcl cgnsplot.ico cgnsplot.png cgnsplot-icon.xbm cgnsplot-mask.xbm DESTINATION share/cgnstools) endif (WIN32) CGNS-3.4.0/src/cgnstools/cgnsplot/Makefile.unix000066400000000000000000000050051343724673500213430ustar00rootroot00000000000000# Makefile for Unix/Linux include ../make.defs COPTS = $(CFLAGS) -I../common -I$(CGNSDIR) $(TKINCS) $(OGLINCS) LDLIST = $(CGNSLIB) $(BUILDLIBS) $(TKOGLLIB) $(TKLIBS) \ $(OGLLIBS) $(X11LIBS) $(TKOGLXLIB) $(CLIBS) #-------------------------------------------------- plotwish$(EXE) : plotwish.$(O) cgnstcl.$(O) hash.$(O) $(TKOGLLIB) $(CC) $(LDFLAGS) -o $@ plotwish.$(O) cgnstcl.$(O) hash.$(O) $(LDLIST) $(STRIP) $@ plotwish.$(O) : plotwish.c cgnstcl.$(O) : cgnstcl.c $(CC) $(COPTS) $(PLOTOPTS) -c cgnstcl.c hash.$(O) : ../common/hash.c ../common/hash.h $(CC) $(COPTS) -o hash.$(O) -c ../common/hash.c #--------------------------------------------------------------- ICONS = cgnsplot.ico cgnsplot.png cgnsplot-icon.xbm cgnsplot-mask.xbm install : install-dirs install-prog install-wish install-script install-dirs : @for d in \ $(BIN_INSTALL_DIR) \ $(EXE_INSTALL_DIR) \ $(WSH_INSTALL_DIR) \ $(LIB_INSTALL_DIR) ; do \ if [ ! -d $$d ] ; then \ echo "Making directory $$d"; \ mkdir -p $$d; \ chmod 755 $$d; \ fi; \ done; install-prog : @echo "installing cgnsplot shell scripts to $(BIN_INSTALL_DIR)" @$(INSTALL_PROG) cgnsplot.sh $(BIN_INSTALL_DIR)/cgnsplot @chmod +x $(BIN_INSTALL_DIR)/cgnsplot @if [ ! -f $(EXE_INSTALL_DIR)/cgconfig ] ; then \ echo "installing configuration file to $(EXE_INSTALL_DIR)"; \ $(INSTALL_DATA) ../cgconfig $(EXE_INSTALL_DIR)/cgconfig; \ fi; install-wish : plotwish$(EXE) @echo "installing plotwish executable to $(WSH_INSTALL_DIR)" @$(INSTALL_PROG) plotwish$(EXE) $(WSH_INSTALL_DIR) install-script : @echo "installing cgnsplot tcl scripts to $(LIB_INSTALL_DIR)" @$(INSTALL_DATA) cgnsplot.tcl $(LIB_INSTALL_DIR) @echo "installing icons to $(LIB_INSTALL_DIR)" @for i in $(ICONS) ; do \ $(INSTALL_DATA) $$i $(LIB_INSTALL_DIR); \ done; uninstall : @echo "uninstalling cgnsplot executables" @if [ -f $(BIN_INSTALL_DIR)/cgnsplot ] ; then \ /bin/rm -f $(BIN_INSTALL_DIR)/cgnsplot; \ fi; @if [ -f $(WSH_INSTALL_DIR)/plotwish$(EXE) ] ; then \ /bin/rm -f $(WSH_INSTALL_DIR)/plotwish$(EXE); \ fi; @echo "uninstalling cgnsplot tcl scripts" @if [ -f $(LIB_INSTALL_DIR)/cgnsplot.tcl ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/cgnsplot.tcl; \ fi; @echo "uninstalling cgnsplot icons" @for i in $(ICONS) ; do \ if [ -f $(LIB_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/$$i; \ fi; \ done; #--------------------------------------------------------------- .c.$(O) : $(CC) $(COPTS) -c $< clean: -$(RM) *.$(O) *~ *.bak plotwish$(EXE) CGNS-3.4.0/src/cgnstools/cgnsplot/Makefile.win000066400000000000000000000035071343724673500211620ustar00rootroot00000000000000include ..\make.win COPTS = $(CFLAGS) -I..\common -I$(CGNSDIR) $(TCLINC) #-------------------------------------------------- all : plotwish.exe dll : cgnstcl.dll install : plotwish.exe $(BINDIR) $(SHAREDIR) -$(INSTALL) plotwish.exe $(BINDIR) -$(INSTALL) cgnsplot.bat $(BINDIR) -$(INSTALL) cgnsplot.tcl $(SHAREDIR) -$(INSTALL) *.ico $(SHAREDIR) $(BINDIR) : $(INSTALLDIR) -mkdir $(BINDIR) $(SHAREDIR) : $(INSTALLDIR) -mkdir $(SHAREDIR) $(INSTALLDIR) : -mkdir $(INSTALLDIR) #-------------------------------------------------- plotwish.exe : winmain.obj cgnstcl.obj hash.obj $(WINHTML_OBJ) $(LINK) $(LFLAGS) /nodefaultlib /subsystem:windows \ -out:$@ winmain.obj cgnstcl.obj hash.obj $(WINHTML_OBJ) \ $(CGNSLIB) $(BUILDLIBS) $(CLIBS) $(TKOGLLIB) $(TCLLIB) $(TKLIB) \ $(guilibs) $(ogllibs) $(WINHTML_LIB) winmain.obj : winmain.c $(CC) $(COPTS) $(WINHTML_OPT) -c winmain.c cgnstcl.obj : cgnstcl.c $(CC) $(COPTS) $(PLOTOPTS) -c cgnstcl.c #-------------------------------------------------- cgnstcl.dll : cgnstcl-dll.obj hash.obj cgnames.obj $(CGNSLIB) $(LINK) -dll -out:cgnstcl.dll cgnstcl-dll.obj \ hash.obj cgnames.obj $(CGNSLIB) $(CLIBS) $(TCLLIB) $(TKLIB) \ $(dlllibs) $(ogllibs) cgnstcl-dll.obj : cgnstcl.c $(CC) $(COPTS) $(PLOTOPTS) -DBUILD_DLL -Fo$@ -c cgnstcl.c #-------------------------------------------------- hash.obj : ..\common\hash.c ..\common\hash.h $(CC) $(COPTS) -Fohash.obj -c ..\common\hash.c #-------------------------------------------------- winhtml.obj : ..\common\winhtml.c $(CC) $(COPTS) $(WINHTML_INC) -Fowinhtml.obj -c ..\common\winhtml.c #-------------------------------------------------- .c.obj : $(CC) $(COPTS) -Fo$@ -c $< .obj.exe : $(LINK) $(LFLAGS) /out:$@ $< $(CGNSLIB) clean: -$(RM) *.obj -$(RM) *.lib -$(RM) *.exp -$(RM) *.exe -$(RM) *.pdb -$(RM) *.ilk -$(RM) *.dll -$(RM) *.bak CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot-icon.xbm000066400000000000000000000016001343724673500222050ustar00rootroot00000000000000#define ploticon_width 32 #define ploticon_height 32 static unsigned char ploticon_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x80, 0x5f, 0x01, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xc0, 0x5f, 0x01, 0x00, 0xe0, 0xbf, 0x02, 0x00, 0xe0, 0x5f, 0x01, 0x00, 0xf0, 0xbf, 0x02, 0x00, 0xc0, 0x5f, 0x01, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot-mask.xbm000066400000000000000000000016001343724673500222100ustar00rootroot00000000000000#define plotmask_width 32 #define plotmask_height 32 static unsigned char plotmask_bits[] = { 0x10, 0x04, 0x41, 0x10, 0x10, 0x04, 0x41, 0x10, 0x10, 0x04, 0x41, 0x10, 0x10, 0x04, 0x51, 0x10, 0x10, 0x04, 0x59, 0x10, 0xff, 0xff, 0xff, 0xff, 0x10, 0x04, 0x7d, 0x10, 0x10, 0x04, 0x7d, 0x10, 0x10, 0x04, 0x7f, 0x10, 0x10, 0x04, 0xff, 0x10, 0x10, 0x04, 0xff, 0x10, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0xff, 0x11, 0x10, 0xc4, 0xff, 0x13, 0x10, 0xe4, 0xff, 0x13, 0x10, 0xe4, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, 0x10, 0xf4, 0xff, 0x1f, 0x08, 0xfa, 0xff, 0x27, 0x08, 0xf2, 0xff, 0x23, 0x04, 0xc2, 0xff, 0x21, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01, 0x7d, 0x41, 0x02, 0x01, 0x11, 0x41, 0x02, 0x81, 0x00, 0x42, 0x01, 0x81, 0x00, 0x82, 0xff, 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x04, 0x80, 0x80, 0x00, 0x04, 0x80, 0x80, 0x00, 0x04, 0x40, 0x80, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff}; CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot.bat000066400000000000000000000015421343724673500212440ustar00rootroot00000000000000@echo off setlocal set dir=%~dps0 if exist %dir%cgconfig.bat ( call %dir%cgconfig.bat goto getwish ) if exist %dir%..\cgconfig.bat call %dir%..\cgconfig.bat :getwish if "%CG_BIN_DIR%" == "" set CG_BIN_DIR=%dir% if exist %dir%plotwish.exe ( set wish=%dir%plotwish.exe goto getscript ) if exist %dir%cgnstools\plotwish.exe ( set wish=%dir%cgnstools\plotwish.exe goto getscript ) echo plotwish.exe not found pause goto done :getscript if exist %dir%cgnsplot.tcl ( set script=%dir%cgnsplot.tcl goto run ) if not "%CG_LIB_DIR%" == "" ( if exist %CG_LIB_DIR%\cgnsplot.tcl ( set script=%CG_LIB_DIR%\cgnsplot.tcl goto run ) ) if exist %dir%..\share\cgnsplot.tcl ( set CG_LIB_DIR=%dir%..\share set script=%dir%..\share\cgnsplot.tcl goto run ) echo cgnsplot.tcl not found pause goto done :run start /b %wish% %script% %1 :done endlocal CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot.ico000066400000000000000000000020661343724673500212520ustar00rootroot00000000000000 &(( @ᙙᙙwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqwwwwwwwqwwwwwwwwwwwwwwww|wwwwwwww|wwwwwwww|wwwwwwwww|wwwwwwwww|wwwwwwwww|www( |ww|ww|wqw̑|w|w|w|q|w|w|w|w|w|w|wCGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot.png000066400000000000000000000005751343724673500212670ustar00rootroot00000000000000PNG  IHDR szzsBIT|d4IDATXW KL|3|ñA/1 Ob  カ. _'@,$h]Ѫ.M{ NmCY %Yܣ_15x~2ka} ?2Ң`*š"Wj/=ksA~R@ bh0-k!&0W\CH"\{> p6vJֽ^'xʑEhh"lSLjS 0OmYa'0s+̽-jYgnҞ?gG ҂ˋ LeIENDB`CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot.sh000066400000000000000000000022271343724673500211110ustar00rootroot00000000000000#!/bin/sh # sh script to launch CGNS plot dir=`dirname $0` # source the setup script for d in $dir $dir/cgnstools $dir/.. ; do if test -f $d/cgconfig ; then . $d/cgconfig break fi done # get the plotwish executable plotwish="" for d in $CG_BIN_DIR $dir $dir/cgnstools $dir/cgnsplot \ /usr/local/bin /usr/local/bin/cgnstools ; do if test -x $d/plotwish ; then plotwish=$d/plotwish break fi if test -x $d/cgnswish/plotwish ; then plotwish=$d/cgnswish/plotwish break fi done if test -z "$plotwish" ; then echo "Error: plotwish executable not found" exit 1 fi # find the cgnsplot tcl script cgnsplot="" for d in $CG_LIB_DIR $dir $dir/cgnstools $dir/cgnsplot \ /usr/local/share /usr/local/share/cgnstools ; do if test -f $d/cgnsplot.tcl ; then cgnsplot=$d/cgnsplot.tcl break fi done if test -z "$cgnsplot" ; then echo "Error: cgnsplot.tcl script not found" exit 1 fi # check that display is set #if test -z "$DISPLAY" ; then # echo "Error: DISPLAY environment variable not set" # exit 1 #fi # execute if test "$#" = 0 ; then exec $plotwish $cgnsplot else exec $plotwish $cgnsplot "$@" fi CGNS-3.4.0/src/cgnstools/cgnsplot/cgnsplot.tcl000066400000000000000000001641421343724673500212660ustar00rootroot00000000000000#!/bin/sh # the next line restarts using wish \ exec plotwish -f "$0" "$@" proc error_exit {msg} { wm withdraw . tk_dialog .error Error $msg error 0 Exit exit 1 } if {[catch {package require Tk 8.0} msg]} { error_exit $msg } #---------- get platform set platform $tcl_platform(platform) if {$platform == "windows" && [info exists env(TERM)] && ($env(TERM) == "cygwin" || $env(TERM) == "xterm")} { set platform cygwin } #----- get startup directory and name set cmd_name [file tail $argv0] set cmd_dir [file dirname $argv0] if {![file exists $argv0] || [file isdirectory $argv0]} { if {$platform == "windows"} { set sep ";" } else { set sep ":" } foreach i [split $env(PATH) $sep] { if {$sep == ";"} { set i [join [split $i \\] /] } if {[file exists $i/$cmd_name] && ![file isdirectory $i/$cmd_name]} { set cmd_dir $i break; } } } set curdir [pwd] if ![catch {cd $cmd_dir}] { set cmd_dir [pwd] cd $curdir } if {$tcl_platform(platform) == "windows"} { set cmd_dir [file attributes $cmd_dir -shortname] } #----- set path to tcl scripts set auto_path "$cmd_dir $cmd_dir/../common $auto_path" if {[info exists env(TCL_PROC_DIR)]} { set auto_path "$env(TCL_PROC_DIR) $auto_path" } #----- initialize if {$platform == "windows"} { set vers [join [split $tcl_version .] {}] if {[info commands CGNSopen] == {}} { if {[catch {load cgnstcl$vers} msg]} { error_exit $msg } } catch {load tclreg$vers registry} } else { if {[info commands CGNSopen] == {}} { error_exit "need to run script with plotwish" } } if {[catch {package require Tkogl} msg]} { error_exit $msg } if [catch {config_defaults 1} msg] {error_exit $msg} array set ProgData { winwidth 700 winheight 500 seppos 0.25 sepwd 7 cgnsfile "" displaylist "" axislist "" planelist "" cutlist "" background {0.0 0.0 0.0} autocolor 1 showcolors 1 showlines 1 twosided 0 culling disable revnorm 0 axis 0 meshvis 1 meshmode 1 regvis 0 regmode 2 edgeangle 60 fov 30 np 0.025 fp 2.0 bases {} nzones 0 zones {} curbase "" curnode "" curdim 0 curclr "" curmode 0 cutplane "" cutcolor {0.7 0.7 0.4 0.5} cutmode 1 usecutclr 0 ignorevis 0 drawID "" dotrace 0 reg,file ".cgnstools" reg,base "HKEY_CURRENT_USER/Software/CGNS" reg,key "CGNSplot" reg,vals {cgnsfile background autocolor twosided culling \ axis edgeangle meshvis meshmode regvis regmode fov \ winwidth winheight seppos cutcolor usecutclr ignorevis \ showcolors showlines} } #----- read registry if {[tclreg_init -base $ProgData(reg,base) -fname $ProgData(reg,file)]} { foreach i $ProgData(reg,vals) { if {![catch {tclreg_get $ProgData(reg,key) $i} val] && $val != ""} { set ProgData($i) $val } } } #---------- main window wm title . "CGNSplot" wm protocol . WM_DELETE_WINDOW do_quit proc do_quit {} { global ProgData catch CGNSclose set ProgData(winwidth) [winfo width .main] set ProgData(winheight) [winfo height .main] foreach i $ProgData(reg,vals) { catch {tclreg_set $ProgData(reg,key) $i $ProgData($i)} } catch tclreg_close catch {WinHtml close} destroy . exit 0 } #----- menu menubar_create {File Options View Display Help} #----- file menu set m [menubar_get File] $m add command -label "Load CGNS..." -command load_cgns $m add separator $m add command -label "Quit" -command do_quit #----- options menu set m [menubar_get Options] $m add command -label "Set Defaults..." -command set_defaults $m add command -label "Set Perspective..." -command set_perspective #----- view menu set m [menubar_get View] $m add command -label "Open Level" -command tree_open $m add command -label "Close Level" -command tree_close $m add separator $m add command -label "Reset View" -command {reset_view; $OGLwin redraw} $m add command -label "Center View" -command Center #----- display menu set m [menubar_get Display] $m add checkbutton -label "Two Sided" -command set_twosided \ -variable ProgData(twosided) -onvalue 1 -offvalue 0 $m add checkbutton -label "Backface Culling" -command set_culling \ -variable ProgData(culling) -onvalue enable -offvalue disable #$m add checkbutton -label "Reverse Normals" -command set_normals \ # -variable ProgData(revnorm) -onvalue 1 -offvalue 0 $m add checkbutton -label "Display Axis" -command set_axis \ -variable ProgData(axis) -onvalue 1 -offvalue 0 if {[info commands OGLcutplane] != ""} { $m add command -label "Cutting Plane..." -command cutplane_control } proc set_twosided {} { global ProgData OGLwin if {$ProgData(twosided)} { .toolbar.but.b3.twosided configure -relief sunken set_balloon .toolbar.but.b3.twosided "Disable Two-Sided Lighting" } else { .toolbar.but.b3.twosided configure -relief raised set_balloon .toolbar.but.b3.twosided "Enable Two-Sided Lighting" } $OGLwin eval -lightmodel lightmodeltwoside $ProgData(twosided) $OGLwin redraw } proc set_culling {} { global ProgData OGLwin if {$ProgData(culling) == "enable"} { .toolbar.but.b3.culling configure -relief sunken set_balloon .toolbar.but.b3.culling "Disable Backface Culling" } else { .toolbar.but.b3.culling configure -relief raised set_balloon .toolbar.but.b3.culling "Enable Backface Culling" } $OGLwin eval -$ProgData(culling) cullface $OGLwin redraw } proc set_normals {} { global ProgData OGLwin if {$ProgData(revnorm)} { .toolbar.but.b3.revnorm configure -relief sunken set_balloon .toolbar.but.b3.revnorm "Default Face Normals" } else { .toolbar.but.b3.revnorm configure -relief raised set_balloon .toolbar.but.b3.revnorm "Reverse Face Normals" } } proc set_axis {} { global ProgData OGLwin if {$ProgData(axis)} { .toolbar.but.b3.axis configure -relief sunken set_balloon .toolbar.but.b3.axis "Disable Axis Display" } else { .toolbar.but.b3.axis configure -relief raised set_balloon .toolbar.but.b3.axis "Enable Axis Display" } OGLaxis $ProgData(axis) $OGLwin redraw } #----- help menu set m [menubar_get Help] $m add command -label "CGNSplot Help..." \ -command {help_show cgnstools/cgnsplot/index.html} $m add command -label "CGNS Help..." -command {help_show} $m add separator $m add command -label "Configure Help..." -command help_setup $m add separator $m add command -label "About..." -underline 0 -command do_about image create photo img_about -data {\ R0lGODlhIAAgALMAAAAA/wD//4QAAMbGxv8AAP//////////////////////////////////\ /////////ywAAAAAIAAgAAAEv3AMIGelEttbN8+fp3mkGGpj2plgawluiZ6XAJMooO98v9sC\ H881cwkINtyqyBocgaoOs3hE2qI0oqQKvMWas6o1eRKaxd2gT0sUj8my7MSdvo3AFfebfJ/m\ CYCAdTA5Zj+BgYM9AQEAjI6MjYx6e1CRko+RkJSVNpiYkJmTiIJ1mp+hnwE2iHWphmeJXUKi\ p5eSXEC2l6mqorO3r7e+tQK1tb3ExMmOsM7Ow8rSydHU09HD1tfYx9nYvc/hQhEAADs=} proc do_about {} { global ProgData dialog .about -1 -1 "About CGNSplot" \ "CGNSplot Version 3.2 Bruce Wedan leavingdust@gmail.com" img_about 0 Close } #---------- toolbar frame .toolbar pack .toolbar -side top -pady 2 -fill x set f [frame .toolbar.but] pack $f -side left #--- image create photo img_open -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQ4EMlJKwJvZcC7BxdnSV04nCgKjtR6vZgmZ49L\ bmlus7xV9j4QQPYRtWbI3RCXU10WgKaTVPQAexEAOw==} button $f.open -image img_open -takefocus 0 \ -command {load_cgns ""} pack $f.open -side left -padx 5 set_balloon $f.open "Open a CGNS File..." #--- image create photo img_colors -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwRFEMlJ63TYsc2ab1QiJku5KKhCPewDvMAhH+Fo\ nimVadwHTi0XbEazGI/IyohkSqkmy5tTl+F0PlSM1bdqwWKzLutLTB4jADs=} image create photo img_viewing -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQqEMlJqwT2uo0z6JkFht44fdSnVuipmiXpyUhL\ wiwMbA5onzzcj3bB0ToRADs=} set b [frame $f.b1] pack $b -side left -padx 5 button $b.colors -image img_colors -takefocus 0 \ -command set_defaults set_balloon $b.colors "Set Defaults..." button $b.viewing -image img_viewing -takefocus 0 \ -command set_perspective set_balloon $b.viewing "Set Perspective..." pack $b.colors $b.viewing -side left -padx 1 #--- image create photo img_expand -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQvEMlJq712DJzX5pP2VQBIWuWVUitBTCsMlMTz\ IrHl3jnYUy7J7Cep8UA7k3IpiQAAOw==} image create photo img_collapse -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQkEMlJq7046wrwGBQgXsMCTh35hRvbSqm1urJJ\ V98Jvzvv/5UIADs=} image create photo img_reset -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQiEMlJKwXYWqA17xXGjQgZguA3qWhbni58vaQY\ vzHb2XdvRQA7} image create photo img_center -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQmEMmJAL22Ypmp/dolduJYcqiXqiB5umcFwG9s\ YzOd07fZy7yfJAIAOw==} set b [frame $f.b2] pack $b -side left -padx 5 button $b.expand -image img_expand -takefocus 0 -command tree_open set_balloon $b.expand "Open One Level" button $b.collapse -image img_collapse -takefocus 0 -command tree_close set_balloon $b.collapse "Close One Level" button $b.reset -image img_reset -takefocus 0 \ -command {reset_view; $OGLwin redraw} set_balloon $b.reset "Reset View" button $b.center -image img_center -takefocus 0 \ -command Center set_balloon $b.center "Center View" pack $b.expand $b.collapse $b.reset $b.center -side left #--- image create photo img_twosided -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwRGEMlJKwLnUMZoBtSyPNwjWpJIMuaCbh2KTQvn\ Sgd4aak95S/OyyIc0nyyG6KIWOgwB9GoJP1ApavW4iMBKJnOV42hNDIpEQA7} image create photo img_culling -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQqEMlJq5UgX6oxuF0VhuCHfKR3YlM3spzZwpxI\ z/Vq56nc+zcRKlXaGC0RADs=} image create photo img_axis -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQwEEkJUJ04o5V6p9o2hJlAnteJLaOKKIqJujNt\ Z+ydY1UqwYKAMGAp/mIqgNKm9J0iADs=} image create photo img_revnorm -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQ5EMlJq6XsIsAn+1rnhdsEMMCVStzpiCwLODRD\ v2s634595zIeDVYK4iw600q1RGSYTc3l85SOrNgIADs=} image create photo img_cutting -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQwEMlJq5UEkFsBQB6HbGNpXp+UimDIErBJWjFL\ rSuH22DP+7wNbFYhCTEXI4b4m0QAADs=} set b [frame $f.b3] pack $b -side left -padx 5 button $b.twosided -image img_twosided -takefocus 0 \ -command toggle_twosided if {$ProgData(twosided)} { $b.twosided configure -relief sunken set_balloon $b.twosided "Disable Two-Sided Lighting" } else { set_balloon $b.twosided "Enable Two-Sided Lighting" } button $b.culling -image img_culling -takefocus 0 \ -command toggle_culling if {$ProgData(culling) == "enable"} { $b.culling configure -relief sunken set_balloon $b.culling "Disable Backface Culling" } else { set_balloon $b.culling "Enable Backface Culling" } button $b.revnorm -image img_revnorm -takefocus 0 \ -command toggle_normals if {$ProgData(revnorm)} { $b.revnorm configure -relief sunken set_balloon $b.revnorm "Default Face Normals" } else { set_balloon $b.revnorm "Reverse Face Normals" } button $b.axis -image img_axis -takefocus 0 \ -command toggle_axis if {$ProgData(axis)} { $b.axis configure -relief sunken set_balloon $b.axis "Disable Axis Display" } else { set_balloon $b.axis "Enable Axis Display" } #pack $b.twosided $b.culling $b.revnorm $b.axis -side left -padx 1 pack $b.twosided $b.culling $b.axis -side left -padx 1 if {[info commands OGLcutplane] != ""} { button $b.cutting -image img_cutting -takefocus 0 \ -command cutplane_control set_balloon $b.cutting "Cutting Plane..." pack $b.cutting -side left -padx 1 } proc toggle_twosided {} { global ProgData if {$ProgData(twosided)} { set ProgData(twosided) 0 } else { set ProgData(twosided) 1 } set_twosided } proc toggle_culling {} { global ProgData if {$ProgData(culling) == "enable"} { set ProgData(culling) disable } else { set ProgData(culling) enable } set_culling } proc toggle_normals {} { global ProgData if {$ProgData(revnorm)} { set ProgData(revnorm) 0 } else { set ProgData(revnorm) 1 } set_normals } proc toggle_axis {} { global ProgData if {$ProgData(axis)} { set ProgData(axis) 0 } else { set ProgData(axis) 1 } set_axis } #--- image create photo img_help -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQiEMlJq50kX5kJ1hvShd+4mSJ4qmTrXl28ehw7\ t+j75joVAQA7} button $f.help -image img_help -takefocus 0 \ -command {help_show cgnstools/cgnsplot/index.html} set_balloon $f.help "CGNSplot Help..." pack $f.help -side left -padx 5 frame .toolsep -bd 1 -height 2 -relief sunken pack .toolsep -side top -fill x #----- status bar set ProgData(status) "" label .status -textvariable ProgData(status) -relief sunken -anchor w pack .status -side bottom -fill x -padx 5 -pady 3 proc display_message {msg} { global ProgData set ProgData(status) $msg update idletasks } #---------- main window frame .main -width $ProgData(winwidth) -height $ProgData(winheight) pack .main -side top -fill both -expand 1 -padx 5 -pady 2 #--- window seperator frame .main.sep -width 4 -bd 2 -relief raised -cursor sb_h_double_arrow bind .main.sep sep_begin_move proc sep_begin_move {} { set width [winfo width .main] set x [winfo rootx .main.sep] set y [winfo rooty .main.sep] set h [winfo height .main.sep] set xmin [expr [winfo rootx .main] + 100] set xmax [expr [winfo rootx .main] + $width - 100] set top [toplevel .main.move -borderwidth 1 \ -relief raised -cursor sb_h_double_arrow] wm overrideredirect $top 1 wm geom $top "4x$h+$x+$y" update idletasks grab set $top bind $top "sep_end_move $top $xmin $xmax %X" bind $top "sep_move $top $xmin $xmax %X $y" } proc sep_move {top xmin xmax x y} { if {$x < $xmin} { set x $xmin } elseif {$x > $xmax} { set x $xmax } wm geom $top "+$x+$y" } proc sep_end_move {top xmin xmax x} { global ProgData destroy $top if {$x < $xmin} { set x $xmin } elseif {$x > $xmax} { set x $xmax } set s [expr double($x - [winfo rootx .main]) / \ double([winfo width .main])] sep_locate $s } proc sep_locate {s} { global ProgData if [expr $s < 0.5] { place .main.sel -relx 0 -x 0 \ -relwidth $s -width -$ProgData(sepwd) \ -rely 0 -relheight 1 place .main.plot -relx $s -x $ProgData(sepwd) \ -relwidth [expr 1.0 - $s] -width -$ProgData(sepwd) \ -rely 0 -relheight 1 } else { place .main.plot -relx 0 -x 0 \ -relwidth $s -width -$ProgData(sepwd) \ -rely 0 -relheight 1 place .main.sel -relx $s -x $ProgData(sepwd) \ -relwidth [expr 1.0 - $s] -width -$ProgData(sepwd) \ -rely 0 -relheight 1 } place .main.sep -relx $s -x -2 -rely 0 -relheight 1 set ProgData(seppos) $s } frame .main.plot frame .main.sel sep_locate $ProgData(seppos) #----- OpenGL window set OGLwin .main.plot.gl if {[catch {OGLwin $OGLwin} msg]} { error_exit $msg } pack $OGLwin -side left -fill both -expand 1 #---------- selections # base selection set f [frame .main.sel.base] pack $f -side top -fill x -pady 5 label $f.lab -text Base pack $f.lab -side left set ProgData(baselist) [ComboboxCreate $f.cb -width 10 \ -edit 0 -state disabled -command set_base] pack $f.cb -side left -fill x -expand 1 # object tree image create photo box_empty -data { R0lGODlhDAAMALMAAAAAAMbGxv//////////////////////////////////////////////\ /////////yH5BAEAAAEALAAAAAAMAAwAAAQaEMhJZ7g4y8zD7tgHesB4iSDaqRyrlWYlSxEA\ Ow==} image create photo box_checked -data { R0lGODlhDAAMALMAAAAAAMbGxv//////////////////////////////////////////////\ /////////yH5BAEAAAEALAAAAAAMAAwAAAQjEMhJabj4CrmznkGHddJnBuUnokC2siOwpqJY\ vqTcelvlSxEAOw==} image create photo box_question -data { R0lGODlhDAAMALMAAIQAAMbGxv8AAP//////////////////////////////////////////\ /////////yH5BAEAAAEALAAAAAAMAAwAAAQjMMggap1TgL0FrsAEXJIWSqNXbiKJoePbqnIn\ i/Gtv7beSxEAOw==} set f [frame .main.sel.objs] pack $f -side top -fill both -expand 1 set ProgData(tree) $f.tree scrollbar $f.ys -orient vertical -command "$ProgData(tree) yview" \ -takefocus 0 -highlightthickness 0 pack $f.ys -side right -fill y scrollbar $f.xs -orient horizontal -command "$ProgData(tree) xview" \ -takefocus 0 -highlightthickness 0 pack $f.xs -side bottom -fill x TreeCreate $ProgData(tree) -width 150 -height 300 -relief sunken \ -bd 2 -highlightthickness 1 -yscrollcommand "$f.ys set" -takefocus 1 \ -xscrollcommand "$f.xs set" -font $Font(normal) -padx 4 \ -lines $ProgData(showlines) pack $ProgData(tree) -side left -fill both -expand 1 bind $ProgData(tree) <1> {tree_show %W %x %y} bind $ProgData(tree) {tree_info %W %x %y} bind $ProgData(tree) <3> {tree_menu %W %x %y} bind $ProgData(tree) {tree_at %W %x %y Toggle} bind $ProgData(tree) {tree_at %W %x %y Expand} bind $ProgData(tree) {tree_at %W %x %y Collapse} set ProgData(menu) [menu .nodemenu -tearoff 0] $ProgData(menu) add radiobutton -label "Outline" \ -variable ProgData(curmode) -value 1 -command update_mode $ProgData(menu) add radiobutton -label "Mesh" \ -variable ProgData(curmode) -value 2 -command update_mode $ProgData(menu) add radiobutton -label "Shaded" \ -variable ProgData(curmode) -value 3 -command update_mode $ProgData(menu) add separator $ProgData(menu) add command -label "Color..." \ -command "update_color $ProgData(tree)" $ProgData(menu) add command -label "AutoColor" \ -command "auto_color $ProgData(tree)" $ProgData(menu) add command -label "Info..." proc tree_show {w x y} { set value [TreeTypeAt $w $x $y] if {$value == ""} return set type [lindex $value 0] set node [lindex $value 1] if {$type == "image"} { toggle_visibility $node } else { if {$node != [TreeSelectionGet $w]} { set_node $node } } } proc tree_info {w x y} { set value [TreeTypeAt $w $x $y] if {$value == ""} return if {[lindex $value 0] == "text"} { show_info $w $x $y [lindex $value 1] } } proc tree_menu {w x y} { global ProgData set value [TreeTypeAt $w $x $y] if {$value == ""} return if {[lindex $value 0] == "image"} return set node [lindex $value 1] if {$node != [TreeSelectionGet $w]} { set_node $node } if {$ProgData(curdim) == 0} { set state disabled } else { set state normal } foreach n {0 1 2 4 5} { $ProgData(menu) entryconfigure $n -state $state } set cnt [llength [TreeGet $w $node -tag]] if {$cnt < 1 || $cnt > 2} { $ProgData(menu) entryconfigure 6 -state disabled } else { $ProgData(menu) entryconfigure 6 -state normal \ -command "show_info $w $x $y {$node}" } $ProgData(menu) post [expr [winfo rootx $ProgData(tree)] + $x] \ [expr [winfo rooty $ProgData(tree)] + $y] } proc tree_at {w x y mode} { set value [TreeTypeAt $w $x $y] if {$value == ""} return set type [lindex $value 0] set node [lindex $value 1] if {$type == "image"} { if {$mode == "Expand"} { set_visibility $node 1 1 if {$node != [TreeSelectionGet $w]} { set_node $node } } elseif {$mode == "Collapse"} { set_visibility $node 0 1 } else { return } update_node $node } else { if {$node != [TreeSelectionGet $w]} { set_node $node } Tree$mode $w $node } } proc tree_open {} { global ProgData catch {TreeOpenLevel $ProgData(tree) /} } proc tree_close {} { global ProgData catch {TreeCloseLevel $ProgData(tree) /} } # options frame .main.sel.opts pack .main.sel.opts -side top -fill x set f [frame .main.sel.opts.top] pack $f -side top -fill x radiobutton $f.o -text "Outline" -variable ProgData(curmode) -value 1 \ -command update_mode -state disabled pack $f.o -side left radiobutton $f.m -text "Mesh" -variable ProgData(curmode) -value 2 \ -command update_mode -state disabled pack $f.m -side right set f [frame .main.sel.opts.bot] pack $f -side top -fill x radiobutton $f.s -text "Shaded" -variable ProgData(curmode) -value 3 \ -command update_mode -state disabled pack $f.s -side left set ProgData(clrbut) [button $f.c -relief solid -text Color... \ -borderwidth 1 -command "update_color $f.c" -state disabled] pack $f.c -side right -padx 5 proc options_state {dim} { if {$dim} { set state normal } else { set state disabled } foreach i {top.o top.m bot.s} { .main.sel.opts.$i configure -state $state } } #----- help proc help_menu {} { if [help_valid] { menubar_state Help normal 0 menubar_state Help normal 1 .toolbar.but.help configure -state normal } else { menubar_state Help disabled 0 menubar_state Help disabled 1 .toolbar.but.help configure -state disabled } } help_init #----- set default colors and zone/region viewing proc set_defaults {{loc .}} { global ProgData Defaults OGLwin fgColor Font foreach i {showcolors showlines meshvis meshmode regvis regmode \ background autocolor} { set Defaults($i) $ProgData($i) } set w .defaults toplevel $w wm title $w "Defaults" wm transient $w . wm protocol $w WM_DELETE_WINDOW {set ProgData(done) 0} FrameCreate $w.tree -text "Display Tree" -font $Font(bold) -padx 0 -pady 0 pack $w.tree -side top -padx 5 -pady 2 -fill x -expand 1 set tree [FrameGet $w.tree] checkbutton $tree.colors -text "Show Colors" -onvalue 1 -offvalue 0 \ -variable Defaults(showcolors) -highlightthickness 0 checkbutton $tree.lines -text "Show Lines" -onvalue 1 -offvalue 0 \ -variable Defaults(showlines) -highlightthickness 0 pack $tree.colors $tree.lines -side left -expand 1 FrameCreate $w.zone -text "Volume Mesh" -font $Font(bold) -padx 0 -pady 0 pack $w.zone -side top -padx 5 -pady 2 -fill x -expand 1 set zone [FrameGet $w.zone] checkbutton $zone.vis -text "Visible as" -onvalue 1 -offvalue 0 \ -variable Defaults(meshvis) -highlightthickness 0 pack $zone.vis -side top -anchor w set f [frame $zone.mode] pack $f -side top -fill x -expand 1 radiobutton $f.o -text "Outline" -variable Defaults(meshmode) -value 1 \ -highlightthickness 0 radiobutton $f.m -text "Mesh" -variable Defaults(meshmode) -value 2 \ -highlightthickness 0 radiobutton $f.s -text "Shaded" -variable Defaults(meshmode) -value 3 \ -highlightthickness 0 pack $f.o $f.m $f.s -side left -expand 1 FrameCreate $w.reg -text Regions -font $Font(bold) -padx 0 -pady 0 pack $w.reg -side top -padx 5 -pady 2 -fill x -expand 1 set reg [FrameGet $w.reg] checkbutton $reg.vis -text "Visible as" -onvalue 1 -offvalue 0 \ -variable Defaults(regvis) -highlightthickness 0 pack $reg.vis -side top -anchor w set f [frame $reg.mode] pack $f -side top -fill x -expand 1 radiobutton $f.o -text "Outline" -variable Defaults(regmode) -value 1 \ -highlightthickness 0 radiobutton $f.m -text "Mesh" -variable Defaults(regmode) -value 2 \ -highlightthickness 0 radiobutton $f.s -text "Shaded" -variable Defaults(regmode) -value 3 \ -highlightthickness 0 pack $f.o $f.m $f.s -side left -expand 1 FrameCreate $w.colors -text Colors -font $Font(bold) pack $w.colors -side top -padx 5 -pady 2 -fill x -expand 1 set colors [FrameGet $w.colors] set f [frame $colors.bg] pack $f -side top -fill x -expand 1 label $f.lab -text "Background Color" pack $f.lab -side left button $f.but -text Select -relief solid -bd 1 \ -command "background_color $f.but" color_button $f.but $Defaults(background) pack $f.but -side right set auto [frame $colors.auto] pack $auto -side top -fill x -expand 1 label $auto.lab -text "Assign Color Based On" pack $auto.lab -side top -anchor w set f [frame $auto.mode] pack $f -side top -fill x -expand 1 radiobutton $f.z -text "Zone" -variable Defaults(autocolor) -value 0 \ -highlightthickness 0 radiobutton $f.r -text "Region" -variable Defaults(autocolor) -value 1 \ -highlightthickness 0 pack $f.z $f.r -side left -expand 1 set f [frame $w.but] pack $f -side top -padx 5 -pady 2 -fill x -expand 1 button $f.default -text Defaults -width 8 -underline 0 \ -command "default_values $w" button $f.accept -text Accept -width 8 -underline 0 \ -command {set ProgData(done) 1} button $f.cancel -text Cancel -width 8 -underline 0 \ -command {set ProgData(done) 0} pack $f.default $f.accept $f.cancel -side left -pady 5 bind $w "$f.default flash; default_values $w" bind $w "$f.accept flash; set ProgData(done) 1" bind $w "$f.cancel flash; set ProgData(done) 0" center_window $w $loc set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable ProgData(done) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } if {$ProgData(done)} { foreach i {meshvis meshmode regvis regmode background autocolor} { set ProgData($i) $Defaults($i) } eval $OGLwin eval -clearcolor $ProgData(background) init_display Center if {$Defaults(showlines) != $ProgData(showlines)} { set ProgData(showlines) $Defaults(showlines) TreeConfig $ProgData(tree) -lines $ProgData(showlines) } if {$Defaults(showcolors) != $ProgData(showcolors)} { set ProgData(showcolors) $Defaults(showcolors) build_tree } } } proc default_values {w} { global Defaults array set Defaults { showcolors 1 showlines 1 meshvis 1 meshmode 1 regvis 0 regmode 2 autocolor 0 background {0.0 0.0 0.0} } set cf [FrameGet $w.colors] color_button $cf.bg.but $Defaults(background) } proc background_color {but} { global Defaults set clr [select_color $Defaults(background) "Background Color" $but] if {$clr != ""} { set Defaults(background) $clr color_button $but $clr } } proc color_button {but clr} { global fgColor bgColor if {$clr == ""} { $but configure -fg $fgColor(normal) -activeforeground $fgColor(active) \ -bg $bgColor(normal) -activebackground $bgColor(active) \ -state disabled } else { if {[color_gray $clr] > 0.5} { set fg black } else { set fg white } $but configure -fg $fg -activeforeground $fg \ -bg [color_value $clr] \ -activebackground [color_value [color_lighten $clr]] \ -state normal } } proc select_color {oldclr title {loc .}} { return [color_select .color $title $oldclr $loc] } #----- set perspective ----- set Perspective(fov) $ProgData(fov) set Perspective(fd) [expr 0.5 / tan(0.00872665 * $Perspective(fov))] set Perspective(np) [expr $Perspective(fd) * $ProgData(np)] set Perspective(fp) [expr $Perspective(fd) * $ProgData(fp)] set Perspective(ar) 1.0 set Viewpoint(x) 0 set Viewpoint(y) 0 set Viewpoint(z) $Perspective(fd) proc apply_perspective {what val} { global ProgData Perspective OGLwin Viewpoint set Perspective(fov) $ProgData(fov) set fd [expr 0.5 / tan(0.00872665 * $Perspective(fov))] set Viewpoint(z) [expr $fd * $Viewpoint(z) / $Perspective(fd)] set Perspective(fd) $fd if {[expr $ProgData(fp) <= $ProgData(np)]} { if {$what == "np"} { set ProgData(fp) [expr 0.01 * (100.0 * $ProgData(np) + 1.0)] } else { set ProgData(np) [expr $ProgData(fp) - 0.001] } } set Perspective(np) [expr $fd * $ProgData(np)] set Perspective(fp) [expr $fd * $ProgData(fp)] compute_viewport $OGLwin set_view $OGLwin } proc set_perspective {{loc .}} { global ProgData fgColor Font set w .perspective if [winfo exists $w] { wm deiconify $w return } toplevel $w wm title $w "Perspective" FrameCreate $w.opts -font $Font(bold) pack $w.opts -side top -padx 5 -pady 5 set opts [FrameGet $w.opts] set f [frame $opts.fov] pack $f -side top label $f.lab -width 18 -anchor w -text "Field of View" scale $f.scl -length 200 -from 5 -to 85 -variable ProgData(fov) \ -orient horizontal -command {apply_perspective fov} pack $f.lab $f.scl -side left set f [frame $opts.np] pack $f -side top label $f.lab -width 18 -anchor w -text "Near Clipping Plane" scale $f.scl -length 200 -from 0.001 -to 1 -resolution .001 \ -variable ProgData(np) -orient horizontal -command {apply_perspective np} pack $f.lab $f.scl -side left set f [frame $opts.fp] pack $f -side top label $f.lab -width 18 -anchor w -text "Far Clipping Plane" scale $f.scl -length 200 -from .01 -to 5 -resolution .01 \ -variable ProgData(fp) -orient horizontal -command {apply_perspective fp} pack $f.lab $f.scl -side left set f [frame $w.but] pack $f -side top -fill x -expand 1 button $f.default -text Defaults -width 8 -command perspective_defaults button $f.close -text Close -width 8 -command "destroy $w" pack $f.default $f.close -side left -pady 2 -expand 1 center_window $w $loc } proc perspective_defaults {} { global ProgData array set ProgData { fov 30 np 0.025 fp 2 } apply_perspective all 0 } #----- OGL window controls set ProgData(axislist) [OGLaxis $ProgData(axis)] $OGLwin main -clear colorbuffer depthbuffer -call $ProgData(axislist) if {[info commands OGLcutplane] != ""} { OGLcutconfig $ProgData(cutcolor) $ProgData(usecutclr) $ProgData(ignorevis) set ProgData(cutlist) [OGLcutplane] set ProgData(planelist) [OGLdrawplane] } eval $OGLwin eval \ -clearcolor $ProgData(background) \ -$ProgData(culling) cullface \ -matrixmode projection \ -loadidentity \ -perspective $Perspective(fov) $Perspective(ar) \ $Perspective(np) $Perspective(fp) \ -matrixmode modelview \ -loadidentity \ -light light0 position 0 1 5 0 \ -light light0 diffuse .8 .8 .8 \ -light light0 specular 1 1 1 \ -light light0 ambient .2 .2 .2 \ -lightmodel lightmodeltwoside $ProgData(twosided) \ -enable lighting -enable light0 \ -enable depthtest -enable normalize -shademodel flat set ViewMatrix [$OGLwin get modelviewmatrix] bind $OGLwin {compute_viewport %W} bind $OGLwin {set xlast %x ; set ylast %y} bind $OGLwin {Rotate %W %x %y} bind $OGLwin {Pan %W %x %y} bind $OGLwin {Zoom %W %x %y} bind $OGLwin {Zoom %W %x %y} bind $OGLwin {Pan %W %x %y} catch {bind . {WheelZoom %D}} bind . {Center} bind . {reset_view ; $OGLwin redraw} bind . toggle_twosided bind . toggle_culling bind . toggle_axis if {[info commands OGLcutplane] != ""} { bind . cutplane_control bind . {if [winfo exists .cutplane] draw_cut} } proc compute_viewport {w} { global ProgData Perspective set ProgData(width) [winfo width $w] set ProgData(height) [winfo height $w] set ProgData(scale) [expr 1.0 / double($ProgData(height))] set Perspective(ar) [expr double($ProgData(width)) / \ double($ProgData(height))] $w eval \ -matrixmode projection \ -loadidentity \ -perspective $Perspective(fov) $Perspective(ar) \ $Perspective(np) $Perspective(fp) \ -matrixmode modelview } proc set_view {w} { global Viewpoint ViewMatrix eval $w eval \ -loadidentity \ -lookat $Viewpoint(x) $Viewpoint(y) $Viewpoint(z) \ $Viewpoint(x) $Viewpoint(y) 0 0 1 0 \ -multmatrix $ViewMatrix $w redraw } proc Rotate {w x y} { global xlast ylast ViewMatrix Viewpoint Perspective set scl [expr $Viewpoint(z) / $Perspective(fd)] if {[expr $scl > 1.0]} { set dx [expr $x - $xlast] set dy [expr $y - $ylast] } else { if {[expr $scl < 0.1]} {set scl 0.1} set dx [expr $scl * ($x - $xlast)] set dy [expr $scl * ($y - $ylast)] } set xlast $x set ylast $y eval $w eval \ -loadidentity \ -rotate $dy 1 0 0 \ -rotate $dx 0 1 0 \ -multmatrix $ViewMatrix set ViewMatrix [$w get modelviewmatrix] set_view $w } proc Pan {w x y} { global xlast ylast Viewpoint Perspective ProgData set scl [expr $Viewpoint(z) / $Perspective(fd)] if {[expr $scl > 1.0]} { set scl $ProgData(scale) } else { if {[expr $scl < 0.1]} {set scl 0.1} set scl [expr $scl * $ProgData(scale)] } set Viewpoint(x) [expr $scl * ($xlast - $x) + $Viewpoint(x)] set Viewpoint(y) [expr $scl * ($y - $ylast) + $Viewpoint(y)] set xlast $x set ylast $y set_view $w } proc Zoom {w x y} { global xlast ylast Viewpoint set scl [expr 0.01 * $Viewpoint(z)] if {[expr $scl < 0.001]} {set scl 0.001} set Viewpoint(z) [expr $scl * ($ylast - $y) + $Viewpoint(z)] if {[expr $Viewpoint(z) < 0.001]} { set Viewpoint(z) 0.001 } set xlast $x set ylast $y set_view $w } proc WheelZoom {d} { global Viewpoint OGLwin set scl [expr 0.001 * $Viewpoint(z)] if {[expr $scl < 0.0001]} {set scl 0.0001} set Viewpoint(z) [expr $scl * $d + $Viewpoint(z)] if {[expr $Viewpoint(z) < 0.001]} { set Viewpoint(z) 0.001 } set_view $OGLwin } proc reset_clipping {} { global ProgData Perspective OGLwin array set ProgData { np 0.025 fp 2.0 } set Perspective(np) [expr $Perspective(fd) * $ProgData(np)] set Perspective(fp) [expr $Perspective(fd) * $ProgData(fp)] compute_viewport $OGLwin } proc Center {} { global ProgData Viewpoint ViewMatrix Perspective OGLwin set bounds [CGNSbounds 0 $ViewMatrix] set b [lindex $bounds 0] set xt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set xd [expr double([lindex $b 1]) - double([lindex $b 0])] set b [lindex $bounds 1] set yt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set yd [expr double([lindex $b 1]) - double([lindex $b 0])] set b [lindex $bounds 2] set zt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set zd [expr double([lindex $b 1]) - double([lindex $b 0])] set dd [expr $xd * $xd + $yd * $yd + $zd * $zd] if {[expr $dd < 1.0e-15]} { set scl 1.0 } else { set scl [expr 1.0 / sqrt($dd)] } # reset_clipping eval $OGLwin eval \ -matrixmode modelview \ -loadidentity \ -scale $scl $scl $scl \ -translate $xt $yt $zt \ -multmatrix $ViewMatrix set ViewMatrix [$OGLwin get modelviewmatrix] set Viewpoint(x) 0 set Viewpoint(y) 0 set Viewpoint(z) $Perspective(fd) set_view $OGLwin } proc reset_view {} { global ProgData Viewpoint ViewMatrix Perspective OGLwin set bounds [CGNSbounds 0] set b [lindex $bounds 0] set xt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set xd [expr double([lindex $b 1]) - double([lindex $b 0])] set b [lindex $bounds 1] set yt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set yd [expr double([lindex $b 1]) - double([lindex $b 0])] set b [lindex $bounds 2] set zt [expr -0.5 * ([lindex $b 1] + [lindex $b 0])] set zd [expr double([lindex $b 1]) - double([lindex $b 0])] set dd [expr $xd * $xd + $yd * $yd + $zd * $zd] if {[expr $dd < 1.0e-15]} { set scl 1.0 } else { set scl [expr 1.0 / sqrt($dd)] } set Viewpoint(x) 0 set Viewpoint(y) 0 set Viewpoint(z) $Perspective(fd) reset_clipping $OGLwin eval \ -matrixmode modelview \ -loadidentity \ -scale $scl $scl $scl \ -translate $xt $yt $zt set ViewMatrix [$OGLwin get modelviewmatrix] eval $OGLwin eval \ -loadidentity \ -lookat $Viewpoint(x) $Viewpoint(y) $Viewpoint(z) \ $Viewpoint(x) $Viewpoint(y) 0 0 1 0 \ -multmatrix $ViewMatrix } proc init_data {} { global ProgData set ProgData(/,dim) 0 set ProgData(/,mode) 0 set ProgData(/,vis) 1 set ProgData(/,clr) "" set ProgData(/,msg) [CGNSsummary] set nz 0 foreach z $ProgData(zones) { set clr [OGLcolor $nz] set zone /$z set ProgData($zone,dim) 0 set ProgData($zone,vis) 1 set ProgData($zone,mode) 0 set ProgData($zone,clr) $clr set ProgData($zone,msg) [CGNSsummary $nz] set subdirs {} set nr 0 foreach r $ProgData($nz,regions) { set reg $zone/$r if [catch {CGNSregiondim $nz $nr} dim] { set msg $dim set dim 0 } else { set msg "" } if {$dim < 1} { set ProgData($reg,dim) 0 set ProgData($reg,vis) 0 set ProgData($reg,mode) 0 set ProgData($reg,clr) "" if {$msg == ""} { set ProgData($reg,msg) "couldn't process for exterior faces" } else { set ProgData($reg,msg) $msg } } else { set ProgData($reg,dim) $dim if {$nr == 0 || $dim == 3} { set ProgData($reg,vis) $ProgData(meshvis) set ProgData($reg,mode) $ProgData(meshmode) } else { set ProgData($reg,vis) $ProgData(regvis) set ProgData($reg,mode) $ProgData(regmode) } if {$ProgData(autocolor)} { set clr [OGLcolor [expr $nz + $nr]] } set ProgData($reg,clr) $clr set ProgData($reg,msg) [CGNSsummary $nz $nr] } set dir [file dirname $r] if {$dir != "" && $dir != "."} { if {[lsearch $subdirs $dir] < 0} { lappend subdirs $dir set ProgData($zone/$dir,dim) $ProgData($reg,dim) set ProgData($zone/$dir,vis) 1 set ProgData($zone/$dir,mode) $ProgData($reg,mode) set ProgData($zone/$dir,clr) $clr set ProgData($zone/$dir,msg) "" } else { if {$ProgData($zone/$dir,dim) < $ProgData($reg,dim)} { set ProgData($zone/$dir,dim) $ProgData($reg,dim) } if {$ProgData($zone/$dir,mode) != $ProgData($reg,mode)} { set ProgData($zone/$dir,mode) 0 } } } if {$nr == 0} { set ProgData($zone,dim) $ProgData($reg,dim) set ProgData($zone,mode) $ProgData($reg,mode) } else { if {$ProgData($zone,dim) < $ProgData($reg,dim)} { set ProgData($zone,dim) $ProgData($reg,dim) } if {$ProgData($zone,mode) != $ProgData($reg,mode)} { set ProgData($zone,mode) 0 } } incr nr } if {$nz == 0} { set ProgData(/,dim) $ProgData($zone,dim) set ProgData(/,mode) $ProgData($zone,mode) } else { if {$ProgData(/,dim) < $ProgData($zone,dim)} { set ProgData(/,dim) $ProgData($zone,dim) } if {$ProgData(/,mode) != $ProgData($zone,mode)} { set ProgData(/,mode) 0 } } incr nz } } proc init_display {} { global ProgData OGLwin if {$ProgData(displaylist) != ""} { $OGLwin deletelist $ProgData(displaylist) } if {$ProgData(nzones) < 1} { set ProgData(displaylist) "" $OGLwin main -clear colorbuffer depthbuffer -call $ProgData(axislist) } else { set calllist {} set nz 0 foreach z $ProgData(zones) { set nr 0 foreach r $ProgData($nz,regions) { if {$ProgData(/$z/$r,dim)} { set clr $ProgData(/$z/$r,clr) if {$ProgData(/$z/$r,vis)} { set dl [OGLregion $nz $nr $ProgData(/$z/$r,mode) $clr] } else { set dl [OGLregion $nz $nr 0 $clr] } lappend calllist -call $dl } incr nr } incr nz } if {$ProgData(cutlist) != ""} { lappend calllist -call $ProgData(cutlist) } if {$ProgData(planelist) != ""} { lappend calllist -call $ProgData(planelist) } set ProgData(displaylist) [eval $OGLwin newlist $calllist] $OGLwin main -clear colorbuffer depthbuffer \ -call $ProgData(axislist) -call $ProgData(displaylist) } OGLaxis $ProgData(axis) } proc cleanup_display {} { global ProgData OGLwin display_message "" if {$ProgData(cgnsfile) == ""} return catch CGNSclose close_cutplane if {$ProgData(displaylist) != ""} { $OGLwin deletelist $ProgData(displaylist) set ProgData(displaylist) "" } $OGLwin main -clear colorbuffer depthbuffer -call $ProgData(axislist) TreeDelete $ProgData(tree) / array set ProgData { bases {} nzones 0 zones {} curnode "" curdim 0 curclr "" curmode 0 } OGLaxis $ProgData(axis) $OGLwin redraw } #---------- set base proc build_tree {} { global ProgData set_node "" TreeDelete $ProgData(tree) / TreeInsert $ProgData(tree) / -text $ProgData(curbase) set nz 0 foreach z $ProgData(zones) { set zone /$z if {$ProgData($zone,dim) == 0} { set icon box_question set clr "" } else { if {$ProgData($zone,vis)} { set icon box_checked } else { set icon box_empty } if {$ProgData(showcolors)} { set clr [color_value $ProgData($zone,clr)] } else { set clr "" } } TreeInsert $ProgData(tree) $zone -tag $nz -icon $icon -iconbg $clr set nr 0 foreach r $ProgData($nz,regions) { set dir [file dirname $r] if {$dir != "" && $dir != "." && ![TreeExists $ProgData(tree) $zone/$dir]} { if {$ProgData($zone/$dir,dim) == 0} { set icon box_question set clr "" } else { if {$ProgData($zone/$dir,vis)} { set icon box_checked } else { set icon box_empty } if {$ProgData(showcolors)} { set clr [color_value $ProgData($zone/$dir,clr)] } else { set clr "" } } TreeInsert $ProgData(tree) $zone/$dir -icon $icon -iconbg $clr } set reg $zone/$r if {$ProgData($reg,dim) == 0} { set icon box_question set clr "" } else { if {$ProgData($reg,vis)} { set icon box_checked } else { set icon box_empty } if {$ProgData(showcolors)} { set clr [color_value $ProgData($reg,clr)] } else { set clr "" } } TreeInsert $ProgData(tree) $reg -tag "$nz $nr" -icon $icon -iconbg $clr incr nr } incr nz } } proc set_base {w nb} { global ProgData display_message "reading zone information..." if {[catch {CGNSbase $nb} zones]} { display_message $zones errormsg $zones return "" } set ProgData(zones) $zones set ProgData(nzones) [llength $zones] . configure -cursor watch update for {set nz 0} {$nz < $ProgData(nzones)} {incr nz} { display_message "reading zone [expr $nz + 1]..." if {[catch {CGNSzone $nz} regs]} { errormsg $regs set regs "" } set ProgData($nz,regions) $regs } set ProgData(curbase) [lindex $ProgData(bases) $nb] init_data display_message "building display lists..." init_display reset_view build_tree if [winfo exists .cutplane] { OGLcutplane 0 center_cutplane } . configure -cursor {} display_message "" return "" } proc show_info {w x y node} { global ProgData Font if {$node == ""} return if {$node == "/"} { catch CGNSgetbase msg } else { set tag [TreeGet $w $node -tag] if {[llength $tag] == 1} { catch {CGNSgetzone $tag} msg } elseif {[llength $tag] == 2} { catch {CGNSgetregion [lindex $tag 0] [lindex $tag 1]} msg } else { set msg "" } } if {$msg != ""} { incr x [winfo rootx $w] incr y [winfo rooty $w] popup_message $msg -parent $w -position "$x $y" \ -font $Font(fixed) -wrap 0 } } proc set_node {node} { global ProgData TreeSelectionSet $ProgData(tree) $node set ProgData(curnode) $node if {$node == "" || ![info exists ProgData($node,dim)]} { set ProgData(curdim) 0 set ProgData(curmode) 0 set ProgData(curclr) "" set msg "" } else { set ProgData(curdim) $ProgData($node,dim) set ProgData(curmode) $ProgData($node,mode) set ProgData(curclr) $ProgData($node,clr) set msg $ProgData($node,msg) } color_button $ProgData(clrbut) $ProgData(curclr) options_state $ProgData(curdim) display_message $msg } proc set_visibility {node vis all} { global ProgData if {$ProgData($node,dim) == 0} return if {$vis} { set ProgData($node,vis) 1 TreeSet $ProgData(tree) $node -icon box_checked } else { set ProgData($node,vis) 0 TreeSet $ProgData(tree) $node -icon box_empty } if {$all} { foreach c [TreeGet $ProgData(tree) $node -children] { set_visibility $node/$c $vis 1 } } } proc toggle_visibility {node {all 0}} { global ProgData if {$node == "" || ![info exists ProgData($node,dim)] || $ProgData($node,dim) == 0} return if {$ProgData($node,vis)} { set vis 0 } else { set vis 1 } set_visibility $node $vis $all update_node $node if {$vis && $node != [TreeSelectionGet $ProgData(tree)]} { set_node $node } } proc node_visible {node} { global ProgData if {$ProgData($node,vis) == 0} {return 0} set node [file dirname $node] while {$node != "" && $node != "." && $node != "/"} { if {$ProgData($node,vis) == 0} {return 0} set node [file dirname $node] } return 1 } proc update_children {node mode clr} { global ProgData if {$mode != ""} { set ProgData($node,mode) $mode } if {$clr != ""} { if {[llength $clr] == 1} { set ProgData($node,clr) [OGLcolor $clr] } else { set ProgData($node,clr) $clr } if {$ProgData(showcolors)} { TreeSet $ProgData(tree) $node -iconbg [color_value $ProgData($node,clr)] } } set children [TreeGet $ProgData(tree) $node -children] if {[llength $children] > 0} { if {$node == "/"} {set node ""} foreach c $children { update_children $node/$c $mode $clr if {[llength $clr] == 1} {incr clr} } } else { set tag [TreeGet $ProgData(tree) $node -tag] if {[llength $tag] == 2} { if [node_visible $node] { set mode $ProgData($node,mode) } else { set mode 0 } OGLregion [lindex $tag 0] [lindex $tag 1] $mode $ProgData($node,clr) } } } proc update_node {node {mode ""} {clr ""}} { global ProgData OGLwin if {$node == "" || $ProgData($node,dim) == 0} return update_children $node $mode $clr OGLaxis $ProgData(axis) $OGLwin redraw } proc parent_mode {node} { global ProgData if {$node == "" || $node == "."} return set mode "" set par $node if {$par == "/"} {set par ""} foreach c [TreeGet $ProgData(tree) $node -children] { if {$mode == ""} { set mode $ProgData($par/$c,mode) } else { if {$mode != $ProgData($par/$c,mode)} { set mode 0 break } } } if {$mode == ""} return set ProgData($node,mode) $mode if {$node != "/"} { parent_mode [file dirname $node] } } proc update_mode {} { global ProgData set node $ProgData(curnode) if {$node == "" || $ProgData($node,dim) == 0} return update_node $node $ProgData(curmode) if {$node != "/"} { parent_mode [file dirname $node] } } proc update_color {w} { global ProgData set node $ProgData(curnode) if {$node == "" || $ProgData($node,dim) == 0} return set newclr [select_color $ProgData(curclr) "Set Color" $w] if {$newclr != ""} { set ProgData(curclr) $newclr color_button $ProgData(clrbut) $newclr update_node $node "" $newclr } } proc auto_color {w} { global ProgData set node $ProgData(curnode) if {$node == "" || $ProgData($node,dim) == 0} return set clr [expr [llength [split $node /]] - 2] set newclr [OGLcolor $clr] set ProgData(curclr) $newclr color_button $ProgData(clrbut) $newclr update_node $node "" $clr } #---------- cutting plane proc normalize_cutplane {} { global ProgData set r 0.0 foreach i {x y z} { set r [expr $r + $ProgData(cut$i) * $ProgData(cut$i)] } if [expr $r == 0.0] { set r 1.0 } else { set r [expr sqrt($r)] } foreach i {x y z} { set ProgData(cut$i) [expr $ProgData(cut$i) / $r] } } proc reset_cutplane {} { global ProgData set bounds [CGNSbounds 0] array set ProgData { rotx 0 roty 0 rotz 0 lastx 0 lasty 0 lastz 0 } set n 0 set dist 0.0 set diag 0.0 foreach i {x y z} { set b [lindex $bounds $n] set r [expr [lindex $b 1] - [lindex $b 0]] set diag [expr $diag + $r * $r] set r [expr 0.5 * ([lindex $b 0] + [lindex $b 1])] set dist [expr $dist + $r * $ProgData(cut$i)] incr n } set ProgData(translate) [expr ($ProgData(cutd) - $dist) / sqrt($diag)] } proc draw_cut {{recompute 1}} { global ProgData OGLwin set ProgData(cutplane) \ [list $ProgData(cutx) $ProgData(cuty) $ProgData(cutz) $ProgData(cutd)] if {$recompute} { OGLcutplane $ProgData(cutmode) $ProgData(cutplane) } else { OGLcutplane $ProgData(cutmode) } if {$ProgData(cutmode)} OGLdrawplane $OGLwin redraw reset_cutplane } proc draw_cutplane {} { global ProgData OGLwin if {$ProgData(drawID) == ""} { set ProgData(drawID) [after idle draw_cutplane] return } set ProgData(drawID) "" set plane {} foreach i {x y z d} { if [catch {expr double($ProgData(cut$i))} val] return lappend plane $val } if [catch {OGLdrawplane $plane} msg] { OGLdrawplane } else { set msg "" } $OGLwin redraw display_message $msg } proc update_cutplane {data var op} { global ProgData if {$ProgData(dotrace)} draw_cutplane } proc center_cutplane {} { global ProgData OGLwin set ProgData(dotrace) 0 normalize_cutplane set bounds [CGNSbounds 0] set d 0.0 set n 0 foreach i {x y z} { set b [lindex $bounds $n] set r [expr 0.5 * ([lindex $b 0] + [lindex $b 1])] set d [expr $d + $r * $ProgData(cut$i)] incr n } set ProgData(cutd) [format "%g" $d] set ProgData(translate) 0 draw_cutplane set ProgData(dotrace) 1 } proc set_cutplane {dir} { global ProgData OGLwin set ProgData(dotrace) 0 set bounds [CGNSbounds 0] if {$dir == "x"} { array set ProgData { cutx 1 cuty 0 cutz 0 } set b [lindex $bounds 0] } elseif {$dir == "y"} { array set ProgData { cutx 0 cuty 1 cutz 0 } set b [lindex $bounds 1] } else { array set ProgData { cutx 0 cuty 0 cutz 1 } set b [lindex $bounds 2] } set ProgData(cutd) [format "%g" \ [expr 0.5 * ([lindex $b 0] + [lindex $b 1])]] draw_cutplane reset_cutplane set ProgData(dotrace) 1 } proc rotate_cutplane {axis amt} { global ProgData set ProgData(dotrace) 0 normalize_cutplane set bounds [CGNSbounds 0] set n 0 set d $ProgData(cutd) foreach i {x y z} { set b [lindex $bounds $n] set p$i [expr 0.5 * ([lindex $b 0] + [lindex $b 1])] set d [expr $d - [set p$i] * $ProgData(cut$i)] incr n } foreach i {x y z} { set r$i [expr [set p$i] + $d * $ProgData(cut$i)] } set ca [expr cos(0.0174533 * ($amt - $ProgData(last$axis)))] set sa [expr sin(0.0174533 * ($amt - $ProgData(last$axis)))] set ProgData(last$axis) $amt set x $ProgData(cutx) set y $ProgData(cuty) set z $ProgData(cutz) if {$axis == "x"} { set ProgData(cuty) [format "%g" [expr $ca * $y - $sa * $z]] set ProgData(cutz) [format "%g" [expr $ca * $z + $sa * $y]] } elseif {$axis == "y"} { set ProgData(cutx) [format "%g" [expr $ca * $x + $sa * $z]] set ProgData(cutz) [format "%g" [expr $ca * $z - $sa * $x]] } else { set ProgData(cutx) [format "%g" [expr $ca * $x - $sa * $y]] set ProgData(cuty) [format "%g" [expr $ca * $y + $sa * $x]] } set d 0.0 foreach i {x y z} { set d [expr $d + $ProgData(cut$i) * [set r$i]] } set ProgData(cutd) [format "%g" $d] draw_cutplane set ProgData(dotrace) 1 } proc translate_cutplane {amt} { global ProgData set ProgData(dotrace) 0 normalize_cutplane set bounds [CGNSbounds 0] set n 0 set dist 0.0 set diag 0.0 foreach i {x y z} { set b [lindex $bounds $n] set r [expr [lindex $b 1] - [lindex $b 0]] set diag [expr $diag + $r * $r] set r [expr 0.5 * ([lindex $b 0] + [lindex $b 1])] set dist [expr $dist + $r * $ProgData(cut$i)] incr n } set ProgData(cutd) [format "%g" [expr $dist + $amt * sqrt($diag)]] draw_cutplane set ProgData(dotrace) 1 } proc cutplane_color {but {trans ""}} { global ProgData if {$trans == ""} { set clr [select_color [lrange $ProgData(cutcolor) 0 2] "Select Color" $but] if {$clr == ""} return set trans [lindex $ProgData(cutcolor) 3] set ProgData(cutcolor) $clr lappend ProgData(cutcolor) $trans color_button $but $clr } else { set ProgData(cutcolor) [lreplace $ProgData(cutcolor) 3 3 $trans] } OGLcutconfig $ProgData(cutcolor) draw_cutplane } proc cutplane_config {recompute} { global ProgData OGLcutconfig $ProgData(cutcolor) $ProgData(usecutclr) $ProgData(ignorevis) draw_cut $recompute } proc cutplane_defaults {but} { global ProgData set ProgData(cutcolor) {0.7 0.7 0.4 0.5} set ProgData(transparency) 0.5 color_button $but $ProgData(cutcolor) set ProgData(cutmode) 1 set ProgData(usecutclr) 0 set ProgData(ignorevis) 0 OGLcutconfig $ProgData(cutcolor) 0 0 set_cutplane x } proc cutplane_control {} { global ProgData Font set w .cutplane if [winfo exists $w] { wm deiconify $w raise $w focus $w return } if {$ProgData(cutplane) == ""} { array set ProgData { cutx 1 cuty 0 cutz 0 } } else { set ProgData(cutx) [lindex $ProgData(cutplane) 0] set ProgData(cuty) [lindex $ProgData(cutplane) 1] set ProgData(cutz) [lindex $ProgData(cutplane) 2] } set ProgData(transparency) [lindex $ProgData(cutcolor) 3] toplevel $w wm title $w "Cutting Plane" wm protocol $w WM_DELETE_WINDOW close_cutplane FrameCreate $w.clr -text "Color" -font $Font(bold) -padx 0 -pady 0 pack $w.clr -side top -padx 5 -pady 2 -fill x -expand 1 set clr [FrameGet $w.clr] label $clr.lab -text Transparency pack $clr.lab -side left scale $clr.scl -length 50 -from 0 -to 1 -resolution 0.01 \ -orient horizontal -label "" -showvalue 0 -width 12 \ -highlightthickness 0 -variable ProgData(transparency) \ -command "cutplane_color $clr.but" pack $clr.scl -side left -fill x -expand 1 button $clr.but -text Select -relief solid -bd 1 \ -command "cutplane_color $clr.but" pack $clr.but -side right color_button $clr.but $ProgData(cutcolor) FrameCreate $w.pos -text "Cut Plane" -font $Font(bold) -padx 0 -pady 0 pack $w.pos -side top -padx 5 -pady 2 -fill x -expand 1 set pos [FrameGet $w.pos] foreach r {X Y Z} { set i [string tolower $r] set f [frame $pos.d$i] pack $f -side top -fill x label $f.lab -text "$r Direction" -width 10 -anchor w pack $f.lab -side left entry $f.ent -width 10 -textvariable ProgData(cut$i) pack $f.ent -side left -fill x -expand 1 -padx 2 button $f.but -text "$r Cut" -width 6 -command "set_cutplane $i" pack $f.but -side right set f [frame $pos.r$i] pack $f -side top -fill x label $f.lab -width 10 -text "$r Rotate" -anchor e pack $f.lab -side left scale $f.scl -length 50 -from -90 -to 90 -resolution 1 \ -orient horizontal -label "" -showvalue 0 -width 12 \ -highlightthickness 0 -variable ProgData(rot$i) \ -command "rotate_cutplane $i" pack $f.scl -side left -fill x -expand 1 } set f [frame $pos.dd] pack $f -side top -fill x label $f.lab -text "Offset" -width 10 -anchor w pack $f.lab -side left entry $f.ent -width 10 -textvariable ProgData(cutd) pack $f.ent -side left -fill x -expand 1 -padx 2 button $f.but -text Center -width 6 -command center_cutplane pack $f.but -side right set f [frame $pos.rd] pack $f -side top -fill x label $f.lab -width 10 -text "Translate" -anchor e pack $f.lab -side left scale $f.scl -length 50 -from -.5 -to 0.5 -resolution 0.001 \ -orient horizontal -label "" -showvalue 0 -width 12 \ -highlightthickness 0 -variable ProgData(translate) \ -command translate_cutplane pack $f.scl -side left -fill x -expand 1 FrameCreate $w.mode -text "Display" -font $Font(bold) -padx 0 -pady 0 pack $w.mode -side top -padx 5 -pady 2 -fill x -expand 1 set mode [FrameGet $w.mode] set f [frame $mode.d] pack $f -side top -fill x set n 0 foreach i {Off Planar Elements Shaded} { radiobutton $f.f$n -text $i -variable ProgData(cutmode) \ -value $n -command {draw_cut 0} pack $f.f$n -side left -expand 1 incr n } set f [frame $mode.b] pack $f -side top -fill x checkbutton $f.cc -text "Use Cutplane Color" \ -variable ProgData(usecutclr) -onvalue 1 -offvalue 0 \ -command {cutplane_config 0} checkbutton $f.iv -text "Ignore Region Visibility" \ -variable ProgData(ignorevis) -onvalue 1 -offvalue 0 \ -command {cutplane_config 1} pack $f.cc $f.iv -side left -expand 1 frame $w.but pack $w.but -side top -fill x -padx 5 -expand 1 button $w.but.r -text Compute -width 8 -default active \ -command draw_cut button $w.but.d -text Defaults -width 8 \ -command "cutplane_defaults $clr.but" button $w.but.c -text Close -width 8 -command close_cutplane pack $w.but.r $w.but.d $w.but.c -side left -expand 1 bind $w draw_cut center_cutplane reset_cutplane foreach i {x y z d} { trace variable ProgData(cut$i) w update_cutplane } set ProgData(dotrace) 1 } proc close_cutplane {} { global ProgData OGLwin if {[winfo exists .cutplane]} { set ProgData(dotrace) 1 foreach i {x y z d} { trace vdelete ProgData(cut$i) w update_cutplane } OGLcutplane 0 OGLdrawplane $OGLwin redraw destroy .cutplane } } #---------- set variable for plotting proc set_variable {w n} { global ProgData return "" } #---------- read cgns file set FileList { {{CGNS Files} {.cgns .cga .cgh .cgx}} {{All Files} {*}} } proc load_cgns {{filename ""}} { global ProgData FileList ModelData global Translate Scale if {$filename == ""} { set filename [FileOpen "Open CGNS File" \ $ProgData(cgnsfile) . $FileList] } if {$filename == ""} return cleanup_display display_message "reading base information..." . configure -cursor watch update set msg "" if {[catch {CGNSopen $filename} bases]} { set msg $bases } else { set msg "" } . configure -cursor {} if {$msg != ""} { display_message $msg errormsg $msg return } set ProgData(bases) $bases ComboboxConfig $ProgData(baselist) -values $bases -index 0 -state normal if {[llength $bases] < 2} { ComboboxConfig $ProgData(baselist) -state disabled } set_base $ProgData(baselist) 0 wm title . "CGNSplot : [file tail $filename]" set ProgData(cgnsfile) $filename } catch { config_icon . [list cgnsplot cgns] \ [list $cmd_dir $cmd_dir/images $cmd_dir/../common] } wm deiconify . if {$argc} { set file [lindex $argv [expr $argc - 1]] if {[string index $file 0] != "-" && [file exists $file]} { load_cgns $file } } CGNS-3.4.0/src/cgnstools/cgnsplot/cgnstcl.c000066400000000000000000005363441343724673500205410ustar00rootroot00000000000000#include #include #include #include #include #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include #include "tk.h" #include "cgnslib.h" #include "hash.h" /* define this to exclude structured mesh boundaries */ /* imin, imax, jmin, jmax, kmin, kmax */ /*#define NO_MESH_BOUNDARIES*/ /* define this to disable a cutting plane */ /* the cutting plane requires more memory since all nodes and elements are saved */ /*#define NO_CUTTING_PLANE*/ /* this is the cosine of the angle between faces to define an interior edge */ /* it's set to 60 degrees - comment to remove interior edges */ #define EDGE_ANGLE 0.5 typedef float Node[3]; typedef struct { cgsize_t id; cgsize_t nodes[2]; } Edge; typedef struct { cgsize_t id; int flags; int nnodes; cgsize_t *nodes; float normal[3]; } Face; typedef struct { Face *face; cgsize_t num; int flags; } PolyFace; #ifndef NO_CUTTING_PLANE typedef struct { int id; cgsize_t nodes[3]; float ratio; } CutNode; typedef struct { cgsize_t nelems; cgsize_t *elems; cgsize_t nedges; Edge *edges; } CutData; typedef struct { float plane[4]; cgsize_t nelems; cgsize_t nedges; cgsize_t nnodes; Node *nodes; } CutPlane; static float cutcolor[4] = {(float)0.8, (float)0.4, (float)0.8, (float)0.5}; static int usecutclr = 0; static int ignorevis = 0; static CutPlane cutplane; static int CutDL = 0; static int PlaneDL = 0; #endif typedef struct { char name[33]; int type; int dim; cgsize_t data[10]; char d_name[33]; cgsize_t nedges; Edge *edges; cgsize_t nfaces; Face **faces; #ifndef NO_CUTTING_PLANE CGNS_ENUMT(ElementType_t) elemtype; cgsize_t nelems; cgsize_t *elems; cgsize_t *elem_offsets; int npoly; Face **poly; CutData cut; #endif float bbox[3][2]; int dlist; int mode; float color[4]; char errmsg[81]; } Regn; typedef struct { char name[33]; cgsize_t nnodes; Node *nodes; int nregs; Regn *regs; } Zone; static int cgnsfn = 0; static int cgnsbase = 0; static int cgnszone = 0; static int nbases = 0; static int nzones = 0; static Zone *zones; static int AxisDL = 0; static char BaseName[33]; static int CellDim, PhyDim; static Tcl_Interp *global_interp; enum { REG_MESH, REG_ELEM, REG_1TO1, REG_CONN, REG_HOLE, REG_BOCO, REG_BNDS }; /* mapping from elements to faces */ static int facenodes[22][5] = { /* tri */ {3, 0, 1, 2, 0}, /* quad */ {4, 0, 1, 2, 3}, /* tet */ {3, 0, 2, 1, 0}, {3, 0, 1, 3, 0}, {3, 1, 2, 3, 0}, {3, 2, 0, 3, 0}, /* pyramid */ {4, 0, 3, 2, 1}, {3, 0, 1, 4, 0}, {3, 1, 2, 4, 0}, {3, 2, 3, 4, 0}, {3, 3, 0, 4, 0}, /* wedge */ {4, 0, 1, 4, 3}, {4, 1, 2, 5, 4}, {4, 2, 0, 3, 5}, {3, 0, 2, 1, 0}, {3, 3, 4, 5, 0}, /* hex */ {4, 0, 3, 2, 1}, {4, 0, 1, 5, 4}, {4, 1, 2, 6, 5}, {4, 2, 3, 7, 6}, {4, 0, 4, 7, 3}, {4, 4, 5, 6, 7} }; /*=================================================================== * local routines *===================================================================*/ /*-------------------------------------------------------------------*/ static void FATAL (char *errmsg) { char cmd[129]; sprintf (cmd, "error_exit {%s}", errmsg); Tcl_Eval (global_interp, cmd); exit (1); } /*-------------------------------------------------------------------*/ static void *MALLOC (char *funcname, size_t bytes) { void *data = calloc (bytes, 1); if (NULL == data) { char msg[128]; if (funcname != NULL) sprintf (msg, "%s:malloc failed for %lu bytes", funcname, (unsigned long)bytes); else sprintf (msg, "malloc failed for %lu bytes", (unsigned long)bytes); FATAL (msg); } return data; } /*-------------------------------------------------------------------*/ static void *REALLOC (char *funcname, size_t bytes, void *old_data) { void *new_data; if (NULL == old_data) return MALLOC (funcname, bytes); new_data = realloc (old_data, bytes); if (NULL == new_data) { char msg[128]; if (funcname != NULL) sprintf (msg, "%s:realloc failed for %lu bytes", funcname, (unsigned long)bytes); else sprintf (msg, "realloc failed for %lu bytes", (unsigned long)bytes); FATAL (msg); } return new_data; } /*-------------------------------------------------------------------*/ static Face *new_face(char *funcname, int nnodes) { Face *f = (Face *) calloc (nnodes * sizeof(cgsize_t) + sizeof(Face), 1); if (f == NULL) { char msg[128]; if (funcname != NULL) sprintf (msg, "%s:malloc failed for face with %d nodes", funcname, nnodes); else sprintf (msg, "malloc failed for face with %d nodes", nnodes); FATAL (msg); } f->nnodes = nnodes; f->nodes = (cgsize_t *)(f + 1); return f; } /*-------------------------------------------------------------------*/ static Face *copy_face(char *funcname, Face *face) { int n; Face *f = new_face(funcname, face->nnodes); f->id = face->id; f->flags = face->flags; for (n = 0; n < face->nnodes; n++) f->nodes[n] = face->nodes[n]; for (n = 0; n < 3; n++) f->normal[n] = face->normal[n]; return f; } /*-------------------------------------------------------------------*/ static void zone_message (char *msg, char *name) { char cmd[129]; if (name != NULL) sprintf (cmd, "display_message {Zone %d : %s %s...}", cgnszone, msg, name); else sprintf (cmd, "display_message {Zone %d : %s...}", cgnszone, msg); Tcl_Eval (global_interp, cmd); } /*-------------------------------------------------------------------*/ static void free_all (void) { int nz, nr, nf; if (!nzones) return; for (nz = 0; nz < nzones; nz++) { for (nr = 0; nr < zones[nz].nregs; nr++) { if (zones[nz].regs[nr].dlist) glDeleteLists (zones[nz].regs[nr].dlist, 1); if (zones[nz].regs[nr].nedges) free (zones[nz].regs[nr].edges); if (zones[nz].regs[nr].nfaces) { for (nf = 0; nf < zones[nz].regs[nr].nfaces; nf++) { if (zones[nz].regs[nr].faces[nf]) free (zones[nz].regs[nr].faces[nf]); } free (zones[nz].regs[nr].faces); } #ifndef NO_CUTTING_PLANE if (zones[nz].regs[nr].nelems) free (zones[nz].regs[nr].elems); if (zones[nz].regs[nr].nelems && zones[nz].regs[nr].elem_offsets) free (zones[nz].regs[nr].elem_offsets); if (zones[nz].regs[nr].npoly) free (zones[nz].regs[nr].poly); if (zones[nz].regs[nr].cut.nelems) free (zones[nz].regs[nr].cut.elems); if (zones[nz].regs[nr].cut.nedges) free (zones[nz].regs[nr].cut.edges); #endif } if (zones[nz].nregs) free (zones[nz].regs); if (zones[nz].nnodes) free(zones[nz].nodes); } free (zones); nzones = 0; #ifndef NO_CUTTING_PLANE if (cutplane.nnodes) free (cutplane.nodes); cutplane.nelems = 0; cutplane.nedges = 0; cutplane.nnodes = 0; #endif } /*-------------------------------------------------------------------*/ static int compare_ints (const void *v1, const void *v2) { return (int)(*((cgsize_t *)v1) - *((cgsize_t *)v2)); } /*-------------------------------------------------------------------*/ static int find_int (cgsize_t value, cgsize_t nlist, cgsize_t *list) { cgsize_t lo = 0, hi = nlist - 1, mid; if (!nlist || value < list[0]) return 0; if (value == list[0]) return 1; if (!hi || value > list[hi]) return 0; if (value == list[hi]) return 1; while (lo <= hi) { mid = (lo + hi) >> 1; if (value == list[mid]) return 1; if (value < list[mid]) hi = mid - 1; else lo = mid + 1; } return 0; } /*==================================================================== * structured grid regions *====================================================================*/ #define NODE_INDEX(I,J,K) ((I)+dim[0]*((J)+dim[1]*(K))) /*-------------------------------------------------------------------*/ static int structured_range (Regn *reg, cgsize_t *dim, cgsize_t *ptrng, CGNS_ENUMT(GridLocation_t) location) { int n, i, j, nf; cgsize_t ii, jj, kk, nfaces, rng[3][2]; Face *f; static char *funcname = "structured_range"; if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(IFaceCenter) && location != CGNS_ENUMV(JFaceCenter) && location != CGNS_ENUMV(KFaceCenter)) { i = j = 0; for (n = 0; n < CellDim; n++) { if (ptrng[n] == ptrng[n+CellDim] && (ptrng[n] == 1 || ptrng[n] == dim[n])) { if (ptrng[n] == 1) i++; else if (j) { j = 4; break; } else j = n + 1; } } if (!j && i == 1) { for (n = 0; n < CellDim; n++) { if (ptrng[n] == ptrng[n+CellDim] && ptrng[n] == 1) { j = n + 1; break; } } } if (j == 1) location = CGNS_ENUMV(IFaceCenter); else if (j == 2) location = CGNS_ENUMV(JFaceCenter); else if (j == 3) location = CGNS_ENUMV(KFaceCenter); else { strcpy (reg->errmsg, "unable to determine boundary - use [IJK]FaceCenter"); return 0; } } nfaces = 1; if (location == CGNS_ENUMV(Vertex)) { for (n = 0, i = 0; i < CellDim; i++) { if (ptrng[i] < 1 || ptrng[i] > dim[i]) return 0; if (ptrng[i] == ptrng[i+CellDim]) { if (n || (ptrng[i] != 1 && ptrng[i] != dim[i])) return 0; n = i + 1; rng[i][0] = rng[i][1] = ptrng[i] - 1; } else { if (ptrng[i] < ptrng[i+CellDim]) { rng[i][0] = ptrng[i] - 1; rng[i][1] = ptrng[i+CellDim] - 1; } else { rng[i][0] = ptrng[i+CellDim] - 1; rng[i][1] = ptrng[i] - 1; } nfaces *= (rng[i][1] - rng[i][0]); } } } else { if (location == CGNS_ENUMV(IFaceCenter)) n = 0; else if (location == CGNS_ENUMV(JFaceCenter)) n = 1; else n = 2; for (i = 0; i < CellDim; i++) { if (i == n) { if (ptrng[i] != ptrng[i+CellDim] || (ptrng[i] != 1 && ptrng[i] != dim[i])) return 0; rng[i][0] = rng[i][1] = ptrng[i] - 1; } else { if (ptrng[i] < ptrng[i+CellDim]) { rng[i][0] = ptrng[i] - 1; rng[i][1] = ptrng[i+CellDim]; } else { rng[i][0] = ptrng[i+CellDim] - 1; rng[i][1] = ptrng[i]; } if (rng[i][0] < 0 || rng[i][1] >= dim[i]) return 0; nfaces *= (rng[i][1] - rng[i][0]); } } n++; } if (!nfaces || n < 1 || n > CellDim) { strcpy (reg->errmsg, "couldn't find any exterior faces"); return 0; } if (CellDim == 2) { reg->nedges = nfaces; reg->edges = (Edge *) MALLOC (funcname, (size_t)nfaces * sizeof(Edge)); nf = 0; kk = 0; if (n == 1) { ii = rng[0][0]; for (jj = rng[1][0]; jj < rng[1][1]; jj++) { reg->edges[nf].nodes[0] = NODE_INDEX(ii, jj, kk); reg->edges[nf].nodes[1] = NODE_INDEX(ii, jj+1, kk); nf++; } } else { jj = rng[1][0]; for (ii = rng[0][0]; ii < rng[0][1]; ii++) { reg->edges[nf].nodes[0] = NODE_INDEX(ii, jj, kk); reg->edges[nf].nodes[1] = NODE_INDEX(ii+1, jj, kk); nf++; } } return 1; } reg->nfaces = nfaces; reg->faces = (Face **) MALLOC (funcname, (size_t)nfaces * sizeof(Face *)); for (nf = 0; nf < nfaces; nf++) reg->faces[nf] = new_face (funcname, 4); nf = 0; if (n == 1) { if ((ii = rng[0][0]) == 0) { for (kk = rng[2][0]; kk < rng[2][1]; kk++) { for (jj = rng[1][0]; jj < rng[1][1]; jj++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii, jj, kk+1); f->nodes[2] = NODE_INDEX (ii, jj+1, kk+1); f->nodes[3] = NODE_INDEX (ii, jj+1, kk); } } } else { for (kk = rng[2][0]; kk < rng[2][1]; kk++) { for (jj = rng[1][0]; jj < rng[1][1]; jj++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii, jj+1, kk); f->nodes[2] = NODE_INDEX (ii, jj+1, kk+1); f->nodes[3] = NODE_INDEX (ii, jj, kk+1); } } } } else if (n == 2) { if ((jj = rng[1][0]) == 0) { for (kk = rng[2][0]; kk < rng[2][1]; kk++) { for (ii = rng[0][0]; ii < rng[0][1]; ii++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii+1, jj, kk); f->nodes[2] = NODE_INDEX (ii+1, jj, kk+1); f->nodes[3] = NODE_INDEX (ii, jj, kk+1); } } } else { for (kk = rng[2][0]; kk < rng[2][1]; kk++) { for (ii = rng[0][0]; ii < rng[0][1]; ii++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii, jj, kk+1); f->nodes[2] = NODE_INDEX (ii+1, jj, kk+1); f->nodes[3] = NODE_INDEX (ii+1, jj, kk); } } } } else { if ((kk = rng[2][0]) == 0) { for (jj = rng[1][0]; jj < rng[1][1]; jj++) { for (ii = rng[0][0]; ii < rng[0][1]; ii++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii, jj+1, kk); f->nodes[2] = NODE_INDEX (ii+1, jj+1, kk); f->nodes[3] = NODE_INDEX (ii+1, jj, kk); } } } else { for (jj = rng[1][0]; jj < rng[1][1]; jj++) { for (ii = rng[0][0]; ii < rng[0][1]; ii++) { f = reg->faces[nf++]; f->nodes[0] = NODE_INDEX (ii, jj, kk); f->nodes[1] = NODE_INDEX (ii+1, jj, kk); f->nodes[2] = NODE_INDEX (ii+1, jj+1, kk); f->nodes[3] = NODE_INDEX (ii, jj+1, kk); } } } } return 2; } /*-------------------------------------------------------------------*/ static int structured_list (Regn *mesh, Regn *reg, cgsize_t *dim, cgsize_t npts, cgsize_t *pts, CGNS_ENUMT(GridLocation_t) location) { cgsize_t n, nn, nf, nfaces = 0, noff, nmax; Face **faces, *f; static char *funcname = "structured_list"; if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(IFaceCenter) && location != CGNS_ENUMV(JFaceCenter) && location != CGNS_ENUMV(KFaceCenter)) { int i, j, k; cgsize_t rng[3][2]; for (i = 0; i < CellDim; i++) rng[i][0] = rng[i][1] = pts[i]; for (nf = 1; nf < npts; nf++) { nn = nf * CellDim; for (i = 0; i < CellDim; i++) { if (rng[i][0] > pts[nn+i]) rng[i][0] = pts[nn+i]; if (rng[i][1] < pts[nn+i]) rng[i][1] = pts[nn+i]; } } j = k = 0; for (i = 0; i < CellDim; i++) { if (rng[i][0] == rng[i][1] && (rng[i][0] == 1 || rng[i][0] == dim[i])) { if (rng[i][0] == 1) j++; else if (k) { k = 4; break; } else k = i + 1; } } if (!k && j == 1) { for (i = 0; i < CellDim; i++) { if (rng[i][0] == rng[i][1] && rng[i][0] == 1) { k = i + 1; break; } } } if (k == 1) location = CGNS_ENUMV(IFaceCenter); else if (k == 2) location = CGNS_ENUMV(JFaceCenter); else if (k == 3) location = CGNS_ENUMV(KFaceCenter); else { strcpy (reg->errmsg, "unable to determine boundary - use [IJK]FaceCenter"); return 0; } } nmax = npts; if (CellDim == 2) { cgsize_t ii, jj, n0, n1, ne; Edge *edges = (Edge *) MALLOC (funcname, (size_t)nmax * sizeof(Edge)); ne = 0; if (location == CGNS_ENUMV(Vertex)) { for (nn = 0, n = 0; n < npts; n++) { pts[n] = NODE_INDEX (pts[nn]-1, pts[nn+1]-1, 0); nn += 2; } for (n = 1; n < npts; n++) { if (pts[n] < pts[n-1]) { qsort (pts, (size_t)npts, sizeof(cgsize_t), compare_ints); break; } } ne = 0; jj = 0; for (ii = 1; ii < dim[0]; ii++) { n0 = NODE_INDEX(ii-1, jj, 0); n1 = NODE_INDEX(ii, jj, 0); if (find_int(n0, npts, pts) && find_int(n1, npts, pts)) { if (ne == nmax) { nmax += 100; edges = (Edge *) REALLOC (funcname, (size_t)nmax * sizeof(Edge), edges); } edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } } jj = dim[1] - 1; for (ii = 1; ii < dim[0]; ii++) { n0 = NODE_INDEX(ii-1, jj, 0); n1 = NODE_INDEX(ii, jj, 0); if (find_int(n0, npts, pts) && find_int(n1, npts, pts)) { if (ne == nmax) { nmax += 100; edges = (Edge *) REALLOC (funcname, (size_t)nmax * sizeof(Edge), edges); } edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } } ii = 0; for (jj = 1; jj < dim[1]; jj++) { n0 = NODE_INDEX(ii, jj-1, 0); n1 = NODE_INDEX(ii, jj, 0); if (find_int(n0, npts, pts) && find_int(n1, npts, pts)) { if (ne == nmax) { nmax += 100; edges = (Edge *) REALLOC (funcname, (size_t)nmax * sizeof(Edge), edges); } edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } } ii = dim[0] - 1; for (jj = 1; jj < dim[1]; jj++) { n0 = NODE_INDEX(ii, jj-1, 0); n1 = NODE_INDEX(ii, jj, 0); if (find_int(n0, npts, pts) && find_int(n1, npts, pts)) { if (ne == nmax) { nmax += 100; edges = (Edge *) REALLOC (funcname, (size_t)nmax * sizeof(Edge), edges); } edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } } } else if (location == CGNS_ENUMV(IFaceCenter)) { for (nn = 0, n = 0; n < npts; n++) { if ((pts[nn] == 1 || pts[nn] == dim[0]) && pts[nn+1] > 0 && pts[nn+1] < dim[1]) { ii = pts[nn] - 1; jj = pts[nn+1] - 1; n0 = NODE_INDEX(ii, jj, 0); n1 = NODE_INDEX(ii, jj+1, 0); edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } nn += 2; } } else if (location == CGNS_ENUMV(JFaceCenter)) { for (nn = 0, n = 0; n < npts; n++) { if ((pts[nn+1] == 1 || pts[nn+1] == dim[1]) && pts[nn] > 0 && pts[nn] < dim[0]) { ii = pts[nn] - 1; jj = pts[nn+1] - 1; n0 = NODE_INDEX(ii, jj, 0); n1 = NODE_INDEX(ii+1, jj, 0); edges[ne].nodes[0] = n0; edges[ne].nodes[1] = n1; ne++; } nn += 2; } } if (ne == 0) { free(edges); strcpy (reg->errmsg, "couldn't find any exterior edges"); return 0; } reg->nedges = ne; reg->edges = edges; return 1; } faces = (Face **) MALLOC (funcname, (size_t)nmax * sizeof(Face *)); if (location == CGNS_ENUMV(Vertex)) { for (nn = 0, n = 0; n < npts; n++) { pts[n] = NODE_INDEX (pts[nn]-1, pts[nn+1]-1, pts[nn+2]-1); nn += 3; } for (n = 1; n < npts; n++) { if (pts[n] < pts[n-1]) { qsort (pts, (size_t)npts, sizeof(cgsize_t), compare_ints); break; } } for (nf = 0; nf < mesh->nfaces; nf++) { f = mesh->faces[nf]; for (nn = 0; nn < f->nnodes; nn++) { if (!find_int (f->nodes[nn], npts, pts)) break; } if (nn == f->nnodes) { if (nfaces == nmax) { nmax += 100; faces = (Face **) REALLOC (funcname, (size_t)nmax * sizeof(Face *), faces); } faces[nfaces++] = copy_face (funcname, f); } } } else if (location == CGNS_ENUMV(IFaceCenter)) { for (n = 0; n < npts; n++) { nn = 3 * n; if ((pts[nn] == 1 || pts[nn] == dim[0]) && pts[nn+1] > 0 && pts[nn+1] < dim[1] && pts[nn+2] > 0 && pts[nn+2] < dim[2]) { nf = pts[nn+1]-1 + (pts[nn+2]-1) * (dim[1]-1); if (pts[nn] == dim[0]) nf += (dim[1]-1) * (dim[2]-1); faces[nfaces++] = copy_face (funcname, mesh->faces[nf]); } } } else if (location == CGNS_ENUMV(JFaceCenter)) { noff = 2 * (dim[1]-1) * (dim[2]-1); for (n = 0; n < npts; n++) { nn = 3 * n; if ((pts[nn+1] == 1 || pts[nn+1] == dim[1]) && pts[nn] > 0 && pts[nn] < dim[0] && pts[nn+2] > 0 && pts[nn+2] < dim[2]) { nf = noff + pts[nn]-1 + (pts[nn+2]-1) * (dim[0]-1); if (pts[nn+1] == dim[1]) nf += (dim[0]-1) * (dim[2]-1); faces[nfaces++] = copy_face (funcname, mesh->faces[nf]); } } } else { noff = 2 * ((dim[1]-1) * (dim[2]-1) + (dim[0]-1) * (dim[2]-1)); for (n = 0; n < npts; n++) { nn = 3 * n; if ((pts[nn+2] == 1 || pts[nn+2] == dim[2]) && pts[nn] > 0 && pts[nn] < dim[0] && pts[nn+1] > 0 && pts[nn+1] < dim[1]) { nf = noff + pts[nn]-1 + (pts[nn+1]-1) * (dim[0]-1); if (pts[nn+2] == dim[2]) nf += (dim[0]-1) * (dim[1]-1); faces[nfaces++] = copy_face (funcname, mesh->faces[nf]); } } } if (nfaces == 0) { free (faces); strcpy (reg->errmsg, "couldn't find any exterior faces"); return 0; } reg->nfaces = nfaces; reg->faces = faces; return 2; } /*-------------------------------------------------------------------*/ static int structured_zone (Tcl_Interp *interp, cgsize_t *dim) { char name[33], d_name[33]; int nints, nconns, nbocos, nholes, ii, nn, nr, nsets; cgsize_t i, j, k, n, ni, nj, nk, nf, ne, fn; cgsize_t npts, *pts, ndpts; cgsize_t range[6], d_range[6]; int transform[3]; CGNS_ENUMT(GridLocation_t) location; CGNS_ENUMT(GridConnectivityType_t) type; CGNS_ENUMT(PointSetType_t) ptype, d_ptype; CGNS_ENUMT(ZoneType_t) d_ztype; CGNS_ENUMT(DataType_t) datatype; CGNS_ENUMT(BCType_t) bctype; Face *f; Zone *z = &zones[cgnszone-1]; static char *funcname = "structured_zone"; zone_message ("finding exterior faces", NULL); if (cg_n1to1 (cgnsfn, cgnsbase, cgnszone, &nints) || cg_nconns (cgnsfn, cgnsbase, cgnszone, &nconns) || cg_nholes (cgnsfn, cgnsbase, cgnszone, &nholes) || cg_nbocos (cgnsfn, cgnsbase, cgnszone, &nbocos)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } z->nregs = nints + nconns + nholes + nbocos + 1; #ifndef NO_MESH_BOUNDARIES z->nregs += (2 * CellDim); #endif z->regs = (Regn *) MALLOC (funcname, z->nregs * sizeof(Regn)); ni = dim[0] - 1; nj = dim[1] - 1; nk = dim[2] - 1; nr = 1; /* mesh boundaries */ strcpy (z->regs[0].name, ""); z->regs[0].type = REG_MESH; for (n = 0; n < CellDim; n++) { z->regs[0].data[n] = dim[n]; range[n] = 1; range[n+CellDim] = dim[n]; } if (CellDim == 2) { z->regs[0].dim = 2; z->regs[0].nfaces = ni * nj; z->regs[0].faces = (Face **) MALLOC (funcname, (size_t)z->regs[0].nfaces * sizeof(Face *)); fn = 0; k = 0; for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i, j+1, k); f->nodes[2] = NODE_INDEX (i+1, j+1, k); f->nodes[3] = NODE_INDEX (i+1, j, k); } } #ifndef NO_CUTTING_PLANE nf = z->regs[0].nfaces; z->regs[0].elemtype = CGNS_ENUMV(QUAD_4); z->regs[0].nelems = nf; z->regs[0].elems = (cgsize_t *) MALLOC (funcname, (size_t)(4 * nf) * sizeof(cgsize_t)); for (n = 0, j = 0; j < nf; j++) { f = z->regs[0].faces[j]; for (i = 0; i < 4; i++) z->regs[0].elems[n++] = f->nodes[i]; } #endif #ifndef NO_MESH_BOUNDARIES strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 1; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 4; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[2] = 1; z->regs[nr].nedges = nj; z->regs[nr].edges = (Edge *) MALLOC (funcname, (size_t)nj * sizeof(Edge)); for (i = 0, j = 0; j < nj; j++) { z->regs[nr].edges[j].nodes[0] = NODE_INDEX(i, j, k); z->regs[nr].edges[j].nodes[1] = NODE_INDEX(i, j+1, k); } nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 1; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 4; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[0] = dim[0]; z->regs[nr].nedges = nj; z->regs[nr].edges = (Edge *) MALLOC (funcname, (size_t)nj * sizeof(Edge)); for (i = ni, j = 0; j < nj; j++) { z->regs[nr].edges[j].nodes[0] = NODE_INDEX(i, j, k); z->regs[nr].edges[j].nodes[1] = NODE_INDEX(i, j+1, k); } nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 1; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 4; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[3] = 1; z->regs[nr].nedges = ni; z->regs[nr].edges = (Edge *) MALLOC (funcname, (size_t)ni * sizeof(Edge)); for (j = 0, i = 0; i < ni; i++) { z->regs[nr].edges[i].nodes[0] = NODE_INDEX(i, j, k); z->regs[nr].edges[i].nodes[1] = NODE_INDEX(i+1, j, k); } nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 1; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 4; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[1] = dim[1]; z->regs[nr].nedges = ni; z->regs[nr].edges = (Edge *) MALLOC (funcname, (size_t)ni * sizeof(Edge)); for (j = nj, i = 0; i < ni; i++) { z->regs[nr].edges[i].nodes[0] = NODE_INDEX(i, j, k); z->regs[nr].edges[i].nodes[1] = NODE_INDEX(i+1, j, k); } nr++; #endif } else { z->regs[0].dim = 3; #ifndef NO_CUTTING_PLANE z->regs[0].elemtype = CGNS_ENUMV(HEXA_8); z->regs[0].nelems = ni * nj * nk; z->regs[0].elems = pts = (cgsize_t *) MALLOC (funcname, (size_t)(8 * z->regs[0].nelems) * sizeof(cgsize_t)); for (n = 0, k = 0; k < nk; k++) { for (j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { pts[n++] = NODE_INDEX (i, j, k); pts[n++] = NODE_INDEX (i+1, j, k); pts[n++] = NODE_INDEX (i+1, j+1, k); pts[n++] = NODE_INDEX (i, j+1, k); pts[n++] = NODE_INDEX (i, j, k+1); pts[n++] = NODE_INDEX (i+1, j, k+1); pts[n++] = NODE_INDEX (i+1, j+1, k+1); pts[n++] = NODE_INDEX (i, j+1, k+1); } } } #endif z->regs[0].nfaces = 2 * (nj * nk + ni * nk + ni * nj); z->regs[0].faces = (Face **) MALLOC (funcname, (size_t)z->regs[0].nfaces * sizeof(Face *)); fn = 0; for (i = 0, k = 0; k < nk; k++) { for (j = 0; j < nj; j++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i, j, k+1); f->nodes[2] = NODE_INDEX (i, j+1, k+1); f->nodes[3] = NODE_INDEX (i, j+1, k); } } for (i = ni, k = 0; k < nk; k++) { for (j = 0; j < nj; j++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i, j+1, k); f->nodes[2] = NODE_INDEX (i, j+1, k+1); f->nodes[3] = NODE_INDEX (i, j, k+1); } } for (j = 0, k = 0; k < nk; k++) { for (i = 0; i < ni; i++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i+1, j, k); f->nodes[2] = NODE_INDEX (i+1, j, k+1); f->nodes[3] = NODE_INDEX (i, j, k+1); } } for (j = nj, k = 0; k < nk; k++) { for (i = 0; i < ni; i++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i, j, k+1); f->nodes[2] = NODE_INDEX (i+1, j, k+1); f->nodes[3] = NODE_INDEX (i+1, j, k); } } for (k = 0, j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i, j+1, k); f->nodes[2] = NODE_INDEX (i+1, j+1, k); f->nodes[3] = NODE_INDEX (i+1, j, k); } } for (k = nk, j = 0; j < nj; j++) { for (i = 0; i < ni; i++) { f = z->regs[0].faces[fn++] = new_face (funcname, 4); f->nodes[0] = NODE_INDEX (i, j, k); f->nodes[1] = NODE_INDEX (i+1, j, k); f->nodes[2] = NODE_INDEX (i+1, j+1, k); f->nodes[3] = NODE_INDEX (i, j+1, k); } } #ifndef NO_MESH_BOUNDARIES fn = 0; nf = nj * nk; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[3] = 1; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[0] = dim[0]; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; nf = ni * nk; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[4] = 1; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[1] = dim[1]; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; nf = ni * nj; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[5] = 1; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; strcpy (z->regs[nr].name, ""); z->regs[nr].dim = 2; z->regs[nr].type = REG_BNDS; for (nn = 0; nn < 6; nn++) z->regs[nr].data[nn] = range[nn]; z->regs[nr].data[2] = dim[2]; z->regs[nr].nfaces = nf; z->regs[nr].faces = (Face **) MALLOC (funcname, (size_t)nf * sizeof(Face *)); for (n = 0; n < nf; n++) z->regs[nr].faces[n] = copy_face (funcname, z->regs->faces[fn++]); nr++; #endif } /* 1 to 1 interfaces */ for (nn = 1; nn <= nints; nn++) { if (cg_1to1_read (cgnsfn, cgnsbase, cgnszone, nn, name, d_name, range, d_range, transform)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_1TO1; z->regs[nr].data[0] = 2 * CellDim; for (ii = 0; ii < 2*CellDim; ii++) z->regs[nr].data[ii+1] = range[ii]; strcpy (z->regs[nr].d_name, d_name); k = structured_range (&z->regs[nr], dim, range, CGNS_ENUMV(Vertex)); z->regs[nr].dim = k; nr++; } /* general connectivities */ for (nn = 1; nn <= nconns; nn++) { if (cg_conn_info (cgnsfn, cgnsbase, cgnszone, nn, name, &location, &type, &ptype, &npts, d_name, &d_ztype, &d_ptype, &datatype, &ndpts)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } pts = (cgsize_t *) MALLOC (funcname, (size_t)(3 * npts) * sizeof(cgsize_t)); if (cg_conn_read_short (cgnsfn, cgnsbase, cgnszone, nn, pts)) { free (pts); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_CONN; z->regs[nr].data[0] = type; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = npts; if (ptype == CGNS_ENUMV(PointRange)) { z->regs[nr].data[3] = 2 * CellDim; for (ii = 0; ii < 2*CellDim; ii++) z->regs[nr].data[ii+4] = pts[ii]; } strcpy (z->regs[nr].d_name, d_name); if (type == CGNS_ENUMV(Abutting1to1) || type == CGNS_ENUMV(Abutting)) { if (ptype == CGNS_ENUMV(PointRange)) k = structured_range (&z->regs[nr], dim, pts, location); else if (ptype == CGNS_ENUMV(PointList)) k = structured_list (z->regs, &z->regs[nr], dim, npts, pts, location); else { k = 0; strcpy (z->regs[nr].errmsg, "invalid point set type"); } } else if (type == CGNS_ENUMV(Overset)) { k = 0; strcpy (z->regs[nr].errmsg, "Overset connectivity not implemented"); } else { k = 0; strcpy (z->regs[nr].errmsg, "invalid connectivity type"); } z->regs[nr].dim = k; free (pts); nr++; } /* holes */ for (nn = 1; nn <= nholes; nn++) { if (cg_hole_info (cgnsfn, cgnsbase, cgnszone, nn, name, &location, &ptype, &nsets, &npts)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } pts = (cgsize_t *) MALLOC (funcname, (size_t)(3 * npts * nsets) * sizeof(cgsize_t)); if (cg_hole_read (cgnsfn, cgnsbase, cgnszone, nn, pts)) { free (pts); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_HOLE; z->regs[nr].data[0] = nsets; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = npts; if (ptype == CGNS_ENUMV(PointRange)) { z->regs[nr].data[3] = 2 * CellDim; for (ii = 0; ii < 2*CellDim; ii++) z->regs[nr].data[ii+4] = pts[ii]; z->regs[nr].dim = structured_range (&z->regs[nr], dim, pts, location); if (z->regs[nr].dim && nsets > 1) { Edge *edges = z->regs[nr].edges; Face **faces = z->regs[nr].faces; ne = z->regs[nr].nedges; nf = z->regs[nr].nfaces; for (ii = 1; ii < nsets; ii++) { z->regs[nr].nedges = z->regs[nr].nfaces = 0; k = structured_range (&z->regs[nr], dim, &pts[ii*2*CellDim], location); if (k && z->regs[nr].nedges) { edges = (Edge *) REALLOC (funcname, (ne + z->regs[nr].nedges) * sizeof(Edge), edges); for (i = 0; i < z->regs[nr].nedges; i++) { edges[ne].nodes[0] = z->regs[nr].edges[i].nodes[0]; edges[ne].nodes[1] = z->regs[nr].edges[i].nodes[1]; ne++; } free(z->regs[nr].edges); } if (k && z->regs[nr].nfaces) { faces = (Face **) REALLOC (funcname, (nf + z->regs[nr].nfaces) * sizeof(Face *), faces); for (i = 0; i < z->regs[nr].nfaces; i++) faces[nf++] = z->regs[nr].faces[i]; free(z->regs[nr].faces); } } z->regs[nr].nedges = ne; z->regs[nr].edges = edges; z->regs[nr].nfaces = nf; z->regs[nr].faces = faces; } } else if (ptype == CGNS_ENUMV(PointList)) { z->regs[nr].dim = structured_list (z->regs, &z->regs[nr], dim, npts, pts, location); } else { strcpy (z->regs[nr].errmsg, "invalid Point Set Type"); } free(pts); nr++; } /* boundary conditions */ for (nn = 1; nn <= nbocos; nn++) { if (cg_boco_info (cgnsfn, cgnsbase, cgnszone, nn, name, &bctype, &ptype, &npts, transform, &j, &datatype, &ii) || cg_boco_gridlocation_read(cgnsfn, cgnsbase, cgnszone, nn, &location)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } pts = (cgsize_t *) MALLOC (funcname, (size_t)(3 * npts) * sizeof(cgsize_t)); if (cg_boco_read (cgnsfn, cgnsbase, cgnszone, nn, pts, 0)) { free (pts); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_BOCO; z->regs[nr].data[0] = bctype; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = i; if (ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(ElementRange)) { z->regs[nr].data[3] = 2 * CellDim; for (ii = 0; ii < 2*CellDim; ii++) z->regs[nr].data[ii+4] = pts[ii]; } if (ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(ElementRange)) k = structured_range (&z->regs[nr], dim, pts, location); else if (ptype == CGNS_ENUMV(PointList) || ptype == CGNS_ENUMV(ElementList)) k = structured_list (z->regs, &z->regs[nr], dim, npts, pts, location); else { k = 0; strcpy (z->regs[nr].errmsg, "invalid point set type"); } z->regs[nr].dim = k; free (pts); nr++; } z->nregs = nr; #ifndef NO_CUTTING_PLANE for (nr = 0; nr < z->nregs; nr++) { if (z->regs[nr].dim == 2 && z->regs[nr].nfaces) { nf = z->regs[nr].nfaces; z->regs[nr].elemtype = CGNS_ENUMV(QUAD_4); z->regs[nr].nelems = nf; z->regs[nr].elems = (cgsize_t *) MALLOC (funcname, (size_t)(4 * nf) * sizeof(cgsize_t)); for (n = 0, j = 0; j < nf; j++, f++) { f = z->regs[nr].faces[j]; for (ii = 0; ii < 4; ii++) z->regs[nr].elems[n++] = f->nodes[ii]; } } } #endif return 0; } /*==================================================================== * unstructured grid regions *====================================================================*/ static int max_face_nodes = 0; static cgsize_t *sort_face_nodes = NULL; /*-------------------------------------------------------------------*/ static int compare_faces (void *v1, void *v2) { Face *f1 = (Face *)v1; Face *f2 = (Face *)v2; int i, k; cgsize_t id, nn, *n1, *n2; if (f1->nnodes != f2->nnodes) return (f1->nnodes - f2->nnodes); if (f1->nnodes > max_face_nodes) { max_face_nodes += 10; sort_face_nodes = (cgsize_t *) REALLOC ("compare_faces", 2 * max_face_nodes * sizeof(cgsize_t), sort_face_nodes); } n1 = sort_face_nodes; n2 = sort_face_nodes + max_face_nodes; for (i = 0; i < f1->nnodes; i++) { id = f1->nodes[i]; for (k = 0; k < i; k++) { if (n1[k] > id) { nn = n1[k]; n1[k] = id; id = nn; } } n1[i] = id; } for (i = 0; i < f2->nnodes; i++) { id = f2->nodes[i]; for (k = 0; k < i; k++) { if (n2[k] > id) { nn = n2[k]; n2[k] = id; id = nn; } } n2[i] = id; } for (i = 0; i < f1->nnodes; i++) { if (n1[i] != n2[i]) return (int)(n1[i] - n2[i]); } return 0; } /*-------------------------------------------------------------------*/ static size_t hash_face (void *v) { Face *f = (Face *)v; int n; size_t hash = 0; for (n = 0; n < f->nnodes; n++) hash += (size_t)f->nodes[n]; return hash; } /*-------------------------------------------------------------------*/ static size_t get_faces (void *vf, void *vr) { Face *f = (Face *)vf; Regn *r = (Regn *)vr; r->faces[r->nfaces] = f; (r->nfaces)++; return 1; } /*-------------------------------------------------------------------*/ static int compare_poly (void *v1, void *v2) { PolyFace *p1 = (PolyFace *)v1; PolyFace *p2 = (PolyFace *)v2; return compare_faces(p1->face, p2->face); } /*-------------------------------------------------------------------*/ static size_t hash_poly (void *v) { PolyFace *p = (PolyFace *)v; return hash_face(p->face); } /*-------------------------------------------------------------------*/ static cgsize_t nPolyFaces; static size_t poly_faces (void *vp, void *vl) { PolyFace *pf = (PolyFace *)vp; PolyFace **pl = (PolyFace **)vl; pl[nPolyFaces++] = pf; return 1; } /*-------------------------------------------------------------------*/ static int poly_sort (const void *v1, const void *v2) { const PolyFace **p1 = (const PolyFace **)v1; const PolyFace **p2 = (const PolyFace **)v2; return (int)((*p1)->num - (*p2)->num); } /*-------------------------------------------------------------------*/ static Face *find_face (Zone *z, cgsize_t fnum) { int nr; cgsize_t nf; for (nr = 0; nr < z->nregs; nr++) { if (z->regs[nr].type == REG_ELEM && z->regs[nr].dim == 2 && z->regs[nr].data[1] <= fnum && z->regs[nr].data[2] >= fnum) { nf = fnum - z->regs[nr].data[1]; return z->regs[nr].faces[nf]; } } return NULL; } /*-------------------------------------------------------------------*/ static int element_dimension (CGNS_ENUMT(ElementType_t) elemtype) { switch (elemtype) { case CGNS_ENUMV(NODE): return 0; case CGNS_ENUMV(BAR_2): case CGNS_ENUMV(BAR_3): case CGNS_ENUMV(BAR_4): case CGNS_ENUMV(BAR_5): return 1; case CGNS_ENUMV(TRI_3): case CGNS_ENUMV(TRI_6): case CGNS_ENUMV(TRI_9): case CGNS_ENUMV(TRI_10): case CGNS_ENUMV(TRI_12): case CGNS_ENUMV(TRI_15): case CGNS_ENUMV(QUAD_4): case CGNS_ENUMV(QUAD_8): case CGNS_ENUMV(QUAD_9): case CGNS_ENUMV(QUAD_12): case CGNS_ENUMV(QUAD_16): case CGNS_ENUMV(QUAD_P4_16): case CGNS_ENUMV(QUAD_25): case CGNS_ENUMV(NGON_n): return 2; case CGNS_ENUMV(TETRA_4): case CGNS_ENUMV(TETRA_10): case CGNS_ENUMV(TETRA_16): case CGNS_ENUMV(TETRA_20): case CGNS_ENUMV(TETRA_22): case CGNS_ENUMV(TETRA_34): case CGNS_ENUMV(TETRA_35): case CGNS_ENUMV(PYRA_5): case CGNS_ENUMV(PYRA_13): case CGNS_ENUMV(PYRA_14): case CGNS_ENUMV(PYRA_21): case CGNS_ENUMV(PYRA_29): case CGNS_ENUMV(PYRA_30): case CGNS_ENUMV(PYRA_P4_29): case CGNS_ENUMV(PYRA_50): case CGNS_ENUMV(PYRA_55): case CGNS_ENUMV(PENTA_6): case CGNS_ENUMV(PENTA_15): case CGNS_ENUMV(PENTA_18): case CGNS_ENUMV(PENTA_24): case CGNS_ENUMV(PENTA_38): case CGNS_ENUMV(PENTA_40): case CGNS_ENUMV(PENTA_33): case CGNS_ENUMV(PENTA_66): case CGNS_ENUMV(PENTA_75): case CGNS_ENUMV(HEXA_8): case CGNS_ENUMV(HEXA_20): case CGNS_ENUMV(HEXA_27): case CGNS_ENUMV(HEXA_32): case CGNS_ENUMV(HEXA_56): case CGNS_ENUMV(HEXA_64): case CGNS_ENUMV(HEXA_44): case CGNS_ENUMV(HEXA_98): case CGNS_ENUMV(HEXA_125): case CGNS_ENUMV(NFACE_n): return 3; default: break; } return -1; } /*-------------------------------------------------------------------*/ static void edge_elements (Regn *r, cgsize_t *conn) { int ip; cgsize_t istart, n, ne, nelems; istart = r->data[1]; nelems = r->data[2] - istart + 1; cg_npe ((CGNS_ENUMT(ElementType_t))r->data[0], &ip); r->nedges = nelems; r->edges = (Edge *) MALLOC ("edge_elements", nelems * sizeof(Edge)); for (n = 0, ne = 0; ne < nelems; ne++) { r->edges[ne].id = istart + ne; r->edges[ne].nodes[0] = conn[n] - 1; r->edges[ne].nodes[1] = conn[n+1] - 1; n += ip; } } /*-------------------------------------------------------------------*/ static void face_elements (Regn *r, cgsize_t *conn, cgsize_t *conn_offsets) { int i, ip; cgsize_t ne, nn, istart, nelems; cgsize_t rind0, rind1; CGNS_ENUMT(ElementType_t) elemtype, type; static char *funcname = "face_elements"; elemtype = type = (CGNS_ENUMT(ElementType_t))r->data[0]; istart = r->data[1]; nelems = r->data[2] - istart + 1; rind0 = r->data[3]; rind1 = nelems - r->data[4]; r->nfaces = nelems; r->faces = (Face **) MALLOC (funcname, nelems * sizeof(Face *)); for (nn = 0, ne = 0; ne < nelems; ne++) { if (elemtype == CGNS_ENUMV(MIXED)) type = (CGNS_ENUMT(ElementType_t))conn[nn++]; switch (type) { case CGNS_ENUMV(TRI_3): case CGNS_ENUMV(TRI_6): case CGNS_ENUMV(TRI_9): case CGNS_ENUMV(TRI_10): case CGNS_ENUMV(TRI_12): case CGNS_ENUMV(TRI_15): ip = 3; break; case CGNS_ENUMV(QUAD_4): case CGNS_ENUMV(QUAD_8): case CGNS_ENUMV(QUAD_9): case CGNS_ENUMV(QUAD_12): case CGNS_ENUMV(QUAD_16): case CGNS_ENUMV(QUAD_P4_16): case CGNS_ENUMV(QUAD_25): ip = 4; break; case CGNS_ENUMV(NGON_n): ip = (int)(conn_offsets[ne+1]-conn_offsets[ne]); break; default: if (type < CGNS_ENUMV(NODE) || type >= NofValidElementTypes) FATAL ("face_elements:unknown element type"); ip = 0; break; } if (ip) { r->faces[ne] = new_face (funcname, ip); r->faces[ne]->id = istart + ne; for (i = 0; i < ip; i++) r->faces[ne]->nodes[i] = conn[nn+i] - 1; if (ne < rind0 || ne >= rind1) r->faces[ne]->flags = 1; } else { r->faces[ne] = NULL; } if (type == CGNS_ENUMV(NGON_n)) nn += ip; else { cg_npe (type, &i); nn += i; } } } /*-------------------------------------------------------------------*/ static void exterior_faces (Zone *z, Regn *r, cgsize_t *conn, cgsize_t *conn_offsets) { int i, j, nf, ip, flag; cgsize_t ne, nn, istart, nelems; cgsize_t rind0, rind1; CGNS_ENUMT(ElementType_t) elemtype; HASH *facehash; Face *face, *pf; static char *funcname = "exterior_faces"; elemtype = (CGNS_ENUMT(ElementType_t))r->data[0]; istart = r->data[1]; nelems = r->data[2] - istart + 1; rind0 = r->data[3]; rind1 = nelems - r->data[4]; facehash = HashCreate (nelems > 1024 ? (size_t)nelems / 3 : 127, compare_faces, hash_face); if (NULL == facehash) FATAL ("exterior_faces:face hash table creation failed"); if (elemtype == CGNS_ENUMV(NFACE_n)) { for (ne = 0; ne < nelems; ne++) { flag = (ne < rind0 || ne >= rind1) ? 1 : 0; for (j = conn_offsets[ne]; j < conn_offsets[ne+1]; j++) { face = find_face (z, abs(conn[j])); if (face != NULL) { pf = (Face *) HashFind (facehash, face); if (NULL == pf) { pf = copy_face (funcname, face); pf->id = 0; pf->flags = flag; (void) HashAdd (facehash, pf); } else if (flag == pf->flags) { HashDelete (facehash, pf); free (pf); } else { pf->flags = 0; } } } } } else { CGNS_ENUMT(ElementType_t) type = elemtype; face = new_face(funcname, 4); for (nn = 0, ne = 0; ne < nelems; ne++) { flag = (ne < rind0 || ne >= rind1) ? 1 : 0; if (elemtype == CGNS_ENUMV(MIXED)) type = (CGNS_ENUMT(ElementType_t))conn[nn++]; switch (type) { case CGNS_ENUMV(TETRA_4): case CGNS_ENUMV(TETRA_10): case CGNS_ENUMV(TETRA_16): case CGNS_ENUMV(TETRA_20): case CGNS_ENUMV(TETRA_22): case CGNS_ENUMV(TETRA_34): case CGNS_ENUMV(TETRA_35): ip = 2; nf = 4; break; case CGNS_ENUMV(PYRA_5): case CGNS_ENUMV(PYRA_13): case CGNS_ENUMV(PYRA_14): case CGNS_ENUMV(PYRA_21): case CGNS_ENUMV(PYRA_29): case CGNS_ENUMV(PYRA_30): case CGNS_ENUMV(PYRA_P4_29): case CGNS_ENUMV(PYRA_50): case CGNS_ENUMV(PYRA_55): ip = 6; nf = 5; break; case CGNS_ENUMV(PENTA_6): case CGNS_ENUMV(PENTA_15): case CGNS_ENUMV(PENTA_18): case CGNS_ENUMV(PENTA_24): case CGNS_ENUMV(PENTA_38): case CGNS_ENUMV(PENTA_40): case CGNS_ENUMV(PENTA_33): case CGNS_ENUMV(PENTA_66): case CGNS_ENUMV(PENTA_75): ip = 11; nf = 5; break; case CGNS_ENUMV(HEXA_8): case CGNS_ENUMV(HEXA_20): case CGNS_ENUMV(HEXA_27): case CGNS_ENUMV(HEXA_32): case CGNS_ENUMV(HEXA_56): case CGNS_ENUMV(HEXA_64): case CGNS_ENUMV(HEXA_44): case CGNS_ENUMV(HEXA_98): case CGNS_ENUMV(HEXA_125): ip = 16; nf = 6; break; default: if (type < CGNS_ENUMV(NODE) || type >= NofValidElementTypes) FATAL ("exterior_faces:unknown element type"); ip = 0; nf = 0; break; } for (j = 0; j < nf; j++) { face->nnodes = facenodes[ip+j][0]; for (i = 0; i < face->nnodes; i++) face->nodes[i] = conn[nn + facenodes[ip+j][i+1]] - 1; pf = (Face *) HashFind (facehash, face); if (NULL == pf) { pf = copy_face (funcname, face); pf->id = 0; pf->flags = flag; (void) HashAdd (facehash, pf); } else if (flag == pf->flags) { HashDelete (facehash, pf); free (pf); } else { pf->flags = 0; } } cg_npe (type, &j); nn += j; } free(face); } r->nfaces = 0; ne = (cgsize_t) HashSize (facehash); if (ne) { r->faces = (Face **) MALLOC (funcname, ne * sizeof(Face *)); HashList (facehash, get_faces, r); } else { strcpy (r->errmsg, "couldn't find any exterior faces"); } HashDestroy (facehash, NULL); } /*-------------------------------------------------------------------*/ static void polyhedral_faces (Zone *z, Regn *r, cgsize_t *conn, cgsize_t *conn_offsets) { int j, nf, flag; cgsize_t ne, nn, istart, nelems, nfaces, id; cgsize_t rind0, rind1; HASH *facehash; Face *face; PolyFace poly, *pf, **polylist; static char *funcname = "polyhedral_faces"; istart = r->data[1]; nelems = r->data[2] - istart + 1; rind0 = r->data[3]; rind1 = nelems - r->data[4]; facehash = HashCreate (nelems > 1024 ? (size_t)nelems / 3 : 127, compare_poly, hash_poly); if (NULL == facehash) FATAL ("polyhedral_faces:face hash table creation failed"); nfaces = 0; for (nn = 0, ne = 0; ne < nelems; ne++) { flag = (ne < rind0 || ne >= rind1) ? 1 : 0; for (j = conn_offsets[ne]; j < conn_offsets[ne+1]; j++) { id = conn[j]; face = find_face (z, abs(id)); poly.face = face; pf = (PolyFace *) HashFind (facehash, &poly); if (NULL == pf) { pf = (PolyFace *)MALLOC(funcname, sizeof(PolyFace)); pf->face = face; pf->num = ++nfaces; pf->flags = flag; (void) HashAdd (facehash, pf); } else { if ((pf->flags & 1) != flag) pf->flags &= ~1; pf->flags |= 2; } conn[j] = id < 0 ? -(pf->num) : pf->num; } } nfaces = (cgsize_t) HashSize (facehash); polylist = (PolyFace **) MALLOC (funcname, nfaces * sizeof(PolyFace *)); nPolyFaces = 0; HashList (facehash, poly_faces, polylist); HashDestroy (facehash, NULL); qsort(polylist, nfaces, sizeof(PolyFace *), poly_sort); for (nn = 0, ne = 0; ne < nfaces; ne++) { if ((polylist[ne]->flags & 2) == 0) nn++; } r->nfaces = nn; r->faces = (Face **) MALLOC (funcname, nn * sizeof(Face *)); for (nn = 0, ne = 0; ne < nfaces; ne++) { if ((polylist[ne]->flags & 2) == 0) { r->faces[nn] = copy_face(funcname, polylist[ne]->face); r->faces[nn]->id = 0; r->faces[nn]->flags = (polylist[ne]->flags & 1); nn++; } } r->npoly = nfaces; r->poly = (Face **) MALLOC (funcname, nfaces * sizeof(Face *)); for (nn = 0; nn < nfaces; nn++) { face = polylist[nn]->face; face->flags |= (polylist[nn]->flags & 2); r->poly[nn] = face; free(polylist[nn]); } free(polylist); r->elemtype = CGNS_ENUMV(NFACE_n); r->nelems = nelems; r->elems = conn; r->elem_offsets = conn_offsets; } /*-------------------------------------------------------------------*/ static int sort_elemsets(const void *v1, const void *v2) { return (((Regn *)v2)->dim - ((Regn *)v1)->dim); } /*-------------------------------------------------------------------*/ static cgsize_t unstructured_region (int nregs, Regn *regs, Regn *r, CGNS_ENUMT(PointSetType_t) ptype, cgsize_t nlist, cgsize_t *list) { int nr, nn; cgsize_t nf, nfaces, maxfaces; Face **faces, *f; static char *funcname = "unstructured_region"; if (ptype == CGNS_ENUMV(PointList) || ptype == CGNS_ENUMV(ElementList)) { for (nf = 1; nf < nlist; nf++) { if (list[nf] < list[nf-1]) { qsort (list, (size_t)nlist, sizeof(cgsize_t), compare_ints); break; } } maxfaces = nlist; } else if (ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(ElementRange)) { if (list[0] > list[1]) { nf = list[0]; list[0] = list[1]; list[1] = nf; } maxfaces = list[1] - list[0] + 1; } else { strcpy (r->errmsg, "invalid point set type"); maxfaces = 0; } if (maxfaces < 1) return 0; faces = (Face **)MALLOC(funcname, (size_t)maxfaces * sizeof(Face *)); nfaces = 0; for (nr = 0; nr < nregs; nr++) { if (!regs[nr].nfaces) continue; for (nf = 0; nf < regs[nr].nfaces; nf++) { f = regs[nr].faces[nf]; switch (ptype) { case CGNS_ENUMV(PointList): if (f->id) continue; for (nn = 0; nn < f->nnodes; nn++) { if (!find_int (f->nodes[nn]+1, nlist, list)) break; } if (nn == f->nnodes) break; continue; case CGNS_ENUMV(PointRange): if (f->id) continue; for (nn = 0; nn < f->nnodes; nn++) { if (f->nodes[nn]+1 < list[0] || f->nodes[nn]+1 > list[1]) break; } if (nn == f->nnodes) break; continue; case CGNS_ENUMV(ElementList): if (f->id && find_int (f->id, nlist, list)) break; continue; case CGNS_ENUMV(ElementRange): if (f->id >= list[0] && f->id <= list[1]) break; continue; default: continue; } if (nfaces == maxfaces) { maxfaces += 100; faces = (Face **) REALLOC (funcname, (size_t)maxfaces * sizeof(Face *), faces); } faces[nfaces++] = f; } } if (nfaces) { r->nfaces = nfaces; r->faces = (Face **)MALLOC(funcname, (size_t)nfaces * sizeof(Face *)); for (nf = 0; nf < nfaces; nf++) r->faces[nf] = copy_face(funcname, faces[nf]); } else strcpy (r->errmsg, "couldn't find any exterior faces"); free (faces); return nfaces; } /*-------------------------------------------------------------------*/ static int unstructured_zone (Tcl_Interp *interp) { int i, ns, nb, ip, nr, haspoly, nsets; int nsect, nints, nconns, nholes, nbocos, nrmlindex[3]; int transform[3], rind[2]; cgsize_t is, ie, np, n, ne, nf; cgsize_t nelem, elemsize, *conn, *conn_offsets; cgsize_t range[6], d_range[6]; CGNS_ENUMT(GridLocation_t) location; CGNS_ENUMT(GridConnectivityType_t) type; CGNS_ENUMT(PointSetType_t) ptype, d_ptype; CGNS_ENUMT(ZoneType_t) d_ztype; CGNS_ENUMT(DataType_t) datatype; CGNS_ENUMT(BCType_t) bctype; CGNS_ENUMT(ElementType_t) elemtype; char name[33], d_name[33]; Zone *z = &zones[cgnszone-1]; static char *funcname = "unstructured_zone"; static char *dspmsg = "finding exterior faces for"; if (cg_nsections (cgnsfn, cgnsbase, cgnszone, &nsect) || cg_n1to1 (cgnsfn, cgnsbase, cgnszone, &nints) || cg_nconns (cgnsfn, cgnsbase, cgnszone, &nconns) || cg_nholes (cgnsfn, cgnsbase, cgnszone, &nholes) || cg_nbocos (cgnsfn, cgnsbase, cgnszone, &nbocos)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } z->nregs = nsect + nints + nconns + nholes + nbocos; z->regs = (Regn *) MALLOC (funcname, z->nregs * sizeof(Regn)); /* element sets */ haspoly = 0; for (nr = 0, ns = 1; ns <= nsect; ns++, nr++) { if (cg_section_read (cgnsfn, cgnsbase, cgnszone, ns, name, &elemtype, &is, &ie, &nb, &ip) || cg_ElementDataSize (cgnsfn, cgnsbase, cgnszone, ns, &elemsize)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } zone_message (dspmsg, name); strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_ELEM; z->regs[nr].data[0] = elemtype; z->regs[nr].data[1] = is; z->regs[nr].data[2] = ie; if (cg_goto (cgnsfn, cgnsbase, "Zone_t", cgnszone, "Elements_t", ns, "end") || cg_rind_read (rind)) { rind[0] = rind[1] = 0; } z->regs[nr].data[3] = rind[0]; z->regs[nr].data[4] = rind[1]; if (elemtype < CGNS_ENUMV(BAR_2) || elemtype >= NofValidElementTypes) { strcpy (z->regs[nr].errmsg, "invalid element type"); continue; } /* do this after reading all the sections */ if (elemtype == CGNS_ENUMV(NFACE_n)) { z->regs[nr].dim = 3; haspoly++; continue; } nelem = ie - is + 1; conn = (cgsize_t *) MALLOC (funcname, (size_t)elemsize * sizeof(cgsize_t)); conn_offsets = NULL; if (elemtype == CGNS_ENUMV(MIXED) || elemtype == CGNS_ENUMV(NGON_n) ) { conn_offsets = (cgsize_t *) MALLOC (funcname, (size_t) (nelem+1)*sizeof(cgsize_t)); if (cg_poly_elements_read (cgnsfn, cgnsbase, cgnszone, ns, conn, conn_offsets, 0)) { free (conn); if (conn_offsets) { free(conn_offsets); } Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } } else { if (cg_elements_read (cgnsfn, cgnsbase, cgnszone, ns, conn, 0)) { free (conn); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } } /* check element indices */ if (elemtype == CGNS_ENUMV(MIXED)) { int dim; CGNS_ENUMT(ElementType_t) type; z->regs[nr].dim = -1; for (n = 0, ne = 0; ne < nelem; ne++) { type = (CGNS_ENUMT(ElementType_t))conn[n++]; if (cg_npe (type, &ip) || ip <= 0) { strcpy(z->regs[nr].errmsg, "unhandled element type found in MIXED"); break; } for (i = 0; i < ip; i++) { if (conn[n] < 1 || conn[n] > z->nnodes) { strcpy(z->regs[nr].errmsg, "invalid element index"); break; } n++; } if (i < ip) break; dim = element_dimension(type); if (z->regs[nr].dim < dim) z->regs[nr].dim = dim; } } else if (elemtype == CGNS_ENUMV(NGON_n)) { z->regs[nr].dim = 2; for (ne = 0; ne < nelem; ne++) { ip = (int) conn_offsets[ne+1]; for (n = conn_offsets[ne]; n < conn_offsets[ne+1]; n++) { if (conn[n] < 1 || conn[n] > z->nnodes) { strcpy(z->regs[nr].errmsg, "invalid element index"); break; } } if (n < ip) break; } } else { z->regs[nr].dim = element_dimension(elemtype); cg_npe (elemtype, &ip); for (n = 0, ne = 0; ne < nelem; ne++) { for (i = 0; i < ip; i++) { if (conn[n] < 1 || conn[n] > z->nnodes) { strcpy(z->regs[nr].errmsg, "invalid element index"); break; } n++; } if (i < ip) break; } } if (ne == nelem && z->regs[nr].dim > 0) { if (z->regs[nr].dim == 1) edge_elements(&z->regs[nr], conn); else if (z->regs[nr].dim == 2) face_elements (&z->regs[nr], conn, conn_offsets); else exterior_faces (z, &z->regs[nr], conn, conn_offsets); #ifndef NO_CUTTING_PLANE if (z->regs[nr].dim > 1) { z->regs[nr].elemtype = elemtype; z->regs[nr].nelems = nelem; z->regs[nr].elems = conn; z->regs[nr].elem_offsets = conn_offsets; /* fix element indexing */ cg_npe (elemtype, &ip); for (n = 0, ne = 0; ne < nelem; ne++) { if (elemtype == CGNS_ENUMT(MIXED)) { nb = (int)conn[n++]; cg_npe ((CGNS_ENUMT(ElementType_t))nb, &ip); } else if (elemtype == CGNS_ENUMT(NGON_n)) { ip = (int)(conn_offsets[ne+1] - conn_offsets[ne]); } for (i = 0; i < ip; i++) { (conn[n])--; n++; } } } else #endif free (conn); } } /* process NFACE_n sections */ if (haspoly) { for (ns = 0; ns < nsect; ns++) { if (z->regs[ns].data[0] != CGNS_ENUMV(NFACE_n)) continue; zone_message (dspmsg, z->regs[ns].name); nelem = z->regs[ns].data[2] - z->regs[ns].data[1] + 1; cg_ElementDataSize (cgnsfn, cgnsbase, cgnszone, ns+1, &elemsize); conn = (cgsize_t *) MALLOC (funcname, (size_t)elemsize * sizeof(cgsize_t)); conn_offsets = (cgsize_t *) MALLOC (funcname, (size_t) (nelem+1)*sizeof(cgsize_t)); if (cg_poly_elements_read (cgnsfn, cgnsbase, cgnszone, ns+1, conn, conn_offsets, 0)) { free (conn); free(conn_offsets); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } /* check element indices */ for (n = 0, ne = 0; ne < nelem; ne++) { ip = (int) conn_offsets[ne+1]; for (n = conn_offsets[ne]; n < conn_offsets[ne+1]; n++) { if (NULL == find_face(z, abs(conn[n]))) { strcpy(z->regs[nr].errmsg, "invalid face index"); break; } } if (n < ip) break; } if (ne == nelem) { #ifndef NO_CUTTING_PLANE polyhedral_faces (z, &z->regs[ns], conn, conn_offsets); #else exterior_faces (z, &z->regs[ns], conn, conn_offsets); free (conn); #endif } } } qsort(z->regs, nr, sizeof(Regn), sort_elemsets); /* 1to1 connectivities */ for (ns = 1; ns <= nints; ns++) { if (cg_1to1_read (cgnsfn, cgnsbase, cgnszone, ns, name, d_name, range, d_range, transform)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } zone_message (dspmsg, name); strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_1TO1; z->regs[nr].data[0] = 2; z->regs[nr].data[1] = range[0]; z->regs[nr].data[2] = range[1]; strcpy (z->regs[nr].d_name, d_name); if (unstructured_region (nsect, z->regs, &z->regs[nr], CGNS_ENUMV(PointRange), 2, range)) z->regs[nr].dim = 2; nr++; } /* general connectivities */ for (ns = 1; ns <= nconns; ns++) { if (cg_conn_info (cgnsfn, cgnsbase, cgnszone, ns, name, &location, &type, &ptype, &np, d_name, &d_ztype, &d_ptype, &datatype, &ie)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } zone_message (dspmsg, name); conn = (cgsize_t *) MALLOC (funcname, (size_t)np * sizeof(cgsize_t)); if (cg_conn_read_short (cgnsfn, cgnsbase, cgnszone, ns, conn)) { free (conn); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_CONN; z->regs[nr].data[0] = type; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = np; if (ptype == CGNS_ENUMT(PointRange)) { z->regs[nr].data[4] = conn[0]; z->regs[nr].data[5] = conn[1]; } strcpy (z->regs[nr].d_name, d_name); if (type != CGNS_ENUMV(Abutting) && type != CGNS_ENUMV(Abutting1to1)) { strcpy(z->regs[nr].errmsg, "can only handle Abutting or Abutting1to1 currently"); } else if (ptype != CGNS_ENUMV(PointList) && ptype != CGNS_ENUMV(PointRange)) { strcpy(z->regs[nr].errmsg, "point set type not PointList or PointRange"); } else if (location != CGNS_ENUMV(Vertex) && location != CGNS_ENUMV(CellCenter) && location != CGNS_ENUMV(FaceCenter)) { strcpy(z->regs[nr].errmsg, "location not Vertex, CellCenter or FaceCenter"); } else { if (location != CGNS_ENUMV(Vertex)) { ptype = (ptype == CGNS_ENUMV(PointRange) ? CGNS_ENUMV(ElementRange) : CGNS_ENUMV(ElementList)); } if (unstructured_region (nsect, z->regs, &z->regs[nr], ptype, np, conn)) z->regs[nr].dim = 2; } free (conn); nr++; } /* holes */ for (ns = 1; ns <= nholes; ns++) { if (cg_hole_info (cgnsfn, cgnsbase, cgnszone, ns, name, &location, &ptype, &nsets, &np)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } conn = (cgsize_t *) MALLOC (funcname, (size_t)(3 * np * nsets) * sizeof(cgsize_t)); if (cg_hole_read (cgnsfn, cgnsbase, cgnszone, ns, conn)) { free (conn); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_HOLE; z->regs[nr].data[0] = nsets; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = np; if (ptype == CGNS_ENUMV(PointRange)) { z->regs[nr].data[4] = conn[0]; z->regs[nr].data[5] = conn[1]; } else if (ptype != CGNS_ENUMV(PointList)) { strcpy(z->regs[nr].errmsg, "point set type not PointList or PointRange"); } else { if (location == CGNS_ENUMV(Vertex)) { d_ptype = ptype; } else { d_ptype = (ptype == CGNS_ENUMV(PointRange) ? CGNS_ENUMV(ElementRange) : CGNS_ENUMV(ElementList)); } if (unstructured_region (nsect, z->regs, &z->regs[nr], d_ptype, np, conn)) z->regs[nr].dim = 2; if (z->regs[nr].dim && nsets > 1 && ptype == CGNS_ENUMV(PointRange)) { Edge *edges = z->regs[nr].edges; Face **faces = z->regs[nr].faces; ne = z->regs[nr].nedges; nf = z->regs[nr].nfaces; for (ip = 1; ip < nsets; ip++) { z->regs[nr].nedges = z->regs[nr].nfaces = 0; is = unstructured_region (nsect, z->regs, &z->regs[nr], d_ptype, np, &conn[ip*2]); if (is && z->regs[nr].nedges) { edges = (Edge *) REALLOC (funcname, (ne + z->regs[nr].nedges) * sizeof(Edge), edges); for (i = 0; i < z->regs[nr].nedges; i++) { edges[ne].nodes[0] = z->regs[nr].edges[i].nodes[0]; edges[ne].nodes[1] = z->regs[nr].edges[i].nodes[1]; ne++; } free(z->regs[nr].edges); } if (is && z->regs[nr].nfaces) { faces = (Face **) REALLOC (funcname, (nf + z->regs[nr].nfaces) * sizeof(Face *), faces); for (i = 0; i < z->regs[nr].nfaces; i++) faces[nf++] = z->regs[nr].faces[i]; free(z->regs[nr].faces); } } z->regs[nr].nedges = ne; z->regs[nr].edges = edges; z->regs[nr].nfaces = nf; z->regs[nr].faces = faces; } } free (conn); nr++; } /* boundary conditions */ for (ns = 1; ns <= nbocos; ns++) { if (cg_boco_info (cgnsfn, cgnsbase, cgnszone, ns, name, &bctype, &ptype, &np, nrmlindex, &is, &datatype, &nb) || cg_boco_gridlocation_read (cgnsfn, cgnsbase, cgnszone, ns, &location)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } zone_message (dspmsg, name); conn = (cgsize_t *) MALLOC (funcname, (size_t)np * sizeof(cgsize_t)); if (cg_boco_read (cgnsfn, cgnsbase, cgnszone, ns, conn, 0)) { free (conn); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return 1; } strcpy (z->regs[nr].name, name); z->regs[nr].type = REG_BOCO; z->regs[nr].data[0] = bctype; z->regs[nr].data[1] = location; z->regs[nr].data[2] = ptype; z->regs[nr].data[3] = np; if (ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(ElementRange)) { z->regs[nr].data[4] = conn[0]; z->regs[nr].data[5] = conn[1]; } if ((ptype == CGNS_ENUMV(PointRange) || ptype == CGNS_ENUMV(PointList)) && (location == CGNS_ENUMV(FaceCenter) || location == CGNS_ENUMV(CellCenter))) { ptype = (ptype == CGNS_ENUMV(PointRange) ? CGNS_ENUMV(ElementRange) : CGNS_ENUMV(ElementList)); } if (unstructured_region (nsect, z->regs, &z->regs[nr], ptype, np, conn)) z->regs[nr].dim = 2; free (conn); nr++; } z->nregs = nr; return 0; } /*==================================================================== * find region edges *====================================================================*/ /*-------------------------------------------------------------------*/ static int compare_edges (void *v1, void *v2) { Edge *e1 = (Edge *)v1; Edge *e2 = (Edge *)v2; if (e1->nodes[0] < e1->nodes[1]) { if (e2->nodes[0] < e2->nodes[1]) return (int)(e1->nodes[0] - e2->nodes[0]); return (int)(e1->nodes[0] - e2->nodes[1]); } if (e2->nodes[0] < e2->nodes[1]) return (int)(e1->nodes[1] - e2->nodes[0]); return (int)(e1->nodes[1] - e2->nodes[1]); } /*-------------------------------------------------------------------*/ static size_t hash_edge (void *v) { Edge *e = (Edge *)v; return ((size_t)(e->nodes[0] + e->nodes[1])); } /*-------------------------------------------------------------------*/ static size_t get_edges (void *ve, void *vr) { Edge *e = (Edge *)ve; Regn *r = (Regn *)vr; r->edges[r->nedges].nodes[0] = e->nodes[0]; r->edges[r->nedges].nodes[1] = e->nodes[1]; (r->nedges)++; return 1; } /*-------------------------------------------------------------------*/ static void extract_edges (Regn *r) { int i, k; cgsize_t j, n; size_t ne; Face *f; Edge edge, *ep; HASH *edgehash; float dot; static char *funcname = "extract_edges"; if (!r->nfaces) return; edgehash = HashCreate ((size_t)r->nfaces, compare_edges, hash_edge); if (NULL == edgehash) FATAL ("edge hash table creation failed"); for (j = 0; j < r->nfaces; j++) { f = r->faces[j]; if (f->flags) continue; for (i = 0, k = f->nnodes-1; i < f->nnodes; k = i++) { if (f->nodes[i] == f->nodes[k]) continue; if (f->nodes[i] < f->nodes[k]) { edge.nodes[0] = f->nodes[i]; edge.nodes[1] = f->nodes[k]; } else { edge.nodes[0] = f->nodes[k]; edge.nodes[1] = f->nodes[i]; } ep = (Edge *) HashFind (edgehash, &edge); if (NULL == ep) { ep = (Edge *) MALLOC (funcname, sizeof(Edge)); ep->nodes[0] = edge.nodes[0]; ep->nodes[1] = edge.nodes[1]; ep->id = j; (void) HashAdd (edgehash, ep); } else { n = ep->id; dot = r->faces[n]->normal[0] * f->normal[0] + r->faces[n]->normal[1] * f->normal[1] + r->faces[n]->normal[2] * f->normal[2]; if (dot > EDGE_ANGLE) { HashDelete (edgehash, ep); free (ep); } } } } ne = HashSize (edgehash); if (ne) { r->nedges = 0; r->edges = (Edge *) MALLOC (funcname, ne * sizeof(Edge)); HashList (edgehash, get_edges, r); } HashDestroy (edgehash, NULL); } /*=================================================================== * region manipulation *===================================================================*/ /*-------------------------------------------------------------------*/ static float *compute_normal (Node n0, Node n1, Node n2, Node n3) { int j; double xn, yn, zn, sn; double d1[3], d2[3]; static float norm[3]; /* triangle */ if (NULL == n3) { for (j = 0; j < 3; j++) { d1[j] = n1[j] - n0[j]; d2[j] = n2[j] - n0[j]; } sn = 0.5; } /* quadrilateral */ else { for (j = 0; j < 3; j++) { d1[j] = n2[j] - n0[j]; d2[j] = n3[j] - n1[j]; } sn = 1.0; } xn = sn * (d1[1] * d2[2] - d2[1] * d1[2]); yn = sn * (d1[2] * d2[0] - d2[2] * d1[0]); zn = sn * (d1[0] * d2[1] - d2[0] * d1[1]); sn = sqrt (xn * xn + yn * yn + zn * zn); if (sn == 0.0) sn = 1.0; norm[0] = (float)(xn / sn); norm[1] = (float)(yn / sn); norm[2] = (float)(zn / sn); return norm; } /*-------------------------------------------------------------------*/ static float *face_normal (Zone *z, int nnodes, cgsize_t *nodes) { int i, n; float *n0, *n1, *n2, *n3; float *norm, sn; static float sum[3]; if (nnodes < 3) { for (i = 0; i < 3; i++) sum[i] = 0.0; return sum; } if (nnodes <= 4) { n0 = z->nodes[nodes[0]]; n1 = z->nodes[nodes[1]]; n2 = z->nodes[nodes[2]]; n3 = nnodes == 4 ? z->nodes[nodes[3]] : NULL; return compute_normal(n0, n1, n2, n3); } for (i = 0; i < 3; i++) sum[i] = 0.0; n0 = z->nodes[nodes[0]]; n1 = z->nodes[nodes[1]]; for (n = 2; n < nnodes; n++) { n2 = z->nodes[nodes[n]]; norm = compute_normal(n0, n1, n2, NULL); for (i = 0; i < 3; i++) sum[i] += norm[i]; n1 = n2; } sn = (float)sqrt(sum[0]*sum[0] + sum[1]*sum[1] + sum[2]*sum[2]); if (sn == 0.0) sn = 1.0; for (i = 0; i < 3; i++) sum[i] /= sn; return sum; } /*-------------------------------------------------------------------*/ static void region_normals (Zone *z, Regn *r) { int i, n; Face *f; float *norm; for (n = 0; n < r->nfaces; n++) { f = r->faces[n]; norm = face_normal(z, f->nnodes, f->nodes); for (i = 0; i < 3; i++) f->normal[i] = norm[i]; } } /*-------------------------------------------------------------------*/ static void bounding_box (Zone *z, Regn *r) { int i, j, n; if (r->nfaces) { Face *f = r->faces[0]; for (j = 0; j < 3; j++) r->bbox[j][0] = r->bbox[j][1] = z->nodes[f->nodes[0]][j]; for (n = 0; n < r->nfaces; n++) { f = r->faces[n]; for (i = 0; i < f->nnodes; i++) { for (j = 0; j < 3; j++) { if (r->bbox[j][0] > z->nodes[f->nodes[i]][j]) r->bbox[j][0] = z->nodes[f->nodes[i]][j]; if (r->bbox[j][1] < z->nodes[f->nodes[i]][j]) r->bbox[j][1] = z->nodes[f->nodes[i]][j]; } } } } else if (r->nedges) { Edge *e = r->edges; for (j = 0; j < 3; j++) r->bbox[j][0] = r->bbox[j][1] = z->nodes[e->nodes[0]][j]; for (n = 0; n < r->nedges; n++, e++) { for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { if (r->bbox[j][0] > z->nodes[e->nodes[i]][j]) r->bbox[j][0] = z->nodes[e->nodes[i]][j]; if (r->bbox[j][1] < z->nodes[e->nodes[i]][j]) r->bbox[j][1] = z->nodes[e->nodes[i]][j]; } } } } else { for (j = 0; j < 3; j++) r->bbox[j][0] = r->bbox[j][1] = 0.0; } } /*-------------------------------------------------------------------*/ static void get_bounds (int all, float bbox[3][2]) { int nz, nr, n, first = 1; for (nz = 0; nz < nzones; nz++) { for (nr = 0; nr < zones[nz].nregs; nr++) { if (zones[nz].regs[nr].nfaces && (all || zones[nz].regs[nr].mode)) { if (first) { for (n = 0; n < 3; n++) { bbox[n][0] = zones[nz].regs[nr].bbox[n][0]; bbox[n][1] = zones[nz].regs[nr].bbox[n][1]; } first = 0; } else { for (n = 0; n < 3; n++) { if (bbox[n][0] > zones[nz].regs[nr].bbox[n][0]) bbox[n][0] = zones[nz].regs[nr].bbox[n][0]; if (bbox[n][1] < zones[nz].regs[nr].bbox[n][1]) bbox[n][1] = zones[nz].regs[nr].bbox[n][1]; } } } } } if (first) { for (n = 0; n < 3; n++) { bbox[n][0] = 0.0; bbox[n][1] = 1.0; } } } /*-------------------------------------------------------------------*/ static void draw_outlines (Zone *z, Regn *r) { glDisable (GL_LIGHTING); glShadeModel (GL_FLAT); glBegin (GL_LINES); if (r->nedges) { int ne; for (ne = 0; ne < r->nedges; ne++) { glVertex3fv (z->nodes[r->edges[ne].nodes[0]]); glVertex3fv (z->nodes[r->edges[ne].nodes[1]]); } } else { glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][1]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][1]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][1]); glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][0], r->bbox[2][1]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][1], r->bbox[1][1], r->bbox[2][1]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][0]); glVertex3f (r->bbox[0][0], r->bbox[1][1], r->bbox[2][1]); } glEnd (); } /*-------------------------------------------------------------------*/ static void draw_mesh (Zone *z, Regn *r) { int nf, nn; Face *f; glEnable (GL_LIGHTING); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); for (nf = 0; nf < r->nfaces; nf++) { f = r->faces[nf]; if (f->flags || f->nnodes < 2) continue; if (f->nnodes == 2) glBegin (GL_LINES); else if (f->nnodes == 3) glBegin (GL_TRIANGLES); else if (f->nnodes == 4) glBegin (GL_QUADS); else glBegin (GL_POLYGON); glNormal3fv (f->normal); for (nn = 0; nn < f->nnodes; nn++) glVertex3fv (z->nodes[f->nodes[nn]]); glEnd (); } } /*-------------------------------------------------------------------*/ static void draw_shaded (Zone *z, Regn *r) { int nf, nn; Face *f; glEnable (GL_LIGHTING); glShadeModel (GL_FLAT); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); for (nf = 0; nf < r->nfaces; nf++) { f = r->faces[nf]; if (f->flags || f->nnodes < 3) continue; if (f->nnodes == 3) glBegin (GL_TRIANGLES); else if (f->nnodes == 4) glBegin (GL_QUADS); else glBegin (GL_POLYGON); glNormal3fv (f->normal); for (nn = 0; nn < f->nnodes; nn++) glVertex3fv (z->nodes[f->nodes[nn]]); glEnd (); } } /*=================================================================== * tcl interface *===================================================================*/ /*---------- CGNSopen ---------------------------------------------- * open a CGNS file - return bases *------------------------------------------------------------------*/ static int CGNSopen (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int fn, nb, idum; static char buff[33]; if (argc != 2) { Tcl_SetResult (interp, "usage: CGNSopen filename", TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); if (cgnsfn) { cg_close (cgnsfn); cgnsfn = 0; } if (cg_open (argv[1], CG_MODE_READ, &fn)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } if (cg_nbases (fn, &nb)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); cg_close (fn); return TCL_ERROR; } if (nb < 1) { Tcl_SetResult (interp, "no bases defined", TCL_STATIC); cg_close (fn); return TCL_ERROR; } nbases = nb; for (nb = 1; nb <= nbases; nb++) { if (cg_base_read (fn, nb, buff, &idum, &idum)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); cg_close (fn); return TCL_ERROR; } Tcl_AppendElement (interp, buff); } cgnsfn = fn; return TCL_OK; } /*---------- CGNSclose --------------------------------------------- * close the open CGNS file *------------------------------------------------------------------*/ static int CGNSclose (ClientData data, Tcl_Interp *interp, int argc, char **argv) { if (cgnsfn && cg_close (cgnsfn)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } cgnsfn = 0; free_all (); Tcl_ResetResult (interp); return TCL_OK; } /*---------- CGNSbase ---------------------------------------------- * set the CGNS base - return zones *------------------------------------------------------------------*/ static int CGNSbase (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int base, nz; cgsize_t sizes[9]; char buff[33]; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 2) { Tcl_SetResult (interp, "usage: CGNSbase basenum", TCL_STATIC); return TCL_ERROR; } base = atoi (argv[1]) + 1; if (base < 1 || base > nbases) { Tcl_SetResult (interp, "base number out of range", TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); cgnsbase = base; if (cg_base_read (cgnsfn, cgnsbase, BaseName, &CellDim, &PhyDim) || cg_nzones (cgnsfn, cgnsbase, &nz)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } free_all (); if (CellDim < 2 || CellDim > 3 || PhyDim < 2 || PhyDim > 3) { Tcl_SetResult (interp, "CellDim and Phydim not 2 or 3", TCL_STATIC); return TCL_ERROR; } nzones = nz; zones = (Zone *) MALLOC ("CGNSbase", nzones * sizeof(Zone)); for (nz = 1; nz <= nzones; nz++) { if (cg_zone_read (cgnsfn, cgnsbase, nz, buff, sizes)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } strcpy (zones[nz-1].name, buff); Tcl_AppendElement (interp, buff); } return TCL_OK; } /*---------- CGNSzone ---------------------------------------------- * set the CGNS zone - return regions *------------------------------------------------------------------*/ static int CGNSzone (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int i, j, zone, nr, ncoords; cgsize_t sizes[9], rng[2][3], n, nnodes; int rind[6]; CGNS_ENUMT(DataType_t) datatype; CGNS_ENUMT(ZoneType_t) zonetype; Node *nodes; float *xyz; double rad, theta, phi; char buff[65], coordtype[4]; Zone *z; #ifdef NO_CUTTING_PLANE int *tag, nf, nn; #endif static char *funcname = "CGNSzone"; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 2) { Tcl_SetResult (interp, "usage: CGNSzone zonenum", TCL_STATIC); return TCL_ERROR; } zone = atoi (argv[1]) + 1; if (zone < 1 || zone > nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } if (cg_zone_read (cgnsfn, cgnsbase, zone, buff, sizes) || cg_zone_type (cgnsfn, cgnsbase, zone, &zonetype)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } if (zonetype == CGNS_ENUMV(Structured)) { for (i = 0; i < CellDim; i++) { if (sizes[i] < 2) { Tcl_SetResult (interp, "zone dimension < 2", TCL_STATIC); return TCL_ERROR; } } } else if (zonetype != CGNS_ENUMV(Unstructured)) { Tcl_SetResult (interp, "invalid zone type", TCL_STATIC); return TCL_ERROR; } cgnszone = zone; z = &zones[zone-1]; /* get number of coordinates */ if (cg_ncoords (cgnsfn, cgnsbase, cgnszone, &ncoords)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } if (ncoords < PhyDim) { Tcl_SetResult (interp, "less than PhyDim coordinates", TCL_STATIC); return TCL_ERROR; } /* check for rind */ if (cg_goto (cgnsfn, cgnsbase, "Zone_t", zone, "GridCoordinates_t", 1, "end")) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } if ((i = cg_rind_read (rind)) != CG_OK) { if (i != CG_NODE_NOT_FOUND) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } for (i = 0; i < 6; i++) rind[i] = 0; } /* get grid coordinate range */ if (zonetype == CGNS_ENUMV(Structured)) { for (i = 0; i < 3; i++) { rng[0][i] = 1; rng[1][i] = 1; } nnodes = 1; for (i = 0; i < CellDim; i++) { rng[0][i] = rind[2*i] + 1; rng[1][i] = rind[2*i] + sizes[i]; nnodes *= sizes[i]; } } else { nnodes = sizes[0] + rind[0] + rind[1]; rng[0][0] = 1; rng[1][0] = nnodes; } /* read the nodes */ strcpy (coordtype, " "); zone_message ("reading coordinates", NULL); xyz = (float *) MALLOC (funcname, (size_t)nnodes * sizeof(float)); nodes = (Node *) MALLOC (funcname, (size_t)nnodes * sizeof(Node)); for (i = 1; i <= ncoords; i++) { if (cg_coord_info (cgnsfn, cgnsbase, cgnszone, i, &datatype, buff) || cg_coord_read (cgnsfn, cgnsbase, cgnszone, buff, CGNS_ENUMV(RealSingle), rng[0], rng[1], xyz)) { free (xyz); free (nodes); Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } if (0 == strcmp (buff, "CoordinateX") || 0 == strcmp (buff, "CoordinateR")) j = 0; else if (0 == strcmp (buff, "CoordinateY") || 0 == strcmp (buff, "CoordinateTheta")) j = 1; else if (0 == strcmp (buff, "CoordinateZ") || 0 == strcmp (buff, "CoordinatePhi")) j = 2; else continue; if (coordtype[j] == ' ' || strchr ("XYZ", buff[10]) != NULL) coordtype[j] = buff[10]; for (n = 0; n < nnodes; n++) nodes[n][j] = xyz[n]; } free (xyz); if (0 == strncmp (coordtype, "RTZ", PhyDim)) { for (n = 0; n < nnodes; n++) { rad = nodes[n][0]; theta = nodes[n][1]; nodes[n][0] = (float)(rad * cos (theta)); nodes[n][1] = (float)(rad * sin (theta)); } } else if (0 == strcmp (coordtype, "RTP")) { for (n = 0; n < nnodes; n++) { rad = nodes[n][0]; theta = nodes[n][1]; phi = nodes[n][2]; nodes[n][0] = (float)(rad * sin (theta) * cos (phi)); nodes[n][1] = (float)(rad * sin (theta) * sin (phi)); nodes[n][2] = (float)(rad * cos (theta)); } } else if (strncmp (coordtype, "XYZ", PhyDim)) { free (nodes); Tcl_SetResult (interp, "unknown coordinate system", TCL_STATIC); return TCL_ERROR; } z->nnodes = nnodes; z->nodes = nodes; /* build regions */ if (zonetype == CGNS_ENUMV(Structured)) { if (structured_zone (interp, sizes)) return TCL_ERROR; } else { if (unstructured_zone (interp)) return TCL_ERROR; } #ifdef NO_CUTTING_PLANE tag = (int *) MALLOC (funcname, nnodes * sizeof(int)); for (n = 0; n < nnodes; n++) tag[n] = -1; /* tag nodes which are actually used */ for (nn = 0, nr = 0; nr < z->nregs; nr++) { for (nf = 0; nf < z->regs[nr].nfaces; nf++) { for (n = 0; n < z->regs[nr].faces[nf]->nnodes; n++) { i = z->regs[nr].faces[nf]->nodes[n]; if (tag[i] < 0) tag[i] = nn++; } } } nodes = (Node *) MALLOC (funcname, nn * sizeof(Node)); for (n = 0; n < nnodes; n++) { if (tag[n] >= 0) { j = tag[n]; for (i = 0; i < 3; i++) nodes[j][i] = z->nodes[n][i]; } } free(z->nodes); z->nodes = nodes; z->nnodes = nn; /* re-index region faces */ for (nr = 0; nr < z->nregs; nr++) { for (nf = 0; nf < z->regs[nr].nfaces; nf++) { for (n = 0; n < z->regs[nr].faces[nf]->nnodes; n++) { i = z->regs[nr].faces[nf]->nodes[n]; z->regs[nr].faces[nf]->nodes[n] = tag[i]; } } } free(tag); #endif /* find region bounding box, edges and normals */ zone_message ("finding normals and edges", NULL); for (nr = 0; nr < z->nregs; nr++) { if (z->regs[nr].nfaces) { bounding_box (z, &z->regs[nr]); region_normals (z, &z->regs[nr]); extract_edges (&z->regs[nr]); } } Tcl_ResetResult (interp); for (nr = 0; nr < z->nregs; nr++) { switch (z->regs[nr].type) { case REG_MESH: strcpy(buff, z->regs[nr].name); break; case REG_ELEM: sprintf(buff, "/%s", z->regs[nr].name); break; case REG_1TO1: sprintf(buff, "<1to1 Connections>/%s", z->regs[nr].name); break; case REG_CONN: sprintf(buff, "/%s", z->regs[nr].name); break; case REG_HOLE: sprintf(buff, "/%s", z->regs[nr].name); break; case REG_BOCO: sprintf(buff, "/%s", z->regs[nr].name); break; case REG_BNDS: sprintf(buff, "/%s", z->regs[nr].name); break; } Tcl_AppendElement (interp, buff); } return TCL_OK; } /*---------- CGNSsummary ------------------------------------------- * return info summary string *------------------------------------------------------------------*/ static int CGNSsummary (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, nz; char *p, buff[128]; Regn *r; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc < 1 || argc > 3) { Tcl_SetResult (interp, "usage: CGNSsummary [zone [reg]]", TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); if (argc == 1) { sprintf (buff, "Physical Dim = %d, Cell Dim = %d", PhyDim, CellDim); Tcl_AppendResult (interp, buff, NULL); return TCL_OK; } nz = atoi (argv[1]); if (nz < 0 || nz >= nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } if (argc == 2) { cgsize_t sizes[9]; CGNS_ENUMT(ZoneType_t) zonetype; if (cg_zone_read (cgnsfn, cgnsbase, nz+1, buff, sizes) || cg_zone_type (cgnsfn, cgnsbase, nz+1, &zonetype)) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } Tcl_AppendResult (interp, cg_ZoneTypeName(zonetype), " Zone : ", NULL); if (zonetype == CGNS_ENUMV(Unstructured)) { sprintf (buff, "%ld vertices, %ld elements", (long)sizes[0], (long)sizes[1]); Tcl_AppendResult (interp, buff, NULL); } else { sprintf (buff, "%ld", (long)sizes[0]); for (n = 1; n < CellDim; n++) { p = buff + strlen(buff); sprintf (p, " x %ld", (long)sizes[n]); } Tcl_AppendResult (interp, buff, " vertices", NULL); } return TCL_OK; } n = atoi (argv[2]); if (n < 0 || n >= zones[nz].nregs) { Tcl_SetResult (interp, "region number out of range", TCL_STATIC); return TCL_ERROR; } r = &zones[nz].regs[n]; switch (r->type) { case REG_MESH: if (CellDim == 2) { sprintf (buff, "%ld x %ld", (long)r->data[0], (long)r->data[1]); } else { sprintf (buff, "%ld x %ld x %ld", (long)r->data[0], (long)r->data[1], (long)r->data[2]); } Tcl_AppendResult (interp, "Structured Mesh : ", buff, " vertices", NULL); break; case REG_ELEM: sprintf (buff, "%ld", (long)(r->data[2] - r->data[1] + 1)); Tcl_AppendResult (interp, cg_ElementTypeName(r->data[0]), " Element Set : ", buff, " elements", NULL); break; case REG_1TO1: if (r->data[0] == 2) sprintf (buff, "%ld", (long)(r->data[2] - r->data[1] + 1)); else if (CellDim == 2) { sprintf (buff, "%ld x %ld", (long)(r->data[3] - r->data[1] + 1), (long)(r->data[4] - r->data[2] + 1)); } else { sprintf (buff, "%ld x %ld x %ld", (long)(r->data[4] - r->data[1] + 1), (long)(r->data[5] - r->data[2] + 1), (long)(r->data[6] - r->data[3] + 1)); } Tcl_AppendResult (interp, "1to1 Connection : PointRange ", buff, " -> ", r->d_name, NULL); break; case REG_CONN: if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) sprintf (buff, " %ld", (long)r->data[3]); else if (r->data[3] == 2) sprintf (buff, " %ld", (long)(r->data[5] - r->data[4] + 1)); else if (CellDim == 2) { sprintf (buff, " %ld x %ld", (long)(r->data[6] - r->data[4] + 1), (long)(r->data[7] - r->data[5] + 1)); } else { sprintf (buff, " %ld x %ld x %ld", (long)(r->data[7] - r->data[4] + 1), (long)(r->data[8] - r->data[5] + 1), (long)(r->data[9] - r->data[6] + 1)); } Tcl_AppendResult (interp, cg_GridConnectivityTypeName(r->data[0]), " Connection : ", cg_PointSetTypeName(r->data[2]), buff, " -> ", r->d_name, NULL); break; case REG_HOLE: if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) sprintf (buff, " %ld", (long)r->data[3]); else if (r->data[3] == 2) sprintf (buff, " %ld", (long)(r->data[5] - r->data[4] + 1)); else if (CellDim == 2) { sprintf (buff, " %ld x %ld", (long)(r->data[6] - r->data[4] + 1), (long)(r->data[7] - r->data[5] + 1)); } else { sprintf (buff, " %ld x %ld x %ld", (long)(r->data[7] - r->data[4] + 1), (long)(r->data[8] - r->data[5] + 1), (long)(r->data[9] - r->data[6] + 1)); } Tcl_AppendResult (interp, "Overset Hole : ", cg_PointSetTypeName(r->data[2]), buff, NULL); break; case REG_BOCO: if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) sprintf (buff, " %ld", (long)r->data[3]); else if (r->data[3] == 2) sprintf (buff, " %ld", (long)(r->data[5] - r->data[4] + 1)); else if (CellDim == 2) { sprintf (buff, " %ld x %ld", (long)(r->data[6] - r->data[4] + 1), (long)(r->data[7] - r->data[5] + 1)); } else { sprintf (buff, " %ld x %ld x %ld", (long)(r->data[7] - r->data[4] + 1), (long)(r->data[8] - r->data[5] + 1), (long)(r->data[9] - r->data[6] + 1)); } Tcl_AppendResult (interp, cg_BCTypeName(r->data[0]), " Boundary Condition : ", cg_PointSetTypeName(r->data[2]), buff, NULL); break; case REG_BNDS: if (CellDim == 2) { sprintf (buff, "%ld x %ld", (long)(r->data[2] - r->data[0] + 1), (long)(r->data[3] - r->data[1] + 1)); } else { sprintf (buff, "%ld x %ld x %ld", (long)(r->data[3] - r->data[0] + 1), (long)(r->data[4] - r->data[1] + 1), (long)(r->data[5] - r->data[2] + 1)); } Tcl_AppendResult (interp, "Mesh Boundary : ", buff, " vertices", NULL); break; } return TCL_OK; } /*---------- CGNSgetbase ------------------------------------------- * get base properties *------------------------------------------------------------------*/ static int CGNSgetbase (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char cd[16], pd[16], nz[16]; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 1) { Tcl_SetResult (interp, "usage: CGNSgetbase", TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); sprintf (pd, "%d", PhyDim); sprintf (cd, "%d", CellDim); sprintf (nz, "%d", nzones); Tcl_AppendResult (interp, "Base Name : ", BaseName, "\nPhysical Dim: ", pd, "\nCell Dim : ", cd, "\nNumber Zones: ", nz, NULL); return TCL_OK; } /*---------- CGNSgetzone ------------------------------------------- * get zone properties *------------------------------------------------------------------*/ static int CGNSgetzone (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, ndim, zone, cnts[4]; cgsize_t sizes[9]; CGNS_ENUMT(ZoneType_t) zonetype; char *p, buff[65]; static char *cntname[] = { "Element Sections", "1to1 Connections", "General Connections", "Boundary Conditions" }; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 2) { Tcl_SetResult (interp, "usage: CGNSgetzone zonenum", TCL_STATIC); return TCL_ERROR; } zone = atoi (argv[1]) + 1; if (zone < 1 || zone > nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } if (cg_zone_read (cgnsfn, cgnsbase, zone, buff, sizes) || cg_zone_type (cgnsfn, cgnsbase, zone, &zonetype) || cg_nsections (cgnsfn, cgnsbase, zone, &cnts[0]) || cg_n1to1 (cgnsfn, cgnsbase, zone, &cnts[1]) || cg_nconns (cgnsfn, cgnsbase, zone, &cnts[2]) || cg_nbocos (cgnsfn, cgnsbase, zone, &cnts[3])) { Tcl_SetResult (interp, (char *)cg_get_error(), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); Tcl_AppendResult (interp, "Zone Name : ", buff, "\nType of Zone : ", cg_ZoneTypeName(zonetype), "\nVertex Dimensions : ", NULL); ndim = zonetype == CGNS_ENUMV(Unstructured) ? 1 : CellDim; sprintf (buff, "%ld", (long)sizes[0]); for (n = 1; n < ndim; n++) { p = buff + strlen(buff); sprintf (p, " x %ld", (long)sizes[n]); } Tcl_AppendResult (interp, buff, "\nCell Dimensions : ", NULL); sprintf (buff, "%ld", (long)sizes[ndim]); for (n = 1; n < ndim; n++) { p = buff + strlen(buff); sprintf (p, " x %ld", (long)sizes[n+CellDim]); } Tcl_AppendResult (interp, buff, NULL); for (n = 0; n < 4; n++) { sprintf (buff, "\n%-19s: %d", cntname[n], cnts[n]); Tcl_AppendResult (interp, buff, NULL); } return TCL_OK; } /*---------- CGNSgetregion ----------------------------------------- * get region properties *------------------------------------------------------------------*/ static int CGNSgetregion (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n; char buff[128]; Zone *z; Regn *r; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 3) { Tcl_SetResult (interp, "usage: CGNSgetregion zone reg", TCL_STATIC); return TCL_ERROR; } n = atoi (argv[1]); if (n < 0 || n >= nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } z = &zones[n]; n = atoi (argv[2]); if (n < 0 || n >= z->nregs) { Tcl_SetResult (interp, "region number out of range", TCL_STATIC); return TCL_ERROR; } r = &z->regs[n]; Tcl_ResetResult (interp); switch (r->type) { case REG_MESH: if (CellDim == 2) { sprintf (buff, "%ld x %ld", (long)r->data[0], (long)r->data[1]); } else { sprintf (buff, "%ld x %ld x %ld", (long)r->data[0], (long)r->data[1], (long)r->data[2]); } Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region : Structured Mesh", "\nMesh Dimensions: ", buff, NULL); break; case REG_ELEM: sprintf (buff, "%ld -> %ld", (long)r->data[1], (long)r->data[2]); Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region : Element Set", "\nElement Set Type: ", cg_ElementTypeName(r->data[0]), "\nElement Range : ", buff, NULL); if (r->data[3] || r->data[4]) { sprintf (buff, "%ld %ld", (long)r->data[3], (long)r->data[4]); Tcl_AppendResult (interp, "\nRind Elements : ", buff, NULL); } break; case REG_1TO1: Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region: 1to1 Connectivity", "\nPoint Set Type: PointRange", NULL); if (r->data[0] == 2) { sprintf (buff, "%ld -> %ld", (long)r->data[1], (long)r->data[2]); Tcl_AppendResult (interp, "\nIndex Range : ", buff, NULL); } else { sprintf (buff, "%ld -> %ld", (long)r->data[1], (long)r->data[1+CellDim]); Tcl_AppendResult (interp, "\nI Index Range : ", buff, NULL); sprintf (buff, "%ld -> %ld", (long)r->data[2], (long)r->data[2+CellDim]); Tcl_AppendResult (interp, "\nJ Index Range : ", buff, NULL); if (CellDim == 3) { sprintf (buff, "%ld -> %ld", (long)r->data[3], (long)r->data[6]); Tcl_AppendResult (interp, "\nK Index Range : ", buff, NULL); } } Tcl_AppendResult (interp, "\nDonor Zone : ", r->d_name, NULL); break; case REG_CONN: Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region : General Connectivity", "\nConnectivity Type: ", cg_GridConnectivityTypeName(r->data[0]), "\nGrid Location : ", cg_GridLocationName(r->data[1]), "\nPoint Set Type : ", cg_PointSetTypeName(r->data[2]), NULL); if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) { sprintf (buff, "%ld", (long)r->data[3]); Tcl_AppendResult (interp, "\nNumber of Points : ", buff, NULL); } else if (r->data[3] == 2) { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[5]); Tcl_AppendResult (interp, "\nIndex Range : ", buff, NULL); } else { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[4+CellDim]); Tcl_AppendResult (interp, "\nI Index Range : ", buff, NULL); sprintf (buff, "%ld -> %ld", (long)r->data[5], (long)r->data[5+CellDim]); Tcl_AppendResult (interp, "\nJ Index Range : ", buff, NULL); if (CellDim == 3) { sprintf (buff, "%ld -> %ld", (long)r->data[6], (long)r->data[9]); Tcl_AppendResult (interp, "\nK Index Range : ", buff, NULL); } } Tcl_AppendResult (interp, "\nDonor Zone : ", r->d_name, NULL); break; case REG_HOLE: sprintf(buff, "%ld", (long)r->data[0]); Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region : Overset Hole", "\nNumber Sets : ", buff, "\nGrid Location : ", cg_GridLocationName(r->data[1]), "\nPoint Set Type : ", cg_PointSetTypeName(r->data[2]), NULL); if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) { sprintf (buff, "%ld", (long)r->data[3]); Tcl_AppendResult (interp, "\nNumber of Points : ", buff, NULL); } else if (r->data[3] == 2) { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[5]); Tcl_AppendResult (interp, "\nIndex Range : ", buff, NULL); } else { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[4+CellDim]); Tcl_AppendResult (interp, "\nI Index Range : ", buff, NULL); sprintf (buff, "%ld -> %ld", (long)r->data[5], (long)r->data[5+CellDim]); Tcl_AppendResult (interp, "\nJ Index Range : ", buff, NULL); if (CellDim == 3) { sprintf (buff, "%ld -> %ld", (long)r->data[6], (long)r->data[9]); Tcl_AppendResult (interp, "\nK Index Range : ", buff, NULL); } } break; case REG_BOCO: Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region : Boundary Condition", "\nType of BC : ", cg_BCTypeName(r->data[0]), "\nGrid Location : ", cg_GridLocationName(r->data[1]), "\nPoint Set Type : ", cg_PointSetTypeName(r->data[2]), NULL); if (r->data[2] == CGNS_ENUMV(PointList) || r->data[2] == CGNS_ENUMV(ElementList)) { sprintf (buff, "%ld", (long)r->data[3]); Tcl_AppendResult (interp, "\nNumber of Points: ", buff, NULL); } else if (r->data[3] == 2) { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[5]); Tcl_AppendResult (interp, "\nIndex Range : ", buff, NULL); } else { sprintf (buff, "%ld -> %ld", (long)r->data[4], (long)r->data[4+CellDim]); Tcl_AppendResult (interp, "\nI Index Range : ", buff, NULL); sprintf (buff, "%ld -> %ld", (long)r->data[5], (long)r->data[5+CellDim]); Tcl_AppendResult (interp, "\nJ Index Range : ", buff, NULL); if (CellDim == 3) { sprintf (buff, "%ld -> %ld", (long)r->data[6], (long)r->data[9]); Tcl_AppendResult (interp, "\nK Index Range : ", buff, NULL); } } break; case REG_BNDS: strcpy (buff, r->name); Tcl_AppendResult (interp, "Region Name : ", r->name, "\nType of Region: Mesh Boundary", NULL); sprintf (buff, "%ld -> %ld", (long)r->data[0], (long)r->data[CellDim]); Tcl_AppendResult (interp, "\nI Index Range : ", buff, NULL); sprintf (buff, "%ld -> %ld", (long)r->data[1], (long)r->data[1+CellDim]); Tcl_AppendResult (interp, "\nJ Index Range : ", buff, NULL); if (CellDim == 3) { sprintf (buff, "%ld -> %ld", (long)r->data[2], (long)r->data[5]); Tcl_AppendResult (interp, "\nK Index Range : ", buff, NULL); } break; } return TCL_OK; } /*---------- CGNSregiondim ----------------------------------------- * return dimension of a region *------------------------------------------------------------------*/ static int CGNSregiondim (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n; char buff[16]; Zone *z; if (!cgnsfn) { Tcl_SetResult (interp, "CGNS file not open", TCL_STATIC); return TCL_ERROR; } if (argc != 3) { Tcl_SetResult (interp, "usage: CGNSregtype zone reg", TCL_STATIC); return TCL_ERROR; } n = atoi (argv[1]); if (n < 0 || n >= nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } z = &zones[n]; n = atoi (argv[2]); if (n < 0 || n >= z->nregs) { Tcl_SetResult (interp, "region number out of range", TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult (interp); if (!z->regs[n].dim) { if (*(z->regs[n].errmsg)) Tcl_SetResult (interp, z->regs[n].errmsg, TCL_STATIC); return TCL_ERROR; } sprintf (buff, "%d", z->regs[n].dim); Tcl_AppendResult (interp, buff, NULL); return TCL_OK; } /*---------- CGNSbounds -------------------------------------------- * get bounding box *------------------------------------------------------------------*/ static void transform_bounds (float m[16], float bb[3][2]) { int i, j; float x, y, z, bbox[3][2]; x = m[0] * bb[0][0] + m[4] * bb[1][0] + m[8] * bb[2][0] + m[12]; y = m[1] * bb[0][0] + m[5] * bb[1][0] + m[9] * bb[2][0] + m[13]; z = m[2] * bb[0][0] + m[6] * bb[1][0] + m[10] * bb[2][0] + m[14]; bbox[0][0] = bbox[0][1] = x; bbox[1][0] = bbox[1][1] = y; bbox[2][0] = bbox[2][1] = z; x = m[0] * bb[0][1] + m[4] * bb[1][0] + m[8] * bb[2][0] + m[12]; y = m[1] * bb[0][1] + m[5] * bb[1][0] + m[9] * bb[2][0] + m[13]; z = m[2] * bb[0][1] + m[6] * bb[1][0] + m[10] * bb[2][0] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][0] + m[4] * bb[1][1] + m[8] * bb[2][0] + m[12]; y = m[1] * bb[0][0] + m[5] * bb[1][1] + m[9] * bb[2][0] + m[13]; z = m[2] * bb[0][0] + m[6] * bb[1][1] + m[10] * bb[2][0] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][1] + m[4] * bb[1][1] + m[8] * bb[2][0] + m[12]; y = m[1] * bb[0][1] + m[5] * bb[1][1] + m[9] * bb[2][0] + m[13]; z = m[2] * bb[0][1] + m[6] * bb[1][1] + m[10] * bb[2][0] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][0] + m[4] * bb[1][0] + m[8] * bb[2][1] + m[12]; y = m[1] * bb[0][0] + m[5] * bb[1][0] + m[9] * bb[2][1] + m[13]; z = m[2] * bb[0][0] + m[6] * bb[1][0] + m[10] * bb[2][1] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][1] + m[4] * bb[1][0] + m[8] * bb[2][1] + m[12]; y = m[1] * bb[0][1] + m[5] * bb[1][0] + m[9] * bb[2][1] + m[13]; z = m[2] * bb[0][1] + m[6] * bb[1][0] + m[10] * bb[2][1] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][0] + m[4] * bb[1][1] + m[8] * bb[2][1] + m[12]; y = m[1] * bb[0][0] + m[5] * bb[1][1] + m[9] * bb[2][1] + m[13]; z = m[2] * bb[0][0] + m[6] * bb[1][1] + m[10] * bb[2][1] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; x = m[0] * bb[0][1] + m[4] * bb[1][1] + m[8] * bb[2][1] + m[12]; y = m[1] * bb[0][1] + m[5] * bb[1][1] + m[9] * bb[2][1] + m[13]; z = m[2] * bb[0][1] + m[6] * bb[1][1] + m[10] * bb[2][1] + m[14]; if (bbox[0][0] > x) bbox[0][0] = x; if (bbox[0][1] < x) bbox[0][1] = x; if (bbox[1][0] > y) bbox[1][0] = y; if (bbox[1][1] < y) bbox[1][1] = y; if (bbox[2][0] > z) bbox[2][0] = z; if (bbox[2][1] < z) bbox[2][1] = z; for (i = 0; i < 3; i++) for (j = 0; j < 2; j++) bb[i][j] = bbox[i][j]; } /*-------------------------------------------------------------------*/ static int CGNSbounds (ClientData data, Tcl_Interp *interp, int argc, char **argv) { float bbox[3][2], matrix[16]; int n, all = 0; CONST char **args; char sbb[65]; if (argc > 1) all = atoi(argv[1]); get_bounds (all, bbox); if (argc > 2) { if (TCL_OK != Tcl_SplitList (interp, argv[2], &n, &args)) return TCL_ERROR; for (n = 0; n < 16; n++) matrix[n] = (float) atof (args[n]); Tcl_Free ((char *)args); transform_bounds (matrix, bbox); } Tcl_ResetResult (interp); for (n = 0; n < 3; n++) { sprintf (sbb, "%f %f", bbox[n][0], bbox[n][1]); Tcl_AppendElement (interp, sbb); } return TCL_OK; } /*---------- OGLregion --------------------------------------------- * create OGL display list for region *------------------------------------------------------------------*/ static int OGLregion (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int zone, regn, nc; CONST char **args; Zone *z; Regn *r; static char slist[17]; if (argc != 5) { Tcl_SetResult (interp, "usage: OGLregion zone region mode color", TCL_STATIC); return TCL_ERROR; } zone = atoi (argv[1]); if (zone < 0 || zone >= nzones) { Tcl_SetResult (interp, "zone number out of range", TCL_STATIC); return TCL_ERROR; } z = &zones[zone]; regn = atoi (argv[2]); if (regn < 0 || regn >= z->nregs) { Tcl_SetResult (interp, "region number out of range", TCL_STATIC); return TCL_ERROR; } r = &z->regs[regn]; if (r->nfaces || r->nedges) { r->mode = atoi (argv[3]); if (TCL_OK != Tcl_SplitList (interp, argv[4], &nc, &args)) return TCL_ERROR; if (nc != 3) { Tcl_Free ((char *)args); Tcl_SetResult (interp, "invalid color", TCL_STATIC); return TCL_ERROR; } for (nc = 0; nc < 3; nc++) r->color[nc] = (float)atof (args[nc]); r->color[3] = 1.0; Tcl_Free ((char *)args); if (!r->dlist) r->dlist = glGenLists (1); glNewList (r->dlist, GL_COMPILE); glColor3fv (r->color); glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, r->color); if (r->nfaces) { switch (r->mode) { case 1: draw_outlines (z, r); break; case 2: draw_mesh (z, r); break; case 3: draw_shaded (z, r); break; default: r->mode = 0; break; } } else if (r->mode < 1 || r->mode > 3) { r->mode = 0; } else { draw_outlines (z, r); } glEndList (); } sprintf (slist, "%d", r->dlist); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } /*---------- OGLaxis ----------------------------------------------- * create OGL display list for axis *------------------------------------------------------------------*/ #define CHAR_W 8 #define CHAR_H 13 static GLubyte x_raster[] = { 0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3 }; static GLubyte y_raster[] = { 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3 }; static GLubyte z_raster[] = { 0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff }; /*-------------------------------------------------------------------*/ static int OGLaxis (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int vis; float bbox[3][2]; static char slist[17]; if (argc < 2 || argc > 3) { Tcl_SetResult (interp, "usage: OGLaxis visible [bounds]", TCL_STATIC); return TCL_ERROR; } vis = atoi (argv[1]); if (!AxisDL) AxisDL = glGenLists (1); glNewList (AxisDL, GL_COMPILE); if (vis) { if (argc == 3) { int nb, n = 0; CONST char **args; if (TCL_OK != Tcl_SplitList (interp, argv[2], &nb, &args)) return TCL_ERROR; if (nb == 3) { for (n = 0; n < nb; n++) { if (sscanf (args[n], "%f %f", &bbox[n][0], &bbox[n][1]) != 2) break; } } Tcl_Free ((char *)args); if (n != 3) { Tcl_SetResult (interp, "invalid bounding box", TCL_STATIC); return TCL_ERROR; } } else get_bounds (0, bbox); glLineWidth (3.0); glDisable (GL_LIGHTING); glShadeModel (GL_FLAT); glBegin (GL_LINES); glColor3f (1.0, 0.0, 0.0); glVertex3f (bbox[0][0], bbox[1][0], bbox[2][0]); glVertex3f (bbox[0][1], bbox[1][0], bbox[2][0]); glColor3f (1.0, 1.0, 0.0); glVertex3f (bbox[0][0], bbox[1][0], bbox[2][0]); glVertex3f (bbox[0][0], bbox[1][1], bbox[2][0]); glColor3f (0.0, 1.0, 0.0); glVertex3f (bbox[0][0], bbox[1][0], bbox[2][0]); glVertex3f (bbox[0][0], bbox[1][0], bbox[2][1]); glEnd (); glLineWidth (1.0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glColor3f (1.0, 0.0, 0.0); glRasterPos3f (bbox[0][1], bbox[1][0], bbox[2][0]); glBitmap (CHAR_W, CHAR_H, -0.5 * (float)CHAR_W, 0.5 * (float)CHAR_H, 0.0, 0.0, x_raster); glColor3f (1.0, 1.0, 0.0); glRasterPos3f (bbox[0][0], bbox[1][1], bbox[2][0]); glBitmap (CHAR_W, CHAR_H, -0.5 * (float)CHAR_W, 0.5 * (float)CHAR_H, 0.0, 0.0, y_raster); glColor3f (0.0, 1.0, 0.0); glRasterPos3f (bbox[0][0], bbox[1][0], bbox[2][1]); glBitmap (CHAR_W, CHAR_H, -0.5 * (float)CHAR_W, 0.5 * (float)CHAR_H, 0.0, 0.0, z_raster); } glEndList (); sprintf (slist, "%d", AxisDL); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } /*-------------------------------------------------------------------*/ static int OGLcolor (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int index, i, j; double r, g, b; double h, v, s; static char color[256]; static double huemap[12] = {0,1,2,3,4,5,0.5,1.25,2.65,3.4,4.5,5.5}; if (argc != 2) { Tcl_SetResult (interp, "usage: OGLcolor index", TCL_STATIC); return TCL_ERROR; } index = abs(atoi(argv[1])) % 132; h = huemap[index % 12]; i = (int)h; h -= (double)i; j = index / 12; if ((j % 2) == 0) { v = 1.0; s = 1.0 - sqrt((double)j / 22.0); } else { v = 1.0 - sqrt((double)j / 44.0); s = 1.0; } r = g = b = 0.0; switch (i) { case 6: h = 0.0; case 0: r = v; g = v * (1.0 - (s * (1.0 - h))); b = v * (1.0 - s); break; case 1: r = v * (1.0 - (s * h)); g = v; b = v * (1.0 - s); break; case 2: r = v * (1.0 - s); g = v; b = v * (1.0 - (s * (1.0 - h))); break; case 3: r = v * (1.0 - s); g = v * (1.0 - (s * h)); b = v; break; case 4: r = v * (1.0 - (s * (1.0 - h))); g = v * (1.0 - s); b = v; break; case 5: r = v; g = v * (1.0 - s); b = v * (1.0 - (s * h)); break; } if (r < 0.0) r = 0.0; if (r > 1.0) r = 1.0; if (g < 0.0) g = 0.0; if (g > 1.0) g = 1.0; if (b < 0.0) b = 0.0; if (b > 1.0) b = 1.0; sprintf(color, "%g %g %g", r, g, b); Tcl_SetResult (interp, color, TCL_STATIC); return TCL_OK; } /*============================================================== * cutting plane routines *==============================================================*/ #ifndef NO_CUTTING_PLANE /*------------------------------------------------------------------*/ static void init_cutplane (float plane[4]) { int nz, nr; for (nz = 0; nz < nzones; nz++) { for (nr = 0; nr < zones[nz].nregs; nr++) { if (zones[nz].regs[nr].cut.nelems) { free (zones[nz].regs[nr].cut.elems); zones[nz].regs[nr].cut.nelems = 0; } if (zones[nz].regs[nr].cut.nedges) { free (zones[nz].regs[nr].cut.edges); zones[nz].regs[nr].cut.nedges = 0; } } } if (cutplane.nnodes) free (cutplane.nodes); cutplane.nelems = 0; cutplane.nedges = 0; cutplane.nnodes = 0; for (nr = 0; nr < 4; nr++) cutplane.plane[nr] = plane[nr]; } /*------------------------------------------------------------------*/ static int classify_element (Zone *z, int nnodes, cgsize_t *nodeid) { int n, index = 0; int mask = (1 << (nnodes - 1)) - 1; float *node; double s; for (n = 0; n < nnodes; n++) { node = z->nodes[nodeid[n]]; s = node[0] * cutplane.plane[0] + node[1] * cutplane.plane[1] + node[2] * cutplane.plane[2] - cutplane.plane[3]; if (s >= 0.0) index |= (1 << n); } if (index > mask) index ^= ((mask << 1) | 1); return index; } /*------------------------------------------------------------------*/ static int classify_polygon (Zone *z, int nnodes, cgsize_t *nodeid) { int n, start, diff; float *node; double s; node = z->nodes[nodeid[0]]; s = node[0] * cutplane.plane[0] + node[1] * cutplane.plane[1] + node[2] * cutplane.plane[2] - cutplane.plane[3]; start = s >= 0.0 ? 1 : -1; for (n = 1; n < nnodes; n++) { node = z->nodes[nodeid[n]]; s = node[0] * cutplane.plane[0] + node[1] * cutplane.plane[1] + node[2] * cutplane.plane[2] - cutplane.plane[3]; diff = start * (s >= 0.0 ? 1 : -1); if (diff < 0) return 1; } return 0; } /*------------------------------------------------------------------*/ static cgsize_t find_elements () { #define ELEM_INC 50 int nz, nnodes, nn, nr, nf; cgsize_t n, ne, maxelems, nelems, *elems; CGNS_ENUMT(ElementType_t) type; Zone *z; Regn *r; Face *f; for (nz = 0; nz < nzones; nz++) { z = &zones[nz]; for (nr = 0; nr < z->nregs; nr++) { r = &z->regs[nr]; if (r->dim < 2 || (r->mode == 0 && !ignorevis)) continue; type = r->elemtype; cg_npe(type, &nnodes); maxelems = nelems = 0; elems = NULL; if (type == CGNS_ENUMV(NGON_n)) { for (n = 0, ne = 0; ne < r->nelems; ne++) { nn = r->elem_offsets[ne+1] - r->elem_offsets[ne]; if (nn > 2 && classify_polygon(z, nn, &r->elems[n])) { if (nelems >= maxelems) { maxelems += ELEM_INC; elems = (cgsize_t *) REALLOC ("find_elements", (size_t)maxelems * sizeof(cgsize_t), elems); } elems[nelems++] = ne; } n += nn; } } else if (type == CGNS_ENUMV(NFACE_n)) { for (n = 0, ne = 0; ne < r->nelems; ne++) { nf = r->elem_offsets[ne+1] - r->elem_offsets[ne]; for (nn = 0; nn < nf; nn++) { f = r->poly[abs(r->elems[n+nn])-1]; if (f->nnodes > 2 && classify_polygon(z, f->nnodes, f->nodes)) { if (nelems >= maxelems) { maxelems += ELEM_INC; elems = (cgsize_t *) REALLOC ("find_elements", (size_t)maxelems * sizeof(cgsize_t), elems); } elems[nelems++] = ne; break; } } n += nf; } } else { for (n = 0, ne = 0; ne < r->nelems; ne++) { if (r->elemtype == CGNS_ENUMV(MIXED)) { type = (CGNS_ENUMT(ElementType_t))r->elems[n++]; cg_npe(type, &nnodes); } switch (type) { case CGNS_ENUMV(TRI_3): case CGNS_ENUMV(TRI_6): case CGNS_ENUMV(TRI_9): case CGNS_ENUMV(TRI_10): case CGNS_ENUMV(TRI_12): case CGNS_ENUMV(TRI_15): nn = 3; break; case CGNS_ENUMV(QUAD_4): case CGNS_ENUMV(QUAD_8): case CGNS_ENUMV(QUAD_9): case CGNS_ENUMV(QUAD_12): case CGNS_ENUMV(QUAD_16): case CGNS_ENUMV(QUAD_P4_16): case CGNS_ENUMV(QUAD_25): case CGNS_ENUMV(TETRA_4): case CGNS_ENUMV(TETRA_10): case CGNS_ENUMV(TETRA_16): case CGNS_ENUMV(TETRA_20): case CGNS_ENUMV(TETRA_22): case CGNS_ENUMV(TETRA_34): case CGNS_ENUMV(TETRA_35): nn = 4; break; case CGNS_ENUMV(PYRA_5): case CGNS_ENUMV(PYRA_13): case CGNS_ENUMV(PYRA_14): case CGNS_ENUMV(PYRA_21): case CGNS_ENUMV(PYRA_29): case CGNS_ENUMV(PYRA_30): case CGNS_ENUMV(PYRA_P4_29): case CGNS_ENUMV(PYRA_50): case CGNS_ENUMV(PYRA_55): nn = 5; break; case CGNS_ENUMV(PENTA_6): case CGNS_ENUMV(PENTA_15): case CGNS_ENUMV(PENTA_18): case CGNS_ENUMV(PENTA_24): case CGNS_ENUMV(PENTA_38): case CGNS_ENUMV(PENTA_40): case CGNS_ENUMV(PENTA_33): case CGNS_ENUMV(PENTA_66): case CGNS_ENUMV(PENTA_75): nn = 6; break; case CGNS_ENUMV(HEXA_8): case CGNS_ENUMV(HEXA_20): case CGNS_ENUMV(HEXA_27): case CGNS_ENUMV(HEXA_32): case CGNS_ENUMV(HEXA_56): case CGNS_ENUMV(HEXA_64): case CGNS_ENUMV(HEXA_44): case CGNS_ENUMV(HEXA_98): case CGNS_ENUMV(HEXA_125): nn = 8; break; default: nn = 0; break; } if (nn && classify_element(z, nn, &r->elems[n])) { if (nelems >= maxelems) { maxelems += ELEM_INC; elems = (cgsize_t *) REALLOC ("find_elements", (size_t)maxelems * sizeof(cgsize_t), elems); } if (r->elemtype == CGNS_ENUMV(MIXED)) elems[nelems] = n - 1; else elems[nelems] = n; nelems++; } n += nnodes; } } r->cut.nelems = nelems; r->cut.elems = elems; cutplane.nelems += nelems; } } return cutplane.nelems; } /*-------------------------------------------------------------------*/ static int compare_cut_node (void *v1, void *v2) { int i; CutNode *c1 = (CutNode *)v1; CutNode *c2 = (CutNode *)v2; for (i = 0; i < 3; i++) { if (c1->nodes[i] != c2->nodes[i]) return (int)(c1->nodes[i] - c2->nodes[i]); } return 0; } /*-------------------------------------------------------------------*/ static size_t hash_cut_node (void *v) { CutNode *c = (CutNode *)v; return ((size_t)(c->nodes[0] + c->nodes[1] + c->nodes[2])); } /*-------------------------------------------------------------------*/ static void get_cut_node (void *v) { int i; CutNode *c = (CutNode *)v; Zone *z = &zones[c->nodes[0]]; float *n, *n1, *n2; n = cutplane.nodes[c->id]; n1 = z->nodes[c->nodes[1]]; n2 = z->nodes[c->nodes[2]]; for (i = 0; i < 3; i++) n[i] = n1[i] + c->ratio * (n2[i] - n1[i]); free (c); } /*-------------------------------------------------------------------*/ static size_t get_cut_edge (void *ve, void *vc) { Edge *e = (Edge *)ve; CutData *c = (CutData *)vc; c->edges[c->nedges].nodes[0] = e->nodes[0]; c->edges[c->nedges].nodes[1] = e->nodes[1]; (c->nedges)++; return 1; } /*----- tri elements -----*/ #define TRI_SIZE 3 #define TRI_EDGES 3 static int triCuts[TRI_SIZE+1][4] = { {0}, {2,0,2, 0}, {2,0,1, 0}, {2,1,2, 0} }; static int triEdges[TRI_EDGES][2] = { {0,1}, {1,2}, {2,0} }; /*----- quad elements -----*/ #define QUAD_SIZE 7 #define QUAD_EDGES 4 static int quadCuts[QUAD_SIZE+1][4] = { {0}, {2,0,3, 0}, {2,0,1, 0}, {2,1,3, 0}, {2,1,2, 0}, {2,0,3, 0}, {2,0,2, 0}, {2,2,3, 0} }; static int quadEdges[QUAD_EDGES][2] = { {0,1}, {1,2}, {2,3}, {3,0} }; /*----- tet elements -----*/ #define TET_SIZE 7 #define TET_EDGES 6 static int tetCuts[TET_SIZE+1][6] = { {0}, {3,0,3,2, 0}, {3,0,1,4, 0}, {4,1,4,3,2, 0}, {3,1,2,5, 0}, {4,0,3,5,1, 0}, {4,0,2,5,4, 0}, {3,3,5,4, 0} }; static int tetEdges[TET_EDGES][2] = { {0,1}, {1,2}, {2,0}, {0,3}, {1,3}, {2,3} }; /*----- pyramid elements -----*/ #define PYR_SIZE 15 #define PYR_EDGES 8 static int pyrCuts[PYR_SIZE+1][9] = { {0}, {3,0,4,3, 0}, {3,0,1,5, 0}, {4,1,5,4,3, 0}, {3,1,2,6, 0}, {3,0,4,3, 3,1,2,6, 0}, {4,0,2,6,5, 0}, {5,3,2,6,5,4, 0}, {3,2,3,7, 0}, {4,0,4,7,2, 0}, {3,2,3,7, 3,0,1,5, 0}, {5,1,5,4,7,2, 0}, {4,1,3,7,6, 0}, {5,0,4,7,6,1, 0}, {5,0,3,7,6,5, 0}, {4,4,7,6,5, 0}, }; static int pyrEdges[PYR_EDGES][2] = { {0,1}, {1,2}, {2,3}, {3,0}, {0,4}, {1,4}, {2,4}, {3,4} }; /*----- wedge elements -----*/ #define WDG_SIZE 31 #define WDG_EDGES 9 static int wdgCuts[WDG_SIZE+1][10] = { {0}, {3,0,3,2, 0}, {3,0,1,4, 0}, {4,1,4,3,2, 0}, {3,1,2,5, 0}, {4,0,3,5,1, 0}, {4,0,2,5,4, 0}, {3,3,5,4, 0}, {3,3,6,8, 0}, {4,0,6,8,2, 0}, {3,3,6,8, 3,0,1,4, 0}, {5,1,4,6,8,2, 0}, {3,3,6,8, 3,1,2,5, 0}, {5,0,6,8,5,1, 0}, {3,3,6,8, 4,0,2,5,4, 0}, {4,4,6,8,5, 0}, {3,4,7,6, 0}, {3,4,7,6, 3,0,3,2, 0}, {4,0,1,7,6, 0}, {5,1,7,6,3,2, 0}, {3,4,7,6, 3,1,2,5, 0}, {3,4,7,6, 4,0,3,5,1, 0}, {5,0,2,5,7,6, 0}, {4,3,5,7,6, 0}, {4,3,4,7,8, 0}, {5,0,4,7,8,2, 0}, {5,0,1,7,8,3, 0}, {4,1,7,8,2, 0}, {4,3,4,7,8, 3,1,2,5, 0}, {3,0,4,1, 3,5,7,8, 0}, {3,0,2,3, 3,5,7,8, 0}, {3,5,7,8, 0} }; static int wdgEdges[WDG_EDGES][2] = { {0,1}, {1,2}, {2,0}, {0,3}, {1,4}, {2,5}, {3,4}, {4,5}, {5,3} }; /*----- hex elements -----*/ #define HEX_SIZE 127 #define HEX_EDGES 12 static int hexCuts[HEX_SIZE+1][17] = { {0}, {3,3,0,4, 0}, {3,0,1,5, 0}, {4,3,1,5,4, 0}, {3,1,2,6, 0}, {3,3,0,4, 3,1,2,6, 0}, {4,0,2,6,5, 0}, {5,3,2,6,5,4, 0}, {3,3,7,2, 0}, {4,0,4,7,2, 0}, {3,0,1,5, 3,3,7,2, 0}, {5,4,7,2,1,5, 0}, {4,3,7,6,1, 0}, {5,0,4,7,6,1, 0}, {5,0,3,7,6,5, 0}, {4,7,6,5,4, 0}, {3,4,11,8, 0}, {4,0,8,11,3, 0}, {3,0,1,5, 3,4,11,8, 0}, {5,3,11,8,5,1, 0}, {3,1,2,6, 3,4,11,8, 0}, {4,0,8,11,3, 3,1,2,6, 0}, {4,0,2,6,5, 3,4,11,8, 0}, {6,3,2,6,5,8,11, 0}, {3,3,7,2, 3,4,11,8, 0}, {5,0,2,7,11,8, 0}, {3,0,1,5, 3,3,7,2, 3,4,11,8, 0}, {6,2,1,5,8,11,7, 0}, {4,3,7,6,1, 3,4,11,8, 0}, {6,0,8,11,7,6,1, 0}, {5,0,3,7,6,5, 3,4,11,8, 0}, {5,11,7,6,5,8, 0}, {3,8,9,5, 0}, {3,8,9,5, 3,3,0,4, 0}, {4,0,8,9,1, 0}, {5,4,3,1,9,8, 0}, {3,8,9,5, 3,1,2,6, 0}, {3,1,9,5, 3,3,0,4, 3,1,2,6, 0}, {5,0,2,6,9,8, 0}, {6,3,2,6,9,8,4, 0}, {3,8,9,5, 3,3,7,2, 0}, {4,0,4,7,2, 3,8,9,5, 0}, {4,0,8,9,1, 3,3,7,2, 0}, {6,4,7,2,1,9,8, 0}, {4,3,7,6,1, 3,8,9,5, 0}, {5,7,6,1,0,4, 3,8,9,5, 0}, {6,0,3,7,6,9,8, 0}, {5,4,7,6,9,8, 0}, {4,4,11,9,5, 0}, {5,0,3,11,9,5, 0}, {5,0,4,11,9,1, 0}, {4,3,1,9,11, 0}, {4,4,11,9,5, 3,1,2,6, 0}, {6,0,3,11,9,6,2, 0}, {6,0,2,6,9,11,4, 0}, {5,3,2,6,9,11, 0}, {4,4,11,9,5, 3,3,7,2, 0}, {6,0,2,7,11,9,5, 0}, {5,11,9,1,0,4, 3,3,7,2, 0}, {5,11,7,2,1,9, 0}, {4,3,7,6,1, 4,4,11,9,5, 0}, {4,11,7,6,9, 3,0,1,5, 0}, {4,11,7,6,9, 3,3,0,4, 0}, {4,11,7,6,9, 0}, {3,9,10,6, 0}, {3,9,10,6, 3,3,0,4, 0}, {3,9,10,6, 3,0,1,5, 0}, {4,4,3,1,5, 3,9,10,6, 0}, {4,2,1,9,10, 0}, {4,2,1,9,10, 3,3,0,4, 0}, {5,0,2,10,9,5, 0}, {6,3,2,10,9,5,4, 0}, {3,3,7,2, 3,9,10,6, 0}, {4,7,2,0,4, 3,9,10,6, 0}, {3,0,1,5, 3,2,3,7, 3,9,10,6, 0}, {4,4,7,10,9, 4,1,2,6,5, 0}, {5,3,7,10,9,1, 0}, {6,4,7,10,9,1,0, 0}, {6,3,7,10,9,5,0, 0}, {5,4,7,10,9,5, 0}, {3,4,11,8, 3,9,10,6, 0}, {4,0,8,11,3, 3,9,10,6, 0}, {3,0,1,5, 3,4,11,8, 3,9,10,6, 0}, {5,3,11,10,6,1, 3,1,9,5, 0}, {4,1,2,10,9, 3,4,11,8, 0}, {4,3,11,10,2, 4,0,8,9,1, 0}, {5,4,11,10,2,0, 3,8,9,5, 0}, {4,3,11,10,2, 3,8,9,5, 0}, {3,3,7,2, 3,9,10,6, 3,4,11,8, 0}, {5,0,2,6,9,8, 3,11,7,10, 0}, {3,0,4,3, 3,11,7,10, 3,1,2,6, 3,8,9,5, 0}, {3,1,9,5, 3,11,7,10, 3,1,2,6, 0}, {5,3,1,9,8,4, 3,11,7,10, 0}, {4,0,8,9,1, 3,11,7,10, 0}, {3,11,7,10, 3,8,9,5, 3,3,0,4, 0}, {3,11,7,10, 3,8,9,5, 0}, {4,8,10,6,5, 0}, {4,8,10,6,5, 3,3,0,4, 0}, {5,0,8,10,6,1, 0}, {6,3,4,8,10,6,1, 0}, {5,10,2,1,5,8, 0}, {5,3,2,10,8,4, 3,0,1,5, 0}, {4,0,8,10,2, 0}, {5,3,2,10,8,4, 0}, {4,8,10,6,5, 3,3,7,2, 0}, {4,4,7,10,8, 4,0,2,6,5, 0}, {5,3,7,10,8,0, 3,1,2,6, 0}, {4,4,7,10,8, 3,1,2,6, 0}, {6,3,7,10,8,5,1, 0}, {4,4,7,10,8, 3,0,1,5, 0}, {5,3,7,10,8,0, 0}, {4,4,7,10,8, 0}, {5,4,11,10,6,5, 0}, {6,0,3,11,10,6,5, 0}, {6,4,11,10,6,1,0, 0}, {5,3,11,10,6,1, 0}, {6,4,11,10,2,1,5, 0}, {4,3,11,10,2, 3,0,1,5, 0}, {5,4,11,10,2,0, 0}, {4,11,10,2,3, 0}, {5,3,2,6,5,4, 3,11,7,10, 0}, {4,0,2,6,5, 3,11,7,10, 0}, {3,3,0,4, 3,1,2,6, 3,11,7,10, 0}, {3,1,2,6, 3,11,7,10, 0}, {4,4,3,1,5, 3,11,7,10, 0}, {3,0,1,5, 3,11,7,10, 0}, {3,11,7,10, 3,3,0,4, 0}, {3,11,7,10, 0} }; static int hexEdges[HEX_EDGES][2] = { {0,1}, {1,2}, {2,3}, {3,0}, {0,4}, {1,5}, {2,6}, {3,7}, {4,5}, {5,6}, {6,7}, {7,4} }; static int n_cut_nodes; static HASH *cut_hash; /*------------------------------------------------------------------*/ static void intersect_polygon (int zonenum, int nnodes, cgsize_t *nodeid, HASH *edgehash) { int i, n, nn, i1, i2; cgsize_t id = -1; float *node; double s1, s2; CutNode cnode, *cn; Edge edge, *ep; Zone *z = &zones[zonenum]; static char *funcname = "intersect_polygon"; if (nnodes < 3) return; node = z->nodes[nodeid[0]]; for (s1 = 0.0, i = 0; i < 3; i++) s1 += (node[i] * cutplane.plane[i]); i1 = (s1 - cutplane.plane[3]) >= 0.0 ? 1 : -1; for (n = 1; n <= nnodes; n++) { nn = n % nnodes; node = z->nodes[nodeid[nn]]; for (s2 = 0.0, i = 0; i < 3; i++) s2 += (node[i] * cutplane.plane[i]); i2 = (s2 - cutplane.plane[3]) >= 0.0 ? 1 : -1; if (i1 * i2 < 0) { cnode.nodes[0] = zonenum; if (nodeid[n-1] < nodeid[nn]) { cnode.nodes[1] = nodeid[n-1]; cnode.nodes[2] = nodeid[nn]; if (s1 == s2) cnode.ratio = 0.0; else cnode.ratio = (float)((cutplane.plane[3] - s1) / (s2 - s1)); } else { cnode.nodes[1] = nodeid[nn]; cnode.nodes[2] = nodeid[n-1]; if (s1 == s2) cnode.ratio = 0.0; else cnode.ratio = (float)((cutplane.plane[3] - s2) / (s1 - s2)); } cn = (CutNode *) HashFind (cut_hash, &cnode); if (cn == NULL) { cn = (CutNode *) MALLOC (funcname, sizeof(CutNode)); for (i = 0; i < 3; i++) cn->nodes[i] = cnode.nodes[i]; cn->id = n_cut_nodes++; cn->ratio = cnode.ratio; (void) HashAdd (cut_hash, cn); } if (id >= 0) { edge.nodes[0] = id; edge.nodes[1] = cn->id; ep = (Edge *) HashFind (edgehash, &edge); if (NULL == ep) { ep = (Edge *) MALLOC (funcname, sizeof(Edge)); ep->nodes[0] = edge.nodes[0]; ep->nodes[1] = edge.nodes[1]; (void) HashAdd (edgehash, ep); } } id = cn->id; } s1 = s2; i1 = i2; } } /*------------------------------------------------------------------*/ static void intersect_element (int zonenum, CGNS_ENUMT(ElementType_t) elemtype, cgsize_t *nodeid, HASH *edgehash) { int i, n, index, nn, nc, *cuts; int edgemap[HEX_EDGES][2], ids[7]; cgsize_t swap; double s1, s2; float *node; CutNode cnode, *cn; Edge edge, *ep; Zone *z = &zones[zonenum]; static char *funcname = "intersect_element"; /* get intersection lookup table */ switch (elemtype) { case CGNS_ENUMV(TRI_3): case CGNS_ENUMV(TRI_6): case CGNS_ENUMV(TRI_9): case CGNS_ENUMV(TRI_10): case CGNS_ENUMV(TRI_12): case CGNS_ENUMV(TRI_15): index = classify_element(z, 3, nodeid); if (index < 1 || index > TRI_SIZE) return; cuts = triCuts[index]; for (n = 0; n < TRI_EDGES; n++) { edgemap[n][0] = triEdges[n][0]; edgemap[n][1] = triEdges[n][1]; } break; case CGNS_ENUMV(QUAD_4): case CGNS_ENUMV(QUAD_8): case CGNS_ENUMV(QUAD_9): case CGNS_ENUMV(QUAD_12): case CGNS_ENUMV(QUAD_16): case CGNS_ENUMV(QUAD_P4_16): case CGNS_ENUMV(QUAD_25): index = classify_element(z, 4, nodeid); if (index < 1 || index > QUAD_SIZE) return; cuts = quadCuts[index]; for (n = 0; n < QUAD_EDGES; n++) { edgemap[n][0] = quadEdges[n][0]; edgemap[n][1] = quadEdges[n][1]; } break; case CGNS_ENUMV(TETRA_4): case CGNS_ENUMV(TETRA_10): case CGNS_ENUMV(TETRA_16): case CGNS_ENUMV(TETRA_20): case CGNS_ENUMV(TETRA_22): case CGNS_ENUMV(TETRA_34): case CGNS_ENUMV(TETRA_35): index = classify_element(z, 4, nodeid); if (index < 1 || index > TET_SIZE) return; cuts = tetCuts[index]; for (n = 0; n < TET_EDGES; n++) { edgemap[n][0] = tetEdges[n][0]; edgemap[n][1] = tetEdges[n][1]; } break; case CGNS_ENUMV(PYRA_5): case CGNS_ENUMV(PYRA_13): case CGNS_ENUMV(PYRA_14): case CGNS_ENUMV(PYRA_21): case CGNS_ENUMV(PYRA_29): case CGNS_ENUMV(PYRA_30): case CGNS_ENUMV(PYRA_P4_29): case CGNS_ENUMV(PYRA_50): case CGNS_ENUMV(PYRA_55): index = classify_element(z, 5, nodeid); if (index < 1 || index > PYR_SIZE) return; cuts = pyrCuts[index]; for (n = 0; n < PYR_EDGES; n++) { edgemap[n][0] = pyrEdges[n][0]; edgemap[n][1] = pyrEdges[n][1]; } break; case CGNS_ENUMV(PENTA_6): case CGNS_ENUMV(PENTA_15): case CGNS_ENUMV(PENTA_18): case CGNS_ENUMV(PENTA_24): case CGNS_ENUMV(PENTA_38): case CGNS_ENUMV(PENTA_40): case CGNS_ENUMV(PENTA_33): case CGNS_ENUMV(PENTA_66): case CGNS_ENUMV(PENTA_75): index = classify_element(z, 6, nodeid); if (index < 1 || index > WDG_SIZE) return; cuts = wdgCuts[index]; for (n = 0; n < WDG_EDGES; n++) { edgemap[n][0] = wdgEdges[n][0]; edgemap[n][1] = wdgEdges[n][1]; } break; case CGNS_ENUMV(HEXA_8): case CGNS_ENUMV(HEXA_20): case CGNS_ENUMV(HEXA_27): case CGNS_ENUMV(HEXA_32): case CGNS_ENUMV(HEXA_56): case CGNS_ENUMV(HEXA_64): case CGNS_ENUMV(HEXA_44): case CGNS_ENUMV(HEXA_98): case CGNS_ENUMV(HEXA_125): index = classify_element(z, 8, nodeid); if (index < 1 || index > HEX_SIZE) return; cuts = hexCuts[index]; for (n = 0; n < HEX_EDGES; n++) { edgemap[n][0] = hexEdges[n][0]; edgemap[n][1] = hexEdges[n][1]; } break; default: return; } /* get the edge intersections */ for (nc = 0; cuts[nc];) { nn = cuts[nc]; for (n = 1; n <= nn; n++) { /* get edge nodes */ cnode.nodes[0] = zonenum; cnode.nodes[1] = nodeid[edgemap[cuts[nc+n]][0]]; cnode.nodes[2] = nodeid[edgemap[cuts[nc+n]][1]]; if (cnode.nodes[2] < cnode.nodes[1]) { swap = cnode.nodes[1]; cnode.nodes[1] = cnode.nodes[2]; cnode.nodes[2] = swap; } cn = (CutNode *) HashFind (cut_hash, &cnode); /* add node to hash table if not there */ if (NULL == cn) { cn = (CutNode *) MALLOC (funcname, sizeof(CutNode)); cn->id = n_cut_nodes++; for (i = 0; i < 3; i++) cn->nodes[i] = cnode.nodes[i]; node = z->nodes[cn->nodes[1]]; for (s1 = 0.0, i = 0; i < 3; i++) s1 += (node[i] * cutplane.plane[i]); node = z->nodes[cn->nodes[2]]; for (s2 = 0.0, i = 0; i < 3; i++) s2 += (node[i] * cutplane.plane[i]); if (s1 == s2) cn->ratio = 0.0; else cn->ratio = (float)((cutplane.plane[3] - s1) / (s2 - s1)); (void) HashAdd (cut_hash, cn); } ids[n-1] = cn->id; } ids[nn] = ids[0]; /* add cutplane edge */ for (n = 0; n < nn; n++) { edge.nodes[0] = ids[n]; edge.nodes[1] = ids[n+1]; ep = (Edge *) HashFind (edgehash, &edge); if (NULL == ep) { ep = (Edge *) MALLOC (funcname, sizeof(Edge)); ep->nodes[0] = edge.nodes[0]; ep->nodes[1] = edge.nodes[1]; (void) HashAdd (edgehash, ep); } } /* next cut */ nc += (nn + 1); } } /*------------------------------------------------------------------*/ static cgsize_t find_intersects () { int nz, nr, nf, nfaces, nnodes; cgsize_t n, ne; size_t nn; CGNS_ENUMT(ElementType_t) type; Face *f; Regn *r; HASH *edgehash; static char *funcname = "find_intersects"; /* create hash table to store nodes at edge intersections */ n_cut_nodes = 0; nn = (size_t)cutplane.nelems; cut_hash = HashCreate (nn > 1024 ? nn / 3 : 127, compare_cut_node, hash_cut_node); cutplane.nedges = 0; for (nz = 0; nz < nzones; nz++) { for (nr = 0; nr < zones[nz].nregs; nr++) { r = &zones[nz].regs[nr]; if (r->cut.nelems == 0) continue; type = r->elemtype; nn = (size_t)r->cut.nelems; edgehash = HashCreate (nn > 1024 ? nn / 3: 127, compare_edges, hash_edge); for (n = 0, ne = 0; ne < r->cut.nelems; ne++) { n = r->cut.elems[ne]; if (r->elemtype == CGNS_ENUMV(NGON_n)) { nnodes = r->elem_offsets[n+1]-r->elem_offsets[n]; intersect_polygon(nz, nnodes, &r->elems[r->elem_offsets[n]], edgehash); } else if (r->elemtype == CGNS_ENUMV(NFACE_n)) { nfaces = r->elem_offsets[n+1]-r->elem_offsets[n]; for (nf = 0; nf < nfaces; nf++) { f = r->poly[abs(r->elems[r->elem_offsets[n]+nf])-1]; intersect_polygon(nz, f->nnodes, f->nodes, edgehash); } } else { cg_npe(type, &nnodes); if (r->elemtype == CGNS_ENUMV(MIXED)) { type = (CGNS_ENUMT(ElementType_t))r->elems[n++]; cg_npe(type, &nnodes); } intersect_element (nz, type, &r->elems[n], edgehash); } } r->cut.nedges = 0; nn = HashSize (edgehash); if (nn) { r->cut.edges = (Edge *) MALLOC (funcname, nn * sizeof(Edge)); HashList (edgehash, get_cut_edge, &r->cut); } HashDestroy (edgehash, NULL); cutplane.nedges += r->cut.nedges; } } nn = HashSize (cut_hash); cutplane.nnodes = (cgsize_t)nn; cutplane.nodes = (Node *) MALLOC (funcname, nn * sizeof(Node)); HashDestroy (cut_hash, get_cut_node); return cutplane.nelems; } /*------------------------------------------------------------------*/ static void draw_edges () { int nz, nr; cgsize_t ne, nn; Zone *z; Regn *r; glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); glBegin(GL_LINES); glColor3fv(cutcolor); for (nz = 0; nz < nzones; nz++) { z = &zones[nz]; for (nr = 0; nr < z->nregs; nr++) { r = &z->regs[nr]; if (r->cut.nedges == 0) continue; if (!usecutclr) glColor3fv(r->color); for (ne = 0; ne < r->cut.nedges; ne++) { nn = r->cut.edges[ne].nodes[0]; glVertex3fv(cutplane.nodes[nn]); nn = r->cut.edges[ne].nodes[1]; glVertex3fv(cutplane.nodes[nn]); } } } glEnd(); } /*------------------------------------------------------------------*/ static void draw_elements (int mode) { int nz, nr, i, j; int ip, nf, nnodes; cgsize_t n, ne, nn; float *nodes[4], norm[3]; CGNS_ENUMT(ElementType_t) type; Zone *z; Regn *r; Face *f; glEnable(GL_LIGHTING); glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK, mode); glColor3fv(cutcolor); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, cutcolor); for (nz = 0; nz < nzones; nz++) { z = &zones[nz]; for (nr = 0; nr < z->nregs; nr++) { r = &z->regs[nr]; if (r->cut.nelems == 0) continue; type = r->elemtype; if (!usecutclr) { glColor3fv(r->color); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, r->color); } if (type == CGNS_ENUMV(NGON_n)) { for (ne = 0; ne < r->cut.nelems; ne++) { nn = r->cut.elems[ne]; nnodes = r->elem_offsets[nn+1]- r->elem_offsets[nn]; if (nnodes < 3) continue; if (nnodes == 3) glBegin(GL_TRIANGLES); else if (nnodes == 4) glBegin(GL_QUADS); else glBegin(GL_POLYGON); glNormal3fv(face_normal(z, nnodes, &r->elems[r->elem_offsets[nn]])); for (i = r->elem_offsets[nn]; i < r->elem_offsets[nn+1]; i++) glVertex3fv(z->nodes[r->elems[i]]); glEnd(); } } else if (type == CGNS_ENUMV(NFACE_n)) { for (ne = 0; ne < r->cut.nelems; ne++) { nn = r->cut.elems[ne]; nf = r->elem_offsets[nn+1]- r->elem_offsets[nn]; for (j = 0; j < nf; j++) { f = r->poly[abs(r->elems[r->elem_offsets[nn]+j])-1]; if (f->nnodes < 3) continue; if (f->nnodes == 3) glBegin(GL_TRIANGLES); else if (f->nnodes == 4) glBegin(GL_QUADS); else glBegin(GL_POLYGON); if (r->elems[r->elem_offsets[nn]+j] < 0) { for (i = 0; i < 3; i++) norm[i] = -f->normal[i]; } else { for (i = 0; i < 3; i++) norm[i] = f->normal[i]; } glNormal3fv(norm); for (i = 0; i < f->nnodes; i++) glVertex3fv(z->nodes[f->nodes[i]]); glEnd(); } } } else { for (ne = 0; ne < r->cut.nelems; ne++) { n = r->cut.elems[ne]; if (r->elemtype == CGNS_ENUMV(MIXED)) type = (CGNS_ENUMT(ElementType_t))r->elems[n++]; switch (type) { case CGNS_ENUMV(TRI_3): case CGNS_ENUMV(TRI_6): case CGNS_ENUMV(TRI_9): case CGNS_ENUMV(TRI_10): case CGNS_ENUMV(TRI_12): case CGNS_ENUMV(TRI_15): ip = 0; nf = 1; break; case CGNS_ENUMV(QUAD_4): case CGNS_ENUMV(QUAD_8): case CGNS_ENUMV(QUAD_9): case CGNS_ENUMV(QUAD_12): case CGNS_ENUMV(QUAD_16): case CGNS_ENUMV(QUAD_P4_16): case CGNS_ENUMV(QUAD_25): ip = 1; nf = 1; break; case CGNS_ENUMV(TETRA_4): case CGNS_ENUMV(TETRA_10): case CGNS_ENUMV(TETRA_16): case CGNS_ENUMV(TETRA_20): case CGNS_ENUMV(TETRA_22): case CGNS_ENUMV(TETRA_34): case CGNS_ENUMV(TETRA_35): ip = 2; nf = 4; break; case CGNS_ENUMV(PYRA_5): case CGNS_ENUMV(PYRA_13): case CGNS_ENUMV(PYRA_14): case CGNS_ENUMV(PYRA_21): case CGNS_ENUMV(PYRA_29): case CGNS_ENUMV(PYRA_30): case CGNS_ENUMV(PYRA_P4_29): case CGNS_ENUMV(PYRA_50): case CGNS_ENUMV(PYRA_55): ip = 6; nf = 5; break; case CGNS_ENUMV(PENTA_6): case CGNS_ENUMV(PENTA_15): case CGNS_ENUMV(PENTA_18): case CGNS_ENUMV(PENTA_24): case CGNS_ENUMV(PENTA_38): case CGNS_ENUMV(PENTA_40): case CGNS_ENUMV(PENTA_33): case CGNS_ENUMV(PENTA_66): case CGNS_ENUMV(PENTA_75): ip = 11; nf = 5; break; case CGNS_ENUMV(HEXA_8): case CGNS_ENUMV(HEXA_20): case CGNS_ENUMV(HEXA_27): case CGNS_ENUMV(HEXA_32): case CGNS_ENUMV(HEXA_56): case CGNS_ENUMV(HEXA_64): case CGNS_ENUMV(HEXA_44): case CGNS_ENUMV(HEXA_98): case CGNS_ENUMV(HEXA_125): ip = 16; nf = 6; break; default: ip = 0; nf = 0; break; } for (j = 0; j < nf; j++) { nnodes = facenodes[ip+j][0]; for (i = 0; i < nnodes; i++) { nn = r->elems[n+facenodes[ip+j][i+1]]; nodes[i] = z->nodes[nn]; } if (nnodes == 4) { glBegin(GL_QUADS); glNormal3fv(compute_normal(nodes[0], nodes[1], nodes[2], nodes[3])); } else { glBegin(GL_TRIANGLES); glNormal3fv(compute_normal(nodes[0], nodes[1], nodes[2], NULL)); } for (i = 0; i < nnodes; i++) glVertex3fv(nodes[i]); glEnd(); } } } } } } /*---------- OGLcutplane ------------------------------------------- * create OGL display list for a cutting plane *------------------------------------------------------------------*/ static int OGLcutplane (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int mode; float plane[4]; static char slist[33]; if (argc < 1 || argc > 3) { Tcl_SetResult (interp, "usage: OGLcutplane [mode] [plane]", TCL_STATIC); return TCL_ERROR; } /* create and return displaylist flag */ if (argc == 1) { if (!CutDL) CutDL = glGenLists (1); sprintf (slist, "%d", CutDL); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } mode = atoi(argv[1]); if (argc == 3) { int np; CONST char **args; if (TCL_OK != Tcl_SplitList (interp, argv[2], &np, &args)) return TCL_ERROR; if (np != 4) { Tcl_Free ((char *)args); Tcl_SetResult (interp, "invalid plane", TCL_STATIC); return TCL_ERROR; } for (np = 0; np < 4; np++) plane[np] = (float) atof (args[np]); Tcl_Free ((char *)args); init_cutplane(plane); find_elements(); } if (!CutDL) CutDL = glGenLists (1); glNewList (CutDL, GL_COMPILE); if (mode && cutplane.nelems) { if (mode == 1) { if (cutplane.nedges == 0) find_intersects(); draw_edges (); } else { draw_elements (mode > 2 ? GL_FILL : GL_LINE); } } glEndList (); sprintf (slist, "%ld %ld", (long)cutplane.nelems, (long)cutplane.nedges); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } /*---------- OGLdrawplane ------------------------------------------ * draw the cutting plane *------------------------------------------------------------------*/ static int OGLdrawplane (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, np, i, j, k, index, n0, n1; CONST char **args; float plane[4], bbox[3][2], s[8], ds; float node[8][3], pnode[6][3]; static char slist[17]; if (argc < 1 || argc > 2) { Tcl_SetResult (interp, "usage: OGLdrawplane [plane]", TCL_STATIC); return TCL_ERROR; } if (!PlaneDL) PlaneDL = glGenLists (1); if (argc == 1) { glNewList (PlaneDL, GL_COMPILE); glEndList (); sprintf (slist, "%d", PlaneDL); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } if (TCL_OK != Tcl_SplitList (interp, argv[1], &np, &args)) return TCL_ERROR; if (np != 4) { Tcl_Free ((char *)args); Tcl_SetResult (interp, "invalid plane", TCL_STATIC); return TCL_ERROR; } for (n = 0; n < np; n++) plane[n] = (float) atof (args[n]); Tcl_Free ((char *)args); get_bounds (ignorevis, bbox); index = n = 0; for (k = 0; k < 2; k++) { for (j = 0; j < 2; j++) { for (i = 0; i < 2; i++) { node[n][0] = bbox[0][(i+j)%2]; node[n][1] = bbox[1][j]; node[n][2] = bbox[2][k]; s[n] = node[n][0] * plane[0] + node[n][1] * plane[1] + node[n][2] * plane[2]; if (s[n] >= plane[3]) index |= (1 << n); n++; } } } if (index > 0x7f) index ^= 0xff; if (index < 1 || index > HEX_SIZE) { Tcl_SetResult (interp, "plane doesn't intersect", TCL_STATIC); return TCL_ERROR; } np = hexCuts[index][0]; for (n = 0; n < np; n++) { j = hexCuts[index][n+1]; n0 = hexEdges[j][0]; n1 = hexEdges[j][1]; ds = s[n1] - s[n0]; if (ds != 0.0) ds = (plane[3] - s[n0]) / ds; for (i = 0; i < 3; i++) pnode[n][i] = node[n0][i] + ds * (node[n1][i] - node[n0][i]); } glNewList (PlaneDL, GL_COMPILE); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_LIGHTING); glShadeModel(GL_FLAT); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor4fv(cutcolor); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, cutcolor); glBegin(GL_TRIANGLE_FAN); glNormal3fv(plane); for (n = 0; n < np; n++) glVertex3fv(pnode[n]); glEnd(); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glEnable(GL_LIGHTING); glEndList (); sprintf (slist, "%d", PlaneDL); Tcl_SetResult (interp, slist, TCL_STATIC); return TCL_OK; } /*---------- OGLcutconfig ------------------------------------------ * set the cutting plane color and operation *------------------------------------------------------------------*/ static int OGLcutconfig (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, np; CONST char **args; if (argc < 2 || argc > 4) { Tcl_SetResult (interp, "usage: OGLcutconfig color [usecutclr] [ignorevis]", TCL_STATIC); return TCL_ERROR; } if (TCL_OK != Tcl_SplitList (interp, argv[1], &np, &args)) return TCL_ERROR; if (np < 3 || np > 4) { Tcl_Free ((char *)args); Tcl_SetResult (interp, "invalid color", TCL_STATIC); return TCL_ERROR; } for (n = 0; n < np; n++) cutcolor[n] = (float) atof (args[n]); Tcl_Free ((char *)args); if (argc > 2) { usecutclr = atoi (argv[2]); if (argc > 3) ignorevis = atoi (argv[3]); } return TCL_OK; } #endif /*---------- Cgnstcl_Init -------------------------------------- * Initialize and create the commands *--------------------------------------------------------------*/ #if defined(_WIN32) && defined(BUILD_DLL) __declspec(dllexport) #endif int Cgnstcl_Init(Tcl_Interp *interp) { global_interp = interp; Tcl_CreateCommand (interp, "CGNSopen", (Tcl_CmdProc *)CGNSopen, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSclose", (Tcl_CmdProc *)CGNSclose, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSbase", (Tcl_CmdProc *)CGNSbase, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSzone", (Tcl_CmdProc *)CGNSzone, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSsummary", (Tcl_CmdProc *)CGNSsummary, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSgetbase", (Tcl_CmdProc *)CGNSgetbase, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSgetzone", (Tcl_CmdProc *)CGNSgetzone, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSgetregion", (Tcl_CmdProc *)CGNSgetregion, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSregiondim", (Tcl_CmdProc *)CGNSregiondim, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSbounds", (Tcl_CmdProc *)CGNSbounds, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "OGLregion", (Tcl_CmdProc *)OGLregion, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "OGLaxis", (Tcl_CmdProc *)OGLaxis, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "OGLcolor", (Tcl_CmdProc *)OGLcolor, (ClientData)0, (Tcl_CmdDeleteProc *)0); #ifndef NO_CUTTING_PLANE Tcl_CreateCommand (interp, "OGLcutplane", (Tcl_CmdProc *)OGLcutplane, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "OGLdrawplane", (Tcl_CmdProc *)OGLdrawplane, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "OGLcutconfig", (Tcl_CmdProc *)OGLcutconfig, (ClientData)0, (Tcl_CmdDeleteProc *)0); #endif return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsplot/plotwish.c000066400000000000000000000056141343724673500207440ustar00rootroot00000000000000/* * tkAppInit.c -- * * Provides a default version of the Tcl_AppInit procedure for * use in wish and similar Tk-based applications. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include "tk.h" #include "locale.h" extern int Cgnstcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tkogl_Init _ANSI_ARGS_((Tcl_Interp *interp)); /* *---------------------------------------------------------------------- * * main -- * * This is the main program for the application. * * Results: * None: Tk_Main never returns here, so this procedure never * returns either. * * Side effects: * Whatever the application does. * *---------------------------------------------------------------------- */ int main(argc, argv) int argc; /* Number of command-line arguments. */ char **argv; /* Values of command-line arguments. */ { Tk_Main(argc, argv, Tcl_AppInit); return 0; /* Needed only to prevent compiler warning. */ } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); /* * Call the init procedures for included packages. Each call should * look like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. */ if (Cgnstcl_Init(interp) == TCL_ERROR) return TCL_ERROR; if (Tkogl_Init(interp) == TCL_ERROR) return TCL_ERROR; /* * Call Tcl_CreateCommand for application-specific commands, if * they weren't already created by the init procedures called above. */ /* * Specify a user-specific startup file to invoke if the application * is run interactively. Typically the startup file is "~/.apprc" * where "app" is the name of the application. If this line is deleted * then no user-specific startup file will be run under any conditions. */ Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsplot/winmain.c000066400000000000000000000205471343724673500205370ustar00rootroot00000000000000/* * winMain.c -- * * Main entry point for wish and other Tk-based applications. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include #include "tkWinInt.h" #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include #include extern int Cgnstcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tkogl_Init _ANSI_ARGS_((Tcl_Interp *interp)); #ifdef USE_HTMLHELP extern int WinHtml_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* * Forward declarations for procedures defined later in this file: */ static void setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr)); static void WishPanic _ANSI_ARGS_(TCL_VARARGS(char *,format)); static int Proc_LoadIcon _ANSI_ARGS_((ClientData data, Tcl_Interp *interp, int argc, char **argv)); static HINSTANCE myInstance; /* *---------------------------------------------------------------------- * * WinMain -- * * Main entry point from Windows. * * Results: * Returns false if initialization fails, otherwise it never * returns. * * Side effects: * Just about anything, since from here we call arbitrary Tcl code. * *---------------------------------------------------------------------- */ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { char **argv; int argc; char buffer[MAX_PATH+1]; char *p; Tcl_SetPanicProc((Tcl_PanicProc *)WishPanic); /* * Increase the application queue size from default value of 8. * At the default value, cross application SendMessage of WM_KILLFOCUS * will fail because the handler will not be able to do a PostMessage! * This is only needed for Windows 3.x, since NT dynamically expands * the queue. */ SetMessageQueue(64); /* * Set up the default locale to be standard "C" locale so parsing * is performed correctly. */ setlocale(LC_ALL, "C"); setargv(&argc, &argv); /* * Replace argv[0] with full pathname of executable, and forward * slashes substituted for backslashes. */ GetModuleFileName(NULL, buffer, sizeof(buffer)); argv[0] = buffer; for (p = buffer; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } myInstance = hInstance; Tk_Main(argc, argv, Tcl_AppInit); return 1; } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(Tcl_Interp *interp) { if (Tcl_Init(interp) == TCL_ERROR) { goto error; } if (Tk_Init(interp) == TCL_ERROR) { goto error; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); if (Cgnstcl_Init(interp) == TCL_ERROR) goto error; if (Tkogl_Init(interp) == TCL_ERROR) goto error; #ifdef USE_HTMLHELP if (WinHtml_Init(interp) == TCL_ERROR) goto error; #endif Tcl_CreateCommand (interp, "LoadIcon", (Tcl_CmdProc *)Proc_LoadIcon, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_SetVar(interp, "tcl_rcFileName", "~/wishrc.tcl", TCL_GLOBAL_ONLY); return TCL_OK; error: MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); ExitProcess(1); /* we won't reach this, but we need the return */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * WishPanic -- * * Display a message and exit. * * Results: * None. * * Side effects: * Exits the program. * *---------------------------------------------------------------------- */ void WishPanic TCL_VARARGS_DEF(char *,arg1) { va_list argList; char buf[1024]; char *format; format = TCL_VARARGS_START(char *,arg1,argList); vsprintf(buf, format, argList); MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, buf, "Fatal Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); #ifdef _MSC_VER DebugBreak(); #endif ExitProcess(1); } /* *------------------------------------------------------------------------- * * setargv -- * * Parse the Windows command line string into argc/argv. Done here * because we don't trust the builtin argument parser in crt0. * Windows applications are responsible for breaking their command * line into arguments. * * 2N backslashes + quote -> N backslashes + begin quoted string * 2N + 1 backslashes + quote -> literal * N backslashes + non-quote -> literal * quote + quote in a quoted string -> single quote * quote + quote not in quoted string -> empty string * quote -> begin quoted string * * Results: * Fills argcPtr with the number of arguments and argvPtr with the * array of arguments. * * Side effects: * Memory allocated. * *-------------------------------------------------------------------------- */ static void setargv(int *argcPtr, char ***argvPtr) { char *cmdLine, *p, *arg, *argSpace; char **argv; int argc, size, inquote, copy, slashes; cmdLine = GetCommandLine(); /* INTL: BUG */ /* * Precompute an overly pessimistic guess at the number of arguments * in the command line by counting non-space spans. */ size = 2; for (p = cmdLine; *p != '\0'; p++) { if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ size++; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } } } argSpace = (char *) Tcl_Alloc( (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1)); argv = (char **) argSpace; argSpace += size * sizeof(char *); size--; p = cmdLine; for (argc = 0; argc < size; argc++) { argv[argc] = arg = argSpace; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } inquote = 0; slashes = 0; while (1) { copy = 1; while (*p == '\\') { slashes++; p++; } if (*p == '"') { if ((slashes & 1) == 0) { copy = 0; if ((inquote) && (p[1] == '"')) { p++; copy = 1; } else { inquote = !inquote; } } slashes >>= 1; } while (slashes) { *arg = '\\'; arg++; slashes--; } if ((*p == '\0') || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */ break; } if (copy != 0) { *arg = *p; arg++; } p++; } *arg = '\0'; argSpace = arg + 1; } argv[argc] = NULL; *argcPtr = argc; *argvPtr = argv; } /*---------------------------------------------------------------------- * set the toplevel window icon *----------------------------------------------------------------------*/ typedef struct TkWmInfo { TkWindow *winPtr; HWND hwnd; } WmInfo; static int Proc_LoadIcon(ClientData data, Tcl_Interp *interp, int argc, char **argv) { TkWindow *winPtr; HANDLE hIcon; HWND hwnd = NULL; if (2 != argc) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " iconname\"", (char *) NULL); return TCL_ERROR; } winPtr = (TkWindow *) Tk_MainWindow (interp); if (NULL != winPtr && NULL != winPtr->wmInfoPtr) hwnd = winPtr->wmInfoPtr->hwnd; if (!hwnd) { Tcl_SetResult (interp, "toplevel window has not been created/mapped", TCL_STATIC); return TCL_ERROR; } if (argv[1][0] == '@') hIcon = LoadImage (NULL, &argv[1][1], IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); else hIcon = (HANDLE) LoadIcon (myInstance, argv[1]); if (!hIcon) { Tcl_SetResult (interp, "icon not found", TCL_STATIC); return TCL_ERROR; } SetClassLongPtr (hwnd, GCLP_HICON, (LONG_PTR)hIcon); Tcl_ResetResult (interp); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsview/000077500000000000000000000000001343724673500167155ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/cgnsview/CMakeLists.txt000066400000000000000000000041231343724673500214550ustar00rootroot00000000000000############# # cgnsview # ############# include_directories(${TCL_INCLUDE_PATH} ${TK_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR}) include_directories(../common) include_directories(../..) link_directories(.) if (CGNS_USE_SHARED) link_libraries(cgns_shared) else (CGNS_USE_SHARED) link_libraries(cgns_static) endif (CGNS_USE_SHARED) link_libraries(${TCL_LIBRARY} ${TK_LIBRARY}) if (CGNS_ENABLE_HDF5) link_libraries(${HDF5_LIBRARY}) if(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) link_libraries(${ZLIB_LIBRARY}) endif(HDF5_NEED_ZLIB AND ZLIB_LIBRARY) if(HDF5_NEED_SZIP AND SZIP_LIBRARY) link_libraries(${SZIP_LIBRARY}) endif(HDF5_NEED_SZIP AND SZIP_LIBRARY) if(HDF5_NEED_MPI AND MPI_LIBS) link_libraries(${MPI_LIBS}) endif(HDF5_NEED_MPI AND MPI_LIBS) endif (CGNS_ENABLE_HDF5) if (WIN32) if (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) add_definitions(-DUSE_HTMLHELP) include_directories(${HTML_HELP_INCLUDE_PATH}) link_libraries(${HTML_HELP_LIBRARY}) set(cgnsview_FILES cgiotcl.c winmain.c ../common/winhtml.c) else (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) set(cgnsview_FILES cgiotcl.c winmain.c) endif (HTML_HELP_INCLUDE_PATH AND HTML_HELP_LIBRARY) else (WIN32) include_directories(${X11_X11_INCLUDE_PATH}) link_libraries(${X11_X11_LIB} m) set(cgnsview_FILES cgiowish.c cgiotcl.c) endif (WIN32) add_executable(cgiowish ${cgnsview_FILES}) add_dependencies(cgiowish cgns_static) if (WIN32) set_target_properties(cgiowish PROPERTIES LINK_FLAGS /subsystem:windows) endif (WIN32) if (WIN32) install(TARGETS cgiowish RUNTIME DESTINATION bin) install(PROGRAMS cgnsview.bat cgnsnodes.bat DESTINATION bin) install(FILES cgnsview.tcl cgns.tcl cgnsnodes.tcl export.tcl import.tcl tools.tcl DESTINATION share) else (WIN32) install(TARGETS cgiowish RUNTIME DESTINATION bin/cgnstools) install(PROGRAMS cgnsview.sh DESTINATION bin RENAME cgnsview) install(PROGRAMS cgnsnodes.sh DESTINATION bin RENAME cgnsnodes) install(FILES cgnsview.tcl cgns.tcl cgnsnodes.tcl export.tcl import.tcl tools.tcl DESTINATION share/cgnstools) endif (WIN32) CGNS-3.4.0/src/cgnstools/cgnsview/Makefile.unix000066400000000000000000000056221343724673500213440ustar00rootroot00000000000000# Makefile for adfviewer include ../make.defs COPTS = $(CFLAGS) -I$(CGNSDIR) $(TKINCS) LDLIST = $(CGNSLIB) $(BUILDLIBS) $(TKLIBS) $(X11LIBS) $(CLIBS) #-------------------------------------------------- all : cgiowish$(EXE) cgiowish$(EXE) : cgiowish.$(O) cgiotcl.$(O) $(CGNSLIB) $(CC) $(LDFLAGS) -o $@ cgiowish.$(O) cgiotcl.$(O) $(LDLIST) $(STRIP) $@ cgiowish.$(O) : cgiowish.c cgiotcl.$(O) : cgiotcl.c #--------------------------------------------------------------- TCLSCRIPTS = \ cgnsview.tcl \ balloon.tcl \ cgns.tcl \ cgnsnodes.tcl \ combobox.tcl \ config.tcl \ dialog.tcl \ editfile.tcl \ export.tcl \ filesel.tcl \ findfile.tcl \ frame.tcl \ help.tcl \ import.tcl \ menubar.tcl \ tclreg.tcl \ tkdir.tcl \ tools.tcl \ tree.tcl \ units.tcl \ tclIndex ICONS = cgns.ico cgns.png cgns-icon.xbm cgns-mask.xbm install : install-dirs install-prog install-wish install-script install-dirs : @for d in \ $(BIN_INSTALL_DIR) \ $(EXE_INSTALL_DIR) \ $(WSH_INSTALL_DIR) \ $(LIB_INSTALL_DIR) ; do \ if [ ! -d $$d ] ; then \ echo "Making directory $$d"; \ mkdir -p $$d; \ chmod 755 $$d; \ fi; \ done; install-prog : $(ALL) @echo "installing shell scripts to $(BIN_INSTALL_DIR)" @$(INSTALL_PROG) cgnsview.sh $(BIN_INSTALL_DIR)/cgnsview @chmod +x $(BIN_INSTALL_DIR)/cgnsview @$(INSTALL_PROG) cgnsnodes.sh $(BIN_INSTALL_DIR)/cgnsnodes @chmod +x $(BIN_INSTALL_DIR)/cgnsnodes @if [ ! -f $(EXE_INSTALL_DIR)/cgconfig ] ; then \ echo "installing configuration file to $(EXE_INSTALL_DIR)"; \ $(INSTALL_DATA) ../cgconfig $(EXE_INSTALL_DIR)/cgconfig; \ fi; install-wish : cgiowish$(EXE) @echo "installing cgiowish executable to $(WSH_INSTALL_DIR)" @$(INSTALL_PROG) cgiowish$(EXE) $(WSH_INSTALL_DIR) install-script : @echo "installing tcl scripts to $(LIB_INSTALL_DIR)" @for i in *.tcl ; do \ $(INSTALL_DATA) $$i $(LIB_INSTALL_DIR); \ done; @for i in ../common/*.tcl ; do \ $(INSTALL_DATA) $$i $(LIB_INSTALL_DIR); \ done; @$(INSTALL_DATA) ../common/tclIndex $(LIB_INSTALL_DIR) @echo "installing icons to $(LIB_INSTALL_DIR)" @for i in $(ICONS) ; do \ $(INSTALL_DATA) ../common/$$i $(LIB_INSTALL_DIR); \ done; uninstall : @echo "uninstalling executables" @for i in cgnsview cgnsnodes ; do \ if [ -f $(BIN_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(BIN_INSTALL_DIR)/$$i; \ fi; \ done; @if [ -f $(WSH_INSTALL_DIR)/cgiowish$(EXE) ] ; then \ /bin/rm -f $(WSH_INSTALL_DIR)/cgiowish$(EXE); \ fi; @echo "uninstalling tcl scripts" @for i in $(TCLSCRIPTS) ; do \ if [ -f $(LIB_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/$$i; \ fi; \ done; @echo "uninstalling icons" @for i in $(ICONS) ; do \ if [ -f $(LIB_INSTALL_DIR)/$$i ] ; then \ /bin/rm -f $(LIB_INSTALL_DIR)/$$i; \ fi; \ done; #--------------------------------------------------------------- .c.$(O) : $(CC) $(COPTS) -c $< clean: $(RM) *.$(O) *~ *.bak cgiowish$(EXE) CGNS-3.4.0/src/cgnstools/cgnsview/Makefile.win000066400000000000000000000034321343724673500211530ustar00rootroot00000000000000include ..\make.win COPTS = $(CFLAGS) -I$(CGNSDIR) $(TCLINC) #-------------------------------------------------- all : cgiowish.exe dll : cgiotcl.dll #-------------------------------------------------- cgiowish.exe : winmain.obj cgiotcl.obj $(WINHTML_OBJ) $(LINK) $(LFLAGS) /nodefaultlib /subsystem:windows \ -out:$@ winmain.obj cgiotcl.obj $(WINHTML_OBJ) \ $(CGNSLIB) $(CLIBS) $(BUILDLIBS) $(TCLLIB) $(TKLIB) \ $(guilibs) $(WINHTML_LIB) winmain.obj : winmain.c $(CC) $(COPTS) $(WINHTML_OPT) -c winmain.c cgiotcl.obj : cgiotcl.c $(CC) $(COPTS) -c cgiotcl.c #-------------------------------------------------- cgiotcl.dll : cgiotcl-dll.obj $(CGNSLIB) $(LINK) -dll -out:cgiotcl.dll cgiotcl-dll.obj \ $(CGNSLIB) $(CLIBS) $(TCLLIB) $(TKLIB) $(dlllibs) cgiotcl-dll.obj : cgiotcl.c $(CC) $(COPTS) -DBUILD_DLL -Fo$@ -c cgiotcl.c #-------------------------------------------------- winhtml.obj : ..\common\winhtml.c $(CC) $(COPTS) $(WINHTML_INC) -Fowinhtml.obj -c ..\common\winhtml.c #--------------------------------------------------------------- install : cgiowish.exe $(BINDIR) $(SHAREDIR) -$(INSTALL) cgiowish.exe $(BINDIR) -$(INSTALL) cgnsview.bat $(BINDIR) -$(INSTALL) cgnsnodes.bat $(BINDIR) -$(INSTALL) *.tcl $(SHAREDIR) -$(INSTALL) *.ico $(SHAREDIR) -$(INSTALL) ..\common\tclIndex $(SHAREDIR) -$(INSTALL) ..\common\*.tcl $(SHAREDIR) -$(INSTALL) ..\common\*.ico $(SHAREDIR) $(BINDIR) : $(INSTALLDIR) -mkdir $(BINDIR) $(SHAREDIR) : $(INSTALLDIR) -mkdir $(SHAREDIR) $(INSTALLDIR) : -mkdir $(INSTALLDIR) #-------------------------------------------------- .c.obj : $(CC) $(COPTS) -Fo$@ -c $< .obj.exe : $(LINK) $(LFLAGS) /out:$@ $< $(CGNSLIB) $(BUILDLIBS) clean: -$(RM) *.obj -$(RM) *.lib -$(RM) *.exp -$(RM) *.pdb -$(RM) *.ilk -$(RM) *.exe -$(RM) *.dll -$(RM) *.bak CGNS-3.4.0/src/cgnstools/cgnsview/cgiotcl.c000066400000000000000000002120321343724673500205050ustar00rootroot00000000000000#include #include #include #include #include "tk.h" #include "cgns_io.h" #include "cgnslib.h" /* only needed for CGNS_VERSION */ #ifndef CGNSTYPES_H # define cgsize_t int # define cglong_t long # define cgulong_t unsigned long #endif #ifndef CONST # define CONST #endif /* these are the data types as used in CGIO */ #define I4 int #define U4 unsigned int #define I8 cglong_t #define U8 cgulong_t #define R4 float #define R8 double #define X4 float #define X8 double #define C1 char #define B1 unsigned char enum DataTags { MTdata = 0, I4data, I8data, U4data, U8data, R4data, R8data, X4data, X8data, C1data, B1data, LKdata }; static struct DataType { char *name; int type; int bytes; int size; } DataList[] = { {"MT", MTdata, 0, 0}, {"I4", I4data, 4, sizeof(I4)}, {"I8", I8data, 8, sizeof(I8)}, {"U4", U4data, 4, sizeof(U4)}, {"U8", U8data, 8, sizeof(U8)}, {"R4", R4data, 4, sizeof(R4)}, {"R8", R8data, 8, sizeof(R8)}, {"X4", X4data, 8, sizeof(X4)*2}, {"X8", X8data, 16, sizeof(X8)*2}, {"C1", C1data, 1, 1}, {"B1", B1data, 1, 1}, {"LK", LKdata, 0, 0} }; #define NumDataTypes (sizeof(DataList)/sizeof(struct DataType)) static int cgioNum = 0; static double RootID = 0.0; /*=================================================================== * local routines *===================================================================*/ /*---------- get_error ---------------------------------------------- * save error message *-------------------------------------------------------------------*/ static int get_error (Tcl_Interp *interp, char *funcname) { char errmsg[CGIO_MAX_ERROR_LENGTH+1]; cgio_error_message (errmsg); Tcl_AppendResult (interp, /*funcname, ":",*/ errmsg, NULL); return TCL_ERROR; } /*---------- get_node ---------------------------------------------- * get the node ID for a node *------------------------------------------------------------------*/ static int get_node (Tcl_Interp *interp, char *nodename, double *nodeid) { if (!*nodename || 0 == strcmp (nodename, "/")) *nodeid = RootID; else { if (cgio_get_node_id (cgioNum, RootID, nodename, nodeid)) return (get_error (interp, "cgio_get_node_id")); } return TCL_OK; } /*---------- get_parent ---------------------------------------------- * get the parent node ID for a node *------------------------------------------------------------------*/ static char *get_parent (Tcl_Interp *interp, char *nodename, double *nodeid) { char *node; if (!*nodename || 0 == strcmp (nodename, "/") || NULL == (node = strrchr (nodename, '/'))) { Tcl_AppendResult (interp, "node does not have a parent", NULL); return NULL; } if (node == nodename) *nodeid = RootID; else { *node = 0; if (cgio_get_node_id (cgioNum, RootID, nodename, nodeid)) { get_error (interp, "cgio_get_node_id"); return NULL; } *node = '/'; } return (++node); } /*---------- data_size --------------------------------------------- * return number of data values for a node *------------------------------------------------------------------*/ static cgsize_t data_size (Tcl_Interp *interp, double nodeid) { int n, ndim; cgsize_t np, dims[CGIO_MAX_DIMENSIONS]; if (cgio_get_dimensions (cgioNum, nodeid, &ndim, dims)) { get_error (interp, "cgio_get_dimensions"); return -1; } if (ndim == 0) return 0; for (np = 1, n = 0; n < ndim; n++) np *= dims[n]; return np; } /*---------- data_type --------------------------------------------- * return number of data values for a node *------------------------------------------------------------------*/ static struct DataType * data_type (Tcl_Interp *interp, double nodeid) { int n; char type[CGIO_MAX_DATATYPE_LENGTH+1]; if (cgio_get_data_type (cgioNum, nodeid, type)) { get_error (interp, "cgio_get_data_type"); return NULL; } for (n = 0; n < CGIO_MAX_DATATYPE_LENGTH && type[n]; n++) { if (islower (type[n])) type[n] = toupper (type[n]); } for (n = 0; n < NumDataTypes; n++) { if (0 == strncmp (type, DataList[n].name, 2)) return (&DataList[n]); } Tcl_AppendResult (interp, "unrecognized data type:", type, NULL); return NULL; } /*---------- convert_C1 -------------------------------------------- * convert data from C1 *------------------------------------------------------------------*/ static char *convert_C1 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; C1 *d = (C1 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == C1data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_B1 -------------------------------------------- * convert data from B1 *------------------------------------------------------------------*/ static char *convert_B1 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; B1 *d = (B1 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == B1data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_I4 -------------------------------------------- * convert data from I4 *------------------------------------------------------------------*/ static char *convert_I4 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; I4 *d = (I4 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == I4data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_U4 -------------------------------------------- * convert data from U4 *------------------------------------------------------------------*/ static char *convert_U4 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; U4 *d = (U4 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == U4data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_I8 -------------------------------------------- * convert data from I8 *------------------------------------------------------------------*/ static char *convert_I8 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; I8 *d = (I8 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == I8data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_U8 -------------------------------------------- * convert data from U8 *------------------------------------------------------------------*/ static char *convert_U8 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; U8 *d = (U8 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == U8data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_R4 -------------------------------------------- * convert data from R4 *------------------------------------------------------------------*/ static char *convert_R4 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; R4 *d = (R4 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == R4data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_R8 -------------------------------------------- * convert data from R8 *------------------------------------------------------------------*/ static char *convert_R8 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; R8 *d = (R8 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == R8data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++) *r++ = (R4)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = 0.0; } break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = 0.0; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_X4 -------------------------------------------- * convert data from X4 *------------------------------------------------------------------*/ static char *convert_X4 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; X4 *d = (X4 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == X4data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++, d++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++, d++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++, d++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++, d++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++, d++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++, d++) *r++ = (R8)*d++; break; } case X8data: { X8 *x = (X8 *)newdata; for (n = 0; n < np; n++) { *x++ = (X8)*d++; *x++ = (X8)*d++; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++, d++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++, d++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*---------- convert_X8 -------------------------------------------- * convert data from C1 *------------------------------------------------------------------*/ static char *convert_X8 (size_t np, char *olddata, struct DataType *dtnew) { size_t n; X8 *d = (X8 *)olddata; char *newdata; if (np < 1 || dtnew->size == 0) return NULL; if (dtnew->type == X8data) return olddata; newdata = (char *) calloc (np, dtnew->size); if (NULL == newdata) return NULL; switch (dtnew->type) { case I4data: { I4 *i = (I4 *)newdata; for (n = 0; n < np; n++, d++) *i++ = (I4)*d++; break; } case U4data: { U4 *u = (U4 *)newdata; for (n = 0; n < np; n++, d++) *u++ = (U4)*d++; break; } case I8data: { I8 *i = (I8 *)newdata; for (n = 0; n < np; n++, d++) *i++ = (I8)*d++; break; } case U8data: { U8 *u = (U8 *)newdata; for (n = 0; n < np; n++, d++) *u++ = (U8)*d++; break; } case R4data: { R4 *r = (R4 *)newdata; for (n = 0; n < np; n++, d++) *r++ = (R4)*d++; break; } case R8data: { R8 *r = (R8 *)newdata; for (n = 0; n < np; n++, d++) *r++ = (R8)*d++; break; } case X4data: { X4 *x = (X4 *)newdata; for (n = 0; n < np; n++) { *x++ = (X4)*d++; *x++ = (X4)*d++; } break; } case C1data: { C1 *c = (C1 *)newdata; for (n = 0; n < np; n++, d++) *c++ = (C1)*d++; break; } case B1data: { B1 *b = (B1 *)newdata; for (n = 0; n < np; n++, d++) *b++ = (B1)*d++; break; } default: free (newdata); newdata = NULL; break; } return newdata; } /*=================================================================== * tcl routines *===================================================================*/ /*---------- CGNSversion ----------------------------------------------- * get CGNS library version *----------------------------------------------------------------------*/ static int CGNSversion (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char version[33]; Tcl_ResetResult (interp); if (argc != 1) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], "\"", NULL); return TCL_ERROR; } sprintf (version, "%g", CGNS_DOTVERS); Tcl_AppendResult (interp, version, NULL); return TCL_OK; } /*---------- CGNSfile -------------------------------------------------- * detect file type *----------------------------------------------------------------------*/ static int CGNSfile (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int file_type; Tcl_ResetResult (interp); if (argc != 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " filename\"", NULL); return TCL_ERROR; } if (cgio_check_file (argv[1], &file_type)) return (get_error (interp, "cgio_check_file")); if (file_type == CGIO_FILE_ADF) Tcl_SetResult (interp, "adf", TCL_STATIC); else if (file_type == CGIO_FILE_HDF5) Tcl_SetResult (interp, "hdf5", TCL_STATIC); else { Tcl_SetResult (interp, "unknown file type", TCL_STATIC); return TCL_ERROR; } return TCL_OK; } /*---------- CGIOsupported ---------------------------------------------- * get supported file types *----------------------------------------------------------------------*/ static int CGIOsupported (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int type = CGIO_FILE_NONE; Tcl_ResetResult (interp); if (argc < 1 || argc > 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " ?type?\"", NULL); return TCL_ERROR; } if (argc == 2) { switch (argv[1][0]) { case 'a': case 'A': type = CGIO_FILE_ADF; break; case 'h': case 'H': type = CGIO_FILE_HDF5; break; default: Tcl_SetResult (interp, "unknown file type", TCL_STATIC); return TCL_ERROR; } } if ((type == CGIO_FILE_NONE || type == CGIO_FILE_ADF) && cgio_is_supported (CGIO_FILE_ADF) == 0) Tcl_AppendElement (interp, "adf"); if ((type == CGIO_FILE_NONE || type == CGIO_FILE_HDF5) && cgio_is_supported (CGIO_FILE_HDF5) == 0) Tcl_AppendElement (interp, "hdf5"); return TCL_OK; } /*---------- CGIOversion ------------------------------------------------ * get CGIO library version *----------------------------------------------------------------------*/ static int CGIOversion (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char version[CGIO_MAX_VERSION_LENGTH+1]; Tcl_ResetResult (interp); if (argc != 1) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], "\"", NULL); return TCL_ERROR; } if (cgioNum > 0) { if (cgio_library_version (cgioNum, version)) return (get_error (interp, "cgio_library_version")); Tcl_AppendResult (interp, version, NULL); } return TCL_OK; } /*---------- CGIOopen --------------------------------------------------- * open CGIO database *----------------------------------------------------------------------*/ static int CGIOopen (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int mode, type, cgio_num; char rootname[CGIO_MAX_NAME_LENGTH+1]; double root_id; Tcl_ResetResult (interp); if (argc < 2 || argc > 4) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " filename ?mode? ?type?\"", NULL); return TCL_ERROR; } if (cgioNum != 0) { cgio_close_file (cgioNum); cgioNum = 0; } mode = CGIO_MODE_READ; type = CGIO_FILE_NONE; if (argc > 2) { switch (argv[2][0]) { case 'r': case 'R': mode = CGIO_MODE_READ; break; case 'w': case 'W': case 'n': case 'N': mode = CGIO_MODE_WRITE; break; case 'm': case 'M': case 'a': case 'A': case 'o': case 'O': mode = CGIO_MODE_MODIFY; break; default: Tcl_SetResult (interp, "unknown file mode", TCL_STATIC); return TCL_ERROR; } if (argc > 3) { switch (argv[3][0]) { case 'a': case 'A': type = CGIO_FILE_ADF; break; case 'h': case 'H': type = CGIO_FILE_HDF5; break; default: Tcl_SetResult (interp, "unknown file type", TCL_STATIC); return TCL_ERROR; } } } if (cgio_open_file (argv[1], mode, type, &cgio_num)) return (get_error (interp, "cgio_open_file")); if (cgio_get_root_id (cgio_num, &root_id)) return (get_error (interp, "cgio_get_root_id")); if (cgio_get_name (cgio_num, root_id, rootname)) return (get_error (interp, "cgio_get_name")); cgioNum = cgio_num; RootID = root_id; Tcl_AppendResult (interp, rootname, NULL); return TCL_OK; } /*---------- CGIOsave --------------------------------------------------- * save CGIO database *----------------------------------------------------------------------*/ static int CGIOsave (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int err, type, cgio_num; Tcl_ResetResult (interp); if (argc != 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " filename type\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } switch (argv[2][0]) { case 'a': case 'A': type = CGIO_FILE_ADF; break; case 'h': case 'H': type = CGIO_FILE_HDF5; break; default: Tcl_SetResult (interp, "unknown file type", TCL_STATIC); return TCL_ERROR; } if (cgio_open_file (argv[1], CGIO_MODE_WRITE, type, &cgio_num)) return (get_error (interp, "cgio_open_file")); err = cgio_copy_file (cgioNum, cgio_num, 1); cgio_close_file (cgio_num); if (err) return (get_error (interp, "cgio_copy_file")); return TCL_OK; } /*---------- CGIOclose -------------------------------------------------- * close CGIO database file *----------------------------------------------------------------------*/ static int CGIOclose (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int err; Tcl_ResetResult (interp); if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } err = cgio_close_file (cgioNum); cgioNum = 0; if (err) return (get_error (interp, "cgio_close_file")); return TCL_OK; } /*---------- CGIOcompress ----------------------------------------------- * remove empty space from CGIO database file *----------------------------------------------------------------------*/ static int CGIOcompress (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int err; Tcl_ResetResult (interp); if (argc != 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " filename\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } err = cgio_compress_file (cgioNum, argv[1]); if (err) return (get_error (interp, "cgio_compress_file")); return TCL_OK; } /*---------- CGIOnode --------------------------------------------------- * get type of node *----------------------------------------------------------------------*/ static int CGIOnode (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int len; double node_id; Tcl_ResetResult (interp); if (argc != 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (0 == strcmp (argv[1], "/")) { Tcl_SetResult (interp, "root", TCL_STATIC); return TCL_OK; } if (cgio_get_node_id (cgioNum, RootID, argv[1], &node_id) == 0) { if (cgio_is_link (cgioNum, node_id, &len) == 0 && len > 0) Tcl_SetResult (interp, "link", TCL_STATIC); else Tcl_SetResult (interp, "node", TCL_STATIC); } return TCL_OK; } /*---------- CGIOname --------------------------------------------------- * get/set name for a node *----------------------------------------------------------------------*/ static int CGIOname (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char name[CGIO_MAX_NAME_LENGTH+1]; double parent_id, node_id; Tcl_ResetResult (interp); if (argc < 2 || argc > 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?newname?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (argc == 3) { if (NULL == get_parent (interp, argv[1], &parent_id)) return TCL_ERROR; if (cgio_set_name (cgioNum, parent_id, node_id, argv[2])) return (get_error (interp, "cgio_set_name")); } if (cgio_get_name (cgioNum, node_id, name)) return (get_error (interp, "cgio_get_name")); Tcl_AppendResult (interp, name, NULL); return TCL_OK; } /*---------- CGIOlabel -------------------------------------------------- * get/set label for a node *----------------------------------------------------------------------*/ static int CGIOlabel (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char label[CGIO_MAX_LABEL_LENGTH+1]; double node_id; Tcl_ResetResult (interp); if (argc < 2 || argc > 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?newlabel?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (argc == 3) { if (cgio_set_label (cgioNum, node_id, argv[2])) return (get_error (interp, "cgio_set_label")); } if (cgio_get_label (cgioNum, node_id, label)) return (get_error (interp, "cgio_get_label")); Tcl_AppendResult (interp, label, NULL); return TCL_OK; } /*---------- CGIOtype --------------------------------------------------- * get data type for a node *----------------------------------------------------------------------*/ static int CGIOtype (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, ndim, err; cgsize_t np, dims[CGIO_MAX_DIMENSIONS]; char type[CGIO_MAX_DATATYPE_LENGTH+1]; double node_id; struct DataType *dtnew, *dtold; char *olddata, *newdata; Tcl_ResetResult (interp); if (argc == 1) { for (ndim = 0; ndim < NumDataTypes; ndim++) Tcl_AppendElement (interp, DataList[ndim].name); return TCL_OK; } if (argc > 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?newtype?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (argc > 2) { /* get new data type */ strncpy (type, argv[2], CGIO_MAX_DATATYPE_LENGTH); type[CGIO_MAX_DATATYPE_LENGTH] = 0; for (n = 0; n < CGIO_MAX_DATATYPE_LENGTH && type[n]; n++) { if (islower (type[n])) type[n] = toupper (type[n]); } dtnew = NULL; for (n = 0; n < NumDataTypes; n++) { if (0 == strncmp (type, DataList[n].name, 2)) { dtnew = &DataList[n]; break; } } if (NULL == dtnew) { Tcl_AppendResult (interp, "unrecognized data type", NULL); return TCL_ERROR; } /* get old data type */ dtold = data_type (interp, node_id); if (NULL == dtold) return TCL_ERROR; /* convert the data */ if (dtnew->type != dtold->type) { /* get current data size */ np = 0; if (cgio_get_dimensions (cgioNum, node_id, &ndim, dims)) return (get_error (interp, "cgio_get_dimensions")); if (ndim > 0) { for (np = 1, n = 0; n < ndim; n++) np *= dims[n]; } newdata = NULL; if (np > 0 && dtold->size > 0) { olddata = (char *) malloc ((size_t)(np * dtold->size)); if (NULL == olddata) { Tcl_AppendResult (interp, "malloc failed for data", NULL); return TCL_ERROR; } if (cgio_read_all_data (cgioNum, node_id, olddata)) { free (olddata); return (get_error (interp, "cgio_read_all_data")); } switch (dtold->type) { case C1data: newdata = convert_C1 ((size_t)np, olddata, dtnew); break; case B1data: newdata = convert_B1 ((size_t)np, olddata, dtnew); break; case I4data: newdata = convert_I4 ((size_t)np, olddata, dtnew); break; case U4data: newdata = convert_U4 ((size_t)np, olddata, dtnew); break; case I8data: newdata = convert_I8 ((size_t)np, olddata, dtnew); break; case U8data: newdata = convert_U8 ((size_t)np, olddata, dtnew); break; case R4data: newdata = convert_R4 ((size_t)np, olddata, dtnew); break; case R8data: newdata = convert_R8 ((size_t)np, olddata, dtnew); break; case X4data: newdata = convert_X4 ((size_t)np, olddata, dtnew); break; case X8data: newdata = convert_X8 ((size_t)np, olddata, dtnew); break; } if (newdata != olddata) free (olddata); } /* rewrite the data */ if (NULL == newdata) ndim = 0; if (cgio_set_dimensions (cgioNum, node_id, dtnew->name, ndim, dims)) return (get_error (interp, "cgio_set_dimensions")); if (NULL != newdata) { err = cgio_write_all_data (cgioNum, node_id, newdata); free (newdata); if (err) return (get_error (interp, "cgio_write_all_data")); } } } if (cgio_get_data_type (cgioNum, node_id, type)) return (get_error (interp, "cgio_get_data_type")); Tcl_AppendResult (interp, type, NULL); return TCL_OK; } /*---------- CGIOdimensions --------------------------------------------- * get/set data dimensions for a node *----------------------------------------------------------------------*/ static int CGIOdimensions (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n; int ndim; cgsize_t dims[CGIO_MAX_DIMENSIONS]; double node_id; CONST char **args; char str[65]; Tcl_ResetResult (interp); if (argc < 2 || argc > 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?newdimensions?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (argc > 2) { if (cgio_get_data_type (cgioNum, node_id, str)) return (get_error (interp, "cgio_get_data_type")); if (TCL_OK != Tcl_SplitList (interp, argv[2], &ndim, &args)) return TCL_ERROR; if (ndim > CGIO_MAX_DIMENSIONS) { Tcl_Free ((char *)args); Tcl_AppendResult (interp, "invalid number of dimensions", NULL); return TCL_ERROR; } if (ndim) { for (n = 0; n < ndim; n++) dims[n] = atoi (args[n]); Tcl_Free ((char *)args); } if (cgio_set_dimensions (cgioNum, node_id, str, ndim, dims)) return (get_error (interp, "cgio_set_dimensions")); } if (cgio_get_dimensions (cgioNum, node_id, &ndim, dims)) return (get_error (interp, "cgio_get_dimensions")); if (ndim > 0) { for (n = 0; n < ndim; n++) { sprintf (str, "%ld", (long)dims[n]); Tcl_AppendElement (interp, str); } } return TCL_OK; } /*---------- CGIOsize --------------------------------------------------- * get number of bytes of data for a node *----------------------------------------------------------------------*/ static int CGIOsize (ClientData data, Tcl_Interp *interp, int argc, char **argv) { cgsize_t np; char str[65]; double node_id; struct DataType *type; Tcl_ResetResult (interp); if (argc != 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; np = data_size (interp, node_id); if (np == -1) return TCL_ERROR; type = data_type (interp, node_id); if (NULL == type) return TCL_ERROR; sprintf (str, "%u", (unsigned)np * (unsigned)type->bytes); Tcl_AppendResult (interp, str, NULL); return TCL_OK; } /*---------- CGIOread --------------------------------------------------- * read node data *----------------------------------------------------------------------*/ static int CGIOread (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n; cgsize_t np; char *values, str[65]; double node_id; struct DataType *dt; Tcl_ResetResult (interp); if (argc < 2 || argc > 14) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?range1 range2 ...?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; np = data_size (interp, node_id); if (np == -1) return TCL_ERROR; dt = data_type (interp, node_id); if (NULL == dt) return TCL_ERROR; if (np == 0 || dt->size == 0) return TCL_OK; values = (char *) malloc ((unsigned)np * (unsigned)dt->size + 1); if (NULL == values) { Tcl_AppendResult (interp, "malloc failed for data", NULL); return TCL_ERROR; } if (cgio_read_all_data (cgioNum, node_id, values)) { free (values); return (get_error (interp, "cgio_read_all_data")); } if (dt->type == C1data) { values[np] = 0; Tcl_AppendResult (interp, values, NULL); } else if (dt->type == B1data) { B1 *u = (B1 *)values; for (n = 0; n < np; n++, u++) { sprintf (str, "%d", (int)*u); Tcl_AppendElement (interp, str); } } else if (dt->type == I4data) { I4 *i = (I4 *)values; for (n = 0; n < np; n++, i++) { sprintf (str, "%d", *i); Tcl_AppendElement (interp, str); } } else if (dt->type == U4data) { U4 *u = (U4 *)values; for (n = 0; n < np; n++, u++) { sprintf (str, "%u", *u); Tcl_AppendElement (interp, str); } } else if (dt->type == I8data) { I8 *i = (I8 *)values; for (n = 0; n < np; n++, i++) { sprintf (str, "%ld", *i); Tcl_AppendElement (interp, str); } } else if (dt->type == U8data) { U8 *u = (U8 *)values; for (n = 0; n < np; n++, u++) { sprintf (str, "%lu", *u); Tcl_AppendElement (interp, str); } } else if (dt->type == R4data) { R4 *r = (R4 *)values; for (n = 0; n < np; n++, r++) { sprintf (str, "%g", *r); Tcl_AppendElement (interp, str); } } else if (dt->type == R8data) { R8 *r = (R8 *)values; for (n = 0; n < np; n++, r++) { sprintf (str, "%g", *r); Tcl_AppendElement (interp, str); } } else if (dt->type == X4data) { X4 *r = (X4 *)values; for (n = 0; n < np; n++, r++) { sprintf (str, "%g %g", *r, *(r+1)); Tcl_AppendElement (interp, str); r++; } } else if (dt->type == X8data) { X8 *r = (X8 *)values; for (n = 0; n < np; n++, r++) { sprintf (str, "%g %g", *r, *(r+1)); Tcl_AppendElement (interp, str); r++; } } else { free (values); Tcl_AppendResult (interp, "internal error - should not happen", NULL); return TCL_ERROR; } free (values); return TCL_OK; } /*---------- CGIOwrite -------------------------------------------------- * write node data *----------------------------------------------------------------------*/ static int CGIOwrite (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, nv, ns; int ndim; cgsize_t np, dims[CGIO_MAX_DIMENSIONS]; double node_id; CONST char **args; char *values, type[CGIO_MAX_DATATYPE_LENGTH+1]; struct DataType *dt = NULL; Tcl_ResetResult (interp); if (argc < 3 || argc > 5) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node type ?dimensions? ?data?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } /* get node ID for node */ if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; /* get data type */ strncpy (type, argv[2], CGIO_MAX_DATATYPE_LENGTH); type[CGIO_MAX_DATATYPE_LENGTH] = 0; for (n = 0; n < CGIO_MAX_DATATYPE_LENGTH && type[n]; n++) { if (islower (type[n])) type[n] = toupper (type[n]); } for (n = 0; n < NumDataTypes; n++) { if (0 == strncmp (type, DataList[n].name, 2)) { dt = &DataList[n]; break; } } if (dt == NULL) { Tcl_AppendResult (interp, "data type not recognized", NULL); return TCL_ERROR; } /* get dimensions */ ndim = 0; args = NULL; if (argc > 3 && TCL_OK != Tcl_SplitList (interp, argv[3], &ndim, &args)) return TCL_ERROR; if (ndim == 0) { if (cgio_set_dimensions (cgioNum, node_id, dt->name, ndim, dims)) return (get_error (interp, "cgio_set_dimensions")); return TCL_OK; } if (ndim > CGIO_MAX_DIMENSIONS) { Tcl_Free ((char *)args); Tcl_AppendResult (interp, "invalid number of dimensions", NULL); return TCL_ERROR; } for (n = 0; n < ndim; n++) dims[n] = (cgsize_t) atol (args[n]); Tcl_Free ((char *)args); for (np = 1, n = 0; n < ndim; n++) { if (dims[n] < 1) { Tcl_AppendResult (interp, "invalid dimension", NULL); return TCL_ERROR; } np *= dims[n]; } /* create data array */ if (NULL == (values = (char *) calloc ((size_t)np, dt->size))) { Tcl_AppendResult (interp, "malloc failed for data", NULL); return TCL_ERROR; } /* get data */ if (argc > 4) { if (dt->type == C1data && ndim == 1) { strncpy (values, argv[4], (size_t)np); for (ns = (int)strlen(argv[4]); ns < np; ns++) values[ns] = ' '; } else { if (TCL_OK != Tcl_SplitList (interp, argv[4], &nv, &args)) { free (values); return TCL_ERROR; } if (nv) { if (dt->type == C1data) np /= dims[0]; if (np > nv) np = nv; if (dt->type == C1data) { char *p = values; for (n = 0; n < np; n++) { strncpy (p, args[n], (size_t)dims[0]); for (ns = (int)strlen(args[n]); ns < dims[0]; ns++) p[ns] = ' '; p += dims[0]; } } else if (dt->type == B1data) { B1 *u = (B1 *)values; for (n = 0; n < np; n++, u++) *u = (B1) atoi (args[n]); } else if (dt->type == I4data) { I4 *i = (I4 *)values; for (n = 0; n < np; n++, i++) *i = (I4) atoi (args[n]); } else if (dt->type == U4data) { U4 *u = (U4 *)values; for (n = 0; n < np; n++, u++) *u = (U4) atoi (args[n]); } else if (dt->type == I8data) { I8 *i = (I8 *)values; for (n = 0; n < np; n++, i++) *i = (I8) atol (args[n]); } else if (dt->type == U8data) { U8 *u = (U8 *)values; for (n = 0; n < np; n++, u++) *u = (U8) atol (args[n]); } else if (dt->type == R4data) { R4 *r = (R4 *)values; for (n = 0; n < np; n++, r++) *r = (R4) atof (args[n]); } else if (dt->type == R8data) { R8 *r = (R8 *)values; for (n = 0; n < np; n++, r++) *r = (R8) atof (args[n]); } else if (dt->type == X4data) { float fr, fi; X4 *r = (X4 *)values; for (n = 0; n < np; n++, r++) { if (2 != sscanf (args[n], "%f %f", &fr, &fi)) { fr = (float) atof (args[n]); fi = 0.0; } *r = (R4) fr; *++r = (R4) fi; } } else if (dt->type == X8data) { double dr, di; X8 *r = (X8 *)values; for (n = 0; n < np; n++, r++) { if (2 != sscanf (args[n], "%lf %lf", &dr, &di)) { dr = atof (args[n]); di = 0.0; } *r = (X8) dr; *++r = (X8) di; } } else { Tcl_Free ((char *)args); free (values); Tcl_AppendResult (interp, "internal error - should not happen", NULL); return TCL_ERROR; } Tcl_Free ((char *)args); } } } if (cgio_set_dimensions (cgioNum, node_id, dt->name, ndim, dims)) { free (values); return (get_error (interp, "cgio_set_dimensions")); } n = cgio_write_all_data (cgioNum, node_id, values); free (values); if (n) return (get_error (interp, "cgio_write_all_data")); return TCL_OK; } /*---------- CGIOlink --------------------------------------------------- * create/retrieve link of a node *----------------------------------------------------------------------*/ static int CGIOlink (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int file_len, name_len; char *node, *name_in_file, *file_name; double parent_id, node_id; Tcl_ResetResult (interp); if (argc < 2 || argc > 4) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?linknode? ?linkfile?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (argc > 2) { if (NULL == (node = get_parent (interp, argv[1], &parent_id))) return TCL_ERROR; name_in_file = argv[2]; if (argc > 3) file_name = argv[3]; else file_name = NULL; if (cgio_create_link (cgioNum, parent_id, node, file_name, name_in_file, &node_id)) return (get_error (interp, "cgio_create_link")); } else { if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; } if (cgio_is_link (cgioNum, node_id, &name_len)) return (get_error (interp, "cgio_is_link")); if (name_len > 0) { if (cgio_link_size (cgioNum, node_id, &file_len, &name_len)) return (get_error (interp, "cgio_link_size")); file_name = (char *) malloc (file_len + name_len + 2); if (NULL == file_name) { Tcl_AppendResult (interp, "malloc failed for link", NULL); return TCL_ERROR; } name_in_file = file_name + file_len + 1; if (cgio_get_link (cgioNum, node_id, file_name, name_in_file)) { free (file_name); return (get_error (interp, "cgio_get_link")); } Tcl_AppendElement (interp, name_in_file); Tcl_AppendElement (interp, file_name); free (file_name); } return TCL_OK; } /*---------- CGIOchildren ----------------------------------------------- * retrieve children of a node *----------------------------------------------------------------------*/ static int CGIOchildren (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int n, nchildren, len; char name[CGIO_MAX_NAME_LENGTH+1]; double node_id, *ids; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (cgio_number_children (cgioNum, node_id, &nchildren)) return (get_error (interp, "cgio_number_children")); if (nchildren < 1) return TCL_OK; ids = (double *) malloc (nchildren * sizeof(double)); if (NULL == ids) { Tcl_AppendResult (interp, "malloc failed for IDs", NULL); return TCL_ERROR; } if (cgio_children_ids (cgioNum, node_id, 1, nchildren, &len, ids)) { free (ids); Tcl_ResetResult (interp); return (get_error (interp, "cgio_children_ids")); } for (n = 0; n < nchildren; n++) { if (cgio_get_name (cgioNum, ids[n], name)) { free (ids); Tcl_ResetResult (interp); return (get_error (interp, "cgio_get_name")); } Tcl_AppendElement (interp, name); } free (ids); return TCL_OK; } /*---------- CGIOnumchild ----------------------------------------------- * returns number of children for a node *----------------------------------------------------------------------*/ static int CGIOnumchild (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int nchildren; double node_id; char buf[33]; Tcl_ResetResult (interp); if (2 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (cgio_number_children (cgioNum, node_id, &nchildren)) return (get_error (interp, "cgio_number_children")); sprintf (buf, "%d", nchildren); Tcl_AppendResult (interp, buf, NULL); return TCL_OK; } /*---------- CGIOchildname ---------------------------------------------- * retrieve child name for child index *----------------------------------------------------------------------*/ static int CGIOchildname (ClientData data, Tcl_Interp *interp, int argc, char **argv) { int len; char name[CGIO_MAX_NAME_LENGTH+1]; double node_id; Tcl_ResetResult (interp); if (3 != argc) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node childnum\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (get_node (interp, argv[1], &node_id)) return TCL_ERROR; if (cgio_children_names (cgioNum, node_id, atoi(argv[2]), 1, CGIO_MAX_NAME_LENGTH+1, &len, name)) return (get_error (interp, "cgio_children_names")); Tcl_AppendResult (interp, name, NULL); return TCL_OK; } /*---------- CGIOcreate ------------------------------------------------- * create a new node *----------------------------------------------------------------------*/ static int CGIOcreate (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *node, label[CGIO_MAX_LABEL_LENGTH+1]; double parent_id, node_id; Tcl_ResetResult (interp); if (argc < 2 || argc > 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node ?label?\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (NULL == (node = get_parent (interp, argv[1], &parent_id))) return TCL_ERROR; if (cgio_create_node (cgioNum, parent_id, node, &node_id)) return (get_error (interp, "cgio_create_node")); if (argc > 2) { if (cgio_set_label (cgioNum, node_id, argv[2])) return (get_error (interp, "cgio_set_label")); } if (cgio_get_label (cgioNum, node_id, label)) return (get_error (interp, "cgio_get_label")); Tcl_AppendResult (interp, label, NULL); return TCL_OK; } /*---------- CGIOdelete ------------------------------------------------- * delete a node *----------------------------------------------------------------------*/ static int CGIOdelete (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *node; double parent_id, node_id; Tcl_ResetResult (interp); if (argc != 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (NULL == (node = get_parent (interp, argv[1], &parent_id))) return TCL_ERROR; if (cgio_get_node_id (cgioNum, parent_id, node, &node_id)) return (get_error (interp, "cgio_get_node_id")); if (cgio_delete_node (cgioNum, parent_id, node_id)) return (get_error (interp, "cgio_delete_node")); return TCL_OK; } /*---------- CGIOmove --------------------------------------------------- * move a node *----------------------------------------------------------------------*/ static int CGIOmove (ClientData data, Tcl_Interp *interp, int argc, char **argv) { char *node; double parent_id, node_id, new_parent_id; Tcl_ResetResult (interp); if (argc != 3) { Tcl_AppendResult (interp, "wrong # args: should be \"", argv[0], " node parent\"", NULL); return TCL_ERROR; } if (cgioNum == 0) { Tcl_AppendResult (interp, "no database is open", NULL); return TCL_ERROR; } if (NULL == (node = get_parent (interp, argv[1], &parent_id))) return TCL_ERROR; if (cgio_get_node_id (cgioNum, parent_id, node, &node_id)) return (get_error (interp, "cgio_get_node_id")); if (get_node (interp, argv[2], &new_parent_id)) return TCL_ERROR; if (cgio_move_node (cgioNum, parent_id, node_id, new_parent_id)) return (get_error (interp, "cgio_move_node")); return TCL_OK; } #ifdef SINGLE_COMMAND /*---------- CGIOcommand ---------------------------------------- * process CGIO command *--------------------------------------------------------------*/ static int CGIOcommand (ClientData data, Tcl_Interp *interp, int argc, char **argv) { static char usg_msg[] = "CGIO version\n" "CGIO supported ?type?\n" "CGIO open filename ?status? ?format?\n" "CGIO save filename format\n" "CGIO compress filename\n" "CGIO close\n" "CGIO node node\n" "CGIO name node ?newname?\n" "CGIO label node ?newlabel?\n" "CGIO type node ?newtype?\n" "CGIO dimensions node ?newdimensions?\n" "CGIO size node\n" "CGIO read node ?range1 range2 ...?\n" "CGIO write node type dimensions data\n" "CGIO link node ?linknode? ?linkfile?\n" "CGIO children node\n" "CGIO numchild node\n" "CGIO childname node childnum\n" "CGIO create node ?label?\n" "CGIO delete node\n" "CGIO move node newparent\n"; if (argc < 2) { Tcl_SetResult (interp, usg_msg, TCL_STATIC); return TCL_ERROR; } if (0 == strcmp (argv[1], "version")) return CGIOversion (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "supported")) return CGIOsupported (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "open")) return CGIOopen (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "save")) return CGIOsave (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "close")) return CGIOclose (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "compress")) return CGIOcompress (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "node")) return CGIOnode (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "name")) return CGIOname (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "label")) return CGIOlabel (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "type")) return CGIOtype (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "dimensions")) return CGIOdimensions (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "size")) return CGIOsize (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "read")) return CGIOread (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "write")) return CGIOwrite (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "link")) return CGIOlink (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "children")) return CGIOchildren (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "numchild")) return CGIOnumchild (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "childname")) return CGIOchildname (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "create")) return CGIOcreate (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "delete")) return CGIOdelete (data, interp, argc-1, argv+1); if (0 == strcmp (argv[1], "move")) return CGIOmove (data, interp, argc-1, argv+1); Tcl_SetResult (interp, usg_msg, TCL_STATIC); return TCL_ERROR; } #endif /*---------- CGIOtcl_Init --------------------------------------- * Initialize and create the commands *--------------------------------------------------------------*/ #if defined(_WIN32) && defined(BUILD_DLL) __declspec(dllexport) #endif int CGIOtcl_Init(Tcl_Interp *interp) { #ifdef SINGLE_COMMAND Tcl_CreateCommand (interp, "CGIO", (Tcl_CmdProc *)CGIOcommand, (ClientData)0, (Tcl_CmdDeleteProc *)0); #else Tcl_CreateCommand (interp, "CGIOversion", (Tcl_CmdProc *)CGIOversion, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOsupported", (Tcl_CmdProc *)CGIOsupported, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOopen", (Tcl_CmdProc *)CGIOopen, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOsave", (Tcl_CmdProc *)CGIOsave, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOclose", (Tcl_CmdProc *)CGIOclose, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOcompress", (Tcl_CmdProc *)CGIOcompress, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOnode", (Tcl_CmdProc *)CGIOnode, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOname", (Tcl_CmdProc *)CGIOname, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOlabel", (Tcl_CmdProc *)CGIOlabel, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOtype", (Tcl_CmdProc *)CGIOtype, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOdimensions", (Tcl_CmdProc *)CGIOdimensions, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOsize", (Tcl_CmdProc *)CGIOsize, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOread", (Tcl_CmdProc *)CGIOread, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOwrite", (Tcl_CmdProc *)CGIOwrite, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOlink", (Tcl_CmdProc *)CGIOlink, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOchildren", (Tcl_CmdProc *)CGIOchildren, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOnumchild", (Tcl_CmdProc *)CGIOnumchild, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOchildname", (Tcl_CmdProc *)CGIOchildname, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOcreate", (Tcl_CmdProc *)CGIOcreate, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOdelete", (Tcl_CmdProc *)CGIOdelete, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGIOmove", (Tcl_CmdProc *)CGIOmove, (ClientData)0, (Tcl_CmdDeleteProc *)0); #endif Tcl_CreateCommand (interp, "CGNSversion", (Tcl_CmdProc *)CGNSversion, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_CreateCommand (interp, "CGNSfile", (Tcl_CmdProc *)CGNSfile, (ClientData)0, (Tcl_CmdDeleteProc *)0); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsview/cgiowish.c000066400000000000000000000100401343724673500206700ustar00rootroot00000000000000/* * tkAppInit.c -- * * Provides a default version of the Tcl_AppInit procedure for * use in wish and similar Tk-based applications. * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include "tk.h" #include "locale.h" #ifdef TK_TEST extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* TK_TEST */ extern int CGIOtcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); /* *---------------------------------------------------------------------- * * main -- * * This is the main program for the application. * * Results: * None: Tk_Main never returns here, so this procedure never * returns either. * * Side effects: * Whatever the application does. * *---------------------------------------------------------------------- */ int main(argc, argv) int argc; /* Number of command-line arguments. */ char **argv; /* Values of command-line arguments. */ { /* * The following #if block allows you to change the AppInit * function by using a #define of TCL_LOCAL_APPINIT instead * of rewriting this entire file. The #if checks for that * #define and uses Tcl_AppInit if it doesn't exist. */ #ifndef TK_LOCAL_APPINIT #define TK_LOCAL_APPINIT Tcl_AppInit #endif extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp)); /* * The following #if block allows you to change how Tcl finds the startup * script, prime the library or encoding paths, fiddle with the argv, * etc., without needing to rewrite Tk_Main() */ #ifdef TK_LOCAL_MAIN_HOOK extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); TK_LOCAL_MAIN_HOOK(&argc, &argv); #endif Tk_Main(argc, argv, TK_LOCAL_APPINIT); return 0; /* Needed only to prevent compiler warning. */ } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); #ifdef TK_TEST if (Tcltest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, (Tcl_PackageInitProc *) NULL); if (Tktest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tktest", Tktest_Init, (Tcl_PackageInitProc *) NULL); #endif /* TK_TEST */ /* * Call the init procedures for included packages. Each call should * look like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. */ if (CGIOtcl_Init(interp) == TCL_ERROR) return TCL_ERROR; /* * Call Tcl_CreateCommand for application-specific commands, if * they weren't already created by the init procedures called above. */ /* * Specify a user-specific startup file to invoke if the application * is run interactively. Typically the startup file is "~/.apprc" * where "app" is the name of the application. If this line is deleted * then no user-specific startup file will be run under any conditions. */ Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); return TCL_OK; } CGNS-3.4.0/src/cgnstools/cgnsview/cgns.tcl000066400000000000000000002255331343724673500203650ustar00rootroot00000000000000 array set CGNSnodes { AdditionalExponents {1 AdditionalExponents_t R4 3 0} AdditionalFamilyName {0 AdditionalFamilyName_t C1 {} 1} AdditionalUnits {1 AdditionalUnits_t C1 {32 3} 0} ArbitraryGridMotion {0 ArbitraryGridMotion_t C1 {} 1} ArbitraryGridMotionPointers {1 DataArray_t C1 32 0} Area {1 Area_t MT {} 0} AreaType {1 AreaType_t C1 {} 0} AverageInterface {1 AverageInterface_t MT {} 0} AverageInterfaceType {1 AverageInterfaceType_t C1 {} 0} Axisymmetry {1 Axisymmetry_t MT {} 0} AxisymmetryAngle {1 DataArray_t R4 1 0} AxisymmetryAxisVector {1 DataArray_t R4 2 0} AxisymmetryReferencePoint {1 DataArray_t R4 2 0} BaseIterativeData {0 BaseIterativeData_t I4 1 0} BC {0 BC_t C1 {} 1} BCData {0 BCData_t MT {} 0} BCDataSet {0 BCDataSet_t C1 {} 1} BCProperty {1 BCProperty_t MT {} 0} BCRegionName {1 Descriptor_t C1 {} 1} CellListDonor {1 IndexArray_t I4 {} 0} CGNSBase {0 CGNSBase_t I4 2 1} CGNSLibraryVersion {1 CGNSLibraryVersion_t R4 1 0} ChemicalKineticsModel {1 ChemicalKineticsModel_t C1 {} 0} ConvergenceDataArray {1 DataArray_t R4 {} 1} CoordinateNames {1 DataArray_t C1 {32 2} 0} CoordinateData {0 DataArray_t R4 {} 1} DataArray {0 DataArray_t {} {} 1} DataClass {1 DataClass_t C1 {} 0} DataConversion {1 DataConversion_t R4 2 0} Descriptor {0 Descriptor_t C1 {} 1} DiffusionModel {1 \"int[1+...+IndexDimension]\" I4 {} 0} DimensionalExponents {1 DimensionalExponents_t R4 5 0} DimensionalUnits {1 DimensionalUnits_t C1 {32 5} 0} DirichletData {1 BCData_t MT {} 0} DiscreteData {0 DiscreteData_t MT {} 1} DiscreteDataArray {0 DataArray_t R4 {} 1} ElementConnectivity {1 DataArray_t I4 {} 0} ElementList {1 IndexArray_t I4 {} 0} ElementRange {1 IndexRange_t I4 {} 0} Elements {0 Elements_t I4 2 1} EMConductivityModel {1 EMConductivityModel_t C1 {} 0} EMElectricFieldModel {1 EMElectricFieldModel_t C1 {} 0} EMMagneticFieldModel {1 EMMagneticFieldModel_t C1 {} 0} EquationDimension {1 \"int\" I4 1 0} Family {0 Family_t MT {} 1} FamilyBC {1 FamilyBC_t C1 {} 0} FamilyBCDataSet {0 FamilyBCDataSet_t C1 {} 1} FamilyName {1 FamilyName_t C1 {} 0} FamilyNameReference {0 FamilyName_t C1 {} 0} FamilyPointers {1 DataArray_t C1 32 0} FlowEquationSet {1 FlowEquationSet_t MT {} 0} FlowSolution {0 FlowSolution_t MT {} 1} FlowSolutionPointers {1 DataArray_t C1 32 0} GasModel {1 GasModel_t C1 {} 0} GeometryEntity {0 GeometryEntity_t MT {} 1} GeometryFile {1 GeometryFile_t C1 {} 0} GeometryFormat {1 GeometryFormat_t C1 {} 0} GeometryReference {0 GeometryReference_t MT {} 1} GlobalConvergenceHistory {1 ConvergenceHistory_t I4 1 0} GoverningEquations {1 GoverningEquations_t C1 {} 0} Gravity {1 Gravity_t MT {} 0} GravityVector {1 DataArray_t R4 3 0} GridConnectivity {0 GridConnectivity_t C1 {} 1} GridConnectivity1to1 {0 GridConnectivity1to1_t C1 {} 1} GridConnectivityProperty {1 GridConnectivityProperty_t MT {} 0} GridConnectivityRegionName {1 Descriptor_t C1 {} 1} GridConnectivityType {1 GridConnectivityType_t C1 {} 0} GridCoordinates {0 GridCoordinates_t MT {} 1} GridCoordinatesPointers {1 DataArray_t C1 32 0} GridLocation {1 GridLocation_t C1 {} 0} GridVelocity {0 DataArray_t R4 {} 1} IndexArray {0 IndexArray_t I4 {} 0} IndexRange {0 IndexRange_t I4 {} 0} IntegralData {0 IntegralData_t MT {} 1} IntegralDataValue {0 DataArray_t R4 1 1} InterpolantsDonor {1 DataArray_t R4 {} 0} InwardNormalIndex {1 \"int[IndexDimension]\" I4 {} 0} InwardNormalList {1 IndexArray_t R4 {} 0} IterationValues {1 DataArray_t I4 {} 0} NeumannData {1 BCData_t MT {} 0} NormDefinitions {1 Descriptor_t C1 {} 0} NumberOfFamilies {1 DataArray_t I4 {} 0} NumberOfZones {1 DataArray_t I4 {} 0} Ordinal {1 Ordinal_t I4 1 0} OriginLocation {1 DataArray_t R4 {3 2} 0} OversetHoles {0 OversetHoles_t MT {} 1} ParentData {1 DataArray_t I4 {} 0} ParentElements {1 DataArray_t I4 {} 0} ParentElementsPosition {1 DataArray_t I4 {} 0} Periodic {1 Periodic_t MT {} 0} PointList {1 IndexArray_t I4 {} 0} PointListDonor {1 IndexArray_t I4 {} 0} PointRange {1 IndexRange_t I4 {} 0} PointRangeDonor {1 IndexRange_t I4 {} 0} ReferenceState {1 ReferenceState_t MT {} 0} ReferenceStateDescription {1 Descriptor_t C1 {} 0} ReferenceStateValue {0 DataArray_t R4 1 1} RegionName {1 DataArray_t C1 32 0} RigidGridMotion {0 RigidGridMotion_t C1 {} 1} RigidGridMotionPointers {1 DataArray_t C1 32 0} RigidRotationAngle {1 DataArray_t R4 3 0} RigidRotationRate {1 DataArray_t R4 3 0} RigidVelocity {1 DataArray_t R4 3 0} Rind {1 Rind_t I4 {} 0} RotatingCoordinates {1 RotatingCoordinates_t MT {} 0} RotationAngle {1 DataArray_t R4 3 0} RotationCenter {1 DataArray_t R4 3 0} RotationRateVector {1 DataArray_t R4 3 0} SimulationType {1 SimulationType_t C1 {} 0} SolutionData {0 DataArray_t R4 {} 1} SurfaceArea {1 DataArray_t R4 1 0} ThermalConductivityModel {1 ThermalConductivityModel_t C1 {} 0} ThermalRelaxationModel {1 ThermalRelaxationModel_t C1 {} 0} TimeValues {1 DataArray_t R4 {} 0} Transform {1 \"int[IndexDimension]\" I4 {} 0} Translation {1 DataArray_t R4 3 0} TurbulenceClosure {1 TurbulenceClosure_t C1 {} 0} TurbulenceModel {1 TurbulenceModel_t C1 {} 0} UserDefinedData {0 UserDefinedData_t MT {} 1} ViscosityModel {1 ViscosityModel_t C1 {} 0} WallFunction {1 WallFunction_t MT {} 0} WallFunctionType {1 WallFunctionType_t C1 {} 0} Zone {0 Zone_t I4 {} 1} ZoneBC {1 ZoneBC_t MT {} 0} ZoneConvergenceHistory {1 ConvergenceHistory_t I4 1 0} ZoneGridConnectivity {1 ZoneGridConnectivity_t MT {} 0} ZoneGridConnectivityPointers {1 DataArray_t C1 32 0} ZoneIterativeData {0 ZoneIterativeData_t MT {} 0} ZonePointers {1 DataArray_t C1 32 0} ZoneSubRegion {0 ZoneSubRegion_t I4 {} 1} ZoneSubRegionPointers {1 DataArray_t C1 32 0} ZoneType {1 ZoneType_t C1 {} 0} } array set CGNSnodeChildren { / {CGNSBase CGNSLibraryVersion} ArbitraryGridMotion_t {DataClass Descriptor DimensionalUnits \ GridLocation GridVelocity Rind UserDefinedData} Area_t {AreaType Descriptor RegionName SurfaceArea UserDefinedData} AverageInterface_t {AverageInterfaceType Descriptor UserDefinedData} Axisymmetry_t {AxisymmetryAngle AxisymmetryAxisVector \ AxisymmetryReferencePoint CoordinateNames DataClass \ Descriptor DimensionalUnits UserDefinedData} BaseIterativeData_t {DataArray DataClass Descriptor DimensionalUnits \ FamilyPointers IterationValues NumberOfFamilies NumberOfZones \ TimeValues UserDefinedData ZonePointers} BC_t {BCDataSet BCProperty DataClass Descriptor DimensionalUnits \ ElementList ElementRange FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange \ ReferenceState UserDefinedData} BCData_t {DataArray DataClass Descriptor DimensionalUnits UserDefinedData} BCDataSet_t {DataClass Descriptor DimensionalUnits DirichletData \ NeumannData ReferenceState UserDefinedData} BCProperty_t {Area Descriptor UserDefinedData WallFunction} CGNSBase_t {Axisymmetry BaseIterativeData DataClass Descriptor \ DimensionalUnits Family FlowEquationSet GlobalConvergenceHistory \ Gravity IntegralData ReferenceState RotatingCoordinates \ SimulationType UserDefinedData Zone} ChemicalKineticsModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} ConvergenceHistory_t {ConvergenceDataArray DataClass Descriptor \ DimensionalUnits NormDefinitions UserDefinedData} DataArray_t {DataConversion DataClass Descriptor \ DimensionalExponents DimensionalUnits} DiscreteData_t {DataClass Descriptor DimensionalUnits \ DiscreteDataArray GridLocation Rind UserDefinedData} Elements_t {Descriptor ElementConnectivity ElementRange \ ParentData Rind UserDefinedData} Family_t {Descriptor FamilyBC GeometryReference Ordinal UserDefinedData} FamilyBCDataSet_t {DataClass Descriptor DimensionalUnits DirichletData \ NeumannData ReferenceState UserDefinedData} FlowEquationSet_t {ChemicalKineticsModel DataClass Descriptor \ DimensionalUnits EquationDimension GasModel GoverningEquations \ ThermalConductivityModel ThermalRelaxationModel TurbulenceClosure \ TurbulenceModel UserDefinedData ViscosityModel} FlowSolution_t {DataClass Descriptor DimensionalUnits \ GridLocation Rind SolutionData UserDefinedData} GasModel_t {DataArray DataClass Descriptor DimensionalUnits \ UserDefinedData} GeometryReference_t {Descriptor GeometryEntity GeometryFile \ GeometryFormat UserDefinedData} GoverningEquations_t {Descriptor DiffusionModel UserDefinedData} Gravity_t {DataClass Descriptor DimensionalUnits \ GravityVector UserDefinedData} GridConnectivity_t {CellListDonor Descriptor GridConnectivityProperty \ GridConnectivityType GridLocation InterpolantsDonor Ordinal \ PointList PointListDonor PointRange UserDefinedData} GridConnectivity1to1_t {Descriptor Ordinal PointRange PointRangeDonor \ Transform UserDefinedData} GridConnectivityProperty_t {AverageInterface Descriptor Periodic \ UserDefinedData} GridCoordinates_t {CoordinateData DataClass Descriptor DimensionalUnits \ Rind UserDefinedData} IntegralData_t {DataClass Descriptor DimensionalUnits \ IntegralDataValue UserDefinedData} OversetHoles_t {Descriptor GridLocation PointList PointRange \ UserDefinedData} Periodic_t {DataClass Descriptor DimensionalUnits RotationAngle \ RotationCenter Translation UserDefinedData} ReferenceState_t {DataClass Descriptor DimensionalUnits \ ReferenceStateDescription ReferenceStateValue UserDefinedData} RigidGridMotion_t {DataArray DataClass Descriptor DimensionalUnits \ OriginLocation RigidRotationAngle RigidRotationRate \ RigidVelocity UserDefinedData} RotatingCoordinates_t {DataClass Descriptor DimensionalUnits \ RotationCenter RotationRateVector UserDefinedData} ThermalConductivityModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} ThermalRelaxationModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} TurbulenceClosure_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} TurbulenceModel_t {DataArray DataClass Descriptor DiffusionModel \ DimensionalUnits UserDefinedData} UserDefinedData_t {DataArray DataClass Descriptor DimensionalUnits} ViscosityModel_t {DataArray DataClass Descriptor DimensionalUnits \ UserDefinedData} WallFunction_t {Descriptor UserDefinedData WallFunctionType} Zone_t {ArbitraryGridMotion DataClass Descriptor DiscreteData \ DimensionalUnits Elements FamilyName FlowEquationSet FlowSolution \ GridCoordinates IntegralData Ordinal ReferenceState RigidGridMotion \ RotatingCoordinates UserDefinedData ZoneBC ZoneConvergenceHistory \ ZoneGridConnectivity ZoneIterativeData ZoneType} ZoneBC_t {BC DataClass Descriptor DimensionalUnits ReferenceState \ UserDefinedData} ZoneGridConnectivity_t {Descriptor GridConnectivity \ GridConnectivity1to1 OversetHoles UserDefinedData} ZoneIterativeData_t {ArbitraryGridMotionPointers DataArray DataClass \ Descriptor DimensionalUnits FlowSolutionPointers \ GridCoordinatesPointers RigidGridMotionPointers UserDefinedData} ZoneSubRegion_t {BCRegionName DataArray DataClass DimensionalUnits \ Descriptor FamilyName GridConnectivityRegionName GridLocation \ PointList PointRange Rind UserDefinedData} } array set CGNSdataValues { AdditionalUnits_t {\ {Null UserDefined Ampere Abampere Statampere Edison auCurrent} \ {Null UserDefined Mole Entities StandardCubicFoot StandardCubicMeter} \ {Null UserDefined Candela Candle Carcel Hefner Violle}} AngleUnits_t {Null UserDefined Degree Radian} ArbitraryGridMotion_t {Null UserDefined NonDeformingGrid DeformingGrid} AreaType_t {Null UserDefined BleedArea CaptureArea} AverageInterfaceType_t {Null UserDefined AverageAll AverageCircumferential \ AverageRadial AverageI AverageJ AverageK} BC_t {Null UserDefined BCAxisymmetricWedge BCDegenerateLine \ BCDegeneratePoint BCDirichlet BCExtrapolate BCFarfield BCGeneral \ BCInflow BCInflowSubsonic BCInflowSupersonic BCNeumann BCOutflow \ BCOutflowSubsonic BCOutflowSupersonic BCSymmetryPlane BCSymmetryPolar \ BCTunnelInflow BCTunnelOutflow BCWall BCWallInviscid BCWallViscous \ BCWallViscousHeatFlux BCWallViscousIsothermal FamilySpecified} BCData_t {Null UserDefined Dirichlet Neumann} BCDataSet_t {Null UserDefined BCAxisymmetricWedge BCDegenerateLine \ BCDegeneratePoint BCDirichlet BCExtrapolate BCGeneral \ BCInflowSubsonic BCInflowSupersonic BCNeumann \ BCOutflowSubsonic BCOutflowSupersonic BCSymmetryPlane BCSymmetryPolar \ BCTunnelInflow BCTunnelOutflow BCWall BCWallInviscid BCWallViscous \ BCWallViscousHeatFlux BCWallViscousIsothermal FamilySpecified} ChemicalKineticsModel_t {Null UserDefined Frozen ChemicalEquilibCurveFit \ ChemicalEquilibMinimization ChemicalNonequilib} DataClass_t {Null UserDefined Dimensional NormalizedByDimensional \ NormalizedByUnknownDimensional NondimensionalParameter \ DimensionlessConstant} DimensionalUnits_t {\ {Null UserDefined Kilogram Gram Slug PoundMass} \ {Null UserDefined Meter Centimeter Millimeter Foot Inch} \ {Null UserDefined Second} \ {Null UserDefined Kelvin Celcius Rankine Fahrenheit} \ {Null UserDefined Radian Degree}} EMConductivityModel_t {Null UserDefined Constant Frozen \ Equilibrium_LinRessler Chemistry_LinRessler} EMElectricFieldModel_t {Null UserDefined Voltage Interpolated \ Constant Frozen} EMMagneticFieldModel_t {Null UserDefined Interpolated \ Constant Frozen} FamilyBC_t {Null UserDefined BCAxisymmetricWedge BCDegenerateLine \ BCDegeneratePoint BCDirichlet BCExtrapolate BCFarfield BCGeneral \ BCInflow BCInflowSubsonic BCInflowSupersonic BCNeumann BCOutflow \ BCOutflowSubsonic BCOutflowSupersonic BCSymmetryPlane BCSymmetryPolar \ BCTunnelInflow BCTunnelOutflow BCWall BCWallInviscid BCWallViscous \ BCWallViscousHeatFlux BCWallViscousIsothermal FamilySpecified} FamilyBCDataSet_t {Null UserDefined BCAxisymmetricWedge BCDegenerateLine \ BCDegeneratePoint BCDirichlet BCExtrapolate BCGeneral \ BCInflowSubsonic BCInflowSupersonic BCNeumann \ BCOutflowSubsonic BCOutflowSupersonic BCSymmetryPlane BCSymmetryPolar \ BCTunnelInflow BCTunnelOutflow BCWall BCWallInviscid BCWallViscous \ BCWallViscousHeatFlux BCWallViscousIsothermal} GasModel_t {Null UserDefined Ideal VanderWaals CaloricallyPerfect \ ThermallyPerfect ConstantDensity RedlichKwong} GoverningEquations_t {Null UserDefined FullPotential Euler NSLaminar \ NSTurbulent NSLaminarIncompressible NSTurbulentIncompressible} GridConnectivityType_t {Null UserDefined Overset Abutting Abutting1to1} GridLocation_t {Null UserDefined Vertex CellCenter FaceCenter \ IFaceCenter JFaceCenter KFaceCenter EdgeCenter} LengthUnits_t {Null UserDefined Meter Centimeter Millimeter Foot Inch} MassUnits_t {Null UserDefined Kilogram Gram Slug PoundMass} RigidGridMotion_t {Null UserDefined ConstantRate VariableRate} SimulationType_t {Null UserDefined TimeAccurate NonTimeAccurate} TemperatureUnits_t {Null UserDefined Kelvin Celcius Rankine Fahrenheit} ThermalConductivityModel_t {Null UserDefined PowerLaw SutherlandLaw \ ConstantPrandtl} ThermalRelaxationModel_t {Null UserDefined Frozen ThermalEquilib \ ThermalNonequilib} TimeUnits_t {Null UserDefined Second} TurbulenceClosure_t {Null UserDefined EddyViscosity ReynoldsStress \ ReynoldsStressAlgebraic} TurbulenceModel_t {Null UserDefined \ Algebraic_BaldwinLomax Algebraic_CebeciSmith \ HalfEquation_JohnsonKing OneEquation_BaldwinBarth \ OneEquation_SpalartAllmaras TwoEquation_JonesLaunder \ TwoEquation_MenterSST TwoEquation_Wilcox} ViscosityModel_t {Null UserDefined Constant PowerLaw SutherlandLaw} WallFunctionType_t {Null UserDefined Generic} ZoneType_t {Null UserDefined Structured Unstructured} DataType_t {Null UserDefined Integer RealSingle RealDouble Character} ElementType_t {Null UserDefined NODE BAR_2 BAR_3 TRI_3 TRI_6 QUAD_4 \ QUAD_8 QUAD_9 TETRA_4 TETRA_10 PYRA_5 PYRA_14 PENTA_6 PENTA_15 \ PENTA_18 HEXA_8 HEXA_20 HEXA_27 MIXED NGON_n} PointSet_t {Null UserDefined PointList PointListDonor PointRange \ PointRangeDonor ElementRange ElementList CellListDonor} } array set CGNSnodeDesc { AdditionalExponents_t {AdditionalExponents AdditionalExponents_t {0,1} \ {R4 or R8} 1 3 {ElectricCurrentExponent, SubstanceAmountExponent,\ LuminousIntensityExponent}} AdditionalFamilyName_t {{user defined} AdditionalFamilyName_t {0,N} \ C1 1 {length of string} {name of family}} AdditionalUnits_t {AdditionalUnits AdditionalUnits_t {0,1} C1 2 {32,3} \ {For ElectricCurrent, one of: Null, UserDefined, Ampere, Abampere,\ Statampere, Edison, auCurrent For SubstanceAmount, one of: Null, UserDefined, Mole, Entities,\ StandardCubicFoot, StandardCubicMeter For LuminousIntensity, one of: Null, UserDefined, Candela, Candle,\ Carcel, Hefner, Violle}} ArbitraryGridMotion_t {{user defined} ArbitraryGridMotion_t {0,N} C1 1 \ {length of string} {one of: Null, UserDefined, NonDeformingGrid,\ or DeformingGrid}} ArbitraryGridMotionPointers {ArbitraryGridMotionPointers DataArray_t {0,1} \ C1 2 {32,NumberOfSteps} {pointers to ArbitraryGridMotion_t nodes}} Area_t {Area Area_t {0,1} MT {} {} {}} AreaType_t {AreaType AreaType_t 1 C1 1 {length of string} {one of:\ Null, UserDefined, BleedArea, or CaptureArea}} AverageInterface_t {AverageInterface AverageInterface_t {0,1} MT {} {} {}} AverageInterfaceType_t {AverageInterfaceType AverageInterfaceType_t 1 \ C1 1 {length of string} {one of: Null, UserDefined, AverageAll,\ AverageCircumferential, AverageRadial, AverageI, AverageJ or AverageK}} Axisymmetry_t {Axisymmetry Axisymmetry_t {0,1} MT {} {} {}} AxisymmetryAngle {AxisymmetryAngle DataArray_t {0,1} R4 1 1 \ {circumferential extent}} AxisymmetryAxisVector {AxisymmetryAxisVector DataArray_t 1 R4 1 2 \ {direction cosines of rotation axis}} AxisymmetryReferencePoint {AxisymmetryReferencePoint DataArray_t 1 R4 1 2 \ {origin for defining rotation axis}} BaseIterativeData_t {{user defined} BaseIterativeData_t {0,1} I4 1 1 \ {NumberOfSteps}} BC_t {{user defined} BC_t {0,N} C1 1 {length of string} \ {one of: Null, UserDefined, BCAxisymmetricWedge, BCDegenerateLine,\ BCDegeneratePoint, BCDirichlet, BCExtrapolate, BCFarfield, BCGeneral,\ BCInflow, BCInflowSubsonic, BCInflowSupersonic, BCNeumann,\ BCOutflow, BCOutflowSubsonic, BCOutflowSupersonic,\ BCSymmetryPlane, BCSymmetryPolar, BCTunnelInflow,\ BCTunnelOutflow, BCWall, BCWallInviscid, BCWallViscous,\ BCWallViscousHeatFlux, BCWallViscousIsothermal or FamilySpecified}} BCData_t {{user defined} BCData_t {0,1} MT {} {} {}} BCDataSet_t {{user defined} BCDataSet_t {0,N} C1 1 {length of string} \ {BCTypeSimple value, one of: Null, UserDefined, BCAxisymmetricWedge,\ BCDegenerateLine, BCDegeneratePoint, BCDirichlet, BCExtrapolate,\ BCGeneral, BCInflowSubsonic, BCInflowSupersonic, BCNeumann,\ BCOutflowSubsonic, BCOutflowSupersonic, BCSymmetryPlane,\ BCSymmetryPolar, BCTunnelInflow, BCTunnelOutflow, BCWall,\ BCWallInviscid, BCWallViscous, BCWallViscousHeatFlux,\ BCWallViscousIsothermal or FamilySpecified}} BCProperty_t {BCProperty BCProperty_t {0,1} MT {} {} {}} BCRegionName {BCRegionName Descriptor_t {0,1} C1 1 \ {length of string} {name of a ZoneBC node}} CellListDonor {CellListDonor IndexArray_t {0,1} I4 2 \ {IndexDimension of donor,ListLength} \ {list of indices for cells on adjoining patch}} CGNSBase_t {{user defined} CGNSBase_t {0,N} I4 1 2 \ {CellDimension, PhysicalDimension}} CGNSLibraryVersion_t {CGNSLibraryVersion CGNSLibraryVersion_t 1 R4 1 1 \ {CGNS Mid-Level Library version number}} ChemicalKineticsModel_t {ChemicalKineticsModel ChemicalKineticsModel_t \ {0,1} C1 1 {length of string} {one of: Null, UserDefined, Frozen,\ ChemicalEquilibCurveFit, ChemicalEquilibMinimization,\ or ChemicalNonequilib}} ConvergenceDataArray {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ 1 NumIterations {convergence data}} ConvergenceHistory_t {{user defined} ConvergenceHistory_t {0,1} I4 1 1 \ {number of iterations}} CoordinateNames {CoordinateNames DataArray_t {0,1} C1 2 {32,2} \ {dataname identifiers for coordinates}} CoordinateData {{user defined} DataArray_t {0,N} {R4 or R8} 1 \ NumberOfVertices {coordinate component array. Data-name identifiers\ for coordinates are: CoordinateX, CoordinateY, CoordinateZ,\ CoordinateR, CoordinateTheta, CoordinatePhi, CoordinateXi,\ CoordinateEta, CoordinateZeta, CoordinateNormal and\ CoordinateTangential}} DataArray_t {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ {context dependent} {context dependent} {data values}} DataClass_t {DataClass DataClass_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, Dimensional, NormalizedByDimensional,\ NormalizedByUnknownDimensional, NondimensionalParameter or\ DimensionlessConstant}} DataConversion_t {DataConversion DataConversion_t {0,1} {R4 or R8} 1 2 \ {ConversionScale, ConversionOffset}} Descriptor_t {{user defined} Descriptor_t {0,N} C1 1 {length of string} \ {description string}} DimensionalExponents_t {DimensionalExponents DimensionalExponents_t {0,1} \ {R4 or R8} 1 5 {MassExponent, LengthExponent, TimeExponent,\ TemperatureExponent, AngleExponent}} DimensionalUnits_t {DimensionalUnits DimensionalUnits_t {0,1} C1 2 {32,5} \ {For mass, one of: Null, UserDefined, Kilogram, Gram, Slug, PoundMass For length, one of: Null, UserDefined, Meter, Centimeter, Millimeter, Foot, Inch For time, one of: Null, UserDefined, Second For temperature, one of: Null, UserDefined, Kelvin, Celsius, Rankine, Fahrenheit For angles, one of: Null, UserDefined, Degree, Radian}} DirichletData {DirichletData BCData_t {0,1} MT {} {} {}} DiscreteData_t {{user defined} DiscreteData_t {0,N} MT {} {} {}} DiscreteDataArray {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ IndexDimension {number of vertices or cells} {additional solution data\ not normally part of the flow solution}} ElementConnectivity {ElementConnectivity DataArray_t 1 I4 1 \ {ElementDataSize} {element connectivity table}} ElementList {ElementList IndexArray_t {0,1} I4 2 \ {IndexDimension,ListLength} {list of indices for cells}} ElementRange {ElementRange IndexRange_t 1 I4 1 2 {begin and end indices}} Elements_t {{user defined} Elements_t {0,N} I4 1 2 \ {ElementType, ElementSizeBoundary element types are: 0:Null, 1:UserDefined, 2:NODE, 3:BAR_2, 4:BAR_3,\ 5:TRI_3, 6:TRI_6, 7:QUAD_4, 8:QUAD_8, 9:QUAD_9, 10:TETRA_4, 11:TETRA_10,\ 12:PYRA_5, 13:PYRA_14, 14:PENTA_6, 15:PENTA_15, 16:PENTA_18, 17:HEXA_8,\ 18:HEXA_20, 19:HEXA_27, 20:MIXED, 21+:NGON_n}} EMConductivityModel_t {EMConductivityModel EMConductivityModel_t \ {0,1} C1 1 {length of string} {one of: Null, UserDefined, Constant,\ Frozen, Equilibrium_LinRessler or Chemistry_LinRessler}} EMElectricFieldModel_t {EMElectricFieldModel EMElectricFieldModel_t \ {0,1} C1 1 {length of string} {one of: Null, UserDefined, Voltage,\ Interpolated, Constant or Frozen}} EMMagneticFieldModel_t {EMMagneticFieldModel EMMagneticFieldModel_t \ {0,1} C1 1 {length of string} {one of: Null, UserDefined, Interpolated,\ Constant or Frozen}} EquationDimension {EquationDimension \"int\" {0,1} I4 1 1 \ {EquationDimension value}} Family_t {{user defined} Family_t {0,N} MT {} {} {}} FamilyBC_t {FamilyBC FamilyBC_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, BCAxisymmetricWedge, BCDegenerateLine,\ BCDegeneratePoint, BCDirichlet, BCExtrapolate, BCFarfield, BCGeneral,\ BCInflow, BCInflowSubsonic, BCInflowSupersonic, BCNeumann,\ BCOutflow, BCOutflowSubsonic, BCOutflowSupersonic,\ BCSymmetryPlane, BCSymmetryPolar, BCTunnelInflow,\ BCTunnelOutflow, BCWall, BCWallInviscid, BCWallViscous,\ BCWallViscousHeatFlux, BCWallViscousIsothermal or FamilySpecified}} FamilyBCDataSet_t {{user defined} FamilyBCDataSet_t {0,N} C1 1 {length of string} \ {BCTypeSimple value, one of: Null, UserDefined, BCAxisymmetricWedge,\ BCDegenerateLine, BCDegeneratePoint, BCDirichlet, BCExtrapolate,\ BCGeneral, BCInflowSubsonic, BCInflowSupersonic, BCNeumann,\ BCOutflowSubsonic, BCOutflowSupersonic, BCSymmetryPlane,\ BCSymmetryPolar, BCTunnelInflow, BCTunnelOutflow, BCWall,\ BCWallInviscid, BCWallViscous, BCWallViscousHeatFlux,\ BCWallViscousIsothermal}} FamilyName_t {FamilyName FamilyName_t {0,1} C1 1 {length of string} \ {name of CFD family}} FamilyNameReference {{FamilyParent or user defined} FamilyName_t {0,N} \ C1 1 {length of string} {name of family}} FamilyPointers {FamilyPointers DataArray_t {0,1} C1 3 \ {32,MaxNumberOfZones,NumberOfSteps} {pointers to Family_t nodes}} FlowEquationSet_t {FlowEquationSet FlowEquationSet_t {0,1} MT {} {} {}} FlowSolution_t {{user defined} FlowSolution_t {0,N} MT {} {} {}} FlowSolutionPointers {FlowSolutionPointers DataArray_t {0,1} C1 2 \ {32,NumberOfSteps} {pointers to FlowSolution_t nodes}} GasModel_t {GasModel GasModel_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, Ideal, VanderWaals, CaloricallyPerfect,\ ThermallyPerfect, ConstantDensity, or RedlichKwong}} GeometryEntity_t {{user defined} GeometryEntity_t {0,N} MT {} {} {}} GeometryFile_t {GeometryFile GeometryFile_t 1 C1 1 {length of string} \ {name of the geometry file}} GeometryFormat_t {GeometryFormat GeometryFormat_t 1 C1 1 {length of string} \ {name of the geometry format}} GeometryReference_t {{user defined} GeometryReference_t {0,N} MT {} {} {}} GlobalConvergenceHistory {GlobalConvergenceHistory ConvergenceHistory_t \ {0,1} I4 1 1 {number of iterations}} GoverningEquations_t {GoverningEquations GoverningEquations_t {0,1} \ C1 1 {length of string} {one of: Null, UserDefined, FullPotential,\ Euler, NSLaminar, NSTurbulent, NSLaminarIncompressible\ or NSTurbulentIncompressible}} Gravity_t {Gravity Gravity_t {0,1} MT {} {} {}} GravityVector {GravityVector DataArray_t 1 {R4 or R8} 1 PhysicalDimension \ {components of the gravity vector}} GridConnectivity_t {{user defined} GridConnectivity_t {0,N} C1 1 \ {length of string} {ZoneDonorName}} GridConnectivity1to1_t {{user defined} GridConnectivity1to1_t {0,N} C1 1 \ {length of string} {ZoneDonorName}} GridConnectivityProperty_t {GridConnectivityProperty \ GridConnectivityProperty_t {0,1} MT {} {} {}} GridConnectivityRegionName {GridConnectivityRegionName Descriptor_t {0,1} \ C1 1 {length of string} {name of a ZoneGridConnectivity node}} GridConnectivityType_t {GridConnectivityType GridConnectivityType_t {0,1} \ C1 1 {length of string} {one of: Null, UserDefined, Overset,\ Abutting, or Abutting1to1}} GridCoordinates_t {{user defined} GridCoordinates_t {0,N} MT {} {} {}} GridCoordinatesPointers {GridCoordinatesPointers DataArray_t {0,1} \ C1 2 {32,NumberOfSteps} {pointers to GridCoordinates_t nodes}} GridLocation_t {GridLocation GridLocation_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, Vertex, CellCenter, FaceCenter,\ IFaceCenter, JFaceCenter, KFaceCenter or EdgeCenter}} GridVelocity {{user defined} DataArray_t {0,N} {R4 or R8} 1 \ NumberOfVertices {component of grid velocity. Data-name identifiers\ are: GridVelocityX, GridVelocityY, GridVelocityZ, GridVelocityR,\ GridVelocityTheta, GridVelocityPhi, GridVelocityXi,\ GridVelocityEta and GridVelocityZeta}} IndexArray_t {{user defined} IndexArray_t {0,1} I4 2 \ {IndexDimension,number of items in the list} {Index coordinates of\ each point or element in the list}} IndexRange_t {{user defined} IndexRange_t {0,1} I4 2 {IndexDimension,2} \ {first indices, last indices}} \"int\" {{user defined} \"int\" {0,1} I4 1 1 {an integer value}} \"int[IndexDimension]\" {{user defined} \"int[IndexDimension]\" \ {0,1} I4 1 IndexDimension {array of integer values}} \"int[2*IndexDimension]\" {{user defined} \"int[2*IndexDimension]\" \ {0,1} I4 1 {2*IndexDimension} {array of integer values}} \"int[1+...+IndexDimension]\" {{user defined} \"int[1+...+IndexDimension]\" \ {0,1} I4 1 {1 + ... + IndexDimension} {array of integer values}} IntegralData_t {{user defined} IntegralData_t {0,N} MT {} {} {}} IntegralDataValue {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ 1 1 {integral data value}} InterpolantsDonor {InterpolantsDonor DataArray_t {0,1} {R4 or R8} 2 \ {CellDimension,PointListSize} {interpolants for each node}} InwardNormalIndex {InwardNormalIndex \"int[IndexDimension]\" {0,1} I4 \ 1 IndexDimension {index of inward normal}} InwardNormalList {InwardNormalList IndexArray_t {0,1} {R4 or R8} 2 \ {PhysicalDimension,number of items in the list} {physical-space\ normal vectors at each point or element in the list}} IterationValues {IterationValues DataArray_t {0,1} I4 1 NumberOfSteps \ {array of interation values}} NeumannData {NeumannData BCData_t {0,1} MT {} {} {}} NormDefinitions {NormDefinitions Descriptor_t {0,1} C1 1 \ {length of string} {description of convergence information}} NumberOfFamilies {NumberOfFamilies DataArray_t {0,1} I4 1 NumberOfSteps \ {array of number of families involved in each time step}} NumberOfZones {NumberOfZones DataArray_t {0,1} I4 1 NumberOfSteps \ {array of number of zones involved in each time step}} Ordinal_t {Ordinal Ordinal_t {0,1} I4 1 1 \ {user-defined ordinal number (an integer)}} OriginLocation {OriginLocation DataArray_t 1 R4 2 {PhysicalDimension,2} \ {coordinates of origin before and after motion}} OversetHoles_t {{user defined} OversetHoles_t {0,N} MT {} {} {}} ParentData {ParentData DataArray_t {0,1} I4 2 {ElementSize,4} \ {Parent1[ElementSize], Parent2[ElementSize], SideOfParent1[ElementSize],\ SideOfParent2[ElementSize]}} ParentElements {ParentElements DataArray_t {0,1} I4 2 {ElementSize,2} \ {Parent1[ElementSize], Parent2[ElementSize]}} ParentElementsPosition {ParentElementsPosition DataArray_t {0,1} I4 2 \ {ElementSize,2} {SideOfParent1[ElementSize], SideOfParent2[ElementSize]}} Periodic_t {Periodic Periodic_t {0,1} MT {} {} {}} PointList {PointList IndexArray_t {0,1} I4 2 {IndexDimension,ListLength} \ {list of indices for vertices or cells}} PointListDonor {PointListDonor IndexArray_t {0,1} I4 2 \ {IndexDimension of donor,ListLength} \ {list of indices for vertices or cells on adjoining patch}} PointRange {PointRange IndexRange_t {0,1} I4 2 {IndexDimension,2} \ {begin[IndexDimension], end[IndexDimension]}} PointRangeDonor {PointRangeDonor IndexRange_t {0,1} I4 2 \ {IndexDimension of donor,2} \ {begin[IndexDimension], end[IndexDimension] for adjoining patch}} ReferenceState_t {ReferenceState ReferenceState_t {0,1} MT {} {} {}} ReferenceStateDescription {ReferenceStateDescription Descriptor_t {0,1} \ C1 1 {length of string} {reference state description}} ReferenceStateValue {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ 1 1 {reference state quantity}} RegionName {RegionName DataArray_t 1 C1 1 32 {name of region}} RigidGridMotion_t {{user defined} RigidGridMotion_t {0,N} C1 1 \ {length of string} {one of: Null, UserDefined, ConstantRate\ or VariableRate}} RigidGridMotionPointers {RigidGridMotionPointers DataArray_t {0,1} C1 2 \ {32,NumberOfSteps} {pointers to RigidGridMotion_t nodes}} RigidRotationAngle {RigidRotationAngle DataArray_t {0,1} {R4 or R8} \ 1 PhysicalDimension {rotation angles about each axis of the\ translated coordinate system}} RigidRotationRate {RigidRotationRate DataArray_t {0,1} {R4 or R8} \ 1 PhysicalDimension {rotation rate vector about each axis of the\ translated coordinate system}} RigidVelocity {RigidVelocity DataArray_t {0,1} {R4 or R8} \ 1 PhysicalDimension {grid velocity vector of the origin translation}} Rind_t {Rind Rind_t {0,1} I4 1 {2*IndexDimension} \ {number of planes of extra data in low i, high i, low j, high j, etc.}} RotatingCoordinates_t {RotatingCoordinates RotatingCoordinates_t {0,1} \ MT {} {} {}} RotationAngle {RotationAngle DataArray_t 1 {R4 or R8} 1 \ PhysicalDimension {defines angle from current interface to\ the connecting interface}} RotationCenter {RotationCenter DataArray_t 1 {R4 or R8} 1 \ PhysicalDimension {coordinates of center of rotation}} RotationRateVector {RotationRateVector DataArray_t 1 R4 1 PhysicalDimension \ {components of the angular velocity about the center of rotation}} SimulationType_t {SimulationType SimulationType_t {0,1} C1 1 \ {length of string} {one of: Null, UserDefined, TimeAccurate\ or NonTimeAccurate}} SolutionData {{user defined} DataArray_t {0,N} {C1,I4,R4 or R8} \ IndexDimension {number of vertices or cells} {solution data.\ See the documentation for a list of data-name identifiers}} SurfaceArea {SurfaceArea DataArray_t 1 R4 1 1 {size of area}} ThermalConductivityModel_t {ThermalConductivityModel \ ThermalConductivityModel_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, PowerLaw, SutherlandLaw or ConstantPrandtl}} ThermalRelaxationModel_t {ThermalRelaxationModel \ ThermalRelaxationModel_t {0,1} C1 1 {length of string} \ {one of: Null, UserDefined, Frozen, ThermalEquilib or ThermalNonequilib}} TimeValues {TimeValues DataArray_t {0,1} {R4 or R8} 1 NumberOfSteps \ {array of iteration time values}} Transform {Transform \"int[IndexDimension]\" {0,1} I4 1 IndexDimension \ {shorthand for the connectivity transformation matrix}} Translation {Translation DataArray_t 1 {R4 or R8} 1 \ PhysicalDimension {defines translation from current interface to\ the connecting interface}} TurbulenceClosure_t {TurbulenceClosure TurbulenceClosure_t {0,1} C1 1 \ {length of string} {one of: Null, UserDefined, EddyViscosity,\ ReynoldsStress or ReynoldsStressAlgebraic}} TurbulenceModel_t {TurbulenceModel TurbulenceModel_t {0,1} C1 1 \ {length of string} {one of: Null, UserDefined,\ Algebraic_BaldwinLomax, Algebraic_CebeciSmith,\ HalfEquation_JohnsonKing, OneEquation_BaldwinBarth,\ OneEquation_SpalartAllmaras, TwoEquation_JonesLaunder,\ TwoEquation_MenterSST or TwoEquation_Wilcox}} UserDefinedData_t {{user defined} UserDefinedData_t {0,N} MT {} {} {}} ViscosityModel_t {ViscosityModel ViscosityModel_t {0,1} C1 1 \ {length of string} {one of: Null, UserDefined, Constant,\ PowerLaw or SutherlandLaw}} WallFunction_t {WallFunction WallFunction_t {0,1} MT {} {} {}} WallFunctionType_t {WallFunctionType WallFunctionType_t 1 C1 1 \ {length of string} {one of: Null, UserDefined, or Generic}} Zone_t {{user defined} Zone_t {0,N} I4 2 {IndexDimension,3} \ {VertexSize[IndexDimension], CellSize[IndexDimension],\ VertexSizeBoundary[IndexDimension]}} ZoneBC_t {ZoneBC ZoneBC_t {0,1} MT {} {} {}} ZoneConvergenceHistory {ZoneConvergenceHistory ConvergenceHistory_t \ {0,1} I4 1 1 {number of iterations}} ZoneGridConnectivity_t {ZoneGridConnectivity ZoneGridConnectivity_t \ {0,1} MT {} {} {}} ZoneGridConnectivityPointers {ZoneGridConnectivityPointers DataArray_t \ {0,1} C1 2 {32,NumberOfSteps} \ {pointers to ZoneGridConnectivity_t nodes}} ZoneIterativeData_t {{user defined} ZoneIterativeData_t {0,1} MT {} {} {}} ZonePointers {ZonePointers DataArray_t {0,1} C1 3 \ {32,MaxNumberOfZones,NumberOfSteps} {pointers to Zone_t nodes}} ZoneSubRegion_t {{user defined} ZoneSubRegion_t {0,N} I4 1 \ RegionCellDimension {region dimension}} ZoneSubRegionPointers {ZoneSubRegionPointers DataArray_t \ {0,1} C1 2 {32,NumberOfSteps} \ {pointers to ZoneSubRegion_t nodes}} ZoneType_t {ZoneType ZoneType_t 1 C1 1 {length of string} \ {one of: Null, UserDefined, Structured or Unstructured}} DataType_t {{} DataType_t {} C1 1 {length of string} \ {one of: Null, UserDefined, Integer, RealSingle, RealDouble\ or Character}} ElementType_t {{} ElementType_t {} C1 1 {length of string} \ {one of: Null, UserDefined, NODE, BAR_2, BAR_3, TRI_3, TRI_6, QUAD_4,\ QUAD_8, QUAD_9, TETRA_4, TETRA_10, PYRA_5, PYRA_14, PENTA_6, PENTA_15,\ PENTA_18, HEXA_8, HEXA_20, HEXA_27, MIXED, or NGON_n}} PointSet_t {{} PointSet_t {} C1 1 {length of string} \ {one of: Null, UserDefined, PointList, PointListDonor, PointRange,\ PointRangeDonor, ElementRange, ElementList, or CellListDonor}} } array set CGNSnodeRef { AdditionalExponents_t {{build DimensionalExponents} \ {physical dimensionalexponents}} AdditionalFamilyName_t {{} {families familyname}} AdditionalUnits_t {{build DimensionalUnits} {physical dimensionalunits}} ArbitraryGridMotion_t {{timedep ArbitraryGridMotion} {timedep arbitrary}} ArbitraryGridMotionPointers {} Area_t {{bc Area} {bc bcproperty}} AreaType_t {} AverageInterface_t {{cnct AverageInterface} {connectivity connproperty}} AverageInterfaceType_t {} Axisymmetry_t {{gridflow Axisymmetry} {grid axisymmetry}} AxisymmetryAngle {{} {physical dataarray}} AxisymmetryAxisVector {} AxisymmetryReferencePoint {} BaseIterativeData_t {{timedep BaseIterativeData} {timedep biter}} BC_t {{bc BC} {bc bc}} BCData_t {{bc BCData} {bc bcdata}} BCDataSet_t {{bc BCDataSet} {bc bcdataset}} BCProperty_t {{bc BCProperty} {bc bcproperty}} BCType_t {{bc BCType} {}} CellListDonor {} CGNSBase_t {{cgnsbase CGNSBase} {structural base}} CGNSLibraryVersion_t {{cgnsbase CGNSLibraryVersion} {open}} ChemicalKineticsModel_t {{floweqn ChemicalKineticsModel} \ {equation auxiliary}} ConvergenceHistory_t {{misc ConvergenceHistory} {auxiliary convergence}} CoordinateNames {{} {physical dataarray}} CoordinateData {{dataname dataname_grid} {grid gridcoordinates}} DataArray_t {{data DataArray} {physical dataarray}} DataClass_t {{build DataClass} {physical dataclass}} DataConversion_t {{data DataConversion} {physical dataconversion}} Descriptor_t {{build Descriptor} {descriptor descriptor}} DiffusionModel {{floweqn DiffusionModel} {equation governingequations}} DimensionalExponents_t {{build DimensionalExponents} \ {physical dimensionalexponents}} DimensionalUnits_t {{build DimensionalUnits} {physical dimensionalunits}} DiscreteData_t {{misc DiscreteData} {solution discretedata}} ElementConnectivity {{gridflow ElementConnectivity} {}} ElementList {} ElementRange {} Elements_t {{gridflow Elements} {grid elements}} EMConductivityModel_t {{floweqn EMConductivityModel} \ {equation auxiliary}} EMElectricFieldModel_t {{floweqn EMElectricFieldModel} \ {equation auxiliary}} EMMagneticFieldModel_t {{floweqn EMMagneticFieldModel} \ {equation auxiliary}} EquationDimension {} Family_t {{misc Family} {families family}} FamilyBC_t {{misc FamilyBC} {families familybc}} FamilyBCDataSet_t {{bc BCDataSet} {bc bcdataset}} FamilyName_t {{} {families familyname}} FamilyNameReference {{} {families familyname}} FamilyPointers {{} {physical dataarray}} FlowEquationSet_t {{floweqn FlowEquationSet} {equation flowequationset}} FlowSolution_t {{gridflow FlowSolution} {solution flowsolution}} FlowSolutionPointers {} GasModel_t {{floweqn GasModel} {equation auxiliary}} GeometryEntity_t {{} {families geometry}} GeometryFile_t {} GeometryFormat_t {} GeometryReference_t {{misc GeometryReference} {families geometry}} GoverningEquations_t {{floweqn GoverningEquations} \ {equation governingequations}} Gravity_t {{misc Gravity} {auxiliary gravity}} GravityVector {} GridConnectivity_t {{cnct GridConnectivity} {connectivity general}} GridConnectivity1to1_t {{cnct GridConnectivity1to1} {connectivity 1to1}} GridConnectivityProperty_t {{cnct GridConnectivityProperty} \ {connectivity connproperty}} GridConnectivityType_t {} GridCoordinates_t {{gridflow GridCoordinates} {grid gridcoordinates}} GridCoordinatesPointers {} GridLocation_t {{build GridLocation} {location gridlocation}} GridVelocity {} IndexArray_t {{build IndexArray} {}} IndexRange_t {{build IndexRange} {}} IntegralData_t {{misc IntegralData} {auxiliary integral}} InterpolantsDonor {} InwardNormalIndex {} InwardNormalList {} IterationValues {{} {physical dataarray}} NeumannData {} NormDefinitions {} NumberOfFamilies {{} {physical dataarray}} NumberOfZones {{} {physical dataarray}} Ordinal_t {{} {descriptor ordinal}} OriginLocation {} OversetHoles_t {{cnct OversetHoles} {connectivity overset}} ParentData {{} {grid elements}} ParentElements {{} {grid elements}} ParentElementsPosition {{} {grid elements}} Periodic_t {{cnct Periodic} {connectivity connproperty}} PointList {} PointListDonor {} PointRange {} PointRangeDonor {} ReferenceState_t {{misc ReferenceState} {auxiliary refstate}} ReferenceStateDescription {} RegionName {} RigidGridMotion_t {{timedep RigidGridMotion} {timedep rigid}} RigidGridMotionPointers {} RigidRotationAngle {} RigidRotationRate {} RigidVelocity {} Rind_t {{build Rind} {location rind}} RotatingCoordinates_t {{gridflow RotatingCoordinates} \ {grid rotatingcoordinates}} RotationAngle {} RotationCenter {} RotationRateVector {} SimulationType_t {{cgnsbase SimulationType} {structural simulationtype}} SolutionData {{dataname dataname_flow} {solution flowsolution}} SurfaceArea {} ThermalConductivityModel_t {{floweqn ThermalConductivityModel} \ {equation auxiliary}} ThermalRelaxationModel_t {{floweqn ThermalRelaxationModel} \ {equation auxiliary}} TimeValues {{} {physical dataarray}} Transform {} Translation {} TurbulenceClosure_t {{floweqn TurbulenceClosure} {equation auxiliary}} TurbulenceModel_t {{floweqn TurbulenceModel} {equation auxiliary}} UserDefinedData_t {{misc UserDefinedData} {auxiliary userdefined}} ViscosityModel_t {{floweqn ViscosityModel} {equation auxiliary}} WallFunction_t {{bc WallFunction} {bc bcproperty}} WallFunctionType_t {} Zone_t {{cgnsbase Zone} {structural zone}} ZoneBC_t {{bc ZoneBC} {bc}} ZoneGridConnectivity_t {{cnct ZoneGridConnectivity} {connectivity}} ZoneIterativeData_t {{timedep ZoneIterativeData} {timedep ziter}} ZonePointers {{} {physical dataarray}} ZoneType_t {} } set CGNSlibraryVersion 3.2 #----- initialize CGNS nodes proc cgns_init {{version ""}} { global CGNSlibraryVersion CGNSnodeChildren global CGNSnodeDesc CGNSdataValues if {$version == "" && [catch CGNSversion version]} { set CGNSlibraryVersion 3.2 } else { set CGNSlibraryVersion $version } set version [expr int(1000.0 * $CGNSlibraryVersion + 0.5)] if {$version < 2100} { array set CGNSnodeChildren { ArbitraryGridMotion_t {DataClass Descriptor DimensionalUnits \ GridLocation GridVelocity Rind} BaseIterativeData_t {DataArray DataClass Descriptor DimensionalUnits \ FamilyPointers IterationValues NumberOfFamilies NumberOfZones \ TimeValues ZonePointers} BCData_t {DataArray DataClass Descriptor DimensionalUnits} BCDataSet_t {DataClass Descriptor DimensionalUnits DirichletData \ NeumannData ReferenceState} ConvergenceHistory_t {ConvergenceDataArray DataClass Descriptor \ DimensionalUnits NormDefinitions} DiscreteData_t {DataClass Descriptor DimensionalUnits \ DiscreteDataArray GridLocation Rind} Elements_t {Descriptor ElementConnectivity ElementRange ParentData} Family_t {Descriptor FamilyBC GeometryReference Ordinal} FlowEquationSet_t {DataClass Descriptor \ DimensionalUnits EquationDimension GasModel GoverningEquations \ ThermalConductivityModel ThermalRelaxationModel TurbulenceClosure \ TurbulenceModel ViscosityModel} FlowSolution_t {DataClass Descriptor DimensionalUnits \ GridLocation Rind SolutionData} GasModel_t {DataArray DataClass Descriptor DimensionalUnits} GeometryReference_t {Descriptor GeometryEntity GeometryFile \ GeometryFormat} GridConnectivity1to1_t {Descriptor Ordinal PointRange PointRangeDonor \ Transform} GridCoordinates_t {CoordinateData DataClass Descriptor DimensionalUnits \ Rind} GoverningEquations_t {Descriptor DiffusionModel} IntegralData_t {DataClass Descriptor DimensionalUnits \ IntegralDataValue} OversetHoles_t {Descriptor GridLocation PointList PointRange} ReferenceState_t {DataClass Descriptor DimensionalUnits \ ReferenceStateDescription ReferenceStateValue} RigidGridMotion_t {DataArray DataClass Descriptor DimensionalUnits \ OriginLocation RigidRotationAngle RigidRotationRate \ RigidVelocity} ThermalConductivityModel_t {DataArray DataClass Descriptor \ DimensionalUnits} ThermalRelaxationModel_t {DataArray DataClass Descriptor \ DimensionalUnits} TurbulenceClosure_t {DataArray DataClass Descriptor \ DimensionalUnits} TurbulenceModel_t {DataArray DataClass Descriptor DiffusionModel \ DimensionalUnits} ViscosityModel_t {DataArray DataClass Descriptor DimensionalUnits} ZoneBC_t {BC DataClass Descriptor DimensionalUnits ReferenceState} ZoneGridConnectivity_t {Descriptor GridConnectivity \ GridConnectivity1to1 OversetHoles} ZoneIterativeData_t {ArbitraryGridMotionPointers DataArray DataClass \ Descriptor DimensionalUnits FlowSolutionPointers \ GridCoordinatesPointers RigidGridMotionPointers} } } else { array set CGNSnodeChildren { ArbitraryGridMotion_t {DataClass Descriptor DimensionalUnits \ GridLocation GridVelocity Rind UserDefinedData} BaseIterativeData_t {DataArray DataClass Descriptor DimensionalUnits \ FamilyPointers IterationValues NumberOfFamilies NumberOfZones \ TimeValues UserDefinedData ZonePointers} BCData_t {DataArray DataClass Descriptor DimensionalUnits UserDefinedData} BCDataSet_t {DataClass Descriptor DimensionalUnits DirichletData \ NeumannData ReferenceState UserDefinedData} ConvergenceHistory_t {ConvergenceDataArray DataClass Descriptor \ DimensionalUnits NormDefinitions} DiscreteData_t {DataClass Descriptor DimensionalUnits \ DiscreteDataArray GridLocation Rind UserDefinedData} Elements_t {Descriptor ElementConnectivity ElementRange \ ParentData UserDefinedData} Family_t {Descriptor FamilyBC GeometryReference Ordinal UserDefinedData} FlowEquationSet_t {ChemicalKineticsModel DataClass Descriptor \ DimensionalUnits EquationDimension GasModel GoverningEquations \ ThermalConductivityModel ThermalRelaxationModel TurbulenceClosure \ TurbulenceModel UserDefinedData ViscosityModel} FlowSolution_t {DataClass Descriptor DimensionalUnits \ GridLocation Rind SolutionData UserDefinedData} GasModel_t {DataArray DataClass Descriptor DimensionalUnits \ UserDefinedData} GeometryReference_t {Descriptor GeometryEntity GeometryFile \ GeometryFormat UserDefinedData} GridConnectivity1to1_t {Descriptor Ordinal PointRange PointRangeDonor \ Transform UserDefinedData} GridCoordinates_t {CoordinateData DataClass Descriptor DimensionalUnits \ Rind UserDefinedData} GoverningEquations_t {Descriptor DiffusionModel UserDefinedData} IntegralData_t {DataClass Descriptor DimensionalUnits \ IntegralDataValue UserDefinedData} OversetHoles_t {Descriptor GridLocation PointList PointRange \ UserDefinedData} ReferenceState_t {DataClass Descriptor DimensionalUnits \ ReferenceStateDescription ReferenceStateValue UserDefinedData} RigidGridMotion_t {DataArray DataClass Descriptor DimensionalUnits \ OriginLocation RigidRotationAngle RigidRotationRate \ RigidVelocity UserDefinedData} ThermalConductivityModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} ThermalRelaxationModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} TurbulenceClosure_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} TurbulenceModel_t {DataArray DataClass Descriptor DiffusionModel \ DimensionalUnits UserDefinedData} ViscosityModel_t {DataArray DataClass Descriptor DimensionalUnits \ UserDefinedData} ZoneBC_t {BC DataClass Descriptor DimensionalUnits ReferenceState \ UserDefinedData} ZoneGridConnectivity_t {Descriptor GridConnectivity \ GridConnectivity1to1 OversetHoles UserDefinedData} ZoneIterativeData_t {ArbitraryGridMotionPointers DataArray DataClass \ Descriptor DimensionalUnits FlowSolutionPointers \ GridCoordinatesPointers RigidGridMotionPointers UserDefinedData} } } if {$version < 2000} { array set CGNSnodeChildren { CGNSBase_t {DataClass Descriptor \ DimensionalUnits Family FlowEquationSet GlobalConvergenceHistory \ IntegralData ReferenceState Zone} BC_t {BCDataSet DataClass Descriptor DimensionalUnits \ ElementList ElementRange FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange ReferenceState} GridConnectivity_t {CellListDonor Descriptor \ GridConnectivityType GridLocation InterpolantsDonor Ordinal \ PointList PointListDonor PointRange} Zone_t {DataClass Descriptor \ DiscreteData DimensionalUnits Elements FamilyName FlowEquationSet \ FlowSolution GridCoordinates IntegralData Ordinal ReferenceState \ ZoneBC ZoneConvergenceHistory ZoneGridConnectivity ZoneType} } } elseif {$version < 2100} { array set CGNSnodeChildren { CGNSBase_t {BaseIterativeData DataClass Descriptor \ DimensionalUnits Family FlowEquationSet GlobalConvergenceHistory \ IntegralData ReferenceState SimulationType Zone} BC_t {BCDataSet DataClass Descriptor DimensionalUnits \ FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange ReferenceState} GridConnectivity_t {CellListDonor Descriptor \ GridConnectivityType GridLocation InterpolantsDonor Ordinal \ PointList PointListDonor PointRange} Zone_t {ArbitraryGridMotion DataClass Descriptor \ DiscreteData DimensionalUnits Elements FamilyName FlowEquationSet \ FlowSolution GridCoordinates IntegralData Ordinal ReferenceState \ RigidGridMotion ZoneBC ZoneConvergenceHistory ZoneGridConnectivity \ ZoneIterativeData ZoneType} } } elseif {$version < 2200} { array set CGNSnodeChildren { CGNSBase_t {BaseIterativeData DataClass Descriptor \ DimensionalUnits Family FlowEquationSet GlobalConvergenceHistory \ IntegralData ReferenceState SimulationType UserDefinedData Zone} BC_t {BCDataSet DataClass Descriptor DimensionalUnits \ FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange \ ReferenceState UserDefinedData} GridConnectivity_t {CellListDonor Descriptor \ GridConnectivityType GridLocation InterpolantsDonor Ordinal \ PointList PointListDonor PointRange UserDefinedData} Zone_t {ArbitraryGridMotion DataClass Descriptor \ DiscreteData DimensionalUnits Elements FamilyName FlowEquationSet \ FlowSolution GridCoordinates IntegralData Ordinal ReferenceState \ RigidGridMotion UserDefinedData ZoneBC ZoneConvergenceHistory \ ZoneGridConnectivity ZoneIterativeData ZoneType} } } else { array set CGNSnodeChildren { CGNSBase_t {Axisymmetry BaseIterativeData DataClass \ Descriptor DimensionalUnits Family FlowEquationSet \ GlobalConvergenceHistory Gravity IntegralData ReferenceState \ RotatingCoordinates SimulationType UserDefinedData Zone} BC_t {BCDataSet BCProperty DataClass Descriptor DimensionalUnits \ ElementList ElementRange FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange \ ReferenceState UserDefinedData} GridConnectivity_t {CellListDonor Descriptor GridConnectivityProperty \ GridConnectivityType GridLocation InterpolantsDonor Ordinal \ PointList PointListDonor PointRange UserDefinedData} Zone_t {ArbitraryGridMotion DataClass Descriptor \ DiscreteData DimensionalUnits Elements FamilyName FlowEquationSet \ FlowSolution GridCoordinates IntegralData Ordinal ReferenceState \ RigidGridMotion RotatingCoordinates UserDefinedData ZoneBC \ ZoneConvergenceHistory ZoneGridConnectivity ZoneIterativeData ZoneType} } } if {$version > 2300} { array set CGNSnodeChildren { BCDataSet_t {DataClass Descriptor DimensionalUnits DirichletData \ GridLocation NeumannData PointList PointRange ReferenceState \ UserDefinedData} DimensionalUnits_t {AdditionalUnits} DimensionalExponents_t {AdditionalExponents} EMConductivityModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} EMElectricFieldModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} EMMagneticFieldModel_t {DataArray DataClass Descriptor \ DimensionalUnits UserDefinedData} Family_t {Descriptor FamilyBC GeometryReference Ordinal \ RotatingCoordinates UserDefinedData} FamilyBC_t {BCDataSet} FlowEquationSet_t {ChemicalKineticsModel DataClass Descriptor \ DimensionalUnits EMConductivityModel EMElectricFieldModel \ EMMagneticFieldModel EquationDimension GasModel GoverningEquations \ ThermalConductivityModel ThermalRelaxationModel TurbulenceClosure \ TurbulenceModel UserDefinedData ViscosityModel} GridConnectivity1to1_t {Descriptor GridConnectivityProperty Ordinal \ PointRange PointRangeDonor Transform UserDefinedData} UserDefinedData_t {DataArray DataClass Descriptor DimensionalUnits \ FamilyName GridLocation Ordinal PointList PointRange UserDefinedData} } } if {$version >= 2500} { set CGNSnodeChildren(Elements_t) {Descriptor ElementConnectivity \ ElementRange ParentData Rind UserDefinedData} } if {$version >= 2530} { array set CGNSdataValues { DimensionalUnits_t {\ {Null UserDefined Kilogram Gram Slug PoundMass} \ {Null UserDefined Meter Centimeter Millimeter Foot Inch} \ {Null UserDefined Second} \ {Null UserDefined Kelvin Celsius Rankine Fahrenheit} \ {Null UserDefined Radian Degree}} TemperatureUnits_t {Null UserDefined Kelvin Celsius Rankine Fahrenheit} } } if {$version >= 3100} { array set CGNSnodeDesc { ZoneGridConnectivity_t {\ {ZoneGridConnectivity or user defined} \ ZoneGridConnectivity_t {0,N} MT {} {} {}} } array set CGNSnodeChildren { DiscreteData_t {DataClass Descriptor DimensionalUnits \ DiscreteDataArray GridLocation PointList PointRange Rind \ UserDefinedData} Elements_t {Descriptor ElementConnectivity ElementRange \ ParentElements ParentElementsPosition Rind UserDefinedData} FamilyBC_t {FamilyBCDataSet} FlowSolution_t {DataClass Descriptor DimensionalUnits \ GridLocation PointList PointRange Rind SolutionData \ UserDefinedData} ZoneIterativeData_t {ArbitraryGridMotionPointers DataArray DataClass \ Descriptor DimensionalUnits FlowSolutionPointers \ GridCoordinatesPointers RigidGridMotionPointers \ ZoneGridConnectivityPointers ZoneSubRegionPointers UserDefinedData} } if {$version >= 3200} { if {$version >= 3220} { array set CGNSnodeDesc { Elements_t {{user defined} Elements_t {0,N} I4 1 2 \ {ElementType, ElementSizeBoundary element types are: 0:Null, 1:UserDefined, 2:NODE, 3:BAR_2, 4:BAR_3,\ 5:TRI_3, 6:TRI_6, 7:QUAD_4, 8:QUAD_8, 9:QUAD_9, 10:TETRA_4, 11:TETRA_10,\ 12:PYRA_5, 13:PYRA_14, 14:PENTA_6, 15:PENTA_15, 16:PENTA_18, 17:HEXA_8,\ 18:HEXA_20, 19:HEXA_27, 20:MIXED, 21:PYRA_13, 22:NGON_n, 23:NFACE_n,\ 24:BAR_4, 25:TRI_9, 26:TRI_10, 27:QUAD_12, 28:QUAD_16, 29:TETRA_16,\ 30:TETRA_20, 31:PYRA_21, 32:PYRA_29, 33:PYRA_30, 34:PENTA_24,\ 35:PENTA_38, 36:PENTA_40, 37:HEXA_32, 38:HEXA_56, 39:HEXA_64,\ 40:BAR_5, 41:TRI_12, 42:TRI_15, 43:QUAD_P4_16, 44:QUAD_25, 45:TETRA_22,\ 46:TETRA_34, 47:TETRA_35, 48:PYRA_P4_29, 49:PYRA_50, 50:PYRA_55,\ 51:PENTA_33, 52:PENTA_66, 53:PENTA_75, 54:HEXA_44, 55:HEXA_98,\ 56:HEXA_125}} }} else { array set CGNSnodeDesc { Elements_t {{user defined} Elements_t {0,N} I4 1 2 \ {ElementType, ElementSizeBoundary element types are: 0:Null, 1:UserDefined, 2:NODE, 3:BAR_2, 4:BAR_3,\ 5:TRI_3, 6:TRI_6, 7:QUAD_4, 8:QUAD_8, 9:QUAD_9, 10:TETRA_4, 11:TETRA_10,\ 12:PYRA_5, 13:PYRA_14, 14:PENTA_6, 15:PENTA_15, 16:PENTA_18, 17:HEXA_8,\ 18:HEXA_20, 19:HEXA_27, 20:MIXED, 21:PYRA_13, 22:NGON_n, 23:NFACE_n,\ 24:BAR_4, 25:TRI_9, 26:TRI_10, 27:QUAD_12, 28:QUAD_16, 29:TETRA_16,\ 30:TETRA_20, 31:PYRA_21, 32:PYRA_29, 33:PYRA_30, 34:PENTA_24,\ 35:PENTA_38, 36:PENTA_40, 37:HEXA_32, 38:HEXA_56, 39:HEXA_64}} }} array set CGNSnodeChildren { BC_t {AdditionalFamilyName BCDataSet BCProperty DataClass Descriptor \ DimensionalUnits FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange \ ReferenceState UserDefinedData} Family_t {Descriptor FamilyBC FamilyNameReference GeometryReference \ Ordinal RotatingCoordinates UserDefinedData} UserDefinedData_t {AdditionalFamilyName DataArray DataClass Descriptor \ DimensionalUnits FamilyName GridLocation Ordinal PointList \ PointRange UserDefinedData} Zone_t {AdditionalFamilyName ArbitraryGridMotion DataClass Descriptor \ DiscreteData DimensionalUnits Elements FamilyName FlowEquationSet \ FlowSolution GridCoordinates IntegralData Ordinal ReferenceState \ RigidGridMotion RotatingCoordinates UserDefinedData ZoneBC \ ZoneConvergenceHistory ZoneGridConnectivity ZoneIterativeData \ ZoneSubRegion ZoneType} ZoneSubRegion_t {AdditionalFamilyName BCRegionName DataArray DataClass \ DimensionalUnits Descriptor FamilyName GridConnectivityRegionName \ GridLocation PointList PointRange Rind UserDefinedData} } } else { array set CGNSnodeDesc { Elements_t {{user defined} Elements_t {0,N} I4 1 2 \ {ElementType, ElementSizeBoundary element types are: 0:Null, 1:UserDefined, 2:NODE, 3:BAR_2, 4:BAR_3,\ 5:TRI_3, 6:TRI_6, 7:QUAD_4, 8:QUAD_8, 9:QUAD_9, 10:TETRA_4, 11:TETRA_10,\ 12:PYRA_5, 13:PYRA_14, 14:PENTA_6, 15:PENTA_15, 16:PENTA_18, 17:HEXA_8,\ 18:HEXA_20, 19:HEXA_27, 20:MIXED, 21:PYRA_13, 22:NGON_n, 23:NFACE_n}} } array set CGNSnodeChildren { BC_t {BCDataSet BCProperty DataClass Descriptor DimensionalUnits \ FamilyName GridLocation InwardNormalIndex \ InwardNormalList Ordinal PointList PointRange \ ReferenceState UserDefinedData} Zone_t {ArbitraryGridMotion DataClass Descriptor DiscreteData \ DimensionalUnits Elements FamilyName FlowEquationSet FlowSolution \ GridCoordinates IntegralData Ordinal ReferenceState RigidGridMotion \ RotatingCoordinates UserDefinedData ZoneBC ZoneConvergenceHistory \ ZoneGridConnectivity ZoneIterativeData ZoneSubRegion ZoneType} } } } else { array set CGNSnodeDesc { Elements_t {{user defined} Elements_t {0,N} I4 1 2 \ {ElementType, ElementSizeBoundary element types are: 0:Null, 1:UserDefined, 2:NODE, 3:BAR_2, 4:BAR_3,\ 5:TRI_3, 6:TRI_6, 7:QUAD_4, 8:QUAD_8, 9:QUAD_9, 10:TETRA_4, 11:TETRA_10,\ 12:PYRA_5, 13:PYRA_14, 14:PENTA_6, 15:PENTA_15, 16:PENTA_18, 17:HEXA_8,\ 18:HEXA_20, 19:HEXA_27, 20:MIXED, 21+:NGON_n}} ZoneGridConnectivity_t {ZoneGridConnectivity \ ZoneGridConnectivity_t {0,1} MT {} {} {}} } } } #----- popup windows for node data proc cgns_data {} { global ProgData Node CGNSdataValues CGNSnodeDesc set label [string trim $Node(label)] if {$label != "" && [info exists CGNSdataValues($label)] && [$ProgData(text) cget -state] == "normal"} { if {$label == "DimensionalUnits_t" || $label == "AdditionalUnits_t"} { cgns_units $label } else { cgns_string $label } return } set name [string trim $Node(name)] if {$name == "" || ![info exists CGNSnodeDesc($name)]} { if {$label == "" || ![info exists CGNSnodeDesc($label)]} return set name $label } set data [string trim [lindex $CGNSnodeDesc($name) 6]] if {$data != ""} { popup_message $data -pos $ProgData(text) } } proc cgns_units {label} { global ProgData Node CGNSdataValues set data $CGNSdataValues($label) set cur [split [string trim [$ProgData(text) get 1.0 end]] "\n"] if {$label == "DimensionalUnits_t"} { set units {mass length time temp angle} set names {Mass Length Time Temperature Angle} } else { set units {current amount intensity} set names {ElectricCurrent SubstanceAmount LuminousIntensity} } set w .unitlist catch {destroy $w} toplevel $w -relief flat -bd 0 wm overrideredirect $w 1 wm transient $w . wm group $w . wm protocol $w WM_DELETE_WINDOW {set ProgData(done) 0} frame $w.outer -relief solid -bd 1 pack $w.outer -side top -fill both -expand 1 set top [frame $w.outer.top] pack $top -side top -padx 3 -pady 3 -fill x -expand 1 set n 0 foreach i $units { FrameCreate $top.$i -text [lindex $names $n] -pady 0 -padx 0 -width 15 pack $top.$i -side left -fill y -padx 2 set f [FrameGet $top.$i] foreach v [lindex $data $n] { set j [string tolower $v] radiobutton $f.$j -text $v -variable ProgData(units,$i) \ -value $v -highlightthickness 0 -bd 0 pack $f.$j -side top -anchor w } set v [string trim [lindex $cur $n]] if {$v != "" && [lsearch [lindex $data $n] $v] >= 0} { set ProgData(units,$i) $v } incr n } set b [frame $w.outer.but] pack $b -side top -pady 3 button $b.accept -text Accept -default active \ -command {set ProgData(done) 1} button $b.cancel -text Cancel -command {set ProgData(done) 0} pack $b.accept $b.cancel -side left -padx 5 bind $w {set ProgData(done) 1} center_window $w $ProgData(text) set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable ProgData(done) destroy $w catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } if {$ProgData(done)} { set cnt [llength $units] set Node(type) C1 set Node(dim) "32 $cnt" set Node(size) [expr 32 * $cnt] $ProgData(text) delete 1.0 end incr cnt -1 for {set n 0} {$n < $cnt} {incr n} { set i [lindex $units $n] $ProgData(text) insert end "$ProgData(units,$i)\n" } set i [lindex $units end] $ProgData(text) insert end "$ProgData(units,$i)" } } proc cgns_string {label} { global ProgData Node CGNSdataValues set data $CGNSdataValues($label) set width 0 foreach i $data { set len [string length $i] if {$width < $len} {set width $len} } set cnt [llength $data] set w .datalist catch {destroy $w} toplevel $w -relief flat -bd 0 -cursor left_ptr wm overrideredirect $w 1 wm transient $w . wm group $w . wm protocol $w WM_DELETE_WINDOW {set ProgData(done) 0} bind $w {set ProgData(done) 0} bind $w {set ProgData(done) 0} bind $w {set ProgData(done) 0} bind $w {set ProgData(done) 0} set top [frame $w.top -relief solid -bd 1] pack $top -side top -fill both -expand 1 label $top.lab -text $label pack $top.lab -side top -fill x frame $top.sep -height 2 -bd 1 -relief sunken pack $top.sep -side top -fill x if {$cnt > 10} { listbox $top.list -relief flat -bd 0 -highlightthickness 0 \ -exportselection 0 -width $width -height 10 \ -yscroll "$top.scroll set" -takefocus 0 -cursor hand2 scrollbar $top.scroll -highlightthickness 0 -takefocus 0 \ -orient vertical -command "$top.list yview" pack $top.scroll -side right -fill y bind $top.scroll break } else { listbox $top.list -relief flat -bd 0 -highlightthickness 0 \ -exportselection 0 -width $width -height $cnt \ -takefocus 0 -cursor hand2 } pack $top.list -side left -fill both -expand 1 bind $top.list {set ProgData(done) 1; break} foreach i $data { $top.list insert end $i } set n [lsearch $data [string trim [$ProgData(text) get 1.0 end]]] if {$n >= 0} { $top.list selection set $n $n $top.list see $n } center_window $w $ProgData(text) set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable ProgData(done) set sel [$top.list curselection] if {$sel == ""} { set data "" } else { set data [$top.list get $sel] } destroy $w catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } if {$data != "" && $ProgData(done)} { $ProgData(text) delete 1.0 end $ProgData(text) insert end $data set Node(type) C1 set Node(dim) [string length $data] set Node(size) $Node(dim) } } proc cgns_info {} { global ProgData Node CGNSnodeDesc Font set name [string trim $Node(name)] if {$name == "" || ![info exists CGNSnodeDesc($name)]} { set name [string trim $Node(label)] if {$name == "" || ![info exists CGNSnodeDesc($name)]} return } set labw 10 set wrap 30 set w .datainfo catch {destroy $w} toplevel $w -bg black wm overrideredirect $w 1 wm transient $w . frame $w.f -bg #ffffcc pack $w.f -side top -padx 1 -pady 1 set n 0 foreach i {"Node Name" "Node Label" Cardinality "Data Type"} { set f [frame $w.f.n$n -bg #ffffcc] pack $f -side top -padx 5 -anchor w label $f.lab -text "$i:" -width $labw -anchor w -font $Font(normal) \ -bg #ffffcc -fg black label $f.ent -font $Font(fixed) -bg #ffffcc -fg black \ -text [lindex $CGNSnodeDesc($name) $n] pack $f.lab $f.ent -side left incr n } if {[lindex $CGNSnodeDesc($name) 3] != "MT"} { foreach i {Dimension "Dim Values"} { set f [frame $w.f.n$n -bg #ffffcc] pack $f -side top -padx 5 -anchor w label $f.lab -text "$i:" -width $labw -anchor w -font $Font(normal) \ -bg #ffffcc -fg black label $f.ent -font $Font(fixed) -bg #ffffcc -fg black \ -text [lindex $CGNSnodeDesc($name) $n] pack $f.lab $f.ent -side left incr n } set data "" foreach line [split [lindex $CGNSnodeDesc($name) 6] "\n"] { if {$data != ""} {append data "\n"} set len 0 foreach word $line { set n [string length $word] if [expr {$len + $n + 1 > $wrap}] { append data "\n" set len 0 } if {$len} { append data " $word" incr n } else { append data $word } incr len $n } } set f [frame $w.f.data -bg #ffffcc] pack $f -side top -padx 5 -anchor w label $f.lab -text "Data:" -width $labw -anchor w -font $Font(normal) \ -bg #ffffcc -fg black label $f.ent -justify left -font $Font(fixed) -bg #ffffcc -fg black \ -text $data pack $f.lab $f.ent -side left -anchor n } center_window $w . bind $w {catch {destroy .datainfo};break} bind $w {catch {destroy .datainfo};break} bind $w {catch {destroy .datainfo}} set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} focus $w tkwait window $w catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } } proc cgns_tree {{top ""}} { global Font CGNSlibraryVersion CGNSnodes CGNSnodeChildren global CGNSdataValues CGNSdataDesc CGNSdata if {$top == ""} { set top .cgnstree } if {$top == "."} { set w "" } else { if {[winfo exists $top]} { wm deiconify $top return } toplevel $top set w $top } wm title $top "CGNS $CGNSlibraryVersion Node Reference" array set CGNSdata { node "" name "" label "" count "" type "" ndim "" dims "" sids "" midlevel "" } FrameCreate $w.tree -text "Node Tree" -font $Font(bold) pack $w.tree -side left -fill both -expand 1 set tree [FrameGet $w.tree] scrollbar $tree.ys -orient vertical -command "$tree.tree yview" pack $tree.ys -side right -fill y scrollbar $tree.xs -orient horizontal -command "$tree.tree xview" pack $tree.xs -side bottom -fill x TreeCreate $tree.tree -width 200 -height 300 -relief sunken \ -bd 2 -yscrollcommand "$tree.ys set" -xscrollcommand "$tree.xs set" \ -font $Font(normal) set CGSNdata(tree) $tree.tree pack $tree.tree -side left -fill both -expand 1 bind $tree.tree <1> {cgns:show_node %W [TreeAt %W %x %y]} bind $tree.tree {TreeToggle %W [TreeAt %W %x %y]} bind $tree.tree {cgns:tree %W %x %y open} bind $tree.tree {cgns:tree %W %x %y close} bind $tree.tree {cgns:tree %W %x %y expand} bind $tree.tree {cgns:tree %W %x %y collapse} TreeInsert $tree.tree / foreach n $CGNSnodeChildren(/) { cgns:add_node $tree.tree "" $n } set labw 10 set entw 32 FrameCreate $w.prop -text "Node Properties" -font $Font(bold) pack $w.prop -side right -fill y set prop [FrameGet $w.prop] foreach {i j} {name "Node Name" label "Node Label" count Cardinality \ type "Data Type" ndim Dimensions dims "Dim Values"} { set f [frame $prop.$i] pack $f -side top label $f.lab -width $labw -text $j -anchor w entry $f.ent -width $entw -textvariable CGNSdata($i) \ -state disabled -cursor {} pack $f.lab $f.ent -side left } set f [frame $prop.data] pack $f -side top -fill both -expand 1 label $f.lab -text "Data" pack $f.lab -side top -anchor w set CGNSdata(text) [text $f.text -width $entw -height 15 \ -wrap word -cursor {}] pack $CGNSdata(text) -side top -fill both -expand 1 frame $prop.sep -relief groove -bd 1 -height 2 pack $prop.sep -side top -fill x -pady 3 set f [frame $prop.but] pack $f -side top -fill x button $f.midlevel -text "MLL Doc..." -state disabled \ -command {cgns:help midlevel} button $f.sids -text "SIDS Doc.." -state disabled \ -command {cgns:help sids} pack $f.midlevel $f.sids -side left -expand 1 if {$top == "."} { button $f.setup -text "Setup..." -command help_setup pack $f.setup -side left -expand 1 } button $f.exit -text Exit -command "destroy $top" -width 6 pack $f.exit -side left -expand 1 set CGNSdata(buts) $f } proc cgns:add_node {tree parent child} { global CGNSnodes CGNSnodeChildren set node $parent/$child TreeInsert $tree $node set type [lindex $CGNSnodes($child) 1] if {[info exists CGNSnodeChildren($type)]} { foreach n $CGNSnodeChildren($type) { if {$n == $child} { TreeInsert $tree $node/$n } else { cgns:add_node $tree $node $n } } } } proc cgns:show_node {w node} { global CGNSnodes CGNSnodeDesc CGNSnodeRef CGNSdata TreeSelectionSet $w $node $CGNSdata(text) delete 1.0 end if {$node == "" || $node == "/"} { array set CGNSdata { node "" name "" label "" count "" type "" ndim "" dims "" sids "" midlevel "" } } else { set name [file tail $node] if {![info exists CGNSnodeDesc($name)]} { set name [lindex $CGNSnodes($name) 1] } set n 0 foreach i {name label count type ndim dims} { set CGNSdata($i) [lindex $CGNSnodeDesc($name) $n] incr n } $CGNSdata(text) insert end [lindex $CGNSnodeDesc($name) 6] set name [file tail $node] if {![info exists CGNSnodeRef($name)]} { set name [lindex $CGNSnodes($name) 1] } if {[info exists CGNSnodeRef($name)]} { set CGNSdata(sids) [lindex $CGNSnodeRef($name) 0] set CGNSdata(midlevel) [lindex $CGNSnodeRef($name) 1] } else { set CGNSdata(sids) "" set CGNSdata(midlevel) "" } } foreach i {sids midlevel} { if {$CGNSdata($i) == {}} { $CGNSdata(buts).$i configure -state disabled } else { $CGNSdata(buts).$i configure -state normal } } } proc cgns:tree {w x y mode} { set node [TreeAt $w $x $y] if {$node == ""} return if {$node != [TreeSelectionGet $w]} { cgns:show_node $w $node } switch $mode { expand {TreeExpand $w $node} collapse {TreeCollapse $w $node} open {TreeOpenLevel $w $node} close {TreeCloseLevel $w $node} } } proc cgns:format {text width} { if {[string trim $text] == ""} {return ""} return $data } proc cgns:help {type} { global CGNSdata set html [lindex $CGNSdata($type) 0] if {$html == ""} return help_show "$type/$html.html" [lindex $CGNSdata($type) 1] } CGNS-3.4.0/src/cgnstools/cgnsview/cgnsnodes.bat000066400000000000000000000020041343724673500213640ustar00rootroot00000000000000@echo off setlocal rem the standard wish command will work for this rem set wish=c:\progra~1\tcl\bin\wish83.exe set dir=%~dps0 if exist %dir%cgconfig.bat ( call %dir%cgconfig.bat goto getwish ) if exist %dir%..\cgconfig.bat call %dir%..\cgconfig.bat :getwish if "%CG_BIN_DIR%" == "" set CG_BIN_DIR=%dir% if not "%wish%" == "" goto getscript if exist %dir%cgiowish.exe ( set wish=%dir%cgiowish.exe goto getscript ) if exist %dir%cgnstools\cgiowish.exe ( set wish=%dir%cgnstools\cgiowish.exe goto getscript ) echo cgiowish.exe not found pause goto done :getscript if exist %dir%cgnsnodes.tcl ( set script=%dir%cgnsnodes.tcl goto run ) if not "%CG_LIB_DIR%" == "" ( if exist %CG_LIB_DIR%\cgnsnodes.tcl ( set script=%CG_LIB_DIR%\cgnsnodes.tcl goto run ) ) if exist %dir%..\share\cgnsnodes.tcl ( if "%CG_LIB_DIR%" == "" set CG_LIB_DIR=%dir%..\share set script=%dir%..\share\cgnsnodes.tcl goto run ) echo cgnsnodes.tcl not found pause goto done :run start /b %wish% %script% %1 :done endlocal CGNS-3.4.0/src/cgnstools/cgnsview/cgnsnodes.sh000077500000000000000000000022501343724673500212360ustar00rootroot00000000000000#!/bin/sh # sh script to launch CGNS File viewer/editor dir=`dirname $0` # source the setup script for d in $dir $dir/cgnstools $dir/.. ; do if test -f $d/cgconfig ; then . $d/cgconfig break fi done # The normal wish will work here, but cgiowish should # be available, and may also be used cgiowish="" for d in $CG_BIN_DIR $dir $dir/cgnstools $dir/cgnsview \ /usr/local/bin /usr/local/bin/cgnstools ; do if test -x $d/cgiowish ; then cgiowish=$d/cgiowish break fi if test -x $d/cgnswish/cgiowish ; then cgiowish=$d/cgnswish/cgiowish break fi done if test -z "$cgiowish" ; then echo "Error: cgiowish executable not found" exit 1 fi # find the cgnsnodes tcl script cgnsnodes="" for d in $CG_LIB_DIR $dir $dir/cgnstools $dir/cgnsview \ /usr/local/share /usr/local/share/cgnstools ; do if test -f $d/cgnsnodes.tcl ; then cgnsnodes=$d/cgnsnodes.tcl break fi done if test -z "$cgnsnodes" ; then echo "Error: cgnsnodes.tcl script not found" exit 1 fi # check that display is set #if test -z "$DISPLAY" ; then # echo "Error: DISPLAY environment variable not set" # exit 1 #fi # execute exec $cgiowish $cgnsnodes CGNS-3.4.0/src/cgnstools/cgnsview/cgnsnodes.tcl000077500000000000000000000033011343724673500214040ustar00rootroot00000000000000#!/bin/sh # the next line restarts using wish \ exec adfwish -f "$0" "$@" proc error_exit {msg} { wm withdraw . tk_dialog .error Error $msg error 0 Exit exit 1 } if {[catch {package require Tk 8.0} msg]} { error_exit $msg } #----- check for CGNS version if {$argc} { set version [lindex $argv [expr $argc - 1]] if {[catch {expr $version < 1.1 || $version > 3.2} ok] || !$ok} { error_exit "invalid CGNS version number : $version" } } else { set version "" } #----- get startup directory and name set cmd_name [file tail $argv0] set cmd_dir [file dirname $argv0] if {![file exists $argv0] || [file isdirectory $argv0]} { if {$tcl_platform(platform) == "windows"} { set sep ";" } else { set sep ":" } foreach i [split $env(PATH) $sep] { if {$sep == ";"} { set i [join [split $i \\] /] } if {[file exists $i/$cmd_name] && ![file isdirectory $i/$cmd_name]} { set cmd_dir $i break; } } } set curdir [pwd] if ![catch {cd $cmd_dir}] { set cmd_dir [pwd] cd $curdir } if {$tcl_platform(platform) == "windows"} { set cmd_dir [file attributes $cmd_dir -shortname] } set auto_path "$cmd_dir $cmd_dir/../common $auto_path" if {[info exists env(TCL_PROC_DIR)]} { set auto_path "$env(TCL_PROC_DIR) $auto_path" } if [catch {config_defaults 1} msg] { error_exit $msg } if {$tcl_platform(platform) == "windows"} { set vers [join [split $tcl_version .] {}] catch {load tclreg$vers registry} } #---------- initialize set file ".cgnstools" set base "HKEY_CURRENT_USER/Software/CGNS" catch {tclreg_init -base $base -fname $file} help_init cgns_init $version cgns_tree . catch { config_icon . cgns [list $cmd_dir $cmd_dir/images $cmd_dir/../common] } CGNS-3.4.0/src/cgnstools/cgnsview/cgnsview.bat000066400000000000000000000016221343724673500212330ustar00rootroot00000000000000@echo off setlocal set dir=%~dps0 if exist "%dir%cgconfig.bat" ( call %dir%cgconfig.bat goto getwish ) if exist "%dir%..\cgconfig.bat" call "%dir%..\cgconfig.bat" :getwish if "%CG_BIN_DIR%" == "" set CG_BIN_DIR=%dir% if exist "%dir%cgiowish.exe" ( set wish=%dir%cgiowish.exe goto getscript ) if exist "%dir%cgnstools\cgiowish.exe" ( set wish=%dir%cgnstools\cgiowish.exe goto getscript ) echo cgiowish.exe not found pause goto done :getscript if exist "%dir%cgnsview.tcl" ( set script=%dir%cgnsview.tcl goto run ) if not "%CG_LIB_DIR%" == "" ( if exist "%CG_LIB_DIR%\cgnsview.tcl" ( set script=%CG_LIB_DIR%\cgnsview.tcl goto run ) ) if exist "%dir%..\share\cgnsview.tcl" ( if "%CG_LIB_DIR%" == "" set CG_LIB_DIR=%dir%..\share set script=%dir%..\share\cgnsview.tcl goto run ) echo cgnsview.tcl not found pause goto done :run start "" /b "%wish%" "%script%" %1 :done endlocal CGNS-3.4.0/src/cgnstools/cgnsview/cgnsview.sh000077500000000000000000000022451343724673500211040ustar00rootroot00000000000000#!/bin/sh # sh script to launch CGNS File viewer/editor dir=`dirname $0` # source the setup script for d in $dir $dir/cgnstools $dir/.. ; do if test -f $d/cgconfig ; then . $d/cgconfig break fi done # get the cgiowish executable cgiowish="" for d in $CG_BIN_DIR $dir $dir/cgnstools $dir/cgnsview \ /usr/local/bin /usr/local/bin/cgnstools ; do if test -x $d/cgiowish ; then cgiowish=$d/cgiowish break fi if test -x $d/cgnswish/cgiowish ; then cgiowish=$d/cgnswish/cgiowish break fi done if test -z "$cgiowish" ; then echo "Error: cgiowish executable not found" exit 1 fi # find the cgnsview tcl script cgnsview="" for d in $CG_LIB_DIR $dir $dir/cgnstools $dir/cgnsview \ /usr/local/share /usr/local/share/cgnstools ; do if test -f $d/cgnsview.tcl ; then cgnsview=$d/cgnsview.tcl break fi done if test -z "$cgnsview" ; then echo "Error: cgnsview.tcl script not found" exit 1 fi # check that display is set #if test -z "$DISPLAY" ; then # echo "Error: DISPLAY environment variable not set" # exit 1 #fi # execute if test "$#" = 0 ; then exec $cgiowish $cgnsview else exec $cgiowish $cgnsview "$@" fi CGNS-3.4.0/src/cgnstools/cgnsview/cgnsview.tcl000066400000000000000000002343311343724673500212540ustar00rootroot00000000000000#!/bin/sh # the next line restarts using wish \ exec cgiowish -f "$0" "$@" proc error_exit {msg} { wm withdraw . tk_dialog .error Error $msg error 0 Exit exit 1 } if {[catch {package require Tk 8.0} msg]} { error_exit $msg } #---------- get platform set platform $tcl_platform(platform) if {$platform == "windows" && [info exists env(TERM)] && ($env(TERM) == "cygwin" || $env(TERM) == "xterm")} { set platform cygwin } #---------- setup paths to tcl files set cmd_name [file tail $argv0] set cmd_dir [file dirname $argv0] if {![file exists $argv0] || [file isdirectory $argv0]} { if {$platform == "windows"} { set sep ";" } else { set sep ":" } foreach i [split $env(PATH) $sep] { if {$sep == ";"} { set i [join [split $i \\] /] } if {[file exists $i/$cmd_name] && ![file isdirectory $i/$cmd_name]} { set cmd_dir $i break; } } } set curdir [pwd] if ![catch {cd $cmd_dir}] { set cmd_dir [pwd] cd $curdir } if {$tcl_platform(platform) == "windows"} { set cmd_dir [file attributes $cmd_dir -shortname] } set auto_path "$cmd_dir $cmd_dir/../common $auto_path" if {[info exists env(TCL_PROC_DIR)]} { set auto_path "$env(TCL_PROC_DIR) $auto_path" } #---------- initialize windows if {$platform == "windows"} { set vers [join [split $tcl_version .] {}] if {[info commands CGIOopen] == {}} { if {[catch {load cgiotcl$vers} msg]} { error_exit $msg } } catch {load tclreg$vers registry} } else { if {[info commands CGIOopen] == {}} { error_exit "need to run script with cgiowish" } } if [catch {config_defaults 1} msg] {error_exit $msg} #----- node tree icons image create photo dirimg -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAUABAAAARF0MlJq5Un53sPWh9ycJQHnqK2VcfjvrB7AOyD\ 3t9chziolzaecPGbtIbCIibYy9GASJTS0Wqepqps9kkBeL9gMGlMLksiADs=} image create photo fileimg -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAUABAAAAQ5EMlJq5Ug63wreGDIdRhInA+AqOQXgltroqL8\ vuzlnjxs377OjkcI6oA14ayX+gFzlo10RKpar5IIADs=} image create photo badimg -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAUABAAAAQkEMlJq704S8K5pl34Id1UaifpoatKjGALp7Nc\ v3Ce0bfu/4gIADs=} image create photo dirlink -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAUABAAAARR0MlJq5Un53sPWh9ycJQHnqK2VcfjvrB7AOyD\ 3t9chziolzHX7TdpPQBIwIMnogFdSRuPiIFGmVRHK6ocOotH5UuV+U6OsaTaAoWRKMHH2xEB\ ADs=} image create photo filelink -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAUABAAAAQ/EMlJq5Ug63wreGDIdRhInA+AqOQXgltroqL8\ vqx1z3AHa7dcRZR50ISUXxHnA36OTdcOOUkFYxfYi5TccRERADs=} image create photo badlink -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAUABAAAAQ5EMlJq704S8K5pl34Id1UaifpjeBqPXD8qEQG\ AzjwpFec7zXN7efCPH461lEXK/aYzaDtKFPKYJ8IADs=} image create photo invalid -data { R0lGODlhFAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAUABAAAARLEMmZap04A2B7/lzyjE/4YdVDrI93pmRbmR+8\ WuOVzSQ+0pQEIFdhlXTBoY8EDFpWRiRqGZNOVVCC7CQJxWQALmLTsWzETit6PYkAADs=} #----- initialize program data array set ProgData { libvers "" filevers "" supported "" extensions "" newfile "" format adf file "" readonly 1 follow 0 verify 1 backup 1 bakfile "" autoload 1 defsize 1024 maxsize 1024 defcnt 10 maxcnt 10 showlines 1 linenum "" linecnt "" lineval "" toolbar 1 tree "" buttons "" find "" case 0 fromtop 0 start / winwidth 640 winheight 500 seppos 0.4 sepwd 7 reg,file ".cgnstools" reg,base "HKEY_CURRENT_USER/Software/CGNS" reg,key "CGNSview" reg,vals {file follow verify backup autoload maxsize maxcnt toolbar \ find case fromtop showlines winwidth winheight seppos} cgnsdiff "" cgnscheck "" cgnsplot "" cgnscalc "" menucfg "" file,name "" file,dir "" file,size "" file,cgns "" file,type "" file,vers "" file,mode "" file,mtime "" file,atime "" units,mass Kilogram units,length Meter units,time Second units,temp Kelvin units,angle Radian units,current Ampere units,amount Mole units,intensity Candela } array set Node { parent "" name "" label "" type "" dim "" size "" lnode "" lfile "" trace 0 } foreach i [array names Node] { set NodeSave($i) $Node($i) } set ProgData(libvers) [CGNSversion] cgns_init $ProgData(libvers) set ProgData(supported) [CGIOsupported] set cgnsexts .cgns foreach ext $ProgData(supported) { lappend cgnsexts ".cg[string index $ext 0]" } set ProgData(extensions) [list [list "CGNS Files" $cgnsexts]] if {[CGIOsupported adf] != ""} { lappend ProgData(extensions) [list "ADF Files" [list .adf .cga]] } if {[CGIOsupported hdf5] != ""} { lappend ProgData(extensions) [list "HDF5 Files" [list .hdf .hdf5 .cgh]] } lappend ProgData(extensions) [list "All Files" *] array set Import { inputfile "" cgnsfile "" exefile "" options "" basename "" basename,flag 1 dupcheck,flag 0 dupcheck d duptol "" } array set Export { cgnsfile "" outputfile "" exefile "" options "" basenum "" zonenum "" solnum "" basenum,flag 1 zonenum,flag 1 solnum,flag 1 ascii 0 solution 1 weight 0 } array set Tools { cgnsinput "" cgnsoutput "" verbose "" warnings 2 errors "" exefile "" options "" weight "" basenum "" basename "" zonenum "" solnum "" solname "" basenum,flag 1 basename,flag 1 zonenum,flag 1 solnum,flag 1 solname,flag 1 background 0 nocase "" whitespace "" followlinks "" cmpdata "" cmptol 0 } set DataTypes { "MT (empty)" "C1 (character data)" "I4 (32-bit integer)" "R4 (32-bit real)" "R8 (64-bit real)" "B1 (byte data)" "U4 (unsigned 32-bit integer)" "I8 (64-bit integer)" "U8 (unsigned 64-bit integer)" "X4 (32-bit complex real)" "X8 (64-bit complex real)" } #----- read registry if {[tclreg_init -base $ProgData(reg,base) -fname $ProgData(reg,file)]} { foreach i $ProgData(reg,vals) { if {![catch {tclreg_get $ProgData(reg,key) $i} val] && $val != ""} { set ProgData($i) $val } } catch units_read } #----- setup search paths for executable files and script files set ProgData(exepath) [list $cmd_dir $cmd_dir/cgnstools] if {[info exists env(CG_BIN_DIR)] && $env(CG_BIN_DIR) != ""} { if {$platform == "windows"} { set bin_dir [file attributes $env(CG_BIN_DIR) -shortname] } else { set bin_dir $env(CG_BIN_DIR) } lappend ProgData(exepath) $bin_dir $bin_dir/cgnstools } set ProgData(libpath) [list $cmd_dir $cmd_dir/cgnstools] if {[info exists env(CG_LIB_DIR)] && $env(CG_LIB_DIR) != ""} { if {$platform == "windows"} { set lib_dir [file attributes $env(CG_LIB_DIR) -shortname] } else { set lib_dir $env(CG_LIB_DIR) } lappend ProgData(libpath) $lib_dir $lib_dir/cgnstools } set root_dir [file dirname $cmd_dir] foreach d {cgnscalc cgnsplot tools utilities} { if [file isdirectory $root_dir/$d] { lappend ProgData(exepath) $root_dir/$d lappend ProgData(libpath) $root_dir/$d } } proc get_executable {name {showerr 0}} { global ProgData set exe [find_file executable $name $ProgData(exepath) \$PATH] if {$exe == "" && $showerr} { set msg "$name executable not found in:" foreach p $ProgData(exepath) { append msg "\n $p" } append msg "\n \$PATH" errormsg $msg } return $exe } proc get_file {name {showerr 0}} { global ProgData set fname [find_file exists $name $ProgData(libpath) \$PATH] if {$fname == "" && $showerr} { set msg "$name file not found in:" foreach p $ProgData(libpath) { append msg "\n $p" } append msg "\n \$PATH" errormsg $msg } return $fname } #----- find cgnscheck, cgnsdiff, cgnsplot, cgnscalc set ProgData(cgnscheck) [get_executable cgnscheck] set ProgData(cgnsdiff) [get_executable cgnsdiff] set plotwish [get_executable plotwish] set cgnsplot [get_file cgnsplot.tcl] if {$plotwish != "" && $cgnsplot != ""} { set ProgData(cgnsplot) [list $plotwish $cgnsplot] } set calcwish [get_executable calcwish] set cgnscalc [get_file cgnscalc.tcl] if {$calcwish != "" && $cgnscalc != ""} { set ProgData(cgnscalc) [list $calcwish $cgnscalc] } #---------- main window wm title . CGNSview wm protocol . WM_DELETE_WINDOW do_quit bind . cgns_info #---------- menu menubar_create {File Config Tree Tools Help} #--- file menu set m [menubar_get File] $m add command -label "New..." -command file_new $m add command -label "Open..." -command file_load $m add command -label "Save..." -command file_save -state disabled $m add command -label "Compress..." -command file_compress -state disabled $m add separator $m add command -label "Reload" -command file_reload -state disabled $m add command -label "File Info..." -command file_info -state disabled $m add command -label "Restore" -command restore_backup -state disabled #--- config menu set m [menubar_get Config] $m add checkbutton -label " Show Lines" -variable ProgData(showlines) \ -onvalue 1 -offvalue 0 -command { TreeConfig $ProgData(tree) -lines $ProgData(showlines) } $m add checkbutton -label " Show Toolbar" -variable ProgData(toolbar) \ -onvalue 1 -offvalue 0 -command { if {$ProgData(toolbar)} { pack .toolbar.but -side left } else { pack forget .toolbar.but .toolbar configure -height 1 } } $m add checkbutton -label " Verify Delete" -variable ProgData(verify) \ -onvalue 1 -offvalue 0 $m add checkbutton -label " Auto Backup" -variable ProgData(backup) \ -onvalue 1 -offvalue 0 $m add checkbutton -label " Auto Load Data" -variable ProgData(autoload) \ -onvalue 1 -offvalue 0 $m add command -label " Auto Data Size..." -command auto_size #--- tree menu set m [menubar_get Tree] $m add checkbutton -label " Follow Links" -variable ProgData(follow) \ -onvalue 1 -offvalue 0 -command {follow_links $ProgData(follow)} $m add command -label " Expand All" -command {tree_expand /} \ -state disabled $m add command -label " Collapse All" -command {tree_collapse /} \ -state disabled $m add separator $m add command -label " Find Node..." -command find_node \ -state disabled $m add command -label " Find Again" -command find_again \ -state disabled #--- tools menu set m [menubar_get Tools] $m add command -label "Diff CGNS Files..." -state disabled -command diff_cgns $m add command -label "Check CGNS..." -state disabled -command check_cgns $m add command -label "Plot CGNS..." -state disabled -command plot_cgns $m add command -label "Calculate CGNS..." -state disabled -command calc_cgns $m add separator $m add command -label "Unit Conversions..." -command units_convert #--- help menu set m [menubar_get Help] $m add command -label "CGNSview..." \ -command {help_show cgnstools/cgnsview/index.html} $m add command -label "Utilities..." \ -command {help_show cgnstools/utilities/index.html} $m add command -label "CGNS..." -command {help_show} $m add separator $m add command -label "Configure..." -command help_setup $m add separator $m add command -label "CGNS Nodes..." -command cgns_tree $m add command -label "About..." -underline 0 -command do_about #----- add menu options proc next_line {fp} { set input "" while {[gets $fp line] >= 0} { set n [string first "\#" $line] if {$n == 0} { set line "" } elseif {$n > 0} { set line [string trim [string range $line 0 [expr $n - 1]]] } else { set line [string trim $line] } if {$line == ""} continue set end [expr [string length $line] - 1] if {[string index $line $end] == "\\"} { incr end -1 append input [string range $line 0 $end] continue } append input $line break } return $input } set menufiles [glob -nocomplain $cmd_dir/*.mnu] if {$menufiles == ""} { set menufiles [get_file utilities.mnu] } if {$menufiles != ""} { set cnt 0 foreach f $menufiles { if {![catch {open $f r} fp]} { while (1) { set line [next_line $fp] if {$line == ""} break set mnu [split [lindex $line 0] :] set len [expr [llength $mnu] - 1] if {$len < 1} { error_exit "invalid menu specification - [lindex $line 0]" } set m [menubar_add [lindex $mnu 0] Help] for {set i 1} {$i < $len} {incr i} { set entry [lindex $mnu $i] if {[catch {$m index $entry} n]} { $m add cascade -label $entry -menu $m.m$cnt set m $m.m$cnt incr cnt menu $m -tearoff 0 } else { set m [$m entrycget $n -menu] if {$m == ""} { error_exit "menu item is not a submenu - [lindex $line 0]" } } } set entry [lindex $mnu $len] if {[string match "sep*" $entry]} { $m add separator } else { set opts [list $entry] eval lappend opts [lrange $line 1 end] $m add command -label $entry -command "run_menu $opts" set class [string tolower [lindex $line 1]] if {[string match "ex*" $class] || [string match "con*" $class] || [string match "ut*" $class]} { set n [$m index end] $m entryconfigure $n -state disabled lappend ProgData(menucfg) [list $m $n] } } } close $fp } } } proc run_menu {args} { set n 0 foreach i {name class exe func script} { set $i [lindex $args $n] incr n } if {$func == ""} { switch -glob [string tolower $class] { im* {set func import_default} ex* {set func export_default} con* {set func tools_convert} ut* {set func tools_utility} default {set func tools_default} } } else { if {![get_external_proc $func $script]} return } if {[catch {$func .tools $name $exe} msg]} { errormsg $msg } catch {destroy .tools} } proc get_external_proc {func script} { if {[info commands $func] == "" && $script != ""} { set scr [get_file $script 1] if {$scr == ""} {return 0} if {[catch {uplevel \#0 source $scr} msg]} { errormsg $msg return 0 } if {[info commands $func] == ""} { errormsg "procedure $func not found in script $script" return 0 } } return 1 } #----- add Quit to file menu set m [menubar_get File] $m add separator $m add command -label "Quit" -command do_quit #----- toolbar frame .toolbar -height 1 pack .toolbar -side top -pady 3 -fill x set f [frame .toolbar.but] if {$ProgData(toolbar)} { pack $f -side left } #--- file image create photo img_new -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQvEMlJ6wQvaw0q3g8gdtQHZuR1ihZirt7JtbQ1\ 3mkMYrn07jpZ77cZylAeHK7GjAAAOw==} image create photo img_open -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQ4EMlJKwJvZcC7BxdnSV04nCgKjtR6vZgmZ49L\ bmlus7xV9j4QQPYRtWbI3RCXU10WgKaTVPQAexEAOw==} image create photo img_save -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwQ90MlJqwRjgM13BpeGjOSIgQ6mdYCphW1Jtugp\ z2/6sVye8rwLMKiL3Tiwm6smUp5Cmaj0A+Utq6yrZTuJAAA7} image create photo img_compress -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAcALAAAAAAQABAAAAQ7EMgJjr0XvL0lxtr0hJ8VclSpcWz1hRQpISbb\ ZnVMmrXdmR4YZYQ7rHwukG5iZJZeneTTOCJOe9ZrLAIAOw==} image create photo img_reload -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAcALAAAAAAQABAAAAQ98IBJ67kYvM33xJfWcRoAiqRHZePUmSFZkewD\ IDZq16K+x7aWp5YK/iQvDaJHrKBgSFmL6JkCR6+McwuLAAA7} image create photo img_info -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwRG0MlJqwMv64c5BSCIACNimgSBgVy4Wt95Auk6\ cmXo1G0behOXUAcLCneECokkQ/Bwy5KJpupllkBJZ7MBfLhcbxDcLZonEQA7} set b [frame $f.file] pack $b -side left -padx 5 button $b.new -image img_new -takefocus 0 -command file_new set_balloon $b.new "New File..." button $b.open -image img_open -takefocus 0 -command file_load set_balloon $b.open "Open File..." button $b.save -image img_save -takefocus 0 \ -command file_save -state disabled set_balloon $b.save "Save As..." button $b.compress -image img_compress -takefocus 0 \ -command file_compress -state disabled set_balloon $b.compress "Compress File" button $b.reload -image img_reload -takefocus 0 \ -command file_reload -state disabled set_balloon $b.reload "Reload File" button $b.info -image img_info -takefocus 0 \ -command "file_info $b.info" -state disabled set_balloon $b.info "File Information..." pack $b.new $b.open $b.save $b.compress $b.reload $b.info -side left #--- config image create photo img_size -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQ8EMlJq72V6M05/khHWNoHnEC2ScAhHSnWOs4b\ h2vqHC5yVz/WxNNCHGowUw9267BQgEHQJMWJVr4BCBgBADs=} set b [frame $f.config] pack $b -side left -padx 5 button $b.size -image img_size -takefocus 0 \ -command "auto_size $b.size" set_balloon $b.size "Auto Data Size..." pack $b.size -side left #--- tree image create photo img_follow -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQwEMlJq714jpHrWFwnbaFoVkAGrCnSIgSBrhIL\ P3JtV3FuvxgaJjYBWgi4YqZ3aloiADs=} image create photo img_expand -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQvEMlJq712DJzX5pP2VQBIWuWVUitBTCsMlMTz\ IrHl3jnYUy7J7Cep8UA7k3IpiQAAOw==} image create photo img_collapse -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQkEMlJq7046wrwGBQgXsMCTh35hRvbSqm1urJJ\ V98Jvzvv/5UIADs=} set b [frame $f.tree] pack $b -side left -padx 5 button $b.follow -image img_follow -takefocus 0 \ -command {follow_links ""} set_balloon $b.follow "Follow Links..." if {$ProgData(follow)} { $b.follow configure -relief sunken } button $b.expand -image img_expand -takefocus 0 \ -command {tree_open /} -state disabled set_balloon $b.expand "Open One Level" button $b.collapse -image img_collapse -takefocus 0 \ -command {tree_close /} -state disabled set_balloon $b.collapse "Close One Level" pack $b.follow $b.expand $b.collapse -side left image create photo img_find -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAAARC0MnpELiIagfQO4+1Sd1nihriPeyZUYDJgscB\ aADYmjbO8z2Yh/Y5qHAlmvEGe2BqS99lipFeRpPYFAu7cmHfMDYCADs=} image create photo img_again -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAAARH0MnpELiIagfQO4+1Sd1nihriPeyZUYDJgscB\ aADYmjbO8z2Yh/Y5qHAlmvEGe2BqS99lipFeRpPYFAu7km5XL6fLATO5mwgAOw==} set b [frame $f.find] pack $b -side left -padx 5 button $b.first -image img_find -takefocus 0 \ -command find_node -state disabled set_balloon $b.first "Find Node..." button $b.again -image img_again -takefocus 0 \ -command find_again -state disabled set_balloon $b.again "Find Again" pack $b.first $b.again -side left #--- tools image create photo img_diff -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgMDAwICAgP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAcALAAAAAAQABAAQwQ6EEh5qr1n6gqep930ANeEnZ33hSNVWqE0njSW\ qmR9r3iuITDVxxYU5mBFHGdT44xaRxR0pptGbRpJBAA7} image create photo img_check -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAAAQ3EMlJq70V6A0wAk8YapkEig/YfeuHplzrvqPs\ niKZjblOnRpYyoLjDHc1IBFVXNKOvxjHQ5VEAAA7} image create photo img_plot -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAUALAAAAAAQABAAQwRKEDEkq7UsaxaSD+Amakk4ip05TRU7BZdbdSVI\ MU6Og14N5jqgAwckYo43ytEFCrCWlJRTKXt9bIhhkHb9EbVDWhNM1oaEwaKQGAEAOw==} image create photo img_calc -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQ8EIFJ60RYvg14fx2AfSH4ceMGqmqYrmEJvuXE\ zRqro/nOir2d67X6UYg+3unUwpGSTk/MFDVNYSOL9hIBADs=} set b [frame $f.tools] pack $b -side left -padx 5 button $b.diff -image img_diff -takefocus 0 \ -command diff_cgns -state disabled set_balloon $b.diff "Diff CGNS Files..." button $b.check -image img_check -takefocus 0 \ -command check_cgns -state disabled set_balloon $b.check "Check CGNS File..." button $b.plot -image img_plot -takefocus 0 \ -command plot_cgns -state disabled set_balloon $b.plot "Plot CGNS File..." button $b.calc -image img_calc -takefocus 0 \ -command calc_cgns -state disabled set_balloon $b.calc "Calculate CGNS..." pack $b.diff $b.check $b.plot $b.calc -side left image create photo img_convert -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAA4ALAAAAAAQABAAQwQt0MlJq70VSO349B0ghhwYntuIXZ7YUmaWxeu3\ 3eTb4Sld8yngztYDuYbC3yQCADs=} button $f.convert -image img_convert -takefocus 0 \ -command "units_convert $f.convert" set_balloon $f.convert "Unit Conversions..." pack $f.convert -side left -padx 5 #--- help image create photo img_help -data {\ R0lGODlhEAAQALMAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A\ /wD//////yH5BAEAAAgALAAAAAAQABAAQwQiEMlJq50kX5kJ1hvShd+4mSJ4qmTrXl28ehw7\ t+j75joVAQA7} button $f.help -image img_help -takefocus 0 \ -command {help_show cgnstools/cgnsview/index.html} pack $f.help -side left -padx 5 set_balloon $f.help Help proc help_menu {} { if [help_valid] { menubar_state Help normal 0 menubar_state Help normal 1 menubar_state Help normal 2 .toolbar.but.help configure -state normal } else { menubar_state Help disabled 0 menubar_state Help disabled 1 menubar_state Help disabled 2 .toolbar.but.help configure -state disabled } } help_init #---------- main window frame .main -width $ProgData(winwidth) -height $ProgData(winheight) pack .main -side top -fill both -expand 1 -padx 5 -pady 5 #--- window seperator frame .main.sep -width 6 -bd 2 -relief raised -cursor sb_h_double_arrow place .main.sep -relx $ProgData(seppos) -x -3 -rely 0 -relheight 1 bind .main.sep sep_begin_move proc sep_begin_move {} { set width [winfo width .main] set x [winfo rootx .main.sep] set y [winfo rooty .main.sep] set h [winfo height .main.sep] set xmin [expr [winfo rootx .main] + 100] set xmax [expr [winfo rootx .main] + $width - 100] set top [toplevel .main.move -borderwidth 1 \ -relief raised -cursor sb_h_double_arrow] wm overrideredirect $top 1 wm geom $top "4x$h+$x+$y" update idletasks grab set $top bind $top "sep_end_move $top $xmin $xmax %X" bind $top "sep_move $top $xmin $xmax %X $y" } proc sep_move {top xmin xmax x y} { if {$x < $xmin} { set x $xmin } elseif {$x > $xmax} { set x $xmax } wm geom $top "+$x+$y" } proc sep_end_move {top xmin xmax x} { global ProgData destroy $top if {$x < $xmin} { set x $xmin } elseif {$x > $xmax} { set x $xmax } set s [expr double($x - [winfo rootx .main]) / \ double([winfo width .main])] place .main.tree -relx 0 -relwidth $s -width -$ProgData(sepwd) \ -rely 0 -relheight 1 place .main.node -relx $s -x $ProgData(sepwd) \ -relwidth [expr 1.0 - $s] -width -$ProgData(sepwd) \ -rely 0 -relheight 1 place .main.sep -relx $s -x -3 -rely 0 -relheight 1 set ProgData(seppos) $s } #---------- node tree FrameCreate .main.tree -text "Node Tree" -font $Font(bold) place .main.tree -relx 0 -relwidth $ProgData(seppos) \ -width -$ProgData(sepwd) -rely 0 -relheight 1 set f [FrameGet .main.tree] set ProgData(tree) $f.tree scrollbar $f.ys -orient vertical -command "$ProgData(tree) yview" \ -takefocus 0 -highlightthickness 0 pack $f.ys -side right -fill y scrollbar $f.xs -orient horizontal -command "$ProgData(tree) xview" \ -takefocus 0 -highlightthickness 0 pack $f.xs -side bottom -fill x TreeCreate $ProgData(tree) -width 200 -height 400 -relief sunken \ -bd 2 -highlightthickness 1 -yscrollcommand "$f.ys set" -takefocus 1 \ -xscrollcommand "$f.xs set" -font $Font(normal) \ -lines $ProgData(showlines) pack $ProgData(tree) -side left -fill both -expand 1 bind $ProgData(tree) <1> {tree_show %W %x %y} bind $ProgData(tree) <2> {tree_info %W %x %y} bind $ProgData(tree) <3> {tree_menu %W %x %y} bind $ProgData(tree) {TreeToggle %W [TreeAt %W %x %y]} bind $ProgData(tree) {tree_at %W %x %y open} bind $ProgData(tree) {tree_at %W %x %y close} bind $ProgData(tree) {tree_at %W %x %y expand} bind $ProgData(tree) {tree_at %W %x %y collapse} bind $ProgData(tree) tree_next bind $ProgData(tree) tree_prev bind $ProgData(tree) tree_collapse bind $ProgData(tree) tree_expand bind $ProgData(tree) tree_toggle bind $ProgData(tree) tree_insert bind $ProgData(tree) tree_rename bind $ProgData(tree) tree_delete set ProgData(menu) [menu .nodemenu -tearoff 0] $ProgData(menu) add command -label "Expand" -command tree_expand $ProgData(menu) add command -label "Collapse" -command tree_collapse $ProgData(menu) add command -label "Info..." -command cgns_info $ProgData(menu) add separator set ProgData(insert) [menu .nodemenu.insert -tearoff 0] $ProgData(menu) add cascade -label "Insert" -menu $ProgData(insert) $ProgData(menu) add command -label "Rename" -command tree_rename $ProgData(menu) add command -label "Delete" -command tree_delete #---------- node data set wl 12 set we 30 frame .main.node place .main.node -relx $ProgData(seppos) -x $ProgData(sepwd) \ -relwidth [expr 1.0 - $ProgData(seppos)] -width -$ProgData(sepwd) \ -rely 0 -relheight 1 #----- node description FrameCreate .main.node.node -text "Node Description" -font $Font(bold) pack .main.node.node -side top -pady 2 -fill x set node [FrameGet .main.node.node] set f [frame $node.parent] pack $f -side top -fill x label $f.lab -text "Parent Node" -width $wl -anchor w pack $f.lab -side left entry $f.ent -textvariable Node(parent) -width $we -highlightthickness 0 pack $f.ent -side left -fill x -expand 1 entry_balloon $f.ent set f [frame $node.name] pack $f -side top -fill x label $f.lab -text "Node Name" -width $wl -anchor w pack $f.lab -side left ComboboxCreate $f.cb -width 5 -variable Node(name) \ -command set_node_name pack $f.cb -side top -fill x -expand 1 entry_balloon $f.cb.ent proc set_node_name {w n} { global Node NodeSave CGNSnodes _Combobox set name [ComboboxValue $w $n] if {$NodeSave(lnode) == ""} { set Node(label) [lindex $CGNSnodes($name) 1] set Node(type) [lindex $CGNSnodes($name) 2] set Node(dim) [lindex $CGNSnodes($name) 3] } if {[lindex $CGNSnodes($name) 0]} { $w.ent selection clear } else { set _Combobox($w,focus) $w.ent $w.ent delete 0 end $w.ent insert 0 $name $w.ent selection range 0 end } return $name } set f [frame $node.label] pack $f -side top -fill x label $f.lab -text "Node Label" -width $wl -anchor w pack $f.lab -side left ComboboxCreate $f.cb -width 5 -variable Node(label) pack $f.cb -side top -fill x -expand 1 entry_balloon $f.cb.ent #----- link description FrameCreate .main.node.link -text "Link Description" -font $Font(bold) pack .main.node.link -side top -pady 2 -fill x set link [FrameGet .main.node.link] foreach i {\ {lfile "Link File"} \ {lnode "Link Node"}} { set j [lindex $i 0] set f [frame $link.$j] pack $f -side top -fill x label $f.lab -text [lindex $i 1] -width $wl -anchor w pack $f.lab -side left entry $f.ent -textvariable Node($j) -width 5 -highlightthickness 0 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -padx 0 -pady 0 -command "select_$j $f.but" pack $f.but -side right -fill y entry_balloon $f.ent } #----- data description FrameCreate .main.node.fmt -text "Data Description" -font $Font(bold) pack .main.node.fmt -side top -pady 2 -fill x set fmt [FrameGet .main.node.fmt] set f [frame $fmt.type] pack $f -side top -fill x label $f.lab -text "Data Type" -width $wl -anchor w pack $f.lab -side left ComboboxCreate $f.cb -values $DataTypes -variable Node(type) \ -edit 0 -width 5 -height 5 -command set_data_type -post get_data_index pack $f.cb -side top -fill x -expand 1 proc set_data_type {w n} { global ProgData DataTypes Node set oldtype [ComboboxEntry $w] set newtype [lindex [lindex $DataTypes $n] 0] if {$oldtype == $newtype} {return $newtype} node_clear if {![string match {?[148]} $newtype] || ![string match {?[148]} $oldtype]} { set Node(dim) "" set Node(size) 0 $ProgData(buttons).read configure -state disabled return $newtype } $ProgData(buttons).read configure -state normal if {![catch {expr int($Node(size))} size]} { if {[string match "X?" $oldtype]} { set oldsize [expr 2 * [string index $oldtype 1]] } else { set oldsize [string index $oldtype 1] } if {[string match "X?" $newtype]} { set newsize [expr 2 * [string index $newtype 1]] } else { set newsize [string index $newtype 1] } set Node(size) [expr ($size * $newsize) / $oldsize] } return $newtype } proc get_data_index {w s} { global DataTypes return [lsearch -glob $DataTypes "$s*"] } set f [frame $fmt.dim] pack $f -side top -fill x label $f.lab -text Dimensions -width $wl -anchor w pack $f.lab -side left entry $f.ent -textvariable Node(dim) -width $we -highlightthickness 0 pack $f.ent -side left -fill x -expand 1 set f [frame $fmt.size] pack $f -side top -fill x label $f.lab -text Bytes -width $wl -anchor w pack $f.lab -side left entry $f.ent -textvariable Node(size) -width $we \ -state disabled -cursor {} -highlightthickness 0 pack $f.ent -side left -fill x -expand 1 #---------- buttons set ProgData(buttons) [frame .main.node.buttons] pack $ProgData(buttons) -side top -fill x -pady 3 foreach i {create modify read clear delete} { button $ProgData(buttons).$i -text $i -width 6 -state disabled \ -command node_$i pack $ProgData(buttons).$i -side left -expand 1 } #---------- node data FrameCreate .main.node.data -text "Node Data" -font $Font(bold) -pady 0 pack .main.node.data -side top -pady 2 -fill both -expand 1 set data [FrameGet .main.node.data] set f [frame $data.list] pack $f -side top -fill both -expand 1 -pady 2 scrollbar $f.ys -orient vertical -command "$f.text yview" \ -takefocus 0 -highlightthickness 0 pack $f.ys -side right -fill y scrollbar $f.xs -orient horizontal -command "$f.text xview" \ -takefocus 0 -highlightthickness 0 pack $f.xs -side bottom -fill x set ProgData(text) [text $f.text -width 40 -height 5 \ -wrap none -xscrollcommand "$f.xs set" \ -yscrollcommand "$f.ys set" -highlightthickness 0] pack $f.text -side top -fill both -expand 1 bind $ProgData(text) cgns_data bind $ProgData(text) {tkTabToWindow [tk_focusNext %W];break} bind $ProgData(text) {tkTabToWindow [tk_focusPrev %W];break} bind $ProgData(text) get_location bind $ProgData(text) get_location set f [frame $data.loc] pack $f -side top -fill x -pady 2 label $f.lab -text Line entry $f.ent -width 10 -textvariable ProgData(linenum) pack $f.lab $f.ent -side left bind $f.ent {set_location %W} label $f.val -textvariable ProgData(lineval) pack $f.val -side left -padx 5 frame $f.cnt pack $f.cnt -side right label $f.cnt.lab -text "Values/Line" entry $f.cnt.ent -width 8 -textvariable ProgData(linecnt) pack $f.cnt.lab $f.cnt.ent -side left bind $f.cnt.ent {set_perline %W} proc get_location {} { global ProgData set linenum [lindex [split [$ProgData(text) index insert] .] 0] set ProgData(linenum) $linenum if {$ProgData(linecnt) == ""} { set ProgData(lineval) "" } else { set ProgData(lineval) "([expr $ProgData(linecnt) * ($linenum - 1) + 1])" } } proc set_location {w} { global ProgData if {![catch {expr int([$w get])} linenum]} { catch { $ProgData(text) mark set insert $linenum.0 $ProgData(text) see $linenum.0 } } get_location focus $ProgData(text) } proc set_perline {w} { if {[catch {expr int([$w get])} cnt] || $cnt < 1} { set cnt 0 } node_read $cnt } #---------- update buttons when node changes trace variable Node(parent) w check_node trace variable Node(name) w check_node #========== procedures =============================================== proc do_quit {} { global ProgData if {![remove_backup]} return catch CGIOclose set ProgData(winwidth) [winfo width .main] set ProgData(winheight) [winfo height .main] foreach i $ProgData(reg,vals) { catch {tclreg_set $ProgData(reg,key) $i $ProgData($i)} } catch units_write catch tclreg_close catch {WinHtml close} destroy . exit 0 } image create photo img_about -data {\ R0lGODlhIAAgAMIEAAAAgICAAMDAwP/OIf///////////////yH5BAEKAAQALAAAAAAgACAA\ AAPASLrc/m7ICSucmFqbu9yXFwQZ2HRjGhCayWJptn4uOY2DAr85aEszFU/Xs+BoA9WxRzP+\ CKRFjNKsPFeNZa76WAK+AAUYMPiWyYSxA/dNh9sEQWBMhkNGZoF4PB9LwCdSZm2EAH1nR3Y6\ CwJqboVnZ4oLRSNDDCg2IQpTHhhQLZxEnJaeFD9FpJcpPDJEXFAzpyoyWCVZWjlKQq2wsVpS\ vJ5dnaamVsXGt3fJyr64ucZYPrSmli6ku7vYa9rX3OAJADs=} proc do_about {} { global ProgData dialog .about -1 -1 "About CGNSview" \ "CGNSview Version 3.2 CGNS Library Version $ProgData(libvers) Bruce Wedan leavingdust@gmail.com" img_about 0 Close } proc do_backup {} { global ProgData if {!$ProgData(backup) || $ProgData(bakfile) != ""} return set name "$ProgData(file,name).bak" if {[file exists $name]} { for {set n 1} {$n < 100} {incr n} { if {![file exists $name$n]} { append name $n break } } } dialog .backup -1 -1 "Back Up" "Backing up file to \"$name\"" \ hourglass 0 update if {![catch {file copy $ProgData(file,name) $name} msg]} { set msg "" } destroy .backup if {$msg == ""} { set ProgData(bakfile) $name menubar_state File normal 7 } else { errormsg $msg menubar_state File disabled 7 } } proc remove_backup {} { global ProgData if {$ProgData(bakfile) != "" && [file exists $ProgData(bakfile)]} { set del [dialog .delbak -1 -1 Delete \ "delete the backup file ?" question 0 Yes No Cancel] if {$del == 2} {return 0} if {$del == 0} {catch {file delete $ProgData(bakfile)}} } set ProgData(bakfile) "" menubar_state File disabled 7 return 1 } proc restore_backup {} { global ProgData if {$ProgData(bakfile) == "" ||![file exists $ProgData(bakfile)]} return catch CGIOclose if {[catch {file rename -force $ProgData(bakfile) \ $ProgData(file,name)} msg]} { errormsg $msg return } set ProgData(bakfile) "" menubar_state File disabled 7 file_reload } #----- configuration proc follow_links {state} { global ProgData if {$state == ""} { if {$ProgData(follow)} { set ProgData(follow) 0 } else { set ProgData(follow) 1 } } if {$ProgData(follow)} { .toolbar.but.tree.follow configure -relief sunken } else { .toolbar.but.tree.follow configure -relief raised } file_reload } proc auto_size {{loc .}} { global ProgData NewSize catch {destroy .size} toplevel .size wm title .size "Node Data Loading" wm transient .size . foreach i {maxsize maxcnt} { set NewSize($i) $ProgData($i) } FrameCreate .size.top pack .size.top -side top -padx 5 -pady 2 -fill x set top [FrameGet .size.top] set f [frame $top.size] pack $f -side top -fill x -padx 5 -pady 5 label $f.lab -width 24 -text "Auto Load Data Size (bytes)" -anchor w entry $f.ent -width 15 -textvariable NewSize(maxsize) pack $f.lab $f.ent -side left set f [frame $top.cnt] pack $f -side top -fill x -padx 5 -pady 5 label $f.lab -width 24 -text "Max Data Values per Line" -anchor w entry $f.ent -width 15 -textvariable NewSize(maxcnt) pack $f.lab $f.ent -side left set f [frame .size.but] pack $f -side top -fill x -expand 1 -padx 5 -pady 5 button $f.accept -text Accept -width 8 -default active -command { foreach i {maxsize maxcnt} { if {![catch {expr int($NewSize($i))} size]} { set ProgData($i) $size } } destroy .size } button $f.default -text Default -width 8 -command { foreach i {size cnt} { set NewSize(max$i) $ProgData(def$i) } } button $f.cancel -text Cancel -width 8 -command {destroy .size} pack $f.accept $f.default $f.cancel -side left -expand 1 bind .size "$f.accept invoke" center_window .size $loc set oldFocus [focus] set oldGrab [grab current .size] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab .size} tkwait visibility .size focus .size tkwait window .size catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } } #----- node operations proc check_links {node} { set path {} foreach p [split [file dirname $node] /] { if {$p != ""} { append path "/$p" if {[CGIOlink $path] != {}} {return 1} } } return 0 } proc recursive_link {node link} { set path {} foreach p [split $node /] { if {$p != ""} { append path "/$p" if {$link == $path} {return 1} } } return 0 } proc get_node {parent name} { if {$name == ""} {return ""} if {$parent == ""} { if {$name == "/"} {return "/"} return "" } if {$parent == "/"} {return "/$name"} return "$parent/$name" } proc delete_node {node} { global ProgData if {$node == ""} return if {$node == "/"} { errormsg "can't delete root node of CGNS file" return } if {[check_links $node]} { errormsg "can't delete child of a linked parent node" return } if {$ProgData(verify) && [dialog .delete -1 -1 "Delete Node" \ "Delete the node \"$node\" ?" warning 0 Yes No Cancel]} { return } do_backup if {[catch {CGIOdelete $node} msg]} { errormsg $msg file_reload } else { TreeDelete $ProgData(tree) $node update_node [TreeSelectionGet $ProgData(tree)] } } proc update_node {node} { global ProgData Node NodeSave CGNSnodes CGNSnodeChildren set Node(trace) 0 node_clear if {$node == {}} { array set Node { parent "" name "" node "" label "" type "" dim "" size "" lnode "" lfile "" link 0 } set size 0 } else { set ProgData(start) $node set Node(node) $node if {$node == "/"} { set Node(parent) {} set Node(name) $node } else { set Node(parent) [file dirname $node] set Node(name) [file tail $node] } catch {CGIOlabel $node} Node(label) if {![catch {CGIOtype $node} type]} { set Node(type) [string toupper $type] } else { set Node(type) $type } catch {CGIOdimensions $node} Node(dim) if {[catch {CGIOsize $node} Node(size)]} { set size 0 } else { set size $Node(size) } if {[catch {CGIOlink $node} link]} { set Node(lnode) $link } else { set Node(lnode) [lindex $link 0] set Node(lfile) [lindex $link 1] } set Node(link) [check_links $node] } foreach i [array names Node] { set NodeSave($i) $Node($i) } set node [FrameGet .main.node.node] set link [FrameGet .main.node.link] set fmt [FrameGet .main.node.fmt] if {$ProgData(readonly) || $Node(node) == "/" || $Node(link)} { $node.parent.ent configure -state disabled -cursor {} ComboboxConfig $node.name.cb -state disabled ComboboxConfig $node.label.cb -state disabled foreach i {lfile lnode} { $link.$i.ent configure -state disabled -cursor {} $link.$i.but configure -state disabled } ComboboxConfig $fmt.type.cb -state disabled $fmt.dim.ent configure -state disabled -cursor {} } else { $node.parent.ent configure -state normal -cursor xterm if {$Node(parent) == "/"} { set names $CGNSnodeChildren(/) } elseif {[catch {CGIOlabel $Node(parent)} label] || ![info exists CGNSnodeChildren($label)]} { set names "" } else { set names $CGNSnodeChildren($label) } ComboboxConfig $node.name.cb -values $names -state normal foreach i {lfile lnode} { $link.$i.ent configure -state normal -cursor xterm $link.$i.but configure -state normal } if {$Node(lnode) == ""} { set vallist {} foreach n $names { set val [lindex $CGNSnodes($n) 1] if {[lsearch $vallist $val] < 0} { lappend vallist $val } } ComboboxConfig $node.label.cb -values $vallist -state normal ComboboxConfig $fmt.type.cb -state normal $fmt.dim.ent configure -state normal -cursor xterm } else { ComboboxConfig $node.label.cb -state disabled ComboboxConfig $fmt.type.cb -state disabled $fmt.dim.ent configure -state disabled -cursor {} } } update idletasks set Node(trace) 1 check_node if {!$size} { $ProgData(buttons).read configure -state disabled } else { $ProgData(buttons).read configure -state normal if {$ProgData(autoload) && [expr $size <= $ProgData(maxsize)]} { node_read } } } proc show_node {node} { global ProgData TreeSelectionSet $ProgData(tree) $node update_node $node } proc check_node {args} { global ProgData Node NodeSave if {!$Node(trace)} return set parent [string trim $Node(parent)] set name [string trim $Node(name)] set node [get_node $parent $name] if {$ProgData(readonly)} { foreach b {create modify delete} { $ProgData(buttons).$b configure -state disabled } if {$NodeSave(node) == ""} { $ProgData(buttons).read configure -state disabled } else { $ProgData(buttons).read configure -state normal } $ProgData(text) configure -state disabled -cursor {} -takefocus 0 return } if {$NodeSave(node) == "" || $NodeSave(link)} { foreach b {modify delete} { $ProgData(buttons).$b configure -state disabled } if {$NodeSave(node) == ""} { $ProgData(buttons).read configure -state disabled } else { $ProgData(buttons).read configure -state normal } if {$node != "" && [CGIOnode $node] == ""} { $ProgData(buttons).create configure -state normal $ProgData(text) configure -state normal -cursor xterm -takefocus 1 } else { $ProgData(buttons).create configure -state disabled $ProgData(text) configure -state disabled -cursor {} -takefocus 0 } return } if {$node == $NodeSave(node)} { $ProgData(buttons).read configure -state normal if {$node == "/"} { foreach b {create modify delete} { $ProgData(buttons).$b configure -state disabled } $ProgData(text) configure -state disabled -cursor {} -takefocus 0 } else { $ProgData(buttons).create configure -state disabled foreach b {modify delete} { $ProgData(buttons).$b configure -state normal } if {[string trim $Node(lnode)] == ""} { $ProgData(text) configure -state normal -cursor xterm -takefocus 1 } else { $ProgData(text) configure -state disabled -cursor {} -takefocus 0 } } return } foreach b {create modify read delete} { $ProgData(buttons).$b configure -state disabled } $ProgData(text) configure -state disabled -cursor {} -takefocus 0 if {$node == "" || [CGIOnode $node] != ""} return if {$parent == "/" || [CGIOnode $parent] == "node"} { foreach b {create modify} { $ProgData(buttons).$b configure -state normal } $ProgData(text) configure -state normal -cursor xterm -takefocus 1 } } proc add_node {parent child args} { global ProgData Font set tree $ProgData(tree) set node $parent/$child if {[string first / $child] >= 0 || [catch {CGIOlink $node} link]} { if {$parent == ""} {set parent /} TreeInsert $tree $child -dir $parent -icon invalid -fill red return } if {$link == {}} { set img img set opts $args } else { if {[lindex $link 1] == "" && [recursive_link $node [lindex $link 0]]} { TreeInsert $tree $node -icon badlink -fill red return } set img link set opts "-fill blue -tag link" } if {[catch {CGIOnumchild $node} numchild]} { TreeInsert $tree $node -icon bad$img -fill red return } if {$numchild < 1} { eval TreeInsert $tree {$node} -icon file$img $args return } eval TreeInsert $tree {$node} -icon dir$img $args if {$link != {} && !$ProgData(follow)} return if {[catch {CGIOchildren $node} children] || $children == {}} { for {set n 1} {$n <= $numchild} {incr n} { if {[catch {CGIOchildname $node $n} name]} { TreeInsert $tree invalid$n -dir $node -icon invalid -fill red } else { eval add_node {$node} {$name} $opts } } } else { foreach n $children { eval add_node {$node} {$n} $opts } } } proc build_tree {} { global ProgData if {[catch {CGIOchildren /} children]} { TreeInsert $ProgData(tree) / -icon badimg return } dialog .build -1 -1 "Reading..." \ "Reading nodes and building node tree" hourglass 0 {} .build configure -cursor watch . configure -cursor watch update TreeInsert $ProgData(tree) / -icon dirimg foreach n $children { add_node "" $n } destroy .build . configure -cursor {} } #----- tree proc tree_show {w x y} { set node [TreeAt $w $x $y] if {$node != ""} { show_node $node } } proc tree_info {w x y} { set node [TreeAt $w $x $y] if {$node == ""} return if {$node != [TreeSelectionGet $w]} { show_node $node } cgns_info } proc insert_menu {w node} { global ProgData CGNSnodes CGNSnodeChildren set allowed {} if {$node == "/"} { set parent "" set type / } else { set parent $node if [catch {CGIOlabel $node} type] {set type ""} } if {$type != "" && [info exists CGNSnodeChildren($type)]} { set existing {} foreach child [TreeGet $w $node -children] { if [info exists CGNSnodes($child)] { if [lindex $CGNSnodes($child) 0] { lappend existing $child } else { lappend existing [lindex $CGNSnodes($child) 1] } } else { if {![catch {CGIOlabel $parent/$child} lab]} { lappend existing $lab } } } if {[lsearch $CGNSnodeChildren($type) PointList] >= 0} { foreach n {PointList PointRange ElementList ElementRange} { if {[lsearch $existing $n] >= 0} { lappend existing PointList PointRange ElementList ElementRange break } } if {$type == "GridConnectivity_t"} { if {[lsearch $existing PointListDonor] >= 0 || [lsearch $existing CellListDonor] >= 0} { lappend existing PointListDonor CellListDonor } } } foreach n $CGNSnodeChildren($type) { if [lindex $CGNSnodes($n) 0] { set i $n } else { set i [lindex $CGNSnodes($n) 1] } if {[lindex $CGNSnodes($n) 4] || [lsearch $existing $i] < 0} { lappend allowed $n } } } destroy $ProgData(insert) set m [menu $ProgData(insert) -tearoff 0] $m add command -label "New Node" -command tree_insert if {$allowed != {}} { $m add separator foreach n $allowed { $m add command -label $n -command "tree_insert $n" } } } proc tree_menu {w x y} { global ProgData set node [TreeAt $w $x $y] if {$node == ""} return if {$node != [TreeSelectionGet $w]} { show_node $node } if {$ProgData(readonly) || [TreeGet $w $node -tag] == "link"} { if {[TreeGet $w $node -children] == {}} return foreach n {0 1} { $ProgData(menu) entryconfigure $n -state normal } foreach n {4 5 6} { $ProgData(menu) entryconfigure $n -state disabled } } else { if {[TreeGet $w $node -children] == {}} { $ProgData(menu) entryconfigure 0 -state disabled $ProgData(menu) entryconfigure 1 -state disabled } else { $ProgData(menu) entryconfigure 0 -state normal $ProgData(menu) entryconfigure 1 -state normal } if {[string match "*link" [TreeGet $w $node -icon]]} { $ProgData(menu) entryconfigure 4 -state disabled } else { $ProgData(menu) entryconfigure 4 -state normal insert_menu $w $node } if {$node == "/"} { $ProgData(menu) entryconfigure 2 -state disabled $ProgData(menu) entryconfigure 5 -state disabled $ProgData(menu) entryconfigure 6 -state disabled } else { $ProgData(menu) entryconfigure 2 -state normal $ProgData(menu) entryconfigure 5 -state normal $ProgData(menu) entryconfigure 6 -state normal } } $ProgData(menu) post [expr [winfo rootx $ProgData(tree)] + $x] \ [expr [winfo rooty $ProgData(tree)] + $y] } proc tree_toggle {{node ""}} { global ProgData if {$node == ""} { set node [TreeSelectionGet $ProgData(tree)] if {$node == ""} return } TreeToggle $ProgData(tree) $node } proc tree_expand {{node ""}} { global ProgData if {$node == ""} { set node [TreeSelectionGet $ProgData(tree)] if {$node == ""} return } TreeExpand $ProgData(tree) $node } proc tree_open {{node ""}} { global ProgData if {$node == ""} { set node [TreeSelectionGet $ProgData(tree)] if {$node == ""} return } TreeOpenLevel $ProgData(tree) $node } proc tree_collapse {{node ""}} { global ProgData if {$node == ""} { set node [TreeSelectionGet $ProgData(tree)] if {$node == ""} return } TreeCollapse $ProgData(tree) $node } proc tree_close {{node ""}} { global ProgData if {$node == ""} { set node [TreeSelectionGet $ProgData(tree)] if {$node == ""} return } TreeCloseLevel $ProgData(tree) $node } proc tree_at {w x y mode} { set node [TreeAt $w $x $y] if {$node == ""} return if {$node != [TreeSelectionGet $w]} { show_node $node } switch $mode { expand {TreeExpand $w $node} collapse {TreeCollapse $w $node} open {tree_open $node} close {tree_close $node} } } proc tree_insert {{name "New Node"}} { global ProgData CGNSnodes if {$ProgData(readonly)} return set w $ProgData(tree) set parent [TreeSelectionGet $w] if {$parent == ""} return set icon [TreeGet $w $parent -icon] set open [TreeGet $w $parent -open] TreeSet $w $parent -icon dirimg -open 1 if {$parent == "/"} { set root "" } else { set root $parent } set node "$root/$name" if {[CGIOnode $node] != ""} { for {set n 1} {$n < 100} {incr n} { if {[CGIOnode "$node$n"] == ""} { append node "$n" break } } } if [info exists CGNSnodes($name)] { set cgnsnode $CGNSnodes($name) set fixed [lindex $cgnsnode 0] } else { set cgnsnode {} set fixed 0 } TreeInsert $w $node -icon fileimg if {!$fixed} { set name [TreeEdit $w $node] if {$name == ""} { TreeSet $w $parent -icon $icon -open $open TreeDelete $w $node return } TreeMove $w $node $name } do_backup if {[catch {CGIOcreate "$root/$name"} msg]} { errormsg $msg file_reload return } TreeSelectionSet $w "$root/$name" if {$cgnsnode != {}} { set labl [lindex $cgnsnode 1] set type [lindex $cgnsnode 2] set dims [lindex $cgnsnode 3] catch {CGIOlabel "$root/$name" $labl} if {$type == "C1"} { if {$labl == "DimensionalUnits_t"} { set data [list Kilogram Meter Second Kelvin Radian] } elseif {$labl == "AdditionalUnits_t"} { set data [list Ampere Mole Candela] } else { set data Null } if {$dims == {}} {set dims [string length $data]} catch {CGIOwrite "$root/$name" $type $dims $data} } elseif {$type != {} && $dims != {}} { catch {CGIOwrite "$root/$name" $type $dims 0} } else { if {$type != {}} { catch {CGIOtype "$root/$name" $type} } if {$dims != {}} { catch {CGIOdimensions "$root/$name" $dims} } } } update_node "$root/$name" } proc tree_delete {} { global ProgData if {$ProgData(readonly)} return delete_node [TreeSelectionGet $ProgData(tree)] } proc tree_rename {} { global ProgData if {$ProgData(readonly)} return set w $ProgData(tree) set node [TreeSelectionGet $w] if {$node == ""} return set name [TreeEdit $w $node] if {$name == "" || $name == [file tail $node]} return do_backup if {[catch {CGIOname $node $name} msg]} { errormsg $msg } else { TreeMove $w $node $name set node [get_node [file dirname $node] $name] } file_reload if {[CGIOnode $node] != ""} { TreeSelectionSet $w $node update_node $node } } proc tree_prev {{update 1}} { global ProgData set tree $ProgData(tree) set cur [TreeSelectionGet $tree] if {$cur == ""} { set node / } else { set node [TreePrev $tree $cur] } if {$node != ""} { TreeSelectionSet $tree $node TreeSee $tree $node if {$update} { update_node $node } } } proc tree_next {{update 1}} { global ProgData set tree $ProgData(tree) set cur [TreeSelectionGet $tree] if {$cur == ""} { set node / } else { set node [TreeNext $tree $cur] } if {$node != ""} { TreeSelectionSet $tree $node TreeSee $tree $node if {$update} { update_node $node } } } #----- node search proc find_node {} { global ProgData set w .find catch {destroy $w} toplevel $w wm title $w "Find Node..." wm transient $w . wm protocol $w WM_DELETE_WINDOW {set ProgData(done) 0} set f [frame $w.f1] pack $f -side top -fill x -padx 5 -pady 5 -fill x label $f.lab -text "Node:" pack $f.lab -side left entry $f.ent -relief sunken -width 20 -textvariable ProgData(find) \ -highlightthickness 0 pack $f.ent -side left -fill x -expand 1 set f [frame $w.f2] pack $f -side left -fill y -padx 5 -pady 5 checkbutton $f.case -text "Match Case" -variable ProgData(case) \ -onvalue 1 -offvalue 0 checkbutton $f.top -text "Start from Root" \ -variable ProgData(fromtop) -onvalue 1 -offvalue 0 pack $f.case $f.top -side top -anchor w -expand 1 set sel [TreeSelectionGet $ProgData(tree)] if {$sel == "" || ![TreeExists $ProgData(tree) $sel]} { set ProgData(start) / $f.top configure -state disabled } else { set ProgData(start) $sel } set f [frame $w.f3] pack $f -side right -fill y -padx 5 -pady 5 button $f.find -text Find -width 6 -default active \ -command {set ProgData(done) 1} button $f.cancel -text Cancel -width 6 -command {set ProgData(done) 0} pack $f.find $f.cancel -side top -expand 1 bind $w {set ProgData(done) 1} center_window $w . set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w.f1.ent tkwait variable ProgData(done) destroy $w catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } if {$ProgData(done) && $ProgData(find) != ""} { if {$ProgData(fromtop)} { set ProgData(start) / } find_again } } proc find_again {} { global ProgData if {$ProgData(find) == ""} { find_node return } if {$ProgData(start) == ""} {set ProgData(start) /} set node [TreeFind $ProgData(tree) $ProgData(start) \ $ProgData(find) $ProgData(case)] if {$node == ""} { errormsg "node not found" set ProgData(start) / return } TreeSee $ProgData(tree) $node TreeSelectionSet $ProgData(tree) $node update_node $node set ProgData(start) $node } #----- file operations proc file_stats {} { global ProgData set ProgData(file,size) "[file size $ProgData(file,name)] bytes" set ProgData(file,type) [CGNSfile $ProgData(file)] set ProgData(file,vers) [CGIOversion] if [file writable $ProgData(file,name)] { set ProgData(file,mode) "read/write" } else { set ProgData(file,mode) "read-only" } foreach t {mtime atime} { if {[catch {clock format [file $t $ProgData(file,name)] \ -format "%a %b %d %Y %T"} time]} { set ProgData(file,$t) unknown } else { set ProgData(file,$t) $time } } if {[catch {CGIOread /CGNSLibraryVersion} cgns]} { set ProgData(filevers) "" set ProgData(file,cgns) unknown } else { set ProgData(filevers) $cgns set ProgData(file,cgns) "CGNS $cgns" } } proc file_extension {} { global ProgData } proc file_select {what name format} { global ProgData tcl_platform Font set ProgData(newfile) $name set ProgData(format) [string tolower $format] set w .selfile catch {destroy $w} toplevel $w wm title $w "$what File..." wm transient $w . wm protocol $w WM_DELETE_WINDOW {set ProgData(done) 0} FrameCreate $w.file -text "File Name" -font $Font(bold) pack $w.file -side top -pady 2 -fill x set file [FrameGet $w.file] entry $file.ent -textvariable ProgData(newfile) -width 30 pack $file.ent -side left -fill x -expand 1 button $file.but -text Browse -pady 0 -command " set fname \[FileSave {$what File} \$ProgData(newfile) . \ \$ProgData(extensions) \$ProgData(format)\] if {\$fname != {}} { set ProgData(newfile) \$fname } " pack $file.but -side right -fill y FrameCreate $w.format -text "File Type" -font $Font(bold) pack $w.format -side top -fill x set fmt [FrameGet $w.format] foreach i {adf hdf5} { radiobutton $fmt.$i -text [string toupper $i] \ -variable ProgData(format) -value $i -command file_extension if {[CGIOsupported $i] == ""} { $fmt.$i configure -state disabled } pack $fmt.$i -side left -expand 1 } set f [frame $w.but] pack $f -side top -pady 5 button $f.accept -text Accept -width 6 -default active \ -command {set ProgData(done) 1} button $f.cancel -text Cancel -width 6 -command {set ProgData(done) 0} pack $f.accept $f.cancel -side left -padx 5 bind $w {set ProgData(done) 1} center_window $w . set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $file.ent $file.ent selection range 0 end tkwait variable ProgData(done) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } if {$ProgData(done) && $ProgData(newfile) != ""} { return 1 } return 0 } proc file_new {} { global ProgData set name NewFile.$ProgData(format) if [file_select New $name $ProgData(format)] { catch CGIOclose if {[file exists $ProgData(newfile)] && [catch {file delete $ProgData(newfile)} msg]} { errormsg $msg return } catch {CGIOopen $ProgData(newfile) write $ProgData(format)} file_load $ProgData(newfile) } } proc file_load {{inpfile ""}} { global ProgData tcl_platform if {$inpfile == ""} { set inpfile [FileOpen "Open File" $ProgData(file) . \ $ProgData(extensions)] if {$inpfile == ""} return } if [catch {CGNSfile $inpfile} type] { errormsg $type return } if {[CGIOsupported $type] == ""} { errormsg "file type $type not supported" return } set dir [file dirname $inpfile] set fname [file tail $inpfile] catch CGIOclose remove_backup if {[catch {cd $dir} msg]} { errormsg $msg return } set dir [pwd] if [file writable $fname] { set mode modify set ProgData(readonly) 0 } else { set mode read set ProgData(readonly) 1 } dialog .open -1 -1 "Opening..." \ "Opening and reading $fname" hourglass 0 {} .open configure -cursor watch . configure -cursor watch update if {![catch {CGIOopen $fname $mode $type} msg]} { set msg "" } destroy .open . configure -cursor {} if {$msg != ""} { errormsg $msg return } set ProgData(file,name) $fname if {$tcl_platform(platform) == "windows"} { set ProgData(file,dir) [join [split $dir /] \\] } else { set ProgData(file,dir) $dir } set ProgData(file) $inpfile file_stats TreeDelete $ProgData(tree) / build_tree if {$ProgData(readonly)} { append fname " (read only)" } wm title . "CGNSview : $fname" foreach i {compress reload save info} { .toolbar.but.file.$i configure -state normal } foreach i {2 3 5 6} { menubar_state File normal $i } foreach i {tree.expand tree.collapse find.first find.again} { .toolbar.but.$i configure -state normal } foreach i {1 2 4 5} { menubar_state Tree normal $i } if {$ProgData(filevers) == ""} { set state disabled } else { set state normal } if {$ProgData(cgnsdiff) == ""} { .toolbar.but.tools.diff configure -state disabled menubar_state Tools disabled 0 } else { .toolbar.but.tools.diff configure -state $state menubar_state Tools $state 0 } if {$ProgData(cgnscheck) == ""} { .toolbar.but.tools.check configure -state disabled menubar_state Tools disabled 1 } else { .toolbar.but.tools.check configure -state $state menubar_state Tools $state 1 } if {$ProgData(cgnsplot) == ""} { .toolbar.but.tools.plot configure -state disabled menubar_state Tools disabled 2 } else { .toolbar.but.tools.plot configure -state $state menubar_state Tools $state 2 } if {$ProgData(cgnscalc) == ""} { .toolbar.but.tools.calc configure -state disabled menubar_state Tools disabled 3 } else { .toolbar.but.tools.calc configure -state $state menubar_state Tools $state 3 } foreach i $ProgData(menucfg) { catch {[lindex $i 0] entryconfigure [lindex $i 1] -state $state} } $ProgData(buttons).clear configure -state normal update_node "" } proc file_reload {} { global ProgData if {$ProgData(file,name) == ""} return catch {cd $ProgData(file,dir)} if [file writable $ProgData(file,name)] { set mode modify set ProgData(readonly) 0 wm title . "CGNSview : $ProgData(file,name)" } else { set mode read set ProgData(readonly) 1 wm title . "CGNSview : $ProgData(file,name) (read only)" } if {[catch {CGIOopen $ProgData(file,name) $mode $ProgData(file,type)} msg]} { errormsg $msg } else { build_tree } set node [TreeSelectionGet $ProgData(tree)] if {$node != "" && ![TreeVisible $ProgData(tree) $node]} { set node "" } update_node $node } proc file_compress {} { global ProgData if {$ProgData(file,name) == ""} return if {![file writable $ProgData(file,name)]} { errormsg "current file is not writable" return } do_backup catch {cd $ProgData(file,dir)} set oldsize [file size $ProgData(file,name)] if [catch {CGIOcompress $ProgData(file,name)} msg] { errormsg $msg catch CGIOclose } else { set newsize [file size $ProgData(file,name)] if {$newsize < $oldsize} { dialog .compress -1 -1 "Compression" \ "File size reduced from $oldsize to $newsize" info 0 Close } else { dialog .compress -1 -1 "Compression" \ "No reduction in File size" info 0 Close } } file_reload file_stats } proc file_save {} { global ProgData if {$ProgData(file,name) == "" || ![file_select Save $ProgData(file,name) $ProgData(file,type)]} return set fname $ProgData(newfile) if {[same_file $fname $ProgData(file)]} { errormsg "current file and save file are the same" return } if {[file exists $fname] && [catch {file delete $fname} msg]} { errormsg $msg return } if {$ProgData(format) == $ProgData(file,type)} { if [catch {file copy $ProgData(file) $fname} msg] { errormsg $msg return } } else { if [catch {CGIOsave $fname $ProgData(format)} msg] { errormsg $msg return } } catch {file attributes $fname -readonly 0} file_load $fname } proc file_info {{loc .}} { global ProgData tcl_platform if {$ProgData(file,name) == ""} return file_stats if {[winfo exists .info]} { wm deiconify .info raise .info return } toplevel .info wm title .info "File Information" wm resizable .info 0 0 set wl 10 frame .info.main pack .info.main -side top -padx 5 -pady 5 set base [frame .info.main.base -relief groove -bd 2] pack $base -side top -padx 5 -pady 5 foreach i {\ {name Name:} \ {dir Location:} \ {size Size:} \ {sep1 {}} \ {type Type:} \ {vers Version:} \ {cgns CGNSlib:} \ {sep2 {}} \ {mode Mode:} \ {mtime Modified:} \ {atime Accessed:}} { set j [lindex $i 0] if {[lindex $i 1] == {}} { set f [frame $base.$j -relief groove -bd 1 -height 2] pack $f -side top -fill x -pady 2 } else { set f [frame $base.$j] pack $f -side top -anchor w -padx 5 label $f.lab -text [lindex $i 1] -width $wl -anchor w label $f.dat -textvariable ProgData(file,$j) pack $f.lab $f.dat -side left } } set f [frame .info.main.but] pack $f -side top button $f.close -text Close -default active -command {destroy .info} button $f.stats -text Update -command file_stats pack $f.close $f.stats -side left -padx 5 bind .info {destroy .info} center_window .info $loc } #----- link selection proc select_lfile {{loc .}} { global ProgData Node tcl_platform set lfile [FileOpen "Link File" $Node(lfile) $loc $ProgData(extensions)] if {$lfile == ""} return if [catch {CGNSfile $lfile} type] { errormsg $type return } if {$type != $ProgData(file,type)} { errormsg "linked to files must be of the same file type" return } if {[same_file $lfile $ProgData(file)]} { set Node(lfile) "" } elseif {[same_file [file dirname $lfile] \ [file dirname $ProgData(file)]]} { set Node(lfile) [file tail $lfile] } elseif {$tcl_platform(platform) == "windows"} { set Node(lfile) [join [split $lfile /] \\] } else { set Node(lfile) $lfile } } proc select_lnode {{loc .}} { global Node ProgData Font if {$Node(lfile) == ""} { set lfile $ProgData(file) } else { set lfile $Node(lfile) } if {![file exists $lfile]} { errormsg "can't browse - link file does not exist" return } set type $ProgData(file,type) if {[catch {cd [file dirname $lfile]} msg] || [catch {CGIOopen [file tail $lfile] read $type} msg]} { errormsg $msg file_reload return } set tree $ProgData(tree) set w .lnode catch {destroy $w} toplevel $w wm title $w "Select Link Node" wm transient $w . wm withdraw $w label $w.file -text [file tail $lfile] pack $w.file -side top -padx 5 -pady 5 set f [frame $w.top] pack $f -side top -fill both -expand 1 -padx 5 set ProgData(tree) $f.tree scrollbar $f.ys -orient vertical -command "$ProgData(tree) yview" pack $f.ys -side right -fill y scrollbar $f.xs -orient horizontal -command "$ProgData(tree) xview" pack $f.xs -side bottom -fill x TreeCreate $ProgData(tree) -width 200 -height 300 -relief sunken \ -bd 2 -yscrollcommand "$f.ys set" -xscrollcommand "$f.xs set" \ -font $Font(normal) -lines $ProgData(showlines) pack $ProgData(tree) -side left -fill both -expand 1 bind $ProgData(tree) <1> { set node [TreeAt %W %x %y] if {$node != ""} { TreeSelectionSet %W $node } } bind $ProgData(tree) {TreeToggle %W [TreeAt %W %x %y]} bind $w {tree_next 0} bind $w {tree_prev 0} bind $w tree_collapse bind $w tree_expand bind $w tree_toggle set f [frame $w.but] pack $f -side top -fill x -padx 5 -pady 5 button $f.accept -text Accept -width 6 -default active -command { if {[TreeSelectionGet $ProgData(tree)] != ""} { set Node(done) 1 } } button $f.cancel -text Cancel -width 6 -command {set Node(done) 0} pack $f.accept $f.cancel -side left -expand 1 bind $w "$f.accept invoke" build_tree TreeSee $ProgData(tree) $Node(lnode) TreeSelectionSet $ProgData(tree) $Node(lnode) center_window $w $loc set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable Node(done) if {$Node(done)} { set Node(lnode) [TreeSelectionGet $ProgData(tree)] } set ProgData(tree) $tree destroy $w catch {focus $oldFocus} if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } catch {cd $ProgData(file,dir)} if {$ProgData(readonly)} { set mode read } else { set mode modify } if {[catch {CGIOopen $ProgData(file,name) $mode $type} msg]} { errormsg $msg } } #----- operation buttons proc node_create {} { global ProgData Node set parent [string trim $Node(parent)] set name [string trim $Node(name)] if {$parent == "" || $name == ""} { errormsg "need to specify parent node and node name" return } set node [get_node $parent $name] if {[CGIOnode $node] != ""} { errormsg "node \"$node\" already exists" return } do_backup foreach i {label lfile lnode type dim} { set $i [string trim $Node($i)] } if {$lnode == ""} { if {[catch {CGIOcreate $node} msg]} { errormsg msg } } else { if {[catch {CGIOlink $node $lnode $lfile} msg]} { errormsg $msg } } if {$label != "" && [catch {CGIOlabel $node $label} msg]} { errormsg $msg } if {$lnode == "" && [string match {?[148]} $type]} { set data [string trim [$ProgData(text) get 1.0 end]] if {$data != ""} { if {$dim == ""} { if {$type == "C1"} { set dim [string length $data] } else { set dim [llength $data] } } if {$type == "C1" && [llength $dim] > 1} { set data [split $data "\n"] } if {[catch {CGIOwrite $node $type $dim $data} msg]} { errormsg $msg } } } file_reload if {[CGIOnode $node] != ""} { TreeSee $ProgData(tree) $node TreeSelectionSet $ProgData(tree) $node update_node $node } } proc node_modify {} { global ProgData Node NodeSave if {$NodeSave(node) == "" || $NodeSave(node) == "/" || [CGIOnode $NodeSave(node)] == ""} return foreach i {parent name label lfile lnode type dim} { set $i [string trim $Node($i)] } if {$parent == "" || $name == ""} return set node [get_node $parent $name] if {$node != $NodeSave(node)} { if {[CGIOnode $node] != ""} { errormsg "node \"$node\" already exists" return } } if {$lfile == ""} { if {$lnode != ""} { if {[recursive_link $node $lnode]} { errormsg "link is recursive" return } } } else { if {$lnode == ""} { errormsg "must specify the link node for a link" return } } if {$lnode != $NodeSave(lnode) || $lfile != $NodeSave(lfile)} { do_backup catch {CGIOdelete $NodeSave(node)} if {$lnode == ""} { if {[catch {CGIOcreate $node} msg]} { errormsg $msg } set NodeSave(label) "" } else { if {[catch {CGIOlink $node $lnode $lfile} msg]} { errormsg $msg } set label $NodeSave(label) } } else { if {$node != $NodeSave(node)} { do_backup if {$parent != $NodeSave(parent)} { if {[catch {CGIOmove $NodeSave(node) $parent} msg]} { errormsg $msg file_reload return } } if {$name != $NodeSave(name)} { set tmpnode [get_node $parent $NodeSave(name)] if {[catch {CGIOname $tmpnode $name} msg]} { errormsg msg } } } } if {$label != $NodeSave(label)} { do_backup if {[catch {CGIOlabel $node $label} msg]} { errormsg $msg } } if {$node != $NodeSave(node)} { TreeMove $ProgData(tree) $NodeSave(node) $node TreeSee $ProgData(tree) $node TreeSelectionSet $ProgData(tree) $node } if {$lnode != ""} { file_reload return } if {$type == "MT"} { if {$NodeSave(type) != "MT"} { do_backup if {[catch {CGIOtype $node MT} msg] || [catch {CGIOdimensions $node {}} msg]} { errormsg $msg } } file_reload return } set data [string trim [$ProgData(text) get 1.0 end]] if {$data == ""} { if {$dim != $NodeSave(dim)} { do_backup if {[catch {CGIOdimensions $node $dim} msg]} { errormsg $msg } } if {$type != $NodeSave(type)} { do_backup if {[catch {CGIOtype $node $type} msg]} { errormsg $msg } } } else { if {$dim == ""} { if {$type == "C1"} { set dim [string length $data] } else { set dim [llength $data] } } if {$type == "C1" && [llength $dim] > 1} { set data [split $data "\n"] } do_backup if {[catch {CGIOwrite $node $type $dim $data} msg]} { errormsg $msg } } file_reload } proc values_perline {} { global ProgData NodeSave if {$NodeSave(name) == "ElementConnectivity" && $NodeSave(label) == "DataArray_t" && ![catch {CGIOlabel $NodeSave(parent)} label] && $label == "Elements_t" && ![catch {CGIOdimensions $NodeSave(parent)} dim] && $dim == 2 && ![catch {CGIOread $NodeSave(parent)} data]} { switch [lindex $data 0] { 2 {return 1} 3 {return 2} 4 - 5 {return 3} 6 - 14 {return 6} 7 - 10 {return 4} 8 - 17 {return 8} 9 {return 9} 11 {return 10} 12 {return 5} 13 {return 14} 15 {return 15} 16 {return 18} 18 {return 20} 19 {return 27} } } set len [lindex $NodeSave(dim) 0] if {$ProgData(maxcnt) && $len > $ProgData(maxcnt)} { return $ProgData(maxcnt) } return $len } proc node_read {{perline 0}} { global ProgData NodeSave set state [$ProgData(text) cget -state] $ProgData(text) configure -state normal $ProgData(text) delete 1.0 end set ProgData(linecnt) "" set node $NodeSave(node) if {$node != "" && [CGIOnode $node] != ""} { . configure -cursor watch update if {[catch {CGIOread $node} data]} { $ProgData(text) insert end $data } else { set dim [llength $NodeSave(dim)] set cnt 1 for {set n 0} {$n < $dim} {incr n} { set cnt [expr $cnt * [lindex $NodeSave(dim) $n]] } if {$NodeSave(type) == "C1"} { if {$dim == 1 && $perline < 1} { $ProgData(text) insert end $data } else { if {$perline > 0} { set len $perline set ProgData(linecnt) $len } else { set len [lindex $NodeSave(dim) 0] } for {set n1 0} {$n1 < $cnt} {incr n1 $len} { set n2 [expr $n1 + $len - 1] $ProgData(text) insert end "[string range $data $n1 $n2]\n" } } } else { if {$perline > 0} { set len $perline } else { set len [values_perline] } for {set n1 0} {$n1 < $cnt} {incr n1 $len} { set n2 [expr $n1 + $len - 1] $ProgData(text) insert end "[lrange $data $n1 $n2]\n" } set ProgData(linecnt) $len } } . configure -cursor {} } $ProgData(text) mark set insert 1.0 $ProgData(text) configure -state $state get_location } proc node_clear {} { global ProgData set state [$ProgData(text) cget -state] if {$state == "normal"} { $ProgData(text) delete 1.0 end } else { $ProgData(text) configure -state normal $ProgData(text) delete 1.0 end $ProgData(text) configure -state $state } set ProgData(linenum) "" set ProgData(lineval) "" set ProgData(linecnt) "" } proc node_delete {} { global ProgData Node set node [get_node [string trim $Node(parent)] \ [string trim $Node(name)]] if {$node != "" && $node != "/"} { delete_node $node } } #---------- utility routines proc full_path {filename} { global tcl_platform set cdir [pwd] if {[catch {cd [file dirname $filename]}]} { return $filename } set pathname "[pwd]/[file tail $filename]" cd $cdir if {$tcl_platform(platform) == "windows"} { return [string tolower $pathname] } return $pathname } proc same_file {file1 file2} { global tcl_platform if {$tcl_platform(platform) == "windows"} { set file1 [join [split $file1 \\] /] set file2 [join [split $file2 \\] /] } set n [expr [file exists $file1] + [file exists $file2]] if {$n == 1} {return 0} if [string compare [full_path $file1] [full_path $file2]] {return 0} return 1 } proc ignore_quit {} {} proc run_command {title cmd {height 10} {width 60}} { global ProgData tcl_platform if {$tcl_platform(platform) == "windows"} { set exe [join [split [lindex $cmd 0] \\] /] set cmd [lreplace $cmd 0 0 $exe] } set w .command catch {destroy $w} toplevel $w wm title $w $title wm transient $w . wm protocol $w WM_DELETE_WINDOW ignore_quit frame $w.f pack $w.f -side top -fill both -padx 5 -pady 5 -expand 1 scrollbar $w.f.s -command "$w.f.t yview" pack $w.f.s -side right -fill y text $w.f.t -width $width -height $height -yscroll "$w.f.s set" pack $w.f.t -side top -fill both -expand 1 $w.f.t tag configure warning -foreground blue $w.f.t tag configure error -foreground red frame $w.b pack $w.b -side bottom button $w.b.close -text Close -command "destroy $w" -state disabled button $w.b.save -text Save -command "save_output $w" -state disabled pack $w.b.close $w.b.save -side left -padx 5 $w.f.t insert end "EXECUTING:\n$cmd\n\n" center_window $w . tkwait visibility $w update if {[catch {open |$cmd r} f]} { destroy $w errormsg $f return 0 } set ProgData(status) 0 fileevent $f readable "run_event $w $f" tkwait window $w return $ProgData(status) } proc run_event {w f} { global ProgData if {![eof $f]} { fconfigure $f -blocking 0 while {[gets $f line] >= 0} { if {[string match {WARNING:*} $line]} { $w.f.t insert end "$line\n" warning } elseif {[string match {ERROR:*} $line]} { $w.f.t insert end "$line\n" error } else { $w.f.t insert end "$line\n" } } fconfigure $f -blocking 1 $w.f.t yview -pickplace end update idletasks return } if {[catch {close $f} msg]} { errormsg $msg $w.f.t insert end "\nERROR:\n$msg" set ProgData(status) 0 } else { $w.f.t insert end "\nFINISHED\n" set ProgData(status) 1 } $w.f.t yview -pickplace end $w.b.close configure -state normal $w.b.save configure -state normal } proc save_output {w} { global ProgData if {$ProgData(file) == ""} { set outfile "output.txt" } else { set outfile [file rootname $ProgData(file)].txt } if {$ProgData(file,name) == ""} return set fname [FileSave "Save Output" $outfile $w \ {{{Text Files} {.txt .out .log}} {{All Files} {*}}} txt] if {$fname == ""} return if {[catch {open $fname w+} f]} { errormsg $f } else { puts $f [$w.f.t get 1.0 end] catch {close $f} } } #---------- initialize and display window catch { config_icon . [list cgnsview cgns] \ [list $cmd_dir $cmd_dir/images $cmd_dir/../common] } update_node "" if {$argc} { set fname [lindex $argv [expr $argc - 1]] if {[file isfile $fname] && [file readable $fname]} { file_load $fname } } CGNS-3.4.0/src/cgnstools/cgnsview/export.tcl000066400000000000000000000201341343724673500207420ustar00rootroot00000000000000# export.tcl - CGNS export routines proc export_default {w name cmd} { global ProgData Font Export tcl_platform if {$cmd != ""} { set exe [lindex $cmd 0] set exepath [get_executable $exe] if {$exepath != ""} {set exe $exepath} if {$tcl_platform(platform) == "windows"} { set Export(exefile) [join [split $exe /] \\] } else { set Export(exefile) $exe } set Export(options) [lrange $cmd 1 end] } set Export(cgnsfile) $ProgData(file,name) toplevel $w wm title $w $name wm transient $w . wm protocol $w WM_DELETE_WINDOW {set Export(done) 0} set labw 12 FrameCreate $w.top -text "Export Command" -font $Font(bold) pack $w.top -side top -padx 5 -pady 5 -fill x set top [FrameGet $w.top] set f [frame $top.exe] pack $f -side top -fill x -expand 1 label $f.lab -text Executable -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export(exefile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "export_browse $w exefile" pack $f.but -side right -fill y $f.ent xview [$f.ent index end] set f [frame $top.opts] pack $f -side top -fill x -expand 1 label $f.lab -text Options -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export(options) -width 30 pack $f.ent -side left -fill x -expand 1 set f [frame $top.input] pack $f -side top -fill x -expand 1 label $f.lab -text "CGNS Input" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export(cgnsfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "export_browse $w cgnsfile" pack $f.but -side right -fill y set f [frame $top.output] pack $f -side top -fill x -expand 1 label $f.lab -text "Output File" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export(outputfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 \ -command "export_browse $w outputfile {$name}" pack $f.but -side right -fill y if {[export_buttons $w export_check]} { set cmd [tools_unix_path $Export(exefile)] foreach opt $Export(options) { lappend cmd $opt } lappend cmd $Export(cgnsfile) $Export(outputfile) run_command $name $cmd } } proc export_input {w {base 0} {zone 0} {sol 0} {labw ""}} { global Export Font if {$labw == ""} { if {$sol} { set labw 12 } else { set labw 10 } } FrameCreate $w.input -text "CGNS Input" -font $Font(bold) pack $w.input -side top -padx 5 -pady 2 -fill x set input [FrameGet $w.input] set f [frame $input.file] pack $f -side top -fill x label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export(cgnsfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "export_browse $w cgnsfile" pack $f.but -side right -fill y if {$base} { set f [frame $input.base] pack $f -side top -anchor w label $f.lab -text "Base Index" -width $labw -anchor w entry $f.ent -textvariable Export(basenum) -width 10 checkbutton $f.but -text default \ -variable Export(basenum,flag) -onvalue 1 -offvalue 0 \ -command "export_state basenum $f.ent" pack $f.lab $f.ent $f.but -side left export_state basenum $f.ent } if {$zone} { set f [frame $input.zone] pack $f -side top -anchor w label $f.lab -text "Zone Index" -width $labw -anchor w entry $f.ent -textvariable Export(zonenum) -width 10 checkbutton $f.but -text default \ -variable Export(zonenum,flag) -onvalue 1 -offvalue 0 \ -command "export_state zonenum $f.ent" pack $f.lab $f.ent $f.but -side left export_state zonenum $f.ent } if {$sol} { set f [frame $input.sol] pack $f -side top -anchor w label $f.lab -text "Solution Index" -width $labw -anchor w entry $f.ent -textvariable Export(solnum) -width 10 checkbutton $f.but -text default \ -variable Export(solnum,flag) -onvalue 1 -offvalue 0 \ -command "export_state solnum $f.ent" pack $f.lab $f.ent $f.but -side left export_state solnum $f.ent } } proc export_output {w ftype name exts {labw 10}} { global Export Font FrameCreate $w.output -text "$name Output" -font $Font(bold) pack $w.output -side top -padx 5 -pady 2 -fill x set f [FrameGet $w.output] label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Export($ftype) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 \ -command "export_browse $w $ftype {$name} {$exts}" pack $f.but -side right -fill y } proc export_options {w {labw ""}} { global Export Font FrameCreate $w.opts -text "Command Line Options" -font $Font(bold) pack $w.opts -side top -padx 5 -pady 2 -fill x set f [FrameGet $w.opts] label $f.lab -text Options pack $f.lab -side left if {$labw != ""} { $f.lab configure -width $labw -anchor w } entry $f.ent -textvariable Export(options) -width 30 pack $f.ent -side left -fill x -expand 1 } proc export_browse {w ftype {name ""} {exts {}}} { global Export tcl_platform if {$ftype == "cgnsfile"} { set fname [FileOpen "CGNS Input File" $Export(cgnsfile) $w \ {{{CGNS Files} {.cgns .cgn .adf}} {{All Files} {*}}}] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Export(cgnsfile) [join [split $fname /] \\] } else { set Export(cgnsfile) $fname } } } elseif {$ftype == "exefile"} { if {$tcl_platform(platform) == "windows"} { set types {{{Executable Files} {.exe .cmd .bat .com}} {{All Files} {*}}} } else { set types {{{All Files} {*}}} } set fname [FileOpen "Export Executable" $Export(exefile) $w $types] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Export(exefile) [join [split $fname /] \\] } else { set Export(exefile) $fname } } } else { if {$name == ""} {set name Output} if {$exts == {}} { set types {{{All Files} {*}}} } else { set types [list [list "$name Files" $exts] [list "All Files" *]] } set fname [FileSave "$name File" $Export($ftype) $w $types] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Export($ftype) [join [split $fname /] \\] } else { set Export($ftype) $fname } } } } proc export_state {what ent {def 1}} { global Export if {$Export($what,flag)} { set Export($what) "" $ent configure -state disabled -cursor {} } else { if {$Export($what) == ""} { set Export($what) $def } $ent configure -state normal -cursor xterm } } proc export_buttons {w {check ""}} { global Export set f [frame $w.but] pack $f -side top -pady 5 button $f.accept -text Accept -width 6 -default active button $f.cancel -text Cancel -width 6 -command {set Export(done) 0} pack $f.accept $f.cancel -side left -padx 5 if {$check == ""} { $f.accept configure -command {set Export(done) 1} } else { $f.accept configure -command "$check $w" bind $w "$check $w" } center_window $w . set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable Export(done) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } return $Export(done) } proc export_check {w} { global Export if {$Export(exefile) == "" || $Export(outputfile) == "" || $Export(cgnsfile) == ""} { errormsg "must specify an executable, CGNS file and an output file" $w return } if {![file exists $Export(exefile)] || ![file executable $Export(exefile)]} { errormsg "the export executable does not exist or is not executable" $w return } if {![file exists $Export(cgnsfile)]} { errormsg "the CGNS input file doesn't exist" $w return } set Export(done) 1 } CGNS-3.4.0/src/cgnstools/cgnsview/import.tcl000066400000000000000000000204361343724673500207400ustar00rootroot00000000000000# import.tcl - CGNS import routines proc import_default {w name cmd} { global ProgData Font Import tcl_platform if {$cmd != ""} { set exe [lindex $cmd 0] set exepath [get_executable $exe] if {$exepath != ""} {set exe $exepath} if {$tcl_platform(platform) == "windows"} { set Import(exefile) [join [split $exe /] \\] } else { set Import(exefile) $exe } set Import(options) [lrange $cmd 1 end] } set Import(cgnsfile) $ProgData(file,name) toplevel $w wm title $w $name wm transient $w . wm protocol $w WM_DELETE_WINDOW {set Import(done) 0} set labw 12 FrameCreate $w.top -text "Import Command" -font $Font(bold) pack $w.top -side top -padx 5 -pady 5 -fill x set top [FrameGet $w.top] set f [frame $top.exe] pack $f -side top -fill x -expand 1 label $f.lab -text Executable -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import(exefile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "import_browse $w exefile" pack $f.but -side right -fill y $f.ent xview [$f.ent index end] set f [frame $top.opts] pack $f -side top -fill x -expand 1 label $f.lab -text Options -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import(options) -width 30 pack $f.ent -side left -fill x -expand 1 set f [frame $top.input] pack $f -side top -fill x -expand 1 label $f.lab -text "Input File" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import(inputfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 \ -command "import_browse $w inputfile {$name}" pack $f.but -side right -fill y set f [frame $top.output] pack $f -side top -fill x -expand 1 label $f.lab -text "CGNS Output" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import(cgnsfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "import_browse $w cgnsfile" pack $f.but -side right -fill y if {[import_buttons $w import_check]} { set cmd [tools_unix_path $Import(exefile)] foreach opt $Import(options) { lappend cmd $opt } lappend cmd $Import(inputfile) $Import(cgnsfile) import_run $name $cmd $Import(cgnsfile) } } proc import_input {w ftype name exts {labw 10}} { global Import Font FrameCreate $w.input -text "$name Input" -font $Font(bold) pack $w.input -side top -padx 5 -pady 2 -fill x set f [FrameGet $w.input] label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import($ftype) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 \ -command "import_browse $w $ftype {$name} {$exts}" pack $f.but -side right -fill y } proc import_output {w {use_base 0} {labw 10}} { global Import Font FrameCreate $w.output -text "CGNS Output" -font $Font(bold) pack $w.output -side top -padx 5 -pady 2 -fill x set output [FrameGet $w.output] set f [frame $output.file] pack $f -side top -fill x label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Import(cgnsfile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "import_browse $w cgnsfile" pack $f.but -side right -fill y if {$use_base} { set f [frame $output.basename] pack $f -side top -anchor w label $f.lab -text "Base Name" -width $labw -anchor w entry $f.ent -textvariable Import(basename) -width 30 checkbutton $f.but -text default \ -variable Import(basename,flag) -onvalue 1 -offvalue 0 \ -command "import_set_state basename $f.ent" pack $f.lab $f.ent $f.but -side left import_set_state basename $f.ent } } proc import_options {w {labw ""}} { global Import Font FrameCreate $w.opts -text "Command Line Options" -font $Font(bold) pack $w.opts -side top -padx 5 -pady 2 -fill x set f [FrameGet $w.opts] label $f.lab -text Options if {$labw != ""} { $f.lab configure -width $labw -anchor w } pack $f.lab -side left entry $f.ent -textvariable Import(options) -width 30 pack $f.ent -side left -fill x -expand 1 } proc import_browse {w ftype {name ""} {exts {}}} { global Import tcl_platform if {$ftype == "cgnsfile"} { set fname [FileSave "CGNS Output File" $Import(cgnsfile) $w \ {{{CGNS Files} {.cgns .cga .cgh .cgx}} {{All Files} {*}}} cgns] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Import(cgnsfile) [join [split $fname /] \\] } else { set Import(cgnsfile) $fname } } } elseif {$ftype == "exefile"} { if {$tcl_platform(platform) == "windows"} { set types {{{Executable Files} {.exe .cmd .bat .com}} {{All Files} {*}}} } else { set types {{{All Files} {*}}} } set fname [FileOpen "Import Executable" $Import(exefile) $w $types] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Import(exefile) [join [split $fname /] \\] } else { set Import(exefile) $fname } } } else { if {$name == ""} {set name Input} if {$exts == {}} { set types {{{All Files} {*}}} } else { set types [list [list "$name Files" $exts] [list "All Files" *]] } set fname [FileOpen "$name File" $Import($ftype) $w $types] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Import($ftype) [join [split $fname /] \\] } else { set Import($ftype) $fname } set Import(cgnsfile) [file rootname $Import($ftype)].cgns } } } proc import_check {w} { global Import if {$Import(exefile) == "" || $Import(inputfile) == "" || $Import(cgnsfile) == ""} { errormsg "must specify an executable, input file and a CGNS file" $w return } if {![file exists $Import(exefile)] || ![file executable $Import(exefile)]} { errormsg "the import executable does not exist or is not executable" $w return } if {![file exists $Import(inputfile)]} { errormsg "the input file doesn't exist" $w return } set Import(done) 1 } proc import_buttons {w {check ""}} { global Import set f [frame $w.but] pack $f -side top -pady 5 button $f.accept -text Accept -width 6 -default active button $f.cancel -text Cancel -width 6 -command {set Import(done) 0} pack $f.accept $f.cancel -side left -padx 5 if {$check == ""} { $f.accept configure -command {set Import(done) 1} } else { $f.accept configure -command "$check $w" bind $w "$check $w" } center_window $w . set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable Import(done) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } return $Import(done) } proc import_run {title cmd {outfile ""}} { global ProgData if {$ProgData(file,name) == ""} { set same 0 } elseif {$outfile == ""} { set same 1 } elseif {[file dirname $outfile] == "."} { set same [same_file $outfile $ProgData(file,name)] } else { set same [same_file $outfile $ProgData(file)] } if {$same} { catch CGIOclose do_backup } update if {[run_command $title $cmd] && !$same} { file_load $outfile } else { file_reload } } proc import_dup_check {f} { global Import checkbutton $f.dup -text "Duplicate Node Checking" \ -variable Import(dupcheck,flag) -onvalue 1 -offvalue 0 pack $f.dup -side top -anchor w frame $f.tol pack $f.tol -side left label $f.tol.lab -text Tolerance entry $f.tol.ent -textvariable Import(duptol) -width 10 pack $f.tol.lab $f.tol.ent -side top frame $f.type pack $f.type -side left radiobutton $f.type.rel -text Relative -variable Import(dupcheck) -value d radiobutton $f.type.abs -text Absolute -variable Import(dupcheck) -value D pack $f.type.rel $f.type.abs -side top -anchor w } proc import_set_state {what ent} { global Import if {$Import($what,flag)} { set Import($what) "" $ent configure -state disabled -cursor {} } else { $ent configure -state normal -cursor xterm } } CGNS-3.4.0/src/cgnstools/cgnsview/tclIndex000066400000000000000000000040561343724673500204170ustar00rootroot00000000000000# Tcl autoload index file, version 2.0 # cgns.tcl set auto_index(cgns_init) "source $dir/cgns.tcl" set auto_index(cgns_data) "source $dir/cgns.tcl" set auto_index(cgns_tree) "source $dir/cgns.tcl" # import.tcl set auto_index(import_default) "source $dir/import.tcl" set auto_index(import_input) "source $dir/import.tcl" set auto_index(import_output) "source $dir/import.tcl" set auto_index(import_options) "source $dir/import.tcl" set auto_index(import_browse) "source $dir/import.tcl" set auto_index(import_check) "source $dir/import.tcl" set auto_index(import_buttons) "source $dir/import.tcl" set auto_index(import_run) "source $dir/import.tcl" set auto_index(import_dup_check) "source $dir/import.tcl" set auto_index(import_set_state) "source $dir/import.tcl" # export.tcl set auto_index(export_default) "source $dir/export.tcl" set auto_index(export_input) "source $dir/export.tcl" set auto_index(export_output) "source $dir/export.tcl" set auto_index(export_options) "source $dir/export.tcl" set auto_index(export_browse) "source $dir/export.tcl" set auto_index(export_buttons) "source $dir/export.tcl" set auto_index(export_state) "source $dir/export.tcl" set auto_index(export_check) "source $dir/export.tcl" # tools.tcl set auto_index(check_cgns) "source $dir/tools.tcl" set auto_index(diff_cgns) "source $dir/tools.tcl" set auto_index(plot_cgns) "source $dir/tools.tcl" set auto_index(calc_cgns) "source $dir/tools.tcl" set auto_index(tools_default) "source $dir/tools.tcl" set auto_index(tools_utility) "source $dir/tools.tcl" set auto_index(tools_convert) "source $dir/tools.tcl" set auto_index(tools_unix_path) "source $dir/tools.tcl" set auto_index(tools_cgnsinput) "source $dir/tools.tcl" set auto_index(tools_cgnsoutput) "source $dir/tools.tcl" set auto_index(tools_averaging) "source $dir/tools.tcl" set auto_index(tools_browse) "source $dir/tools.tcl" set auto_index(tools_state) "source $dir/tools.tcl" set auto_index(tools_check_input) "source $dir/tools.tcl" set auto_index(tools_interact) "source $dir/tools.tcl" set auto_index(tools_run) "source $dir/tools.tcl" CGNS-3.4.0/src/cgnstools/cgnsview/tools.tcl000066400000000000000000000367071343724673500205760ustar00rootroot00000000000000# tools.tcl - CGNS tool routines proc check_cgns {} { global ProgData Tools if {$ProgData(cgnscheck) == "" || $ProgData(file,name) == ""} return set w .cgnscheck toplevel $w wm title $w "Check CGNS File" wm transient $w . wm protocol $w WM_DELETE_WINDOW {set Tools(done) 0} FrameCreate $w.top pack $w.top -side top -padx 5 -pady 5 -fill x set top [FrameGet $w.top] set f [frame $top.opts] pack $f -side top -fill x -expand 1 checkbutton $f.verbose -text "Verbose Output" -variable Tools(verbose) \ -onvalue "-v" -offvalue "" checkbutton $f.errors -text "Show Errors" -variable Tools(errors) \ -onvalue "" -offvalue "-e" pack $f.verbose $f.errors -side left -fill x -expand 1 set f [frame $top.warn] pack $f -side top -fill x -expand 1 label $f.lab -text "Warning Level" pack $f.lab -side left foreach i {0 1 2 3} { radiobutton $f.f$i -text $i -variable Tools(warnings) -value $i pack $f.f$i -side left -fill x -expand 1 } if {[tools_interact $w ""]} { set cmd [tools_unix_path $ProgData(cgnscheck)] foreach i {verbose errors} { if {$Tools($i) != ""} {lappend cmd $Tools($i)} } lappend cmd -w$Tools(warnings) $ProgData(file,name) run_command "Check CGNS" $cmd 25 } } proc diff_cgns {} { global ProgData Tools if {$ProgData(cgnscheck) == "" || $ProgData(file,name) == ""} return set w .cgnsdiff toplevel $w wm title $w "Diff CGNS File" wm transient $w . wm protocol $w WM_DELETE_WINDOW {set Tools(done) 0} FrameCreate $w.top -text "Diff With ..." pack $w.top -side top -padx 5 -pady 5 -fill x set top [FrameGet $w.top] set f [frame $top.input] pack $f -side top -fill x label $f.lab -text "CGNS File" pack $f.lab -side left entry $f.ent -textvariable Tools(cgnsinput) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "tools_browse $f.but cgnsinput" pack $f.but -side right -fill y FrameCreate $w.opts -text "Options" pack $w.opts -side top -padx 5 -pady 5 -fill x set opts [FrameGet $w.opts] set f [frame $opts.f1] pack $f -side top -fill x -expand 1 checkbutton $f.case -text "Case-insensitive" -variable Tools(nocase) \ -onvalue "-c" -offvalue "" checkbutton $f.space -text "Ignore White Space" -variable Tools(whitespace) \ -onvalue "-i" -offvalue "" checkbutton $f.links -text "Follow Links" -variable Tools(followlinks) \ -onvalue "-f" -offvalue "" pack $f.case $f.space $f.links -side left -fill x -expand 1 set f [frame $opts.f2] pack $f -side top -fill x -expand 1 checkbutton $f.data -text "Compare Node Data" -variable Tools(cmpdata) \ -onvalue "-d" -offvalue "" pack $f.data -side left frame $f.tol label $f.tol.lab -text "Compare Tolerance" entry $f.tol.ent -width 10 -textvariable Tools(cmptol) pack $f.tol.lab $f.tol.ent -side left pack $f.tol -side right if {[tools_interact $w ""]} { set cmd [tools_unix_path $ProgData(cgnsdiff)] foreach i {nocase whitespace followlinks cmpdata} { if {$Tools($i) != ""} {lappend cmd $Tools($i)} } lappend cmd $ProgData(file,name) $Tools(cgnsinput) run_command "Diff CGNS" $cmd 25 } } proc plot_cgns {} { global ProgData tcl_platform if {$ProgData(cgnsplot) == "" || $ProgData(file,name) == ""} return set cmd [tools_unix_path $ProgData(cgnsplot)] lappend cmd $ProgData(file,name) if {[catch {eval exec $cmd &} msg]} { errormsg $msg return } } proc calc_cgns {} { global ProgData if {$ProgData(cgnscalc) == "" || $ProgData(file,name) == ""} return set cmd [tools_unix_path $ProgData(cgnscalc)] lappend cmd $ProgData(file,name) if {[catch {eval exec $cmd &} msg]} { errormsg $msg return } } proc tools_default {w name exe} { global ProgData Tools tools_window $w $name $exe run if {[tools_interact $w tools_check_exe]} { set cmd [tools_unix_path $Tools(exefile)] foreach opt $Tools(options) { lappend cmd $opt } if {$Tools(background)} { if {[catch {eval exec $cmd &} msg]} { errormsg $msg } } else { run_command $name $cmd } } } proc tools_utility {w name exe} { global ProgData Tools set Tools(cgnsinput) $ProgData(file,name) tools_window $w $name $exe utility if {[tools_interact $w tools_check]} { set cmd [tools_unix_path $Tools(exefile)] foreach opt $Tools(options) { lappend cmd $opt } lappend cmd $Tools(cgnsinput) if {$Tools(background)} { if {[catch {eval exec $cmd &} msg]} { errormsg $msg } } else { $name $cmd } } } proc tools_convert {w name exe} { global ProgData Tools set Tools(cgnsinput) $ProgData(file,name) if {$Tools(cgnsoutput) == ""} { set Tools(cgnsoutput) $ProgData(file,name) } tools_window $w $name $exe convert if {[tools_interact $w tools_check]} { set cmd [tools_unix_path $Tools(exefile)] foreach opt $Tools(options) { lappend cmd $opt } lappend cmd $Tools(cgnsinput) if {$Tools(cgnsoutput) != ""} { lappend cmd $Tools(cgnsoutput) } tools_run $name $cmd $Tools(cgnsoutput) } } proc tools_window {w name exe type} { global ProgData Tools Font tcl_platform if {$exe != ""} { set exename [lindex $exe 0] set exepath [get_executable $exename] if {$exepath != ""} {set exename $exepath} if {$tcl_platform(platform) == "windows"} { set Tools(exefile) [join [split $exename /] \\] } else { set Tools(exefile) $exename } set Tools(options) [lrange $exe 1 end] } toplevel $w wm title $w $name wm transient $w . wm protocol $w WM_DELETE_WINDOW {set Tools(done) 0} set labw 12 set lab "[string toupper [string index $type 0]][string range $type 1 end]" FrameCreate $w.top -text "$lab Command" -font $Font(bold) pack $w.top -side top -padx 5 -pady 5 -fill x set top [FrameGet $w.top] set f [frame $top.exe] pack $f -side top -fill x -expand 1 label $f.lab -text Executable -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(exefile) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "tools_browse $w exefile" pack $f.but -side right -fill y $f.ent xview [$f.ent index end] set f [frame $top.opts] pack $f -side top -fill x -expand 1 if {$type == "run"} { set lab Arguments } else { set lab Options } label $f.lab -text $lab -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(options) -width 30 pack $f.ent -side left -fill x -expand 1 if {$type != "run"} { set f [frame $top.input] pack $f -side top -fill x label $f.lab -text "CGNS Input" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(cgnsinput) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "tools_browse $f.but cgnsinput" pack $f.but -side right -fill y if {$type == "convert"} { set f [frame $top.output] pack $f -side top -fill x label $f.lab -text "CGNS Output" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(cgnsoutput) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 \ -command "tools_browse $f.but cgnsoutput" pack $f.but -side right -fill y } } if {$type != "convert"} { checkbutton $top.bg -text "Run Command in Background" \ -variable Tools(background) -onvalue 1 -offvalue 0 pack $top.bg -side top -anchor w } } proc tools_check_input {w} { global Tools if {$Tools(cgnsinput) == "" || ![file exists $Tools(cgnsinput)]} { errormsg "CGNS input file not specified or does not exist" $w return 0 } return 1 } proc tools_check_exe {w} { global Tools if {$Tools(exefile) == ""} { errormsg "must specify an executable" $w return 0 } if {![file exists $Tools(exefile)] || ![file executable $Tools(exefile)]} { errormsg "the utility executable does not exist or is not executable" $w return 0 } return 1 } proc tools_check {w} { if {[tools_check_exe $w] && [tools_check_input $w]} {return 1} return 0 } proc tools_unix_path {exepath} { global tcl_platform if {$tcl_platform(platform) == "windows"} { if {![catch {file attributes $exepath -shortname} name]} { return [join [split $name \\] /] } return [join [split $exepath \\] /] } return $exepath } proc tools_cgnsinput {w {loc 0} {labw 13}} { global ProgData Font Tools FrameCreate $w.cgnsinput -text "CGNS Input" -font $Font(bold) pack $w.cgnsinput -side top -padx 5 -pady 2 -fill x set wf [FrameGet $w.cgnsinput] set f [frame $wf.file] pack $f -side top -fill x label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(cgnsinput) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "tools_browse $f.but cgnsinput" pack $f.but -side right -fill y if {!$loc} return set f [frame $wf.basenum] pack $f -side top -fill x label $f.lab -text "Base Index" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(basenum) -width 10 pack $f.ent -side left checkbutton $f.but -text default \ -variable Tools(basenum,flag) -onvalue 1 -offvalue 0 \ -command "tools_state basenum $f.ent" pack $f.but -side left tools_state basenum $f.ent set f [frame $wf.zonenum] pack $f -side top -fill x label $f.lab -text "Zone Index" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(zonenum) -width 10 pack $f.ent -side left checkbutton $f.but -text "all zones" \ -variable Tools(zonenum,flag) -onvalue 1 -offvalue 0 \ -command "tools_state zonenum $f.ent" pack $f.but -side left tools_state zonenum $f.ent if {$loc < 2} return set f [frame $wf.solnum] pack $f -side top -fill x label $f.lab -text "Solution Index" -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(solnum) -width 10 pack $f.ent -side left checkbutton $f.but -text "all solutions" \ -variable Tools(solnum,flag) -onvalue 1 -offvalue 0 \ -command "tools_state solnum $f.ent" pack $f.but -side left tools_state solnum $f.ent } proc tools_cgnsoutput {w {newloc ""} {labw 13}} { global Font Tools FrameCreate $w.cgnsoutput -text "CGNS Output" -font $Font(bold) pack $w.cgnsoutput -side top -padx 5 -pady 2 -fill x set wf [FrameGet $w.cgnsoutput] set f [frame $wf.file] pack $f -side top -fill x label $f.lab -text Filename -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools(cgnsoutput) -width 30 pack $f.ent -side left -fill x -expand 1 button $f.but -text Browse -pady 0 -command "tools_browse $f.but cgnsoutput" pack $f.but -side right -fill y if {$newloc == "solname"} { set lab "Solution Name" } elseif {$newloc == "basename"} { set lab "Base Name" } else { return } set f [frame $wf.newloc] pack $f -side top -fill x label $f.lab -text $lab -width $labw -anchor w pack $f.lab -side left entry $f.ent -textvariable Tools($newloc) -width 30 pack $f.ent -side left -fill x -expand 1 checkbutton $f.but -text default \ -variable Tools($newloc,flag) -onvalue 1 -offvalue 0 \ -command "tools_state $newloc $f.ent {}" pack $f.but -side left tools_state $newloc $f.ent "" } proc tools_averaging {w} { global Font Tools FrameCreate $w.avg -text Averaging -font $Font(bold) pack $w.avg -side top -padx 5 -pady 2 -fill x set avg [FrameGet $w.avg] set f [frame $avg.f] pack $f -side top -fill x -expand 1 radiobutton $f.a -text "Simple Averaging" \ -variable Tools(weight) -value "" radiobutton $f.w -text "Volume Weighting" \ -variable Tools(weight) -value w pack $f.a $f.w -side left -expand 1 return $avg } proc tools_options {w {bgopt 0} {labw ""}} { global Tools Font FrameCreate $w.opts -text "Command Line Options" -font $Font(bold) pack $w.opts -side top -padx 5 -pady 2 -fill x set opts [FrameGet $w.opts] set f [frame $opts.f] pack $f -side top -fill x -expand 1 label $f.lab -text Options if {$labw != ""} { $f.lab configure -width $labw -anchor w } pack $f.lab -side left entry $f.ent -textvariable Tools(options) -width 30 pack $f.ent -side left -fill x -expand 1 if {$bgopt} { checkbutton $opts.bg -text "Run Command in Background" \ -variable Tools(background) -onvalue 1 -offvalue 0 pack $opts.bg -side top -anchor w } return $opts } proc tools_browse {w ftype {name ""}} { global Tools tcl_platform if {$ftype == "exefile"} { if {$tcl_platform(platform) == "windows"} { set types {{{Executable Files} {.exe .cmd .bat .com}} {{All Files} {*}}} } else { set types {{{All Files} {*}}} } set fname [FileOpen Executable $Tools(exefile) $w $types] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Tools(exefile) [join [split $fname /] \\] } else { set Tools(exefile) $fname } } } elseif {$ftype == "cgnsoutput"} { set fname [FileSave "CGNS Output File" $Tools(cgnsoutput) . \ {{{CGNS Files} {.cgns .cgn}} {{All Files} {*}}} cgns] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Tools(cgnsoutput) [join [split $fname /] \\] } else { set Tools(cgnsoutput) $fname } } } else { if {$name == ""} {set name Input} set fname [FileOpen "CGNS $name File" $Tools($ftype) . \ {{{CGNS Files} {.cgns .cga .cgh .cgx}} {{All Files} {*}}}] if {$fname != ""} { if {$tcl_platform(platform) == "windows"} { set Tools($ftype) [join [split $fname /] \\] } else { set Tools($ftype) $fname } } } } proc tools_state {what ent {def 1}} { global Tools if {$Tools($what,flag)} { set Tools($what) "" $ent configure -state disabled -cursor {} } else { if {$Tools($what) == ""} { set Tools($what) $def } $ent configure -state normal -cursor xterm } } proc tools_interact {w {check_proc tools_check_input}} { global Tools set f [frame $w.but] pack $f -side bottom -pady 5 button $f.accept -text Accept -width 6 -default active button $f.cancel -text Cancel -width 6 -command {set Tools(done) 0} pack $f.accept $f.cancel -side left -padx 5 if {$check_proc == ""} { $f.accept configure -command {set Tools(done) 1} bind $w {set Tools(done) 1} } else { $f.accept configure -command " if {!\[catch {$check_proc $w} result\] && \$result} { set Tools(done) 1 } " bind $w " if {!\[catch {$check_proc $w} result\] && \$result} { set Tools(done) 1 } " } center_window $w . set oldFocus [focus] set oldGrab [grab current $w] if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] } catch {grab $w} tkwait visibility $w focus $w tkwait variable Tools(done) catch {focus $oldFocus} destroy $w if {$oldGrab != ""} { if {$grabStatus == "global"} { grab -global $oldGrab } else { grab $oldGrab } } return $Tools(done) } proc tools_run {title cmd {outfile ""}} { global ProgData if {$outfile == ""} { set same 1 } elseif {[file dirname $outfile] == "."} { set same [same_file $outfile $ProgData(file,name)] } else { set same [same_file $outfile $ProgData(file)] } if {$same} { catch CGIOclose do_backup } update if {[run_command $title $cmd] && !$same} { file_load $outfile } else { file_reload } } CGNS-3.4.0/src/cgnstools/cgnsview/winmain.c000066400000000000000000000203611343724673500205250ustar00rootroot00000000000000/* * winMain.c -- * * Main entry point for wish and other Tk-based applications. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ #include #include "tkWinInt.h" #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN #include #include extern int CGIOtcl_Init _ANSI_ARGS_((Tcl_Interp *interp)); #ifdef USE_HTMLHELP extern int WinHtml_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* * Forward declarations for procedures defined later in this file: */ static void setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr)); static void WishPanic _ANSI_ARGS_(TCL_VARARGS(char *,format)); static int Proc_LoadIcon _ANSI_ARGS_((ClientData data, Tcl_Interp *interp, int argc, char **argv)); static HINSTANCE myInstance; /* *---------------------------------------------------------------------- * * WinMain -- * * Main entry point from Windows. * * Results: * Returns false if initialization fails, otherwise it never * returns. * * Side effects: * Just about anything, since from here we call arbitrary Tcl code. * *---------------------------------------------------------------------- */ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { char **argv; int argc; char buffer[MAX_PATH+1]; char *p; Tcl_SetPanicProc((Tcl_PanicProc *)WishPanic); /* * Increase the application queue size from default value of 8. * At the default value, cross application SendMessage of WM_KILLFOCUS * will fail because the handler will not be able to do a PostMessage! * This is only needed for Windows 3.x, since NT dynamically expands * the queue. */ SetMessageQueue(64); /* * Set up the default locale to be standard "C" locale so parsing * is performed correctly. */ setlocale(LC_ALL, "C"); setargv(&argc, &argv); /* * Replace argv[0] with full pathname of executable, and forward * slashes substituted for backslashes. */ GetModuleFileName(NULL, buffer, sizeof(buffer)); argv[0] = buffer; for (p = buffer; *p != '\0'; p++) { if (*p == '\\') { *p = '/'; } } myInstance = hInstance; Tk_Main(argc, argv, Tcl_AppInit); return 1; } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(Tcl_Interp *interp) { if (Tcl_Init(interp) == TCL_ERROR) { goto error; } if (Tk_Init(interp) == TCL_ERROR) { goto error; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); if (CGIOtcl_Init(interp) == TCL_ERROR) goto error; #ifdef USE_HTMLHELP if (WinHtml_Init(interp) == TCL_ERROR) goto error; #endif Tcl_CreateCommand (interp, "LoadIcon", (Tcl_CmdProc *)Proc_LoadIcon, (ClientData)0, (Tcl_CmdDeleteProc *)0); Tcl_SetVar(interp, "tcl_rcFileName", "~/wishrc.tcl", TCL_GLOBAL_ONLY); return TCL_OK; error: MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); ExitProcess(1); /* we won't reach this, but we need the return */ return TCL_ERROR; } /* *---------------------------------------------------------------------- * * WishPanic -- * * Display a message and exit. * * Results: * None. * * Side effects: * Exits the program. * *---------------------------------------------------------------------- */ void WishPanic TCL_VARARGS_DEF(char *,arg1) { va_list argList; char buf[1024]; char *format; format = TCL_VARARGS_START(char *,arg1,argList); vsprintf(buf, format, argList); MessageBeep(MB_ICONEXCLAMATION); MessageBox(NULL, buf, "Fatal Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); #ifdef _MSC_VER DebugBreak(); #endif ExitProcess(1); } /* *------------------------------------------------------------------------- * * setargv -- * * Parse the Windows command line string into argc/argv. Done here * because we don't trust the builtin argument parser in crt0. * Windows applications are responsible for breaking their command * line into arguments. * * 2N backslashes + quote -> N backslashes + begin quoted string * 2N + 1 backslashes + quote -> literal * N backslashes + non-quote -> literal * quote + quote in a quoted string -> single quote * quote + quote not in quoted string -> empty string * quote -> begin quoted string * * Results: * Fills argcPtr with the number of arguments and argvPtr with the * array of arguments. * * Side effects: * Memory allocated. * *-------------------------------------------------------------------------- */ static void setargv(int *argcPtr, char ***argvPtr) { char *cmdLine, *p, *arg, *argSpace; char **argv; int argc, size, inquote, copy, slashes; cmdLine = GetCommandLine(); /* INTL: BUG */ /* * Precompute an overly pessimistic guess at the number of arguments * in the command line by counting non-space spans. */ size = 2; for (p = cmdLine; *p != '\0'; p++) { if ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ size++; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } } } argSpace = (char *) Tcl_Alloc( (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1)); argv = (char **) argSpace; argSpace += size * sizeof(char *); size--; p = cmdLine; for (argc = 0; argc < size; argc++) { argv[argc] = arg = argSpace; while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */ p++; } if (*p == '\0') { break; } inquote = 0; slashes = 0; while (1) { copy = 1; while (*p == '\\') { slashes++; p++; } if (*p == '"') { if ((slashes & 1) == 0) { copy = 0; if ((inquote) && (p[1] == '"')) { p++; copy = 1; } else { inquote = !inquote; } } slashes >>= 1; } while (slashes) { *arg = '\\'; arg++; slashes--; } if ((*p == '\0') || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */ break; } if (copy != 0) { *arg = *p; arg++; } p++; } *arg = '\0'; argSpace = arg + 1; } argv[argc] = NULL; *argcPtr = argc; *argvPtr = argv; } /*---------------------------------------------------------------------- * set the toplevel window icon *----------------------------------------------------------------------*/ typedef struct TkWmInfo { TkWindow *winPtr; HWND hwnd; } WmInfo; static int Proc_LoadIcon(ClientData data, Tcl_Interp *interp, int argc, char **argv) { TkWindow *winPtr; HANDLE hIcon; HWND hwnd = NULL; if (2 != argc) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " iconname\"", (char *) NULL); return TCL_ERROR; } winPtr = (TkWindow *) Tk_MainWindow (interp); if (NULL != winPtr && NULL != winPtr->wmInfoPtr) hwnd = winPtr->wmInfoPtr->hwnd; if (!hwnd) { Tcl_SetResult (interp, "toplevel window has not been created/mapped", TCL_STATIC); return TCL_ERROR; } if (argv[1][0] == '@') hIcon = LoadImage (NULL, &argv[1][1], IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); else hIcon = (HANDLE) LoadIcon (myInstance, argv[1]); if (!hIcon) { Tcl_SetResult (interp, "icon not found", TCL_STATIC); return TCL_ERROR; } SetClassLongPtr (hwnd, GCLP_HICON, (LONG_PTR)hIcon); Tcl_ResetResult (interp); return TCL_OK; } CGNS-3.4.0/src/cgnstools/common/000077500000000000000000000000001343724673500163605ustar00rootroot00000000000000CGNS-3.4.0/src/cgnstools/common/CMakeLists.txt000066400000000000000000000011751343724673500211240ustar00rootroot00000000000000########## # common # ########## if (WIN32) install(FILES balloon.tcl color.tcl combobox.tcl config.tcl dialog.tcl editfile.tcl filesel.tcl findfile.tcl frame.tcl help.tcl menubar.tcl tclIndex tclreg.tcl tkdir.tcl tree.tcl units.tcl cgns.ico cgns.png cgns-icon.xbm cgns-mask.xbm DESTINATION share) else (WIN32) install(FILES balloon.tcl color.tcl combobox.tcl config.tcl dialog.tcl editfile.tcl filesel.tcl findfile.tcl frame.tcl help.tcl menubar.tcl tclIndex tclreg.tcl tkdir.tcl tree.tcl units.tcl cgns.ico cgns.png cgns-icon.xbm cgns-mask.xbm DESTINATION share/cgnstools) endif (WIN32) CGNS-3.4.0/src/cgnstools/common/balloon.tcl000066400000000000000000000055741343724673500205250ustar00rootroot00000000000000 array set Balloon { set 0 first 0 id "" } proc set_balloon {target message} { global Balloon set tags [bindtags $target] set n [lsearch $tags Balloon] if {$message == ""} { if {$n >= 0} { bindtags $target [lreplace $tags $n $n] } } else { if {$n < 0} { bindtags $target "Balloon $tags" } } set Balloon($target) $message } proc end_balloon {target} { set_balloon $target "" } bind Balloon { set Balloon(set) 0 set Balloon(first) 1 set Balloon(id) [after 500 {Balloon:show %W $Balloon(%W) %X %Y}] } bind Balloon

> stream xڥMo0 T֪%JU+{k.Vi} h4ɥB`3g}Ĕ$żkY˂cGjgXف&]7l?R$44V8jh*\Nʊ<5&?Po\#iƕbpILThEU=E+Ɖ@X57֐+a(0Zo>tP@vECXkt#Rպ%9"]V{)K$'Y1ίBxo 7g0yS S1 !ًhD endstream endobj 136 0 obj << /Type /XObject /Subtype /Image /Width 1370 /Height 850 /BitsPerComponent 8 /ColorSpace /DeviceRGB /SMask 157 0 R /Length 95287 /Filter /FlateDecode >> stream x TUGQP#A%q$k꘴mhFM$F4دH@8@h1 *NQL* "ayȫX}O &V-߮]?~jRRR;w'ϤI:uԮ]'޾}ny);Ufu떝/|ΝW_}GiiiM =j_ggg܎;64 5 99Yg̘i5kQJJ<\Ԁu ݻ5+VE ;v_rE/<\GGGa133S{>45VKJJ4P{eeQ <\kkka4 <\Ԁݻ {^^177WK~MM8Ɖ'E Xd9rD&ׯWpa??411IMMUGeC8_Oj`„ ]t\I5yj@ sLi2M4&dZMW_}E,g ),,<~Tć" iiivvvʭ[<==azzzmD̟X4&jLi2ɨmtzƉwޝ8qΝ;ú4dLi5M4Vd6M-M4&jLi2ɨm@i24VdLi5MF @ `ldHi24VdLi5MF @ `ldHi24VdLi5MF @ `lDLi5Mɴ&dLi2jjM6`dZMi24&jВv 4&jLi5M4Vd68PQQ;$D -Q@p"drs sZT+@ I555$'jjjHB8Q PPPI555$q"jjj$DI@ 8PPP@p"$D@ @ @ I555$'jjjHB}@䈤8555@p"jjj$D @ 8PPP@p"$D@ @ @ I555$'jjjHN ʼnZ'DH:@ PPP$'HN@ @ I555$'jjjHN @ 8PPP@p"$D@ @ @ I87oݿ ײwY^u*??_]]\\!gϞ>}z>}y3fݻw88_jժ6po$4O.\ѣp٨Q222E+++^}Ua1bb?3qj޼y5E BzjBQQɓz뭈.Zu֍;u+PD* Pfhr)a+++Nuڵk^RR2j(KKˣGMLLlWjjjHDhiF8QN: {dd%K,y#G|72>}qgCR rx7Ee>|{yyiٝ|3o6554hlGn jA555$'(9"jsפdxgε<a;::J?ˣ(GGG?`ffikaX#g|*7 2335rڿR5yk0ׇp9sΝ;ˆAf̘ `Ƭwkk\D <())i۶qxx{yyyhha^ rXYY)n*[l&n-.yUN&i|I_MZjaa!)))Wt証`.Nҁk^Cu>۳ܽG<@ 8 o8p…vAԀVZiZ "+F// &ĉU_uu***fϞ-?;Vd^`f+Wwykl¶m Ƚ 474Hk=00Pdn׮A"keVH<@ 8pi9sF~Ai?|pe_ Hs^Ν;e677wfee𶺷$?s~,--:T՟ "Uv kmjjzeyk5k^PZ"YnoԨȷE*iCdgg+}5A^5<|XԢRvvjjHNR\\ܦMmjB."xn3))I~ i׌E.,[nMNN:u4.\Pk7Xጌ?"*̚ͺ*u+ڵ@ @ @ @ "G$@ @ @ @ I5555@p"$Dhl޼YkUa?s???SRX 2s||ljjjjHDhɔ_pGbH5*##CX2--W_#F(vy*;;>͛^]D i"55UTYY٭[Ə m۲*$N@! @ɩS駟:׵kFy~~?))I9?'jjjjHDhiiF k+**:u$쑑Z,Y~9PYxnvjPPPP@p"To!FÇv///-SpppodA"@ @ @ @ IP%Gg4>xViOKKkݺuQQQӻwoԀ"@ @ @ @ IP%eee۷ڵkq۶msqttz `Z%$&&.] ,;vBF]_rkkkqq\Ue2;&$$,Y蜵k׊VVV/rzzzaa8իW/KK?Oꋍ_xq߾}EGmذA2a„\]TZZӻwo Ã5555$'c2m410[hh]ZnZCv;;;0|={ OJJ3f/\P5 //ӳƛ꿣%>|8}tq?="""33sԩ"N}&&&Yfȸ~̙k;o=n8yGKG>|JE̚)ST[[[Qyyy~5@.ݦL?NkFoooeGww'n/9555$'BsD,vZۼyϝ;Wy@|UWjZv*uUΝ;5wԺ)u(Ve;vR؝Ϟ=XD['555$'Bs$88X ͽcjjtHNKIII۶m ;t Mhh]m*C]¸elcmE>W7nIj1/jjjjHN_c .Դ˗=<< jJ2d9\1zyyM01Հ^{ʜjX,VEvکiuslb$Dh`8 #3gh<(}ˣ񍌌4'ܹSfsss{nVV{+AvVeܱj"l977Ww`njjjjHNiӦm۶Z F0>>^III7nHf8xbaٺukrrԩSq…ZoܸQOU322-[&s;wP %%%;}\1..NLHHPJ+WH111Z׶Xqmu*HnS( .]*-Z#uPPPP$'ĉuSLQrP)hѣ[j%[ C ٽ{wX z玺*H5kְa,,,zSZvS5555@p"4{@ 8PPP@OPPPPIPPPP@'jjjj$D@ @ @ @ @ 8͛7k- ײwY^u*??_]]\\cH*#:_jժ֪:uNHH`jjjHN… =z5jTFF{eeeZZګ*#FPTvvg}&N͛7/=ME "7x}hZn]TTT{5@ l ؒ)++k߾km̙A@@JHLL\ti,X`cc3vXi(9G...qi2NMMմV@ͽt---]|y~,,, a5⬓<,**[YYum̙6T{5^@ 8dڴi-44[}>a„[n-S:Tt*իW3,,LIIIcƌq VQyyy*+Pt/qww+W[ĈD HOOgE%K/$EܻwOe Ts$DE,sò]_tI%rj]%ԈM{aaaj%**$$$Dl"NWk뢧juɉ'Ipذaeȝ {=5W5 ?@ @ @ @ MkNƍz衼DpÇ {+**j š5-SL2Uꟊ^ZLt͛*{OUz~MLq+?2p߀Q|?ŀ jjjjHN 8p…vAԀVZiZ "+F// &V Py*/ٶmaՀUVSӧOW,r k" jjjjHNrH9sF~Ai?|pԀJұcG##2ŲsNݻYYY"IAA*??x\{iEBU333ZTn70b nii)2**wd=5Wsc͛^]D ݖ߾}w{ffbccDFEE}Æ 3226mZAA5%'oDݚ{{(Æġ" D>>w^G3U^S{G$DhY:uJ؟~JSqqq]vmRذaE~K5@֭[y晜'jh_jf lrO>>X1K% Oz ҞK7F^S/ꓗ/;Li<)SD ^zLSxjG";7^g\J~A1jHNzM6¹"״WTTtI###.Ydo879ra[1t5kֈ)3Tb qͭ{55PDM/ygm[ cco= u(}J.5}R$4E71}ewrr 킂 ;x\ҷo_aРAYeee{g/\Ј TtJ @ו{p.%gg I )(fKS~{zWǍ~;O'f# 9rp>i|GӞֺu뢢+''GćO>D+4k5@ l^@ @ C>ևQ"otY[ũ*z IU4SPME{ t"R Rn87CΝ;snn855U7JVi/**0`YnfΜ졠 e<ϟgT׫5^`tJ1 @;/y7z)/xYԝ*_16m𯿿bqss _O0! @֭[8TCv놽U«WٳgXXWƌciifѣY+Y^Faɹw8\x,իO=L?pSl}@@ 8|Y瞓eee]v-..tK%%%666"Ժ<++KFv&WxYebbXRRRD1cX'~add[nk VWÆ |K"77WkU{i@*kRe 55@}v}̆L>_7pğ u;ԀRâ'ii*m׮p۷ӧǍ'OCyѣÇVTTCkZL򻪰_l[[ۇj,=x`m+kfaaisΝ;ǎ[kddd:uRY*{UU:s_ KGf@5Vq^"tiё; ]V|~6o,sU^"}}}kVjZv*U"*j+9lذA Z6n(,ӟ;wzfCwgu=5U5W5 Yy>?.<}ФԀ?I`ƃ~vR~jL}i .{;::* ::333M*1bĩS999VVV̻w>p9sΝ;˺يri@YFV_^UsUksXãMA Oqǹxo}TٸrZj@mm@NnSN#NIII۶m ;t kjFRTl٢ 88XOz)."<ХKGGǛ7oɶj*a_":Jԧ jTTT }zj۫*_"M6 ԘҤϏߩ(><;4`(L;@p"48 3gh<(;عLܹSfsss{nVVm{+G+kNO{{{QݻXZZ oN=pu/y]`$P*O\>N5Pʩ_^P@p"ЦMmjnccceeUTTT2LJJҴ߸qC5ŋ ֭[N* .Zpƍ_%|W"͐>`9= 66VjU:ȑ#q֬Yyyy)))^^^r}WjoggoUl2yǨܘ?׿UXۚ7/_RJOԫp"TlV=R1?nj j@q m@{a½, ww'ڧL9XP^PP0zVZ3F=00A؇ ?}Mݻ诏ŋ@Ҳ"f;wMtMץK{N쑑n֪ >FM[ԇp*:E*Wm^DŽj j@}9MP懈’xSN#|),,ܹ۷IWj@i跶0{oLg5cn}%j*v+Hl4X T]>U4I͗5koTc}:PԤ֌4{o+"U:{0aQ7Tco~i)qqq:tr ]PjЏȹo:gm_KDm_{2ԀƚcTl |ޣCPI x#Ԃ^p+`}Ħ$5Szu~rP3ā;E%@ uTTT!O}}BDd濉f|e|v9TPȮoM{r9zݷḒ< ĉ #?9ux)5)k]uS F 87|G{82+u){ t55S̏l_UkUN# M]zѣGG PׯZj*={v}~gf̘w˗7ଲ... 3dߞpl N# ̃|||\^^6~xa0`8: ԘhoVDDD^^Çccc-ZԺuk4d+F0@ 1:U߿^~f"8,Nm>2ɹ2G @ hízٷS:U4IWGO2E=<<jQFYZZ=zTlbbb׮]qplhŎ4_0ZC˜r%(B 0T$'BcT׭W\F;;ƪy2>}qgC#Gdj@"#o9tqІd wWaN]jj@s*ԪM;@p"40H͛B}mSSA/g-A  1hjNmIޫ8q]} kOv?5@p"40O׬Y...666ƍSN0̬[n3gJ/_ޯ_? 3""8YdpBڵgϞ#Gzn_ܷo_m$&&.] ,;vVkE:::*ŋWaKK &QFi/>>>{}=<24ǩ6ҝ*pbTLnF 8K (++[~FE \YYy={ !jRRҘ1cDH/(*888''޽{P% ʕ+bbb\]]kTlmmEY}MEvëW G([]4JTuС*[agge111Yf.Q}r}r a4ibQ37Td(++S٢'OVR,"~ꩧQ#f p,uqXԀ'`ߦ n]<T|u 5@p"4 ?Ϟ=[|2dHIInN.z P'O,,aaaE.W\mVdS٢qƉ7o4FeG:um@f8dQPTTTz$ƃ&`~ǑIE <|駟^^^9v*NXfvv GZ 8PdHHHP٢:ZƥKQRlE,;P^bjjZ+;vRqvv>{l CWYDhj@d g;~"-A iQXxLFu#ch. j$Dh,5@p)###cccA+|ڵkzJ9slmmΝ{eaqqq9c?W"fAffQN733SlE,;P^YC~4h,mƌ_0 _}i붯y Y^#Xmw*l#jjQ؞5I׺G[@p"4 ^z }Ȑ!T^ׄ gvZmV+5@0qD믫'rEEٳcNJ ,pa>OuuSي:Xj@iiժUk)@]vjƆu/̶P=wp ^:-%O_aĤcdZr*N)>tۭ%>w _^~֮oi/PbɅ j-\qF咑#G ˬYRRR􄄄Whxxxb͛'5OQ?"US9Zj5dȐݻwk(MWWWKKΝ;~ӦM2OVV֛oپ}{kkk`_~"sbb:|x\PPP$i?;},W|=( !ڌt=ca}r$QZr?W_ڷo۱cGwww"??8ea Q&x$ДՀ3?\u룹"u\sgMlv:jjj@  (g軓)|Oh,3f4Κ5(%%'B+W] buVM#G2Op*o^gĹT@ @ @ PCxjƃr d@ hju}ݚ +p",**FsssԀ&((Z#+_}\>91Rdfr(XqjGJ`{ 5XL0vXar劦1>>^):SSSo߾JNNN޽yNԭ%dZ|"e|וEAL?/B zfިo?o?y7PԀ8:: 4(:}k֬kkkq)|}} `eeeff֭[3gk^^ZZ|~YXXHƜzdɒ?eeek׮D_~BqW^ӟ222x}oذA2a„\%ϨQtE]#sE?24Gk"-QZ`kk+%%%Fq("TPO#PDׯclҥ:_«WٳgXX񓒒ƌ#" .ȳ/(*888''޽{PDĚ% ʕ+bbb\]]G Ȼϩڢwy>>}8,j9uTa6mbMLLdf }"3gyeѢE7n^e@3Uc܀뿓{Hʽoo?y:jjj@H+;ȯM|w)j@Td(Ca455ʼn`… u .2$$D" Æ ӧrVXN8!,&MR,Pz%/$&&Jˏ?(-wݻwW_CYҙnݺuӪcǎ¨̩ɱa#'?:jjj@֘-zٷ"+$kkka4 -Ng 5)E"EU=[XX('O0"+|~5@M.ݦLkY:[^^.MLLjeFoooE վ'=ʃB0w|X^׷yM&>+_>"jjjsak{/ះĥg5Eݻwvhuي#ÇO?8ٵkWq27l0x`-WKOOW|Rܹ_ PSmK***jrPbh9v옥;;;={qGFaɀQgixG|ӨjcuA{w?b B͛75P'NFSk׮rߟ3gܹs/_U8,..6PcN5VSfffZ4Hf1cFYYYJ2jRPHG;-[Ojjjj@(*+_r*zDPZda?r䈦1,,Lׯ_FY;يXطl٢ 88X~NHHҥbinaa!SRRL PS:-Vooo9xzzin߼){E Zao ӡ#ӷo㷣dB @ @ @ -qY?!}"~dzck[O˴H4jjjj@m˾0Vف QbT"ҥ"PHAAZ￟8qH+r߹svݬ,FGG mwaLfq /()fffꩧ~Zڵo[Tծ`b;v(Z]eV\*Dk`nj@b <ڻb9H+CZZ+r-kxzzCp"ԙj*o {6m %8]pfqF咑#G ˬYRRRDWhxxx-7o,Gk=MDŖ-[&;wN<8RLݻw077_v0ɜJ -CHK||h|PY:`²uVqSv̘1Ⱐ`ҥpѢE2BX75ƴhǙ^--͆`@v_q=%+1-YPIBݾ8jџ߼)$PߔUTH~aU{e#cIPxr׏}]d݊B @ @ @ hn_oW_:-ى5n[ѸwO.)&h@Ԁcovp߹>"-t5@:z4nю3V:=+v{bQPPP׃Ws@h|F}$q"d}쩧=zG}T\\~}ժUU=S&]\\=>>5477ԩwBB 5`ю3W<ۭ-5Hɨk?X$|/<]\V I-XXF噙aaaǏkh$'ݿ_ݹsgĉ#FpvvVmxw55/ƊeggGEE}Æ 3226mZAACvϬ'u˾}7dHhG @ @ @ h,rK\[軓)"ĉϯ2ԝ2e0zxxon׎ƍuz5` njll30 C}'u~;o9~Hиf5\b8V9! X]?>d틣B^NiyŊW[='{@'B TaYYY޽ .[PPO(j@/)W'P|qR5555p=3[ Q~\^$ĉвԀTa۷/jj(TY) 0DP2q⨅GeOo9ptKmD]s%;HDh1j\o͚58bmmmcc3nܸ8TQQ̺u6s|KKK/_ޯ_? 3""α,DQmGGGXPϋNNN*jԨQ&a@ [:3}q~|"M¿:#_r4A.$HP7_^K.ԑAW^ݳgϰ0&%%3RK/srrݻ)/^Y0\2///&&յn\Xt_*CxCPtͥnjԀڦ#G <D&hX@ @ @ @ hLю*~;+) r$rDҁ'^paFFnΨ(Œ"[6O>Yb9qℰL4I?z ,5VX7~VwTs)JhlliQsOG-qRxz5 M좒!?{EaÚ9k5$IΈ( 3H9眃$ A *5sg$|Μ~JeI`Z]3HAM'- wuuĦ$ŋ)|…LLL(%22 W8$䡤$a IԄ֮Z¶RΝ՝l5%0ꍑ}K@Z4h{v-OSsq ^ 4h$W|~s#j{W8_AM'ѱuVVBB<ѪO>}۷ c566RnV]]=< ZCb梵G=='{ϥ%{=#~S F)t}1LU!:84b4h_{zbrEG#%F0 8)GbbbfϞ=g@sܹ(gII0}VXXxŊ"""^")|/_k OX Ziii +p޼y#jTS)cοޏ0!4yiOQ=G%gN 4`jUcQ r13I8GPƍ[[[ sAę;;;µkpBbh%۷oܹ(l+,0[ MH%.[֪e3~;:3 f{]舳 Κ h@_WrF?(:]qz 4}˖-(߿#(!!q l~x ?±'PR &ZIHj[a) , NdsB~Be+K<0 ξghkl9Gj[ 4`J(8Kl}'\ 8NN<\5{l_ep---Ȯfeea-Z֢t- XoǏ.$LI=ۿ nz5DԘwq ϙ*(h@b*^$aV?݀HpFGW8G @cNSb`CtpT@ 0W.&wd.[|"H @ +`Ne0{,Vrⴎɞrh@rZ SID@B^ҙϕs N80Ϡ) 4`_-!k< kH @  pʤ3 a`h9@ 0UM8H]`$ApA QH|CqaB-@e/}p@ ҟT]R57 F41GD[f 55/1+\ii={F/]4[xV:uꔴtaa!| A WE<6CTXhz$fsZGW:k:m8@Uv\t/;FU# W{N^^seee͑kݻw]G: y̙SUU5[5*srrzzzZ[[333 ><{lN*@a4ԼVa˻u<4hЀ&_gUW~0 8S{{f%w>~8R?Mdddn #Ι3篿|A 4M8ofuت8-9@@5fNO-z$"h\5C֭^Fƪ;E[ZFZɓ' (^Ѳ{zN-/*G%g縰i 4`f*n6~3# 0g!F~ww^===+ZNy f x$"k?SWF˰ 4`&]{ =aZ4ee*T555(ݓ` Ќ[|<'z0z0"h@LomwX7%: e*TqDmmm~~~NZx?|\ªϟ?+**޽?ϼy6lNywwwرpB3%%rۻnݺ 80gΜEEE;wD<~Uä_sI֯_%j'55=x mxYP h'7T͍5E@ 0CW2"k#M7$hb"M{ӣL%rdjiim޼9229bEz_pÇ111VVVFFF֖MEEE LMMMx6|y+ydˁIk֬A)LLL>}"%""bΜ9Bh d+4?Gq9 4hQ֛͂Пl9ԶԘCFGRRPkfՉKweLMMg AoUHFFF(ŋM6Q2{Ek9ByM~a0!?"yt@ȧgUWt$}*@ 7Y :S)# v3{9ssE9KJJ)۷+VyIGo|2 p1*}?Xmm7Ҁk߁n 8 4&6Z+--MyMy捴Lh?& @@@ /$AG|{WI@ T~>$p)c'ID7$qVBb9sP5qΠ lpڵgyy/\) (..޼y3Hlllhsyyo_9&MMMxڵ^TA3 ۷oܹsQ( 8#Po?y~ j q" NNv 4P˧.:h4N/K4h@@rϯZuATÇrH#Ν;( rwލu8CAAVlqq1qҿZsF_֭[GlƇjRl?~F;k.xmTHk"++RlmmGT Q>T솎dDV.ހ 4hh(~BlfAYoރA sIGX͛ ۷o_`In#sJEEhѢ;w***"+""pm۶`yZZZ-[xb;vEEE5lhh W?EFFIPGZszl-}ZzuUU4Po?tjj^at` nW4h@@ëG2"k#:2H}Fvikk߽{ JO/Nb4W~'G&' 4h%Jii5sySg# Q˗?O(=Nkr,fA^^#h@(WwoZB|E'tU' IDhDfX@.L\b7? m(J4hUca$"Dxyy/^|'OA@@F6;Y%vt 4h(ׯRXhzzT :;@@^މ7)}ݼG]@ Z-ԶشW>vs@ Ѐq {ڞk#e74h@@ߢ,y`R%2J# @ c+2*;8D}{@ 4zk,ICTUkID  'y[ 4h@@c%<e޾%Fh@3{%a\nxxY@ 44j㟊NX6}# @  +Z(8= 0mmI$QPi&ot暧$MSh@  ?+9oRuq 0=2s@@DtgxmI@z]3I  0X̂;[vH] 4`zD${ M*%TaG0@@ 0L8{$AOŶkG@ Qvщ@@J{br):V=0@@ 0h8ǬG%'q@z4Խ=~ygѫρ 9M-@@J9 -̓(Ǒ;0@@  4@&?7P6?w7v 4`G=`TEe +7 }/%/ gwa I  @t8`Ln^S@L(Nsٰ^K_^u) qf<(p jzUhhbTM86]`$@ 4iG~-/8K|!_@L[Ԍ7smnEf5SA<8>%p|;)bzߗV~44ҟ[憖H @ hf *KU&r@ Qp6N_OLS36C.C=QdMI ܶ&h5oQNt5:H @ hFy1u 4`jE}ecF^{݃ :V %@ ou7L_BVuK)# 4@iOܽi "7bn ~㟊ͭZ-<gY.&.W(  f Jb1 +9Q@&yG>_[eѩ$.=\;KT"_ffgeG}O_&|j|_RQXlj/v{Dpٰ mRF%^u)-?w| %dI'U}n!Ґ'DmpTXO!.uOa?ԛu7@. F@ Lw-b}Q@&o4f:q?ߖCij u[5uXx+p߄Gr`yKޏrqnRn2ܥcp_P@O>WRQ~ohlfaf7$4E\|Y/3 K++kjj뛚޽9RJ\R^Pl瞥'v{/5L `~.7@o_l9^mN1F~Eq Dse=BdAfl*:xfb}$RVVctD>v`or~򲴢WY)Qn*/ĭ?<*ƺfQL6w9/?EE_[QDG婑s3cuScCKKc3 =M]eUuy%)9'O*f{2rJfa/3 MH8+ɋ?o [?txd(BŘe|3|$@@} F0ӢmQ (T *vvvv:EA^~~(8dzUvOR/_#O@>!+C@k,@@ 4@1z eΪQ 4`.6.GC[_HīJ\fދmHfrro+cy#eY[U ]f^$_2 ![?Ty]*+ 5):4SNDTUuGx>` d"Fxm3K+EUAA:`䖐606ONIQ' kO :r1hz"PwSو?X,P:\ @ h2y vkzںON4hЀ1"?0sK[y<$&.##5-k[0w[ :!k2S Y4aw0>2+*`4#-שXd 4`j6W'f$EX : ޫsιP\PyxjKHI3dP&AQEUk[ȨWy-352x [Ԍv,ؾ<+,ŝ]u＀J L:u2rc]z@BJZ[O39%kj툠?GYCێbौZGC| E 0@@ 45n,9ba 4`oGD%Tr.1a*Y:<˂Z dž1- @2wn46u~O ܒ$KX[Ie{N4[{yMgs.hIt465SٞZ`׃+wb7J2#?;gQw46ǣ粃){ߕGzBrg; l=r$E*xhP$6dv;mRY;?eMo7WT;:h>LY* ADdTQqO)?IuwwedgL >5gWyi& < RaSC @ h2}]g9$k182""S拋O0%5{bn|5RI[>kNS]96NȦE ]%b)ki(%('0\2rX:)?$X俇RP9uuWօb3Fx~r6; ?2 +?N:3L8.v%2a)eǔJ7|DQbQSI|&Vl)u-ɵ1h$A-,in_)$dek9'<2O$j^0j 2mϽ}mi @o^k)+[΁+D&!xfkӏoeYrqy=<_t `\V-%qlf[΢+T3>͋@py?g0H-Ϫ&TSs&4 >H ׵ѝz?v$Yx=0Gv3v:d+u&)2޷6!5UxJWXsq{?JoqNg~mh/SԧSb|΍ *B<:Fa?g1f,aZ;.%"$?}omsoFh8U@ 443,9r7< 0#1 <"?=QGRUMOVcIYAG<,l#Y9zv;wd]aD=,< ,d3ϯls `@ Ԭu 8vk! U/= pe'S`0 ^)N|.E3'3Tdu?/z0_J3ȠР3Gd!6v汳 "d}N Fs dx0^^$!?iQ ?35T[B[[Fn޵'u &nUs%PQ:lzpiie!>QήA6fJ:OD=|pJqz m.\tpCυ`_䡤cIi<1njpW7ﰈw}3`H+dx.ֽY֬#sfyHУΩ@FG>O.39{o"=р "O{$dأ6?E#ѧNӼR\p;;DJHI3 pYQ=qwKTnsr0educ,4wYM;xؒW խJ٩빯.d;:zEF!0&U@ $rv?+%v:FBB2-< 槦l>rG9tgb|$65펒O(Oh*)0xm9@p6Z`{%V;j&Zq #^w&6Tj@FG0{.3Ol &_h*s$ aNDf='u-rJY(Zn_---C=vMx#Q$/5wcbe{Sc~2[g0Nqm 1.X(tu欚פ'ʒږww2GG e"\\ @ hiWYy4u< Q41>׿yd)V>fKʎV]Ffb' yc=@s_xAA AM@0W_+ѠףE,pq,ȅQ# Q F^#>ju60"Z= " "6I)7ʭx_[द!("J<؈Nl8Pҽ\َ?~ĊR tP9~mr sy=BD0)M0sV[]!CckKήf:@e;xId$AFZ@@ pXky /f LgA״¢j"%2'{f mHnXP~A$=1O񋊊37 H L:`iE:i.g8w_K!U%7Xd0Wofa&*h7W/7ާC醒Xۧ)v;??+ͿZ׬$yP 1g%dqVNzFűGqn ]xa[FN*(8$"K+^/y)~#;Vr!Hh9U7СG7ҏ" L3DF2" ^|.W(  b*brvƙdM#}Դ3fYVdşq h=EDJ"/iohmiR2$0~j5~{,tB+ u[;Ai)״Uh*/\Iq7M9 7L *M>+?{S겁iH֢bw'rNuҏ[D@kJJ;?RznRt蒗 Z} Ơ FjtPXu p֬Lm," .S@#@ hI.&Awuw i) 􌵰P0R"?ٹDIII+)(kiؽvwv  MMK+ ( O;}0`]Y}M]Vkذt"aiV\Ãyg* o@(W7DQ'̈$ 1}kBFfՂVYj9ZUQY~_zsOt*.##'ojn몶~%ϴL\^w̪{M=Qݽ=LЯ2H=} ʇRJ>#4@1glc ت8Q /}-ʨ 10ҽ ߣ3*.>bm9=>Ѐqտ7v{R(/c;|nZ\Q?4`Lhm弚VgSWvS[@;gDcbzWB>X6!.zghni;utvN. >B=wicBFr/.~\A2p8@ 44|:ig 3 (` Ҁ7(3sRƒgBh-ʃrفqs >$ŗ4hяx&o]8'.nDƾʛ30!f:mQ4Q2 ЀH_>ӫI㸞Rhf2Eڭ (UF]뜺"ξ?B`GG6QW P}|UT!r_:96ƐF眶C K <;)j<||I8Eqqg$x0Gg[Wk"S oKkoILԑ4`liR vp+`  sjŧ(mFff-7@',.2guk!І@@ Cb]pi_@&d,3dKqa OP쩬w·7.`Fq#@0570wP?fe^[Lyi.ԗ}MHrӋ1h2g99t{z{8N2 \|e9a&tY54i?~Qf@ И' u mg;+j>zM~ߟq9 (s``xhЀ!o׽KQu|@†lEɺfצkXV]{̕W}2  F'e=|cg,j R; z .&+{̽?Ѐ1ľ ?eyip+WcS:nJ%eY~Qs/*^RZ 4@oW_Yrú{PJzzL @>? _JFEC򅗧W\hhwyBh v+GlfZq u0hhU,ދx./Qg\4`Jڪ݂9#ռkskZԤdj߽Ѷ]]]IiH%wwwCcNi bc,9.XJBBF6鰰呣',$.}_4hM h=U#ϲ邈VnI(,yb~gϑ1,PCם_jN?d-"ɠGK{_/] Zx񦢢(JFmjsr>UwOpw۶UTAUB5k6_|[SSWO:uABByyHBVV…7dע$RRI`$9̙3$g xaYyM7{H zgg-REꟅ[SyEmC;{h0uh د~fyME񈴌EiXneL1X}Bx:11а@lhdgɓQ 2cC2_ w7Vbg!;wG?&&^dob52ru@ٿ/^BCsUNN}I?7ueɒ=GYf̡g9Wq#!4@Uy|!QIQ)++ 2~?+/O)m @i!G:Zi䔑ڔܜ+OF 47x4`h&`L on7ԝFmk|Ih[ȝ_`{%<~yb89L6[[u`9&м.:Vޤd@ J\f0-ܹsWPw&yyo2^+ ١م ʝS!?</S˖o1ZExMMˍ͜,,9E /N{OQY>?#\lhYNQ#z 4hDm^S.H)xoש0p1O\(Lw ͇O\;M `Ja1ЀiLFdy6&7|c6ݧCt5м@Ƶ7Ig:(q=POuBy0?>~z"Ty^8Kde}PmNM %nذ;F&xw?oՍ̻w&t *s߆p^-ym6Ǐ,}g\!?UEKyLqӒ=T`b# s <z 77p?4h!^fy<]UM +$#WNcC6ȈQ=_EFWm,ދR:M ЀMb21{]0w~_\J?F0%޻,i+ z=yfG>U0Ljh#:vʆ2<|ЀA&^m"y_K &02rcXo߱>j15wf `bBi%]L'\D$-<-X9xg 485o2Cm,XП8~^HE:-7Wga= `?~YB?<-(h(tR};LUoPKfYr%.l$3Ѐt:(qkM~l4{ȥjjZgPU5ٺu} Ѐa &VH[ Kl(H#J\zLCLVlg@ҽfaPXb݆ [mm%ypctH3kn՝Rw%C>h/D JDC0 =RV5 g``hdca9CP̤I;NeO{ pKAsuow-{S-}*&ay5͓ H{HOƶ3UxV6kA˩(?# M 4`"Jܷ(a[D{˖9r `8ZdO?-_˗H ^d!w|,q>L9Ԅr@0& y…"_ڐםvMM zz_ak&PS;#VmjCNF^`M~v܇jiY~m~ˁaăih @7@C]_ݎx 21nݺ_VjL$)7eSW7 3!7чӷ,21P89E S%yDM͔M;}  @ش7t8K 9KapNQo`DZğipqff Rǂ6 w3r&/,+,O2; E[hsPok] q9S!q=A1M.%vnV8ho^=eDM˫FjK뤭>T9!1_vFyӤ@&R -ͧ%8j;_}}v+QSQhn0F4Ѐ +aDXX]l5Y-II}ر5BGwWQQ…cΞ#*k(^r0%S-Zj%C,b]PVHaȩr6:4;wǜ8ŏ?.|G^^e ȑoe奪j$NP B=|;s*5g(+9i{ViiEȤR=2H`TTd'`&/]Ph,5[F07ܗ[} ޯ ^1-i D:xJjkxRMH|ghG0+5!`I073urҴPU!(URީ`=;i\#tB]s)٧3n2f}UvjlY-.[0 P j(..)+×NAf'~ *'ײG;T0jՔ]zO?Q Z7n n~`g,zss7<ڀr- Őop:oyu238yBCF |;w!+ze=趄yWώP{lBC-[#`|=3YYL_a߲E_`2]+Oc2(hjKW206@s+4{>;g59'J0~5AZ)9U;PX-1qYnF}88{FE25L2yDcekX( [(*T>&([;l6]>ZʪN*mwv۱U{V-mUߦCT]rT}CPGؽTk⎹.- K޻tk_nyRtf `:0qsL cH+RԵK Ϗ l >}`O11ټ65 L-iGpON64Sꕖ^A>6k˗/M3I*u~xIȦ# O˗ř-X\=矋 ޝ0 }૾71؀5(H=No `8"5BNz X̔,rQAbi B٭Q~4W{@mo WtBHw?kGE}䰧/j!8 Հ %RVĤ-O~FL Aԏ_K" 4Tơ[m$b^s *0s7BR}ٲ5H#-^ɮ!sU\$Q5@pr#)mM4oG]i: y&ic*=!%vRl yX8r0o%e%?za8w|{_sέ;wh)ޭOgܜdegFMN++W74w6w58xЮPj]*vۤO.pkܺ;(6}f4% :pqN}XQY /)s#c\l'MC5`s,řJ QK΀=:riiE}ӚkP> Q]R%dURR >t୶nU3QtŠkxaN\_p+탾Y;^IIiD2BtTLY޽WK%%-Tw̙sE|<  EEM4# ; xJQFGx|'j`4)h/,2T Xl*AR*T(UX-Y^a7wqmڻ۹xӭ[os ~M2+7FKިS#_ՐkQAr { <+pNE7xϞ>~uzJBdžu7E__z n8D˗^~zAZc^>(b1oX#_}9J\hQOm8z{-"w|wB$!jxS،`85k6p m3Clgy2ylt@TC5KJCch'Aa@&]+tUTT8o>ɡ o Oo4`a0 4=Цfu^ |+]ogMmhho倇#LnNRVm۔ $asFRr&we ɉ(ZcJEȜ=ՃpՀ$j@kIE~9{7YH[j-oG5Ttqqq231"x5Vڵ;rN̦e K7d,ZO]$?]:ڲ9Q.%[bgF:} MF-nFJg)=VDS]{nqDGίr4٠}Ehjg|70 sPs/h\apz274pjnF#]l춣lrɧ4EXW:*6fO7 5u7 oKJTlBptKĥZѸb<_l[mB:#0s(hI?}$iۀQϜ9WTti) w(ILX 02…EE%;Ò|O2 '̚5qjeK3g8˗sq ``21Ȃym٢hm큕< EE-ޠjm)%&&6i6Ikx0C.JGG W h˩=ʬ ̢ %LU8q4q%Wm-_-ZCϘH%]zb]/i~Vˁ-+)!7Lexs9X3K CVD@$!jĠ@W 1ZITcU;FP _ 8/;zvY`*׵op!77t4|Ӎl/2^ɪT<7 _{9VbN{?l|E4E|LL #,?(^Pt0/~bF-ӧ [ZۘŹyyz 1%W4;5;()+CT`0`ջp !e]&O36:g" 4T wP^gx E*\ّR5Fertt\@XhN!vi_-J0S!B9_tw_"t*7mKWjάT홾e:N |Hj9iX޺pG?ݾ}Ls665WV1Y9~ gKNfgO[{{csGO^_ U=0g-St̎EAL_ϟ7" 4T zxkEȜO(%Ɍ3(5Mr@L@L84p*:II񀧣k>_5N&KX?PKjͣA?)wY+(k*ݔNყ/:_?wk'._?w gveN+__P(Wj/8Z8OL}RsRX83Gks|ÇOΞ*. Ak[{yɚF?؄xDE޹s.^| <85#=.1L }uz={3#GEO>ř%$Sbc2Tqfܹ?#h||+s/WKa %\w{9qqi@@@@@@Ad{dm0jI8dueL 7T aהT WRr4fWj@yKCF16L+KnbCSJ]X ڊYG}>WZ`\<=5v0Uik@/j)wHZhF".Z)ىKߦVfzkܛgkvc.€`sf4[nG/qTVס 46>ۃmd\A؍#3]5WTV!ao3 #Gl\}$Y'Ԭ#GO:$\qWYh 쮖9ߎ[" 4T pe5E9Zi))%/#ar!#v&*e1X?JGJ+:.UY\ٶĿLzӻ%nUa?pa'N>qWYƩ#h9u!,vҟ娭Yz'/͗w&!6V.TEKM^EsB 4-kR33Y:m1Ovc䂚̖;iy̤"wA _8s34K w0uSbdne%l==Y 8 >Հ+Wn )KFεk?s_iq `op#[FO;?|?a :6&2|z/ _|)?AL*r÷L#?L$!j,vDnՉ졷C*6v@9C~An <9"S:A+Zabqw&EGdd%0ʋ:Z!oop!~zDWV6]ͲRTZc(q=7:wGkܪ9z-j.h4^WN\au*%'m0͎ƨYհ2QQ6SVܭmfc^bٖDl6{rYFa-'rw."Hz  [;\8{W>ZhHT*I)~%vԬmσ? tzFL#6dA˗hWْ]{zo\_=Lfgg.gĄ+eڝں&f1g4jj??|?'? eo_'{Nujmo/`y^ pY@po9">)`2+x= ~ח/_~P'$ b^{'MC5`TɖW/a7_p Dŋe,ARf•lS'#qJ?\78<߹ETT…EEgJZ|,)$7-OIaXX,]flWݍխK|OUUՕ^6}Lq9JOgWAA%p*pudT9ѥ9 (b6Y>,l|#I5!# R8Eoy{AEl.8z~"DC/YyJ?|{T X0*\tvOLOay  P j SfO#S jg&Bf4cի70 2˫$$ Y#64Zx>^en |E*,STP[8:ZPP @djiJ%%-^ȖJɿcnPȞ0р+FO & 슊Z^EELNw$04g wCٳ32Xfo=sw{ix#s> %f&wtwxz~ ̬CY%UU UFVԃ_Muͱ.7%U(U+ZڋZ;Zώs 8d9TGS |̓d+*WGI͌Oelq3,g%ԫQL*[}Cˎ\B734uu t =h:| 5W;Etu) VLw"j;f]'o&SA(.f45}_q+8~-6!M (juB}Ş-{yŵ9tL͉z =_}7nCn,J_E!cN={w4j*%fT%7ٳ!DKhFw'"Q .~G;Tnk |C2T?sśnݿDžE t@$G0,P ܲ!X}|Ʀ«*~$@5@MJ/'(x[01 }+ŧ2^99+*j f_ &bh'V 4ϒ?akr3/eVp' $sTw_n AkCe @ݱj_`V@3(,/9S}Elf~*vW=S+ h}΂7 ju'иWULMr}4 5>n&۠`ܹ㤗pxؼL6>-#]9!@5`•ֳǑ~1~ ɓ' :ŋG'@i\ :M3駟KĪ4 @5`Xo fqX_2pgΜ Xjrr>A\\E+8zz૛[୐x]*%$O5dzXXE6MLl(X;g΂t XV%IIii,:2JI2cn ^>!@0BX:Ծ[+"aMa7LHJ0J@$)K7Y\Rʹ.:*F[(r@gK>z?z Fڿq_n)G4z7`o'%Ǖ_P]ҥ;P >2LF9KL||}CÇO!˹[W{rO>0V3U T^xo=!=b0ٹ9I)X(Հ9<0 fs.>}ƦM9983?kDEg 4Wku||"yÛ/ZYWSƢk͎7XzJ CYYp˖qu . l.]=}?GgaAA()IVUE6\t.\ؓm.\x߼yWNNVdXQx[淯,<\r=R0P`;MM@neiD72^p9`n߮ b5:.Z/f֢2;4ZFZz٫ta{u7WD& ;K E-"47&#QCÀ)[[OP_*?,ykXj֗,*%5TR2=# 3SSs(tN_Z^Ik;ydxo} ]*B,'O=S;5" ʖ]N12eʡC߀ xuU6\|f.j-7]j nį~7-w^8H +zqϟ&ģj.,P &slLLlKr-,\3vhh"My{ÆV`W蕧gxaaS7100G $.~+ 8o%%y+CB@tu/5ƍ;Wk0f+: 矋edKHG#A}˫DJG.5eT꒰y5RiDd!PU_nURT#hyci/we!Y 05KJȖo%+e&.|C6LfȠցˏ\XX 3\]{ٳcd`[%NNo suCCKA]&` jp(+9{ `[CC+poIK+BF*Me|A)!s3UZlf*hi㐃Y,vx4^f[hO$:؅mOBM2ly'Pޛ%z>#LZپ T2˶yZns3S372٫fatebiEMm5mMqK `3<}_\Rڀ3;ptvn!bv5άxBR:Ee8cx,")9 G.fkl>xK_}ՀAoxc>uw+@5`+;޾1}"0{4 ^c$Q@i`j;}$U^_bcsE EkYؠaa}K] !>V##;Z\pH?t:v+wPT*G\|ή] 0|]jÂqQ &^}(.n'X{EG$'F]Qea! tX&XN.3ph/_y;ddp'ܹ YRM;:m }0oA .&.[F ;0WiWo: s6" W %Pp_Boo8u&,]f ,vʄr2gMb{xMQI}Y|R.?j9THj0qg]% EdmNM]DT{+aޣvIo=ƛko?ax1S[<)%ǸF,93۷95̢+.]Xܺ]Ss{|R8c; j$S@/g`o0(/Д8A)̰l@$F9lLf#:m Lm-䢢ЅkZ78v9vLG63Q1_)*U-^,i⋙QrrJIIK/CC oq5k8^"P|j@ϛ Ӧ!,L9sXFGSD{0`t͝iP\܌O6q^QQ=49耚gh~rw\&W'F\>a.3$kNtC7 l fp%%7"p1Xw`Q-BE氆.LH߀$8@ph :Jj@mlVgrf2}\ $}Z;7e GH 8p!c4-}^R?!BkBFUTt7Q==7;:z2rH+)ǿ¿lƙ:t?64™9r TK1ٱcqgv8pѣ_1#E:8,^LMFq Aa09UGMA5:NEΞ``CS+T0zͤpH*CCkȥsK/ٳgH!,P /~A\ MZ@h ʘlP ~܍G6G* ,>p}BZ P44`נ>G#|H-`aJpI^^ 2iA qAGTb$$mNLWPQQ]0.]ӷJ@@T:J nJJ!Go `ff4/{FȜ#K" R`L2O)5H,(iV @}f+7I{C{?][96&oBjYZ{L,3rXo_$$e#T|&&|=C=X|ʷ8]Ws!`0KpfGUU78zԥ˗NJ5Hk+r9wƳՀQ^|Q Am yV#?M&" 4TFk|8jY.@F̱|1`inO&uh 𫶶18i&H,pbbrr d q/^,,ڐr S- j#JԒaN ûG@Aell)<<,Y"Iw'e2X5?/50B3`w!˖AQWuA-:ߨ22vȍJ-m $SKLjye:1K 5T]7ȥ.HoRywЅK >m_cmb^6 Ď^#ADžp$һotlR,OL)"' :;W.:z˶ÕU"Nǁ8j\5Ԁ/:to"T&_ dT䧧E\ՀҥGC Of.`0cs^K9v5_4`ȆDE%pbΟ3g`٨##7hV4o"+/Օ+e^"OV5 % >L]|11^|W4v|U4{EbP ( zy!վ}20 $لa+) -d2c$hj_ѻQoI!sCٜn 7"H~aM3K*n-hK*"$rD_ @b((+o$|k޺2מҨ/՞<P\C[57 15$DfJI.]5zWߜ8qWmΥ.o܏3;}2ﲅS>|8%!hǎ; }|+ME' l&I|J$!jۛ cmm 1 # QPРR9tzqq9O"XА PS#][LprGjsf5bb^^.R\Ǒm۔הإ Hzl@U,Y",DjѢU84ΎK> 6h#RTTff |#$ٳ[''8N&o`C:uЦ|]z:hX?ޜz`` z"))w|ܝ䝨kʁvb ?)) zz+a2wQKfՊ9D5 % ;ؐ@2"FQR1jBiob >Nw~6/-[/oқ&v~3ulԆUFZ?9vO_du bwx,6WA0BҶlt{Dd2Հ;w~{_ޛOj/deDDF:܃3̢+yӧ/`Q[][] j,W^ll3?))Ĥ$&MC5`U%%ȋH$/UAơRR _I/9}&n5nƍAKPj*cq رc7mmc@Ll,==3s899BOHIFx*)i)(̾qo^DSM$# [#*>1 1A0tÌ:;~G$>\ǾWP`11Y8!g+y`񝇀6m pu *am9**P'022"uƖpML a]&מo?"$Í-e_{rwWFcψ઩Nn٢MU[8\#5}AxapBzz44˫]1"o W?%.25MPM%/G+~kLߊhU}-^tBq0/nʞBZtkU$BZB: kx"0$r~Q g0!_ ú>rgV^Y_̮o:yk+.] PTUUT֢{!ʚ>ITT^x}P O7x"htNq|+3G'=l++?/t|y-x•-_}{,ucHv+`_k ,6M|ѢFo>}ƢEۂmm/)-k=؟@a|DߥjW@$9x _))aWcad7--LP.+0S3#)1"ޛX/狓@͵L>Հr]l53^E%!MC5`@@@ 11-Fqj2gFt2Ș;@ph 6G/yHr?,߻-6jqw6}:ND8Ky,ﯤg|Lm.Wt$6G+@5`ҠckWס$P2@5`Du6BQQ3 d6yH$FDHp24RVVflr ZaV֢!5g_ӯ?SS ' f T0})%@5`?8$dP 7ykr:Ő@"[  ZLq ة#ܕSEZՅUk^ ߛ`zi[ ri4[`HhkLaV.1JٖEs8c6"UXLz jTX0QUUӧW{{{LC)l8#BXg hLbYH9%(lqO&(+o+0/Z TP)TFF @Iv_m-g#יj"wP TU*bֶ @5P jT`dj|xm@@_8dP %~lR0h~1FDSC? f^74@@SnNj2`)l/8bK)AV"~nP+7h~@5P Q,Xo_F~y󦜜2@@@@@1VR^,ï/fYLl&_ߤ&b&ڻҵKr+ӷ)< ',7 3LQ}%Q' 8dP jTXF wUɓ'***...pȠz{do^\Z!dja5/wFhS( *ZW(e(\W[,pr2JON.dy;:zC}I$o_4VqC/oT25Հk̙/>pRI"MHpȠC:3JY#,-hneH ;MYQن r[--p&q?CmKcsRJvTtB!@5ݲ89p]Rd$PW MYnh(nݮ5hSY :2h j{- xpaP jT TPL7|GCJZ334?bH DD&ߎH/wAt:d%^C8ԀWCkL'+{8K""B=&jTX0bbb2{liiiKKK @5bϩ!s>65ϯst5$f)o͖d nQřF r[XZÌ8EԀںO;֛OW,jtiF&@5@5[]Fœ9sϟoaaQTTt8:P ¦"lPͬl $ Ojj;C%`#-p*9UVB(<̬9D Pwp56A@5 \~=//H$JJJJII3۷oÑj4VˌR2G!A\|1ܐ@rraտِQ*f$jXwW%#-pҫV:XNWPQSE qHzD Ԙ$@5P jT`jƍt:D"͝;w޼yfffrܹH$JHH@5b@9I"d"5;HU=ŖBk]``u kF j>{݌ÜW5յG#٪p/yf T@5 ܼy3??tRΝ;]]]BS 2sJIzQ3z7_CɘdPL[wdlh^ =S&l`5_VM4)&q& 1:vfZ&{:%g$C5P jT`j,/=2HNP>>Q`nn!djizHNCOsfΨE :9zY7UػF4 hn "TX1H+jY))N00$ -I-4EMō vn-\P:ݞj@Iq#'VqTZVmwFhlUaMg)%@5P j,P  |௏ϳgϠ Fqt\. #n 7"H޾lɴ.=;WlhF -;:#@PU[wkrjbKiiN@5P ʏ?4o޼>h֬Y֏="oM6=P PJ!sfŔެg<}lvK!^/gAYDq>ҀZc-p +臨||+"ɱ,zv@5@5@@?W\ݻ]vs玗);;P ˩!s>,-lB+U*%-Ը'-5Q3Q޵`8ߒ_ds]iFh-*T@5(.]믿jtN \pG%3\QAߠK$YfHCE4 @ x\{=Gv'?yg4hI5iyso9ꩭgͷ/XnV 8Qp(%bO@8Ery=p&gЅf%hhg/__Gv駎}?D4uɩzꥺ3›cMyj}.&D]띗Vqn]ԀW>6NW9~T[s:%>+?z @4 `Ѐhђxgjʆ o'ʒ֗҈<,;-4pˀ@׾l-muژKU˷@4 @4~>#4 "Z:|zrfKGG$]ݵ9-pk{ 쇗/3u.w_B4 @4 5h@Dtz֩zʽ扊!&B?u;~',ԞеzI3DwG[ c_0IGx-4 @4Y {̅F""gm睪V7]-(S=k/ Њ<&6Z.p HXo }e |91Th\$g innvT O~mO"\RꩯLWKJ k6Cl/ xzp5ҕMS\|T|$Y*f(hO_կ~O/~%/@ڑX 0Ƹ=:mؤ{̶}Z?7w+mw<)vۉWο!4 @4A'Eg""ǨʆCކgxN96ꁅZҀo 8=󭒼Pq#_hh0h=H76sZs5ҀRi D/|th]w^%?럺z͆ѯc@4 @4@DEv]\V9)Egkj.\qZo r;9S樂mo}W&h pȞ={="\կW:.:qkhiOWmzA!wzG䨜LBǦnhh4@ףhRDĊD{ugiOWr7|uݼ{ mG3Z4 @4 `+zÆ |?{4 "r̓וηO \>:mt5'ߏ=)zI@JH):4 @4 `O""z|vI@{ώH%W7iO܀>}FI&nv*2D4 @ xW_41)/< wFwZޚ]'|mhh<<==razDDdڕXݡ5QG2;iO@ ?xz|k_ːE~4 @4Avz-Xb0˗/~Ɨ "ZMZnL4hK}s7DžϿ`oOMXpؾNKF.~td] 5tak2w4 @4YD^~0;BK-FWGNG?a\oo(l:@u7RU7Vh@N<:2/c:}oUhh4ĉ"xƍpdhSl|zmPƩFB {ڀÊ@yoM;_=0Vn;O>phQ 7erU$y)IR|cIoXxh,. OyfdhrroPoa?;{ zvk>T/Ql{00Kx/ۛ|Uhw35)N7g]4 @4A?/'|O~%C.Uv'Յf0ń]tהca~c%n۷Zv=z=$RCGjQGUǩWfUrEvTDLVHL1M^AvÂWX "z|83آ8^Vkn~"CGwe%uƴMt^8rgW8UO3"&-K\`+G[smVX fYh0 vh7OٺuOq DD\m]5!Y;\#Jqb][6>Rl4 Cs[T=W3}-7_k=rο{y5w5EZnSe'9$҅G4 @ xIHHHJJz'K\dhÞ^㖢Y`?_o~9r>>>~4h!W>|=jOv-f˟):>SQLο:4@e߲O?к?OO=V9zg_8xn[rn@WHn.h s,[,))O?勅48v٭\[.)w~/<>8vIwt5:^0'(D+{#B>/Y,HIL$lͷ&, _x潞K/yo:h5/R[[jժ{-??//2DHmMc}!xͶԵ ƕqJgC' 𖈣=.e͇#SϘ*jCX䅬|l&S~ ّ^4 @4A4 xE$=#DAޯ:+=[>̆'ɥmS}X|-:,[Dʓ!八jۜJ CL,e&4 @4 ` "/9~Z4wE(v;ܱj KƧAz*Kmw/]*lzQm8vM4 @4 ` ".mk+[79$迢}g[Eԕ oNڗ%=kYn f\WܾwtWϾh D5ξ[R{בUݫJs3jѿ#%=U%luAA]#!jD/@4 @s "z2嶌b?Ki:MY"GjKIa=p *G7?B푏ެtT@4 @ `";ɫϼc=P+:ttv7E ~v[hVɑRf{Lmw_RHF}m4 @ `""=+rgxS_ݮC3crK{+,c4ihk"*lmNTX5 9) @4 ` %^յ< ƌ!gj&+psOe{Sh D{9=Yg=30T9}eqx QlnM`w|$hx'64 @4A45mKFmO5,čMMN֫Q=w)v[SK4 @ `"ZMXnQѱoP*F8Qe*@!+nn?6qÂN]=4 @4A4Z=7T;u][Ybe3}SKߦ约mq4 @4A4ZUCWVg 2ohgYNIy_q`OپswG4 @ `"rb;_Js։]ģG=3,Rk|[鳃>h DXW*H2_ceBxh0hkigCN[{ftv5˲dh9 k=r5#7V ygYBCWVT9.3IJΠhhõ @DKĮAQӃXW+LeJww=hh @DP穑qJgxJtb!gj&+N&3}Ǿ۟K&ohh0h9A[] gxGo#ō,R_{ĉڼ_q{P)hh0h9Aι.zA!ރ'XSnss毧:v[)-]h0h">(K zyX SWXu?A͂3~݊+}B4 @ `"Z6Wku5Q#SI%S[qI4 @4 ` xP֓gllk9]˲h0h#PPRg=(Xwѐetj64 @4 ` %RR綾0&β,?[d12q @4 @4Ah 0|q,˒r'Й-gסhh0h9A7VvCum z7OAeIUcy&d.4hh0h9AE. 8$i \`YT'>dK.z约97 @4 ` ">( <{SFpie;5|i8ɵ ?&:9=4 @ `"r\c:*(@n˲4:W]U>xg; hc5AT}P(CޣMC,fzlWhhõ @D +]:RS!C@34 @4 ` UreLAab&uAK-% gFϡhh0h9vf˛~SZgU#N;ٚueYۇTN&wq:hhcz`zP(w.e itR:$Gl?hl ">(`|gY%)3$>rqvxW:4 @4 ` ~PkJ#cWY%XdSfI#RND4 @4A1 hYv։Wj1^'s&'o2KM/*D2ч.ފ.hh0h9A۫k%:(OCie)Wc>ʸ h @DyPSk5:plqHsK?B3C4= @4 @4A {y]JJQOnoe'h0hѓ<(@2ɠq։]"w1yd+4j)|5w @4 @ `"Z ܢq։׫D)>≉P]S$)A4 @4A"rFϯ_w]rIEeS0-48:$^^ߊHG4 @4A"rlLL_peYYRY,Mr6z_hE4 @4A"rĭ;Qփt(D}ܙ Vfɶ6$%=?pkS4 @4A"rvW lS9kԢ耀$9VfVzg$<>K @4 @4A+:(`sN xIXzVUVfI_+bQqqv>MB4 @f!5A J+r։Hb"%k&'o2$tgv4 @4 {P[T3~:h0h|s_.&8`okael7=B4 @4A"rԃ^Ϭޤ^U᧗%ϰ2K1%YN&ɟL\E4 @4A"rƤ ptJUjz%Vf6lrQI|JHn hh0h@DtP@@ X3ON`ql}W_(Ht2IV$Lluvir @4 @ @a 8P޷/"Y'^ɤ!CLEeemI64qłd'J9E @4 @4 "G:(`bKMJ22B,BZ͛ -ތ-hhh9LIWkփEUjML\Rw$+C] W_=t3; hhD05N{Ke. tщCCXe~g!hh @DuP3:V,Y%fuQhh @D~PgBɎH?gxJTKj93p:vdސ h #3A=#>(`"@h X%^gsN&OYh "|zT%!ccƺȮK{gDITz!6cZ >u2Ivj.y)4 @4 `4iQ]r}4re4 ^R'SFѱi}o('Po:hhD|ܽ Z/p? JA4bFGg反_exSf*L[g8E @4 @4/"'-&,o ]`Jv_T19yZL\^rdEHhh @4X5r=\dE,$$,"I.QEWjj)U3Ay٩ݢo :; hh0hihV+EtT'zxшy1N(dIi.LwL ^\?h0h9~Z–R&-R EAd>U?_oׅQ$F+Lఓ{o7Wuײ)_KMh0h-F'n)2ULj.24"407=gG*4A XMdr\tvV|QQJ²̜̘d>Z%l_eU& FL^᫰d+16B4 @4A4+jrJWXUi)!Ϩ4*eQ!qC[~x:p&Ӡ7D$h Yimt߿OhclB$y[Rzf{qHʩA4KĎ&2 @4 @ `ZZ<փ'oY::JL%)ѩHuD$(X|4ww~US쮖hFhDF(Ii̼܂ҲڪӍ=C=S##)`|jlb8S榘Є, )UpId(|/hh @_KBщnju7/;7qz5*?6-^W˃$^~O* J T+%ZLS joON1egUhkon6xvuO@ \R@bZw$1,"ۗœL$_o&N;M%4 @4Y;GaM/d HZ/WۛŸ~+ֱ3UiyXm"X&-ue^eJ~DhDz]p-aα?L7:TS6xfZL)$[)hhpm̔{wd1*UT" wkʀQ!uz8QlRxtܟ~QiUEe#p:|`|Iu3{ hh0h-&oJ\tŽ5f}B;A{(5Cñ) !q)JS32 *9-{X]* NO?]\a HKቫj&{TdLB"IoTd4 @4 @4Ahd_ooPgJjy?ѢnlF}Sװ7M;~qsLnI~$[v Nvٞ(ӿy>%hV'<"C4 @4A4Z7j:'zضZ,l ie~?iAeҴ88ij\piO#it_wQ^R[,JI%'X>-ud{|˚>-eHT^H YMpP_e{2/SCSw$eT&-u"hQT8i|p,3svfBGT`qF|Ay9jjS3vn@T7… hh @_T'ht wm]5jޘ佩^2cR)*eTfKNoϯMM(/<ZC1UH,,0@)ާ?Y+M!2ٲ~]3G WotΫk6:Cm#q<I$}VVZaigS{dTXQSUhh0h=ꚞvl{WtqY9%f5~#qR2xf Bhh,ݰ&h=#Z^WX %'ɲ"$\d<?h0\ UU5mRZ)`W!5EHʉX4=WehGfXB4 @ `zr֨wt[XZ$8$$ʋ',7XB4 @ `zSVipXJ0uus/6Z4)N,y1M၄h G\txqYCYZDY,mf $4 @4 ` jb↟*Y'vՊE*SVU,XB4 @ `zF/UHuX/5gL\f) @4 @4Aaޣp։7*UƊF ?o~ -@'Ђh0hCԿ5zPHq.Tc/kB e&?s)!N&&EqkBhh @^ $O.0$uaWE 7I"{$fL\cY @4 @4AK?6s -jfŅ:$/ -,hh0h=TZ d!Ic>I*7dt^d) @4 @d @rKs։]t0YnA ,hh0h=d^*Nʕ>xN:hh#78r-JSچ] -ǯuG%SĪhh0h=Z];u- Q*s5|Q7LWR84 @4 @4ה3_ }3 -,̉E"Bxhh0h=t'֫F62ފn'qqK_Sǂhl$Y4U$`J/4 Kk$.&uY$Ahh0h@4䢳R@PHPIq_UϺ1zIhh0h@eOY'vъ$5m h0h8p#ÝuL6Ț=00Da) @4 @ @Kvf.UNQ)R5=ք`g{]プJjObA @4 @ @kئ p։* - /}Uu hhh=ZE{_U;RifuքZӣWeѯLgBɲh УT^Fc}0Q^z$;,Z<dF[YB4 @4Az"r W޾ei B !-r:/hhȉ]nS@Xp`S} B ˓[hhh=ZɛgU# 2&P5ޟ4 @4 `4Siuj>L14x5ƈƠ:S>Ahh0h@_ցs;T!:(ք%:I3iwXB4 @4AUtoV8įGI7XZ@gءCpYռ֡, hhh};׫gYxE6-2d_K^RrwM뤅]h JzVղ КڕdH,XKB4 @4A4KRk* $PVÂ}%K쮓 eAhh0h|ٟ:.Z2 ;`Ւ'N_gA @4 @ `Ѐ5:*(6@2ʁl SU DUN{q%y)>޶£)i@hh0h<ƺ.T9UPń :$wlRqO~ 4 @4 @4AS}[:V_*va>@$es(ԛ5ys~~fr^xJNXV3QuZVya'k$)1(ɖuK>uk=>77WHSVmMM(9_l}Us5(Y\T㡕&LkA)Z wi]Wy:)N5 1A߾)OYkXB4 @4A4Sռ6 9S?ZEIK6baw,ʄGTcѪ5DIԂҹ4_'Yy!cUaLϟ[LӢSqI[i{=mtwB1§,\tϧm)>i?mOp0+KxSbi1 fYB4 @4A4KZP|:]j /|.Ť϶#m[c梸8Cjνy/4ӌliic^UNaFF"Gx'`N˴^ ڀ4A#!2y4B1.\57JIMUJb)کh\P:]\QV37Um=GQahr>}D9p@-<"<hh0hHjJQbpSH/61IRRv]jvI9`{m:3dM<{'E\|j^2oNSrfvWV(SUyݙn_k[MxUY,gmbz[=em'{. >BxܱNܧ sO}`>84 @4 `z~Z]FGG Ú5kЀjw}qFgU+>}1vb%vOo )S Җھx S`i~ʄhh8'?Y~}hh???d6m~r=h}NF#J jV1XV-KO6ʅSYm}=%dsL0:22&OW149#6&4%hBN՝ط$4 @4 @4&""W_׫V2 x/wVߜ*:!Nۢ s։7)Ea/{'AVEmtٴɻo\86v5!5mx`pllӱXza_b؍]\B4 @4Aiiis\lُǫ7>{ å:eޤv։wFU|ɛYU Q99>I1{"Ƈ=*Y*ܼkj"!՘`7]&"TƧgNNdgMDhh?z^paW^ljjz??۱cֳǝǎ>w=,\ Jl^ p։|R S]r49y Q:ƯX,X|""4 @4 `Ѐ%5aaazG?__  x v)>'={IwKh2_qr3|U9yYYjN]z(#ikR+a{&DMI%;F'-7ƞ @4 @4͞={k5=e1s_)`KbmzR&+b*잖~TU[i<Ր֚%23bnݟI3T#%eݫ @4 @4ϸ v›ƒ7tra'{4:FBh}k\C*.0oz>Zo4{=Mh4d폖$H FjRuƲG2r=BJr 5vOk0̜=7h"4_ SmۓbRv{ 0ays_jvyB\~KSƚbsJNDDhh#˅0AMg}jWFiu:Y+N[~P:./OL*(kii,ϭ)ejL9 Y&Axa5 @qxoO(!d^\ #硁A94EFO󓢄ǝ$RRu.)Q_K>SeJ]3ф/3IV*duYy ߊhh_żz~;AWWǫGN/ ;jTvGT^(!AsfBCFuoˬKH^ Sƈ|S yD%0qhgwwRtOZfUvent&^gKI+6U׵6wuON>c747 Vu,m=]6a 04UԄM:oRN*&8⏈ @4 @ xr,??}PxSxP>^ R̮s+"f!-u٩%m6R! {J|v}7+ h6CkU1R;9s1j뿻 lv#mo FקΙ[{rr3uIj$,28H}LmZWA[4a۴&:SCGuÈ59|A>=|MDhh<я~$gQQ/_ӟ^ݟ[w(TG{Y. 57ThY[KɊ$U&bD}@Y!r<mԅm+hw2r}OԵ7.fqA!G;!/ o;m""4 @4 @{ KGP[n2w\ _n,<Ք\TOɒ뒃(T%:GX_A#٤ ͠zhp! hm 8ɷDDhh0\?RO~_򗅅›ov >>>v'6 ~駟.J MOWwMH+ΪGɳDI>~//ﱠ/pQ~IYU}|MDhh<gVbŊ5k ͹o8< צۦsk50}XVs؆Ul'F3G6 @4 @ X_ĥ𝤡nļѽz vo:l""4 @4 @4 pZ܄u/ۛoHDDhh0h^+*33ij_ ?M @4 @6,>˷DDhh0h@DDhhDDDhh0wv_fv @DDh 0hh0hhh0hhh @DDhh0hh DDhh0hhh @DDhh0h@DDhh3h7 @DDhh0hh0hhh0hh0hhh0hh0hh DDhh0hhh @DDhh0hhC5A4 @4  ""B4 @ `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @ `""B4 @4A44 @4 ` ""4 @4 @4A @4 @ `""B4 @4A"""4 @4 @5A4 @4  ""B4 @ `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @ `""B4 @4A44 @4 ` ""4 @4 @4A @4 @ `""B4 @4A"""4 @4 @4 ""B4 @4A"""4 @4 @4 ""B4 @4`5A4 @4  ""B4 @ `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @ `""B4 @4A44 @4 ` ""4 @4 @4A @4 @ `""B4 @4A"""4 @4 @4 ""B4 @4A"""4 @4 @4 ""B4 @4 `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @f5A4 @4  ""B4 @ `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @ `""B4 @4A44 @4 ` ""4 @4 @4A @4 @ `""B4 @4A"""4 @4 @4 ""B4 @4A"""4 @4 @4 ""B4 @4 `"""4 @4 ` ""B4 @ `"""4 @4 ` ""B4 @ `"""4 @4 ` ""4 @4oL*>nJ! $l!HZ!AL)6ԣD8-J[ZjK RXh-֍]lȾ|ssL2N20wf~?;w>` l!l6 ` l!l6 `p-`!l6 `7B6 ` l! `l`@!`l6B!l6 6B6 ` l!l6 ` l!l6 ` l!l6 ` l!l6 ` l!l6 ` B!l6 ` Bl6 6@!`l6 l6B`l6 l! `l`@!`l6B!l6 6B6 ` l! `l`@! `l`@! `l`@! `l`@! `l`@! `l`@! `l`B6 ``!l6 ` B!l6 ` Bl6 `@!`l6B!l6 6B6 ` l! `l 6B`l6{@!`l6B!l6 6B6 ` l! `l`@!`l6B`l6B`l6B`l6B`l6B`l6l! `l6B! `l`B6 ``!l6 `B!l6 6B6 ` l! `l`@!`l6B!l6 6Bl6 6Bl6 6Bl6 6Bl6 6Bl6 6Bl6 6@!`l6 l6B`l6l! `l6B! `l6B6 ` l! `l`@!`l6B!l6 6Bl6 6Bl6 6Bl6 6Bl6 6Bl6 6Bl6 6@!`l6 l6B`l6l! `l6 I:gϞѣGxxxFFƹsfڵ&gϞB!l6 `` {=f̘;o߾/^CΝ{7`!`l6 lqHOO޽{yyv"**d29!B!l6 ``( X͞=[?sY<@!S3/y Xoz ػo76gχަJJʸ4d0˱ڰa~ޓ\<@! `lƔl(RSSX9rD?x1l!l6 `\S****)ٳg׮]k2z=Uܹ3)))00W^=XUUW x_[j.]̚5Kf7WX1jԨI&m߾ݴiwU xݮUsv-2K[ZZ?" RS&gl٣Gy8w\ ta˫Jv1luU2tР(ɓ xUJ.ipT(7#pKH=/YsN?b>K߳ggK.o֭rފ //_.|srr.^> .Y^^~z)G~׽Ϡ;6il]+n۶M\O#޽{3EEEcǎ۷)s@ʮl6x[_Gy$88xݺuRQAAɓCCC8`W)U Ք35ST/_ldR?z޳n72cΜ90mڴsΕYFO>7/%{l`vvݰ–WUU1f*U6NoK/ɠ\[=mF]^M).Q=7>|oaUUUr>mݎ p-:q]6++Nw߾}u?.C}e˖y^ղҦO ~ݽms^-8K?#Yk9kzr2 ;a{'(е-*%c*UGDDM_`zzуlT) TKlp.y)S8tmݎ p-b$˳ /((v7yi?6N6- >--- ill5Ϝ`gV9olllff櫯ZQQ ngMT?r~رc2(w9Z[^eWUJV)h n{oU)dwކjpG~[Qd7VSm-Qlp/&O:tmݎ 0W^ڥ<Ʀ#F۷KN~5rJy!1cƠAyUUVyXiCkp3 [޺"YEGG뿑)44wMn*8k2v&kXo*И-o%-P nwoU%tϞ=ϬW4٨R))KŃy3 ?=o[cƖ-[;wzpN+WMo̙vOѣe_?~KkNN[Ž|Aѹs7|Ӄ\ zFvԭ[Պdϝ;qFdnvqd0Ls$ A)h̖UŒU1N[{19m4Kp5C٨R)KyF,Elu;6h;6%%Ń ܷo[jto={j^T|rre)ry|~\~xC Z:uꔟ r=ws-ow9R+m֭ୖ`+oW@ö^\eoU.--8p7ZuuH_mlpovKvyw|5D}0of߈ԩS߄u;6Pݻ722… Z4Z||,tg{t]+yʕ^տ2~a`zz Ο?ݫ-{~vϠ'5nuNݷgimmaäܺ'NcdK2(U(hؖo\-Y#4*K.͜93**J9...''Gӿa8 1wj%wւNGϫC])8p׮]\cVV֟'o;ǎҥKvvv0!!A3kݿښ^?'2=7j@{=Uvs-,`wXXg4E9Κ 1112nN־E-66V@c|[nɊmFm۶=F]]MY/QL6ST7o7n\;۱e=7Yx^՚r_h֬Y^uBSRR[[[kYr?O(|ĉiii_a ގ3y69uo,mjjJLLLJJ״6x8e2y&O0!::ZaÆY{UvUd[=U_xQ~3?#4l]kܹ)%Jfi/OnGFCNݻ&?XI8|pXXXikc܎O?4((wҥEEE۶m/..zj\\\jj'u떓v&$$DEE!??믿ot=UΩ{JE1c,Cd5X=&hpr2,A{%waaaYYټy˗;XKZ^qW햬RՃoR9sH]z+.l]\M).Q77bA)g}3{F0OV'vN\ $C7 @^a "0/t^ҿ?xttCvJ/_.g?$$vY% t=ϩJE2>}L2eΝN.AL# _pAVݲٳds]+%-KV,ǰ ޾=jԨgeeIZ|׺\۞*%;R\o&;oĂjǎ)))^nGWRRbc37tg?2hGtсqqq/C$frHL{n:7##C.`SRR7ꫯN*LsН Q p 6Č1BAqqҥK=?|}}2ddgg0PhWO>d=zT*@())1 x7d]fc*=ohh9r L30rګW/͛7 nΞR{Gwڀ}wĉnph6O>25k䇸*lo v v֍9ƴC=$?O<ن #_~%K455njsZ;w=zիWO:e2:z=999$$k׮ƍ;tǏ/[,.. , RSSmԾqƤ$yБ#Gnڴz4&M سg }vwnhayᇣ%$$ꇥqҥ  뮻̙c[wui]l@MM.7WXі оTP?r FΝWWW'?<\߿d̙22k,kꌌ y\{=\~󫪪dO?^֞7͎;J{^[/^Xvwߕ=~Z7{Gׯ_o{Tvc׮]ͼy.]T^^~6O?ayezJ=}tJJyomՑw\uwϞ=nꕯHYY6rmW_}\pAnX?QرceW^n~o;w4opY@R-]޽{eUVG]֫W/?6ŋ6m1bONNS 9Vaaaml"tUDEEMg@a~:F6@ؾ}\ʅ^QQQlf`y֯_/#wuvsڴiFHHœN*ƍΜ9\p ܹsll~>zSٍG}Tn5oP[[;xѣG+o}[rsѢE---ڈd{WGK,;S~m\QBaaj7oV)v/V!544]ـvl m=òk׮Ν;6S#O ngZZZd?Sl@GWn@aa9vXBBgnjj{W_{5nMs:u~;v8z}]O4ҥhnTаh"޼yr1>h}סC]h>C?vsСrsذaׯ_7oOL0Tl#G?|ln$&&{WM^^^VVa1o)[N6{WGo[_jm~s{ii[;h_I'̘1#,,ymSʞ=쳁_|7o>E>гhUWW;jTvcڵc̙__vMFBCC7lؠxXvZ^^\QQき:`X}̙r7}t<5lff̝;W.?Ӝkh s8;vL9tu&#/rJee5kNm/^Ӟ8qnٲ~˅&O=ӧz6_z٪UJKK[Ǝݍ'ZT-EhPNGMMͲeSO=e<- VillLNN֏O<944tMMMr!|)Uŀz葙yQ]Zn]lll``СC>nim׿5)))FiaT_rAɑ^~eGKvvwԿK?b㮎<-x6D{o endstream endobj 157 0 obj << /Type /XObject /Subtype /Image /Width 1370 /Height 850 /BitsPerComponent 8 /ColorSpace /DeviceGray /Length 2282 /Filter /FlateDecode >> stream x1 /* $;Q endstream endobj 160 0 obj << /Length 330 /Filter /FlateDecode >> stream x}RN0+|tf#A!!*rT<ڈ&Z@%[ݝ.#c^7#H #hj1a$3JOVLt/8!Iy!A$II!C¥P[$'468UW~ yDmvU6-]<5wi7> stream x XW, (7TQ 8\#$L&, D8 !{$:̽1&cьz ʪ%([4РfOTiAӏO׿NUS{3{OU h[ -(2:Fdt1:Fbt1@Fct 1:~\ Fdt1:F]rk#]v c1:F ctM}HW^?C'0:F ct1:"( c1:F ct$@.ct2:Fcё(fYv]?-s5{xxH,ZdF|qƵ@3cƌ}O?;ϋެӛdɒÇw"@1:ct2:FGv8Я_?w2~bQs=>f.*++{WĪ9sxvN>}JVYYYUUu vI)~2'&&G%qqq&u6n˖-7:uaĈM0NHmrJI EX?e{>x`eܹs:utm;Vyyo}̚5KRāގ=:**$IEAdd՜,Ww/>\ [n򋕓RRR^Qݻy̽K?55U憄8;;[ .\~ ...oVUUձcǤ OS47RaڴiK/UVV:tH2ٰ*+//Yfm&N(*XbmaaallXS:g… ǏKG!Q$HѪY:kjj M6/--B4eDQR)+۷o+YHHHsvpp D?~(/YDypϞ=EQ>5mΝ;Eqԩr|(..*T9yXӧF\+M݆SڣG(u#WD \ Qjkkt"~8:u$J'53[|XWV"""jksvww *++h e(ʷ-[ӦN>]SSSw+[3?ӤϏ)U7xJb|||CCK:?ڵkzLL|Cd!Q.OOOQÇdgg[پ[n}MM(oHw*?")++[rȑ#mrJ?ggg&00pϞ=7.}I̜O(DHq[HII?w3g(&eddx訬HTEQtrrAEqfZ6%%eddMFm߿_Yh4ʇZӦjQ,((yݫW/vlRq166Ә?iYOΎE9sEeU6<3"@@vcÇ_` ^^^QQQ6IM'Mr1...,,BoL"zכkP__3H'M$ϛ7Oѣ[ߦJCظqEљ=>\7D.]?)ߡ||DIE[JiG}o۶MmKHSnڴIj~dZ֒ . :_ڊiq˖-75;889r6͍tٲe8vXyY{3?-&9|}vN[YY|Lavŵ(1lQ"(ⶠ:wnH=Qwsssqq1yN|R~?~\+QٰaC~~~ddT\`[W^b>;;ӧڵ6//oҥC _l-v;f̘ÇlٲE(-in555u9ѓ9sH-U*UsgC)6W cqqqMǎk)!!!V]xX\paC?s=B|6i)ds+(DHq6mڔ)S'(67Τj'LVDKyﭷm޼>o۶mԩ pnȑ~y7|3((_W۷oomFz;\zꩮ] 222ܶT) 6l[EEELL8K^^^k֬i)RʀVڎ{?~B OǏwpHEӷ@zzǿoD\ QEpDHE Q$"QE Q$"QE Q$"Q( Q$HqS]s=<J``ql#5JLLFE+E QF8p_~㋋EEΝ;1c亴W^̙STTQm9p@;E$V$E\]]]׮]kJh=))U4l2QtppPV<==E}nO(ZsDM[؆Zy>gggQ ܳgM Iܛs 0:"HDwK<((H|9sTE_)q㉢"=]P^L[lii&1BjOݔD?w<;Q|'Q"(USSR뫼-[nG;zpɸLypCC8(_^LզGh[(vSFRnCDQYOP( $uQwsssqq_0++KrssǏKue *6lϏ ,0y?ի-t瞓ZݻZ -kjj w$h&33Sj-=*E'ٳgʡCLF-݊m4ybHHXj/ .9V"niӦM2żjybsLZv„ jZȔ7z{{͛߹EiiigXSn}̚5K6&^[(X $H+;99Yر#>>^ԟ}Yn:;u$e\III))){{lNg>%Q"(Lz]V7DIIIΚLOOOQnmw~iˉ52DzJQQQ233Z󐶬lʕ#GYU;83n HoO<ѫW/ m={v5""pD %%E }||Μ9#?C!^^^7(:::*+&isbkeX4yMe˖rhݻw9r5gϚ:RɞyID1~sJ{M6(++ӧOhhhEEEeeeXX؀ۣ H1jjjU*վ}|}}^֭ c"7(OAEqfZ6%%Ŷ2٭ZMGioo-Uė^z8qʳgV9`dy1AQ!DIoY\tIZ<<| o򊊊Ih????i^qqqaaa6hͱdƍM,Y"V͘1CHlٳf.(vbIIϞ=[Y+--m.(#mݺU >#e}۶mRwm[ Wz!~ɕM6IϞ=[ZZVZX(mhZXs,H&;Vމf[8X^T1cƈQugggXtIZlMgϚ:f^Q7,R+;`QW^yEԷo߮,Ulۆ $H:sJL}||lۆ $@x'<_pAYa6\ Q=Q|D}޽EW_m.((9sFŗ_~޾Ҷm$ڵkM~/{{{ܹsM&-2Yh,%00pܸq0ɓ'i7)g)>>>;;7Q$jm(L2SѣGܪl6-v$L8p_~w㋋EEΝ;1c亴W^̙STTQ{,%%%*ԩSi?|rr>|N_~9 .22R_w>c^|oLTWWg!?Y,ԴG.(&֭['NTڵk4dUff-5+W:88/\?F XWmذAR}q(X3QSww^z=bpD7NvYT=<)hR5jřSRR|-[4ѣG "1Bm( 8P=pM<$V$E4?e{>x`eܹs:utm;Vyyٰs]hEEAzbllM<$V$E4k׮t^^\ܸqٳ}||Ln^nɓMxaÆy湹M4I/ZHDn9~xՔ;ٺuq\]]桡&wa7GwާO+***̙3--tɺNKJJuqqqttӧϬYw[+G!?U2--ɡ6Qd/-ZIsgŭH EYdd5,Ww/>\ [n:u{W{m5-]&777$$ٚ~&L`2e[ds'ƊńioǎٳL>Z>JFŢ"限Ң4Ck"Q$Hq#7>ȳ===u:7DԸl^ZZ*%ZiiizuuuJRVo.W D{>eʔ_]^ܿذO>giP]QQaRl5ʭ~zzkIg՚H EMmmm.]SNݻwJ'5BDV__bt&핕jeeeݻwRG)ݶm[k;i^7oV'M:9{&MjЭJZ+{YfPM5kIA$MIo|^|>kJh=))UY){$:yW3(h}'Mr˕+WJAIիWo~i3#fffᭅUkOJDϓ//b"HD:((H|_no ȸDQY7y/ƌk.byyٳgo0Q,**={vcbb9bLIOSurl26>>UkjΞ/c>瓓>6qL\^\ {FNZkmxgE29EXVSSR+z}nď;v DQ~B *ׯW6j))):ۿyxB011F^z8qB%Ko[qD|t#GۋXj}?669V>j" m(r 9ՆY/c=&~S>|7D{yyEEE$Q4y4 Ryp\\\XXΛ7O9Oi߾}b}5y4b`Q̴ܬ[nvvv/~<=)1cFzb~VQw6 }&zߋmEp$|ȑL],/$/Z}Dd֭RG)۶mnEL=zՉmڴIj~dZK.xyyn޼͉(HMZh"i?kγFirWb3Fն'gwe w( (J>rs}ݮbi饡CuN׹sgwwwe0%\\\ėff*77WY?~TWF aÆH`CW^\?O:^h|4MR\'bttteeeAAA\\cǎj~ac6(5kQ.5}f ggc˿t)S]\;qPQj#.>wʊa^e 8|N""(ZN/M־ҷeeb} ,T,(,'˻w)`gDZIOjV+勭NnѢKJ.}{U*Μ-Q EEEvOSC""(6(\LOlЫʵ%%:w6x/dzӧ/;8Tv&[_6`Mn9;_{+rqA~hnWoӮmB*z{_%H HDDGnTIO|o]4o55uɢ+ۻNNNRZlOR?UVVVUU>|x…:ur'91c(X(OgGMsExКDɩ-b}FlgkF}Yے_vxh"""D1**;PQQaMXSS3~xgg|mNNMLH HOMxx ?zfMV''O6>quKmN|Iѣػwsm֯_\ݻw@#Š AEp(׍^Y+O_Nte_7ޱNE''[!;uꔃÈ#,g„ wBe&C( Dqگp@EEpL~ jk]xJe5yΜoŪ0yȮGƷ]nU||bvOof'Q-ZH-[f~֭ƍsuuuss TlLJJuqqqttӧϬY4r~СjZLKKk1  8ЪqAAA:uկ~;ﴶMNNŋ ͛';i$+G!Gdee%$$ 2Dmʕaaa֟+muMLL8pѣLD\ hDrɸ}}_WSR 筊爛3盪K?wl{ݍsGFsw8C&|w$b]]݊+\\\/^`xҥOMMh4!!!r7qDXôiD^qdo֬YrkN`u3gd…bǥ(X J/C]ô5??n݌+tlܮ|lYUui/d?\5)lqTn(蒿Uh.mӮK[P嗗(*-XؼezzJAAh"- V\9rH MzHQQQ* >\4ζrDݺuMBуXe}f(V|MZu]>ggg&00pϞ=7qv'_CEEpD6]T*bRz`^^͞={111G1ٹX<-&W_}IwI?Sg0;::ZߦY9U,@ie.YYY#FO[s ɏ^|G/IűyĿ, "L.(E!::ZT[VV&T*_^XզH߳{#MlsZ- Z(fddGrDc߯,j4C i\߬E*-@Ԫ"O8t}&QHF0`(+~~~b\\\XX]zqfffs;qV%”)SD_<}ҤIy =*?m뛕hC[.>\7D.]0G \ QDhZ)2y Ν;LrM6IϞ=[ZZV322D]Z4eرcW41ą *|mEEEXXXBBeq};889r6%VBmI[vt㭿DEE;wNvΜ9~T*ފw}vvvӧOߵkض6//oҥC _j~1c>l5m>(?.UXO)6Wi aÆHkX Zŋ… oʟg.Q$"ZYѣ{/R6V6oެa~~~ppaÒ***bbbDK//5kHmJKKzꩮ]ddd :T4ɱ۶m:u9rd||~j7 rW[FyfL6lqZSj &Zs]2 @.11fU]о=ݪRM9:sE QHD\ QE3D$@H`E$@H`E Q@H`.(qGGǞ={N0aժU:dɒÇMgee%&&z{{s}I HDD)ϟOMMfh4kkkCj2--E)lnggg'&&2n_TTT]]-V 07MqqJHH{+W; ی?u8PѣGGEEݱ#"@@[?Q[bŋL/]&777$$ډ']ƊńM&/ReeCo$Q;bnJ㏫f̘!z!۴GFFK޷o8'R68k,˽3g,\PY%Q$HqK%J ,0'o߾]!!!b@@{Ν;Eeԩrsc!kۥ&EEER%''G|'Rٳbo߾VCi'3⻟_MMyˈ&}rhMM6oqcv\AYE=00pϞ=7c$EKE Q̸veggR҃,쭨hݻw9rΝĢNabKkmeNutt40++kĈR㧟~D \ Qĭ( 3bCCJ+kڔ{vvv^|||N8jX,((Dњn!Qn7Sjjj266ۓm˖O^# Jnãx35"@@"Qh4 peOz\ K/nln6n⣏>jݶ96ܭQʁohХK+'^>( $hZ)2yΝ;LҿM6IϞ=[ZZV322D]Z4 Ж-[&ǎ+sD~3-U)&zGyԮn-Qn{!Nf777yvlC3G \ QMQ^^b )zkgΜ);w~k&6^zIPPDGGWVVI7fgg;vL_TΝ;'v+YPTSt瞓ݻZ $ w|rQ̔Z{GJ|rYr!RE9݊m aqH)u Zvbq…-Yd9e``q?zVVVbb{!:":rt~IQ{˟+g-"OIIIbbϧNf̘@ѭ8QRÇvvvZ?9Et,>qnY|W.~oh5\9!s:ZgMaU!q8"U DJ4EDDbTTT{wżB?ǏyvknذAR}ɑ()g dyWWco3c]ޛL 1 O\av'ѳI'|7088bi9s @٤xQQݻ@o/X'J֪b{=p .3=Lazm8jLc 3&c3ɧ<}1L8o0ccIPg5(&z:Nz MzXWW7p@m˖-1dE;/|=Q4<ϣio1i~L1͋+1y/5Q|Ux';Is3/7rGQb 㠤ѹgYHѱޙ3gDqȐ!$X+;V^^.(ʾ1 iQpp,kr_Oiņ× ?0k"?Rބl2[n7n[hhhffrfcRRc>}f͚h>CUբeZZZ:)srrD}||pa>cs5~xY[sIIpzmG&ky&o8?O~i Hb]]݊+\\\/^`xҥOMMh4!!!'NJII)///,, =L6M_zC-K+{6ߕ7ڪ&\КHIp˻;@7Ѣ3⻟_MMyˈ&3=WWW ;WE%55Uyt(Ι3dC6tdDqqXa幒*-dמsykHq82>h?"@XXUU5h gx auu,++[rȑ#MB6U#EEEq>}rhM۵JbQ[.*$ Qš?EE$@ks]v٩T*ŤhgaoEEEg޽{LL̑#GLv$u:&Xex+ϕCGGVSӬ_3EPD$]8D-z]ιHV`Ѣҷo߲2РRD}Z6%%EݫW/'N4sZ- : Q#GۋSd幒*sߪ9gOڿu[}vkI(}Roã>( dͻ&scOѢo1l<G"rh  ʺ(z&}^Υ=lܸc(%KĪ3fȕUHfz}&QHI&k)N훬f9iXD(?Nؓ") ܹ$[۴i8<<ٳj:##Cj,֊he߱c644H'ϟLOy6OCѱ&ýzqPq2nj#F![3.n5k0.207_(325oUŹ?.ojqޏ/ofqy㡟=i_k+ۮzS#t01s$` D޿|"o^_ QDF^O }+q%9kcy ~\|?ן/6q1`p=[^nmkgqq0ӆuEƣl\ ˌ^9-5pJ6l|W4 qɛ5 _3=fd11Zch-2Z ("(ޕRqWA nYxWc/)7/|mK782hQO⤓wt7 Q;6Q4f&X~N&kyo>1KEӆ5Ա]]ޘ"OѢqQ?&@Qd|pPrҋJ?3.^xrcxh/E QĭD9O@M⻣Ն_\,ba hC_i~]~"ZHD.P~{1˼FtKEKp3ouUo V Do={0aªUt:]!//oɒ%ÇoV'Oo31nܸlI~exMcv}n1o/VF]~6$`%%%Rҕϟ?:ydQ'''궣J:u-~ LNNxẺ_~9 .22RH.Э >9p >o]Mcx-1N\_DN~iU QmG4EDDbTTT{ww`Q[EgAX#3bb#*h(hDD@EbŞ ҋ&(ݻ)wܹ3sgu9',}dժUw)wٳgjj*>P6aW{CƠ'>t3bDKH.v 71٥(Tv2WG_}էN/??0=e``P>хA>%ɱ52JGSbH@ZH#Ù /bD\LfgI/06EHE4E1'' E???uuuzwѧN<٨EשS'zCO8Q- "+ [6Vw/0a4̒z1t `FdsC+y3Ǣ0f[?U((zv~L&Z!Y̼,r.\/$~Is,vzyi ((FGGS#5(Eqɒ%b1c4jEZ477TVG"}BJȿ _dc0)OrScB8/HV IW}aB2ڧ0Ί`tdd85%D˸tcVfb1#fCt=YLa=0edz'dKF&E(<EQQήPc.^ <;bչsRSSiʊԩSqƍ^^^C\Q=>\X566^|Keee[o߾bg߶m[j>}zvvpWmńnJIְ|<E+W ܛ12/[X2f& /#&e0-ɂxF+ABI _u[h-}kFdK`FdːP-c#Y0&/a-Ωɖʖ%[.3o"&7[ž1/&EE?Krr2-_{3߱c :ԱcƎ[SyyyܐU΄PZZZ `>/0~+.'峥-%$ψWZ@N2~nigxB*z N>|Bِ)ϺW&?I#PAQ\p!-PRRӹ:}tjx"bJJJ֭333>}gO>]{Hh?󼼼o_.4V8tл΄TkW=j(~xܛ)7Ō8+~{aa]"wB(X(;E4E133sδjaaQ=+Fsuue>ƦIHH\pu/*BGʺ?\e3lڴZFVLJ0`3UYYPaM|QP;EE%&F 4%4VdxiyٔlHiO&L%>@QM&+WHK޽{bzKHH055mݺE|}}E:՜( *?TEEE:Z*gκSٸ`Eprrw---% 6k֬ `>9Y%dk:8Q~cR&0v-M;r}_]Tfd7"h"ĄZ디PZZwmu9:00]v=z syyyZ ܡCb(3gΤ[[[FQr,8nܸ|: LWKQ,((ӧ 3]uNfV(R{Rj().#ڡ\.)jIAT恩O:v's"hbFFFǎkԤ~qZXXlf:g{ػwouťKr↓)Zb3 oժݘ1cj"ٳ51% r"5dR SK͇Rkڈ߻ۏ=k'X0(qJO"/]$%%%>|ml``n:yyw ]jgO]= Y+dZZ(ҥ ѣ5V[[[! gddTUAA]=ȃ Piӆ>j0(BؠIz YHz =aW'ЧM?L[A 5Ӵb EРIMMuqqa 6՝?EV){K1I[OXf $HѤH+f@?ٟPh"dggFFFb)usP6:|#К%A{#HK1DHy[ҙ3k+~uVF]YGJIm֡RXYU(l>_maUDĨ3縅ziZ9҉їejvX<h"h8lݺРv DUU}VVFFQf͚mvnnn999"CQ $68p`'++[Y7oޜ3gz?ߺumii(f5{G(P?TD&MjժUQL'O/̙3 63U~Dn=bJVfe>11ŋǏ޽{*w 6ҋ]^r%--+999oߦ X NmFGGs{x츕xRRK._%+++%}AB{ffiLMM2fu… 0++Kؘu~$2zzz_JJؘ۾EbT駚 hnnNFDÉYK=)c ,++ɽK<+2YrK?Y6m$|#N(BQlP"]\^zH@c[yO (mo2(IđR1ӢE)S-'O(UTTI&QK\\[e<###~ NOOzQ䓹|2}AhIMMm۶-T<==eddPù>^eՓX*K,PPVVV'm֬Y3 (//|Z#E( JQС?}k| 5C6 )edg&MʖIZ풶++6&)(JŋERgggFZTTTh\Mx I-OFOO>5\uuu%аBIIINYa^^8wU"oFx 0`$… 鵦p?Yxy>Bт.]W8PVGUUUB^r_|?ɉ<(@BEq̘1Ԟ5*5?$o  Ȁ^dszmG ;9-tU߯<1琐H՛M"2GoI>yVKR?֭[YE鵍$ܹs;bTTTEʼyXJzaÆU6qnU+"냌H;k=/amfz$E hooOׯ_Lپ}mA4R_x}YL5 =t|,CI1*`v8~xnX ԛ*D|U (>/L*Νjii=zDGGsqCtr] s)))iiiz1E >N\EE%%%VuuutD$}*evrrw---|^PNPA"Q~ȹFwwwۗ.y '  'XRFj_[?2?b6+@Q͛oΝ0ֲeK˗/gff/ "Xy ]صkW'ӦM#BCnCcJKKΝ;mYbnn_~I{=L:^_"yCLLL믿f(RON-vvvt<"U3fǎ+## Ʉ C֭w]{DDQ?I>Eʔ)SԸa(rY6UN@#KFQ“%_׶Gub:TW|P+b?5ӦMZ۶m۪U+%%%;wTP?~,dtuu#K.DT9&baa_O"eƌoY'<ݥKsVKر#5||EQMxHIIif޼ym^R]F, ;88[gϮwdB !:g(6޿nݺ~nEqh҅ۏ?_+Wjnnnu`hb1g3x^R^1C#" رcvܹqqqԢ|Qn [[[4DR'StttŜ-ω'ؐ܃ϖuaALLLrru幓sEԩSl~i~ʞbۈ~t钔Tc¬&%33SLo>^|92y%φ~ 7n862=̰q?<999VUU-Ka3!CfUN,]AѷwŰj!"LΜmhh_kn̙Z6 *߇02_ۮn?""1VP(pĉ"_cMMMmFqIE}}e˖ѪD$4hwNNΉ'7mTݱ/_.RNXG\my eK,pt͛7g~Y } Dƅ ; J0 gX< D-[TvՇ׮]6~zvv6 ^jnn.''f)Ott1}vƌB;[Cٱ^4AiKyyŋ{xxdJʝg~~>}G///hzFkXX_q}u)Scq}:t[{r y$>|7$ bΜ9ȇ/Rفz.͚5k׮]-,,Dn;\Q zPu +'>ad!%my (%~N"O`ETͱc ЩS'eee6 vfVZ3Vrrr˖-u\KN'9ѯ'E`L^H:02:3 "( ܹ31//V7oެشŃ3P6χ2䃦%RVz~+!^EXc@QӳgO3==]~=I^IR*'Ng@Q`EШ-% c!iWO+N"I/D0`ihhx̜-[ ~*HcUY.(Bh\<|IGH9Kjsj9?"Ryk1(^G***{611IiQ3Wy "iP\LdA!qz(!s/־d{+"@Q`E9K:32_2c zB A "+"@Q`y)"`Mh.c5%&%Q--~Hx?Έ%9d2+=(l'++[7oΙ3G]]]oݺ%7e``s¡nsrr$ɕHɀ(BE,W H ]0o[QfzKbv)X`E45lmmYҥKY-|P8acaTTԔ)S=<<|l33yg@tl"ƻDM?~<EV`{A~$GsټZI%4A(ҢKB DE4X%JGGGL<555%}7h UUUOQ#Epռ\v---ݳgT]Hff$v:w}G-ZT{6%pnP!Xl@25ʫhlopPA?JaJ^,dD9sHII]r]&--M?[a{{{{zƒE"rZӛ(oɁl?V1潕%)Qe (*NNN *k3x .hVcƌرci3XuԩvWcEbggWѣϞ=۴@Q x!~kq rq#Jxx87NkLQ,](w*f%++KU:͚5k&\GI(n*۷o޽;7rSZj EVWoɾ,G cjN)IzYf0g t4D>z'`+۷=z5JhQQQmrss٪7vAfE 'G W\IehhX.TY'ex6-UK.تUpcRUU(ĉ#gΜL5r#o-&AQP'I.D΋$1SZF.CFڵ_yc!!!BɑV 2囉U%˝;wޒ|,֛S%IͼѸ̛7V/_VϞ=;lذ0H`PPmֿ C0qįDI}ˉAF{tA^CQPdV9)㣨.{W-i(6,hǏm֭[Vccc'+drrr(\"Gşi (>/L}(thZ妕BDJpUɉ޵(~VKiʉl_TA:! s`RF.YϏ_3[z"sLb.cP͛ӯΝֲeK˗/gff/ w/Ȱ v*dڴi#r[ȍp(~BiiiZݹs'MVV5CQL>ZBCCknFl<nj#cH2ς>} SQl\KT-܌pt?3GsA}@3nފfoDggoX/ <~%?sڴi\۶m[jsΝ*Ǐ%.}dҥ\H"*Ԥ~qzXXX׭.T6m͛gkk+FZZʕ+5`ܹޚ={$JQq(O| 3E |L^%2ȗ>oSxmZd򳷨 tE~Xx@Qcvj)s΍KMMeeGr3YڊO!:#---(6GV---eee}}}%lus'S'">57M%=KNWퟻ999VUU-в$!Cp+YPP@QJJjРAYYY<)\MHJGlKT[9rdQ`A:kFS&g@T.eezL /)a5BbQXX8qDȦ6#F8s$~dddjjehƦ1114;''ĉ6mX˗/y)n'#ExT2p%KT6hcccȌ3bcc[nQ#ץ-))Ύ\-;;_xG&zAHw///^zQ#J IҡY< Gnnnv(b,=.p%(U(iosss^jnn.''86P䕒1?sH# DXB[eoQgo(bqƮ]um֭" )))ڦe˖{^p!Kmp…={w|:gȐ!ϟPr}ihh\Ka\zŋ埢 >ƍ, w9s-PC_*;ZΥYfڵ߿HI1CW9 Se*N&gAgETBn?b8wgD?i~ >$9-%eu0W@Wbo=brرtIYYMz¢]-;?H HNNnٲ%>IIFAƠ'{>#+]xy脓'LhqL%ni$%S _%".{K/~w]FFDxxxΝyyyyfEEŦ(('ҷ>cq3E{ 0(d73`(SQ,I.}ufd{jS:V*GE0KL|s~D2&I`n6J$<Ps#`"/$^`mmQWyL5K @Q+:uEgp4Y_@7hXPPШbKס?nm7yPjlq0?Nwi|"9̱en+iY!1LJ̌%(4rEرcZZZJJJC 9~8ag^ɱݻbfڷo?zRlmm{!Z[[x waG\әB/N}W{T=Afog0^C.!z =3y2Sg1 dʼn>8M~pppr؊@-|+_+j~$@N b(!_%o+Ph,5\uuu=T9|=)dddXx< -_TGޔ"xc>1P;EiIxp̙#x,2Q?KJJJ _dć{;֝Wo^mk#'mfm==W~ߐw du?!- CUY ~:t^`! s\eg _2]v7''yzVYD!NΕ߉z8efE3({]$g _Xz yk @Q(Zrss;wP#AVVRRR\]]SWߊbAAAmh5;;oʤR&VT{LerX)Ei9zœX/>At=M?g˃v~N$ UBP3mɯ_aW{߈#Zc/4 |kٚ{Xm;~6/ 0Mq[O%:-jBb-_֎pWNfg},wqtȝKKJ 'tGV+yW'&\Xߐ6LA$V@V۴iCoݾ}kdoߞ#~vCxb+ҴsNnsU9+OaY[~wRC9CQeqB5׏phʞ@6c/ʞ@^諸:Q^]ϋrdf .uL]mt]Wffnlו]m ]-.WEF⺊}]Vq^;M><4\:hZd3mҙWֹ!wnfGXψAub@bXR1 .i"E([K.ȈۃHġCROOI-,,bnFQ蜡(pJ@|33ܺf뒩e3/s_6Vm͏VqnJj>;Kw[ḙVs;nMn{.9ynw߼QrǍD:ܼć9iϟ0_.you߭"E޼Oˋ5~>\yO,o_w2FitNoWM`5K'nd]'7;:G獴%%:i2-\Ϲ<̉#|Mt#!OwURFTcX]",VU,ĉlDgKKKYYY___+Zl|.*)쭰6ÇYALL u޽}ǔf|e,5G|Z 2YbkSm()~V{erۇY]titCh-Đв7eԜ{̜ģ-_n1c.sgwj2Fxt^NZyx]̧.ba5~| xeeuXT{`)+*BLH+2#٥W󛷌~hW0]HkAKH?rE>6iii[la54mLLLAy{{8qBQQqӦM6VVVݻCBBEKKZl@LJZj?PPc))tJ%&&xyy\|HgEE(9O7Q0ڛ;e8dV 3fFaGRpܙ/<:}Fo|q^=Fo(+{-^A| ?\Ԕ>M[/-.~k4oKqqԴy\)`ĎE)i$UDo- =̥fR3dȐϗw >|џCUPP޽MZZڢEh.]lٲEdϳYXۧAgyO5 E!zePQz\#h '>31/5:Xn̼nY>m5Vl]-z#uXAukt[˜vr]:}ˊ9GV_:;yLǬhwj0WTʺ4i}s0J&⏣τdŤtm|Ծ#FDj(>o Kyڡ(@qntߊǜ?[޼,90~Oi ټ8섌(=V[s5jU]WuvϏ+Hc5f?̘dnk+;zˊ /p':3hohp>IK斂좼gOO+ I׶_v#Lֺ׶_Ë6J2&i υYDzjt\E>2P6HB2i5n?"/- (0',+>3+xK滚سm&?:=B-QMJ;n$8B7T]Fَr)!~tn{4yˊ&k%vOq2p2{ӂ?93tw8a cc85L |V@5"58پΞGuWCգh-K}hn>#ڍb\j~5p_5};RZOXu<"vUwUD2٬W]_uuE]Uz|m,ڎty'Gi{c~0"q\(5  wȊ=Ӊm8sʺV*%gO ?~\](ԇQeȇ˴ĘQqO  wAvn~V7􎤨ظNv濏:;{6Ƿ '[ݶew;|.J! E(lP'ċk+ѾZ o kD^#7;D^MI IL:bI 6Our)w̏g ^1%%8=|a>&csEԊ;v|!ݻw˗۶m>boo/r+??_(C;wr޽MLLΜ9Hg7::յO>y5E ݸs@jk5%?3 kjFq{>gB;/+uX!:Sݕw(?rC&"PA]s__:ÇȠjeJJʸq}B;{+77w׮]ֲeҪ]OPTTddd$--=|///WPPf͚͛Z^99P6˃}ZMsowm8+zjɝh]vQfP^10]+FB4M j~\S\(ZݻWƍޥK/_ n߾''Oxw#""$?i%ME`>>A!C딚##&yh46ɵ©/ceX1 fǗҘCr^EЮfĒRBE -***+spp0 UUUjyn…tȐ!9{:{߾}5y>X'K Eh=άB?*Kl^C>EyTq|2wGoaԹ~eA9qN8"$7LS|.bc ]\S,3(P?k̙C2ى D+Wŋ5ܹsdee55571b(ɒBQ`> m6˷u8J; ?yӀG> g 9Ϟ2bvZ^RoO\ W^|㫀0g $j/-.t rP`(ϖ˗/ӯ~-טٺukjWWWSRR7o^TTTrss;w\{k͚5͛778b]-)EV)mг/2 bӒG/׍}jtX SZd#lNܸ|9z}}]=V=d:D={m*{SӧO{衠wyyyc Рmٲ{tym֯_O;TRRj֬_mjjM]%]vmΝl |$E(6$ !358!Vx_ݸ'-?eo8YY4bImf -SP;;q򺝹ߞ#3Z >0fjnz&>T)+{;5t4~=daqeu#J{j*^dBQ@]ԋd| =E }@Q L6ʕ+nkk+O8q޽" +_ŋÆ ׯ*sssرȑ#G*** YlFIIɓjժjM)񂂂-7-222eѢEgjj*l3zhjcѻJY%]l}d͚5nll,; E(4H7# 2ySqRNfX}Ϩ{<ݾ3gZwi.Ǭ5=(VF#̟kNvsqEeF!Nmɖ/ʗ{N,G>qbG:mE+1Džo^eÜYWz{))cDEiO!i?C-(r(B Q@P{yB?~ߟ{ ɓ'-ZHMMy<''GU(JKKs-222.]Z߿O9 t; (?_;[8;02IDJ@;Yb%f3ﻬJ }ٙ7fޙwׯ_Y/엓}ZW^}1[(6, [auܸq}.\xNfS*^)\YL1Q",9i̡^Ho퐒⢸W)]%U2]=< '*Uz]1ڠ&%a`F  k(bU5e|VSS/_C={ _ȴA9ipqqbG;o˖-{}WuO ("F3>E`bc%#u`,>BX] tjW_pWqG:E^>a,VPrۓ8*/}<֣b X.D|N#Q" lxXEc6d?v QO[l|I AJKѾE~n(X +> +5L=`,3ZZ`{Mr,,,,NRhxVLrA]=Ơ\%U!Y}W#?>$Ҫ0Q9s$%%m?N Bd U>q?%Y9NiJKKK;(fff9sfgϞ i) gcǎqB^*RO>#("&-+gjn!y6 T*&Xݓ(vr/1BRGX,0P=?N>0'5zZ_]w0]ac\\\ŏ?3g./\i amk |Uu -A׮ê3`&XO2؝J{2,.o TdA *aZ  ?r C9ۇ\b.a5;(UP]n樵#QI~]L:rãëW /^Z^S=Ԋ[}X|auR>ʯVWYQ=JBެZZ4(kGWȊs3J {,,,Uߑ Af5"x%ķbp?H2d0+}7}gp jcU+ *g x8PC jYD|v7oիW;DO:B CAVTT0\" h 266nmӧO7mwtqڕ`bbDܾS*,,l755;_CmHdReX&XI@B5{յHIeu xDSZFcl( D@%N]!gm@{W``0X-N^lI ,2<}Gg_5PE9%uGl=i/'Od΄+*P yy*l~6}ý٭` "F]'lP8_V GU3"uxF(Uo`u8<%}f2(brpp i;k#ٳ#)`>}X}l--- Ԛ5Yf 2ӧͷ HIIU{{{2"SDCBB8ߧ+UUUK.e^)33 ٚW" Ym1}wL) s0;FQ (^n{lMg̭^͑Ц|3wz}5Ⱥ(^X Lr\\[Ζa6sXnɼErL'Ig ބmkW׶ T Q9 l7֫&~^! CȬFۣZHZW i7$H_Ts!Q=Ȩ>FU f僋I@~_T''PaE~1b[H=>|CW111d;+-FFFч"^ʖXSSZvm>}DDD޼yCPʢTTTO֝O< Odɒ xEz>])FǏOKK#9"SBBB{m.**m۶ [3ckR||| "̙3a;5cvttܷoߤI斐HMMmǏ/_++W>[iJ.ȑ#g͚%##ڱ)Zjٳgó={vSN)%)… IKKu):d9u'cebB =g[]^o:7ϟZh6i5ֲU#y7YMZ?J:s_["0ҁy bd+XF|KRwVK1Q)0='+Zジ욻wd{UՀS6=xvlw%uS0 85\Mh U 傽@&},mrFXa+-"VWF;=w"^ S2i(*K-^jhFYqqN\pW,Š(d Dx\/#d:T(pTݬpݬ^ /< Lf2R^Ek3i]ߛEflLr;#'3Ix$ UrQxCEMCc(፬ [,}< E,,,)Lq.Xq‘#&_wPGM筶˭3{(@{XIa(Vbc+[}Zƃ?YJaTW=H#B beN]4)J7~TMPHG|}zr=K$09p0 ONGL۰JYZdҐ3X%, CXB&0>mQ:Nd؂Q/L0Q ŞB;Hc}EK=ũ&ڌ6BBú_puiˎeY-;VScמW[ڿ n~Uo_U"CPYtUٵUoT<(Cya~NUkizv9JkIU2@"/VU{#՘Ѕ4&>F! 94&d^`/8 YA` xӪ 3,׳#3&XXXX(b`m=zL`0ߤsRi'ZL5.Q:)3J;U(],otVa^*㑳?a2/c-mZ z$XXX?:7'÷ ы".C~QUr3 1QD+L{KoƊ.ewD/'OpZf8mkm͒U3Nh70nDtp+ UOT_}61Qe Av 8[Foy̑~musp*dX0v0墑 by AO*aaau#Ԃwps7 &߼͞p7 @1/vBQ% bVR@ikXK|ia- U3C.}1QD+L{xL?s0סMZ6 ̥6cmxVm-ƹټk@" M_vTvΠB_oAI[$PbndнP!tpgcE*'َU}>?wO WQ~jJhyEM@4Mҩ@# Bd]0ݷ㦢ES:[i1}Z?_jBa"^nfsI9$-XL5Rޥ**БCZ't[SC~yKTF";N<<פ}Uj@\%z= tت"p"iO?p<jԌ%RJLBA_rs\頸SG68add$sS{ba&\o9o0lTq02z3O7_yݎOx{]>'mywZ%<(ŭwN#"'*F(,G P0KTAhl =F`NVUʕ,~qj|RB~v`ɯ9p~~$~QJ1QIR|fm3f la;֭['NN/_ގg7Q{M&Xaʼnh)̷ƱĎ襖Vz܃YKrM]dx:gx!zI[0N趱!2vZfcJ{/dX:(/wדz&|x\E %VRI)C=R5KX: kS^SQDZ~f/AnyR`DbPR`VC2{0 _Kþ0%˔O)"gB'@}# (kۣN6,VG~PFd}=@)e-D|ȑ1<**hbbr̙9s9D !""BNNn.]>|MvYYYxk֬iÊ+~Wxmؼ&%%g=~֭[3f̀_ :tƍpӤI aÆ,O.%%5}t8Q3g΄'󙟟IKKO~xE(b}u؄;⁑|cYVvDZkr[sqیe6 q EyAnuSҖYV`.ey_a!a>jqٴ8 Vs}(A.9z]Q Zx[!@(mGަX(x\ oͻex8e7S=]GD%8C|Rսܨ][( }ݍb `/\ ,gb$rc$"BLtaܭltqq7od >l0]FFiժUχcǎmZ{***'Ntss+,,2dwł .|Ӷ{:t(yȩS9[n9tlSiGɓ dmERR6&&fݺu(bBo^]-gmH+.z84)}ϯnYKug-}0{Ih=٥V^"ezSҖ%zFW+]ߨrsic$))H-«Uۈ"ynI+;5@Z"0LK>`O4 D&3W+z ? sv  <Ţ蝏)cm9poDY-$de7#7twIzZ'"6E@' A]E#rXH$ yhSo3Br.fJ?h%U3H#J|i{GAmBxQD 5 0JKKYi4#Ik{qqqDo߾-{9%.. QlMm0ȼL&ْB$''9?mVVyec||<7)?`caa!3.&Xah%D/|h0hK+-EYKIhN>۰)b8 Z4Puv'|_?558LX~eIڢ%m)M휞tjޫ*9]Aɠkc3vKλxvl:^%,ReL 6z-! 㟸u(9a\| CQ3 ٝBǩW{*]xB7cj 3q/FwXSpN5e8hxy qѮyICy؃PKT N[X4(v*HAA(o,"Pha!Uw)nz=@nY(QzUjfU9 hrQ ^Ĩ&XX_SYY`۷۶m#7M0hѢ6^eeWa_~--"_lϝ;6QGC Zau?rڊҼeԩQBBN-BBB|IȼּvL0QAƊ;RwtxQԟDV\<[7EXb2iYՙLo2 :sk.^gUW nz G$m@. PO,-*HS>%*ZCª+_"/tU+]/SԺ3k*Z 鷺^!$pp13Ȧ!յ[UƢl-aOw0Zhx3X(b$999'˗sIJJ"_~ yyyIK' `m! A=9CAe*" 777c˻(6yʹN1QDNG  R?9[c2g?+X lp+sφ䈇fO/dgm6q Ih6'57 Z_qΞ6wcT^0[h2Ӓ(./v@ NdBE#nkkxT^A F>g׹3N7ٗ­WPaT%]A-$f:F~"Rp?& $3BIZ&J t cKP$IB0=[m#Z#Xpy~."];ߜX(ba5F1bD߾}=<<Ν;j(2vo{-2VOa:;QT'' D}O:Ek$!!Ar .pL:&`}[D;D /P7WtF 8ixJWIPnJ˞8yZJFCjc#Mm\O\}1:K'/c5n>FMy~oUHo2u^>-'u GbMb utb٩$ '24҉pW&֊GOJ>9:}%鷦 roi PKM L$TPQhW*_9j_^k_^St;U`}i w0J)ˆnG}pm53@pؗЧE6$` p0i`,ODVoz旅A^ȥZ'U=JfbIbniUh#DDE%}-&XXbbba|޼yW^m=uǏ Q4hk iYQQlr劀EaaQlӲMBLMM;~ʤaTWf&y`{u"^wH}l)7ޗ!aT u)ow0pKlr?&#z1t6\<<<>S}]ywOc1c"<%iKJ-/"Kd±誑Uc({FH>ѹGV)ÃX}PW˻`J_xkemWG~Lee~g0{k62kjB=exʦdWQX:ss躈/΅ 15"Z7T`ԋ7 i%aO03lBv:(V^bv[$OZɌ!6uRZ&cvD!l||-EI+l;.ɀ' _oK ` ,LzHH?{"3HO>Nnyyy  jÚTT)lڳgO uS4|p Bo(b`S#`9)G-vNu (!gY؄ϐFSPGa'/zohuKN$8TU I[J:{[ z{ڀwN9.:2efP uz|P: Xv׽{@G^cX}n&3ZݗU yLJbITT"&D˪*YS5גё;ݱolto;<f8|PUWS R 2ֲ]l ֡z^VZfs9v3Wbele+LžʯxvOCm/Rux"]z&KCxJ< rkX,Eko6/ |oxݖmVB (B_ FPJ?1c'Q,Q=^%(TF,z&)#}ڏښ*99?U ͑!&2AD9ή"VTiio6b}}C-))ipEFFĐHMJJ EGG:tlz*[~dMM6%//OÇbZho^pad`rϏ?2vd#$ْL]5<ZKSJR`URRQ /P ws:i0L.A9yQO]^Kݱ&f>j .2kHGS /q(rGUgrN]TUƕҾVVVZQcuG~GU9i("iKuGC*iּvR}_MUUe줄 䀗vO />1:J̆(DHHHh޽EEEmֶbkwlT*oРA$"cu9s&lᱶjcxmNZ-NzɅ +WVr/ڪ:Z~YAvjD{gMlWF7e%$}F'+|UTTeF0:GZDG1Ȍ@py#lPm#"x.E`,nrom#޶FP d^l >ePhAx Oxs[ּI9a /)I ^8QO[P D-tD D4s!cboT!#͑D0R2LY}" [Pxn;RZXq@Ϭ{!(A0Q҇p譌"^.; l>oLwoAƊ'vz缲y5[K6[L^d6h/7Fgfr+t0-^D\6=PTTߪ/,>CUS;IwUU_+KٸRqWKVwoSEmnjJZӀ6FltgOP^sx2r,EN[Was;0mB&-ݍ#/i7*0QDEL!Q#gŴN'QMƊl)7viyϮܲ3巘k3|єEƓO_pi coh߇{ov3`8JHnA1tOwu-[q@ #?#WdV_"op tZ"PTȈɦ=gӪ4E|^b+Af5"ŧ’GSóHHl%oI8r]]X-ar\qiD*+ ¯5SBS4O^.666x4ŏH9`2dҐI$F3pm=>`7(x`{FI׉vL|ӍoΞҤ eɽ|0QD+,X# n鑔b4JQZ{=ߘGI-ލtVxQ}B:5Va"2̛$4dmc]S 6w+%iYMYL$^é -~4G&FWXq<*-SXį>w8I nߎJ/p߭wcrRD>|,g/\ҵ7npW 5ZZ:FưY<#޿? PQSBC3ddĐSgd_격& йAsE՝ Avaݖ+6&ޢ Ӎ&ila@)|~IfTkU\BDZĆF~n@-z3n** )pE$}p />3kL0QD EH5u57 K<.uRy`~sw^Ǟ_~ E>rV3t!6-BVIj6.~;/M~ 4iMBJ^v/J)xV) &/~+O. Ort3 }U{.0wͣif.}8}4C=FK|<~>rTu4Q\]6B9ur7 Itς#C/)Nʅ#DI9+>IeE9+n)xL?s0סMZ6 YRf{ܫ.~r ]Yí_=CM)o=,j;+q!quy0{%o\JFY7ȱz2IZf9~%bWd]N>9~N"1O\phB\Bd'X}|߽)T542102~P5 /f,u$K~@L:(¿f YW s9K`Eq2F};Pf]:.7zmkOO'SBsI2Jyʪrz,%ej),yYXn>|Cc Ւ7w^$J<~C wJkȒƊe%deClߓWUgFX?*bIP{y̖op*#L G&~4r<餅678l[D_y`%gAP8좡)ɔdk(9.ԝ{֖?.LMW LՆc~|VZ8tԠL5-<V.PDcP 2mj  PO ZzjwFn~@?\OfPMޥ>Q}ADU@}A!"}gDbE,TQQ;a|f͚,tzZZږ-[`%K& 7?>##㫽3,[ěv\w^&Q1H~ur 808u .ӧÇT*1QLZE6e-Z}e?9 jk \xNdSc+Nپ2}y3χ}z=t|+ANYE$vSL+;UP-T{*NKO^@Bɟzyɬ)oxo+qs?EwI[ 't~Җͷ= 3W z)tc#FK=z4l@~Z^πW{#N ۣPoS,8م 7d Ih&2dIJkތ1Q&Q~ >bWVV3r֭'NH˗/oGrnΝ;p`W&(ɂb7Yݮ6+;vw {j.ՌwK JjHY9o{PN{V.O=Y.j87q3rP0y 7Ŧex91qHǦ HE9緲J:\YjjjZ b2HAx I6{uT&ZJ.ᐂ^s3,Ii;dxMJ6 8r8NI&W~tᾹ#̺&!%("&m}}7{Hf$m9iKe~珂Nsō+VuG"鲂Ɔw )j-GVvYVjQ)tD旅E_5`VENT $Z" Ha\pd= x4B-1+DUzbT/UͦjR BP|"0Enp7s?BXXX_Ʈ*f/R/(4u4&]ˉ3/F7dBZ!2 bL"_BZs}"'*//9r$|ʎb69sfΜ9llg={vEEťKi&]VV5kc&bŊ_m66/ly]RRkKpWӖ)**Κ5ksj ՒxC0`ܸqٴ["&XL< Ԣ_/QD^_jd5`UHٻ1}zEc7o#": q 6x37X+[<߆3EVה_N-T=(z?YXs+>&j]h:MB7OvCK˰wp; ("&yK:;']LY-c'\Qapfi}`HxD#2ۦHT}W\yCt*CDҐo^02|QSPc(R/&!>g B Bi}IQA6z6UՇ9Th⍞% ®aPtŹUߡu(Yvql?'Kzg o-*GD?Gu58-iqN,&XߪÇçlfly&]@@@__aÆKFFiժUχcǎmZl***'Ntss+,,2dW݁NUPPp֖վ"$$[`AAAۅ(fddpduݺu 'B"%% 99 ELH)= Ԛ_/Qm}O9j9YFiiye|Fneu5VnsL_z9$msԷղ{)id[e.o(JpGP܆0+D?PA9oTVVىIZsW[x-5?w鲠ء#N.]Iނ(sҖHCҸ4/v=qEkE-i~8'j[BGprJGt$;M.}=A;I>æ/%ݫsd'205 (** UBDBU7\ʧ ;+A/IdߑoD+~Օ)D ,XZ*--guhÇOOOg;h'$$۷omFn0a!uѢEmʯ"5Xׯkh`_VsεmI_l]bVV:f̘6UA)2`'_Unj+=W~$&#v[g}bɥP zdHNȠZNX $xYACG{9 u_$m WT䊲|7]_v#/lyV_ %j)K U.La_sr,X}:JQ *1Q˗/= _|:k(ߟ 6똛<11mI_lP2228G 6 E]]NL{[;v5Jm̘1x[YÔP9-J+D3LPM)J1lIj :$#{X|"|#%oZ_zl^ATFsw?C.o?y\j{%m g À殞/تo'f/{lHH'Qw^̄1QjGH^gm7>}RSS}%Y"k_J?G" e=Pq0;)"1ntmx&L`t%&wIfȤ OE%nd zJxM%^d"g0[Uoht8 v5[On!r~m봪1II̴Q$֏+=zĜ^* 3Npǿ׼7=|선رCBúhU5Sl+V\KShƆԤP}~XX="ig|It/j56esjRi~p ,+L5L8F1bD߾}=<<Νl5j|wqqaAȌEaАu7*,&ME좱ŀ- #X(**EN:VDwEi{^;+,K CAyywvwvvzv頚3"4iRJJ j _vmvv6V]E'Yd` xzy%<$|hʼn(o@_WV ]tfK1xr.aEc\r(Lh>Q? av#w~ &BhN/ބ[jXSmm]Y#-hh-'MGHz]bkD#_Z"Ίv0@&2D|u;(5MlmmVQ444Ν;ǰ)5zlFV3!X*(N%陣큠8#G{FF1++ *xswg4MΊhn#S\Ã01.pYc6Y0N6[QqYgP]̏m7wIa1-|'~N9+$&!{ZVv(:<>ձDW[[u+vT6=c/=O]8Ш3C/y(T )qU$ÔNd` }t9*+xzz/v///e"@`X~g666ǰ8::̈́ kjjtttM_5ñݪǹ۶mc섑jC9,x< ֭[Y03fAj{+[}xu%cIHۨ?Jʠ"dHu֡</_/PSQi:+nl&L[_?qSǁ^ZXhq9} y -3* ,ww \[Ci;{2yt(>YHѽ캋^?bKuH̜ /I 9s7fWfe$!Պ؆ΎTA"ԏw*?nqDN,z(B~aΜ9̂j={̙3vuKNF4f;;`TUU&33̙3͛=/U,kjjO ͖`#nܸXKJJ^aggWCĴ( vżɎ;uuu999謏'III+[}>\pSd.oy!C(N"GU`(x6"/ TT\? Cc!0[  |\P3Ud߽}wc1%oZYq!1 J%%#hsZz槰n]q~:o56qDdybIae2yķ߄oίs!k@%98*!6jM{]Kb{X9u%*CEň ;vl`?>Ct{yyyMǗɰ٭Z عY&︟sϝ;w֬Y۱WHMMeSL?M###{oFc3fXf ymm999---=V7YXWZ(B^QDT 9vɅ"N۷8"'m19!*ϭn|Ƹ Xfq{ݶ[}@MNlmWy m|Ru3;cmm!FTXi_T6=!"*.zZӋJ2gD0[Wtg9iQ+RrW_2º&ky@ _Nt-~I*̼RJ9WQ &TD\zMc+y+yE@Eq+fLƟ^@(&Ίu]r+ Jc\%srqkA]Nd[ #ihҿbm^ﻺEլs#IH(4+>[AOD('橑X[]FVg?ljbJS@xr"Z"W7!5ہ4T+jvqpT 6 "@E2ŋ?Z[[q ϒ 88YI)8 :+Q[m,s_o{K?*ghu Vj˫9ҝ Z~PL*H?}N 6 gϽ|3OC!!uO"2c'a4j;Flr49F'鈄C OJS̺%D 9a1Бq6|ת(B T8v{QQTQDD^aO{Y .R k*#6\A,>wt3Ǵ.Z7sv6$5.q h_]ɚ)zjn؋Eg430jj T4*=σ|]dELٟX[8b3߿uH ~2š!6& Nċr"Zb=Sq \c8hW.**E(QEQSS߼yl F xXYI(b'(Г_ͫh i*=٥/#ȫrIHcoJ8FGHz̦8^Iy}/ *E(QE1##o޼l`0&M*//T|-cXteVn=v%19~1a<_j"QSYsY%G4gn@59 p88n1lYT6I5w}ݭ+YxtRul}}C1!1 V+ڛ) XxE;yOqnKN 8EDʪժUڵk=Mʘ(۷o߹s78~~a6u_~rJJ fBE}᳢BDDdΜ98 4~H炤r QpLĂ1&'z?}n]180{ )W v@ҵt-w_.o"1@Kl>+ ]]HQQu }OcoBK@ "$ _/OT3$znGbP͋s"I'틏\Sb XHE7"huo'c8GEE-^Go`vPRRr`ߺu+Îb<^ZVV٣=l߾}ϥrʔ)yyy|ثtttPI$..Á!133ۼy3ٳg*x:2E98Yq[HQ YX\6W/۶&o*!uh`'nȟ8"^׾(z_zcsIdж%D").!F&8v\OLB֞BkQeh9{E]H&o}>^cB˨ͥ)Cd,HO-q;m_࣒ ET i_fRC8d_>T35"{$vYpAni-iΡ:3`Tވ0W'o#V"dcw"3AAA|rcU|| FYL<tXEEey}}=(^eccξn:, PQ 4®ZNYq"Њoϫ,J ySCSv:׾ m_Qֻ]$DD7ppYsnq\m~Tx/IuaKqwuPxl!4hGCwj˸Ź%ֶ S̈́G7 &xA ,'vv$]F` *xaZl}LG"6HnDQD~J*1Mcc?^x<_~]tkcǎ= 6`0[G}sX%$$4 E(XAE2$4n|]; ƞQqm}jj'_1-/Qd@$C> TBAR15s}Ԋ{Fhgϗ[?_ 6ٰ@| %ɂx~Erӆ벵ΞB=Nvr̫ oԑWJiUxeF3ac9"$vq03!bd4ˉ}fC$R; `[A6)(*eCחjpP "$ROS倊"d"%%^zطl슊=7nù'}+W \\\`cZQp˖-kFpT+(BȲ_y|Ȧ(gVXte%Կ.QWV+HKWR5s} V5`%Ow"n%ZHJ'q$#n] z5}.ӒCc]޴tߒm}?Iwyd4.VIJJC\dz܍J\"W[  ]@[$4ɋuG q D਎N* y* ˗/l駟}ŊˎbQl5MMM`aa|1(ЉFpT+(B^6/4F@s=z\ @Oh#)Zw%d,+:. bʆ!9x>A3ArAIPlZvN%Yy!1"<9p4 ;fvUt)"3vy !TCttyjMunl3ގG]vsKBs|=}EECA44 /20fzn/N€y.} 6[RIj7UF8,t\E&?n)nܹm:==a[vmǏCjj֚5kۯ_>{CvMMMFKl;ܹsYǎ`l^PPлܬ~3gN2e…222gU2<>3f D;Ng߷o0 ---UPPUUUUtoIII+5551kvvv0t_(sBՁ{Y *P 4"ɝCQg_0Yq’XÂmnAwgKECh&-O=JZZZ\Puaц'm5~gω1;4DWtޭ+ZͦG( g:.:)v\1 0[=i@ #6|zu)KWE$'v>\PPٳgjdd$p…7ofM{n\\\=Qmmm`ԩSYIVPQ^J;StY/A1\sEyاܪchxTڛwO6P2ѷvr8sN9]h4Rpq=2s[W^=#Zsa,f\أ'+#|Dֶ_jxEFHxCA oP-~I%IP $ o)pXV c@Kpכh://T߽{w1tŋ[l@"@uҤIqqb֬Y?~jhh`6YͦOq+_FvHtPє=*|&G3\(1AAs7'a" AGiy0(B& h{7nXYYvyyyF@4XD֧8ydf˂ 9vE@'>Yd*{4377ŋv==l iWwx_k=b|3,brPgE6M[AY p,#cKUcPA4wyfEJχk$D$t>_n;R DK4芦ؐ5e.Ew}sxc9ߵc=&I(u9@jf|wrhNFu>sUrDx"D"d ޠw׮]Hn[FNNدWLl4iR0,u̙֠3> RQ,//駟z7knnFgSD|+=X`0`2==lm4VG_{)G*TcNQ0ίmꊿ? H3+BҨÔP!A3+Ѽg$p-yՎAQțX׺[gݺqzMA늣l-/c>9.ӻ(n}M/%b dr Ӂ(MʱUx[Ӭ@jp 젢9s氳_aooo7oxg JE1C @ 5sF__:dy$ء()))_vmvv `@L3=(EsqqM4 tU')qz6*YOb?xǨ^}$X:X\]1>x:2U^bS44Њo)T ᜹)>U!9}P{Hr>*4蝰=G^,lژGē4ɸ=x,rf͝КmsShMkd4w̨Dɫ /M̵Nה» |N<xNg@i(𼠢 Nܼyw@4''(ӦMcpssnŠ^|̄.ZԈRw 7khh7oÇY=T^I$BnFQfE޺bVc{g Bs@Sn@ yjFQ; Q헤"@2_ 9 ED~3g0gϞ=s>7LNNFժ4f{VVjgTUU&33̙3͛=f377ﯟyyy'Om>}Z_Gjףnqqq_'ر/_\WWcF0h=ƭO***#ĴւN( v8؞Umx.)w*xMXYqOv]+wadln) D3TLtEV$DE%szi+S. 5; "=͚n[W|RcuآwޏcqHu )7FK"XV^ZY5W[ GNKZZ_ y@>##WRHPQL4DDD{ŏ;6b퍍ӦMdVZ=| )--=@tt`; }۽{3֬YQ[[+//?}tNNNKK_}C3̟?ӦM7a'GuP61 ^ΚjѡhA SxPQqQd&tV|By赸+c˲ 26SZ)y%wv+R+$!y刧n9+ɀRɈݚn]R}0΀LHzalqqs栗|_wǨ_ o%טs: ,D:vאG2(:pO/(B @SS<8ϬCN|BEEاmzWZCgE'jΘiΊ5T )T*#5vQ1rBbJ<opZ0 9+7pPMDL{(L踥[W|?dE؛δ#+-)Y&=+2|+dALl$?9 _*+37E(B 9uV(*CCE/ИMA =4'i; MΊ|=!Obs+*!vb*bbH-MJwCo53647*ˬ ȸJ!֗z)<[ >r@'AE @||yPrhLSu\Pgy (nXMLZ*ϭЌ-!:HO^Q=o|.6zpnm-(*:Hߖ.\~a! t2cgMIV8qHs~d4;`ɭΞ$xA BU;, _cl y.]|@z{n666t"7n"F+^!0a7+.s (MdR^Fϙkյ6)ghs%$Yb:[p(}xߖC"(9aMJM'ulcWQ?74z?VfrP1kGmӕe ;|]"=F=7@ƾp4a:]AFe-PG20tzBEFZZz֬YͻuE(XAEh k9"e"زa uvcl[N* K.r] ,.f(6vc~dӬvkL.њuNRL;kUU}Y_J1?Gkei5xA cXҁCRg _mcS j@@ PQ 4p0E rb,̆:ZPuV{QhV{ިh+* ȳsA5`st"`AoATol+.0 bu MJ=} It]RNBqF q{vgEQdE}hxj+*z>C |KaII+~$Fܞ$VW@)dDR:&ʞEEӓTxng[[ ȓ'CEqlS__ߧ'..݁ZVV3f^`TY< T`EȐ+zmxWiZ\T};m9}vތN`<ۼ񏵈5# ][9^|,LhDFTHZ$؈|k?&І[O4GDE=tT'ZE(:zh>|=B^I[^K𜶸$뙹fbig|44cE3ao xsA #R`!ޗ7~ ( eo{'d@Q'BfgGtB++-_ CEq|>0&&&#Hu׮]m[V /IJ/*kjEN *rZJX+"!64 ^n蓴`._f$GGGO3o;:H^^偦wt/ iv4ZIfA5WZ *2DeE pX wZc?} LYyC#CEq)rѠũcn,l2(BE/J$4yg%V5">S;M?)3Nu~J?Vf: #G#-8FƖNHOHHTD?Ma &'f]dlwvXi.E8l8+!fe繫wn^^Vqgz>$gײ{RF/<=nj\m0Gd( V hw Z}N!25GWQIPa#7i}3n \>y K'"^ҶP{alDһ8n$-ZL{G`U B%Jӻ'QC/]W]sj|TL#o1d[ _!-hm2 rxWd64"KH~Vӊ<] jZbWȨ w?4]R9wAYʠDh@br\D+#GhH|"_|'zGOVH lP5j@ #NsMLiYazJ4 (/8^O~ŏZp q 6Bn"<,8V7mbBJmJQd͛[L4Ϗa͛WXXf@^j`frɓA}744d_yVԠ}d?+g0677T.\hD;;? _Gpgφ" Au&GoV~ziۧ`8UGSuj6-'w"XR: rLK!jxj]_ P2_m`mmm٥$Ξ=NK73EKճ]J"Q//^'v9f^fm[Hf3l9GCaxQ! [IZ|3%σ>Ze6= ÛGonZ]ӑ7ˋ6VRI/;;F@zPbKr|KAn%D| +Ș^/8I{+ U+*8}eee2777;wKqqb֬Y|錪2~VQ3ghPWW;v f6*))##l6X5DB2qFt]t[T)o~<_h~>LhQпQY5WCNty6EdTQׁ?v(o(-љ[yyO?$//cSNՖA)ÇY<#4Jو0O26ų2nCKrr2Cx"!!'`ۋPQ }`x$xv$mg¦{^lJ}Sxj?wҊ?ו6wtRPǜmg[Z]^ܱ@uE.53:+$&NhC8boغӲ8y|ɼ[dǑ 7qnp^)36y qP9N7q:ĕ2rMTFP+1]* _]笨TZr1# "+7! m 6zu '|2,Z2ح#56)))_v-#ΧO999RcccA?3B d63OZJY|ZN:ڪʏ Ɯ7fT7]4FVMCx (B,ͣHfdZ9p'4E+cEL):]_8My/ǯ|t>{dF5 fl90WPflH6kǻk z'3\\ߺ-$&Nx{ϑG;pϤ"ax;85>d>'66:iV?IO 0GS27o7R$Qj]M60>@h=Ȅ҉̶$!7B)hr+[ IfɌKE (\WQ_t)0 1۹qƍ "???zY|ZM6"**ʰف?goBC PUUV閤11 "x{{{pqqϓ'O3gڵk%%%q8 8&U8s\ނ ضS\ìIޕe3V_J#4]_0Y {D\}.6 :庍R\}^JhƖ׆;cK\Eָr?#:.ZXJ($&!5ƞ#v.ftqtBѵv}@rqzi0ɂO⃹H,:iht5i!`F{M-=$kpHw(.+_bLjb7/)I6n)N4,M1 1? +#8(QEQF@cc#c7oްBBB555:::ӦME;Zm)B9Mz z`޽󫪪Uwwwt:D}*++O<9!!6),jaaEQޕ0-̞=nfÄ>cHP(VVVϜ9s455x<)UsPi,UmLE;@FĿq dm]'i;}{1$<ϭ@];aK=5<!udlA!IItTENni!1 IysEB͐ R/<|%]5V `ӠcK $J&ң5vk?IIt\("8^?!F8*=M F>VXXxWNMMPQ@oƺ쫁W_{d*Mmʦ>}t]&^BĽ"eb"3R0p {҄cr]2"3DL:ؽO̤PYU9cb>:{-yJ֡Or]IYyCrz,AO)S2|=J0,vp"ghMDuiHxRS7\#xO FZW"g r"v8Fu'B(a51@ɍT(B11EGˬ)FD:7v㝙ILLd}^d csUM̼ݻwϘ1c͚5ӧO䴴DԜ?~ܹf㋍]z5hJ.]: ...ee-_xcǎY]ڵomGdž=۲baeyyy"!+U)7o vN]]m\_,XEGGTUUgcXii9sl(B C BőVQd8WqvɅ>~:IGCeSuYU4]e4]4$m=ߙJz #cKc7 %wRb.?AuEçIAQԢbߗZ":qVl줋 &%LBօ<awty}ԹJMI6Hti0}4֙(5c|Q]Ɔ2䁌]Fvb7/I?1S ]qqmmmcb}ЦDZs L-0v /)+.)MB#}ƨ( ɓ/̌dCEUz#|. yFw<{;}Tйfl[FAU{OѢrmQ]Cw/̕S^Q_G@L . dlGGeL&6Ba!U_7WEw(iSg͢\I88>@+(B /Q{.l] `<cԵ4uVuB|7 g޲rBuE1uK8|W[[jja)y#,Zo_ݹW[ED@3wOIR3 =}WVۻwAGG4ZZZksDʙ+V@/"X!4=A'j.ݽY*F3P[֙ʆf#zg z]s4AP:%-ȪIZ/z8]^16Q7螐 24dK]U79(ʏGbHSC+sZA5a_Һ~w&j(vm }A("M!ˣP(Ǐ%k׮٩üyXyhTRRJKKY7䢢"aX_ "X!4El3 z]FlEq[ Q/p^٩T4tH2r 8C08)wJJ_IYF4PqOZw9/%#KRBS%U5dA9NtӾn :|h~A!BEg2sF0t# *OҀ11@,azbE:FSd2$Pw79&tLn4"҄X":8X;ĭ ^E54):'k(rBD )f+LOO-qת9KctD^k׮ 2"HHh{C-G9BkgsW+b%ئU|ƧvgSb8M0d-:n\{F/#1@ C PQKQD{Ui9zjCqa9(Aqn~1K@xzt` jHRH효xz2DRS?"hΛ7ũ|ux?y(4,H_$MOv 4"+--+"S*"O?! `իѣE$[!s(;2foĖ lh JO?~ѢaZ,xx;)T^SV8ʪ*K{݀\?F+unq?aETE!a~gX7e ,zڧcЮ;^F W貔RRG*LK>VFR24TD[pevM>h4R--[مBr/C҂ \X"4#@FB^kΝ}_|qرTVFEEŵk~駟|ŋI$]]]jjj+W\`Dqk,99˗d]]]궶6iҥ .kkk'lff̯JPWX9~xSS^gU!駟BBB,r|o>uuuGeD{US6[BtXtv|!53)5_BCx!>h*>~7D!W,|խΡ +vKH;xu,GysjV izgX|)s³S6%[V@9[0 a]@e%5k*k6~OIm#D ѓκZ:9&{mo(vEvo/7pt%<2JUC3'+ M,mQDfH&>SeeeVY[[{ɒ%$)''c…pAS>>>D"J\\deddX[8w(lnnNIIٵkE<568Y˵kbcc[ZZ.^G%.\xs΅͊DEE1lPXXxފiiil~~>UDi`% ))9ի˗/GeD>e40Ny7tӜ"Mi=t+G1o"I2+ ՞w'g%NIꚮotůPX튲q| DM.Z6z{Ls-#XYp+\_ƁůBWM5Cix[h9y_:hJQ34& V8g>;9b2K|{yἲyKFׂVU!AG o_]-"H(ݻÍ񀒒Ν닗0y_~ 8X/ %\\\x(1ݸnlllXR^^K@x` a#`ŋz;g֒o⶝D"/@DVş~)OjjjWWjٳ^!zzz行"҇^F?gGC3+zFv`L|zhqIZ!9 &s*΢؄ŬbR2r1lqXJkS2Ռ,ZwU׉_ӿ2Z޾j`MJr_%TSRXADhork՟;,XMk$> s+ֶ=pD-i׸qRQnqۍGˇ~hCms5G 4."<3HHHk[4DHP-1KRψ("M;;;}gc4`<JYF͛cʼntm4t-T4KP@vܹle+A!@mDϝ;7SGFAS` X" /_0gΜ#2&"HH ;OECcj.FIȉ7f#bKWĉeHr KjZeLnh\Ħ&gW WWE7 W:Mwp{c*sW4`.W<'\dL#B]ݗlST1p^ Q#MF<B EU ։1*#lw#9޹aW7g>;㰴%f}44,=#=27?^~Eeզf4JH |~("HI[ZZ-[k`S[[۸mD}}uֱ!5z"$NpŒDͶ J ?f-y… A#""fp '`֭۫[y>;w9"4rϭqEe' d9F1^P ;?!Lϻk  K+Nxha$7nmic[[[2qOKjAIsqYi.9mfG,56hva O~ߛkMzeG|Ep.Zϣ8D_BWNϵig ͭp`D+wDukj2k]W9EB >ڮd1W/$}cKM()g&@W8weg> )Ah 4PH/ D(|Gs+l5ĀcVSSsƍZTT4--ylGG$qkNDS'|¶cff&c\B&QD }@HH#Αs# xj:/ܸ.VS$g[h{?6],'X9ϵtx`qKw'Zـ? NZ|WܗlV7nN(}ܰf[( #ք($*iv~b4ngc9֚ gqo :bu,MƒL[D:IفgK (ͳbQаLbJ3=dgWw=}g77*E&jhА}NirEi&@"""p@"h9sr+++ʭ>>>p=++_zuAA/Xd (No@'YVgj\rKqq 'o5ty&cj-+̂Mx Dض&:A/PsuΩ|.ke&+1il.Ȃ=6veU-xˆ{Qyo5snr>'D=P/*U`_-.&:GGv;% %ylFSKJNj$Ѐں+"ףbb}Ys#",K.ׯ7nP(x: ܜ:Z㰅NQctl'x"@vvv  }PD199y߾}}>}:33=QDBBb˄gUvӿ5܌ )tvH拋F5_ldpbG$=i$zRz/r&䊂̼AO_Ν \,.d>->^;QL.4Ig\xP' vQC6,ZۦrTB'Wƀ+PQyw|[I|ƒPǠdF a&Ŝ]Pi$AEMcx jQ$ٯƤ>:f\-%ѰLӇɔU{QD0 |AAA}srr999UUUϟ +@9̂6n۶ 9GfC̙3#RqfDqoP5u((s*++  RTIIIpo<]]]P k-tXK`IJJ >!,a``Jddd@ 8  ڪ hwX;vll Ǐ1"HHH (F rťOztUj ]bw%ɏb\^Qajn"^\dt;YZA9D`7>)YGQYE!h?F &#EKQ+.31czZ|b\Z6W[39HHWeoZH$WВPл45jg_Fr牍x"̬HUnKt[_͗8Kt.)-}]W1[{J)m4 "H$)ƬY#4άJOOg5 \d wŊ_~ kyyyvZpUDEE,X?:.]ꫯ>3+W爊aDJ&Yh&w^͛-]T^^ wX}EEEF›6mBOaDDe\Mh0bބ.4, ZOOBAy]WO-ZC(Q3RDR5HMF i )OI駟B3 kjjDY"҈% Ɗsoz蘨*t+{eNJsl]'^-&K8> .cLPzXxĭ{Ed[|Vvu[f,:Jeoim9nj[dq݆"J}}}.]hvvv6m.NNN7"HHHcF?Ѡ'Bk+ˀ[8ZE53͠JwOvI_5[EU ]'ηulhh|h}΍;zz0ok藒9W]3֜T}jA.3P\n9)i%شĸd!#yD@%#c8U#]th-=DKsei7-KQ٭u3 WɬW<|]Gi 3m$Q]I9BƅQⵓU2* aIꆢww WF2N!HW!-'?/2Ƶku#B//ybȆaN3G^HHHH+QׇD D&Jj3 ڷĵѯ.t /)|G]甶7M*`bkGHr?}Im"K}o`hw[DW@U;G$R |hkgtvvƍccܼ.Z`6;7K5\KbQSka=m؋^?YZ^P }܌ɷ1VKL6`bϳUt:fkMQ~Z׹8m}Oz^q^~.(yPŦƤ,C 4%K;2NxUY- `pQͦ fa)=bQ1Eų͊sg7Ĕ\ Vf0z Jk&4%uӰB]ul^}vyGV7SL,XfD"^E ~~ŋϝ;wΜ97n@?QDBBz-2 sU-y9d5aQqY^x: '^d-upQGksh/%BhNC-rnoo: |SU \:w_KWh'yuFhD$\3  ;,X\Xl׉[^ ,\K/Ҕc}hߘa N^xR jM ia4eb6&p^> ='8tHg/SYu27qT&2ϞAWSZ'&Nymy;GvS:}Y9[מwͭCYPUY1K@*KsZ!TuihSʻ{%g I z:LqEp[Hgg΁9by?4nI:a)y.2Bnڪt$R>eCX l uنd-u²nw(ykXlQDBBBz_""HHHo.0hЊ626i{p̤\i{βεEP7Q@)-fk뤈؃8 !$"rd_Ihhr;X'Zy,H4^{Xݢ1Ov?V=Ee`⇘GC4hyGQ~$=H^+t`d^f­p}ٔKlNEޞ}}6j DAGUN]AHm˒qTt\~]uձBbY9s7D^y5Xؔ<7{a|񑲐(&:zwcio+-a̾"(2}ň`>>DQD }@HHHW;;m郶gHloXhWmلU"/:QnV9E!-ܢA!DH?i=tGn mNn!Wz톓LVV(`ݑJlvKܙFlI;!0a_|)=BKβJ5kA|[ޝF$)]?zFlPru=]M ₱Qk!v^OluNB'B: {ɹK{ĕ??~N)nmXev|fga1O籮J:08ó-&\}/qADžXF$7.lu $샐.2v%d?HO2hj̄L7 uV&cٚ&5׏Z8)+t, g\i&\:*o7%  7tw+6 fyG1*}YOʤWŕߚOm.vu8vNzLmĻ[Ef8볪o ICγdC QR$Lucd9/Z|d?Y5Sf+1 XU [V"q(sxb\? {:LH0oH>8QDzSCGP?J֮] S݇y"d2ٳ[nݾ}ď_{ *:F$ 7oG]p]r(&cqsUV@^ZQDBBzU71;ADKL!B47񂒬bpEisSR8]3'](֎+#XR{rrkq0Yɩ8`Z-(uJ%Lʝ23[ݸک%y-f( W_B IK[fV (? 4Kጋz3;;%d6i<cb:cxh+~G,$'t^jslo *svW8s/fٱD5Z{`}@AOgp006fO1T^Q!.qWJF``@ ?F1#u%Qw21\/.R69Nf0ROs^qWEi$IM`M!!F*N3{EDB!!@SSӸn~珻4;=3goF$%ڲeKyyko\h?vrrTUU]lzWED -`$Ss5@#3EhqS8Z~}q;iݢjZE_T0r @]ں(3ЄAohC߅)nK_~ZF)Cwur#{kz`V'|v\1cԌb.ca(ԁlM*@j} +4YU38w0K_>^c]ު1 [Y #HG*BrVj;%yPfK J!V* ׭ߙoE?&y`vۃֺcTO8q} e-VO嬾zi0u4tִPH{RN`oX_ӹ5, Bń-= \u{;b+r)8+!Hl$.y]^27I\.m Wʏ ~QivT{ D3?2Y(*|wgP_}& ֜J#JBMۄ*5J*\Np hG[%$'=om(/< rSsy N2Q;h8X#\Vif Df &,W OɭъtxHJIx+kJ*`+ ,);;=$0 0GEX>`(=sI3LVma2:f &][`[5v$3i= =xSL&Ax f'0T7X#*:9N-!Z<:ȠctwMOJSw:t`DQ~ lx<<<Q \:mnذNM%%%[nEo("!!Mj;Ag71:'\3\r(Z,kmE+Z{69ٗn_H:h /&oi0rwv(Y2ޡq'k=,6Y:q$)6G$$t dI~X~P]Ybo+9 k!ꬽ*{8tTJsb2"BLLy 5iH tnhn"J]wpM]R gsA~@j ga:n^>X|>*\$, gmRXF=849iK#{}(zOLF\tDh\,.\ukHYS}Df(_!hQ\\|#BKC .,x߸q"46G#T*Et!')Et7-6M.z#axJ[WDM}{MϮ⌔(hG<<.pSt/.2"vMe(;JO b]CCT+ gP%+W+V D N--hpPa'YpTTڭ|NP?: {%wJ)ԗ,^Iweʆ" . ’Yf̯ixNfW3;rB,ܪ=Vj4VkRy=5 +V l +!&+IKiF]7*mUܤCX1pSCtঃxlAy :yy,-[@H8?DzO}S3Ӟj< ҋ ,}bYPQ[b Ry)P7HxZGw{]z3(Klj Z<c^Ô6*4zQ IJT \v`$jerUEm!~Z{LAi̩=ުf .\  w(r3SM"DIA>N}f+`%Sv[}4DFB^kΝ}_|qرTVFEEŵk~駟|ŋI$]]]jjj+W\`ƼbO< zwxf'[7n8ڽ{`aDE`Eo߾/ࢅzED i*к*7V\fW݄eb~ں(pX']ֲ6 7`0_0>ty 7> \<4/K}fw9>x/ٔk' 0~-`!Ϸ/ % T ;߉k.3GG H|%)K'Ǫnm} iJD{4ŏ_;~,ҺtY5qG[a }eݳ&fVZj{԰(?2/5B0]ͤFVޮf2 c+ZL"j[@gs&Dwn0+VSzKsOJlAߵ9cVdx'-`i45t|YJt]78/Tޢ!X@N"xYhӹaZ;LR^AR v6g:wh6 "HKdާ~L*kkk/Y$00D"ppp,\ݿ?hLJH$VUU k Ν)))vz3^v%-NVT]]:5Djx EIBx3 ߏGp -V65#>" +]Yg%U Δ(v8xp'^qs\CNqbޔ泦BՍG3_=oMbt/2*<r/Twű{酯oiՀFX@F^L1}{GASc0[[PdsfSғLth7>hnxX爱Qs~sStTv$#J9u1;G!̴ ! Viu >.>icUiY 5W)V zMUL@+GCNBSF3N;=`nzeׁAg\pvx`а^ry, ;Ž Ruw@0Sp ,- fLtbzᴍXh>8cAҢYρq8Jߔ]ucl[kR,p(NA='t`R.$𦠨 FƳy ghAi{z"P)Ĝ `tV_dŨg(3< T;3Fi"޽[[[;fRRܹs}}}BPf7o/[a+V%AAA /y] +{8֮.֩)+9sXK&"X! uUI= 6Ԏe0L3Z\,xrůy8+|6VpXzotճcEr䍄Z$;-,qF'yqcʪq?Y5'9QLCl{NJVxc)Is>jV`xce"ےo+d(t h$풟h.>X4υŎYx=<Ѻ1ӗNXӝ>lLZZr34j J2:4bi&b曕;lcC 4:zt&;}Xw3]l}]cI[G5n٧[yڵOi:Z$w;#'^3zShAt))9y8;oxzT9<Td)~/ոe Jj!QS(*}^Ѣ 7pZ-vw%{:7V nYq6fb6FEq`ngWx{cҌ`D&F`}k>1_`%olxMLlLbT[[ ~+X2wqʶtLύHs ';Q`G++ǏODHEK NG"ИLh=Zh=lh2nn.4 y<.qp;dx*zQ΋C/ Q71qż/o[*Em\'Ƨf#E`ހ?Wҡ_/6ՈT%V φ ZWё[Aq0uwHm*2ӊ#!mHIt< @RdbQ~lLt1mՇ%09``c̣b<\ zJ c@x0`S=0 ZH_cޱ"*5o}=ٔTUyGC+v:;DTbsYf<-@aW3yOR |<<Ʃ]w*yܢBoG߄V tzT0)}ԺB 4#Deٲe +!!1?6&H_ndF'ƨVRR26QHJMM[l2 ~ǯ5өƜs3ʼn믿{\\\fdd !4e28KiwPi}DE|D(Bv ёZlhc쒪SR'%Dm@:-ep x~0, r*n jz{{p \y??9^1_z|QiÇ?mf-Ǔ[=PZw3aS j!Gq=,a_lfIX|{ϛkŢgػӈ$%WOM i ymx }L661tbgvxQ~df]o%IOe |d-&5{ g=18N#+R^ %1xSy?x6+';olRcr3MsU>`-륈gIdz#&=ҒFxN238#LGG "Qbbׯ75ҥK~\\zDD iض:Z*SuH7\dMjS ZCh}Ch}]2*{&\մ,j|ҙ+ꀒKj QdcF $tJ*>~== κd-lduaɆ?m_|V/s澖^w>%#YX/щ>yO=m%*u̶ʁ`-˷(Ry/c"۞2o5$~ܚooi$-1Kb-&cWd{[}%+S#27 չras!&'@dhfOBf yǚV~&fݝɄYGzĬ}+SnX&:GaTXdzA`d/>8؎=mP҆!&mi mpMMQјEV[[1~[S%$Mlz&6EHG>UO!7&OR5?S 4DHDDD"/hsVVV[[[}||zVVzꂂ_`NQHT*uݺusC4%k4'G[V>0/TI<="/_pBnnn;;tN Z}}}BBѣG?۷JDM~5Gd0}j6E0N$ά8b2py6O 8.,*sxtW&ʮkLIvtw;pu&ElmƗ#&Wz~uzD1TILl f­;T~t 8f/R1ڀT24#dwٮr0&Dp^coe%UAdvQGQn?4([$ >泯ؙG{K^b>ݪSgN+3]nqh}8<Ȥ|>faTiX ˮF ,UXGr18 4 = >65M-pGzz>`!;]?1l-:~Rv,`ݧ5xKo۴a?Gr Eo=]:9ZˆZU14cb:}X5?u*A-MF#Զ2xjϻ*{#]拭"]Fp.O^o?ds = uUvjM%6:7)!-U_90V?Gv# | i.oUܠ,MXU!9 ۴QGG,n asQ]XXH@/("!!͔~1@q(ОyU?v^H‚KZ(` -~7Ȃ.[DNKPF紤) M(R30Vֿ/ #\F7}g.QS[4 PJV[`W# ﴩMCԦaŽ` XN(.ooJHkI~VUho0[8SY/UR5QT&^^$HQOeQqv轤 9sg}]h l|a|F}q)GsNjH6edk3-wwS[ȕ5wv /F8YbC1wZJ$IQ6Y uN}hse v7Jـmow8F޲@UQ"}C]$}{Ef4#})iit$͔8߃sIQ, duOG9d2zfQDzcD===444jkkY^zݻw ]vJDDD %$$LYYYBggƍAPee%hVLL 3gΜ1i``FaV`8vaCXf=C:%%%Q(0k֬Nbu!XȀNGj#Cmnl" 3558S&* υ;M]HN^{|1 >vb$*ؤdW8,Ip^G nɇL [ ~jwf҅asO:tK?;&rHGdPNN8,O}-Tf1wMi#Kr P:L3ƒ{6`ظ{w{{Ucp6 3>ήVW_y"eH~~ˆ4Ϙ:j3Fޗ"Y =W Ų"HAPZ=F{V)`_oU]u8i뚲ɂ%m%h]wcTBӷq^ϨgZpFw6mn;::n߾}Æ ԩSΝ;;;;7nܸuVئ/貲v,}mF[ȀeUF~~bbbswY\;w _^Lkh1#( *euA-7yZݷ6U\^=0l2 \^܉Dgµ" F @R+ƫP gSA@^;&S/WZ{"( };XlE {2SZ#i7aBt؄+`hgWЌ@ -$X-w=CXJ$3ZHq;DITRz_3u$hG'RQPT6ן[o;P<}$ 'Gc#/qw1M}Yߡ?#߽?7kN6ش ʜoG8#W 9r5n4kO H,qL\oaik_h]avn<拏92?\OBI-`i`M=8+=%sVi m -n~ޣ܁Ӗ|5#pQfN˅@d3>\[dhQ96bLFR5ahA*_fj7x4b,GqMjQ'hQDpY|i򭘋!;7 z@ijYؽyw<1>P[َ q8S$+|G;W(uUb+,,i+Aw|37e"Pӣuִ%ʚa(.#ս(@|@"*@TPAe/-E|ATKKA-abrN*[̳+d!~ط1Y8vU11,UbPc%ЋT69_<#$yQDᜰM  4*aH>0)DY}cmI]i#J {aeAHU(`>'8t%E%˘OKߑ4:6108ڎ R$ ubzchtC@XmNAHϢ@((Q/,1)Cag<z!hy_bo^]d° 篃N[޿y)M@5^~?j8([R+vDo(B/l\ߋio5h^| TPI\]**I+!"Lr4Q;~ՖAipkQf[X467eh9U47e s- =i@2k.#RHEI=5L&C.DZN^@DʺqG19yrZw%EiP"tԅ2VںGc6rgۑ^%K&'ZJzzsm׾:H'D$4z K{EmI5F6n~VYJOXs$U*FvF1\Q0~ۏz{a}g^p WpɮJG.,!;N0Tthz(z,5w<#/Av4Y0A'/5KTC9WXbEU%qe"ƊfYϔ@ɑRy|]~c=7<'{IlA`?i8OGVʪjDK9-;U@PdGUWi>%-vN$5"l/x)BYE=00^V۳Q$&ZRK #q49NTS˄UVX ,:ykdLz(>~٥nK( *6TPyZ7:a: hVjc|S Mʥb8I)?Ƨ]ǿ|;f94A:$7tuNPJ,l4//g˜ƾcDCX^벨NK>`S7vU| g5Q5W? K8}81:4zE_^re!{E 6FZ:*ÂMt W3gSTe5Y{M"OHfq`PUj-ir%\'N9(. M.}E(aE"b9a4}5Ksl땛$n<}늢ipfb`WL:䊏BSUSE}#cvn޹Y]|j̝]rEB/ݫKm6IQ;3r!D*DBtN4s(6Fpx1\|T&~PRo١DTPA" PA/*_*6C6ƙo<540Ռ'JS"Q8R%uV~2^`>fّIdrys65+@',q)?3V\K+&}dl|. h`l3]dbal۩?bX_p"X%"SzJzb+tk$ #3v3i95E %u }{s4ZtZ~wvlmjWD檧ΒGG崲yS#~=]I7jK ` Vl7PguwyMۗi#|PR%drr_lfۯ |PFج7Fy74Jĥf5W+NmFqsh0waOK3d:͕x-\T=h33fmqў'[<#/K/X@kH%{kh)nm@R ,#Ad#CT@x9yYb@=P   0x,/$MB8UOX2;3=pVAJ3j;mLāh2wnMh|JFS\% JQ` zPA5(䩩NЬjz2<1C"Ou7!*ϢD.G}FWs`xu_HϊH]応Wí &v!}ë|W.=+\ʭݢr]+pޏ}:ʭXxɕY?HtRpmV|>]鵽NvzKzEx:h=Wp]%SDHqvH@f`{!jع;wG:D~w;.k"/Ũ&ߟgE ztHGeqϙASR;@@`7ޙ[f ޡnqNIiЉ"hcXݽ''suS 1?҉vAz\Suzb049B/Z BsA; l>\)Ҹ(b!+[uTPv #VC-"@>  ( < \NdWmOi\%.~U1&I`yME;_Az̺_z9.-g1QCT^QUgT06qRhi41! lc'cs`hXQLpF@s6AKڑѡ.=g_J%%'C7JQA(~*++_~%TܹDTPdlP ߙQ<^/Xnڴ򣉣8*X$/7qUԕ7ٺpi^`s7. ,w= Z.jǡp},/_[n1䥚"S%)Q B/'S(Z yWx[GdMOJyjș$ȿk&Q"߻[³+ԓ*lzq pŁ,twXLs7ҺrYP4Yt)LN& xoh7Eƙs M$1CzN.;ԩvn6l9>m fnkH$Ww̬:۪Jb+Cv.jz~R~2c{E0ަВ z0 \K{hn889ԣs#b]\3)Y_6 ւT5!4ӊCH::E AAE>!`TUi@cKIOsɁme U~ {z1!QkenvΝ300޶kiiٳgY{ݸq g~'ћ% I6nH~[7XLv:pX6zc'Dn3ihDB8SZV Zt(*"gCnE`).2d-qmikf(վbgz.8PCag݄*x_/\v4p\1?'o:sEcL"qlb`npKW,`=-qltpԥGjM+qhׂ$|"dz8_Z-nWlOm`ٝ,L82@EЃ8.1ԍ r}knvZ q"CS 0g(?:)*\33w‚呏=% kbD{tvL=LNi9c 3jAv݅j-Qm)ӑ`" z9o41w~#R\MLFG88HOQvw)'4tKzf~uL'=&m^ѢV& 7BE:a߸0;xf'] P̆aIJò^;}{Z03csuy;GZځƦ>Xoo{YRhy86Pb)JHhwmw:ΛR~!- >+!$Zc!HY#jni ,?b4 B)(y~{ݸ$0ˣw J}sr:&}:* 4/>\Hrsƥѹʔ00C?GGs|ydФR5vI5- tBqf)/bWWե])a=L|^6l6lnϓlm\f2#$OAyVʋ2H٥**LH!#lE*mǙ#|c`JS ZYbazp Ssy"qMi`ZZJځj u!86Di.[IBkIX"BEfQ5a eC~gR)`5o ~X6.JQYtww A%//@ggrw;@֭[ttt"Js;5D_Q *|PwiY~)fVd@E%qH+RHE\h;Ԝ}JDv~AcH'/dٶ' 9=fVz,=fY]f'yaf}( H@*jIV6`3 0y/* y(zl7]%E?!.h84"H Fˏ^:E&7G%%"vhF6^w|H_z`1öp" %PI*ԍ3CWo9cKt_ .rjЂQ}LiD#HP/Aς_"k3FV \2cwy41\;6$)6#e*5N|^y!T Yy5M*G8A]>C4Cq&!=83$.`b| '5.T,ٲ*TQJl)nZz0)%+U-! EIש, 2ez!,2yc#A{$%;o75'RabANb,s{YPYY8Tkutt?6122.ǏQ/M>æ&Pa%-$.<{$Ԏߏqf9[@yح~xkBSp0j5í#^1Jf+ޗտ&+e.k^lsCMͅEI)A!.&Jʂ¢Vő#>n>~od/$ZS[ V+*O!J907%Lygͯ` UP6eC1 Tiz^j)-JWl")V?CH},^ZRZ{'P4Cqg.ȊV\ζ #^q7m vh71J,(߫b$(K  Ś&C$R\SQ^TQVрoi#ik}$BCHS?a$[+J?I6pH܃Li59[OMn@G*^ keުBI@W0Ɛ5ِC&2yr1g Kk#cZWS199F`& H! p^2qBf$#ZNۙXs?@06(QDm~oEo{|}}?hH l-Ce1X(~ɓqqq:$H5;wDߵQ *([p#_ZͤE>@42C'Bg;1Eʱ bh*5ĩbde6-]|~Y{2b;m,> {l|<ܺЫQ@Hw&Gfl\3)CQ15Z[**+db-c{xN$8mNvޔa0ogjjr-;jR\zK 'N0t%Ҹn~h`4.;.%r!7LbJ}6M1*R0WPVS&..F"^uj\qll(+ݣedb6bql1%&'H"^fwdvqw#4KvlkC2aT$Z\ $8:0F"h0?JIz(jqtِBB (D52H,/hZ^boBQ ޼ysDDpttrssC_Q *.?GZ{0*{?f$LQOu "60NޱD"'J!WdV0 n Lv2(ۥ`IE M@65Ӌղ.=Xk={xu؈ae{$;cߨozwusC8k# wDp$-^R myrbdUS_)R$?Y4n!1 d iL-~+ oPP~Y:LENg U{!,qlj$Ve+HD'ix֔EEHeGr ՖSst{? UE+khw;r@uz#kfxK$`  j_>TB!#V[Z09L%-%VNL N[vxd |3Ӝ +[GtNFĔx)%ȎtiΜDfܙ;Ǘ/*,ڧ"U4ePOۃOX:IyR=ٹޱq2뱦(QDeuyљĉ_~]v-''ֲQQQq_|g~~n݇vرqF299yDqxxưnݺ- w vC_~&k駟`%umRRR,qϜ9C;vFn)iV6J3\[]}}cCBV@\-(Ϻ%hj-~,Zw敉XP-N<*%o6>>C'ॸ2Fꖒ3L,XjBw1ܷXcPETV(==/BYYytttVcmmM6EDDtww}T .:::*##C>u҉"ܹsT(++;?ح" e/>r<߃, ~/Qnݺ7!!+2s;\^(Qp~O?rA_Q *eVu'3˻Gq0{a8CMئ*ZV&oUR շ9ޖDmI}^4P'a3mJRGǑπn\ ,5`;N1@Y^RٹwƲq rpp?rVJ HrmN%(2J%w;"i'y_7enU9th9"tvARY!sKBVgħQәKaOQA5t N =ΰ,|˓adEs Zt]VE)փ`P-T:cRT "Ti`ke:SIIlEmv֤푇ù80 tU$D 7=Qe̋HStJkW_Xd*JR*XM{ C ).[˒:88GLJ@GKSmoO})@V>塻ؿ%(QDe9DVśO5=T:m6VyԚHPs}jͲlݻgooOUSSS?,[R_;r+++Ps)ڽ<==yhh6dkG;\nݲƏŏXM},Q *B"Oֶ[mp"><"DBDʆn#3)-D^GGγɔf敺R2U)Q<:ݯHڗ9q^qb/={{I%aT^n\A^eqű4:p 4YҒLu^M}^^6(QDeUl?~ 7888%33/r7nHUX,u^"Qozzzh+a~kddd|hh_~ Jzzy, ~K O5w&5ѓrs G"*(QDTPy27˿|ckcM p (..DbtVc}j6(>$w څc!W|j쒀+!/+9)oY.E0$WW[V06'Tg)'?+@LZB"JeF↚43+ [hq"߃ۋ;qq?|e瀪Q1!QgQ1<;Gg`SQYY]S޾Df2@Bek#]D&^"hϱl4X=XS*/ y=#^sK= cJ켩yz )q4"YkMd Fqo\p'TLr,/7gnLD%%8y 5 PKW/,_QY9>ء565w Qڔ5n: +Huj4oũYe.[\W oǖpaA$)93I~A!|9W!9xx 0Ǝ.\x >66576upWV'2fa@aw#x};sPkğt^v>Ahׄ.{Rkr":* 4/͸; T&˸6Xa]dvjX8Sk֬0>8ߞL&w8 `jRrQ'O"hpb".ە0]RZ6Ǹwjh!3/Wb:jlLd`[ LimA&Zⳑ8-MŎ\F_ @5ś..r'PYzm}=CYLj EZa^(QDe"uցzƽAAAp=??~صkWYYټoܸ%6m)]^^MkGEKK T^~}xxg4"###{O>ڸ~1 U酈*(mQA_Q *t9\b|ժpY,QyE+_3R 0d JʁP~&s DNPi!P!k*$jf%jgƮp[]ܣ<0o=9O~zܾl&ڟ@eQU4&;eTw_ N;uqq2!XteyUAe],T0lbRJk+[5O=,9O=2` uVrGgg]}}iYY.^IUU\RZSqG+{q=2c o ugdݿ1APɆ).)SRUW#tprqt6dMHLœ¢Z۸ aYF4,,LҲr$ q߆o.{).7=E&ƦtH\gQ+[fC `_!OۘbqY~DؼDC_P|omёT0LQXze"XoYPa99̔܍D-eE3g<,<3 q xq,$bMuvA~qZgPWC"9=+w[0’9! 9).vvT{:?q PL7Gtjsc!ZC='Ȏ*(sA\.|69B&;ë֎%u",*ȵ5gbbh}]Լ"|PF戜''>6sOP#'{'j< r8g$)/wE;).)RVܴOZ =6:XVXRemr^m-p/W;>CP;ګd :Sf̡W'796;ë4qwUiq"ҖV_P|^rúf{{<%J*ꪜ.?[%Lz{{!z122O>E`cFFƚvUU 6dee9 ŵѣGֆ, 7(se֭׎*JJJpRf{ޮFFFI>r #@XQ XmٲeYETPA._i#9\ kJz="fLPt2&p uK${GPr~Qխkg( XjPnK._"ܲe-j%`E^6kGZő$g$} XvTS^)$i íME0aoK⌫r4 ᷁:2PS. 4EOvrj9d)2Y֜_[ f;6?+835>&28SVTVH-}K) {~1o.>A0elТ0$Sl{Bgt^fR.FCZQ i"808^S[kkHT 34pc9 V.aN37z,P#!yr>]=-,{^l:ys^ي?`_Oo0tPR,rg0^`J~eȈᙷ o0co"44g+^׿ Tp~Ä4c+諟 RꬍI6~d ))k2v>~7z[sFvF|`S}>>PҒ,..>ȈAÇ`|<Ɓ@ //o}}=ɓ'u;;ws466޽)fggCV-,,mPkGN;i׿~GZ)UQQG۷oӺ/q$222ήcYG(~XJQQ1s9!QA"* dVn#.n=D癤RUIh)vn}U=@(Ggx30*bLD[% 7wyߕ6Q3f#թnS!RBOQW}XWz;[2ek~-uz D2ᵑX"%qtn&LO ߱\RoY.F23},}!she|W Q:cЃ{jD-a>+ύOK>8/趺8F[]Z穝#]t'pXNjR.$mü8X-Kb^anVF4ud : {p\u10O @Z\1m ~uPbo|93]P.`Aث XkXX_؛DZ`bac/c/9/`b 8{^kI^y0%A2&7Դ%vъ; 4. V^3!'7=ѭY\ڼ%! VfT"b5`mbeq޵1Aω13Krg&ɕUD"< _[W6EFE=11266D[;*[Z "r23*p!*NOTט}rJ,Mgn_ey?XOWRZF"*KƥGk\i&&j7lذo߾Yf%%%Nwܩ)((qƭ[6_}՗_~IGGcи`fg>r9Ur~ _~8x𠘘Xjj]2s΁K&_QQpݔb1( *.-@uFR [7F*1ySroF$9Z-.ޥk!?Ӵ ?̪h)'ǯ(h+!N*ܚ- R]_P7p2m8nƇ^A^'krT[˝R?{4ċL{E8?I Ht{nha#j/de̤-]OM.t}C I>u N܍e[rN |LNVG) g0Kk;z#\[WWYUUXT\PXJ\BBl\|XDdPH_@=(zPO$6-Z1=q~G?ډԁDS !oF!odGv >.$-ޛdGF3R\c-ꂼeΤZwF5^oFL&TT5 诳=\0Y< JOwC{[(m-e T&RV嗕 8Sk:W=>̺ (:qdppSo7; G+N=-yL2 (k # {o:'#5;p/P;S_1wtdCDTކ}wT,C=,[%hf( *K!OM%ueluJtb|grynpipk M"!: =EЌmrb2EUFZGX+H5+4jkolqH&wՇY LVK%=Ίp ?g>H7E9%'c-.L8\uxܑ*Hbčn澶F3I"wW˓pQxx=!1&8SEFtV H' nĭ?b:s{`a6=M !6 r{]YRPWEu^ cniMEwg_ y7*݆?豖FfV{I #\`bFD&ݹ~rdY@!zS]m΂%X]mu&w ߁ ^j}R5(QQ@ S:P\z;y[زBDLՎ 5KSK~@o<g95@m7hy0/"6*gϨӁ|FKY% ʲA%z,&֦v.>nO3I-- j]wf\s3}Vߏ+U\&(-6K,8Yr~25EyqwydrKL@e-i1%ڼ|2JQA]ݻwyXzF% *+1BsGM4y߼T .Zfxd !!3̫Nv'wٞ8~mrI!Z. JU4rg'ɤi8NNRjH)Ӗ{).[4t81910918&ZS`ApRu8Mp59*3dza8'*Oi(fTw@5q- T.!ɗ]Is#3_l1ݫF_a΁G$}G=%|B?qfW3#nP h022̤( 0`o~9xxUDK-. 78CyD".RO~I-._W?JwcA{ӡI V-J$ 瘀M\bdC&sؙW=q-%qTlmP *@rrr.J11Il_cѨIXXBJ9zMzpG n.s~̞w_gdιX()7n322LfǿW.))yX~~i0Qz3u6eI^">Wƈs|wi 5#d##?Tc nݶu(&)F/)!YG&;h/͆nsK즑[ݶ…PUYaW#dft_4YyyUrE2fF!b<$^i_N-@8Y/?N AR}D &e%sQrq/]g^z4ʂF;qXK#= t<ˢУ2*%Tʃ1ig՞̏V 4gzl;O[+pH)łEaC= 1}Xomo YyYRW8ɑc+C~qBW%~A)T$၁|[#]In/tƤ葞kg~ǕX0/;$?'Y鄵ɁʊL2D --:$@E^71FK ]6QTwwc„nBׂox̴¼~UW[VSKF 1ֹ&+w>W'zӷ)ҙ;T)?mT;ѡ7Y"5-`YWeDVL,tJЏ xܞt"soMD~ui,v 86KyJx*04Q"i͚5(5ҥKx@0Q|kj֬YC)xΝ{mGMLuB A9VYW#mgT'3&:9(lCj^ީ?*BdЫ<Rg'5]GoF)~bn !*i3jB$|i}i~\a?4I3rۋ!З`o6wv&tw3bL΂j-BfAgPKRgCQb3 @:yVCc^Hz6F1(p6fZSD{k>wr{,uC_~#+MF]UPpHqIk\M:\QF2Oබ MºխtշSv=ζ'|42t>ӽbṆB(lc.eME"oCW{EdfOzhfߓ`Dɨ/rsjerHwfIw6*}}^1 UUVRS^PDp#.Hݹ)K51 Fme-GBcslʼnsd>yl_M~Q{|< $-|yM`ف>iu`t tQPv:moxM}2<6Y1$䈘e`XEydG kHuĉO<ʕ+MMMx@0Q|kJMM-&&gL^I5%~??C(acK7K kvC^cS9䛋Ʒ-WGmyT@{Kwt:W nlcvZELz2$dǫdG\O:]xmD,n3ªg*wt42/hA* 5S#YWSftqgsM5,l7;);/4<8.W1Q9ݯ|Z #85斌L>!OOVMWTV'C{8xqy'F^PP/\dXT¤o>/75`fkCEiTz2JZd65U 1 cUɐy-u$wPUcEDR$<|nbt RGĎ^1p@BBW>xbRR,ga[T\}7UP鋠l`0vE`>;rLmTiUzGE,,,LG:QorIIއrrr0D k@57&i%)J"©!Ĕ! pr#IRZ(tNQQ"c>;+`DӅ;d⊟iEy/wvd;b~7:MUMm;WJxb_ded\Ԕ EyM upV yyٮ`3ˊeoܟ:;;+S}.KJgZ28E^G#`gU)1 12RO B=pi?CזlbGؖ1 avI E,,,LG:Q={6̂"+b֖/N!VF.F,ciQg0 ]诳;L$<0d1Jc7*erL.ǟ`ő)Mk7쾦GVs"74t]s5 2sGpRv!_1QN3(9Ѱl%g41KcTͶk):w|祤5u5.X`J+BrY94VD쭎?ѺUL8x:l&*_RȬalnr {([Ynh'qy+*c+w.Z!ټs`"#@ba?%5z_~jIV)G2PT۾O&A&_XRN i*#nMڣg+YXRD Ġ)JA{Us=)٭hkno,ϲ,4DkJWW _̝;/^ȕgSUWWC~oO6~Ԅo*Kzz' /R~~1c388ѣg-9vXHHȀ;vԩSWZ%##ȣGLGQy&&(baaaNȶ8ȢWZT]B0B L}G)P`˙ eR*>vCޱԎ1qe5u*z6-q%H`_:!0 rڐ_Y[?R:+>4*Wb[W\|^TŲOU.#].Bc,d0)z/_ۛ){-CCKފ|#$ηvde]O C0};)Y^F/ f}]^ńݲⰷcn-- O3c-݇w+_;s"g3wrCV4u52#=k;̬,~>>H Whh(@9p9mpd2333uxyy9yQE%`(|:cǞ={[!!!gΜLQQњ0t_II  a|?a̦أ(b g1B/7_m2()9PpK'tK\Wb=71uNpF#bd?5NȄW]8/ KL2߉\PX2M&0Lwr>1aWc xa0Y9^vF&UVQSnlt,j9GR}/oHp;y7K_L_7o- lD[}Jʹ*fa J54*B"Q* *rA)5bRyڣg(6Jq*1WP8#HKDŎ7""A[w;-l'vڲKw~j yN8ELCei@qXgۡ}:Wfuuu^syĉtMLLz;q9]Jm 6(`0$:Auuu˖-:ujXXX >Pl ͟?F3|O0QEl0ıQbV+l~Ú$ApQsXg [.Eont Q )N ھ5+psI4Q?[l vWzL [e4zj_N="kMs5jό݃DQ(oh/Mi3-?\aCSae@vZWsUWBף=\tQWiWG323=cxojj:u*䇆r"'''!!D]̸8/x㱿9sp/haTr]ѣGD???!!!(6 ݽ{ݻ!DE|L1J1kMf4e+2sX6eUr_</sckuPt)zKq(=zdJ o8[9Mt؍@ɹE7 xx)1Yv˪rKhhZ_2$] dz!crgN]9YdB"Wĥ^ha1&l=%nb`sq?aT4|ܼ3"c%~׋+ll?zOf t[0Q:r˕tRȗ_xD-gyaڛEUUUر2+VpwwPBB͛y׿uV(i0o{MLMOb(baa E6K  =y~MWLA_4e7(ʷZNEµQT6v>xU]sdhH/(M/}D5,` JH/ fkZRva;뿌炉"Vjhj_xn?_o2*-ܷ኏?#[r3cEA!&f;ODΝ2{_XK<(ڨ=v@CDO>s5ʭ-v_ްϿ[N t:VBkj>\&s~2oŬ3@yo_(BLm~*rtv+VYCl~j[=r^/[| =!bd/\Qo>k8yye1N^PyVNȌt_M´vFf90m\gp}(bEPDsa'd=69=YQSX0iՕq54@9}:ԳqF5ciirO0a֜GݪUhm8'&C%gnllИ;w.T",,̹qO<99|ٳg͛5!Z__?CETUUQD [l kjjŋRGBa>{Up# Μ;w`"ju^?^k,`WƔ>.LSfM;T M}_bega]nJ$Z R+2LtswS!w(>_2, JX,EZ E~AI\鱖G5v"J.ȑ2И&^… 477nRSS'MtI:PBƎ^ӡ9990MV\\JƘõ׮] \r,TTTf̘Y]]MRׯ_?n8rV,4Urԩ@ĉ`B_c%pw^WWW1Luuu EE](VUUǀXQQ1a„1cdeeqS"/5(Cֆ0دȶBg#I2rl[]J*zV Yb]< 7궆Y*79,Q:1F"}i}J:QGnq#8 #hf Jh6LzO4iϞ=d-QN8ٽ{7#S^^Cq$ZUU9ϟ1p2'Y6md:;;{<֯_̒T 제L0מdN>>""sBtCCjaa!ǩ˗/"؟$ )))f9l1cƀ8'{aN(bO,Pʜ`/xxUcj>y)bNpuƾGqֶ\xjcB𰺎`#~!i(^$]/}繣OE vTAqC}1Y{\Th|84*N6dZVV$t!y .Ҟ?ؒnZʊbUI7Ȉ`<֖,sv8-u6ʜ%(32!dw4nٽA_h[dݙ;Ehᯆ|L]\!kkk͛9'N2 y`Θ17‚:!gܹ7f۶mpJzz:gk sӦM_KTTWIcc#r|1d0#W=___:_ܖ.]>?$M755͜93>> MLh+!7q]CZsΑa֭[Nw}u_($$$G%2׮]߅\G1))sQ.`} UUf$j W]}7E,a {#ӬPxma:;;;aMsj# >Dcl@ΊGX˻eBzS+cY<̿MNA1 كYP^y]buPZM=rC-%)cf{G6L\U.?ه7G]7-jcTE܍v9 3?wά_Y_xCh,Z]No-^-,@yQ,V[,s= E^Ox#ȅO#hi^Bl/2-n^g{8dg?;(PYఊ"вW;\'0//sqU"[VVƵ(߀`I 2D ]r%ϛ7/''s72s̨(>3zh!!!yDOq>qDM4??I)l*>V*2(sVtt4~s)E,(\83 Tofp˟ W hfvXQ纉IO3;z6Hyw}BF6lTQnRD./ӸZR%lm ohn\>ݡI>"I;]xJPдh$#JG(>QTz+"`r 9D-?u˵Tem D{A?p_ dx"=dNm_S]v-έ@f?G"(-$<5Wb8ɉ'|2qDooo:~qq-]8k,3e)ؤ! ,$$ӧO9pvspbCCäIກ ,L/]]] N:9_}"uÖ(89iii`8\R0J7o]֭[{d~ԴpB(8DV vܤrDBL[[[CݰAXXX>}CLE;4&i2H}l}އҫ?@s\!XQitMEf-;:FYU-AB94p3.#=(:=7"9K\Ӣ ] Y}3дD;c2 ߾`˙ eOq2dJB6l9)ܫ2j P7[Sh2siim&T4+~L,,Q(Ҡk467#2 z hTC$leRhlIpʩ{w?,&Zb?[3e9ӦM()D8hLzJFźLQ8q"??FA΄ ,,,8^(((:~z!!!|{-9YFFf̘1_B2{ͭPRR83DΎs2R(ѱsѣ{OF~ :Σ>r_{¹iii۷oGі9gg]SWWbŊSh>l6 , Ѳeˠ׃ǡQ4G (Ya5~߬QgQXfrI4@v;$-ё]Tn.cIŕkYyQ3-\>"xK (ńhmxAHՕĢrKGWȦ OSh]G4#P eɮH|$_&7Z2|eva72!׽hAy̲GO%8^ihW "ve)ʹH]*D W !R.ߓDwGDZEH gIGI> k&/0<DqܼsNEΞ=YfƍEaaᬬ,v%0y"Oheˢmll>#--W˗:Y {j{~嗋/rh|mT >hvaa ƎVNN !n i3SB6`>rO!x$GHL+NO1JL'e~t-=iV輳,vdfۅȢ78ʊ&1 W@]K>wvs3]CL!{Z &{5jT E*S}BUX Ŷ&ZLH-tLQߟ5kرc{2N1) hPO>Y`3g8*>? ^{V\9[Wvvv^xϟϝ;>Xh%Y[ٳ?c[.""gϞ۶m c9k7c ζ.ϻ/קi-~-((%= 5gΜǏ7SdiiiU7CLNx zDE,,AWnWU@c`CrߺHԯd$2<^:ԲM-DfeGv6y3Zb7 >VM}Z;}*Q1iy.! lQv]}MEP6t7<%*&ATS#$6/ǧ$ 𳞛=z&XXXuzu],HK ɸƜ Rf4$Q`R_j ^_^pkTS{9m,BabuuQK[{j^ɋbiAy`Џ๮^׳g98?.56=72G5$N5l1Q|s&=?ЀpiNOoQpY3Y3ٹ8e􌒂ȌdpX}O{;ƺ?*b??ySA΂sj:fׂ+u-m/rH4RV! `J8 }`ESSSQQQ$ Y0D ?7`I^d;mN|KҞQD2C ~#3*YRP^<߸&SͭmaGvF.`&ev&HLe4nIj<}lu顝gcSbr3 ʪjMj{N!_֖:D!lZp!hrdF aQ3-M~AYKRV3q8nG1C> ߓ/ g6 躏{'o:b1pe*a_bLID>$|%y{rح툎dJSS+?99s&/?ykŝ;w&Á(2.,L5);ZcYLBJ-|>J򾒅B _svG bMX2xPzAg{?8vitw]SuÙ>ЭGQ}iniSzgT(>BLd 6 ŷK hTTN#~#w(6_,,,L>Q o (ba OuvRO|&rZxXW-,Z֛~%=bo# iYy ulL<Ѿc 4"i5=5v z`L1%=;tz(,w@^#ǖ<_׳*UF'@J*fgCH$!tv /('WVQ3\B. x ǖOl`,l6f[k=nDɲⰷНFb$h]@0??72ZiXbgh}) 2QRDITƮQکtiI2-:(J?1a23ݸ0;N :'·hܔ|*OyH1q%E疗T7Աaᄻ/ZJ䵷ŷ vƍyM0aĉ ,8uWHs5|)os5&Á(Ξ=[P  oQU ֯K <j}N|[s%ont Q IfIbicwl1׉xka$k/ĕ>w(<"W@\玷 lÓ$1IeH!y'-/&-=2=:*dh\ֻgyJJM Vc'Z< ?aKD+JH׶Գ35-4:[RI@gЊi!r|=騝U!Ql#nK ,זf6T]W]QU땑jz'Ww(@}o1}%$s%vo%H>U.޿&xX֧6L9<{CB MKT3&D93̈E,,,LG€k#_,wP1ȉL,5jli8YqmHMstzf!o70u h0`L 蚘S2Q?5/XJ˔pt-5 ̦1hչ%rz}.&-)(#';TzUrN#qKEoUzWVkԞݐi'2-}h56=4^.A^컡ETȼgy16=Lؚz0fWtuǁªچ6 o$1U*9wk虰SC@NiTAm FCQZ\ᐒhpK_fs1"X1Cϣ¤GHKS"$5S_Qݖӕ;G$r2rHj9IRnE 9\.V$Quu>S"4B][kK ^ME,,,L17 AkPzZdɌ*`}&Mg5J2c(>r="`D\)Rs9c42cRc)^!z>ʦ7$5KFN;W/Z͡[^7)<!ClT68<~ߊzKewz&"$0u {bz7ln)a@N(LT OlꚛDQo9PTOޏY΁>ΕT69%“?am.r8Hp+z9YQ=oSr.a|jϪ`.!UWYLT/ypfB5v{c!Z&XJD6l>}:* pz-[lԩaaaς> pFePHHh43FR1Q ,=vsYi(Â5]J߽{ݻωdr)>>>SSSAΜ9sx0Q7 k@u[(9j"XXVQh~ b)u_$#$(g`Rtx'3S-MhFw@3Euz&*e<:=#prL*5N9VV$v;7(D`(=sfG`G.LeݱcGeVXŬ6o̻[B1(b2~movDا(C"AXX+Jg= 6/9*kiK$Q}"X憖lvHanJ $sl b퉛(Ee'(":t?7n… z~ݺuĉ'M$""d29}̙STTt̙ӧC=7nj_1+W?~ V^mmmyk٭Z fo۶-&&YYٳg766jhh̝;*\\ۛ7o{ͬ/^ &J]?Z ɾBBBOsrr988XHHO?-++!1&(b`oֻ+!f6eA]]xdFi\GwF)Pr .40:`OgRKwJ/#>g.srpz¤0=,)N8 fYe-[awt q >,]@ DqdL˵ D>pBaa!F%ƍ+M4ɓt:= {'$$ ;11tDNNiӦqGsssV||ڵk+Wʌ3<==TǍGNtƣJN:8qLŊ &3&++(O:J.f駟rE!S6(6e>qYQQ/^(VUUgO> 9222L17.''RCLg<%0J_ޏ޻m."݃Ynx'89enKSWlocxXXHQ}/knh!x𖮙WH=sxPQ|d% =`(rEC zvB~Gb`'6ER&Mڳgckk /'N$sv 9ȔСCP8sy (++s¢iӦA3׊|S@P`,))A/|=B󨊊 I)՘1clllp1{e ;O[}V[YYi^iL0Q w$v*ݶQ{YGK#!EsxK3ېw(b^:r5Kg4*&\%3{睘aw&f\ѥ'0Uuq%}ؖa5F|^"t[8D~eY^Yz MsNMM%#~!o S]]ݻo!DKȄC_ yA;yc.J^ 0/_LGGǵkW?&%%A%KΘ8tXG1;;kCϘ 5Nub}L0Qz;jmȏWY"dGVt 챰Q-MXDN`ĊwJ,ퟡ,Y H( QLOxtttW.7uUTc]48I;zqyA/.# (e yv(,, e9? S__DrE?Tu-Lbrr[&p'h407mdee_2~9'pTFF5"?}Q1Q747 <XlS ?Q@fYBkGfVh4zf F-+kdVډ@fD|KKk\I>ftYBųFlEܻaH 5iA!37Rwg(~JO>8q7N?~q㢢xtYo̔)S`+VssO>,SSS͡ @bZZW_}~* ܼy3n{%$$Φ BIG*sc Λّ#s-eY_6D ,,Ru)~G ?<,Xﲊ GÙm,ԍ@d\P)nn/+ WAx0|JQ =6')N̂F &XXXpFPPP +t2hBBB\bL<;s#qV6?nmqۤ6mܤN6ɭcʹMl' C[HHHB{^Ȁmltxs8{{!M6͟?yy7|Bرcǂ OfREtp/p`,9zQ?sG+8> / b9Ι3gɒ%Zv'BzlAu *C]k˗/E0@*o/~vxKwpe`JO2?*uSE2*ht{C[^yRkMhn;kz=K_t-n=")-ke}SK& Ef_>dz6jk#j"駁wꫯr\R~zݾ}͞G}^dɒ&uwNcclFFAj?믿5CԵ#At+DV 迒#%/QK( :@ッB<,,;طo4nBE@Q)ҟJp\V<ƨ6۾-Lwu|l9jG%ZE47K1nC,nXH6ri#U5-ǝu :ZN-֬Ƹ:ubՠ(6{f>l6GGG?wq;̈9s}xgyO> ;=wy'!))K. /?zy:s̢E,Xx@KF |o|QG K/\kѾpVB&… ]+xbZ?"hn$gĮ\դ#<r"(6_{,h4n||wMnE199Q `t|'^e/iԧI  &.wwm)s"SQ?&L/B^m9G_>h9"7Fb!|nh h7h6)nӯ(Q ;wY|}&3 >=0_kSQV|WƩ'4^{d%E0䄐x6 [Z ׍¹IOgzt)DIH>$S2K(}2}^mof68+5_mҵuQʉtF=Rk(c̸X,-q(dMH2E/(G hBQ|?x[w07(>,zf|tF'!!e>---XQw*BM E+ 9zE#FʮKyU>=9 a sW勃߷m.$,!'9+brz|^Jʤ^Qִ1TnG(MCeqom9+QL|Δ֦x'[[giJ#D6ZuB}'[le&;hU7V9]ލ8'u*}@QRܲeSO=uw}#KU ٯ_?ޛTFp8]mI>E(^jv*_XlݖWWb u/SƜ9sjL((` P]j+zܣ}o1IPGQ8OsTӄ,(^Qݑ\]ԝ21 xExA9r5r*+o{>_wf(*bs~q,Hn:lcN961umJ@~;iM MzWo$_EMVW=XQEFN^:xuE~6J07Jقĺ/Qj0eeah ہn]NK꥓fO*=Wa5PN٠ L)K$ɋ;N}w=9]}fn} ΅CJuL:s[v]hvhy=AQȧ(>eee**PJZQoXsɒ%=|0@b}./y!>/bmybi`#ų}gm)h5e+~o+imq~~f'\2K2A'j;eCԚh21M"a6pCC^:uwg z~j]^u_% 't`_J!G(Eqߨwr+aIlC3Q72)'T xT9ƕŇ۟Z[yq59(PQ\I$մ6%$ħ]"ik>LzՕk{ j+b?^Z{+TP%zKwBKR~8X-ۍÍC٥z#90OB\@\>[W݄v:ʵ4|/EBaԖzd tw~$1'W<#Gc>^ - l?tjȠ(@k岲n7ӐEAYns3'.Z *t{N0y;u%'Kz EQgu^ bsQZMOt-X,JDx(GIvhB>#)"߼"IqG1IN_@.Z(4;sb(h=XʈE&)G}EPAE&êNvUz>'̂%]=n\ *eq9ίx w^T{>EB퐉iM^84yѰ2I;6v|r\ _Z)֗q16!F ~wnb[bZ{Ps$l> %*/ ?ׄ,RlOސԯNdIߐp~́3r[aIt4t؝g.̸* i!Aa|tJ"Rkp<[2~Z2EE1==}ҥsϽ /dffn=^߾}3VΩkzKi)_OeY-jݔcח-!&9?rD@m]tg/8qx< ?W|0T.mW/W&u8#XM#IڐpMa .-;WTYѐ_\Fup$J5 kLHDKR~"SۼywߝhZZZ~_\ŋJP( C]t)R؊|uuuW\zZLb 4{jϞ=?pqq@GGo~F&ŭX N(h]F\8U}SE]ѫD<w BZ/%#w@HikкDXJ)_?'~~aM595YQ$ho/n?|ABVɋ.׷R|uUyBX.VjA y`4p,"0R)&&&0;<ܹs__'wU*gѢES(t[ ~?F<"GW566Λ7/pjE00YLRNpY`RAKXq>]12ݙ b,ABW/ -fme*7FbĚ=YmұvM'ṷ3ym9 M-1*)ig產6ie4E'P̥̊zM/%ע6.:Bj)5>u?v7u>"{>]q_Tj  X -AQ +67_~9ͻyS(uɄwq߾m,i6d-4#Fb.=remuiYǁ+Yכ>,ϋJEGcGWωH{Wʶ ,!eّERΜ.٤k*>Z"SWCtf s,f%nf!Ye*돖}k.4WOlqs%)? Q?m lhh@hSϟ?J~ӟPjEbpf(pV=CF;ZG#;ܠ((!^ jO@+v6Qjʢ W@ӭ6-n/yO]D]4n;]3]*"R R5C(kebJH*YGڒztkݚy]hnnM|/oI$mn݋f,<·_dFC0qPPG3|I&o=]X,Oo^y̛7u;;;g(~ -Z=kEE z6?b$Q Jv\UjLQC1A{Ņ*AQRd͢*Y/27uޞ|Rcݎp~AA *mٮrs涨Ww!л2}dGD뤙[0](lVoMT*5p?CGJ-}ꩧ(Zֹs'j/^镩[{]Ik y5Ch ͛-wL2+yopfVտ)`vXpqLA} ?hhԘ2mV{)>)[Ǥ*Lg ا6+ B 2.-^jB45 FTĊd=r"ZAK"ⵔ_~mZn] Dn,Xϲe )}o}/^?fpÆ OokjBC+uON#.(T}1GbD>kz\;|ԡR'((A$oߔBovMV^򖜛r,a t'.J,{2P%Tp8'k\zl(3 S")O+hHE/TmO&(lFR%$$` -&&F.磏>B[,Yd0yfORRZbYt)AUgÆ 8Ea[[[KK ځ`E#?n/aGJ:%<imm#B#& yA@GA@+%.\z. 8xlUQA 6m21Iˠ-z/dFa[nmhA ->Fx)LbG={\VvMjʓ#$D(?(wdΟ?t{| _z 7 Z.[쮻я~}vJz;OHH?ћnms̙E,^8--mFLAEf.swG/ײǠl 1\r='OsKNk_JS*'^[h`.[Úu)a6汾:-/t%l;%ie{'ZG;wqZ9;:u!9wuɏ?u螰qQat/b_$s"S  yB$&@~#1AQ@Qf njvjb6Ivk30mCegܾ/dP%ؤDaU~ )k$XگpZZM Q}zUhIŚs @_PQ TkSEm/!S6g2 "nNZ|)禣I鰪0#Ce}cw&~}rz64zBV2/2c|"tVA X6Kh"4L*v+VgtざKC|NMy5^j""@u#l;2~Zus0vwH{(6/Ήk`Jq`#EP0㶩 YUzΣܐަf.J X*Zܙw,32ic_9 Vvc<;, vER.B>ۑXp i0gȕ*"-UQ Řn?=gOωHiWȭNw"(`fN-,|'ZO`t6P a!}^OTLYyA:hT]*L3.ElsyjX]aD}A{h3g 7|cf$DϾ6U>x;[̓M E@Q )y?b2:1.|7CRm_qv-\4\כ|b*:Qj(7$Hb-fBJc=H)Y[_ζnsϮHAKR.@Q)LR97nX k;ԛ-zȥ՗ۥҟ`.EP0) q&+㲪 BK{ mj"k@ȩR,ousAeAj4Z/RނÆZ"[,vo]~t2ZvQ$sv6*3O>=kZ 8J}O( iyΕXNĭ.ކʹԧѺ4K8 *[JfA%} ?瞬_,Q9zPe@fEhה*YDv8|JP{lRLɭ(>"0|6XMc|Ҙ*OHE -5f>S6+y 8R"%%o)GzB8T~]o0HN{8fhISDIDM)]C JZNOXWx Jg"Ec?EhEϝ4 B3(h f%zr?vG[p &Ƈ.gݭ{90Ka\I1h8xVYZ0ۉ6QJØ 9#4a]mTs' Y@s#,znx)}Y,!ZOn<-])|EPA@!㴛2ί%Q,7nC+¶8h2Ň!3HW\zT7ZEqⅲU%r>õ_l:ԥS#H=R)Z{3i[kX"罖ؐد"y=`@X*S nuj6 QEYUCfDעaWGQzqEK-ѓcr?b2Xls[۶/C) Y&i5.;knV 6kyAݦ ԝi#шͪAe Yf5i:>WUDQj_beoq?G δ'y@Q@v;tUb\xHNyqۉU2Gz8iucxZF?Z M<.xX4{I1Ѹ^K/Z5R1ݕw`wWC_nK3]6ƤKUms*z@eNoF[~4z|*UDz`SP \F&Њ 6;\{vf`]2혚n;rbW$Š%9|z)Zq,))o[Wj5s ν= Q-j5=yXzT]m=kww$$P%!"[>2Z^^BEwExa1 WG vyJey ?:TPΗO  XLI%Nr4,x^d+禫/-rNiPcq]772s"R,.쑌'z)4uI)Y+VP(ihgo8{-DXm6)FVs9T6FBJw938YҐU2# _DCK> L1>X3?{FWf Xf=^簪Z7|on!足J 0m&Ӡ`Tzt_12=G#e͢ʍF&'RuuEM/ULH8$4ح|Ww}X@י6r^<[V$Š%Bl3Z(k5*M"*7[* zίrQ]j")Y]1Tn &ANiMi/F`U ڵ ?3PWћ]ICDf*\"Rf,^NẢL{pDZ{-qК1 CWсj_G z*EkXuUioP P%!Ps K+W(ɉ IV/o:ˣ/͕m3;P@iʹa Q'w]+FYW LMJЁ<|:f?&+'U)ZzN{Ԫ>ù .N˫|bXjWsX鵕_;Lj4Wj'P%!$7EҞRٺEɉCS[5hQ2˓btg+0@w ^Z7i:X.A]˂6Y*r =n(esVD1)҂MQyѢ Vi:uiA]ZV,Y,jl=vZ+rmpq +$Qug>du\fɳ)sgg 9)KOʌ#u,&=V,F~A)xUmChWvŬ4DZMZ&%aetwh9ڔPA ._7f1׊֦x2}2ɝi*,p{Oʍ,9@QC/5e!/âTs4r.:>um29uç )+l,=\B⎴]bg;$1{ĺ=3>,ljj&Ä&4ܖxjUx+*pBS[=csԮSmC͍]j+08Câqr"Q_E;蘯bw*@eb盽$nvz#b!V ف"@"hTb9OX mwhgUR:ac0D,LRzpPh6:Sh=V]Y/:wnwN,/%\k?RTl*X]:Imc$v0uw$s9}rZ!@'c |h *ҵXFY5]`PY_ AEE0д[7,!{4vqaW?q0v VS\L|p7A;8(i!Sr>Φ)/#Q{w/,^ Ef{-Imo>B8 {9yZ+ebJѪ6&jո:L9Qy?"4L* Njoγ|K5кhSjUG٬cDLȩ]ZZk.f!1RqFkr,o {[r:h  ;Tʛ0(r9hīLupX$,  g)noۿ4>ߌIj4[ $ӎ.GcDvͲF(Y1E^ w}Ʃk,cs#SZcP@vW^;U7@!mK~7m+rg\x.>\a[^F}y=(a'6VNPUV.݂t:LWAހK)oi¾ ;f0f{m嗔[Qj#{[;G;[Nvs[šѲ-ysV^M-2yUR 6gp90oVQ21γ|ןlR&2ڗS L"(nȠ ^АY/ #QtډP%ΰbAT_hP6Ͳ2Y/i,шf THbaPP{H`kc$2tN*eKuٺ y 44|n>zGAψ4hcx <5}\8uZnugzVFx^w|✈QioRAHDIݫ}BoQ"yLfmeͼv5z G E 4Dx8,VBBzKޤg/qډzY{084Ԕ 7d,Fw+lt`qYW0 F4m͇ pMe4{<7xu}h([NB֫ڄ"Ao]WVӣ覌.]sSKzsXq۶Ăf 'hr(8ݢğUKەG8/8;I1ˬ?& vBzhh\aqh>ŜW(!yPg6 NJ ;Y2~paef˸kĹ/51cpr N]zS# p:Zazb:uws6!BJsKBALLSʛ]:-8("Aio: :x?$ |fޠAHapX ®G. t%"9TBWAgOd`N'SBKR~Dɪ(~_fd /Q }ΝЗLgw}љZ+!VBz(?(,2ЭinƁ6u"G]VտiiDxquۊpB僦;aqPנduVpRrb>HWC|{I1h쮴{_mqQUgkRS}H$DpHr#sK6jVvY'.TγH*5%*mSE];3#n!hx3hGr+t#D0_Q$k6âoߐ3|Y>f4{H(ΉLgvE]T=Q-6D=?(lBdk]fQSV"AԞQvS %!v߹i%MWO)x\u$ "e 0q^PP>xYU₯٤P)ZȲ/:,vԨ -DZR QEΔ~~բ-0zW~4_qoˉoX32Z]>*+WpX52IJN6bkԝEfAMm9;RXQDgw(zϼw"rot&SbpO3 IwO J"rwMW=ueduìcӮ9h1cٚ$-D1)vq.HPQ{$ aueJAk àC/)Ob'ẄA2KH`HOuKMy_?ȈtCةu_ cEté^_|W4HY+ v`wfcg:4MQBn\`hWqMK}ߺ9wYT5z|O@(v۹"Hފ?)i0,Fakyriq/ER$qEc} z:ϔJSŧ26V_:[ZzǗA.Rè/ꡮ"':kCMyCF\!:^nFhuɏ5-\%lC( g.^(+^ӘhB|kL_,G E1kW-3?6j45\vN@b+GWC.Y]]Oo._Ueeg3b?CS+D](RY?u BQS39\+ΉLTgvP%0i:]Gۊ%?ѢgW$zWƿˣ)h\AŐOvnlz~Sks`7_3?ׂ|;v[R,u}{qGE`E1b_ގ$ݧ v ktN|bzݣDڜY@dYsQ-tJܰ~F)oǷt^7hx}#3G.i lg*/Tf Nޔ|k,{Gu⍣vˏF-:oh+^NK4G[4 q%1߈ bPMCCE}3l|ko\l8'28A30̀ȣHڂ~^i_bB_%90=&ckaQؘb^񒊒5Δ!\WRZ!5> 6/aӫ2Svst]kW|z)uUj롮OT]74QK|`~G=7ՋwԼ԰fzf1Y}"q L'(-7 WYVFFՉ:[OcjÍn&S{9ܞv:.}Uө6Or 2xpG[h[rqQ‰nǓ:,J*eNx%L80Jڟqzܤ8*A< 6noXqs"S^]qa°4sgzP5" ێX4; $GְeRi1/;ӮcN^v *(Ԓ~GI4~Id 7ߔ|$bE  LèT _ a_MzjU8꺜V,UzF\9ٮQ<t9,F">-]W ђ`4uŧ{Eg?TF(q: -I8#n`vBM\X>:Ѧ7YI*0 ՒO`L~ ցI5_8Ɖ{6u" 26J82! D=? XʥtWq;)k|k= )'J0Sn__90eJy ƱmS H~q?ٲӥz&R`[qxeђTu^K'1c -^MqL*l0Ta,{%=tYhso4,h;\}ݙ;j:Sw~s=ZG~@c8&Ha3Tێun@]F}3Nyv]fu0ᗠ=MF-( z/,9Yшٿ/٣;|oEU-禱k> =F[s?\248Jڗq]%4k}}b1}8pn-.TC|,CZKJkKcrZ$ (? XBl)Zq,]vT-Xu$bd+ԝX4JPW+s db:xsښ h;"# *K*JS9)MR"x31 QRAcƴ\z%u gv!TaT(̟~awՈ+Ԕ _DD:t:& 4_[n펨+-JnPV!"@ t׿h9N) vI63֦xp`4ůH. k1QW;j86Պ5d#6f%8vɘ-x&K~\qvϼ-幱_'QQZIUo㶦ʑ;~R9ϑ éYW2v>   `U)nL7Zf5 r!\Bxt :$t&NCmO\e縜I9,(V/VŁۣ>,y hQ`Pe4C'3@pC&-+HB(z ΗGqZ,Dd̚+i{W7]2*R&b@KoυV~5_aAelRx<Ω;v ;P2#Za2nkW]uyQwJG+D cMh'>f9hF=ꂖkxSI):V.qHyS=.k.+LBTLYW''Π.OrGk̍JP֢6fM>V` 0 :" u])QۘǦQsĴ/V}&{ 12 NuTy~^T*W&=' /[Lk`#h4GeV›dG|)( ّGc1Ɵ-`ߒONLQ|e3ͥi-x/, X9kFԕKٚzH~sR22bUZM7MOfv $| zR;Gݙ-I,׺eEyљd we>'GHRV@ujʢ5 $S1I%-Rn:gq9Z"eOn]{G, X6N~OA3=VHՄ^8(iR1u5n1 Փ孌ľ"檪r -8 4L*MzOYinvT~Sw#:jsCnW9=TSvϮMNggY+0_ǖ^]/8\n:dbB4WoC]̨Ua䷷iPDgݑ)o҄Ma v1Y$0:-L%5r nCdL|A E8?{G❮+Ae`f NJ׌L_lh,qZw8הz=5EOKEu^o]6+|QwM' f0G:̂GEՆP#=WX9(=zE")I\CnEqw#y;& ksE+0:-)n̲j4N \e4֔W0͍}UT.[ElQbn;qHlh_FuŴ9x=2pyCRO!T3=X0Z~wE6E&Uk<"5e!>"0'|^FJq "KeTff@0 qlau;(.\KQdw :]4nw6Y*oLA]RP/E]EV%!k7:èQwtG t.l-ݕj6)Bqj^W,{U¶{#"gqC^DŽ]yјޝ+݇ȯl_upOcvЁ?V9ݞ2uW^lTA;/njnN~SO.o''Ae0OK<̻gw];3:3*3 V` %جZBnRZ]tVruY\etEI!Vs9J9uE}xg>(*].#MlaedJTV4ǷyҮ1AIs9.®ĢN }B*Tf9_/>Z.}r`Ae`f $0mUnĊ-VȚ|0r -PTI%0e6-c͍ez/RT3Q%4\q?e@xA1VLeeaٕnmm͇T&G}x|?SUVYc<`4UWpw8ڪ*Z&ۣ^bOJ>\Eޱ(#[/&u%UruZNvBK;T!LL Z6W=w/3A*3 V7E__?|x뭷Bx^rԩ~;_S^)oF]nwvu:fcVTrYqu`۝vZngkww]/X*8yQ |;{5rY5h :b1^:Mz+:֓$G"aHƊtcvfÍ n(y -TtF KHKNύ;Ұz]rn=9%eP1&>;r~B||q驒9ÿzו4;\2, XE"X,~W~a%ޖ-[z|`rY521vbw2!=Pһ\NqPR h4 Fڊ/t>E_+'k74ѢprA@p5Q8.Y#zp.DIX67uhrcw!BBtP-ҩU8>]7f %##'W.Qgw:z(ڕFVmaW.iWkiըJLZmm^[uk{ƻT{71Fں$I,51I;ð0, ΰ 0 /d@B0>9 98o|]SYhч7XOwYݾegY{PEj._Y3Jgyn0}馛/^,8(^au7s|*cٟ>KkksҊVVKlN;PHjh!Cx*B^^^rD_tp3bOw1;/ ѯ$;8<;1.rieÉKU%Kaf_ψ9CgFr"g^w_x$hȞKVuW5y#pT:%fG#g%)uOrceus}[N{ R+fLX-Ys/?2%D15U<ηvz嬩y}x֫fHSU3)qV^zm}ݿO-'uF|wVO7TvRyQ9(¯/'q~pיSoU,E`%Ӗ-[ı:|'NׯsI}0kN?}v51O5 1tsj܌Kʼnp8}RU"QR";}.s:k2?FqASŪ;QdyvGnIDXPؿF[XhhlmƘSČc G]]4Ln!1nZ5[ŭ)n}ás)]mqU>[,Q"Dw(I@V2=Xt:ϝbLr9kb2jbt:Ħ&r2vU4LI|qbFʆnJJCRw8JH烧$ڢSrNYbNyٙ6u_ZqښEKζ57%,5ɬ¯\ЈKl\zΊWNeT}J)*;Y,ʐR^dP +>qZ[[=w ,sIK鳴j rvff%vIgNyn|Vk(Ɲ}UZw(MrRt=ICYEm9kS)˕.>k5w_y¨edGfwM)QbV_\+nW|U+C 2U%ѽѿ;EP,+nFql >oMꫯsIOV>2oƆL)nL9b.;mIn>T*Ɵ]V~gՐZy~_Ae긎r[^^xsj>8xe*L/8Rmn>?¯Hw~VSl^SUe2 `fX4w\q\.(6+Rq&Q}RNX^zT sqbXP>f 5Z`dm^xnQ{첉-o7(I}׌dnyskKVo{}ۿ7,)zќahߏ7IuTWf(L\s8VN<oQq&QlڢLvج7jc^/Ҕ*sRwcWM"C8&Xt&g3hjr>YpWcERX펃?|thqڪ]{֢zGYV2~Xuw_0K{gEn1O2KNr뷚k* rv \(]pt:\.2 $QTeuNPvnR[͍X+-o'[(6䮢wg/}˫<ω#I c;~dڴv,eǕ]5q_GkvKUYYE`%?.UeeN)v9$ͷH_R>־vS}ZM+ꬑ%SWz=<-'}jz7,L;ˤ~"I"(Ol}Y=P|mw2`,8˫Bl9_`pлzr~u \'?ͩ%zVYE`%q"##=wƊr3,Q?2/^5bK]T>8'1Nri2e[NTe8:-.\*v%20ffH,q^p;[%__؝KNL,-2 zӣ׺5C]<ۛ?S8 \j 42kmQg NƆ)IEo6MqO2?ie%G6flnjyY4oY+6=eisͺZMZʋV;XY~ե&WGEcʲ11 5ե67Zަ7K"Zo5o]3^'a^4>ۗFer3]cG1R|g8Kžݚ7r\ ~,+ZUaw}Ad~KZ{Ƶ>VNހù$"5zFBK?5}qӵ-%ƹxm̚crC]ʹM^v.m곴ZP={ be5uQ=RXp_'u"uڝ\2;ʛ{w~.OݷW  wMLmg$ݷ?O>~BK"#u6;sg"Q:뮻n޼y/}-Z4OfR*4uvXz:[qLYl@i_UũO6JY~v)iEzaIʹ7fsp9RvVZVQzm8jY)/~xΛm8lm.{sċIJtwvM^뤿k K_qvDR.TVVr8'}sbr2̏L9CQ1X/HՕg9%R (M"B4͊TM@r;Rv4$eOOI|/)KL1_vd$񎤸1|G@鏧ńꦀxaǟ_|Qz!th/ٓ~,1aN?^b\'Us%U:aV,}.\.ǹ2Qv0 zV >mu+j5/'Ds~vji4.rڬ9v)k보74* ^`TF0]tCf;LZ HIx| >:RT(Jk㮵[Voܩ7 m\.,4菤,1'ɩ=ٝ5ݕY7up+G,Qde)=t&HU {,ټ ğbr'u9+AKM?`)) fk)!m6͂9;o]*íÏ(= gtـgkvvTw}ùSVɾMbЇ~nWV[S7-iըTmi&@xœLj>){RUh։?m>%vO?mz)?b9!WukU[3Y m2%SiN7r/Ǿ*tIfBd:+\<Ҡh4p\S}U:u6(o~'Eqoǟ]Ҕ?8UhҔWHv&M#Tw}=ȍ^XG q_?\Tgx`Tڔ1QR}*+c?g2׭W_ ]nէ#Nr7>:O# /5Jsfef{ͽOs*ۓkcɞ}hz.Cd"Q,Eer_iP4h*dٺ{46:TOwPw6+mcZ*i_Qz)kxsؐ)6 m֧m>m899/֒r].ePy:N瀹`I(- N4:{Iqo s#D9() =ygΆ :DU{euW7i`mƘSHYbB]N%%W zZҊb-~}5kܶO>z?>_[%'(͆116[wksx+dy >Kӵ aP >Aݙ")BΦ3Ĕ_;=.9K=$ߏ'ȞD><]qU{[Uv=χY{y,HYϻY$ T㢉bBkU1Ë~n8$l0&,.'n^&76dH+ XGt*cnWİsB4_4BLMEa"DC6y$DwҞ¨gzXԖGF[lҦ/J['w'Rڃɫׄ-,* `oA7'Nwh‰bf_~e] nZbrN<57?#qS}ֽGA5:E@_4QLO^mNcSz^ҠR(.E%sTo{.EM|q(^7։f-D}áVw[IJ3YT5X;տ9ݤvrM+W bO{cJ+;zf/{|QQuQE"QT + ~(rĄ^K 83eR$[IH}e3ė4w e!mn,.ߛkH(MF_Q xʿK~'.?qB$LNݾk7wk-8\TfrFQ'+YEL+ Jb~[W `FHs rvy^3riaN96Z*BzV+Y_:5-"OHݵzkI[M,{E\<x# g6OsҺt8]˯YsPcdTvPY|fW1Q&JA\i j)6ԥMl~jSӔEEufi*O};iߝY񵵧+ 8E}yG}ڵu*,_%RXX'i@=}wN@#{ή5-'@ݳY$4/+>x&.ri&@2f͸F_SMs'|O͐ΐ* ;.KҦՐ$d1TQWl;Qj\|D{S׭;%DjU<8K<xV-H}uۡ1|,Z(w_^]嵝UgqE"Ai﷚m-ōq%wd~nBkc1ŝf!}O`8QtVO_]bǺ[%WZ$$ZWk  W^PUan6U56VeVq{MgGM]l֮vCkT(hv}eAծhIluq(6u?^ç0]k}}oVZ6Y>T,>E"AP7eu:˛LYu5E sweoJKZy]W^D_%P30 Ԛ(Z:+!p*VS(UB⃿q jqWK:j+ 8;p;N߸ o_QZfЅk4'y&:j8+o떲c%C|4l2Yχ0Xl[~hqm0- /gWV nhߔR"m>7*iebHz:xR&>DMLE<^ }gދj"F;\*{yp;N_?׭x-JW [x^~ѳ%gj|oʧ.;~jzs2 V4~he '<.ަoO7$‹ wdoJL ;IixBŏp:伞_/D5vS[?o2J^-'ҏPr Q㣝6Ejzg,^7jh4˫äDްj5!ܻ׭;xCׯ; Ox{E>GR(^2w>~ ;W=p&B_']=Z=GeG0vZk!̞SP K+QT,>;*7<VLjZ@`tQv^aNF`NƖtꤸdN/LNx'#e]~'j*Mi-.s;S)7c GKm.O}[bޙ_g,CW;swO"Jps/f=b,f-Q,>$ " ~:/ػ>Kko1TVoTFM+ ,ޞqfʆtڡse1jN׮,SV|L}mRKS`mh2/Lx5da4Ye͙-էА׾V8BoB yPs:޽(^} 4Qtn_]VM{k;_=q+mlʮ8byݺC=E QALy2}6[wMڢknmKTFW2J>h8 \ H}31 '8r2t4r9y{\PXhmBibaƱE¤}w{F5yMeP,ω^730gopE@ȯTyֳ;ƵwVZYY$4hڌ}^pfEQg 亚$0B( H;/skNƖ̔ iIRľ)si#1IojҵO(/k%k0WVPܘڢkowwtYZ[ e'Y  ʼnFS+3-L͌?(MoCڂM֚Φl[ړC52z7)n]!QAS6foדNfl8?{Pۯ/: -2ܶ6}wWmo:0{s֍iW=_.W9|W&H?_D-.,H&osCiPsUxI^o19>QE27zXNU2 BHY3rqu\yɑ])d.A)2W"kbɍi[K:˻j-M}VEm>|xݙv1ɸEm]=mEߥHJs] s:$4h<\]͍5e%Gty3S6hbs>➅en-y0.zGLMTN՝QOS$L!QA9S{l( /.xh9K_0nEaҵ,N`) u5AE_ LڧX$LYܠIM8 rgs^0aH^^ }Wi&DQvAR4Ƞ&Mf¡xSi\WA37Vf]>YĐ(*Sy"_ ">e P&/?9z՞1GwqN7*s:$ dt/3(%Rhvxk¡xr†aOoGDwv )+!QT<Н(pK/.KI|?'}sqApeyDQRcr89[z !w͕';I}$LE*qDQѯ1Tl#4A~e)㹟DwqAzX&DQ*?hvNښxK&/N2'Q]dnNXL Ybu98nO4A~k-Eygs:$dZU_fghHߡ ^;$>$) @ \+Bq)}WZXŧ2 EŲ,}hAn2rƴC >WeH}tton鹩31IDC1q9yF=r9.zE2b}UsJOce  WVvK݇Dw;be01V40Zkh'[Ւ3H}{4V]*;O`eE  K!9^MQc{(uDusjM2Oce01V40S8_dp5I}Ȉ9ĭ*(2 S,E ̔74A~~lu]$TL\%ҧ2 +4A~vȹ?)+scx+s[ߺ" Dܺ;XVf`X iiC k,?(!dnTLFh磢@qޣ7*s:V40춮c?Ro@FuJ,eŃG^hǣVs"S( ϟr:?̍ꔉY|g(0uh`:vjR¾]=Q22OSwYL+6MI 5Aی1},)DBuS@B{/(n=wXu祃jOYC`EfiJ; ʬ5x8)4=ZeVϝ9E L˞ ˏg̍(>7: ;<79opTEu:L+U95A~iok3QBzNm~֯OM黪9뙕Y|"SZkYMMi~27,>:V40kR¾ 3~2!:~XC`ESf&ȯ8]y*R)ṘWde0QV40uS&8e5ɧ":Y?n蕬4獕YX i8 ӆQ2g#:Y?u;Hf!Q`X Ti/҆|Cg* JQMŬl}/Sn&n<M_YzNR)::%]* "Aos&/'I[OJnCuTGu^Y|e! X wUj/>- QyVfْVh1~w"UuG'Eu66X u6e$/o3z,Br::Q2Rg&0h[l}iUfPQש:\DiN25#ApgE['::SZ`X WTnz2OnCuTGu^!Ak= ܘ6E?܆ꨎNe+iC`EdM _W[u~ QMJSW[.9 Ap:k~ QMt@+?k2-:PQGF$xs9@&+&M6Y6TGuT7ypKZ{w"   LLO{6nMl48r:P+@OG5A~ק'PQBX $ ˉxNO$:: A/٣ K V_WմPr:P+̤} 5AیQsm@!h@k[2WN&:4Q4 "EuֽG qYdrQi#r٧JQMgEc ,X L5y4A~iO':s9h@MI ̍3HV4pYcJ ڂg5JQ@!h`lN-3 38蚩A*EuT AU 89/T A`Ech2iCn͟WB*EuT AK˒Sנ7/T A`Eb7+EJQ@!hu>1|:l^*'2m<.6<巒T3P[A/n1GyeQ,Qf Mlлc1Лy!zkꨎ  ggVWY*3B﨎2X ;ɍ[I"z__W%::G`E̪$|m]-ꨎ0.V4hL! gE{ꨎ0^V4hL1rb'w.QՍ$WD X *? S]m>mwTGu.g,hhm^&fS2:s9 4OFuBX m\΁ӿؠwTGuX m ķ2>l7;:`2hYv65}wv;:`hY6Ί%{Q0yV4?r/;q4QV4?rҤWŞ9 +`V}U,Ll&YI﨎o!AfٓjC-U'QEV4?Kr?_WK﨎"AfuhH{WTgxO"v9.+{okjjqݻw/^x޼y4sgn+YoN|M=@ooN:$շvO1>7~1!Fv-Z=*Veo$Eq0yȏmOGV3-rCҒG~( A`%lٲEÇ{)NY\\,voy!$ Im 8ʾ]}Mf,qen;N j9<-ϙh`BcYt֚Ӟ3!ͦ/F{*{=g:z.P՜=27Jqhmm&v.X+!Q37kD[1^e6u;J_8h|P$7gn A`%x8l6ϝbS꫽ECm}mt/zh N=]_|WfiT{n27a(Չ[1X srybW^镇(BMx6Fr;#"T QMc9>?bkFyA410 vx^y"?.!q4unRTGubEXp)V.Cwwή.{CH#BLͼ36d4Zk}:շn6jB`%<8TVVzbWB>O%Rr9]}A{چ1 cKGw;;*~x%LhCTGuf3E4S,Gn{ڋ͍img G-̕eoWɉx2آ]2yy'IAwk-<コzkչM^^P QٌDކގΦ6ctX}*3WYCW<ߕ[=W*Vח|V{ІfV4^ڌ}wk.US6HuT`6#A^GQe5P MϊQ/;_~Ƶֳ/"@rLY0h!]Iߐ*#@#( "-s,+(`6#AYur"RfV4^1NN$@v L+"*.D`E"Q@`~V4/Er B`ERw榾 ]`N   K}3˞EX @u 06+@B`E9$V4X @>+G`Eh  #A|VoL'*A`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh 4ӉArX @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @>+G`Eh  #A|V4X @YXUUU=s7|__SS㕇ȼݻ/^E^y+ X=37pl6nŋO!zZE Q%K|s'O!}ZE:@::@:P'|RԨ5zlkk;,X0ᇌiIꨎꨎꨎCnFQf)6ΫzӒ(RQRQQRQ'̝;WrxS?d\OK tm=S˗/MMM;,ZGCdG닉Ej#_wu[x?hѢq=D}fi+Z[[y _UUݻ/^/ƞS%x **X"3gNttiQ}<]^PodɒN}Kss$kJtk^R=E2S[L: 6L.6}5~O8bEE/ZHXPPl}#6充{+A%%%utt7;iii6_>kJTcUbOT֦2O<^xF)Fja)fddH#GǎFy\Y*Qdy_T߿nQ>x̙3gӦMnYx0K.I0G:eĉeeeD{˅n:-\p̘1?MYh}MmeJTUz3eڴ^=Fθ,F}5ŁYEPSS#Fr+>/Osy˨T^ӵw^3_BJtw<{ZK*}p8nQ>xGe̺e7.0 m۶mΝ;͑Ίud%տ|C~M>]ڟ{Yf8,,LMMMo舌|WQbJTL6/9sf˖-999/2rNq/Eyiooo7ʡ4FEEK}T٩DbtJv?0//ϠAϞ֒JvD7.Uw(r @o\`ڌ3͑KYY^ߊhIW_%W/Y M{IÔ)S<(W^gϞ]d|[:;;KJJƍ'aoϞ=&Dy1b%GL6].SjYl߾@0rNq.ŐiyjWByGz,FT=ztppڵk幣'}Io+Q}|Xߘ%˖-3PMMM2%[or^ Z4SMe:aڴi*F}8}N7vttHK vz,FŨ… Rq)))e}Rn2;V7==;ޮD_m<\"}=%SnYq~fѻw6G:M<ǎꪫ ӧOi |69 Mkkk7ڵKe+-[hfJt9/D{)CԦ[ˬT1\1D)$6w[$''+N1r?bTΝ*;vU%;n%Yx?Ż7?TO6%%%3g`̺e=k֬zd圡{QkKss-o-1cH{]]ZŒcUU-kTy1h% L~mjkk%xl4\1D).N7ʡ4fgg+ҷd]fQ1*t곾x/!Yx?Ż7?TO6ƨ2Jfݲ LC[re~~w%+W9 r^hyyyڤ1..X9666Jؓ'O6A%Qt2S_.& n0\1D)j*iߵkqϞ=O+ҷd]fQ1*Z_]wtشiS>-;KavDn<]*$___(u /0nڅ 7$ m&}7Go˅ɓ8k,cXVV&a߈ټ]g*kӃe{n g1\1D)]|ۓO>RYYM.)OQg<@(Fͮ;;;[~d…}xg%va:m%zؾ}{FFgd-+?oF{_o,&1i8~_wrӇjmYn]pp?c8{L/4n%z0/r6=XfeҤI'O !a>YwuWbb&L`YrCyDzvϟ 9}Jtw<]%}lx,XGɬ[VTS;C=?l^ohq f;}QDDDHHի+++/_cǎjSڥKRRR222vXI%$$ȵҞ={ZZZ Qecssi*уy JtUf*`kS%c-\P4e(GR;lhhbT'S K<СC333O>]WWtR9x񢗹vy*F2;jkk/^,_s5?럍ի*ˍSgJ썍G{{{||Lg|[V dp/ѯ_*Niґ;|0٪7Nj6;FZccC=(?OS'vZ|nwݝ@DPq6U/**.6lܹ;wɤ6}2segg\}999r}.]Q9N1>/Fn;vlnnTͷm%*ի*ˍSgJ썍Giiizz7d[V@o ʈ#jjjt`?O7.FvѢE)))K.pB}}.}qay衇c=&Ym֖!CHQX,ϟߺuĉ ULLLvv϶mۤ%!!Ag_aY'ysZz+888!!aw[lZ,9?ƍ妛n0`I/kth̙ԩS˗KnQDFF&''G?ڿ}Tx?CkkرcO8,_pŊZKNNˇ9-L٪Uo>;]]]8}DGGk\s:OG`\\tkoo7߿_!wϦa0ƌ#=޽;22RL4L!oN ݝ)?E[\"-aHH~gQؿVSSoޛ<FXX͛m ˱cҴ-ZdX\>i`Voki}bUU\{_~u_~r/:9CgJޝ=l0wE0*9稧8,}Ŋ}¥K:'hgaСCwiYlv8~x90aBgg#wE0&M$zϮ]rssSKA|ț\p믿nL{YZ7|E| X!7̛7O"{'?'uDB;WXѿÇu[ssnOK/ŋ⋆i޼y 8^˗/t7)UVV-Xz<`slҲdɒ>-Z%v}KqرcZˡCg+WVUU566nذ!**jΝ_櫇}YӖL@z~;9x`[[[II:$NSLѷTWWϙ3'::zEEE%55u'N?zO~2jԨ}k?z}HǏNisKAA71rիW[!oN qI endstream endobj 162 0 obj << /Type /XObject /Subtype /Image /Width 1734 /Height 958 /BitsPerComponent 8 /ColorSpace /DeviceGray /Length 3244 /Filter /FlateDecode >> stream x L endstream endobj 165 0 obj << /Length 260 /Filter /FlateDecode >> stream xe[O0+$RfJ)[(FcԘFX"e(kt399- \3<~eDD!HDL+*Dx\N(6ঊfr !_,HH;0xiD$V$$jHsx~7Ð>|$m_v J^ԍ rĠlWm]^D"muՇ1or*~f=‡7lTk!1;<"B eD endstream endobj 139 0 obj << /Type /XObject /Subtype /Image /Width 1691 /Height 1096 /BitsPerComponent 8 /ColorSpace /DeviceRGB /SMask 167 0 R /Length 157605 /Filter /FlateDecode >> stream xyT'i_L66mf3i6M4(("%}AYD%,n!*lL^f::ü_:f~o`u_n+((򲰰xg{رcy'xܼnfz.oPXX8`C_z?6@oĈO>dMM駟З<}ԩgΜGzNNNb47vvv =.6l؞133SlmQw+"WVVjn_zu=Sb{[[F_Gz?خR47Ɵ罿 =./)+J͍bSO=У^xAlXWW'6˽ =.2d؞Q|(66@ob{DDƨ(ٹGzb~zjoq!X3@O9rs=DΥmtOK(/奼R^P^KyAyHhݠlÇ/,,^`z7奼R^ Ky)/RΓ,))177կ~ZXX6to. Ky)/(/奼R^P^KyAAy)/奼R^ KyA)/(/奼R^P^KyAyA)/奼R^P^ Ky)/>(/奼R^P^KyAy)/>奼R^P^ Ky)/(/>奼R^ KyAy)/奼R^P^Ky)奼t!ҡ0"D:tFH}"j`hpy0PBC`Dt>!ҡ0"D:tFH}"#BC`Dt>!ҡ0"D:tFH}"#BC`Dt>!ҡ0"D:tFH}"#BC`Dt>!ҡ0"D:tFH}"#BcBM 4`\t>!ҡ0"D:tFH}"#BC`Dt>!ҡ0"D:tFH}"ӤPfŊf(X虠Ғ O3z8[( Q 35- ۾_/u'3F`LMn2 Hx>=Ss\`!npIKOˉ+)N(hin@u<\ry(pia("+YS]Dm=S4J+s:Jb^N\zjDB_T !gzyX9eu[GUONN<#'5WTJpLPiIdbv׫* %ũy9qR㢽չ.[#7|~LEGy&'k:CgܬܬXMw+sԈ`ܷܲOrd?qd?VSCG>TN_tI[GگOP_57aR(4O]o^+nI5եܬY1 E+G#=o4<>h}d?$_W<ɷ7W(-t1S߭Ө.QrѭUԘDdL'Ε_yY$߸hG4O~;]Ǩ'EE$'du/|Ǘx82'241?SS[[SMuiٵԈӻ" Z,/e;|wۆ>q!(ϸh8.geι]tbyYvUE؍ꖖL}2gL޽S57VUfzh|ߙSn6įe݇.÷;:{k]>s= aeEA?KY A=1.8&@Or"ou)%<%1$!GGy:U3wc;|b?\٠nBa˄0;$,QHy56<@O>&@OZ[=F鬡}OU--7kK+oe^(O/QHy _[k *d('!L $ ?ˀ1n.FEtX&. Z~{y2]c;]Ǹmė;Uq 'DžC!5Oh-utoD:rcagvy֑GE\J /)N:#hi+n#n)nߛ fAcK)ᝓԘYM)ПȈ/=5":3$`N1k?Њ7|Dܫ^L{ 2[kkcyY߿nHˉDJ9NƳ*'֔=#1etLMkK"\wn'^%iR*EI:>JSʎGD:ZZkK)2Ӽ&z8ӌ 9e}%|k2^zjDcM["SF4#>?N?Ӎ\쇋O8␜\dh/oh<4^vNƋ./6tLFC}x|∃m5kjn0Lu7.,|el?0'uHǔ}MudQ.RIqj[[3u"'Ww^*&uHǔ}^(5եy9q q~GC7E[7~|׈OՖ''Wv.^fgij6Ec>F|>!KO(/V(Z)PGGx!z∃d->)^d.2xhJEeEAv晸hU^V5V~x8:󧈯/n{>>07+`UU'iMsՉ#"D:^D|5#>q.ZZb*Qb ښ=KD: S#R/.ӓ>6u~0?I7/|vM98U0}Zkk(~X5^VZWe.s`Te q~~36~}C^N\[[35R#ҡҒ LL}ۆ*/:S2tfu ⥣xI֖3U4-p8ʊJ%"@?PfŜ͊U(ںM{{KIqxe~fd7Th.OwE=YxIvYL7:'㉗^lPs9Ol=#ҡ JYYQp)%h膞mVWZbѩOhiOO ^]g2^rBpMu)="z83}HSe5zkō;8}rdΣ"\򓘌wt>\Ϭ?#I ʮ]V* @SnZiزC?b}K;"ҡ;% Zyn6 {fw~n|kKIRV,ɹs.Ӧ(oN-uK_t>%b5RDa[}wX<ꐞQS}BJRW;yqq~GiuFCCtEC}㚹[>㚹?ˉkmmVHuteFDGy<;]8{"UX*'RWZ7pWDzGcBM=\3W=qs^mM9&;L\O`vQMyYv۝a]iI(=]WŃ Á@; f|'^xyXuK+\;57+||`nVBF}3s?)^we5@_ҍ/Q xy|CgQ+;jKr ]wn#͏p^RRODo/J=#ed7T7N|׏}\^xA+s9mL 믈t>0(<3W܆Z` n'%'~3]wuP@LܸoD:t XWRNm4}`,z83W}fns(47&e{4tԈt>0Fw=3W쿔ΙT :*%p|#u㻭?]B_^N\MuRA項H~3sݶ~ř<|rj}M|@C@|p3s93}9ÂWE{)(Xg抱uƙDh͊=PRU/l6:3$`~P]vۖBChl홹#<3$L}3Qb {[}wtCCi\}wFE_:sƐӨF 0Rw[ߞy&.nwx$t>R(z`֯tiR41jmip5#sHJ8pȖ}Ow~=NuHI )*Hijxt>k=.cNۚt%ͪ0?Vb8 G$%(Ojt0(D:t;y9qy~Nױ/pN9JbMuJG$R΋.y8}}<@[u#ҡimmpm̴Ox;# v<IaEu{.Nh^z":rGf˔"AiIfb{[RQS]Zt)%\}->֑8'WW*;3> <>wJ6 )~$'^[\ ƅHLh͊9P4S>>a`)uʗ~eF?um.ۣY7 xh::e'g8 S>tyƮL"\./!"~WVdgsee݇^VGC7Y*p}G]eo4RuuQꔏu_Py9qqa<|_6r4}P^m˔oƏ;uPEy9q lW'=5BRhc;'D:tXԫSb?\|V94) u'W:o:'/ה)d}}Z-pQi]|֙HZZJ2#㢽\wgaݝ+>+n#n)n/e RT[S]*ͪl9~eΟ "BGG܌w'].w,lcyuש}ܟҒKgv5ig]Htv\oV٠#Fy:"+*H)O#;Y/q!)4!OL<8}9n ^%Gw!Vnvu.貶=m""bN?A]:98Đ Gs,XRz,GZFJ쨪,߅XRwY-sbo^cy}QcͫER/='nIwsqNTGd1w#G:|QcbXw1e݇gvo*n:nv= q'[.;mvdaqx?vd+;O.=zZޖ溫E/$:g˖ϻ<#J[ip|a."ܷ?*_Έ$"GOjkknlYS]*3&'ێm3O<񄹹yQQ0.< J^ȸR,w9#RJx⹀Ι;:O>Pв}}wOrL/38;⳱\|0qD:ߟ5kcty :ի/XVVF􅎎溚Đ.@1ؑ~r9m貼"8HD:ߠz4bĈ'|F~XWWO[XX}/ ?.$h~Q^^>uT͍3g~VPP@я8ӧ-F'R^ #Dc GNNNb47vvvtSߩ2g):v' WUUQ^ Bc GÆ 57fffSw[88݈Q$57nh͑9RR'h1Q5G5_@zKsxx9/\s3,~5Ɂv[5Uk4 ͂o{8,,jz~ ?.T*͍C?yw? 3m49`{KV8Mtʀgʑ;|RV2 q?FRbhERrSbݧZt] 96l׊AXfnNh2ݨ˴JqIiXXMЪi3b>mZ]^bՔ3-'NuNs lNDlۢutiMCXOL:3/_:򯖔h3Jt;::Oδ%WXL6_lG}}fJKsyw|ltg4kμs=v.<3[#wxfc-Eyeo-Rr$]B6Һ9󴒫 mήaeq lLV~_gd膷ׅ;#zKP8?jfMVOS,y C<"x / kn_~0jv[čo-o)SIVwk7lԝIe;ey[v{#!i{Gb3ŸpYٺ9UAaVN%GݝKZ3{v@;DA2eLᬹΜy$Q9Cg GC 57FssP3q7&qzI 舎`a3uzPp6~ի;]{Out*$N}zRRR[\zV&$T@ A](==]lo57?W^I__{FzKW6>55T0A %2u#G>s 8mu ^qўnޤ,Ԉt Vsssdd ZZZnPVV6`ÇVWW/X@|xuU]H\Vv-f-;ݣas)KJJ_=Co8D(0 {XOڵk0qD:]t}W^"kܫa?jK+mpΫ0)z]t}W^"k2ݽEmڱ_zF޺rr'`L=>D"O)j4G͚q35Sk\!<6^s$_}tW^ڱA#2Zevk.{n,)^a{>wDX&)%&@);P?ZKo_{l=aģӈ7u=y+/ZwO{v3ݾaX wح1v$2UGRӸeg27uӡ WusG-GTbTFJI~1ts/DY;|uH:qud`@69/:8Ok1 w xMÇvs4F N'?w,(,xνMWE&^!OGH[MLUJ uuA!6Jw@~)O0@_ufZ?S\W?h簷> >xO^؛C| #|pnR-&-x;*WGbՅt-])bKEmm?~>!(8d)2%1Jt irXKx{s4;'JUgd\: 42^̷ =O;c65O:H<:9B_8 {I`Wr7^JꎨO݌}DPq^z[,hgCCZY[ąk~aVӷzjٻiTdqh~RַI}A7:R־.%S)Z?s홐Z 箐m4q8F7G;ԩFAb͟~>_Dt knn9vz*3OMoL>h17>eOi3gXo7sŇ@CgE=;奼0p'oO./۽p ":&vμ2֛>{αm] x}@_n~Lv-7*p1s,A!MMM4t>O0WֳozN fM7UTI))-].cISC`t>Ѫ;7g\v/o_?5-}U2?ǷƋH AmN~gB_(PxUy,'LyƈH GCQE~<7gY}A?+;g3 cǍoQV^NBcBM4^-M^a۷:qS]){?z1VJK);`py0P0XMʒWzz%%c,FgfayC~Ae K^XϾqj\^oM9y0dD:t`Z=sx-zv =ee82[zMRJ e ֛5{Ԫ4=m]]PpfR<`Pt>Vwz!z_z#oh 0y.^T*<` t>74f}ckx---ǎGL>Sz~AGH){ߡ>Xi3gXo7sŇTxt>)wN}ao;B;gM=񈶶6*<D:t?(9Dz?6+>|RJ:0E2֛S)NEG 1^߇fSY98YX;nxkWwT#D:t Y>!>Kl,{_Gk|cǍVZJ#ҡ 21t_fS~Ev*q2;L;Z]-)quci5z83 [ (<GD:t@?T)k(Q&ǥ܋9bd\NKذbLv]e.,>`W~ڜ};a.G%9r;QsSBATyl/ߎ63kn߸Qka5AQv@/tLYuUwES+o{Bfhu52C/&3 2CCfhb=}'ۏ:!kb|2o6NtZ#X#7|+ ^:U.yce͗b8qxSxz؁0#vLk犽B,.z O<$.J!R(KreQ+%nUJ%CPxiu z*o_ U3V^ADgj4Ϫ笺+/'->y57e[Z,c2C;};#341d&Z]2F[Mhefy>[9Kh~;Ah>Jh[}T1Zwɱ徉!VAKȧ0b|WʧʌO,] ~y/O|wD%CWVAV98qxWgΧխ޶J7;DVs /'hnvMKݗ<6d]Ï+/XϾPuuuA!6X/)%ERc ?z&9/S=Ftqo'ج>qAۑ urcA_<{ vz?>]9GvG zi2_me~au^p|| sd=_^Vcqdg4bg}"_g:pz^LضZ6WQb!<9{M]'ؓ-"GNJ UFq J*oȜD^~Uk{:S͹V$v/1'C b)xRo{^a Q/Uws_ 2x7'n{BK6k-&vu]nۮSwx:cS͸ fZaxW+c"L xWޥ m5zSeps zz~D4g1>DhoϷ'g e6y:UBd0SA8u!Ahr81KdVvRhM-G_guFO5Cٹ`U}dIMROyX)lsw9ʎ@yOS??L)y:{Kxq(էόD~8h/8l8@uFvԅ2;wWصܨ;1eL-X]tLlGG^RcUTQ Sn~WM!^'u9ԓdl ~i~iLr^b ;Iſ,޷o C.P#)a8՗l7ll1) ;l/5HĨe]-|co *uX檯r8!F|;sL'gdzޘc)#_Rrι93wW5_GF6sf}3o@gWec=⯛)Ig@g{'-L Z[jKoV([sҩ,B'Xێ586+3Mg۷/Z\~CP(cb[ c9vDVv-2ֳ0jV ǂEak:o z "c?O}6,z-7/mp߿X/zvue>DvN-fǎ;ݣ: NoU=cOb`JSU-Dyeh뽿Ɛc֪4Gܫ^}R~|cǍ/--8@Xo/ug?x{k̍+7RcU(=0Xm Oԑ0?ĜT5i!/3{3S.!JJ{=v-'0ji/L \M2[ =MHǔ}0pm E@7'c,$>PhИ}ȟޗ^q>VԱ^ޕ+SMMM~~ <0X* \ql[[>Sӎ_V*zsD:Qhε{N4XOؔЫձ^yl~?rDyՌ35yOq#OK.W|OCc>5wޘcuDa{hjGXکh>D]]]Ppg9aҒ+O^U tD^^!)`t*eXٷ[XuÎmmyCDzw#Zm5i:ӳ]hzgZ^܆}/wWD:1>ZzuCa{ޞ/8l2;YzV]60xt[{["O4Kz, cWgq<@#}q;hP@+=js:jŪ5Η̸uՌ3 9ơ%|+|6"SFP?~x6Vf{ۮ(8p#dwlп<֫27~q',Yڦ \[;zb.g7聖Ȼ+"SFPT?^:Uz뵴*ŇO`;+3W<}szފkRRT[&Ȼ+"SFGKXSF:rwTtħcnz lEEkjjC&Nޜy hmmhv5)_E%|fjx=tT2 ~ۖȨs,~*=%\Xw! )пE%|0e]&[X/lঢ়^c=Jn&YXMpuZR¡tDއ1s+.2 >+mĺ2Wv{ vo+/=Yz6(?J~AK[õ\q@y+_{HK)`:Ҿ)?v{j vo+/1*c0ѣN{[QQ0VN[xIdvSfK)`jFnVz/NfΚzۊ 1ֳoz|Vmnn9vĜ u Öq5ܫdfM]x;{+Z*toVu!(|x-i-!/wWD:ߊ;Xݨi{[s9ܜeyWv+՟0 @o0INn؎cgK))D52{z=k vok7w:cb{[CĖ끚6sL`#]c?PZխ%s!1et)8_ ljÍJ/ZϽ#k=>B8dJYM񭨬0 ƸD]2ЕY?mӯozoynhx0p;ʻ_ĨQ6bᲲ7oq0T/`\"/hQXޏD]26=ec=kɼ]7 /QlԳ6}в[Miy1JctD["ﮈtL,H3/^j8/jMħcnwϿ(/wˮ}uuuᇧ̘%cY;v|R>TԴtzc[ouvɻrct(Kj'Sv'1etp+r|f'O뱃':+j;\_#c?Nsh*,*ea5AN[zMRJJЗK Mmm0OtLܟחq㇨cbC~í d;UzͿ^ Dg&D]2x%7nzXo\CaRYc=!+כ`lN'r<1>K^ smKA\L]*5}Rywe}Tu7XjՒywECxpu5kޓb u [IYPX1ҊzDޒ?=/%4}Ez;c=1Fn•,CѨT^;}|yJ?VuMMPpȄSdpȨ9K9ٹD^myECЯʺ=/N.np}wxm5zc#fFz oh&%/Te7t2/n>dw_6+O$[jzJK9r)`DC;7 uqwa_P^^rԴt?{Օ}w}ͦgl05%E("t2TRMz0az G2" >y\n9{_dR i<'"w@ҁI3Ny&ENrKe) L~p#`tn^>˅Aj![d&Oz } DC-y $h}IY5ͽBY/@\g%%)iJX,x56>nCثNgDzacѱqyj.u[ 1 @4ZSޮ3zh4ZJjjPHPQ Aѯb<~^ wIrܻEVtT44BBICCyXudz%fX%tpe TВK TIZq~K͙-$~9=#?aYo礬/$_`%_)kh>PR  SjgH}CCz yXĘ% Z*J\(NդM̂Cd\N[wg,}aX3Y/5=ڎp/)RU;> 0=SWIy&~0+U; URS{^F<=SH:j}D$W8PPs[nzoNzhSֳ#l*h<;.Z났 XBR1=|^z' 3LH#4nglLw?:^L:wo* V>a|mtĭdaUdCR> >3$[21S9 S:lec+9 =p_یOpŻo8yʓBBd2=$|2b׏7ff zYz`#-ʼnuV QڬBSجB* M$wԚPnUnBN_u!-A/uhYfb䢙E!&STЬˠ|f_LYqslj+uµʹk"9E:v&*VٕVPYVI/&8 ,qg+Xm7pBR9z?V֣h8-!U5 JjzJ*eаw~cMíohpruP  SPE䜙%5欽輙]@=f_f|Pk9F-zf 9xGl Y5/-d| ';,bm\EGR Q\҈EbM;3{xQ,-Vx/_ zogy7?e-565cM'+*+DVc24؜B?\%y?Tx=+ے2> (=ADZ1E:Aҹk]nM\g]LK}KY~e`Re*NqzO(|3qODKg20sVK¼Y-H4"Eh &RdkJ-!TmLUWe?gafhe+n EX:˭bR%4X!{{ޣeM' X,Vn^An~>͞u36))RV{94etl,:6N,785^] s} ;?Nu A|a=j}Dw9 Y)s{l)%ؒ=cKtm\"E!6Ť?>9G](dhf4ArH9$]6zEV ֚ƙl|tMy<K _k)=b j×dAT`if'?quJ엎EyD,-l7er_BYXHYodd 602ŋY,i^~k'p\Qlvn^I#,iG)xQ?6̋6I'Nzs1P8IzIB@V>G<瞈[}PEeJ36Wih6;me=e$%k=-?\>_U]e=EeUK>]ЅX<,:;pbY3y֋ yP'KzsR YnQ8PwsݤGS6a{"nB s6Rhd`dhd?,W|ųNҏ87\U'}g{~4xu瀒 @,4nuL`!-MgC,! 6K"B$ U/(N<@ȫɩcfuAu=w5 SFiҎz>Hi{fRT餋e?wpK=HtlL310+ôqONeƴɩ|x=d3g =l1;pgw),`733іmRRS~߫J`dfe04²֑ѱqT*% G~f&O8NH1˃jY,Ƙl۵w~(%7@ܳY`<^"ӊ[(n߷Zkw'=_X\#r!FKʬllwPEOOOt*fe}W*6 Ԍ:Y>,,gasnq Exd ^s ZIw[ZbeYJn{ۧpyW{imkPխBlnW yT߇:Yn,7&&eܧdScj; ̙~WOz^|caPYmξӡrrK7Ox~xpID5Mmlgb~:7/_ ,sz= eH:6e>\zp3z%RMy׋_id0XLqxBbAW?XKp.]j:{\zuEMLL@78`[`&OpZulIZXΰ_HIJ;R@֛ww.GOzku~̬,u+[cph?>1㕔>ce= ͠P$\F.nQTȦ+ڛ g?4'~1+@,g@ҁ?IYoW^L-m‬[ڟ95e:ewz;u.fG))V6X3;mA^cwDp<YAx<yxx+6SEk3n㉅9\or+*/26202lV ?܌b;00>%|jj[Z)kbML&% kqT&73yFetق'7t% zYXOgXY/!1t}}XO!;zN*]N1Hl)'` UĿEr~1t?e*jZGt- uYR3Jr0]=368u"C"| cYYX۵4J uRT\l`dhlf&N0!Y)RŲ޿43wYԴ4ZXI?\eQ?\q`mGU:p1es3,u2'~vԉ> d}䟁eg\cmrFqjmfFEŒ>˭.UtxZqlZlNae_ʪ*.WV~;amGןU9v\qz$=%%&5EgyﮘtH&\1NdtB2%&j39ckc`d(}U7? m!,NmmHs3)-+&pznt,L&V*zzʪkq `RVik>|J:Ndt=QftlsF} R<"zL.6 NϻNQ 'cbӿ?bp3s'ʪpqS Iɣccp:ç v09P'2 H: N'I(,DzI?.[fCiti9&Dz/}cӱ-wuu4cܹ`?\\Tjxd{8Hф)JBR'`-c!:Q8%F $h}`EROԤ^,z|>J.W Qܶ(@::A#SgW|I"~U/170=X'}W3y{Qem>\+]M:Ec4cnlVHV ƛ[Zp@7<2B|#wtŕWay@6 ;;NB$@ҁV<#BY#q3F1,=6·B^\nUu?SFXًvM"ꇻp `i᰸n٧:k&Op&H:*BI.IYMz CH``0˹\Nba3zX{Nyc]gX6NNMOmhF IopĻaq}0RhH/!R&wcFx 8^G)YoOĭ%érzW$w.\&s~,_ˎ`XBh4Z8EjW[`L`{YB /青d+k#äQUM~)6 b +wvvF4HD<=#>|aPʋ|aō?gJ_bg"<6S8~,PцjwOwZ9Sq/ᄤ#za`rJrM>($뒏acV?:UMmc+c33BX,g @TV4R~| 6ۻuE ԊĆyjN Wt`ް'e^IX{3 -&&&D"Y5p svXò޳Juk;[%а0/%p3aBe/m˾jwvqb\%Xnp\ ֆźH: 'Ifvt>%_'74jP_<./׷?Nf=EhD\xdxszBƖ|~LmǺS޿_,gp_d`d兾CM"*Zu95Vv[O,Jf>c#왝nhy4bY.ј ͌e=T<Ο`*ĝR2]٫ `@wBtuwb:EeUXmu%eemmR['s){PX4V2źf-^ 9Iz{ w"Uz"Mn엎tu]KcN{YgW۬P鴐ͧT^Cb i095匭MPH4B,Vܻc~e=3Wmg 'xwwOPU5xyϿ:2 ɫfֶܼԴHW\,TRӘ^}btLZz;U5ij=e6l 7nfqG-..,9elDjzg4/9D(n{TѪ=@\d}䟁eT2?LMNA]=QZzk)X5Ԉ}Gh5TBHμdbe/捏=&Y y<^IYYT 7`˫{fg+(LӚ3|>_IJ.:6306xt9b,$~`+b70pTD8c{ǀD V_݌D 98oec+ҤVC0/@#bU ofe~Qn8z c8Pc QEqIYg'KP- )ļcY%o {:$[99.X;idx@I0TRS>|HU SŸS(V/76quvuij TAZ%] e ,s'UTd]&0;w]=MW:MLbes3d&Oȣ:>*{~z'OM ־vIhh{Hz69UP{ ISOe?"uzhP- V*X< `QZ !/))pPB 1cz3*0n)1w[_\B^s"³~D%Gu } -?ue;Te`dbmkpHOO$a%ee^|T44Miec1229<|-!*> :(WNHh!itl,gd]XWǛz`0KFT.7>}oeu{ }a`1ŻXu$tc-5WҶ*{ .;2TZHփHU<߾!qm[21C-&9)*jhv?90 *)0IwUQ{+x߭;nn)GHyWKx2+_A5aKuN=OAI%3;Gv*{{m#O)I3+yA٥р BZڸ3ҟuSKK;ؼ<@Y@`dd䌭ak3mPukRm!.Bp s[Ų޳Juk;ŖѕF~HUMC dWwnIhckO ewZ9 R.B=b֯S=Hv/nK1捏mwO,2nĶ:L&J rqs'XrFBtp3_8i}h7;JdFգ؉أ9+fY$ > v `#$?"'Vy0b(V?o_aeoaQMM |W3n\wpNn Ek[[BRYGHkG-qoZ o@Y@%3+U`eɁtm*~b!`ƾQoH,J]Np\zk5`w|{㺝Ζhw>G*./rړE ˌ.0L`'5C /{՘4:!."]ha:!<$ gttBV7-[g U?&+BO'W*j"}I% Pyx^8{L(񃩅ex$ɜ׸t=r^Y-Ig5kN_H&NQX,zv|*+N3I-yFqEQCvr09);%ĿE\ 6=IUI=igb3WE AjQ@"ܯo M,Z v\2'%[ǞZ~FwruSTV1n6-CQ=o@1ImC/ݑl1g>jZ;==w2iS7h)=o&O8cW)gXy'ϫceeO̬leX>*}OjjZXPYⰬrjLmtOǬ5k"H z/}c!#A36.\/ь~\Ɣ Ù#O56 {o0[yjwomIC|kJk~mxudDJ*YP!+(FP?Bٛg6tw@(⡢{\{|Gi QAY@G'&eܧd>\@z_|O_Ǿq1mkoz` vZIë|~nuӊpx}F $AAf8Ȟ`@iYDW p=xl\fx/l62iD@g*:2yWt\> O౐dc3 tPԮ Y!>.?׷zg3yF2>OSd.PV)*យ \:a%%,@X-,#zzz$#&[G<޹"Ojw[À!z` Z7m=.ek0uQmau{= }n`Io"`0zxHg1_~o s=HJOfY4{"&zSAx m/r& 9S9hmk;|T%OC Ia^^ด`|&Pг &ďD"aZ mj=ѣ]VˬCUFKIM Q쫨K4 '&X))-Y\^hel~g}s񾷫:MxϬ%ᕏl5uis 8VOl6,땿Kd55hZ%ϤȷeF IhtzQqqEer:.їLHsXt^g'u\={|o?䏿]yfxO:jwOVB]VΔzxL)Wn6_pto5'8~q~vLeOMSOIYÁ2111G ' r'j6A[mPRƢ=jCjX B602LJI\^DvI B$UVe{OnQo`dKoj2[4%:ҫ?P +cwJVv8œ-uNi<:kiQKԇhW7?î<̃Vޣ*.=\UWj|mCG-PwE\wd8|O|AsAf7 u||+{ Aàz umI{5~?伲|9|EWLA[mMyjGtQ++tf=Sv "౰X,Ww#C_?;[&o ض=;6 _|oNbQɠ=EOoxDd5kj8Vf-S26qL͂CC**+%C47 X@4lqނT\^jΗӕ:@J:ӷ_ڛW.ⴘi0ZLPh&k>/v-C^gec+|Ǥu+{\[:bXYB32V $WvFrjZZ[ַ|AaǶ#@::;tv"[G3 G"Py6YN zsKze:]E~%ǥ㽪5kQs+FܰN5Iӊ[SC[-;+p[aY>i6V,2H,{F&hAfG‰D7(1)b?.ž)=݃¹V&SdЅ.tZ󾦵}J4(W(K"|rL`co#}Q( {Lu7Lg,~ @V={_ ~33t}:fBx,4:ʒD"Is~4x7_y-7R\e1vzbg?n2Ma ZG4D&gfe"H ;i*{efg+L˦pH93;GjUX3<9,칙{G8Mϭ 7G= "PzF8JP,LQԵuVfGxGphtttl)OgVY#KG{s702BB`b:`2^TQj-7xg晀5.1R%ׂt;x7*Tlf0H.rx/Ǻl=bRi5 |lF8|c63^wSe0>,eoR+᪺8D ~9xh2I&ЄK\fxѯxKA#ZA"ýN5?6.[yXaO(͔SџOљܥe*+]ڔ2 -Zl&O,jU4dMٛQ{HU](KOaںѱqsENNV[_FkϮUǻ¡epM6I8ۤ-.qBK>+{|Bg-a7N7+~ȗJ" g9y 񽠺KmFikl߹-=ckw-/0Hc-HhXac)+i5u1qp3s+ 3J(/लYm:Bm}3)q5qEeUt-; 2MwM߅a^qJ97ݰɫ-ǩԂ˾Gnw$($\9jIl)\Ɍ@P3M?_TNX,NW }C31i{%g+A˙o?[w2tHKpɺԢcQn*z P  ]NCu5ͽގl({7o gP'MljmG,Tm ^|‰Qo|Jl䖂NߚὶCZhgbDRmW_kזBR۾Pۨ>xaF_7 #,+pbY3yg7ꎊ=ih,| ;q2<־fkj"Qf+蝓G^bqƞJ8 ]GApt:sp"QNNn_;(8$%5FeHQނZ?`"zɩ)hwN FwtHuGyJj]gS4D>W9r^YkBI()OTLEpٮxO -)>PK|>meD׸؀@" :^*^+m6eA7&pGu),СnZɿ>*{~Q9htTGE$IV™GAsj5 𿖘.2s%6L&+ ˕5uT51l`}C¢H+[_5~9cO{՗E^FKs*ʺ6/eцJτ_|v,QKw-ݟ#-s@>#alT>6Rͭ.嬈$}#G3.ôqܷW:ʺWmU p9&BBѳIrORS8MZge)ܬ%I>Kju'V:lDw`C?@C5+A+řbr唱V&Vw ܬW؃Cjl}CŻq&۷-:gu,:pq^׾f`pxA@Zp1%Wdז`)Ae1EᔲҔ$SpH7?D>7T2!64F1N7L-[vkY,}UNH"1-,B# _WvJ;]MGw'^eۢ)?7$E[{ļ#2d5u:*31?/=Qe,u-riZ )!)yz=*{yt?'S Ka.$;,΋A-셏-q_9zLaDAG]%LJJ6j}JjLA4MNOvȰL -*[o~5ORA>?oOĭ&eن/̃"Vboim?ck#T<$_'6zePٻ':T*5fuo}>3kl|>CiQWw7dfe=ٟuD0ps2ևfj-?-l6CWFtq7D̻!*Z-B$-D?Pǻ;}  BvEj$FJWaj8Y@d9iP=>gD{xdz|dѣ =qL-,=\4"#kTߙKJK刞6 zZђ|蟲E[[[@@};jGrE0MxvٳSC yx 4Byx^@6B˅p|RB-bPxqiEWs;JcJP"Ry7۾t=0gA_EH"-H-dw V:&]f*xXi4?_ pQ8/ֶ6?8=,A5G|DCC~"+P("q&c #ǎCF ?ӓdPnW&'p;f3ϝ+,.b(+n~\y_-^GcLgaǨ%#Tm[wy*uAG!Fj`vXk_EhM Yd2Yr)8e:Ayazuė6-&YrX,0dRIS ú?2CayU5IHSHt֏ص?ݗ}'&܂U_j+T٬Oz'ʭ./̣=h YgH![udz塒d7vz朅ց?X;a0MmsK+ =J\]=j3h) |WsTL:( q Z2sںQ⧢-r{TdcStEErVnXʧx:0^P:W4=}j*qdi,Ϝqvu?QUTf pDl<& U1\Ϻn;#؝F%n'ě掹tTʊ)Y_N,ZO 7'-myy_ģ9(v7$}{v1:u2NvvugfBKW|O>Ү𞱵}jDdZ{%--O\/^ߥ(0|yό0XX_XЀ$?QZ'(̣<Э#]bSjȈU4+*C ^y""̂ցz㢬s8F?4<el4HvXܻaH')?7/ pil%:=8݄sk*Ef9:^5U&11X0ry<41v|偟mYҼlljD^$!5gy3c+Zgw*SU]/ BSGZ%#zֶ2haeyTwji.6{``~}C;)A!,{/1s3п̻}mmj ̾bL^3GN s?q]wO+nCa6VK+ax PLjݷX]20!+;{e;<:u!vv6Eɒ*`8߮}\<kY5J["_䬶yyZIݸBX=|G&Ʊ:b[OW/,kPWfV֤/RyM#DMfFJy<Yf.x+\"Ao=!nK3tL&sn:=$X^3>>?4 ٙO2e\^LmG_~lDw`C?z\2?CKW\^ɋ?Lƪ?ᎊM(#@S5bg=K"0ht:_^eUFG`vj%|mM߫63GVҙ h0Ƌ#$+Isw3:ZrQzj>=o&O1:4yx|Ҏ E46`^II|5O//sdvt/=z+e%~i ^{(2Kg i`dhnyz``@bI^OGj*2ںVF p0击W@?\IIJIFgYg4E;l9Pis?68#uP7=*{t] 4gEM[ZZ$E$0αʪB\s3-3 i.|;:Ql6Q Ox[L2gbEϚGcm:Տ 4QYUM@M-,)pq(M[lp1'jEl@Er^YOyehnz& CȈy {>/}3gzCHzT*B,55P_;⌌ɜc p_}M=F[=Gg-#Nj &!4Ms'y]k/V8K`TTV̔) ]Ckz:] P,3)U=c96@jf$'V_یLc4cAi|0}8l9cpƋ>lPdo; \62MUc,܆]̖ZV_l`dx& (03+y9Ao=u04櫃BOoNj*jdjvR`Q%{o1FMOHrS jGFAzEDzSz E:{,?uEE.̳9̙}|@H/i0b8c^PmKK7FS/+)FsDߘ8r$Goޗbbى3 ( $'@͂y?7ןTe[eiҾQ輿YpWQ030ƶ Tthh#*xZ.mlMa/vS{E\e6u<0{>~3VRE%% K}tt.^ì RȪ)ͿF# 81JlxC4R^-1 H !YUg a At2JenęVGuȸ <,kӰKO@,KrtyE$.-#c1<ŵ-`;ػ\Mڏ'fVDhϡ)lCe@Pu}UjU5 j`R >m.пW@eML!:&Oe E?m6'ut •a5E"{n;FG^r-lf/vR#Ѫ:EY H&#y4|=olμ? ˅׉C gU[ d`tt @$7̢@yz+G vfĶZwO'8B@uɪʭ'Xl?a$:eO'V8Ҳ7F坄zGG AjD>?y1g^[9,ؓ3ӥ؂x-;L,"J/I+e||}0X2T q]} N9$ /7ʋJKlfўn.BC,o0唔IJx@uh@,;Dj00DԶ%tZ241Lf[<& ' H$цUF1i3 |^[ֵrK + ipmAH<3 s_ǩ \4O+(1 $@o+hU1@@Pʾ?Y (>{;4-EO vypߵ@h ,?af${5jי6uAH+Bgq#^ i[CS肋ȅ׌~;df6lM=vV& zF(C`}Sh&q!=M8uG 9|Sᕗ6#===ya:E[jpZ kx'G%( }D[`Վ@>-ƎciXPXHo1N8Byzab5{g1mi(` ζT8=LkM,{im"n l?\輪6GrBzSq ;؞ yVuG9=/Mi =M];WS5Mm xpݻvhk+c#.d',)9<"ZOo_"}9D#TJNaZ |'7%Q]8 zfS>iYen*:26-ݠs_[<[4nx9$W\va(aS^W=\q۫ ԙHIKO:&I1B.iWWR@Bo5{7q`S+&>w)Oqg OR D{oB!*j$.^Q`H*WdVTVdfe&$b#"rUh6s*ZZ[Z.eնvW2kf<3Gl s=|YQb:V51VC-~.y*'>pwl p$(zX,V& UެGqi\П? 0w-/cVՉ.(aKIxU~jf)[A٫u:(pIii]}=Ҳ2st Lf1rrIGn U }pѺuǕ0NN~x#~PϭmlD #%0uo[^PQb6+d3{)u\Gvz} J-_cz:<%B3FZαx?O2Z{ٽ/{H(SE|X[N)W4757/$@ FFFzz**+xݗ,1:e]JA}j@rxp?4<,:6QRbZFzAav=03Mbqﱈu"iݚ}ֶ6S5 d`O_r@R6|r6,'ec*l=2N>^i: m9q5YG+5縐naQ_eJX3啕:H<$ޕ/X: E[72Wdڤvc:^cSc^>d^b6+q:-跄 o ;]FciD"oL))@^72ՍTTpQiws@HOO̦ծƁȲ؀azmxXP|#{xygd,%MPh+!D>Z?ʓA_ğ.B=Cу! 8Q]S}S[KSGaGDKc'&Ig&|H] pwҦjqe\r`.fyM0A4> N{?Ű sFklj,(,NyIm^܌[ꀙ5g8{wNwݺ?=Ѝ On xm=rRy!+;UK8:XL.v]}C| *;(@}Ȇ6Ey p A!ʼn1cw#y4?_F?6$4̢Q6z.`$+6S+h]Z _3kI9v9E0S7qa)Ip.qw4,BCm]}xd#x$ed'}E,TxWB]vjuq[UZ\g+MݤxÎɬ||آ;^K ? ̬*) (dad#-p@tE {ۭ5L槆 k] wK)n~uJ-wbmԎA?EpxBseM$z ˴Q,Xϳ119x򖵩 /Q?ؼYz#1q9 4be{:DO:9|ޕā| i65f \hmc`jZҜyTѠLЁFr/'AgwǠ_[>]|ʎ+L<q StI˥|*]ȶ[$`!4[mQbOt=2>ɛ8 B=s4 ! Vt:o7r·EJ>a$*qoK^V،̓\&|Ovq.Y+mvSX7A-=#:Q6eW5Ϙ,o\].j )}f(whZ# ŐH/0"^KES"w EE?,,*eu XG Ndx=LȈh64;DC^=|z/D!gU[iK-Ĩe7$Sѽ+@%\@ U6wsdžuRgqS {2*~^017N&df,+tGK?2ujVӓAx cQ_(w}vfDo IgTs⤖N뗗/SB*G5<:+5cCՅIaߙb4`'FB]}r˺ZII5 {"8OӴDE2ow~Ȇ:_+iimCijaez:BN[jKK,34A+^RB3t\Xn Ȟ2Ph]Se@|*mWF' Let9_Rաin9}Ghcf E&|WRsܵĒ E 'A?ܥC[ +ƆR^Kli O I&ptc!q:e_/^ѰwsU6s~Nӭ+jCALWXAll z"\}3b6nI^'M[3Uvȇ֊ϛV4_PjaD"`M-FfwC[lu'nyt>~QFX4]WP>5w—p'PpkUU[~=(x^}a2W508#8&qOl;t]2ɡOǓYzn)̌Ʀ<Zffe2B7]ʺc^|+bSJ=VӐzJL>*5RN#K{OR+^ [s~:kGۯ0T=ksᎅE &~Z|\aVVMYE[S v|J?GlE OxN. ^0htoqfoD,nlj.#`df޾z?%T1nU$VBoe6/ST?9Fc]v~!ftXx$q_KK +`~spn̊d@￯\K@;Du?NosJ{rKsfsOg `0me\1nzV 7 2}jJ$6JG1iv(G\zxn;\ՀU~{ٗUwXQBhcjI<IYfmk6I)b=XHj*zw{Tо~]7ɓS/\Ve x::΂c: ae- $a@[Q('gS%& D 4zwWكl;:W+˭?GYIJrs*kzGDJ;e=Phw"&$OŬJPF\S"ގP{z"b'p'WuH6 Ar~Q:nAZ$ýQDdcg;_02:jhb 9fOZ/w-տ #6+̲~ok%o=%ιa#K,dpxBu?sZy+9Ct`[ ŕ"Gc,ŭ)0-kAƎ'g{ڸwٶ\հxN W\4]-^o`,1hsphζc*z\|YYJ/KIܟ"̖Q)iۯ5'̯vVnamce'F "h&$.WT J%F41S $_ͮoƬc0:r n"(UQi4D# &!~xxx jCfSi| (^+_5!*ePrPdzkYіhGpl@@@$d[{ nyxm'6U;s{OjO ԷkU5l?N4Ե_36J췺 M27n {&sK`O)DZ^סm͘WM{'GjjaT~I[}dll&TJv#SJIŇm*WIJ_Q%.qy%>l>_[ %RK NjXW{2A<SgaUy0Y| ;FJv)Cp&-޺ǥ] bYC@@H0L_?N޲%20d.0CV:Cln_O+ȅ_8M@3i  &s~DpFj FACCXzr$` ްlqޞvV+h8$kM7 wr`(8v~@H'r{,箫;/#GGG2LDo;ćVaYq;͹$dIi9Ii=CE[l|&wW%VC꒭%%_uf=郉fDC3< *[K۞Yiݣ@<$`=cfɲ%Tۧc*N!q.^LBY `!1) Fs`):ؤP]G&u5d؏3uخ,XSL?5Tцnj1~9ںKY>.@~|[i/c7cyTYmEmKW냡tBM#lF~C6ZVf̠m>/e`T[Wd2 tl$5T>ܯrF;InៈaNAOeLFBZ4*;Ip`0L :%2?hylQ.߻QH^jY"P)EE8a҉#Ų B!4P$jS? 8 =# O8&_V.;w"Z:ခD3 sMmN /"G~:$v^ Kl>Ќ;mnd}Bsƌ =kw>E|>*SQԁ %(`ȓE=+C=|q^ѸzfhKc sRP c!;[^y:}#h47O/$FLfń *m[NiŠцݪ}l`{"6-+FG nk%.nB<7uƠVWJ0-#M--dBwtj26WU]=EL.k+Yyحԛ{a'Ea0B3QѾqW;~e mĽayzoN^um,r/,Ba|zO'}[/rw.3̌U? aiAȖW'''LIJK+q( ^r(aVe^tAd5+Vӑdjܾ\XTD|dG*n4PbЃ?OT}aAPߊidӕo5uX H?IAЅ8Ry(reL?,W~𢌯ƊN+l\}+,>K^'Gȫ+nS9Ӓq!mM &) wgnKG;SN+ D'1!Y]}= 77oUbPiA?l TN~]oo$/^mniM{%yiO_DDe{Jm䤈>>ZW(/'IS!!&S'6*ĂzqU_(#:i66w۷rPΪNdPFcBuL~<,]-bb9:gO E&Ơq-So^؞ %˟:sܩcby 64;冗fuINrC- '@(jݧs{o?ΖI,&CY(.)uqzA?pPAF:_0)/Y]Sp9Ii]}18]QhCz( N3@W{:tzEeeSR0OsCg2ˆ\1+++Dƽ'"$$N0 *Bg2̜iB􂻙q+̉̂fEmZYAsg[vOrs/.RԢGE% 4X|z駿L-$c)A3T48  TxDNjsZZ)N*]t`3. ^l$ 󆗃Ԍ^AC*LUu^#tg2jÄJ<|NRZV~A!RLjDٌƥF _T\k{ʂddDʪѕM ɅS=I)e@:8-;(a= 8;hPY9011dlf gE=D lg_@kM*pÊ=׀>+̵YQHH|Oa*,5P:ҨuH7.sm'v臝 ~ /B8WPWX,d?IJI~# 蒝zl.|[lUҾi?\<y6h(̾C%nR:ŧ7'ͯ%F6\u{6KK@܃2jI(eęFk4ut|F& AOae2qO}B,iF\)6dPuw}#lGK=} 3'mƛmQh !":|uP&=< 0?@SG%lra&d];`y'wsL*mv"yIKUOQ^/dB7#2U%Hg0tw4`Eh)=k`Volt^FlsBRB꼌/of )cjfgo~)V<UrZjŽ+ I6Oj79>DhFj3qCFW*[P^ƾ$MVu)J x\^,^hN_TpS.:fN /4[.(=軯8huMuRrymwb#= &K"z][,m@sIʧgf!'L5%ՌwpP<ۯ DIx  ih_\Ä )/3!K$ W%O.i* WN\T0 *}0" ɧޓ^&͊/yM#_("G+FaRT+ǰOqB=PgU%# W-W=rH+$W,-FI䕔=x6bDۮ;v㦉9:!1 :Ȉgs4ʖ4-ɴJ W;Q ktFDm>+U2ޖ2ғ:8mlY|C7}=,e7wf\F2 See)5Q7 c+iZY5e#L))>/#3608S܃[wLq2xr:~VqP]\{Z:aC|o0$qYD2 Mp :r| Dщvi@41߫w wX,LluuuG~Xǂ<6/t2Jen Gw.S)"SS[ IU2!-1"TcQN4g)* avKpW"4B9v՘['͜ oFcR^(yWX`0=/W3> -@0;AUu៊Zo?U%#iԠ+-qPz ģ6F!<}Y~_ں/u  42;G7˿`ƥ.mVSF]i0}>v@(LJBںȋ-9[G|dufb$H]-Cޅ}#=CIyf\:` B(dP %)\9Zu^tstx^|:uG\~g3h]+A&7,oYΪvpːՏ ^'b+-A/mL~8iÖu,B|` ‰e` =6PѾce6~b5D@k[6PFG=~KC_R9Q;=Yz,#=-?߼_nÛ;D0xO])Iok ]F s{kg"^fztjv iFח5.ԑ MZﺖN~A!o4Uc}Rc5cIY&H.wQ5tufG 8!eQ/>r":e=Ҟq^i#åp@ DjJJm"jے߾W2R>w.gxPD)# ծD,3U[{NjBV"ީg >k844TQYU@ {zNedU((*]$-D[dpd29~jwYۏ:L6cjz%Fr. n**Z{V9 &:25-VsqGJi`ejX|3k`llhZ^< I,yR">t@7 6`'z?v=, ޗx}{k6<:%P X)l7܀}+|A B}q'V.:W̟^@̓L30=Sw=9d|mroǭk )e;jA6}]b 2*NQ*M^ hEe>4ʗUIJK8:mRPBr ׈(ib.+Jʃ두A"O )$$$.T8mbXY51HrY+_H| ǣ(a{c{11|RS`6w4їa74,xŕ}}]-P R^+`gK2XU%uVwυ[όwUHpfxE@,1\[q='sгLGbDO%uTme@=Xbf'?~tA 憧<lG*LOmԞXoUmCd6,:-n:wz]2b{;[>LlrIKW/Puisֺ-}Kyjj*($ ')+399+_Z vzm=TaGw+(( gپh?#Sk.w<32F$-m^v׆kʒUCC0A0`m0o޸eviwaܳf0.<,YƓΨoəpVTY2Ee~D]y{QҁXbgX' + qJ{( c]pF|*p-'$禶{EE@Lb>`Ri@*|g3+5b009vդv" }8"4Dp;6_̃qE94<_Pyl9rjq7O.] IYե6-Ƚ]Z 7b 2Gq5$mՐJ*[k9')pRL&^~ 22vжI&iBb9.b')+|"z4^/]==p|s3^?J@>CLcSҒWI1[rn-4%O^e%Q '( 3Y C6!` ԙÑj?P8&m &J=S\<)8/H@F&!$^ة65㡠RlS-lpAAq`;!!|'b$^~ɒUq)V4s`ZC(gy%]\.@8UR:uP@Ckb|jڃb],q6ی RB*Gv;h.3+ۮ%o<]jp_^B'8 6#{_eB&V体p叀:s\ң SQӘ1 eheSDFkN .@Z^ኬySΙFp^nʪ*[{;Ss3$5'R""+/<2 -]s8AMmc3SL|<р\T\\S[TWia>OM!wQTo5J|!l1T,(1UVM,apuaf]"1&6VzbG3zŨbƳW%ɱ[rz J)nUyY $lE[XdKߐ[ާ3q. Ө+/5))k׻{zDrJ _cd6Wjh\9&rdZD@pJg{6#lVOɨrLc9:u;XpSLu4+"\P2M%BSFWdlAkݩZ}UU @7T/앒M\/krUUADM>~Uy@&'' %"y޵`bbc&SY :rKAa_c1?mFǚ%1QIZFPY`(ߨ@;F<)2_I,F;l"I c'ʼ-Pd˾ڿC-(!X{?g\q_T3<6jZC˝$!!!LN)aV'Ыi)d]-q(ޕ?ZmkQ b? BQU]}S[KSG˚%v9p&\9fi` \ }˂a{ƈ߀l=P{&GaezrgxPo4ZtU"ip_Ch= +ή &O~ka1b5ŕ{ƭ)ג&&& ME/uh"kc}CCPHϝwmlMʹQ^>Alyu|Wozf/:ZSsØh.o|||)kYR𨨸DpuDt0ZKtg޲\+x5ݞJKgP8W:N&'|Eo&e`rIé흋3$ENg$5~ jsBkF#oB>޾xfys!!!C0(N}$ jyzT}h#!=Tu )C@2a(}ndfe<s: 89yyF8!v7>_: !6"T]⻇FpD ^䕳L+_d]- [n%wf}O=A{GUupg&TZwP?l>K1}>bU%%rU++/LJI).)b`p2;_?өd0c͒PhJ̡Mx>7J=%_R̕ #ӟS|Hr{APf5|Rbg|ݭh^c7eT{@m3^bcۂo<,kA9cAI-'U' 0}URڸG0)~wr{ayyԴ4jY6vwGDE%&'e_\k`(.-3vD4[+gh:? $ڃ+(aM}zU{HaQuxqYL[u=\a]Ae0wD O[X)Q z2~btkX0E#Qwo cҡ- NLNrˍufu Xl$Y=Ϝcxcn2f9¦i=1J''l2-`;o塉1UW5e|wU" d n#7#kY9 x;M^Aig9: G~S#Qc1;NV:SnjW:DfێmO>1w N&N/h^wT͈4Ye+ )9o㊖4lFsPq 6!xϷ-cHo n%Ce'INr+F T5Olhq!!H2L&B/fm(ƤP9B#);X%[tFݧ ֿ*rwbR^XcudnthY<\QR#P'Ft?(\ r?(zzF~zM0GlE OxN.yX/0l=R{-_\ ˘]gpѶp6 [7S؄h \%$$>,:" =cC&P Ar7ɧf4<2rS[ m33xy VVQB7uJ̫W;XS ч#Fv"i|WeLʶkgN3]s4/#@7t+6 ޗ́Q<*UݔCk_i t:=5-v.)uzN)?-`;uvfu}}7nJJHݐULUrá ;8y PZU %eU;آ݉u %TϊiH=%ǤFkːzA!rJ,'c+]ԴPgCcckivcr鋜ۥ|J.@Xxb{9çƁRcoyO*s*_VA;{zn}dHZu"Qmivirj6Xfx$V9V0 :t||<`DZ;XA4u=PXaOVn=u[b[Ȳ]HF0`<,ς]K,+?7hɱrA~{ܻtZV9. Tn'ͯ&勋\o^_pdNMܞ$)&8/#ƅ)y,>`,!jjkSJO;pe#)q݃H? j; .afV1&=y?#_Àe/CSsxzW475%]] k-W> t-"6(atF̡ xL&9g*}x;*;iS7v :Yn_i Z}ivf|ԅXQM|Ҳ RC0{!?Aۡ𰪰 W 0SUVd9p8!  d2APB3Ȕ%$U-;yZN`7A";7䞱?u4޺.i!<%Ppj+Xt~Fŗ=(HsL})gS3qRpy*wOWE^1oKFA)($H\Hh8;Yex%hƶɜሄ{[U x=sn~vOB V;}zv\5)"6/cQ(˪Y99s244T[Wy mqCK7枭GDTTzfFeUUo_GTmF?4zĠ/̄IĿ#bY@[[IT_.h0||+DrȒ~|m3JَW|4CE7߀}'O.i=c Ȧ DesgJaGv{!ӱGGVV-Gc7겼q7 b[V# ?\i~dp3qߙsVj?>)P8𥞼]rJg^G;ї%GI`GX§P<q]E_vGk|W.үx^n6rg/XLWG鎾w@x{DKW7/)wppLSd!4P~(]%WEPQ9B2̑ \}GofY]DZSȫvϹ;rxZAHH謞[XJ2"I^GВ̕N{Vn? p{[Ii)Y>IJ#)wpM]mkZھmѾVq[G[ni(VAa(+(KQ@{H#l;O4Z#O>ɹ'7}$+}cYCA1Hr d['fcʞ;*ŢY׏R* r10azm~w26h^H9h,E<.;^Ggv'J>U5FfI4O4yž/"q&Ngk4rr&GGGG-iɩ3xlɫiJ,5\sY0hۭ{?=TWI-MD3RPV*/jӉsiF 'b :LKO svugg+$8~}|RRZfщ(I2· 4GRUq|w7HJj7_G):Z[ɔ5Gq'_9N_ٔ?'R%vtQO{BÍW0OgڧUrNOϣovebEsCO䕗5 ӟ*0 g&OLFciϻlf> (9J_/ A AiYum-MzWZ|7Y|4muKO# {j ,Bk=z! Sȹ͵1y9II!:agI X]$E 4Ʒ|ld㈍*J֗t ve+a|[{:-SE{ާ c^|vڭ@Gq jy,-h ,wR;EUuBfz/R}߅I.UKW-y EUpP5L*4v3M/q85)應D3;|7"PhUb Z[[M+6@s XzL~竍QPLaUce*Bl 2*mpk( NWx 8=K=%qt(# 8:FZ;8W=+,\ݗ_stu$O ]upwu'܁/ִt 3_>  xc 3d{)Ѽoə:tc wL9]7ty9x;wޫDgӍ}]A =;^srtw7|\d_?Pl\uTy[vyBf3:Ns)RXd.Ьc}SnAJ1V2jv_˟Ҡ|$=v|`E?܌&d2N&T=yWQjj\~B]S{"?Ag]F؟cی5L7 }Luk 4k1/|E%7];|T"Oj~-z)6=88XАe~>Jm֪)uL}n 3lP|uQ %=#sD迏; 4*wlճ0zxKȤ_QYhAQD6JXS>kM^ؗ/pZ4yF GW^↷dxk .']4wyz_A&!*ӄGͳ z*Շs0CcYٸ\'OB]} Zꅕ:)͚;Tt|;>53!~R- $-(>C)=A6/zI;AZ)7˯%An{ȈIӼ4Hq!=#Y1pd6ѧ'3/naDsHWiUMii- ꎩRϝ_ e&[28)tI)$ 3q92@v1J}=ϴ/Ok{PN*1>2* D|x}kt 7Vs/s/&*ZAEZ ;~TFnԐy`tN=LL'w]m@O@!V#& T!j)ІdJSX\Z_F*9WZV6v'|jVVDȺ= X#jGR]3w[J!#Ԁz$WbR{=BuٺuBTn;TlgMvoD:)sޣ$,F|6B#ܼ7t'@!Wg2Bzݶ9rZV2ZkZ7tbbHAYʽ$w#IF5ܕ{Rn/xܲ( h3^c+*Nʹh?HY*a ʞȒGUE37+}:X L֑)4h woJ:8bAMw[JʠOtekٛo~34 J]Oǿ>؜D<;ٖsI 3Xp!@qԳO﯌uNS;sj,,(}GP~<#Cb^7GSvṭV;эp"'t4&#&N *4+ט:b;biMKϸpYLoiniy/657_ rEM}N&'$_E7- $Ŧ1)xGoBls]& J$:X;ET8~Aɫ+w']T֌#̭9t6jݏ\"xU5I!lUq'NX 乮>uK y.͸iO);)?m0ݤ^"/7.^6SŴ=l6̍ 11l oa8ׇ>|XUԻ)*ahs},=XkjI˃/6a^HDO>5R6FGDE+9KNoHi<ᢛH5xc3ruQh},__Et99 1k#VnSpco-d'IE+JwNub'7nwb'LIf9VT&/{FG c|;ܜ}( Ey+H$)c'O((QOo@]_P$QBC`õl9?SPhefY^"Qz^WwX$2OLΨ βvqp7)UϼZu-k\$/_Յ짜-=+Was&#UKUgjaBq:5ƔO)kQ]L%i͊,ˑy` =H]_K;*d2mDsYg3|xEԼBv W;jh#As^9;`ܿ5PVtzWStW}d6ǟJ|c婔'{TDT̚4GMxMM qdzlD/SUuu޾:ڷyoD{-^zlϲ-ʤޛXP_Bf;= .XWET:SPO)+)4-=L }L)y,¼V(Xߟm͵?ueUYuifkr[qߝSgPzYQ,ŚW#bp ớ%4)ۏKۊǘWUxuqǖKzsA[Z=i"8?U؉|u^%PouK jӕ͑2fSxȄ+)T@>&ag ҉$ ܧP>!6[Aax^ DI XUǕPga,++'#gLPHhUuTô/ˁxci6m9w p8fB7@%͐1QH8LԧV%V;7{"eɦV=  n\'{58;#>5g\G/Ia/"uc# .# Ā(K+غa:fT#bF`>|c)ml  ]!t&3.%c~>aGj|۔;'*7bhmf8SO\BNW醐 QhUw\kr[w[`5/pkzRV7eۯ .Vv"L8or6!:Q#{/;whc盘$o ՁLoP{kCdLW^;٩s~z枒i:Pf_<,4i5aTj?">[ FNn(C 3asc/{.6O)䣏ЈZ)+I*:&lcyǥ_C渤& Ouh 9/ZD1V: އ~&6ZOfMɏVC}YM Z7t\zWTgZq)BuW0FZ*oJm[\tzZzFZFp H2ĎOxMbSY웹M>Hb &C=M`q(whu]0w, H~,rW̘g?)<` ' ԃ=0alQ dOCn漵~>uȈ8'2pzL7z2oM|E^˓Z\[o8QQJ^HR+Mu!oDȬ^byfB@`aZ۪ v-qT}Bqyn<峺7Ξ{)z8FqYrxE>zfdU837Ŵ L+# Jꢍ]2-a-- ~_sgy2q)M?pN o^S`Qj:]" U^Ɉ/xjX0q'/yS'ȼĤ`M)O)bRRәҿpUE.xFj~!zLQh?άzƇΖɝaٯ}dys')0sם2tlj+x+CoLC8޻$>^"qp80!`tfO,7RW:=Ne$NpL8|~bu-ʹm;UdԁgݰWnD/\Ëh-6Ka7p<+|+GgEcW8f/r=ecPPcrc7s{G O S3vB+gv`KXiqHqRdH؊2|?yP{s-f >uڒZu7?әƢSPhݥ,|8LlOIcJ7L4g*5*pylGFa z3 lKL }L) 7Ɠi^|B3;FX#2P rq lӄ xQ9sgPpot[jxV9M=Yq; ZUr{k9 (InGM ̖۾PiovƈX~5&)p +9"/ls zp_~O1+hFMr0O㈬GNRqHO SȣexF׻m0WK*b u<.xA# F~aa_~A!ufȄ"҆S bYYZO_?z6;K`$}ʍz`v!\wsH1k^/bOdŶÞCcZg)ַ{"Ket_/cv켚V=stp.% 4]L/kvW`X3>6GQU |.yёw/=JuA[8p!M}KzkKC,~/n%-אxyy]$dEf׶ሬٝy=Y-ڻIGemCn93[npp ׶~ۀdmM ܢK5\/-ybJm'B/F[?Ys8оq#fa)2_r3_P`  zpYiI~G >H FrD(v$8_-1=. /Z铗"c\UQ*}b\]WeRB&ݴ;7b?9u{xXCh-0Y%~tҋBAcmz`r3_2rx'CV䀂Ĵs[WL=T=,ź )_sJ?l Y*|TgӚ߮͠ d0WGGckEg!llDzx׉Ǟ.1k༿O e&3XH,vYՀ!ާHᾇ޴a”̶BdwC"bd //{ UaG:[7j[wo:޲-!ԥ7ޒ@I}Bt!4)8~Dephzşr,Ǝn8 %Q ywg  >uOP`(VЎS@¢"-mz~i鍍 qriތZP#x h4K^fxE<_J0F1DcZT i,dW<4 4ąx譼vS;Kϖ۾@qW; e&7sL2K֎ n~:al[T"z{aHQpx6 ^v&.П8au٣oav ۪svD_i+]V8  e#*غ_-kwHImCmj#>3!YY{O""^^wF9xWZ|7W6d3q5L'*8ѐmIϝl_@iӆAL](ιL (\^y5j8s_?W-о4 ;Uf?>m^wiٺK(I4x;Y\,H eLpf~&ۆ0L~۹r/Nb#d˵H\|#;&sy3HNQ5i2h o=oZ~_}SQYkj匥71$IyW?[zyN8l߽O7]Lق+kGK +Cq iF"{a5}Pz|sOv"AsoPiGueL6B {lE_8 ;a 5.lN4:%vaH)agȨi4 IX7{U,y {zz< fk^N}hAP9t;U+5A G2(!.KGPŀFF_4sc P{kw?A6vWdjE$7WWcaNJ\׌S rqh)uJ͖~Lx;n/a q zp'pH5( z|e '`k ,rNmeE莛MbR )< |f03RQV |NVcڦ) {_4$'~ɍlX,tYHeŭyD&ę~Oo ]EfU( ΁Wz0ZҎ">.RF0Ӈ=uE,}FhJ(I:| Mx6X9hq?\::[n+NpL-: wQv=8@N“ٖα.n#`HQD|z[_h*[b Ck&՚q!sy뺝6C䶅gc(hE`v4泇L&Wʞ:yO(swqӨL[v"gZ8>b[dcNa>lY|^ p.jXze3ۡ,yCz:>fc:> xD~OBϘN;&{l 9eolfbbcyG>a]ez|͸=ϦE^5,ECcc_ts&:8bZe+Kތ>iL_C0 G`"q8j-2Y0%-C#g oEbЧ~=J^P݇^n-(I0!#PY웹MHo‚N-]N`< {Xy? 3_#=WxEBB#X h Rr.LZ[C"mB CHqoeĵ NUsb 4*SCK3)k̭Ky3g~I5Ai;on*S8,VOW_=ỚЙ;‹W,| 1dWnuKO]{[I zlE/uN~6!*K$B%;\sH>>i_*-]k,- f0|1˯ȂE*a(DJC!Mz1ރT)˺ 3$g@tLL!ef}?S66pc Az jiiZr.GL/$E]>6G=IH̪A  mS^sQU(q"q5AU/DDzY+ јg0>W~l3_{`/N!2&. <]"Kja(DJ S43渤#Y D".]39;~`gܥypIJٽ:?;e]n 3_LdLyxzf"AbuZzi'XlvNSa3a!m ]߅3F :!{޺zy>H^Þy{͖~r:)D|#ә 294zʇa3!( (p0MC~<^eM '{zy3OoD.3.;=4a |/ko2H (=Bgz ,vxޙ6ИO>wH3.BohH 7:q_F/o/Ho^I`t2O1K6]V^3gM?oΩ37FF`.T}=Ŝql'̓5䇕'+<40P,=H(LAu(> PCƇa 90cYOgw=cb߈BI VW&9w3y7{!;SbaVQlknD[zL4x}L 8.i3nĎo=H}MA3Cd2U1i//7.Rj^G..} }횑q`PPyEFA2 0W(2O;‹o6% LQ*krEdMd30MxhA \[ZҎm . Qyy)%6\cmC1:[n'we;CvQ5qZE UY 0LE=g,2-h"C@!r1.fQC7aSPX~AփQ˷.oT-)5mFAZHM%Ħ4*3MB^$ zO') &(d8WߴRBm\(T Q~p˭%C2ayd ji54 s QhfJ<tQDg׿MO~̱n4tBQ674"IEնHHHWc3=yQ˷^وcqep1BDf֕ ԧWkJmRX/obK;\=[c*wl0%cWWEU [1֗Sqb&-82d 2q}[VU vԔ=BȬZlzx1:+?Ni1,}g iN4{D[~0"#+wnpURK v>aUf&.O#IcJЈ2~?^Et<6ENҁ#b:l'm{jL1}8u1|!,s%P@"&2=}mav%/)/eI1uxmaںzCY\jkkmlv}D¢"W#$ik+.KTb]llZS#Ln|pf;˻ZSB]!핌$}pU+<@Ɲ"53AWe>P984:M<uf[lQhî#d8" q4qA&Nį#Rޅ;.Yu/b`J{k-=lɝZ]?CAo&#EٔAo:PUxv y^]I.z$Wy Fk[[vNvPH};=-{z˞eRԔs:(|sVl9xeF2z_v]`Si!!m(e(1yzDBl<[بǧLؠsF ɭؖBPt0%+ct0GP;1J 2jN3iwKQzk$?}WԠ0yej^2" Oc0[Tw %Jp0ym1`]LfZ~)н?ʄ3kp)iݎbu+Ã/D683f~===Z.Gݚ3g58#e%+F͓_ 5Wx±GxĴyx+YA:X,V}C=Up94PՒXS|r1y ҳOubl]~U,mk3S;gH'u͈kg-Xw [F"ޖB6, #|N:Dù1_68#l-G)P@=v <y0ԑ'ﳜxLD\K=m>-vȄ|VuCusl8&Xw\"иK%+fz,gz>󛭱陹sV'mf 455IɯEz$mLc9!s)(6a`u+DF$}]|agHn拳f2_tQj)oϥwŽ|Zz~?\:,PܫrJ:8>p~\ݵ!7Т.'VyIef_? K-5׿ f*RWZM$i-K+MM>_ )O1MofwZվvMCKm\YUx~QfLjl.إD>B*܍_C{$7N.7J;/ϿN|vj 77)iPC$@G&ôZ;Ëq}g&.[>*f]/l&^3mIm¹+1 0 @r_M{A=X ކ 4mwxc}Q+̣LuȦC&:DNJ\}oDӴ~QWdʚ-^yvYgr0{BAo&3Gt1S#"^K"sɻ+j:,D;u]XsMw@w/[GMYQ/"1azo~JTynJ]`<;0)]]b+㈍ wSwPt )3(Of`%Rr4k /h64:54@a0 3ȓqD )n]JI_{d!CyɇdWnuKDdw}:xOhf"{ iuɶ 4*W)6_=yW-I?qV@3::KBC'oGoΟ"oU\ ,jJ2~`fI!ƒ,#'FX]?xK awrm|]NXz&; 3"է}Dy[)"\\ ;jsenblKg ^IۙJOg|?"j[&/%RyA<7 o썐2()~h}!j/!&{ݱ0"s hfjђ}>pL1Q;;X >:ϽDepzC9Vŭ}JIXhH>~:fpO>6?hY/fٸja)i5f-ȢBKVu*[ 4# ?J .H)mj 06>ᆡъDxő]`)h?Dc22Q?*P#6Z{/4kJN t9IQ5mSb ʍ%gW#j/=< A xfDwRV婦x2I z] Z+d-VwtE ;8&/v\x(LS <ɥ1>7DcN`Tص oxDŽ)5~Uv4Ow٘Z+7hL 䌱%r`d|ϟ☞W\:itBvav O ]ښ4\~s}uz8AIG߶9 db%-6@%`5bjJ2ܲR"q.rj*a~aj=f V+Mf'_#19S^ӌ1B^ysJ; >[@Wݖ/j̖S KPlE! a-UhVx+&9#'),OEgK/I"dv_}T mro۫Bb[u7ȝl}r?13{#{8 ˺M?w[w"$ָ: _X+|ij?t?&he6tԱ9L_;M]Uxo̫d%3X^ӂfpO.2 Y>il#Q!0c)h2[wfKX0<:D7lK2gy&bh,6QڃUl$ufǩġMZe[4K>ëfB; z3;ഛI8PS `ŷ‹#D&K@r,j9uFkˍ/,U%V alQ*j@Xir4<U %d8+00')7A'ÀB,ӖS thԏ:/;A1ƍ=}R;!Dg%ؗ SY}sU SqR:n]w [43Dn * +uB.n +>[~S V.hv,zSA SE"ͷۆ?a[z`JV<`JEkWGJ Cmg NcAC`f"ld4VzW.%e"htNgR3_흎{-{COQ&Hx=7TtWvQm]$\IJW_v{o8o@EKݯD='c\1)f2py8y0,)p6D<O}gy`ԈlaoD8<|dp8ёn͆%.2Yze,^!9/p-p<_^#x3ũ`N&V*)`wNn@3a.A~N@&T&˫iXD{_* ?ek d̆=% sItdơffgakKܷCY}oIY$;-a7z3|Ddxu:{TLƀ1^2#sهPҙG`9OϚL6 >Й"!,<7?ŸDף;WPZJz sMg7™ețnzIwKdbf9!HAU愾:5xմ:*L75#lRh2Z;ͣܟ=L$ E]!!.vDRc^:7cv;u##kOdFFseg- kOFf+yXϾ~٥DWׄ݌wmӾiٝxӻ^[x0V 毄z8إ#J&H'ȶqo]Zp3_:.>ḿҦz K R7sn蚂Pҙ x2mKڲ~6 2#x$ Á5 #E3\ #C^S>jTe>9\3>pL :%T +uuzL ;Zy!Ne=#T̪%6ሬٝwÞnHSpgC! HgЋoz`1T]|Co'ħ9gҜ~͸aTD2`yzqQjݯZmkZ-Zh"Ϊ*q0l "aC$ Kv! adkcx$<'>#N/ǥ+W*{|zltE-q Ʋ%oؒ肤cȀ2ƈOEP+[)" ``cm>^C](;m'QYʥrUPr*cq[x^;HeM3F>s?}ySUÐݽ[͏mwȫۘPw$fD_YZZTSs3;_luAXO}+d~rTp k֒.~5n/G VLv-`Rތ_"0}@1d;Bqe k7ha`IeeU0,دXdFץrgl9xdǰgz)xۧaoZK):Nxdb:qYY8-&%TSjGZ]0s“;iciQmEF](h{].`yT5joUmT%X=1q%oƥEg  !=Bəف+=3@?GEB YPyMC<.K?yl{`+* j$dzGþʕ/v:ܺSV4!v/&ݳ=&զm !,nv{Z"t(ZԾ\oeT+p Řȡ'~ҢL/`n? !Q6Aʚ뀹^W-5v fdxM: vi56g]ԉ S36w"$^Vymd/2ٜ0F{Ty/~9s#HP oaZHZݝ1߂x/nZxZ1U"RcȀfn3)k]?ZLCDj^e ]W @TO 7/vRxr 쮢 DԊ]BqFs'?7/f/m&_2lˍ]EMI,>xtZD|}rȝ4*o?jE2)X/L+_u667MВ;Ac[Z 2`r5Gqȫ3N~>5L f8<(VP"QY71_q=GV"ƜIQBJ*jH9ZθWGmj3_'nz1aaʆS6w{u}^je2Qkxbե[!7[YMa:Q땛U6]s拧Ɵ64||r&F{Ufxao|b~ۺ1 m>_/mZJMt ݪ})j#OFC ڏX*1N~`똸Y:(E'= TFg{wV_uJ_"Υ &ͯ.]Y~>sRx?%ZDGqq%ׯorCcj+IIփilo=DV't%$? S^xb-,M:*ҴVS@ȫ|Ey*:m=jM8Fl EZ]-v{zÀ=if)&׊G|V6@E̅O<sWh¸: ҕ8*j{*(A9rΣ!s=2- ͕rCզ0pkcw *_lӑzJors{aý`Kpt b:^ComˮTtNsPtoe0OP/=TVV^kWy(ӅF{&mz!.,S꿀$)/\"ޡY>1g,B5<C{Ǐ23DPj/q=;xH.ߙM*wқe)vwґ#ODz3=f*v ! ݀ *_v I"1shyyRany=q<0sMI4(_΍~_-R=`}w} &-Äh ?i}p^S7O*މ~5R c D=cqR*@IeuxB2qYc)BE܅+8|yIy@0_vSMꢺ*7/c{%o_QOIǐkk~}%ߧ <-RlYThdZ  8~Ľv]srGvѨPKnbԄ̞@RxG8~V#۠_K7?A]dw)*_lW\BDᩦKfbs.D}uSax%Xiff6o޼iӦ=z|-[8|i9T3)k]fŐ8 3;a4^'ɐ$ՔxB 5:_ԉ r 8s֚.oi**_l:/P,^d9tɇLꙌ ~%CfJkN5${$DB$_}U܃'n`ZJjC)v:V/\Ub\mM5]2bS cX_[;Va:{|w<%6h8=zw}陕$@ hoouMLLƍ7sB bI68Ժ9A9 -mB<݃/d60.uh:X()Ks^yŌ{xuF"\TI+ti̞US[nH=1ଢ'U+JAΩK>ݿw ].y-9B:u֭[9_~iŽ:% *4g[3O QEv.GfP;r6O@*z5VE}~Ubtq9K:t"OlNQams.onAf$jI矿tc=Y`/>|WE~zvq$wom;{@oĆ,rzTf{(Tװ4@K7;ؐg7O@VVB.mJimSM,;z% vڳg>]]]׬YiOɵv^)؟Qˣ 03`tpffo ީ~e }@=.FxEZǗqYaG_ęo)!11nUI+xT^`ƩK 4in_ &0[w-0/;#Ԇ/85ja7+ቹ@{連.X"S:zc?}+㽸i'͒… -Z62LOF@Ek3${ ȶɭؚj:jkՔZxNv !!Ҕi걍;=;LCwKo]xP?L5]!K1)6v{ldWX&KjdT6zH /<]2^[MǑ-eg5m+ݹ~fG?rVxG8x:ġ 8s{Iq|D{l`yXQ @#ܪ,}cʩKt tL{irp{@@"a/]r z7GL:_<1gI.|g7@qSO&c\m ? ?uQtF\OHԊPM8ua5X8ć0{:upJjC)7a|tu*vbj[ _O5]2م#>ۿݟ{qrL[o{Lp[hOH:`}Ie/d^MkJRh@VHd1iYT sheqtevhLmovke̶/{d;&ݳZw$R͞0yӷv텍_8FA6 ;vlĉ+WTlڴ)<<cNE_PZadGj|HA3qSp_ܣ'N;8=n?BL3Щ#ݣ(iOXweba׏ Eࡧv{9>HS44&JS cΜ9ׯ?sH lޱZL hlfM|Ǐ "oHD)ځ?gگpio3u8m=qd at͛7DGG|~___ogϞa'{_z+BER#kCBI =q/1M<~IYeˊxµͲ/&b/={զNuڼ2]xQR b,5iN5]2ԃ=DiatƍORMԉ>-A" Ԓ =BC-ȏ* }gs^yE w`xC\kf60ͬB.T ½%mX/楉$h6:`Sj]#ur$ֆgl2A͒\mZSf驛e$jja*d#BCcsZ8|6_+i[,idm{ˁH0d7nnbk7.ua1jd0İK:[n+ڷ_`#=>%R%XyMԞJݘPUq`0`+ʦTCO/WX_iC!@^6/V|!cOZݱ? )Kgl)ȷ$X9e̺)uMd#S+;il ˅hLЛC,aD  ε5ת?;S]πQXebvIgݰaí[zzzLf\\ŋJl&N/!ᓐ\1iAh.Lh,F[Gs,&j;HmVs:BH2^AO$U*b74!o-|!juhRf'N1P^Z_H#QnU:ev8%">,6l Ԍ'-:c)qrSrCzߗ ~0@Eb\M"I)v K=v^~i$ !>:-LLE{m"~( +S46k+eE$jټ*L^J.$@7L[(Ws&arC+/V1~7wv [_7/@Ii߾}1c&NpB___;c tKJHDPϖujQ#IdVA<;0xt3{rCBλ_z@".I VՆ!Sy46 Mi:,9KK+޸^+RfxLq eF wp<N=u;c{f*siC5M;ZM}$><1S${cΤZR.`s49Ebcka~#ꨍS+a|Q'zH* E9WoLw z#Z RV]c”̞A}GOp5KB*[\-s&S 90-s`[lCp`Sie,.`8Jt6ZoMpOCo !OX_iC!g[`_. SiagZ㸎 |n`=fyĄ TIW$1p&@%޳ڎ{Vl {nB1|pE^h137|=D~~-[^QF9O> K 6 Fa;@V xƽi~ TsFz$+af" "✖x(D8l e5aG$U/.FXg=8ntrc?c AD751ts;|=߂|o]&lYFAO$*@LNT:Ǎ&JJ4:W"4ޕ-jBdz_iW\% aѩx`t<6,6+Ѓde^GZ9ּRe.zX*qI`aEZYd}5p8tE0Wzn1ut*2D89k#@ DNΡTO,A͝ B"TSjcz*D3LHz C&g`СwbsF3NaND?5㹵m=|1Yr 1o1inPkuhTVGm'$y:CR 8lv))>VQ 7c=uMGӗrSFlp;W s3Χ~JѰL?G}wz]bt++(H~ן:xn-̡P?WJszUK%,ɇ E&w -"l??~zrCYM0E!KqdIE:YH1p#x.L^o8+I_గRs!c];v,+e2ٗ_~ {78x֩EC79zձSJAUy)׫) u&_RKrٻJ0-B/a(^~fws\LKԊh;B=|<[P=|XKxkH\(S3gnߔRPiPV-]y;p9v? m8ݰaK/4u)7n|uX` $m=!qu*]f*^%,&Y8CSΥ/Ȃ4',/sZ>-0/Ȇ)t_hI.k'/} O6ߘdc.Z{`rح ~T%;`1CP,>~5`̞Ukm.^bb"ֹiӦI&=N|w?|g$hNʿ1"z'0=ۍ)MoaZ3ɳ+>]ŀd8CGPr}FܠĤeQ*$2D<@HDjJm]ROwp_B/abwܢw(J /leum:F4(\kl}䞈aɴM^;{ z 9sḻd[.8?ntjd333ݻw1v FAo 񻟎5aTfOFs'K5Iwўg~w귱0xt3{rCBsRxe\{4Ɯ3W1YK߄6=D1Op O_c_<2npҨ]+qFYmO,IGpssCWBNNN1"z0J,66[nb˾__ߕZA,luaLA(>gu-DO@[Mbb[mGʤ:jc1&nM˧.q)a A ;O̍ٽ` 5cbbO$Hk֬WS\DΝ;=4#ÈugR3\SMq 2S ~;U=+i$0QVqCy;9h[GZD~~J!泚 `pb҉'Bq0ݥ;5k~8ZT쬯̍3Sx彲ԃPb.s,>͋ S__ /\pᱞ)gϞ wAm#Hnb{U4qTnIΤ|!VmXUkg'ʿzɋ> s1)h9db:j16 f9(:d-?CJxNv ՔZ@ 4bsF:9e sݽOɠ>Kaj&lYU$Rtn޼ڵd>ۣyǎh|ff[aڴiB?,]Ĉ 1dfMpm-l-mvo]),'h 21]!=ay4*\)o6 Mw$Q$CHB~QOZYd}5ϽjtE1t._|1k8NդIp_www H$BӦM{A+wح)4e/gR3ig @TkrK7B,q*F cp`神f?+oȇȤcIKudI-~ەuk|TU#c(6N0YeƋx ҫgYȝ+5A} 6r.\ؼy̙3L2ziӦ͝;,""B$OAݨ#ޤFGQӮԊIϦ~vk>=  oٴU0(4H%֪4%*g[B~U;'L4/I(*b` <BDzeu&Az/V7G3xBdjlt96昬M6b l̮՘&Mq Sxa4MEׯACy/k?}~5*u֩Es|xm.W^6åA+-Dyn <2ȮfbڝR<{tqoE^_F/akbjh&WZ.V/c҉PHeeRaPcQ|bp #ll<ވ+zka,yO.;Ej3˿fI.XKv7DW,fx`!CO{`0ڷ~[WWft~E}Wvd2& Jxb~mK!'Uؙ7 xP;@˩'t܉ƀ@ 2!MHJfs2-Nb-VDyK#~vԮ_C:+|{RMp|Yl{v9h+=Une֯_?y_~yƍ .\hS2H=W]tK.Ѓ0p^rAs{x=D*` eyh+3W..J֩E&=c'BEo }jb+~gX< PzA1r*S=þ*zᖱ--xP뵈üsAg|ѣc[ZgR\ӠCb?囕v7],s8s#WƨwlQB9O !@#J?*WbwY~)WSm1S$jE7Yc")tR敪Fw#U֗2;E+ NNNҥK'Lݍ[n]AA,=ֵ_9d<6v rdbCJ͢fMQojCE$Eo`lثt12]xQR68b }|րi rӰiGdwQEa{Kr!) eatn߾=n8o<Ǐ;̠2rG?r2MƤI[ʏF [{vtqx# -7͈Iİt&Wwf9_OKB6atVZlٲZ=C=*:*UQA`(I$jK'/cш&urp/է-~7&o#VT/^Qf-N>Ke2YDA6fGʈ0pb|?Uuﻉ'B?'EͰsGej_at}Y.'gرrC3tfڣm2OUB)jyf9~~O`2YPnʒSxȧ7Ej3˿fI.Xү|}WЂt.'=2ř=w'o\KWu%*))IeO$ 5k==>aB&N%<~'L*)!l]OX?5߿ < wG T/ mBq,hj+ØGõ-y.DGG[hO|~ee ϟը@WxP=F"\gKU߬Ԗ(//ˋ( ϼFk'#"_ -g[ j.x9|n匇izffcp30*jI.zB \ }} [}.>i 3QX^}%,']J֩E&=c RF~|Gcs%+gn_A)| 鸸5 %,N>O[MǑbVsѶvT"w =FvkUQGmȥ,R[]BU\>:",g[q/jVz;/_vS‘9H;Il3(W; 1wRKvR-ev$,p؋37sgZ`U<^*ߍQFwQ4Dㅏ?+G=Z>Z"oٲ_5jȑ#?䓰0Xb}E7yYJ>ckr7A>=8O\Bv{Pf:|^6E Sm @tiW8ڽ1hocО'HFGV,:ƢftU?<PP{US r2 O8(Q["SfdPu3Af9}ӵ?=qFvRb؜؊&$^, M:"ߍx=juP%VJ Y-td0o@KHs[ qNr-?] nFJh7H[.]v/ /bl TsS.2B:F`5=.?(ޏX5FN1(եhג\0N^wCl4?-E[v⋉ ?|71Lzū. <ˆMI+ũIǐQs9SfF3j}NLp n6r-TJvVw82Rp[.1[k*W=8Cwhj[X%LCnxa;[PF8$Q$zD䜽p>U8PH&W@1ܳbs:0թœ'Y!g60|M;;y̍>1 U4B{1$B{p,GΪ\whCQrͥOp#Q!&z jw zB[qDc`?]ξx@;s&|^ ;LЛ]$Q,$=2q.׸|T&Ho߾s.^K:mmm;v>}1cp=>ZB7'74?" Wtx mq'hbB5jᖱ-Эr'x]5~w 8יLv7NQ/cMpꝶ..LkkBN&9yWT/>;}hє°Ǭ^dpڇ37BӇi ]. |FBI56|jcةި3|vk*Ą$9/uiFcWK;gh@F_g,&=g=07YMEB񝶮fc)/" Un/8[ j ,0UC_h>uzm 3nܸ;v455Ūjsii)(Nm}z #D\z@|V#1fil0=n'dVY+쉥79 )њ}}DJcs4ZeZvһQNa Hq&yf֗ S/<%.;v,;; a`𐈥XD-qY a{U\q|ŃY x>W?Xcuem]&BLIĤl .hlNf3),6guPR}s? GBL1E+r;d2ez]7nݾ}'> +oaR% yy,\ED- w[5Dk6S>;Vjg!^Z]nI.0 X@{%b V6&]I[PSH*2Q|:Xi 6mK]-qF .鴶^b\Ὀڥ9| ՔZ_ ML:/)dB&^Z2[;{VBq) 5 }ؾ/$;:U,H֒\]6!]37g3 Un ^]Йő9 @60EbSy^{v9 +2 Km_H{Xޭ}VYt"A# &zN3 z9l=G:r#CnjjI"jpUx?pF,Z+dcat{=. ri}D$Q88~y Dhexa!~.Yl2DUb0_(Z ^<,4 X,zblEoj֦F\37z/S>fBPN s[naZZՆE}h-cum*-P*o!,ZH,t1|mwLcIg }]{22 YR0XJCG/t"j9퐟%|cS'YGdW]"&bʳzzEfVlEdGb`,HLc2; J~w I֧b5mqF[n2[u]9z(zk}0dXy \}BQB&]R[Mv';es;K 8D<&3vA#^ud- YD]ҫslcu}$,yAG2~CH^a~І])++0aOP`hyBZԜK "%@wa6λmZjZLs e nMW)"@bGnElES-d0jc?cNR* uteזϳ݉bycȀ`H΢KXy zI(ob/b1-CBnВzJc'/WyT⛕0LsMţpKv~/UqI`"jt_b=q/N/aH%R%@K7q6Ao DBפ7mwvKRkbh^IG&dE"([y"wŃY;5k~8Zآ{ܾg2!bcŊ\~(cg,R pE)̞=b@_aVcG9)D#[dBD-uvo0ni.8*ENm Z$Je2Ԙ0j:|e=rzb}'= '$WSjEP0 $R!c<_Lιe/P!aј=ikEϝ]I \Tu~˿fe˶ꚫۯ-Eʬ4-⢀( ^((!)ޓD1Kj p;M y=9s|î9寬0mn݊$'}L\*Q;ow.(?EZ.]Xo"[>,,.&r χf~=5l~-g- >>ѩKϗp d7.,/S<9x]N7L~4SZ$MW KҸKp*b[_\WTJD\t֒G,U&F]|G-t,:E7ƏWdO듑xs/Τ&15|smذ͛4F&N{|4SoQOy1 V~ZDQS|Ix ^tt4mi 3)k~Y(~=}1:kcߥk:ڛ=6Er35)(Wm$ݰr'#_2{(L_dR‹WE&d2's}pIY/V|-SߥwӞESRPznb-}U[Փe j⠝Vs)U*VFy RKm_!oݻدϢO_@Wg5cd6LILiۻ8r~%߿])"pJh? A<|V6uM._g K]}yܾQ ;w{xc+)#cA[WUc<\c~=ݗ[1rumGOVD:{n˥cWL6h)t+٩9.E9rC}7j悾-Uxt׾O A[䥣W\HL1k繤tU9 .mxvG܏xs45[nrիIiI]vj΍ N\;>pm{7~-ཌྷ+u?WWx+(K}/7}#zۙy|xpEleH7PY=*/pSX 9˝ڦjw$N4Фh tCWYWn⁞ _^ ]dʥ`~YTn]N-;7in6pdv \^^4Pf2@V/qso'ׯwYi*nI)#Qyd1HG쮠7gf/٩9W2SbS?}ؽtېaklBFuwi"Vxj5+{{{(@zE{oVYyԣ kO}~7]OzcGCq3G2 M@LZ_fr#!M?[oָ4bHb8<_ywkbt8/k;Y_4f6O{(ci@o222h>^⼒нa`@'X]:R!ƷXF %, wn:k?L|dڌxl'CTD+g6޴D#^DӢ}XۇN ?\Pome+_JW.mzhƛN\ Quc\D:> wbCtUvUqn|w_6oWNIBgnk{ݲ6OK=vډ]W]yȱS1Ϝ;xdYs*fhdNMvYu'Cͤ@O,߯C=#aX)ut-56!>o-_ХOϺ]#/?D7`#]$O)=uc\D:> ']k 4k^8c[trlKf,[oe+[m@ȺMwOy;~[9V67TT !aXĨ+ _'x+[$g[Ytht}(T Rd8xLZ_f2iJy{|+[ىKtht}kklB?!ъbml +[ٚ] "aXs7Y  UW_|/sWEs|u`Zt}&8"[(ysvf\Τ-cgle\L ;x}O7LKI[P[ylen&H`%ʣ']{IQ6_?F[P[*U_ny~LSVDynyKQ^ДT: ?le+tnHd)T'B=JQުq__=L[ Nbm'{j-("F@T*[ "Š 1nHФaqJ|.1ZMc*W~le!{&`҈t}M\'kZ)ʓn(EH1+[٧ K`҈t}N{nRDy0$󮤦 0Wbԕ|-EyGRQfndUV]G`t}O6HQޒ+T mqje+[a7_"F@56!R>':,NYF`'nfv1 L.ujDMs__$ɀy a4s7Y<xXA[ lL"֩kr9sׅ_0`6t} tMh"ʓh\fe+?|^v~ŋl; L|Ei .ث%yj)tY]wHP26ݾSeeQE9|o ^ءSOP0CֵlMwiEͿP _nm9޳hht}ƕ/,^w̻O[P[ur >y8%tոzWwϻB빼:4 WfN~3S\VI,aH⼒+W;>w-SBi@#{pJ*&!V,c>X/}{>a\@4?ZT97rťG$Xv(=moi]ͶҥzߛNpPhxzuSPtt[ni[ivިW)wz'HG_=٩9WO&?x2-rklB\W_dA!v9E;'^'Jfq^wEn4JJ:S d[vqGge=d80ԙ\sODEmvF]4P:痖b\HJljvjT:2@UTkrŦñr m8hXSt0W25r76}.|56! wۊW\hGud<FF!7^uC•٩9) 7bzWWHiMr|zBEoSe"F8Ĩ+aqi.h.ӹ7VQIRji/!ұXIYbil$4I[?Y|p ?be8=M@Y&iZ1L+P6wI( | '0-R!!1n-jZ n,fP1L:\nP]$ ,zaV2+$N j?0M@Y zHVzK7][;z2Y{\sJrUevXIKyiiQ;WH:s%VDOj%}lvNW+H>MM|z R\yIW5٢2}򑫵[76H{Y5nY6޹y |~YraqK_OYtBNsFzudKtxƹ2rv`'[w{ߣ%r3VAfZGHֻO/!г4W/DZ<5ou): zN,zu4ũq="bش\H6FV70jS+tn-,Թu739Kʷs7+_ wEt?EZu;wL皽}\׷s>kR|s۩߲/zHWUW9tכk8Ed\ɔ!h0zW*nȭnLFzYn뻷C @VV뻩VCfRKmR7Q0#гVwSx(xS-1=jO<5㍟| y a3Fg /Zc!a3FgZHj.5=h/76"F0cz^n0#3rS-ԈHjpD:>`r{H^loRy%T|on0#k:T;~OjK "a3F׸U&qjt}իA;E{OzID%.Z0:"F0czӥD{OaV^asS-+"F0czJ q `MMPt}Շc¾4Keׂa{̦KPt}]Fv{U^l?t}Kn|߉8Xݏ{IW_&ci4"F0cz(P~[#^V^֙0t}Mqi mk)x8xTPjV#FAf@V*ՉKn?υxx8BaqI눟NHNN8qb.]} &\v(u&MO0@ezP$$lxoo3\o ?WH{!i)))]v?yԷ~{ɰa>aHKL~o4o֊wG{"i{\a~~?>i$cmBTĩJ727Fc&Ǜt;>"vUӧkg͚'''e=:$Nڲ w3X㽿ިĔj ҩo>>>۷o.ٳG-[fM8 EXݟqֈ$RE{ԷѣG&?^ )lBTǒ2 nߝ-x8x'/)LN}ӧh;&,Q|g P LT)kWl G<~8Baq 3@S:w,\VV]E]vFل@$NjݳWlJy[e^0'D:y:_0+b- PKH2xI&Ǜ"HYN}k߾hryyvQPbΝ P3NҳrҞvۚǮgܡ`ވt۟'䂂]➟/z2&z@u/q)( ?77T㽿hQ)7tn`to!믿jCQ0aQ6!c6x-c=qֈ$RE{7hQ\rQ6!cSBq8[OY;K<<L]ߓf/uO<񄴉S2dȐaÆ9~sϵk׮}/wܹtF<_rL&߿wtEh/_޼yTl ~ Lz$Npñ %WRt]1"33STޛL0==^{MS O͝;7##ƽW2dH=ɓ'7kO?=uTAAAQQٳg:tиgdZ| 4:kk'|R; Pu؄+VVML՚s~>>MlNRq4p%eS.\}qֈ$R`ՁR|ĩ˗5ٳgGnܠ +++Wx񢻻 /R꫎;=ZѬ9bĈnڻwaڷo/63f-: "6;ݱcСC.:tm׮]]w*(KݻM6;u{܍gg={WիW۶ml׮]˖-z꩙3gjO.\]h3<#/ˌ38cq}{*ՉKn/rq^ RM6Mxxxh*666pBM:((Hgs͔ÇWEk׮S*[|K.5m۶z:lߣsvmVTTt)spp:սSaҤIbŊ_~E,֗dJ^^GQאu{QQQ8qDMz)U/R%%%E<|ꩧ4 4Hgi\Y\<\'ީY`it}4.=kobʍ{h24xܝF ţ>*n]vcƌ޽n܃<3#ʺNyڕ)SgݸwWWΌ<92jѢv[nX\\l_lh:atxu{Ҵ5:T$/QZ߷mV3dȐǏ7+3g݉Iˌg_rG4 "F@ۛ_HxS]׬AFDD8:tO>'nD0`{u9s3#-[jWӞF_|dݺu/ݢOݽg5c:սVZbiii۷oϞ=ss9wZK/I6}t_6"|ߝŮY"ezr?I4"FI[?Y|p ?bez&q[OY;Ĕj:ߐ:uԬY'OOSWTҥk]vsfdxתU+CZ-v*ګ򈈈vw_ߝqB/3di6mD199^JbbO>٧OͽFltGGG)7o!mNc->ޝg_۾C<?g|>[Tɼ quH>m!2n駩Lq8[w{K T Akץq{1c =gFz[֮+E*JSs&L[mܸ˿ ѣG+Ο?/|TNZ{mE-7>>޸-}4M6}QC>$vk8`AFN =ǀ0+[z@$ګR$$>aJ)gpyI)}nt{¢cǎiå} 43/ܽw!?}gXXMZZZNNG֭Wݻwm~wϷvvv޽[*<;j[hq9שzyy_W;LjQc'}ӝʉҎ;jzsFBotz=BD:`9E"&^bZ'r@}G"ޤF}$@sܕÏeզiҤI&L\2eʘ1ciX#Glݺ(i6mի+۷o7'N?=/͛7$o:toۿmש޽7}'|c [;sL޽]]]/^XݶTD. / ^-??Μ9mڴѣǚ5kR)$4hx)ѺE)F]rUe\rD4 " }75+kOY;czQqfQVVw"rEX2hh05Ï x._7*)-"FF$N\[\ZvtR7gk+t405"qkqN^STN_r =~bSxLBRT "ajDD{MקK׉wUyyLBֈI98{/݇c/+ ajDD{MMu[~oGnkN%x\v~!-"FF$Nߦq^y.2y?g""ajDD{MZNL@O8 Elڵ^^D/ԩ?&nnn:Op!C VgvVNHHXh."FF$N+S*NLZ#nX+/q K Tݻ#Fdff{pzzo-꯽.=(;wnFFF{0d;w4bjjSJ2%%JsשS'|⯘m Ï-\ޚ `Ϥ Z=)_PP*N]&=zt̘1Sݻw܍{Ww%WYש4o\2eʔ*x~WzzQgBR[j /R*7rGV߿~ҤI 99r$"0ކTR8$59{ Hsz{{mmm׮]+̙WZݩVg[Uz-ZЮtMkhWׯ ٣&5^W5E}۶mE}Ȑ!Ǐoˑ\6U^D 4"F"^ OǻGkNrA{"""СC}IM?ÇE}w]'v̙N Zl]YN{J6˭!{40yi{jKӧOW* !7|6ONC@$K{;9Dq ڋPVV֩Sf͚H7$z6Ʌ^(^{JұcǴR}߾}zNzޛ־c4,,LZ&---''ãu+55ϟ JZZT_t޵xھضJ-G%rwwwɩ?!|h/ʓ\\1XNr fҤI&L\2eʘ1cgiX#GlݺPi6mի+۷oNsxzXyC*Fy*[$5k֠Aڴi?yѢE cώmfE"a ;ɅL<ņO/xO HsvK{&v@}/M` 5KJ^p mRMu]~o+ʔJfORt]1"33STV\NOOE^ԥrssSsȨq/ bs&]}T*_>a͙]mSNy`ZjU:YYYjgϞ&ZjժA=ӦM|#"a0$N/&xw&Ǜk ZMai4i;r䈨?쳕.uG^XXX]T3;=/_:_*$$Yf/b^^BXt,|NSDD{i$5#&E.?#'>>^^^^ޥKQ>{:ԈotVh]Ymٲe)`pa AD{-j$8xK\-ɀdԩx`Qө0 ""λ۽{NL:S**Ά]&=zt̘1Sݻw܍{Ww&%WYש4o\2eʔ*sxs_/M&O,JIIQLl.]lަM3dWxƮ>ËRoDžD`Hhz%e|FLqY5Ʌ$$g`\w[[۵kJ9shVw&UT^-+ݺu:zKgi CޯmNjg+g/!3dwbW[b-YhHD:>ĉ=Gcحޢc9xir.|Ft29`tlhС>}JÇk&nѣǙ3g;2}v}skįX׷<W?.*F|}qH>8:W*3~q;!9-bKO1vۡB"v֊߿c,9ℨun=z̘1Cϙ^֭+tJ쬭k<}zMBCCkkd2Hת{l95Lb̟*t^? kSV K gILt" ħbcı{|F^n/<?A9k;䅫W)^Y؋ؗأدػ8q0g\G%M82R+OݻWʂ;]s&'s<?R۟|XXMZZZNNG֭W"˥ i!y/ҍ_5/#++KϮŁUٖrSф^{M Mm۶beqH*=CøWŹ'CP== n+@FILZ%N J 2\p셃\N Vl w -rӗ{\nxRR.'r;I8)$LtB9h/GySNyTرcvJJJ0!!A .]]OJJq\z>:ή^ZϡIk.Y`п/i As'lYYـDeƌbsΕi֬YuG)LZ-..NR/+W۷(;yyyڛ :Tg͚UPPlgg'}8 .T=Cj0?NL/H[^޴.;u$q4(&M4a„)S3FiFu\>r֭[5իMz%꯼ksL޽]]]/^hl'8p]tttMD7޶m^xAx~~9sڴiӣG5kT=Cj¢_Wg} aN@^oZng'eԸl?&HӰ3{Y+ذ'O!J,oq\ ;ޓ]VM_?![\X)|ՎȠQ#:y3/\z]쬼B4qnB`u 8+_2}Z-pUq^n2oY+^nG-~cı? ?w(܉K\NIL])r"0f~QƆM&g1R@:4c=?XZ5aܻXcgnfdKd "FVqڰw{Kn?j-7N9yV, (WzVt}L]ȾD$N@^Z!a0i/\F#$NiX"Fӕ7Ͷĩ^8^t0(J&+[ҍߪD"^$]ի:'xBMB{2dȰaXYY4SKZҥ蒣cbb"L>h) ?le+t]Qq]"zF{i/`T*ULLLΈ#233EEjuzzo-꯽.=(;wnFFF{0dȐ~/wiٲefͮ]۞!EygϞU*qqqV4h?}t y/ *ꫯرѣx͚#FОUE;lذۋnjs puvzu{~~ؼYfsUKJJ\]]׮]-[>S3g.4(xԩ*Z'z9}xvCGR]Wk D:>"vJ+[فSgDə6m8Tlll"##E}…uPP:t$WW׈Çꫢ޵kUYO??^tiԨQm۶5S#G (*yyynݚ7ox,څ ?ɓ5{9tPfDj\{;v_2S9B϶j#lX"F󠕭sYW4 k\RE35c@h](A(G}T\vM<M V V^uuH~_6हnﶶk׮s܍+~wuuʓ*-ZhWu&7.reA\pOM 0f-iCK䀉( 2ZjREii ezEYDDaXt: eX~5{<,"Q#Eɉo$_AAApp0 mٲ"*[u֓O>yr`]Ok5s:Z٫bj"oCk}CJe[rJ@۸g<3Wxx8zСCJ>}{@Àbcc͘'􌍍CCC#9D5jTTT P(,,,άz7wޢEtx+Wh+--ewc[ 9f`` ^Uyoê'i=hH`ZE:/ %q+t/F;vH$Νjs4!矹48cGiܽ{7J Ծ}暫{=ǧލ$=z:tu|ש=5>`W|wÇRķDЫۯI~nN^X2 O7ޭ j0>ŠNXOHe6WT.^{9s&M| ɏq c$>gjjʏٱzxx8::hҥK;w*ӧxuJ;woҤI',C8gΜ:DWE_C Gt| })LΊ;FIнJ9r|~7~ѣ,~13&2yt]v5008999eeejg>: 0*Kz*kK4{U|̯W.q'O4t0-|]R|En^{rvv6mfeʔ):KZ*j񦦦iii\<44Ɔvvv3?!G]Imcǎ5772dի /^lff6`m۶iu=̢G?Dž 47^S̬ ' 5hJH`Z 7?Ie%A{E W^6[n7oDW*W?C'F9/ɝ 'B)SNE?t;:R:}%vuٸ:m^{ڎΝ;'$$+Z,t0-lڝR_-2Nzx;O&CZ2t0-УR=xoE"W^ǞeΝ-[VUUhɐb:oSv]nAIн-R:} =+O78z/&ׯd r hvJU\/2#'B@w}6m*++k6\vM.6Ld}Μ9|g͛w߭Yk5ѣnj@C'`QuCaRs˷ju؃^{K奥꼼TJ[[[ZwLLLXj-YZZ:c D?8..nŊڵYISŨQF@ Fy=sI*r! W^hJe0 brqƍ377?yڔ^z5|MQ@3'Ќo~sY 'B@+ht(سgj'|Be+m~杯5eB[z|H }fQX\2/2yȱ_^2NzV4ќ锖RĤwM##{Nw=ǏoiݨaaaCN4ꇫ^*/ۺO]U q+t/iL'33 jX lܸucS(~RtFE]3})Bd h9```f#G3jʔ)ܪիWZXX{JyEEŚ5klffF%ϟ?_k*lTŋu:ÇS;۵k/u-7dZtR:މ'< ږpС\$)){РAT[ppcaa7n"DžZӿj/ꊹ-:tF%edg@|ڭƪ'B@+g:AAA~~~Ղ}P*\m„ TUxxBvwwEooo~ \~}QQ˗ǎ[kBK.TvJpD[lYp]z55ȣٳ bhh"nnnΝ.b pet`ݥ{\,YBX֦mhJŪ~:/ęFƕIx}q~T-p#陛Y2&&\$##;88ő#G8=ƆDFFRw"b322"T^.sBѽ{w rS&??ɯ_Q"ԥ,7hw\Z;D"Ӹtڕ3H·6]N4j/Je;i)H5.֟29Lg…ή\?jbiir333nqƌ"Z;vEEb81e*|r r̊)uNo]+(jjZ444=:d&ˀhˋC|hu>@9q^*ﻭ@jܚk\3z9LE͒zU%%%YPP<|pA =!''G[j4l0*,:wL9K.QV/m"~6122Ӹ:uܜʌ=oJ1m?Dh:tFi]g[^9zP#e`` H腠$ իWuv޽EueW\TnbbBeee:7cG.hkȣ_DwM-9.III=m޼y_nD_ w͟{1C'`@~a{m_ =xXSN͍"})((wVTurrr=]*̌322t7@ 66 "2… R߰NLmmyځ,bbbRqa˽X]LO8+v9. '[YPo:oUU vn[q5Je~(ďQpĈj zxx8::a*g5ݻWw4M6ٳGU .d'NH.]/@w}W|mmyځ,bjjZq>}: O<Ɖ?kPGF,/Sg7m]TuHe*w`4008 ;99eeeƲFmgOz ŗ^z*q_GAWW׻wRK,aH$ݭ_2001cFTTm[QQqՀA}QFŕYXX*LRRk[jj*C1G"\VGZmZ;x{{S$$$$--m֬YbƅJ+V4׻굫\BO3?H`*O|ѭG뎐G !![T*˭⡡666vvvW6vXss!C^pfff ضm+?wN:YZZ:88< iѣGy~?2|p//;wǏk~6(4Ӂ*j,G'f\XpȑTuOEEE3B={&C'`D]U|~LWyb&WTT/FW@SBJ?'He_*Uz,PhH`BRe޺CBt0_8cfLŦ#zF htjl7R?=9/H@N} 4cJeykv(KJlH 9 حef7~6)>@#y[=w4Iظ{ǏߴiSYYYڵkr|ذaujgXᤤ$/@kB'`EZtST&_H =h\aٰ4Z!J)bkkKnIQ;}}}Y̿\Yy `ر#.x Sh,DJer_7ޑFT*kLPU (,,N&55[$c\Soq7Yiޤ9uJHH`Ϟ=.V-=އdtF $ɏrs =ӼIsTZZJAj@=lm 0L]j 0 Q^QцLax36 =ӼIsꔙIA5W]aJ)c Ph/~ʿ*-hf z7iNC(59rd̘1VVVSLV^ظw ,P*+**֬Y3x`333*y&X֒:jժ~rÆ k䔔Ъ~꫹MJJ4hZJ 2ƍ|P/uO^|EWWWmm~50$ɧ-}y[iğ:UVVYXXUWW 7""BT:88_x0aUP(iۛ_3ׯ__TTtc6$G.tl?0::xΜ98ydjf͚EٳgАUv9[`.Y"+VjY m {2 W1HMCCǏs *G9p@n-{ ;Ez6%7;??mr=IIIa۷oO,ZӧjY%\g޸q{-hD"GvJAFBaee7*&tF**~-Ƀo AB4oN .vvv%]\\jLYZŽ[1cE"""{FCu'4[R\buf 6ĿzT-bddď:uܜGߛ[Rnm?6E MyjB'`DLt+~ izye`` H腠$)իWuv޽EueW\TnbbBeee: Ki̛566lsϱͫlc?9=hʯ&tFN2sح\Ni9BB4oL `uuD"ݻU*Uxx8{ܣGC^~h1##CwDSLI1~X^V˿S^^҆bsjzy`T*GA'''~Ύ#FP\ёfV9a޽ ӧOױS~X3ZSSR'xBP.ȿWl75ϴ )NOR|IОfE$ѩT*b .22@|;p+䔕ojj ;Q-RU`` -KbhS*<8uTn&/Yk+XvڕQwn${R =x /L|~  =h\ "((֭[_;|o~Ν\~SP-[pSͭ(##Ã]1e#Fݻw%Kz$vR>sVٳ%%%,Hegg&&&6l`||<+I;j섄LKKc,|2$%%CҶ"ۛ"!!!Yf-T*???Z\bECp=hFH`Dʸso2ٸ<$gL ]MT*˭⡡666vvvW6vXss!C^pfff ضm+?wN:YZZ:88< ogΟ?/(̯DG57ij>:IrTKbnnn#GׯOEEEsI[h/(tFVvIeߟj-DB^nI K*Д![T"mR:}ZtMy-H@F@9S?!ޒۉH`tP_S*17 =h#>T&Z]›H`9v.V*ڒ[P[H`jzΛ=$[%g?uT& P qǏiӦ&hõkraNMѣnj#~III>>>666BkkkjWrr2lC'`ҹ)wbN@TZZZˋJE}ĄN___V޽{\֭[ӦM65jѣcǎ]L Y8jXAAALL͛Gi``0{lJ@#BJ P]wwT&_u:Op^^_8CDR*5f\\\(֚.N^j!!!gQ(x4t0G\3})O4gF ٳgs5pڵɩͳ[@'$߸y1) h "͙Qii)\s5ŋI+O: Li(33 jԻ>(-d7sww0Brxhġ0:oWKe[4HsfBYȑ#cƌ2eJ||>־ "UhddTnbʋqq}?&B'4PFF;cmmOL6͛2vrvv֭F`yL>w69)ό $ 444W^Q۽{-ZԥKŋ_rEP -hv)#M@Z%XuᦤVy%㰤Iny&NrzB< 7nٳkv֭{'޽MDV;f̘?`}v# π hb͍"})((wVTurrr=z+733Ō Ne4ZXUU5|pCCC"}"=oCd&`qg2[5ErCNtBC:u vMT-zP?}U*86;)̌Je~(ďQpĈj zxx8::쁰*g5ݻzWkrV͙3W,bjjʏJ5۸c ֯X4K6No~tBQΛ7tss300F6kH@=TUU{}q@*;:&JSEFFK:p+䔕ojj ZEβN_z%_^yyybکT*uOWy ֜Nֻ԰gUUUSQFQpZtڕ6V:4zj?G{VIB[}uPoUe?Eݲ7X$F@AJ!tBX^^"-,,I]EBSWU-߾_*;FH4Z_p#qZQ7kHxHew(Kp<V )+**(إKzoRj.$;zZZ&nZ!},** )hccSMZ-z ƽ|ŌU23R: 1aׯHiӦ{VԪRmF*#nЪ!Vo͎< uCJ!?~pݺuޤ6$p>ᚣO7ee7 N{w>~M65u]vM.6N[I^{51c&hO6ѱGݍ1B7S8CtyrT&?v.m}||ؼ)--MVEDDHRҢ`bbR׉5X"ܼy0u?;ʂ͛79`* oEFNݽ{gϞ&MqF~~;-pƌcoo_MD!%%% ڤ}Tn Co@T*ķPU `O9,88Ȉ6YbEa"HyB"@cAJᲲM֡Cnݺ9;;"ѣnjSMėi}ޮ#RCW h_QϞ=: dSխk*'')8=8tFKrU*O]f}`9*--e7|kh0h zsV?c+aŋ+ ä@''5233)Rgm>___zuVjҤI9&{"kS(,.O:ʏ6He|}})Yȑ#cƌ2eJ|_AVZZzj[[[ cc޽{/X@T7Xf̨'juϞ=oݺ $33SdJJߐ!ChKRS'N#9Ջxei#Dq4.%w:aHeq<nßUVVYXXUWW 7""BT:88sN0 W(ͯٙׯ/**|رc'sgϦ W\Y]vիWV:[ؽ{w̘1/"H~:@NNvbPB1[4tF'Q1IR|[9u_OO\͒111Ǐu{FFwpp`#G8p =ƆDFFRw"u:Coڴi{/\@[Z_L֖ڵ"cǎouɓ'amk+**+%BDR4tFY򜼂2y -\^ٕktqqGM,--uTnff-Θ1"\=}CK.iۣGj;*q-x')xY.8qw5Zkkk-aCC:)E]_SqNC'`PVQ(kL|z@0f@O=-zxxhի_sMAAApp0˶Wi999EiVlٲ"*[u֓O>yr`]Ok_x-E##ɬ)jP7h4tF[,?޸ g@QQQ^JRɫW޽{-ҥŋ\"Ąt4@QFi6IPXXXPòtWq-dBv'=vԣiТq]dXB.ͣHAS~0(ɝGohN3 777ӧ VWWK$޽_XR=z:tǩ322t7@Sjjj߾}5A{=ǧ\.믿V=5>`WÇRķϽ:_/ռBVdB%dL3׸;@ }h2s{R5N3 Rٯ_? :99vvv1b:SGGG=6>>^[嬆{nKa;wK? nW^-g;wl``7iҤz0e̙SТi=گMjP'KZqw 0ЪW, y[;ФRXGpgHASVVV~~ill,+`nnNk)NAZ]^K/qq'xۋP L'jm9חR*=QF(ԩ%]v +y7 =x .۟2{^:@B buΟ?۷߹s'w[l6[QQQFF^rrrbb"(//1bE\]]޽K.Y#Hjl͛7~m*_+J999$8*LJJbզ kr~uСgϞ".cbbjuaa˗۟}Y [Ta][MYfթMЃ慔N} @+nn^z@'!![T*9' 1556vXss!C^pfff ضm+?wN:YZZ:88< psZf p][qqqvo=lllܣG… iJ?~< u k Of*C7:U˸so2T4nݺݼy]M:Yh2H`R/XK*CzQ``ԩS-R:}hsT*ZQFo@cܹ3dhi@k8L>c܂B4رc3L&CdH`I=$7QZZZvyٲeUUU )>q O~ :P_S*u4z BJmS2*j9=Bl>u!6Np>5~ عX>[7w666OnݺM|}}J%d w}6m*++Ӝ՛uL _|^s玑:ϟ??wAY>B/>Zz̘1^^^:Ycx\m`LN-P;o. t_Jh,jŋO>$MƍKWWW߽{(>j(.V|嗴jɒ%999,~}bJKKyyyR"u~~uXyzAbQQQč]p K-ff`+++oܸz-Vd_脄htv㋊SO=U]]-X߫W/APTxΘ ]]]/..fӴoV0q_smcRSSu 毼bt$i$FxV֭b H$ſ3}wq'}!d:G?FAOBS]I='e[ bRza =XW=51N:eaa]PP_r%W --C ,(..>{lǎD"aLLLXdׯ_W(Vݻ߻wN}6\DPtޝǏCCCnAbnn.^ȍ7hwCv?+++{UVVv%ոԫڦZ\󴕯w'~btR R hQ]{ԇTXUTThlǨWT5@J0UU/%~qKXys#Rs'XY佝G"Ƨ*7= `gH꣏>x'hsvگJV=ո'O|tL,\^q}|]>~\^vvݪ$&&ָΝ; =ncԟ ߠ_k| AAJ[f}A%eziK;DzY|ոzbS\\SO\=nݺU?>;-;vlܸqv$z)))k=xZ+ȗ6-{ڗ~k ǕRUԹ>[Y&Cӗؒ;l~re{wW`8UU_.y-tN*wmLA0Y(++kB]klu_})E)5Nm1NCffTyv1{XÀbccE'**@" ӱ4)댌 p++?2qNێ<<<<644$˫}M5O_V  a^p|]Dc5@J0mGnA#N^A,oۋI-$/ĝl7 N}ԅykFt:v|8ONNncd~ VC  } -+{}Q(sKqŶwjm{w+~n:zP$^[dG/~ĉӧOGw޹sgKKW^yҥK3dgϢߘ'&K.u_vvv8<<<uT̙3iaÆ+{q {yq~($|7{bEEEa``еkq!9s trZ5gΜF4effΚ59s]MA9ok???+W}S*ijjGŏ Z OlV/_LRޢ>lc7<>IyE%|Ӣ<ʋI{[uO7{}GKZZ3mO^_ a|^߿v&1cg M6Yh}w ox< V~Aߴ6vSV84uNs ;yOjsg+j uN. '%߸VW 4j۟na}S(+W:thvlmmO߉v4پ'@KS^krM.?u)"k TeqnRr3?l뾝G"Ƨ*2AB^c0( R:}h9K:_`ݮ8y/{wУJuC%OQm⺽G0 R:}h >,Ip(_\T7nuww˪-5wRbn~a=*'vEURVn|yk-|###m?~ܹ |^|1113fWrrFwzQ*\bSJaxl }hFY_ᚣ|x O frΣ#z3`[Z 余>[ɽ7e' ?l+(VQQѫW/V6QFY[[_xQs+ v֍ 🟫T*ͭBBB$3MK{Ov⯓>X־韅7G4ej81cgy Hs500Ҷ3g$ ӜtX~ڵɩy@bbYZZ`E~颢Ǹ:Ml|' v-(D<K)׿=yvՎC;-~`3щis>]T`Hx meF})A())I"L4Iw'ObTGmSk#~~~5_k;v"6NWT87N̙/QJ3?˅+(k"z}qK.}z;wl``P3._|Ҳ]v/_+~_G3f C͞2eJ||<ooA`ё:z>3z1sLsٴiCш#h155UwnTGShAz5|yDҥKF$𫣧X=hq)UU6K^_7'Eb:u=;;7%rJ@ZZZ,XP\\|َ;RCCCD |ٳ_P(VZEݻw?DU oooji_ƍz-[}FDD(Tsss*Kj<ܹsT+-1o֓߮];##7oRښ ).]Q#*ֵkWuLrrrhmϞ=5WTTDm5ᇴߧ^^^>>>mt R::IuWt >>rY>9sPdɒ%siD.sBѽ{w ?~\bbb MHFFppp`z"7nܠ޽{{ֳtR! -jWVVR1cccuL***hz"kYXXlcǎ!C*8uQ$g?u~ R:}h,~kgG}D_p :W_"VVVT-b߾} :)bcc#1SLM_._'N/2*Qzzasr?UUU HLLq;wg,Wimm{tt氰0O?F>iO?7)!SN_J6}&@BπgwFWH]cKJJhLǿRYL72̥K(HKF=[TRs̟?===cƍ~7KIIb?v^xC ޺uKw.'M =hH`!J+3KʛU`%܏س0A\:[ӝT*2lW?5.dO^klu_P)EիWuV=A*('~wP~vZ//Zֺ5' vWd HJt wtRyʿ:})[@[V?th߾=LJJJNN>]\\wWuuD"ݻw˨T*a#Gf̘A??>},?559i$O<0))IL;N哓k=fI赮.f-%R:hDwr7 Y\LJ?M3I\{FM_O81}t~$11{;w|wQ EzH3R< &@QA z)HE%#R hh "-HIBKh -ޓM's7n̲+/_̳쓙;KlllŃ+վ3={7W aeSN)?o߾F6bAIGCII:('''__3g4}YvڻvjwFq?塗^zdܼ]=H+@I> $}LJ˿OD,XB)e9YYYvZ:ׯ_9s{4Vt޽vvaÆON<_k:LIIȘ={zglRГSԍ}Qn l_caaa@@w]@z֗6nܸK.EEEFzŊYVV&SΝMeQb :~5k 0zzMPҡdp~[}uRޯ_?=ZN=6oެ׷o .dee曲8c s'44TعsGEEEyyy-^ך0a/ވr՟NbxƎ[ծ&''6L2dȐK?a/ g͚lԩ*VAA:t(,Jl_]=~olå)GYpaz'奕k҄Co޺-￯4 R999>ILOekGc^ߏ3m՛(jҲ_ݾvoq=#d; )-;wn6mxe˖|V899: 4x_}U5r 111۷>3'22200.]lٲ≆׊swwW_p߂-]we|gnݺOUYDi߾}/t-#\kӦM~|6?c%JVP哼|<t@5AQ/q 1řKoݾd@MnݺG}u>>>&AAAv^+##A @N~Ad!ӗ(W_&:w}ݧD,Y> zV}w#Z>h։9ׯ_r2s(nrګܾأG}T?;wnҥÇW "L|-e%zpp}_n_{r*{5uvԩS 5AeY|q^ s,8o,\)OҳHPQҡGS\S߾iD']C#702f k_~M{ jiFպ ӧO~ѿ B;ލkG2@M;MkӦͮ]-s }6W^=wF6k?;w@6+`Xo{J)oʨg. jiW_}ebp駟V\nnɂ^MO BpLvJw IS;:&[t_v͠Z' zձC 1Mp(pQn_;f%y|qմL[ye}~8BpLpQn_;r}_n_k`ߧ֜geenݚp P6펝jy6l& p[^~|v4õ}r7dȘyd;u}||t~zӟ*spƌ>k_y\^W~ׯ_7ƍSN޽; c P&Zxȏ~꼕S]y?v0!))Zzvn97o$.)92fKe+7z/ Q+wJK wi3)SxyyY&///>>^)M8z!-YYYW^3f,ʦY٬Y3GeQF߿_v^ŧ~:$$d߾}iiiÆ Ç75o޼VZm߾=77ԩSݻwZ 2-79'/\]~j3Ҳ2v^ՙΝ;p}KVVV&Mq˖--Ԯ][GyM6lYO뚻fdd(-Jɓ'K.)-)))آE >Ν;'t>s93c; Kp¿wx9_lg>l]ݏ[:r !Lܲ2.UbO[q:cKsiDFOL&(ܑU[:{qҤIسgOM5w?+}Ԡ%77נEɢe*t x_] K #mf dM1/\{Cqk,j۟F{?be0HO}qұ"f}l}m?m;pЉ\.7S.:#6~"^|aҲգTFN&gyd޸$ z3O۫:soذ߰|Îu;?zB򵴼XK2rSRN?>qQ|vg_O\jT'C/_bg򧟩σOd^y^ՙނzQ:zFkǏ zZZeӖ%y?~V?O7)?Q'%d0"z6-(x3vƯu;FldՈwpBҖ̥O$]J闙+7^t@eΕMEݴlY/r-=DwM1?\;ĭs7___y:͛[7mڴiv׭=9],\RN~~~tt=j05z*,řK_|YG֜2jɿrIiYRS$Օ,^gStJRrf>0[Un={ƍn^xAwww:]vcǎyx,vԩe?~|߾}mTzBU_)]iizvaٻ\rҀJonĦ7X뀾_---ӧ'ANЬJrAAN)8JF͚mqWZyy|3[TTuyON<___'''ꞞČ e]hoY3?ceAAoJSRRdgϞϿA᫨(oCߡۃo׊u:uDFO]y+Co65 lrYr_aq;V],G_:~y:IRTt:5mtR^qPysG-**Zxz)S:}Ybbaä%00PZ999Ν?~t'N>ǎS^WZϤ$Q}MP.)-)))Jˑ#GE}%  nqkNS5 .m(wRR>F. Ь/Fou+-+3&KJrQ%_R7=}N[V%uj)JW K.[l1X!??[nݻwW h߮]zzzmvƌٯ~KY!Z~~~]#[}nA9?rMӡݖ;f]]Qq(VPy`u|I(XKrig|??2zGb>+2}qO&,j֧Ql]y׺cw&lk72rJK&%z*,.IIMKJu8ش3Ϳv#䕇B&/=I"|uFlٽC;LH:yyܙGIއMD5yCPJt}D\Ruyʏw)?A+QҡQ,-qt}TMc'ZK(#t}J:>%zv;BICPҡ`G(#t}J:>%zv;BICPҡ`G(#t}J:>%zv;BI{4p `_(#t}J:>%zv;BICPҡ`G(#t}J:>%zv;BICPҡ`G(#t}J:>%zv;BICPҡ`G(#t}J:>%zv;BICPҡ`G(#t}J:>%zvqΝ4hw]~ .)6\gŊ!!!7%#Ο?߬Y'|ŋO=T˖-\bSl 5jT[}G@ILj>}4h 33SY )ZG݉%$&&J8#FP7:99;wjNǛxA %^/xx܂ $kתki3gO:HA7xK %^/:={J8qqqƄi,~1D zK ^%^//xkN¹qㆺ1--M[nmSlA'RE ^/xxAKQFNqqQjNǛxA %^/xxS^^nEitqq)ZǠ)"^/xxAK ^%^-ᔕKJJQF?Vt"=\ %^//xKZh!jNǛxA %^/xx\=$gϪeQ-~1D zK ^%^//xM6MٺuqҸpBbu :JI8cǎU7?VؤI۴iSwuԩjѣ+W4k֬W^ϟ3f,^vMBPPP``YO:`۶mJAOQXXH׭[q!!!~4 ((Ȭv>@ `7n`_Ν;bŊƍmٲ%00ݽI&?sssɤ7VZ`+>]wڢEÇtA2aw}[noHϸwۻ~AAA[ne6&G&mqWyy$VMMF8S~A}.88… և SXk2:fFx-+>}c#J%^f;5JLy䧞ze˖C0dxMFl\Ոѣ"""$g}ȑ#|x}D@l|'gsgϞuss}4h 33SYr!!! SXLƫ%:(FGG˳~m}Nk߾agcsGTUog-2;i&,0~r};${wpl_~%c؆%L_aENN4zxxOu̴eeesww߷oAi4jԨRuK^^$\^=fc[1kd2[?hLw ͛7[ {ǡ%:p(#FP7:99?|gn2EkEKZsٸX۫W/Y̙3u.]*_}推Ze6vLX}?uꔄJ86bŊ{1l[-[0#""ԍ'OF򩎙vЬYHr"12VLfcZ+S5]w~m5l2™ pڵƯZ̙cA3EkEKZsH,Zmذ,9q4agcsGTUog-2;i&,sKG=%!7i҄pl%11Q梬,ưm3Fiڵ|l>Ӧׯ_E%%%d1v>2m5hLw~~~ 裏52F8SٳũQ27LĢ%^-9ll<-񺸸Ȣ*جY3QUl M`Cׯ_|(lB={a ۜLr.yϝ;W:M6?#TLdi'"=zT&F|G&qwULw5mT>>>3GLȕF8SP|<--M[nmVLcs66xKvaeb8;z;ka,a 6H[l! | ck%UaÆqBʹO|ƕ޸q#**C[ڵoll=-#ٸLw%&&vEpӦMLUmGOnp,*d4-jΡfc-h7==srrzw.//o_"ȱG/1/X2;wlԨQJJ QXO$cƶjj}] xΝK21ӺKՍ}Ʊcǒv29Hn󟙍grd2WqWUÕ)V]:uw΄lp3(7,++S7H$1LƘxGPX4ޫW6WfݶmۆI~s66kDy;1,aw}M`B6AtLSx/ {w AhhxtƕbnC:ᱹ#J۹x)]v=CwHHH>}1\)߱oV:|pQڣG-[[Ν?Y׫W/{1[̂lll`r2EKoȄEd3(۴iSuSXk2:fFx\"m_|dh#xwyl۶M +j׮]Æ *g19[|駳MF8SLYfr2~1ck׬ 󎟢5b2^-1W5Lƛ.Sȑ#%{?A@l|Y7HڵSSS55C?|˖-oA/Aisrrx㍦MJ};uuui2ۜ#ؚ@pe>g+%͛0`˖-6wZv=߽{4>C1PZZNSNUmۓVk޼yڵy{|'_nB̙3!!!;vlQQlܸ1((ۻN:{>v'OΚ5m۶ƍziw_n]``lǧK.ׯ?ϰbAoǎصkW;f|7 /дiScǎXJJJO޺uk{lȑ55@a?[ 7{ u˩S ZQF߿?//綾^ŧ~:$$d߾}iiiÆ Çm̙3G{꥾yZj}\Y{TQ62cƌ]_U)SdW׬Y#{(ן7x`JKK?JU݈uƌs̿ԩS5oo<ԣGyȚ0IIIsvvޱcG+ܬxeВ*-'OTZ.]b-*nG,SOIˇ~,>|Xm˖-Ν;'+tg޹sojҤ4onAO]re?SXXӲUݺulذAVSX|}}eQajy sdfP j5SRRnqƳ>s}͙3Gӵo><<̙37E$&&+[vss _q"""W٬޷tŠxek*0!JKKΝۦMIXl>#{65pZ endstream endobj 167 0 obj << /Type /XObject /Subtype /Image /Width 1691 /Height 1096 /BitsPerComponent 8 /ColorSpace /DeviceGray /Length 3616 /Filter /FlateDecode >> stream x! ^ endstream endobj 179 0 obj << /Length1 1381 /Length2 6029 /Length3 0 /Length 6979 /Filter /FlateDecode >> stream xڍx4\ڶ Zhчu{NDc0D{ !: G'JM=5k}_w{3ks (!mHZ$(i PD&0пD&Pw ;ؔh P<@"H\ Re'-xD@QDJHWw#S[7Pp `@v`*Bp!}#*%$%vA "dy^0#{BF]F$9P9 h/;1a( @AC -+X/?@+ ; ]\`CZho4?QHL< m1߭ 0f? 0W4JQW6 씐..PE?e;w?@z!^vưp2F<0ѿmP4@()&& @PoЯF>f ~HW=f h"C=4?\@; :DΎ1CZc b}uga7 *_NEE7O@X )@ 1( y?}G ]>ݲptB&#(tc,+#U8/>z1*Fbo)/jC`.@1jP@8`-'RyC`h_nKopD~=a0Q@0"8c"( 5 %6aQ1C9kJ¨!A `f #݉~,H d# 1vxc Bg0Wa5 ^#x+щ}Qhg~Zjn6v/ g͕GL3~9~ԝR[W<(~eC;gDS$3XZp\l*Dm?JNYq yOYWCo[dzi]a?ş)}YZZzߗ!rT[-"kpuR&RyZ"]K2[5z!Egdz7r iNv`W䨶:<0:egZ CEe'-d+]M.(9(4ptXV= ~{4cIA|j~>ydD=h֑f'IC= Vse͓0h֩&P^rn-DbHk+S\*\!hK9˅*wdBe$o(%׮~*PHJ3MDXn'EC|şƁ֔e}poP5nSx{\i CjRlaV~hc~VI3{;Ɠ 3{Vt\T)*nqͅK%2 T&&q<"<ro$ڀi.Z?iPs=<>9nEF_V֚bL<=ұZ˩fZW( ͨ{κ2?+geKzH'˴[xI p,X.F>M=BXͲ7qnYRH6P-aaBkkV<٬Fo$ثU_Vi; >]zXaF)e)P,z" ^d%ԎOSZ EMO=ă޸*G]S*HtC9P+>ZfWuhB66L6FBٖ'lLGrk(R<$ V8zg݉ g-bgu?uox1K:P4'J+ήRARaUK9jJrl!Хb/O#bqzطZ; vīܝTlUջ HVK5> r!v-pxK7ZcO cHy쪘-Nx2.B}FڊsnQZk6b:?-G -՚QRr9s1m0:wb@]g^}1+9r ՞KXV(gK(r^=:Va>O)S+1jeUpM{S*e|}jl~\#̴%]wzj#|>5Nj> oVO*Peߵ1EjdATUfԖ4vT(5][ -O(/r^|'(Kō~Wnߎ=ޖ*v1ʎ m0qXs+}4Dtt05ͶM(@7ǭI}7KLcO NNx#|W_{5rZqDȓ+xP=9ilxp, ȯEt?K Y8QϑXS7b )y' l4,ܺ6OG4Їe%LsZ3 $q]B\r6 _+8d߯}3_ !}x~`IWVNRo\%:9j73eIF^;YF>(W9a as5espĹGstCrnYDHkO%zWsrbXW5@e=ࠫ ǐ\;yH}:44v:c/}-Tz2m!=xjszuu-q5wh|' O^߰UVFz<yHS乺uhꗫ=,"7W}d]ʔN“%1<ٚ0EdR3AU i|V(&Ωd E_ie}d#x׃mp:[tk \}%i72jcpdاjҚ'☥I_|0LK>NAhP*` PvTmhrBf7+~7l;K1%'yA@QB:*⦪/cQ!/g}7ޤ*^;!}Ǟ_C8mIbcN"/cOssۉ] :Vc9j٧N\} `HNw~rli#}-BvH;)d[jP+wN0fC$nyߧm2J\T4_F_3c#ܔhҀcΠ7W3m۶@.>9Aђ(NY8PCu[J:gh; 'uVr(X+.lz\\Xށ=lV S M.u}W:ZH;E,y,q]h.4;jI>C <,X >ˣXBtS{=1ǎ3O?t<ŚF喝'=2ɵl9)1OcGğH+Z'薧|U%RhaoZ'ݹηŃyOĒz&$@@Z_Mv4(On{`pg3eLa綝J#|{hƞ(?u84B?Kd æaLRsOxcMȎ--vn#Ѻ+%.eMf]|Hny/Kǻ D<ts<'ox^l5/_ 痨lܰKfDžE3 lenvFm^$Uoo]^~Ы.=K?h+^gNh=)_ @wccV[fǗ!jVE8V/SLg 5&\ԓyKGp0~exՖ6[ϱ=d|#$}#ƊY#!ZM>v Zpk{Zeز`nlڪY8Y4gޒɚdzU臯so2jm'Կz-(i,3+(2dف3X-HVAյ&g4>QcLɫwf@iT1&Ǒ |>/gtC8 D̺5Kk#5;bOwE5 &=wNUYT#,5ƥIM,(E|A$6QA,iѪeU-ϳ橧aiի ӊUo> @\ـ%hz|MB[Эi2::sPӅ endstream endobj 181 0 obj << /Length1 727 /Length2 20810 /Length3 0 /Length 21388 /Filter /FlateDecode >> stream xl{spfnlyc۶mmcm6&ضsn}U?Uz]69  #3/@MRTGA!btvtjNV+33 @ @mJo#@hfmots6{xx{3 2Hfe3))(J5R.@;)@՜`0ut0&Wp0wq=@AB]DRIQ !Ƥ.:YO׿dxGbcaYL-ś#?f3w>?-vSڛ] f.QG;3v!dUL-vPo_T&cP6[@1ۭ O{ t@_M習ue`e0pXX6}m;1b;gwXc/狊S,-&L٣fOZ1}"E~DmD-:3TW Us<7Vc]<Mܗ bGt3s UzzK1m.Ls̴`<ÅeT'=॰KRb6H]EZ3$䈀L©up[,%f9nfy PHHr翿\v4~:`ߒS&*Zr &J~M1kiҢQ>3;U(vWrg#˽ pX}`7ȑMG*&1Ԕ`5Oi Ԗv̑WIZ?4O,ne]߮%Vi;\L-.^*+<ۢ9-Fqcw5A*6swhKRK:[6\"DGsF$,9朱3hw+Uow2ASn]d04Y9WdA0quJs/Jkuk(e4쥒@b@d*ɞ1אr;H|U=2˪>5dBC ]+h'H4.H6oԘV7jPF߀MIv'"wr9ӬiBf^~+e*q+#3(Ŏ3mi7mk.B͘?ZA`MUp?K\Ekg3Rkd-= R5XxR8yR=`P[hM܏}d|`c 蹛WРC(O8F1No"x9}QN10"h9{Iuo=>M,E^V"]t.1g %qSࠩo-zپw6ԣK\ lo75u" f-ʇ?ieADL'^NI5aq:X{_X{C3ar3xG'7{5 QrAu4G 2 ar^6t()"뮬]U\FeٞB^(@s:wrB"tKmйur#U"Ul3G!p-x;ۈB7tcQ ϸy&XbSE/9B\M9 ZҜ~ M(n?Nd601x T8weK0uk4mԄ<9n>=b 4e"PWNjCBBYnrX^7KTn7O7]S}tMxH#| v<ֹ(ČرS1^kƛ Bځ.HL5 ͮi{ŬG1e)]N*hR+co%{Ws,K(3e`frM|C 30uq>ɁuR2K9z<>8w5i<hL*$-z2Ց/AZR`g\]H3^ץ_/&{Ιo Z0Cyx8';"4A֌Y^TH,KeatȂcCpx'o Id0ց˅-}`.xlE qӾ"q|G]%  dOĊﳷR9DH Frn(dc~$\-'3pw׈G2W V`kf3.[%!wrl6T 4֜u4:r{x=n3 _Ye[vPsGBN4okPh,D,-TuoFkԴ2M.S]`[ScV\͑Γ-?ʊ,%/]@󏉃gGeb%"GWsHSSZ=N/jgٷwP y0.'/d}) |YGq^bF 3<23yfCmgn1H3 2.qe )%2L4Rq~@l1:_ûYAY?A>^ (Yᠯ+Yf2IO}lk}L#78gY4xyCnS 3*fPq50CjoEQ 4qYt5VMY:2LQVhZ:lܥ1)RX njNIłR_50ԬlR-!_qF]1.8p5|Ge!m>50lL/c Nn)_oζV`'ʏǖDT˨,(6&T`MzAӿV^&N Bb2+HS'bq"VW*ţp|zb6y  =8{TItR9k =Xd3 czTE]0Qo՘\%O/#PNӔҦøXO>7Ww6Zrm& 17a.LJu+Ɋ/ 3J F9ҰD.aob87 .>oD-~R?~so5"t޶M]'ud~3~MwV7}&LV! 7z>@JmZ yάiW,s! a._ܧ!ܕ:0(cY=ΔA,SR*~ Fj'ǒ.u^Pq?E |aj N!,-ssI,0wOrNzRqL(5@eZퟠ4LT2X>C!I4 5|M~]eCZ!kXo(ҹ F5'w2> V{0ۮ4Dc%X BLޢJ{?Ö@ ]':90UęڄX6V(3̠Ң{3Fϖ^ػh1|c/Wȟ<}7 QٲmSaYf9]kLb6.gH|T;ȡI_ӷ=jAw~\8d}&\Waϯtvc 75r[$W5a.rzYAV=݀qJxLxYO zՖ+Ɣ?=a{aؼ )}>=~F쓒{`dW 7Ķ68ח,,㖿Hk3QS1&௡(c޴=kk[K|3[PYl&0$DD>HpO2OJȺtBBu{uag}~R+ߛ·uylwo\0>b`FH<א5B%5H,_Wt ~IhZL|O=vto!+`$,* ,畟=Nl Bd449lCf&qdMuE D!$du!'Ҷk=5?BdiVe@,i}^+bt7g6'h0}oBih=t@Z?Y7PK~e^3MF~,8 C3`$b:8(Xe3)rg"Y#g6=-;GQ=:t4Y@Ȝt-SaXJ78ŏ8/= c *cWk0rC;QC߇%]&rG蟘8 a_FCF0PRodJzKbjZj7~EKb3f9hȖ30{%4.詆hC j:NI56?OXwb]ې["{*pت݋OkٵEI-+(i.9:)B}B I.NwέۄE7#<3/ <)viNG4'jG3M}C/?&>nY9ɥh BKtv 4z׹1AtrEGGVF0W\̇KC{©Nvb> zb Afc9P#i3Vkz0ԇ}g%H t۰;^"V ifs1,CwI^Ƴq ;ʌxf#+kb W# ͷ܎EP+)XD!r cR]51`BIBetwJ9!jGS?>J[耱fWugs@L9 䇚Vj_&-Xg .h{f[byR 9|KwD5hbc^ `+Oqp z 2sRTȕQw@"=g"D^ xd|@u[FJW=RA1,x dA֓U"S Ot$k^7 G;%)hٞ$ZoH1:jn j:s =122xmEi> |ܥO. L_mY75d>1p-dȩ4MzsxωW}t$V}e-dEsMY᛻D Z;5M Axpv2Snׅ1Sd&C5xgGy35װ)l&jƒzUמ@%YB={*cBܓ@R:/;eF2nĠy+¥1ʯQP~ä0=%,O0uŃHgohopIBbd" xe&̸sLcWkPхo9$vi5h-x'!oj[_ƃ'y3bj {XEv%XtKkHX;uLaLbWL~1B^=j{RŌw%@EnrئJt3:#$lu EM>*#WznZ܍V+0f+[ 6=Ws2LS: B-6Ċg}l"mi0?W3f=lLSٔvO "9( $(PUpϱqD+r 2t LZ| FӚ%opY2 E %'|D]6a]xѮ%[I&sFtw]&7h%8}2cx:s0 8S*3Ǭi6qg+?\ /K6 P,-u3S! K{i_{]ί 6 J붆k]Y'_y5XtJ:Eh$F} i^ߍ 8:O$^$vmc`w,k}'#(_6gd*۴˔ aW]a[ݭ,޾ r5^Z G9 x¦ {} 3%+Sv./('9x" zޓǭ# Jv{t.85BKO ' cKQvxl\3z RsaK!g3t-CC r+#>fb1|a%H5>>wG}]U{K_W3&L/@~x_5E@}c~ʲˡ(’qO0t[Eν](w05nU 4LX7 a0;N8NaDz'8n+:m\5ⓙvj/0yC¾@V$J >yc&mekZ 8"R*vxtIN,"3|ʼn5yL1O C4QӳbB%0YB:ed7kI6L/4@gC_y ma$~x=#vo1"Kxty7/ P4& yh\+%mB31 YFkKv4y 7rogzֈ^&kF\$MM93@I8QG鴄b}Mh/ڦ<4Qd}3sEUŊwİBˤՙO ڊx4wBslʼn[u{!pp4dIfOW Z3-{QM6w}4>Aʆߚ}337{hR--.>$oJ 5- ˒~\G;fWVE!raV? Mͥ/c`l%As,oclQk| w43Xj0Np:+!ZEE%BoL$!:=82v$ |pJ=KɌ=TŁu /pdx`ь/^xKMF!& ~}!GִXA ӱh"5Ce+Nq6{D8T!1݂mFKi^wZ8ԅw,Ő]9 jPƒ):o6mɷXǝ F'a<VoQK~ǵOܻkcR;`2Fܕ">^wQ+m#2u%6T)$NY(Z*>[ҩ7oJ]L!UukחV-0İ}7 0'O) @զ~XhϣR㶷 AY>;7%-.)G|s @ͺ:gQW~t_odGfECŸD];mFgoPQ䗜wwD~U/򑟖"A714fiG H3*2HTM~Z .}+?%7?ǝܼ'D nݮzt|&UOe^?lp@y( guƣr?CL|D}!V޺QN|jg*co=I3-ʰ)j]YڂWq%3vۧXO7HeI?Xhy2 Ri ׻vGUƙbwBZɋa8nuyH41׉s;_o&ȸ8%,!L/MJ}2w֧n/bG{ֽ ApZ'N;)&S &gq<5 oP_.G e/oEGp◵_벇L~8TowAR NЮ'|1Z;5,vE5ᆣPѷ#5Q*n$`A`/4.x]ߨ.t@+Eep0nz_flEȬG=& 'M N4B# Ba &x>XK<^[M) ꂪBiPi=szf/$Vt3ĖndB=Xx5GAK$բ>0B&vineC:|BݩUu[z9z (ns,I7{ԩD+7XS›Hբx)? v;cL?"å8%nNz=ƪ &-}$ID1fL顮xW$@[ܧܙ _i*?ɕZ`UM.W4S뻿/hLYEJ{* dFe.ĔG;ˏz7ez U4( V%v:%Cf<ͤRǾ9`PH7Ⱥtgf4ea7R57&0{ SS"9bSl) r1K_l9hٝPhߜ_{-cTG5 dl4($ʖv2 {,LJd:3}Ŗk6ZYVqM7j-? 0ihaX )p6 54W l'X[Fs(GFmOs`4 e4Q'ո<&D  fR$W:o"No,2EYj-l\1sGaQI9y%#i=9򫩑VJy1f4ndzVaj47gmEPMC <\ C2,?.u0IuTckD`:P`2!5B {cEB;;unj1iU(p٪@ȀqPug׾do1ύm=QJr0Pێm&lIWTD(v1I""IǍ)>8%ݸje+7_c%t7!#ΰ~5Oh%!!0'D]D"+N@36E&WW辭A<.T C|Kӳo=v3aQAm.$O|6Ǝ$B xT/a|ҹq5OiFlԯG$& JYmZu6Q-iuen4s9~q/eYhh*ȳrZG5b}IdTǿΨϗZ]e''y/w<#|P;]Az-yC)c>ǰ`2y(S{z M 1t^yf`NK|}~qgi}_4_ AL{g#)q"5J.w~ܲL✗G|>5&m Y9P[|OngUTKosAvmu 宄3D֯xHCU_Sq/b34ϩ~[) wLzj5Dʐ ] nKX/p=Yl-!5M}RFTm]dy^X:z+3&ܟ$~$ [o}BX\Nk"SdW'C]j$_rWj؞L$#aT*}`5%H(Upsz|'jqi:Xέ ^N[Ժ'X{!Vxƛjr&|x479uK,-S Ң:&A- D`hWy{,|ԞwvhRT!(O\K"}shtbn8Uy蝋'ˣ EꩉR ߦ)X[ᜬ`g# 4O"XTabP?4 ]\ˑУbTn{̓.{]QLG1<ԨhU+RZuW\DžߎaG^I91MNVKw.WP=ED+2@Spȫr v.2 :~Jڭ*׉U{xt  FEnIhGv[vLD&tm\:|HcYO&Ջj١N~]Sj?XUڮXplrӦ]N5fK`χ+vQU?{M!9"#UZhrVk u }К\A`?uO>G{Q51^p"=uCm-?0cß,=~`\)AeM7ۚG͂U0%+&=VQۛB n]fmMI Y*e ]?c3Of^,0\ .⷇ 'gAviׂc1EߨE"O14. ,@;)St;c/zNy( xvƥp._: `xC|--0iʖ;8?5Ueϑy P_0~,$ %QQ?c~}+Cp= 4!dge qj(,&ogQI5=vq>ASʔ;O|jȸ1 ,ӕBq|$MI0 Lţ7$ AwZ= >0E+`v(MZUkyd6n0f-<#q; $6' gmXkYpRE[nnD$Ty%kգܵ䰎YVHJU/ Ѻκ 7,T~ŗ#^lu5 T;{|SLmюm*.)ճmOtX剞 ?J{ Rv5ȹLQDn] ؐd8q">7P] ' #A$[ "bl.l%Z//ɒj) #Q&XcLĒWے1E7A;ݹU2-)հ_˱"c0_J~zv+iidͺz{֗ԟ<9-ir)an_{<4EAN#$.CGlg`r8th(-d\}j580ޘr)Ƶ㧛X̰-"%)r nYKX2~ϟWT.P1#}dg~ΫT2+0<^-wHUO.>F]jW}T2.5kg!6I7@ 7wxlk( +*66]~~YMWC ,ҹ1'm-h㴞 @Lu Vq]$}&&\hfpxgޝ]c?̺d%qŏ3ts(y"nXhmp"H%K>`]4˳c1%^ x&]}LU-]&6ǐQ[%[^,㴠rG_'W%*\,!&Q^[^c, Po5_Y;jV) E t?q(9xuH5+LMyyw']xxdp9਑xpU#").{?2>imk1oۑ8mo ǕJI%Hl^]%R`忑Z?+A ҃[Vw>zx̧ȜOfj^jhᶤWf8z[0 0P~<+ƎP4;8sLeqFwٵA:Kg{xSB ЗSΣke;L۶wRs?2I {`;)Yv|f+?T Ӓqz*:4]p\9֯zp*ENJw/Տق;oXVڎIş:AI\L\^znpp/I>Q!%tRw8LbSz`ߺc+1m "x pTqgB, =6Ov2[AJ}n\?C9+EgQ>OQ'h8 ${8 UvcJEBgnE=E*ȁ])F[=n݌<QQ߷_]tP;yc#Ir})C,6G8 SWf|bfYjK{F$%a"`+%Wur#fN%Mz!KbK%*G#yL;-d\]r\ª{,6 oE7f>:nZB4Stp .AwHk8zr $GZfjLw{#OGύOza@1/C.Lq=4fg1L0K&5OU;ʬ*/ :VD ^|gG~~Vy`E!CɃ4A3w2\ ?R|rvj0ۯOSdJ] YvVp*/`Mж+.+.Wg>Hf4 jR6j놲 ?;K00 [m@]iHpk2EKjE@c=%Ws%:&Z;g2FHyﴱs*a^ LZF2&,V 枸莹+xYF;a guyE/"iHkV.Lv|WH!OrOo,u$6j.ƪ9AVM_T1 Z}Thks+9I#zJP 3bW( bsǬpҶ~ʳ5$Iqqĉf{wWZTI7`t c(6(msѢR)o8 V"qINdp F"?W|$/ " 똘~Ŧ_+5coL-r}BBpT̸oמ/9`zY SZj)R; ._*=" 3hϭDևcq8ɶB[iIsޕ!*kgBm.|xtSL:fn@'-j ؄(HVhd=fTlu(CoI#%A"Q)b[_Jc_|Bg@lMU;c.i];m:7WA悛4TeW_e{y8~D߃"Șo:*?ax~XS&!? ZE0/,B H.g-O7)_:DY]Cy_&Gra^b.Vqj>!J# RY]GvX zx/Dw"a"a|mYU̴v?u7XuoO0.+g_m4Q b;c>F4v0vŦԋT[QT;)z ^Ys*rfl?_t/qD ߸k+ dE~'@K7!K29j Fј}͈2!7n*"ABԟ-ыԪІżd@I"zR'ѭnrVM.u,\n`%U,wCCۀ[M6Q" VKBԑ֛)̐Nr93$y; [:EūPӟRF ;"iň+ֲYJcUN(8|p\P=+vdŜPdZgY1%Rj-Î0>HS .m9G.Dfv'c,L*/ xMnDw)DaaJKnpO}Ro,.!^.֟l|1-5FwznWr+O9kB[k\3@Ieh^~9PR~SxNԙy#r[[z㻆{!x;-mVh$  e N1{BBʵ([K-p}9" 5 )M7澤dz< LW;EQ;Ri_,?;mkT+N͚'6v  u}/];=n({0E޼Yt&9Ĩv&G肵?\D ytuB&!_ 0pV3-_,~z)qK8d&@sFD5EI[{$q@i`wd-YI&,Vz'W|QH" @nvF/}ɻazA"nY(wjuԖ\>!/cJ2%Qb-T[΋6{7$q{SO՘M_R~HȁxZ<jal?![\\:b0<: v+DXȬïwAg+.-/R4О<;>W'иG 8h|4 aGkE>u?JuRl:_ #13 i[Kb^!`'g~G:r@\M>y"U2=:6V%X_Hf?+?M FFS-QAiR7(ρSW_c7* #ԽEdIY4+묙g8HJ|:>hgdT]Ztf+"'Jj D<\(AU/FR+@šS:F׸Ayj1#" 9Aam)gL*L4Lpti-35@KDiy\x-)TPQEq>QV:Nx,L ը;)H}›i̔_0]p_k$bV6 endstream endobj 183 0 obj << /Length1 727 /Length2 17552 /Length3 0 /Length 18125 /Filter /FlateDecode >> stream xlstf-t^o^=pmt!n6Hٽ7i"Uޜiirٌ&9x[\'o|ӂ4ˡpz GTa`jWos%Z#,c8{PInQt?tt)AB%Clz r'oYU/ H+\u^fz+/TLg V. % AX`Z<}{- B7%ybBXCHl=:/ bW^ٚ\?{ nUnVc8;hnDOφOaPaCVv8Y ۴'G3^gEڋ]{"J4VsbܠMaRèo7L2,T`AaXyF5F톀sl 4ZH11UbGveEX,JS9H.]SSA!"Uyw1%?#U-烛fa$&u|.ȏWH^ƧNOqpQ?)y{K6W>JϝFoW+Ɛ#|U208~:?cU8 RQzuOUt˙_'~u`- 9].D1t1m><Ѓp`SwuL dCx)x71cxhD(Rb+ێ?E{ovA_[s[8/$t,u-JǍN,8M۪f̛NnX#u8BM\i>L!Ԗ Lχ_4}QoKmtS&D05O@?Hx"_3!%ByB[);C4dep5H]ae!ۖ]ԧ/LVH/Ї|n&-9΢^|/^S- 4!PZ֬"yL YŁPu*w|J#Gf$,AyXeD!\"Pkݹ\dQD&.$ͤD\K zQ6b{4!'8,\5` c L|s\䧇#* Kat5PO眽 {ڙmy".cEy *oYտE! P 2_6Fi[~}ٖĊ\LUǥE;B~@dTZ/4^DŽSAr@ C; 6LCA!ȁ(B227,. mH$U jC\y\s;XqvG1GmCE̵]uӪ0N۩ЍĻ Rl^c8(M @UYA݆1# CpQOoEF+M޼ө[XQra*v 9b{8@E}C{Ҟ0[ 4BUy!KAb7T\P!bؘhˤlkgIʐEH0ܾg3N=Nc^ɫ6H:;+n/ci)Y A :a$dޗi$ Jz 2 kDg8z8R8ѳKFt=0)wJ(ɐw{5#n1OWJ?.D+e, 1xK,0*5I~F/CDRR ; r&\SJm%'b֦yٷL&Ih_<@r}8fL Qa+'bBqnt}MWb!qB"oNYA ,]SD>W#; 1i\y7mu4%~mmxdqhGBPE8!Z>a:o(Q4yNo݋\h:2rUmg {s!!)1oc0O\2x' cݻ =%Dҝh46˧ 2={M;׎c|yFĄL~AF;f!>.$Ow`_5yL-r)od <ē#5J_ݜ1Wvm6塸_~Xӽ_NBmTr#z,eYfc',Cy{Ыn>l"įMoAp>e8?^-0ϵu p*x N5IG'VEUzi]xQv3CEqJl!Iky!ŔCEX[m[he XM'0 j]q[8#}9. ' ߰3U;vܡkg)Ȗ1"QD*ado#}eOV, S䲕!KĢ6vIwxXؗ.dJwI-J#Op [;>4sn; FVIRO~&i,nBPCHAE쬐̬p [߇V2!{|ٲAp-DH%~y,>d_;=KevxK@Asnjb&Xb2/:E`{sⱶgyz&l]O{1V -mU$N -B5d.iLrɶ#wi _$Fm3o3@8 ߴquZ,?, _G4\ ~-$|ыŅr^O12XLgc捁G\ƇN?Q7=r$<~dk.ZaM8 >moEkRN GCpN5)E?pSp ~; ɶ>A?5sg`)[.˟ZyJug. c,M?AML_%Hb<!i8]< /`~ & Ȧ[48;ъ{mv LS\_]ҫ2Ӟ\R9VP_ء_{Dvm ,[ájSNPCv3yu- G0̋u<|&IO^?AW&iť5IcC~~L2[~x/ ky+*0qHb]4l F:z 7%7LP\_Ce3: ?5EgZfGgEЎJ[ƒO<RA6p)TwL״W;9$UZvӕ)GbByeU ڄ 4rqtZ[lYV'>Ji9L˖Ű-h# ! .K׍xМ5E{bIIt\dY1* Yi$_%PrJn\M q;=0ܪVP_&„\*Wo ȧ>16:#4?9XV~pq|2Τl-roe鯾 Y}, _$/c"\R_wMݸ;ig DXEcYV AP?6ܫ'?$HM #rRH)X0RuQ ]~)>g"Q5-V0+2K-L9A:Һ7sHA,A`GV%Sf%i-TT=¤̎Z(*[R0I's8JwlkdQpqD\>`5,dith;(\LܩJ2:MK,?]7 rŮ.-a [b&V"pc+`K$=q$~tƹ}3 rδƹV ls_m-+~c2Eɒ3@),7MsEomӷZysƍْܣ !3*bc3{Dcɿ;@jI펞v{*5l!"gPy,1H%*W >hWܓ.V)EU#maeڃU1f)P?$w9qMYD5,\꣚ bW{^.xREM; $-, #Ms)&R6gwąƥ/, 8;ʁ͵חQ D1 `AVB^"_AcGم"Dq|R[`'3}J)IHݟPh9j3OJYdg2o$0HLBгrHۍ!c~T}/RYcTF$pT],I)szG益kRPz͞Nm\` g-u7:T֤[9=|(E8}ΡyGEq#v-SKף11WTd<lR!6ScZ_8+uVrd'y@+RVS?t;L ܵ!SOyS4Tg\}LN}PYΐ$N5 `}L ύuUBB)jW>A-e k5C6K;F,YD?Š&S 0z q< %e-.- =2#_y mM7oyn8 nvKˊ|iZaR k?&#%5%[jՂjm=I+}< 깺* AG(Ou,;@*O}_׆oSʹ~dVTఽOʗx,2brm>M(Ʒ:W!޶[4ZO=Q`VSyzJ` 3-o-4r`c%X'24mO0۝ SC_[3vMu.wc}-=ro j٣Ugy(1t{`MYh%kUɏ6=fwOvcv8=wDm149aveuR (r8Mx %1Pw!@C.Wemcy>ze;y2dNt*y鞭LtQzRRV(b gHVaj G_;-,7SWoS^s,ehpJ9YsdmuJv6**Gh2ubGۀO8tX=,Ǫ)4:`޿n yd52~w`S xx)|n1P$;4~Uz53cԪ'{Ex÷~r}iأ(vck&(s#G&ƩTahd2ƅ TBb'*u"9Jxͽn fG,h}òyMt| umjR[ObsGZ<ㄢ2]xGLaCA3#W%Wȃ#JDv 7q\okywaeG)U|H>sN_ܹ-9M  Ԟn* GAz@]#)]}xJۈ?ٱ0gPkrIؖ?UcOJ3O_pCvb7%c! .xIKqnɴ;8_qSq^ql40| MiKZji!5P>y9js0SfY LڍM~tKH}hA >l"}"%)>,\IYYN4{TuC"ÿ_&E[@%WI+/7[sq|bbHڼE o@qPJ(]VtHYS0{w{}6Ppܹ뗪B'I!!l3n0 "^wfzFcAM3`YAM:GH5KQp[΂Le4bT6l_-RY.[Z3fyo}A;+>ۤ쁣~VND *9: kt99 cX 4匇ɻY+j=[in{,g`Vng\f4kd% \յ\䰲t6jd$q] r]D^>NLRkȹbh +F5NC fe{rBUŦd +qpYolHϯpN9<ڝl|[0#{klf7YsJ}dZxC0Fm9`JlE!wi!^5:m iv77 "c,GGZ>5<.]zDUk'1\:HI4`Ş=Oj5+4l ?̬~5b6KcA*;1󡣢yRYIIpգĎjOPĚSy"`GMQD20.9aL\Л^*Dߓ(婲B: +"16lrWnd½sT<Ī=}l[HqT +q$~Pn X9nDՑkP7 "^~Jt {oЛ^KɎ6zt+=%|5*KS'7kZ^5WPPs5bky5!c:%P;HVU!0*dK.;֒Ãb/!1z% @OMW"NU[S2Uk,Wb7z2sR׏@ R.~NUɹ<K=(1[x]b#E 1DI}P#4&1bzk- ;ǭ3_Sbfy,T dmH.oS >wnk?{!v({Z;Tj}L8^DwŰ찥q2ekzl* ׋?~q N,.$f`h)dtvfT2vnueH!S#2^𬰻35&paVNl|WH;*pj(@q2Y%MA'V<BYX2!ӝ2b/ a -sڽcڀt_8|96U-p]Kyb(,Ho_%A>o1ڥf;jt WxY,|;$6Ťʢ'Ne%YZө-^.ߌH$]Ռok\AJ]PHPoZrz`e'l}8Dj6$aì]6{òň/>@ҥC$S~+$X4"7]\fpk,|d?H2Jy -g[K';x%qgPS^$czL'i_mrQĠ{;a]Vi(Kn[5뻋DsH?sIJgx5 :u1'|E_ UUsz^S#G~Y!ʭU._jɄ$2b-o+{5tA_`VpՑFf]{Yjo&S*:aN)u#"5~R|_H?Dh?$^*Aoȡ2VTim@Hr1fr^ݎpW/ qDKJyCXO(Qin#l܄x,JY8j ӲTeˎYEo912K~=%;M|1tmH}R9 */ù֋G͟E$H᱇_3:"ž$ѹ(7+wAE%|*1dfq8!d2>l*n};6SQ/e[ވ*kizne|UZ1[]G-=n0+ds=ܗTÇMLA~q ݃@wmFˁ|&Gt!ey ^bQ@Z U)We~9w]d;,ᐟ3նi_}nL~G2u)ZdeɱnG >f~}5vqSZ*ӭa-I'{̱+Yt>o-IaHcc^AQ|NQ/7ڝc䷶-1 oO@un5%%-C B୽VkBJ[2 W{Q^.+'w8]]NS){4`̣9RFK Kx3~Nm4 Ttm>)0S܎q̂FR%ֱ4vOG) ݣ"tVШJB(6gm ]('FEi> tjaCOdw$ <*ױD*_S'jiĘϼ^|!7A+T(պ<eA"P޻vgOi Q\,(sQwQFő0|bOk}2A,2nrtn_?\qxY5_S r,)#KdE6HZhz[ oaxv\^eR[89H 7pѿ,Hm,9m\Xaz&L xaMᰑg/Ttۙ>rPQ{[ZAx_,%J bvۄT5{MZfUeE5)ecʷ79? స}S i*6tȅש_)*a\lR"yI%?21QXդCh! _IӲ,K4BbrN]ћ (W.CC$z4T $UXm^<>/a* ٸbPG^fh-ɲ صK:Q_0Hڏw> ͨa0 t]:{50T!;YKb?"[Xu ~+@2ۺ:ht+B>wu ~@.߁ag6n7M"!Q;ǒ'xjiq0.krj^e2;"F6rD31r8fD|< IY(@Nߋicn]Kx[DC5nL7AQj/NX9"垕R`l۲ "EX|/24opq ~=MSRmju*I[h]nf ܼrND,G]o 0 S>Gv6}U5لqۑOwU@'% ^,x P]!u 0^0'-$#xs;s eNǼN-]K}>N-;e~k?OIQNjZ;{">Z?J35ug6s.*uV=>X %HtѱڭAߌ_E[ C$s$!.ߴ &7FwrWQ^x$O[$lK/cX K.Yїv+:t$ "IThŝ+Rl~#) p#//gbK1gv0 aDKѨ6% qP54UvJ?ZvEPl'xqrtf,IgRt+q#yfm+ayF j >u}|DV4O`,z3t˲hf]E&WJAZX:s,Sw\oGEp]e}0Uab:kM(5mèO\OyuP*)hWi7xZvH!&ZB<&Z"4\R5)-u ",K3I1f>z/.ˎ B4V E>IKWa$٦0#W;wZfeȭCy!4YIbfψg,@_BܩJw!歭ú;~ nul@;A,/^#YF6M&=\C>s@ TX,f)F]ЖGӏhRlEd rZ&.u"]Π):ꖑf)zm#D$zěk>̑rc*$ѝ68-ڗ_CX3DxɶPX?d Syn0xlþQ~"V,$4tC8CR)b VKM9o1Y'>A_/l{Os2ٗ >_]f[QR#3y>`Q+Y<*p9WruҎ+ɔ)>Qr1PuGSk~*=P." 40&>릶2ݰiێ}mj}ְ] \݈/8ҧ0)*adRp%KƎ%iة*8dP<%3~EQl~5dʍk]Q+N .+iJV\y 2M4_$3z[l":Y,麴 O endstream endobj 185 0 obj << /Length1 727 /Length2 14855 /Length3 0 /Length 15438 /Filter /FlateDecode >> stream xmcpn]-vضm۶mɉKNҗ.i_61VB\hf~#{I/뵷Շ2sJ ,I8[Ǽ8/_Ɖ٩xEJY;(*ކ;&w'9x^ZbUxƭz ?J'Km@))9 {1b|p򹯸OuZ5x7O?9fޢ6l?Ө4:B^-lhn/iь+w0̓HФȡt0] ]?cdJƧ*C 8ATd T0lK cGYx )%(`: "m2NF?FVXQ %XYe|F2;!ʏFf:uT qN!᎔frdk ` ץf/jh2/nܝ0RguzMXD}NKM_zSNVo|?C8S?_4a@鈱RX3$Y4,~2C``=tҥ ,w{(oɷe·SM7;$~ &F:cm Q;K#!Ȍ^qƤ}Ry/;ņO#( bFޤN쑴 |_Y|e1!f*^Ɖ E5>j?ͦRYq*5{@c| 4a;G4$E/DPbEϔQ3 ,WX!N~A@=̭UӖN(RKJ³bB/@K0AMmoV,ŴwFR}{߂'f5azg? >=Et1 W-S0q [;O"pVB?WYsPdL93\<.٢R", Y*ynr*H_}L$y]4lIdri"Tdfܓ1(D-de#yqZZsܛ=j- KnWG7-q:D^h{a>\0[e[Tbps5~J2 L\ƙq,UAxÀSD,e8$7;TsmPP.h Qm/OG`4fv:nE(x X%+iW:X`Lꗵ^5:;7t`'f y4xO dʖrďgbWG<ԏ&ČrҞLimM;r >>0~VbTFqRB$:EU- u I(osz{8β8ah6~0u'!5/o'worx}[Ҫ\f㕆ު؇SRޔ fIF,qoc CᮒgEHlwH &|X<Ѭ\#=rdmr6*QH_0LwM?9HTЩ 6V46Wmj *=T>KoPNO]< z]` 4C6?p'pxnՑk)mf:1:ZgcXIÙ$=DMhKv}XN^mۅ;?NV jx$#DDL3{oAXpoO7I}!BrvnI,4pt*+ҋVRsv. &9Jhā,7|J޼ DDEaz_dxb aШ !!٪bnrp!9.FM󦃱d|_Փ?k^o]n?*{-7jƽl3W]n 'dDr|*@9+IfF{:fզ*>}VQMb"/k(܎8Jrb'~ei.I҂+96NMQR1<6(k5Byb*P<@GD0eڇ a=|nfu@jA{8k˨6UZm"SB6Ǚph=;mvAn)J$iGҒB\XD%6Ai&wGX{0~ecQ! %GԆcy'i;~- (*W3|X•[0E5bڅK\A@7IlqU|lVljcD#t38%G!ϐW'27Z'\K%,0iD摢iÅ/xDKE">Ƽ! Lƴ8Z8r2u EXyֱ-tE0ئAB6WP`8ur+:C؟:#?'qcWH{sBg4 Clt?CWkkqyFđ r_shx3 kJNOۭM ou:$*DS^b%bnS~1ՏJ Q={E )]&C/^-: j,HKf`%JpINj*h?/앫/Xi>ϧgbzd>x fAaG@Qyj^ ]yMbc$+dF(JwfʥVkYKDG8oQ#acmgjm?gZ ȯ%t<,ťx,;8Ge(ߪ_ /m c % e;?""lO ,&لb*|iZR@8?#\Osp?U;m5ڂiNDPRkkЄ E1AV\Tf Eˀ&>~oP" q* L߉}Ov{BK9@ ruG[:V-PV3;5 'gkN`_ܦbYܧO=!&97v׋Eម|P*4j{FWMt6?z!_qT ^| Wi!K| rdGhާ LU8 ߱_HdW/vHZ4}Yz$n5vօx; E)6줟$m #5ۏjE[lOEuAoFj2.Afvš LW0\WM8RȘ<7͂}4j¨r, S} JJHRA~Ӟ"445ƾQ\xNlULKlWy,wkF zľJ} ʠd0 9pK﨤x8!v}(*F@ԓ67 }F/ƽfa7QG!Y)bѶ`iӝy7#NƟASQXt' y>y^:rm|a QwPz L(8 ,&FܻE'OAa!.rL8#m5'^3L5(5ypݻ-FKp]:CfS'{ &aZ}锢w;6塀C$g*LY8XZa$d2Qt=Ѩ%\zw'Nx-c%R|u\|/)qN^CS,H /u!$^%c0j/}c-=;1!Iߎ睩w&$lg%jPX8$}(ޞadz$1{~skAS*cK$JXм{ ZR Jݫ=M+c0*Fgw;.H 6+Y9I*4O^:B~ԺguYUQP5Iy _gXw8?yO1Zūk+JO1^qzد0~;a;\TKkǠf53/9鬮Kߡ ]J=^'/&) )^]Zw.ceJGi3׈r_b aMhajzhg EUK-#4\L܀Ou2yR9gOarFR&@P|%i~~ՃU8bNLc̼ m`x=YsD,W Ԍk E,5p垸QG7RPKއTMgYi a=Jڅ<dJͪ}xcZ蹅hUstm B=د hI"|FkG@>MO@4PwkoV^`8#!;l)|a5m#/(p" #u!˨?F_ttso0Rcv~] A9e3*^/8 NFfaMi.Ü24Y/ H vs\q#6|@"C =`T<ͪ;$l|đwn~,禮-! oc7mг0H%AEqvjУx d*-}ȅ"Ʒ͜S{W*.F?F @R[So^/n!IxF'B;:tިxD ?xl6=?9Id_B&̿5Ew !;`{{{S-S36iˆS )6 o^S*W'0gզE:!KCM[a韷!`Nꆅ ;L/yyY":U+ӧ ƃ zP~b]'}R AGioIjf(+gGHBlX͠Ф[XrI5noy>Bh)} VTXsf5OWU DflUV`]1[+,TbHPxsX^QQG~+Jz|4\ky`꣨5g:k`/xLkO \W ;pu^gޜL[)\Ok%'?=k4D4sk®T3v "Ǥ!6%)mh4~^>=r>RJ-rӗVrg{~TA }.`k`d# 2wLw%U+Ă>ڤ …Ҭ8kXHX΁ѩ5{;-e%Y|!dp( vFMPF!7@9mFI^|Z]1{,b =CI`]^x p$ ]/IX ,{ppcܸZ2X|h$e~Q7nGs´.__ɱĬ[_X 6X#<n3#|i%'Sk` 24ŮyyP>chQJk! oN T< j U .ۆ$87OYm8&pw/+X6˽E犘u}5|>Po2oVCӢ-*[A*eswGP<[n}J¢P@?hwk[';!Eԍ &`&W$͜D+@5 =溏-3;5ݨGmz q\V75p`1m+*\[6-xs龒][҅Vda2@gU7Z$ic?otBs4`IL m֠| x1OկȪA+ 5KcEb2dge^}*p^+RNj9U?D HoZ{. T`7}|Uc&W+~+OE%D4;&@a`6=QKؤb)%2' ˘#l0`ltl(,])hD$W^eԳunaYp]iRNBRJnB8ޙx SD:ŁVwG2*߳ zBÛX3d'"CT2K^K d[[!_vEI' xТUZidkvPBvtXT33追uKvpW'9;ik9e(à8* c[G;JJI$KQQkHT9N3f=oYDNvrbS6x叩8.3DcZ ֆ 8wŅAJ 蝦22L5Q/$Lh~*2nxQ!y ( 9oPzhJe*B*AmrPWMߘQ &2G}fZ6K; _JEitG [ZLr>C$sk.J Kt'L 3Qj;!_uk/E]Ezl!ڽyTvD!Rb닢3}JSVx~R_crP)t_P17XS} }zʳOډ{20[%i]ZY8`!yBY3wbț9~R{aUdkt:ZHea@uvfu FhUp:knN=zdYԳO4<p]|ȐRI/8 u5H520o=@1:Ҥ+(&{ ^,{Vz;mjϕ-BPGޘv )Ef?;hY4ZQ.Y<=ח9X7%3w'wx=5k! 1Xv3oN|+N2Rótɐ:|D/u T };N\a-N\oH*}ڝmͳ2^:7{A&#Jl뤸,]OYDVr'I_pb@UOra v;R'T dNGق2%X#&nx|T 5IXӰPj 7X4GkLg͠iޒ1߬om=6ztE, G]9vPe婚,;I@|~j,~XH~f?I`$J"X Bsg]#; jzźb`koZr?nQi~1AT4A(Epzn>T4['d~b~NwQ7]pȱ-j*W8@Sak3 bY0BYEMKR(7']SHYba&ź|9z9%Է#E[Ҷ,-^|@^ʓ|>:'pϧ1 \keLObTj$":T : Sج^i&.e:]m{)3f}D<>hbx%\`l Dr[92y-UƩ_r.阋Dz4d!HX:.,fq` !ڏ^VӇp{dEުyv?L?2_<~Ma[k}E:3$_\(Tin#ߑi*Dx\saXf?<Էs?[{N-vᛏ8G`Rxu~[GGP :3]OcRY6|Stcv$snPTL,rΓ,G}?qxK^NN2%LJm[ŻX`S"Qq,j[;1KQXr7Tƕc,q|Z[0 XOf#tLL XoǷ!a[(j񎄄fJpjG.vGVT-c/曮%kʇ-+=s9nI`| UpU4tH+P<~W;Eg 7+iژQmDŽsd['k#T-—Ӵ_I粻 ;Y\ќNI 0W4AftJVAq[#dYk(܏)vߟkrw?Ήj:DqAш%811:.[0zShI7l,`~ ΥD} 0yy<HdH".+P{_]c`d3M==?R$>a]TfD#t䧗 Aۿ.і'hq,3p$D\o@9 9걬UVeγ8C03b{ endstream endobj 187 0 obj << /Length1 736 /Length2 17873 /Length3 0 /Length 18485 /Filter /FlateDecode >> stream xlycpnmlgǶm۶'m۶ضmɎswU֟sתYȈ\T=LtL܄*RL\l,0dd"N#K{;Q#7P@LCF(bdinBHiBoP҉PĂMٕɕ"@hfi QPԒ W#l]m,Me-Mv*B3{'B8&vLovn'9ʉ +ȫ0ٙJSnO6_ײ1e_Q'X0LL&.sK;&egfOBr!?Rv7R:MNv_?MOf']XY[:[zL-]XsZg ?s¦v6w Jj24LM- U\ÊF&B]>rF.N:=co7 ! ;#! ;;!' `oi0X7 JV'V<_N3?kF6{l9lajp|]7h̷'Jl35CZJReWTek"vyH=͚wQ'X·,cX9d'AG 8E-1x= /އ%2( t8.l-Oðm 4gSZ]V8IUi\#ZyAu!Tvkq lp^1N. z-q%Hn;L be~u? Bݰ%AuCX`JCXWĬOz3 ,ʹ.Q;\N]sD`6emIsj\^uEw(Hfw>wPF}Uz&2v 鄕FṿY Ǘ PA Z~p\TOrޒmpSFc.=}M,9Ff#}gM⠨C [ZNcq!%1ke " M e&cyy;eh'hʢ|Y; ݚj?qM/N'gHA>V&1W&SVB/J$@U.l.oX;c~z.*>veWAW}hj05ǡٯz=o0<.p+SNPXOȝ %ptw2uqE䞸 7gD3dp:3蜟1xXKBK7(P?+U7Wo!7!}"x8#P6~}7q)G{|ɉzlI!Ql`^nAhKjdVt衺o[-5t1KqEiwk记"\~-GtyE:$m#IPJ x֥%J#OxgQC9I~3Bwӭ/ciSˌk9VpYy;|Mp%A4 ~$[b0gu{Qv0՜ cH"֎۳i n>)x&u/L:0Qý% 0d'Ă=H<}r* #Pޫԉ.X,mO_u s@)Q_GqdY8 ^"emש8Zc00X&.IͣB(b8|II6*We (sAPo\.#RD_D&ݛ{|b'sӽCg*|]2U*/i?͠z i$Ή-0 h{Kn(#5xpmಓ((h@y4Vd7Y{\J͏/"b"J]գW: " +bߌZ,{u 4.N#z@EO&Yp>\v'GT?U;s#ӄx&Ap0]Ll2r(2tc_Vw&baro/}`W0߿9IFU+>n3FCD3}L5˚W;~[fK3sq;L:75v5\"4z#AUy,dXٸP36ǧZ^yF8G=3_Ը{+wP{l2 9cB^2ǘ@ʙ+:@<"GCciR4cs|Gjo%ޏMN~uC*71ȉo*<33޻݌]Pصd<{k:FL-vA8=25,t7hY+)np&^7L2"lSie|d^voKzFl9#ڹ^*5[уcfXrmy)\k7#Xn|:!hψHrQV2{ESZן3~Dt 7?_kY_5{8$NYޔ_VUGFDLcλ>}˄EI瑠~P,ߔoNGk4f1<%ROCy) ֚qBfA̙u-c0 Nad̡Ĭ:GL5P-}b)*\tNmrwB(@,N@@\[&ori0>Sף]|~5mTu+%3ڣ8MyO𡾿dMfb՝wunlWtK f+('OUD^:1[Tљ3̶y"̓!HSes 8{vE-”;;s'2Xz}@?-4}71r\ـ:M&찧EHx |=>|l1,P(sS=tZ:s}8cyLġR ܥ|wy(|xU\ol`quCwk)cͥ~8h2bft!Bw@OIGBfws5PBPt) DT 3Eh՟|g5 _m J}4^~#ɧf>86d.߭}1f)``5T{8,jK߅OW%'TU}݀]fMjfb GCpcn#XԞ3>X ^Syy[[r⠒ $ЛB*b eVU9-p=Bwj?Y=D)(@N_T%q7%5Cu"E'i#B|?^Zc٤/X;I K}ZPR"Kzޝ0x0 tU_ #?WlycClˈr/# I"P[ګy s(8Le^2k1  R04BC, ,qO"j?mE VZl0V0mŌT^/TڕYf; rRhbX9Hbl@/C,fhR#;rZl RUh^Ϗc^[9VX,͊/`o`G8RCFoE7)nThQe TgcJ}X+W<^fA8i[AVY&F;>f̭<(j'Cxo% m~QTh$hϳvrz@Eՙ7ځ#JٲP8ʷɂLGgҥKP'G jp?|u/n*ӮN c\T@|90i^z2b%b_kD~ Y>7j\^?y N.K Z9ޢ0Ч[Y_07NBUrLx5e3Yɢѝ) :`%$]Ωm!=)\8umb!=YA~%3M}ZλY:qlgSi~鴿\(6EZjMfi/,IoqiYJ&I&-Qo|\:U*@kJg4v 2C ȑs.iޜÞN)~5g+[2S t%^o7(} WBZwhg3Q#?Ѿ ~Dorgqڣi^Y*UGOa\}؝sНԛ)jNW J #m b E+%(c}tts" k!Ny4,3sTEy!%pJ+RKobo!g**Kc茼-Ԩ޹E2Yc/ZF*;+nEx؄h&}i:1b)ӣ86Q=Gn{B* (b^#uQRٻ7CH{/Z(ScރTD{wKu @l/& JQ\Z( pV'_\:n&< OXYEvuG9G3I$pxz]7cQd,t[53f-X{v~|i;`2F;a+5&dNO5,~jfҥ#7xk\8f .1=Ql>90O0#!c's"? Lny~aݘrEF1@ 1F28[_\E,xHw&Qi)ބ5U*J+j 7Esy9ׯ,էO#E#?1_ t2O.Qsn( 6CWa*-={FtvL .Mc3mdLBYm$۴ֱ7Z2:M/Ta:s)n 3~OOl֪>s,,,zlлq b B2@˘K=ğx{` M&f\Ty&tڄu^Zz Cf^(7pXmBACk b! Q2t2y)u2qsTMMo-k5#kW _¡χXKE|L6B刄oɗ?9cg]/욲Ծ3o?g/ضɼTCl;K/ rOU':V҈E·bL4{8YIXu H7Dzsdr#RzӝSU0o!x-Ⱥjy¥'hڛ1 εgV Y5] !-%îc)h6GfBBHf_Y_Wtvwu!=T̺x1bcڀ 6rpo,! 7j6rVfg҅r#]w.YstlLQ3 %`Pfl(2ae/vT Ĕل<>`5sf `vD:vxLVrG Bר^'p:,H76PW0^tjp~cN)53 u=+[f%<88AXV)DmɶEZc*ff}!v{|̡p+YN!Ln$ R:Y3uLϻftR /gkNp?౑؟G95CL#dt@f%KU OWa}W(fG^XB,\@,4ܯt='ND G%oĻwzebqEQ9MxA^4"t4_ʒ_P鉈A*wVSk-3[-\aON ‘ײh; >]w :Ү%M [YVp Sm_T>=?n]x#"y҉y`/ nC k6UUr@ZFHWVNiGn_1l&yO(h^uxÎ ;C'uo"E|}?akr m),j?svn^~f w?b*FᗔŖ-Eh~/jT߶Z *"gyB";\=ϟn$ fpf *3HƬq#\GMxdY!Qt le;[&{b. 2uP6J*Ri&t Y3XQXNfrWg]/IoU,cCYMtpL27^:)UL rD80Jv0fT4Xӗ1_wU j}!P񿂬hL`_ނXO׎h(*'PJH&:Ϲwq%]8]Ǚgy Éx]a:نdtVcA2*&ҳzZ0*6$OLL{A+]vtH 񆔡hKrǜKtʻiZԾh&lN2&q][lZsP5yNpʽB%H"cSŽ0$^~8ֳ$t*zAF9y2lw{{zԳiWѴ-/;e>|ە@n+a_J])08$/ Y|ɦA): ̍J떼Xvfm|/)Iq01+7~!KdH}ҔH  fq%<Йr_WͬnPS|V+ZY|(NNlpPS,=d-e"#) nEI4_|#uJDӀI Im99ڜS܍#CjY+tg(2s$5ukN%WH~&\K1cҁ0k+*`8GJt*dyx #g~Gmbp{J5鍷2mq&]2n_hgv(̿d/Ql-_ >O;?b#r"eȏq.TDR ~xl]rdVhW`iл}lMP@+i91Q/[{Wx`к9=]c=o[!2;Eʔ jS<5I!0YYjػAxtԒV2=f{AI%eISԞВ.;'O|ݔy~&qN}~+4?}էԲmO߯k>uZ|Z kBe|c [) -ZfF!@tu<¥G  MOo߬ Pxf e;/#o蔐n`SqJKFs2U6jp̬qbuC%LeO%1fg)[6g߉` 댗fx.,#E^5(`+_QCyDso|:.lt.W~ .[boS)QtAE~>֬"70o}^vzot3&lADc[blehoźl07T{qd8ao#Lc)_:c?ZD4pAA'*$H+`>ԜY7ު+㴨*9&y"H.gl+ҘK^f,o1X6vx&y7 )o_+ 3(z8K|~F&vwon`MP)tSVmP>e[Z;5ЌfxV)a=K {SJϞbc1C3n,d4TWBbX\>, 7Gk(p(`< oimhdįJ9׫g0n|Js/h&$&Xjg/o(gsCtjb1MSh5&;" Tg\D^q}^,"UE!wb;4/ ֌rr'BVl4HLĵa3zdG*Õ*  H^`uRͩ Ac#MWmU%Saz>m%mkE`N09t$>XRq-hm%I f1 ǃROJ7G?$ea1HbNnq` eOWW0XQz~8[9̈cb\L0Qӿo/*| #/vϰ@ajI]6}\kU8Na88MClbʋzu,!?&ayFoW=$_a\ARZm@аNƐF7UɅ6*= g]Z|/:K|hF P0@1h=={|3*Բn-gÌ^MXjB&Q#IӦR{LgMpSsdܶtFU^SfN+Ɛ6$ឥFrO)m,1{sgA]pU]sc(DI +`oz.̪*,OO|qac؆e!qT= ĉh S\i5;}{{3_F?qĉEXZ1iEWnY'vޏJ};>RdibWl ڷWk7j(nOCvg Cփm^C]PQ+Ht;62L9xGcJSDK*K>>t.#Es7"4 q_s0Q(y$A+hUV\ #rt)XD pAؐjޢ.y}.t]B!ѵ:5*q &*+_<$ѿII0ms儦0"U|;Vy>KDI(@|-I q1D-W6GA\维k)=0 yyϏEj'#Rmsd>% MTz=# vbeQئ#ѣ ْE)/[rM'4}u 7BixBo1drbv^o6{-S`S–WAqTb%H8j| HEEwtC3uO9qDl53$?|^wGu{,Btl*Bh)bꂲ*L)>[58O?C$Ҩգh* j]g_Z jkvV}>@Pg֟e_w5Jp2GNYRhN#ÚrG&aLҹLxuᙾhq`"{%xI/1Ƥ/NsIJ̅'GI^J暑 ܽ/6?{AߕS9:ßh)|jivկT 8gKqZZY|O܈fC`Zq6a>O׫W?uN:עt>^8+_f#U|BU RZS^'F_AqH%g-,}T$eT1z>J -OW;,EbYGs2L ceKGaPiɾJӠ03m;pfMx/LQ/(^!OXy+L[+S h(ɩAf{"γs95g 1ֻ;/?/%yvA[DE&lF닑cdJm-47 ސ}ai>-!r"tjW!z >'o.ķIj1΅qxu_a~XOUÌp,oK;MI0Ճ'n¯NþlJ4gtغ+bP.,x>ݘaY~!P˷ ϲE._`*:G#W+WN#R@~ >DE~[i!ŅԒNӋ;`o$BIA**ʘ*glƱ*YI1֨P&tZ)傴BV| CI{r]*qnBּ qH-M˙s.ژIC8t$D 1cdg'X*}bPZ!U&C%,[ + /@B,祕Dyr@d5M݄5zJw㺡($U!jabX?htsʣ(vY?Ҧ3{9C ͿVxqb/sQCF21(e'|`𥝛Swq~wܦĩػXm_d I,u!FFm/cPGJ!86GGS m]*fgʡ<V _TV:m΁[JX_z'mci'[AMjTfY~V 2dV9ƢW7z_فg7#$`WLD,:iqfKɻcU0'=R_to]IsZ?y%!&f#J2SLun\K1`/qP*V[K|&SH~qr̶snsU fU/PMblD)Y7&㊠XNBQMw3 `=fog&9jQE^ή^Z)mv4 -uU g[4d΃Q0yg &F±>'lٷD:R= j9?^ f(Y,ï ӜΣaSqW!tKMTXOȇs8e1 ?[v[. (ƥӓ'/ggdԬ?vY nQM{(ƪf<~noeZiV!B`֐m4nyܖ+#%?V6 z:1@+z+/k@>2ZSaa5LL&u-c Đ<[R4@b@FC ô/ӮAF/qR\^[j e3\sҊZ/QA7/<אLϮhp&׏͟D͸:(\62J(m7m;]M/x]GĠX~Fk`-*6?v#G;!'kWVBL@$X!ʎ)5Z"=q |ZEmܚd{9X尋8z ܹ:f 9z=Oo+T3V[ҍd$X:Ssů¢b=Cʄd([ζ*]d4'xƢ=@:q :{Ez||XPsS9z|/9Gj@g {lg P'9I0r3=0Z!ͩn t@lԐ2̚>‡<:TI/'c?qNGϯ8x~;3'Iְ#pس#V{-wU/:#ЙUweç$L3l ZӀ4M 60Ro3>TSf5 02o s7T6tptΎ0} ὕic#ݡ0=OZ$UE{{hW)ܮEGYO31sވ][9kZ fR!q#ot*!ͻ띭槓o""r?r_iVzeN*Jva£Bɍ841>ئ/WU&afldzcLZNd&?VM[j֣g!M5% Wl^-[*<5ZQ6!ld?C"t%HJdDrBpo><`}U9I?BvqHT ~1QfV w iګ}![c&LH1j$njv]8w Ď\'|0ă\]}RlAoݏ0#66|;ӷڷ@+tT[(pf,|9ͳ[4*QˆT.+i2+s/Ipd X;Hl97 21;-~9@wy/E¾ s8 y[.JZY䮮s> tz(;2l c;}ldNXSꛉ- h-?peS\[.YO$V!Pt^ >z2 }pQPKșq5L 1f}܅KkZz` H1ٝ B;_@(`4dV^?]kE%z5%,߀]*i|{0펯!!_QF#K{#^$nh+HFNQIT5_҄| Xz38 =""{WkB-Ӽ_)^DY@o L&a=95.Yʓ`"av}Ѱ"gxqo$@; [$qHqO(r)~E&2Wm^Jc\c=Z |GL[-IJA+xWBO1g*M-]ҙ r%š40M <_?Q}g-!?ۘ[nrHH)FDӸ*>;2!u"&ر˾BoNίwTVC|wF;SAG4YQ S~zP(VB(}*KAW9ո%`Nr4.wjzWa7 o0q+Ybz5bVG7.}4_b7BoR\k zRgW0?:lKe@ѲEF d!i{떾TΘrM ^!FA;[ϙ -`f`:zQ>ǼhH;R(vYC܉@IE<>޸bKaw<1ƓY?c4H%uܶP\e8''I+֨vNEd'+s8[%/KvXa(I Kw;փXNB>= ~jh=5zWQ-^ۇ2 xb>Sf KJ*8j  6jyJT+$GVIfsn).Qȴm6|T ppz R>Wm'fyǐ#Cl=m*kfCsTzY*jC|]םzz&W6x59б5`XT ،Bs endstream endobj 189 0 obj << /Length1 721 /Length2 28518 /Length3 0 /Length 29114 /Filter /FlateDecode >> stream xlcfM-\m۶mzʶmmWuٶlu;3wƍX;r;8IN,``gf`!RPgff'bb`!'uZ9؋x4fDG"f"&&fr"QG/g+ KW"*S4lͬ쬜4lܭL-݅])R\-DV"QE%miI"*Iu"I=ؖHʔH`&2wp&Cd`of/N. &`pv((?.<vꎎ,Y:{baf&22u%2XX0K7i{s"?ѐ `V@D%` p&w088elge?iWtG9\$<fJVHmnlDk/3+75s?KƿdTSVR;-no`feoAf ;dl/N]CpF 7ΈzEZ(&vdqn|"W1ӧJ[;ze]nBL($b`u 't\r.+Ȍw#'f6)0g3dt,--]SF@wCO܆R@z+K+y0Ƙ_W^>쎽g0G2(/K*@=XROىz-iϟ~&p97WEw0='0<7xy^BkMw&\^Eu^!4LI`&u)k2X36.ߴ3sEq˃?d',flD6>A|v.?Z@(ҚM)ng%gy[lwJ6ϰV66 C>WSWka`FqH o=}jMH&ψu@c.:s1 >(2 [-דL~ROC4-ou9Y$e'=SYoF?{#hFR*Lr BmV5""<+B<_͐DPA!_d<>cnN|Fzǡ{sXW+K <2!AB S?0彯]7vK; $)Xd ]o;e``ENA&řjnO 9[+2}#Jb%|_,,GR=o;dJyv4(G))qTH~JbMh#զ@wJ_FDj 'y0/C " O3~o*)X:[w1n1 !&y6n̵ǯp48rHLׄb{MFWN LDz$@:@b-]$xVؐ8/|k3b3Ksc,ocKvK'YÊ/Lu+jGׯJ8#Ěz g`ix|G>h`/H F'3cxڞ$e0wنjPM%SODӮ+O NjDy'Yw:Ztl$S#- =aHДܨs .?$EjLمXZޠ-/a8 |ݝeMᐩBJ>XGFyOe_[HE Cv֬`ȹ1tNiy߲)*㳏W  n.N0]d ^&G5+^YiucMRC4K'=)i"2 Iљtz_Aߣ)P3EKCQ>EmR- 7 jةֵPC2vGPAK4*>MuK[PB@=CLw]hC:B\|Z7=IӲL.>l"{q7I;YJ}NECL`~yco++n6ιJpls rio6*<&".쉱Luk _Lk^oRfB27j'MH)4 Жo "Nk0y3Iƿ1|g+`RQ Hi@RBc{[ӍF񴉙g[dBmdt< RIc faMb;~ ՔIQaJdXaW:-IͶ}lش'WW=pOr"x#07~;?@.;d4qaEpDT& pm G\Ir;*bhV0;Fd󉗹M}i&{iޡ !y>v(> DDP$p@r5L$Ԙm0Ϻ HB K}%~U\G"/Ȍ5 v5 ٣2`DZ;/o8uG]i$fKIk,UQi)_Dڞg]HJ|̧W"?_nWmpR)u]X9:{XHߣs3Ͳ) 9ڳCcrqpTGPl;+J"y+ypUc! Œ]*>~p\>$qK\\,>Ӝ/57=!qX H]ۋL7WZdcY% 8yϤ< z=[gJw,0JO6fRkre[5t.5&,R{bcK☍BW+ V5~f~ -b,iUF^˖1 \ 7)`lC't - Ad>ҹqoN|b|;a {h֣=`tšjIIo{;|Q` t$#,ˈ9 :am&` o?UFGм \J8sd&zi^̹WAY P"1Ѥx)/ɁXH;–)J|VW@#Zh/u)X֕ʻ 'HOx%AO p`wd/VT7JAJ+ߵdGǿsלpU ;| b"HR+k7c>h?=2ƃ}QgyFn ,T{ʭ횖KFpKl;0 [/_wiS%$[nQ a4΀5I)apB7f rb3S$6>h}c=;cZm>{71M6'?9zh_0zCK|~`zw!Ǽ1 Q]/O~\s6XOSr6bH@Z1S۸þNGrSb|ʇKx9L]('gr^MCqAԈ!PM.@m{%S$?8 RpRJ~ڑG~^[M(X9b':mUI]S _eptЇf,k '΁ +=qS7ވ%_,E΁pڌ whϡcINn#şrV7&&p\0ciZ\of/fE螌 d {)s%=a;_)xí-e ۣ7ٟgI3B – tj|>RІ^0 Cg39~wlmSb,t嗅Li?Ttyҝ6VG!_ w`m -{ή^<׾Abx^z)YK2 ^զù2`*{ qMNN-d/~_g" ΫFgJ ƌpktkD1)RJ|qyQC*@AA%| .t $ ˦ N/ Z2qjhz寫ѻ]?03Dǣۛgco"t\}q X۩[ &Xy7*tbil>nWaXkh)9b!HVL:~[hM^=w~7y`{J@ H31k${{8ׅ{u  䡽qDut|[}'@7ZL,mi*ԅsr֮n"Tޝƙ`>rwZ~Q)ٛp_6DF5n H-DzLk+fk+ zP&p@ǖJ|9F#WExX2X&` gl -K̺jM43lGO.<Ng-;kX&vZܥQ#Ct<50kJ>Ы_1QeZkڲi~;O,I =ooG`F>>f"h"?18_3B~QC)>,yG "$B-'5/SuکW(}J) mߵ:E+:Y*?+(sc;1LQ; { 1@A&k;o~`A9&R`}="e!K2ecVEuڑѐ7p]XY.| _f=ہKZg[iPPcnR#Eቂnhȿ;?i7RI55 j#zLW-^fq1I2Z3iLt%}~n[4 P>Ib:/~ qXh[GN%VFK^A)6fT}?GJsTt1T[eIT n1vr+'#֌t܉:OΝ"ea,kk:רq'0^ymnҘX$, C:C]-}+R'/pH6 k=k=/x;pY*j}2Ѭrm:q &&~g p#-w@2š#N r2 #H00*Fk^wܻV#9l۠!5dJ|Fo ,V#?kB"t9ʰ% u/m86ݶ,qg〫Q ]Ր { ?PQYN2p;(ړ&Hj}ͽ:#2>_E)NRD|~!yR=]^1dmޗIl>+wz[s6m7zT0XgZR B rCʸ!cC(3hmF){Br!=7_$ڑ|6)yLXt\,)3M^swl Lr\m=M~R~ -;QWN˵ߠSx{#Na3M|r>5 ͒N'66AKw}2b+ti\N$J1 `YLE`J"+(l{ {$ T[HhDfA'-V.a29٪Qr`}{ Lj=Myr7_VַypIοNـl>} *p"@0f*L<'"_)SeJioHr xcDw)C* j?uM?Cv|Ðؚ``9ݹ5 ;<#a rK]Gm X[%.&3 EJ" Tp:l~W;!'LG1ñBgps+Za*/$/M[gL5 @fx@D u*L:w)gƅ}e2o$_h#.,5 6gp!LɀgdG"ЁcJp bZb V2hxq"R]}8.Xt6J,tatb8V&aTp"o#bN㙟2S)&>V6\D&~I ,9Tv_6)$ey)Ƭ˴PIohzRSC&Syc󨝡 13B 6%Ci ΆUi˃0zL튆QkjQsx  ROw+47`8čؖ9$K`ɱ'c0 UOd2k|Bi`tVEۉ5_^>C;E: ]Šx)}@4&նdTwruVøzȔ!mȳ6|l Q(Jnv,Q\lۦR/k ;n!9|4!^DFۤ !p|6^퐴r3!Ph V9hP]xLp Ubg)rгP򣤅#>ED2.Ֆ(3֫gcd[őXgo+rUQhOFtC+PHm(Mqʤ" 4[须+iQ~'6G܂^{FdJp0)I+:SDAQʴZu9~>L}Ć]lͤRȦ% /1E|Zdk2ޠφP '8kkRVwۻR;i>u,2â2v؅zzBJǒ,þ7v/:vfvy@oZй~q۟2lm4mX2:i}-)k5n*Pa95t `bf/'*:O(oolY6T6ܔYTl"7u#Zbho!NHc_=03fnJH>h⹧aO[]%r݆:nDs!%7-.OK(|gD4Rr9F8fEYA: X _'Xk3En,T@逯;UGD|yr5Ozhmkڡ*0DEⱋ _J56wv8zn5`v2*SRgA+0Q ے9P9lt%}_pݢ /!? Av,ž`jIO0 ä8BCrf9Qv\̽B۴{Rȕb۷dT' F,4fAd2xSۮ{*'IFvWy2:'qi7nVoށA`W{GW9T,LlAԇy“ t#]d;A4t]H5ˊUͅ06n[@mK~s߰r‰T^F)id/r' [xE ƁA G:{ T3p}ݮ}߂k1幊 QYD.W P%Ƌ+8c9;qYeLe7M[ xh#"PFD !$I"fYvYŽC42l`f0uɳ1Bu B$BMm#J" 7MW-섶+xo0i/DmeCKR=b5eV<\59|]9rH-bfNʩ֫-b!]QÆhR >,pd)~lcy@%Vey,f˼Y!˄X d9\`ݣkJ4AG#Kunoq? aijm6 :/Iio7BǤ*otםINLެ"tlt, !.:Yo$V]m|M rTx˄M9Iu5U gۋ#Q<<Y^x~SW$%w&DD|S{;nmMEuYZmom"\yoKyGРhM3wl؆qufzNQ%PCu0I-*ԊP%Aazwn/ %pq׵5Ĺ4V-81@YtID_j_t};0 =i;incǘ{dOw$&@|L\Nj,䔋)cSrZ&13IW3'NSFʓ ǍVj+> 5wr>:*2Z gKx Afx#uL/:8= ` Y%RKʤ&FoƈV n'L4hnP18oq71!`}jƪ`Eq[gm/.k+l [˗tD[S4N0xZܼ3wloJPlШ6Y:7զUR` wjt0|OW| tZPX4_+zXDELM\EVcz1ѷ\3bbbp:a\ݺj^#:$vvОR1m78ldžDAMX+]||)?F)O7L#-Y߳شc|Ѣll TRIq½LHȗ:Cfm 86 I7@1TOIVv/^]%`yr̭"]W D?Ķ;abyg"+=,.7~e)EW䋲8B2 L8l%':T3M#&3s* }JTX!V凁l B6k駰a΅HY)j8 kw*܀zRNeߍb%< B($Ex?t$ +sM rOjRyΡhzd NicwK,/`#ୂ@E"ez3ځIunc0l{V_M +,㤮LO!nrf}0C  yϙ-T#VD!f{%^B 3w_!r$2"pRyW}J/ q `ӤYo bjfop򛥓F}q"LB66AYx{|F4p|5:j9'S35!L-Bl'~Pb640VJOTlyO. ]RA)z>1XS.[vi*NӮM4]*PNnYni!'A@)}ک !]07%}p]ӝUUwz#3j~@r 9]B`[3U:b\%.9ݗ|/7 lp]VNh&m؜-IymV VdUQviߨ#&[b ?/Ea3gyjt7\bhY@0QDSAZYjWOכpۮk7]'k{`}Vu֨f{ IQHu\ NPM )NC^  _w3G`^|IK$ڪPL84.)Z ) J- T$삹MՒ̜V|<":O% il иH@vG*4:2F:¯s6Pr8/<5}fƋySVߐ"-C^-aEQ={'m#Ⱦ(" ^a k3(TRxػ2s1!Z $?٫S!{$dʟmi 7WUI{xO1QjO*`o*e &Hrs'mDe-wmCXet?qܼ~o/-^frELd' f΀.!iP< 2Ա|p"F_[@A11|eڱMYӎoE!'atq5`-o: I΃FO1cT4  E<鯍 ַY/f`&O6ܓ`@}:A^pz2qI<9*&1o@zIk-[uIfƃv+{ӋYoқY+~;IOAnS꾮by'\E+-6mjʍT>x}=y‰\φpPt.>Ym=I5Y⠨(#nn9Z4%3YF$gӸHyl󲺄H9Kg4 I4}j(" / ;۬"i䱾 gA]y,QpRV1`^Ҙ2P*'RāW^JN] B|я x̶e~ QU{eL3G? >a :d/Ծ>YB_+-dsf7`t@ `PVsL`ixl2G81թ!9`[Nж97&qI@ƑuNAJbD3xAs*ɽ r'gtRDib!W?h:"O2+ RD07iqhnI TilKYw|Pa)=+H @ŽQrV|L\s+h`V/`*̂ܰǃÁn@55q'UDHǎ.a O!xr4 QOʙjt)ay zoUN9o1AD2K@u8YFO|@@q/*fa%; Aɛ71Hkh+P=I?9ie ,:rp,Wv~ Lfwٓ"4dY|n 6#RZÚo&V Pײ<}4HeZҺUS;wytTTN};IB6V1`+,&i7e'{qxlL%ǧ;ī](l=mQUYZ`!lA.5R|oS/aH >,Pc.>PU$y gy:jaG;bE&'崜A-N2)]ÐAVQF Hre%17*3?'\'NrJ\p} /\t kؕلG9slR",$aL#|Ww{*QNK2ydˡg]q|+%]I0@a^Oֈ  ]Jm?ʏoTd  +-FHEK7f+ssGOP+&p3h0ou9]]nw}qS[[_j"arཪ.+>ܯ$5Uulܿ_in{,A-58N׎ڶsN9S:nHM>yDT_^]ye(ղm{pݴ;lT#@k'3<LZnW hD@MkE1ZZ%M:Bևc6d8iED `i4nwH_5[Km/WRs=Et&JȆijm_k]^zp;h1y2̄ d=9e134kKT|%' N+B`gp-QvجM"+rp#xM^!&&{ڹS<&A ,\0a(ej$6Lz8qCsݖx3 ybl3L^^F^W߁0o+t\Rn1,^N t$-YO=Zm=m `h"k[a%{‚4#̗~ kB) >kMX4 &W5#mkc)B*Z+yDi=6oPB{݇Vb8\<%-j[ƬSycEb` OY 1{gSV%n?v1mQOMt3M-^}uVrg%?8A/*YR/"4wrr Wx_DQ@6{';|.{d .̻Xga1X ^IxOVղyB M_a6J8ՅbVma~'<$>rXZM8;+J.H|V6A5M-ƞ@[9ω%\~p~25 J R¿ff5SUvDJ)Z nIYY)S՞зD p@Rr/,=,Lnn-s&[Purڵ3 ߍ3:7օ礭 )=epg"=gh%xm'őh;V+߻LvGrs-*1ty3.`E(Y+{ z+ON@js"RA3gR$PUԗ}q^(ZoRHLtqJxcЬt:8G 7$<* {yz/g*H(ՃeLXO^0 潾C=U}|G1bp%p2! ' аQ $^ǟHIp}DrYpzii\WD-n7/NBh h{#.LЪbFn~͓DNZfoZ>Rf'GqTB W+9QDY!yW4zy;jyJ BwxqX 0#@?-N1ν# \>#ګ-_U?D&[.=+ȏz#I<7ٹOMUc_CM+KBE&K,&|h"PV~'Qu3p;l1.ߘeQz5Y1r3Gڅ|4gÜFBZ`>@#!1G̣[Y`Dj䄯X+YKM.Vj1*٨y,էXIeʚ]ow:(3E>S+`H.ɛ(68ׂRB^ث6 9xmQŅޅc\200,hو\o3N u;sqG>n, ?R~ "5zu銡n +WD[\NpŋL1%RF`95N2u!/CcΑ;[n)P<7fOYS[ۖv&~GI߿WKX'CGB" MGLxrpN)w.8Hs,əW>DT)\!-(P%3O%L"(W,('zk88ʬꝝOKW,{ 8JNSRr-k*.}jiБT2_jz X=g%TqLw:Czҷ\8rBl8ވx.'9Y9ex_Fl$$IqW|:AQm*=mnCţ))9VG/ܮsg{Ó{ d-ft{ieYN̤ax З7QӮ^ ,p1;Zn]a:kHW >~l3|n$ )]MxMrx" Do -peU{w$Ps6G_>yX$`|=Ш<}MdF!#nZhmKO0wM#DŪ:ڬ2xDT? 87=Ki& H"_$tJ髆P"!iA9aGsn&$39ZZ`g}$?s^>53rR,7XDZD¨щ`MA.a?1Ӌj>dAb~IG|拷t"Qoxyymo x*QԳ.;~$ή nY(UjԸ,L 7K|C L8tk= 1O LU9`$l.RC;$_[L'XڔG%Dӧ56u_l3ܾ%JәzYXV[WP@CT.kJa)x4,'A 2e9~<&@Nm"pA$]<E0/?oWiɿ|ڵ`Yo~ s&ɑ+z1A ~t&]chI@g0^VzF c@%lOfɚevl''~y5mJv<3lV4_90Tz.MwٟKe_ ޜ,,&dLb~xA ,G,FK1V^A$B,Npt;bF1Lb\:pnSjo5#wS?^3&LKFhM`+eFV(U w-`='YR=k_g'S@_(~q 4Zꣶ+BJ8 O:״UہSXOAo0=O6*LXⶶ]J4-'TLd޿neSܗ/y9$p}).1ԷOy` h޶'fç @IƓ_X`5jk cD D&&P hwGYDF>8l+@P7 HȖDT;X0F13,ӆb`]7}ڥ*Rpi zquƸ|j(fk~}2z7b$uQz@޲ Xǒ 6sHw;6֔!+YGb1%z}kcUIbVT 9bėQ s0֖4&J̷dj'>ihEpP5=v&N]!T$oV;AyX{-/]u /8^=1FK6^r~L&k-_|HcK˙[9d χgZh Fb.U:Dzݞ]/ma(m;]33;~u}DF򸯂>*I UVYnicFpDھl xߎݻjR”?m%- !xGa]ف3Ey 4V4D@M\T~q3hQ˄@O_7NA\kntpCY4 l! 0t7h%u☉`I Lb4>tD2>`p:-雎/ˀiz!5T{_Zpm v +<_ƅ@)MHF9?Y#&Avgp?NԔU} F,^TpP $LȯPiZ8ZxT+<-R$Y,=_x㰿L]nxtu"c*o/\3 p UtRg˥I3B9 c2] H$ 8I8:mv $s4y?ġF]8j E".]! D1&m}F'h[T"-BqjXQC;#a@޲b"ǤiV$ydn`#q͓>°sHP_X6Jf}했ܽ=deo\lAUCQ π&x<\kJ+'EGkEdFNG㈩-,J6Yb?:qrk#'Ћwy$Ȝx #+gJf%2Ei!"]2] ̂<(:#XcƐ 恇u{۽o%U7脎-ҭ`b[^mk~W=ު[)CZdFYijl}h'ʕl4"ՅtC=-_LH0rzh xx˧yT32)1 TeKE {1eTƺv5lq)wkdz9*NBwV݅T<k-")Emt☓aH5 d~*C:&[RӄB46_iR1Avbb\{oKE+@o׮)7 a"K53jkKaaa_P aI"y& GJK -p;##x׀E3<^b"#!Ϣ.Z;.vVoOfF°!Ƞ37wTG}M(3DFfھc#/d3CSQ h8qMG-ԭD$c4풀X.*h1 h`46:)գJ՞9ػNU_qv"C_ll#iڙoFnƥ1['䆺 &*礽\793xP'chmqNQG߭9X )i|7)QO6S^ú^ܷ̏#XA)}Yè7+]9 (X_40hц;[)qԼPP=Wk)b5Dʍr*OMVOm5x| Lw2F([C4Wֺ݁b]"`UjbږN3d aA6w;U(;֬K]\>dB+'6},T*PJWݴMeyVGq')epטvedXVy}QMDt,N+ lu/ !`\WWe)(r. )u9zZ3F(Eh]OfeK* FG:5P{b"p$-_]GA* wQ?H)| 2N_Lhcs~Et;Ą H#/㣘{v3+ `op8ZOm989j J4/e,zMZ~w:,,}!۽\"l!$n;pSbR95HI #ΥG&+&[Q"ڕA@DⰶrnڳTC[4e&dH\jG PG>,-=+=o8}]$qd+o|1f%YlX)>"9CYkU: !o^x l~˅l3;x\Ƨfh_SݬXF3ȀL`D]v2ނr ΛwS`0{`iIHaw<d6$17cNɇ-AC8s*\NJnDUE.ZJҠJa=vg U0{݆["^ U.LDØ3*L Xqm%斱MB-ȳXR_$6VYE.tD2ynA#ME7|: L֢"ݬ@)"o'NATr6(Zڤg6Rjtavχٌ!Ws&ȱq+T꾇$/+sk!R)F'k0H0^%bɌ11=Tdy*hVM_ IЂ F 2͆ؐ$2 N/Ǟ|n٨dkݣi;7J~ak@۬[G|XA ve~mG]n(Y2q_Lc@ !@;SIϡZЉ)] O;nY\kʑ2 S[ܐI%qLt=H5q9;s[#]/ 4 f'B#/iV8f=w0j<%γ?3u6GQ]K*cbj 13W?$D+MJh{JcI$ 2*nU2`nx@En3y0gF65,=~{Nk` hUL$$X!ȸCEn&u!EuܑUWg2n)+snĄoO~[Y>])@39 >BrTH,6ʟ@ :+ԢśEe_AΔ퇨HEOmIv+sEm2քyшp){[G&@-XWE$üb=a 3C[hY夸/eX@@ q M- 4C'^} *;[$Z* (Iwmj~3AmG roJ5X}+%p߽wtU]Kmb^rG-+6[O.UƟф(ѴG~6ۏ<9!6F7e!Zct /,cWM*;dP#vSaRZUTcQ@i8m@hOðg1ͤ1Vj$ :3Ct9_Ϛy#>G>g)k*aBY ybZiŽqJq/mI$g+acÓa1 6h";0)Z)Y I|*5q1 J@e?AESk| lkCa:gKp_ ](.d9ieB<݉A67l1(3!zmJ6[Tw-S qu=5AzR!sYC>q-C#'Q 1D$0T^6a͸nvN@F X ?;|Yq'WPkrW+[k1ʲQ,6,F/EvnuA}A ;vз]\Gý ֎ *8~ġ zqZis hDvI濲`{/! F˭HØY1= 5tK;y@ыe36HY2Ilkm|YaSbMw?r8އJb%|k]\( vpӿn!К !l qWC"ۓt&kKڨD;G7h2=LR ʎ-`ڬznR}Ź3+Fm~%wlT))$<9dh_?d̮ewQuTpqf1#Yͩ@k$!>u|I2Ed<DZYtk98W6K_XNjO8N6YasyitLȩ9 1Y4+w]j@R|,Q7E34rB-EU2-qj匏zBk_Ӈcy] _($F~zGG,ޟj0E|)ځl?k5^0WoG;0bnUm,/z3ʲ˕kr5Swq/}Nĺ&;#? u &lm昫 ǃun۠o: 򍀥&0't$'XxS""Z܉s vmKS>\%دUFgVg^ԓ :F-.9VTwguk/}z>ceŞ56`ê\%7竧g-n`"eQM($}tqeEtaU`^r^>'VVScK?cydz~hmE[F( | |օSZH勡 Asb%{5fW| MȰMN{Qv}!EftAvJLAH;ﲅu䴗'#GbZ3ma*d_3!ocj"6 k|]EfYaxSA},+ǻ!bUSWT bA`r:a>%,/4vS~v8߉%xiM)?y4/9ƎbGGPl*FJVּlsuձgAqvx;ĐbI:iˢ14P^ⷃ rr%㫷lrI5[(xb@i9?ߓL,l{ͩLց/M3;Zo˗dH>whL?H8OYЛfFGE@npӾpA3g>ȳqȐVAx@XkmEC#?- In$TU|#j n*PUSbg2'͠V˥dzkIF"s+֡V0z[d]a^ޓi%Ef#?}'$erO]oXM+=%'ʗ0N5$1BH-j *uԜcU~`RI{+X9!!&m:/Qߌ';xBY7K^\\PA,Ԇ0\.Q嗊\p# w %e,ʍU!2HtK:EYy>QEӰ7"CMܕ'@;roP(XͲ`ǧBl2x璄-hϟolDY^ D9dVP#c/v'CKʺ;V7S8ң9^@B E+@mL"߳odpfɐՋɺ>j1s3KapLn+5K氾6x耎RVW!v@R&'3t]楩ӜzKc?AX@Ocj0P-P[P ' iTA'8'Ws6^6O~P a}y> `GN@c:\"k<(C7fה-@DG1(T =a]pfYv@ zDAMO1WNxx^;i'GtI=& O1Sve:]4Bq@VC H|ȯrT#{ c #(VR yJy RǼYlDV盏 e)}/ax^*T4DD0;GcwJ!R/V_L-g5 ;s[TlnAi_n!>S)s_eblpدeSbԉ徫$#}1l'qyVWFag\@ C}&7Yr'T5*gSs%PYz,Fw3L%F月X`S84[CÅYw{>sL퓰 .l̽bk6ZLpٓ饜*NSOƇ'+DO鬿ln?2c)6-;3>@ h7$o<'u~&TǗS| d;wzo?mysUA 6c[ ]}fddN]YsX)+ٷ[Yd#U/$Z3;zJ!;9 =$%h9]'-cƸ[ϝ=Ч9 o(_ܑٿ"9%ZW:ZN.?T kQg4o9B󇺪c䆹IDHs&=! uJ˺kdwXY+>:@px'/2UoUϴ7G{$s&ygNB"hoX#ÊƠ嬯6fr\ݕh0C^:&=*l uE ީq &eWvTZsdmp%/ mpd@|,C2]qSg((u_e(Z_Q`ho4#N]ps4},VKox};>U˱?N ˫9fQ o<`fN5]m(j*v=eī !NdrL IX\zP{%P>ϊ!RQ3xKA1lIgwP88u'D%JGe_%&gXpD;h0*'A3X2-YTDK/L'ؗVOzWZ0:\HO}D qP+#όZwAEoD;@\}&~zX֠$Meo4[G2n&xyh"-0U}DtAe=~&CEC—zjڐ{g LUR"J$iLFBPb%H~a)*ȰkQӥqZPM&ޜg]q XqNqI endstream endobj 191 0 obj << /Length1 721 /Length2 15261 /Length3 0 /Length 15836 /Filter /FlateDecode >> stream xmM-|ڶ4޶m۶m۶m۶mm>73w&کUv*IDl=Mhh9J2 zZ&h!Gg ;[agN1@Mp03wQ;P60pY۹Z]]]]\h]xi)R218L-MBrbr1Y5@ madbdB0sX[ غ8:C #, *' S)uvmbhQgY2,Zh3_IؚX6voBN! \ cglh P1/ `kr Y8Z[8#?;fs11pO?zsvgTeN[ؚ ,=%n0__EO_KܽhY4L~̌>]#GG[ ^LLMq[VWQP2j!Y ]c?(c]J<ęLMGbUn(7ހbɂF;gl fʽt(Ac/C܉__z!C59A7)1{{Kg^X`BαAs'`hU!:檱@&kV@&=i%bM3)'(fA䞪1]!N_8Ow)gV 7>Q5ݓ?9f|WEEbp (T;_?2[w97ѬGMЉ,qߞ _ukNdXHm$ GvIˎg3 WMrʌhlhZZ$I!=qT1CijW2u[ mgqaqǴ` h_ Jgؘ]/fH+^kRK"!;\^HDXbԨl gBUJya`F1RхU8a^a{bc]',?'Z,cny_q Ρ}=> 8F1e43Mo X)C-`ilW`Z{kP?j_'쪝'2NqJBV?^OeJ@|Ui*ʂn{ <ڮU=ZrYW9V, k?cQ0r:ӷtքqCdqܟ%ѸS;-g-xU=tAZ5d'ϭvzN JQlV/!C&} wʻ#@p%6~1d8DC3wMq ʐEA3>>kEbqS.b%l;x6|G7q$L2[o֜' F?TX Q+l< DOv.ސ]Ue.A> \B!E$k V NJmV!jv/QS/2r|Pyő,CLBA们U1" 7(R\;M@(c_cu3}<ۻb*x_ƻ .NF3CG',|{k 'zev2F(X;ԍ(HFѪ 9BW>vcWV8;޴phx|3Mꠜdx~+;n" :Qd9f\j Mh:uVli0bE`!HǻA˯az6;EQT/4f4R@ɲ1GmhC ~n[.ʒYx:ӽD;1قi7(zS0^7Bw'H/'H..G ѝ3iEgZ\`A"j-|k@/e :^< $GwNFeOhd)_rEZAZ={yPy χD`㈬FF^_YZmnJm{%sb4X`5lAkRSpJH0\ٝާ!ܻo*bzB0Gkm^#52aJV3.yW;!Zs0];F0(s 썐)H5򖙀ȠM^j*"߀a* ŢxpXg(˿+'/C]k`s;!HK 'a},L1x|5eg\a5`zָkP:qJp nwM7a]WI>gC)u׋F v+iVum+ClvX>B j=8Ak̏ʧȽ sޖsuJ'R}J:P!ґS8l7u Cd/l)W;A̸Džs"WrEukYG؈%%HSo}袠)iYN*ld0n_~o 1=7F/qT&Fr_.p8lR'eB5[|eW\P<4:('br[bHfhWMix (kW>x?/<%qpքxeyfntkpL)Vȸ6S~Ҫ ?Lj qq+ 1]}t. ÊY7^E 7 ^MM[(-LF!믩 {mZ @Ygzhtڝ\O*B /ۆu3$!)%::EX67?,eB"S&12%˥wĜ$f߫Cޏ[ob \(g_X-qLc521.*_|ܿ7l\'Eg\})i6sI|0GqJToZ(la8 N"aYs\`Gܙ*g6KfI5_ގ3%svV#iy =z#nrͥJyv6gP3U "q]ez?Y.4IB+WbU/=(T,$@L^㍓ew>6!W0(V_*& ~PMs@,OYX&ʻ]5iEu e'Y6ZگQF"I5g%<ڿy U~I QWc#C d]WLLt3D?If? O!8B/`^>93p[ӏ[7>֝k_.2`]\ɛΫEAIaG~}Pz]n쨹n]U!wvu&]6/K!˟/P$@TYg_Sdis|z#$;C(I>h]غ/&j.!*kQ#^SFo,ϝc8x@^puؐ?G=,"E nG'bъ`AeCW򧦣qQud2B?o/%k4Ygwtʯ>Z=1?N0tl|N!1?9^įZ.(&52uE;""vbgLFNT+H= *C+M AH͟eBl?40C2qЍF`͎4 2 (ې^49lv;{Rs8Զu8#j8L;sPmQTȨXW v2ľĻ3z,]tG-X^1*Jg~Q>-|Uuv=W8(Zv Z ']v*w s{fIᢹXIraw{Ջ!]A_/{Tp(.1C`xl^ò9$K JyN_ެ~Ăaz15I.1zQi]`A.m(ԀF%YqWcAPdIW *nKIWx1^@- dc-5}X뭺V T(,UfnJ44$BONԉ!V"@F6 '(ƴ^"а)A VO[Q0n428#^;WܪhRZMWhRHd|pnM']}35orʧGcK7j&M9[h6VEߺ͘g!۶dVEk 'ͭsq:$P}zƍ fY0QV*d0h%7||LZqM]s~ݺ-X3@gn)@T^65|5Me̮M,Tz*8~\8WnjKt'SyѴfQ_*{ mR7Ꝥ,( +u_0/DnQ=wΙ2"L䵥QǾz.?:iV60 ƔmYvW_fWGx6װk#etIõfx1t5DLl[C;\LkJmJ"WV왃Ǝi@'qt|b݊@Hf){B{2 |#Nm}W8T2"6)0ՔC, [&/7٢L=nc'5A+hGlg"D?ma:\i \Qj]7}}Ӵ. {T'CHn[bu7`.vbܝq|< v:,r|^2I۠)&&-:sF5@9:~1%Jǀ+B^k͏=C,"Bd>\C-mQӹlֵ~_W&rmSB)*z{Wjg1cmXt9."i}euM`aE{ x&U춌$mmAe++~$^ȵA_SaP2bӼO+xi:5Uc^&+G/dJ!T<%7tQB$7m6s avH?a;/x?{F-W;J5!k1XԓmH >eZFXpF@_ W H))XA.Z h.n82 xZ Z7K'b?4Q:HG ,z/=!Qi5=ח*iA9ٽ \aeFIo1Oq#WB7񗿠XMSDuZtY/9y 6jpWxTP ʏ`lGJ/bu@sG'q3=i-j7&4=|Ke0t6Z"CJߔv>㊛'^MO.y&8.V0@İ[f΁AmR>AԔV,iOo )X`=vmr]6f6V c/7AD_垅Q_F0 za|۞YL<,=DL1A M򴲽Éܹ}d)4qK`\' a U9ɩch5p [IDӪP, j));; A1Ω6vK웠Qџ߇Xdy-_DgESQQ2m^4rc&1M2R]&-" !<11/НqW(tҗF Cm{;D,_c]P xL<5Ush0M6˸tWm5ˑ睝8]aHua{\0ڙ2&/7uR A_U)d3y߷ըK|TXYq.n,%\.*Ta8޷q|byxqIm&bV"> m:.W׊xk T(GUK<}j2c;&-BbDvb.X2 E`o e4wT ̮ƇI9, NB;WvoSPmYz] ׃?Bg'->ÃѢ^q|ǟC⎱URPf/ظ "KE頞>2^ ⨞s,DMfג]zd7;1FR+ d&֡%y 0@sJr.̀x{ͫ{|3næj[>h$|4g <(^tKPTK⯐X5dkAP,DUIa|WkNοhi/x{SN tP/ <k/Eir}-_ޚ̬'j`wc-@e/e}d;蘋wF-:\茝=%g>q58Bmq LRIè?%#g:\f0uc-hlY9E5KU'1Bs'7ZQU`ȏ֞GEDa8 GmҨ PS \[3@WS,|Ɨc`wS4pgLh܀OI5ru,/}?NM,DM-$P%6 TX("y~kO|f FA(8o6[jcLW+2Bn~/ k~[ƺ(&f`愩@t^&krĚnc-O!%w}?aKrIH 2JA| t$va2 CO`*z3A V̘fBMЗ)pdM8#*(R S= >A4:dTb6`/>0Ux^N<Nj$W8OUar fd+a+#iK|#|#0`}O>8d^#AZHA1wN#k_;vқ'Lp?3/z#iN-E 2 x=J3r; KqQCgn'f1'!e.هFw n:l<8; J!\Jt蔎\m7*H"l &NkB5m~W`m``^K8NOgcrr~fD;[v(Zi0"BYBv HO1uQ`u뇯LdNxe[`=懍H7ƒ֔dnjfL% I$ѫCć5hD[30!8@ NUmuA=_)*ws!:ĵtµ[W!|7Cˋ;]xR&Wġ{>؏a ^Ə짎a1wlkn$Ϥi;ScGĽ4?wɟTl1R(v%R_;Ջpn«=j4mӈeSsEP)SH|]4#z*)+hme`H3Ֆ !yR޾ hyUO|gQnr mL2R05-/˱P 73?Kg/>tU#49 ef=g蕝|KGlELm`0rfA-uJ8)+>0_Wp|[s(o?' & qp&WxM{U'~K79b F->S"{!.=kuc2y='~#1a.4ʂ44!~0e!h9`kuZiOGz3Ќޢ2ۘ#𧻓M%\1*+tq.efVlZFO RY xKެ^%qBM^g[1uARP }mΒ1s $Gt8? Y&C,WCW  .ZVM*1^3|gKnf}yRȘX׈JxJVɦ`8]ؤTQRf"N~U9l#.f3qvчͤ+YB{˱R?X.͂,xiCFx%O~>O6tǶ۹EWt_OFKg)&H!SuQ^X{BgPΰ>c_rIV wgPT: {xrCL\%EDdgr谶>=CCzQ Dy_#L;=4BN"3;$WbaQkx4t 4J,(Q-:JWLw6bBFH5`NۊFV XeqٽGZdlޓMFcGxR/1\*%5)]"j^9N/WCؗ瀔ܛS'{Bw *`*