diff --git a/.gitattributes b/.gitattributes index 8d1f26a78..7a5c5bde5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,8 +3,8 @@ # always use LF, even if the files are edited on windows, they need to be compiled/used on unix * text eol=lf -# Denote all files that are truly binary and should not be modified. +# Denote all files that are binary and should not be modified. *.png binary *.jpg binary -*.cae binary *.hdf5 binary +*.pdf binary diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6e82561c5..7958db9b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -115,13 +115,6 @@ Pytest: - release ################################################################################################### -OrientationRelationship: - stage: preprocessing - script: OrientationRelationship/test.py - except: - - master - - release - Pre_SeedGeneration: stage: preprocessing script: PreProcessing_SeedGeneration/test.py @@ -398,7 +391,6 @@ Marc_compileIfort: stage: compileMarc script: - module load $IntelMarc $HDF5Marc $MSC - - export DAMASK_HDF5=ON - Marc_compileIfort/test.py except: - master @@ -409,7 +401,6 @@ Hex_elastic: stage: marc script: - module load $IntelMarc $HDF5Marc $MSC - - export DAMASK_HDF5=ON - Hex_elastic/test.py except: - master @@ -419,7 +410,6 @@ CubicFCC_elastic: stage: marc script: - module load $IntelMarc $HDF5Marc $MSC - - export DAMASK_HDF5=ON - CubicFCC_elastic/test.py except: - master @@ -429,7 +419,6 @@ CubicBCC_elastic: stage: marc script: - module load $IntelMarc $HDF5Marc $MSC - - export DAMASK_HDF5=ON - CubicBCC_elastic/test.py except: - master @@ -439,7 +428,6 @@ J2_plasticBehavior: stage: marc script: - module load $IntelMarc $HDF5Marc $MSC - - export DAMASK_HDF5=ON - J2_plasticBehavior/test.py except: - master @@ -506,18 +494,6 @@ GridSolver: - master - release -Processing: - stage: createDocumentation - script: - - cd $DAMASKROOT/processing/pre - - $DAMASKROOT/PRIVATE/documenting/scriptHelpToWiki.py --debug *.py - - cd $DAMASKROOT/processing/post - - rm vtk2ang.py DAD*.py - - $DAMASKROOT/PRIVATE/documenting/scriptHelpToWiki.py --debug *.py - except: - - master - - release - ################################################################################################## backupData: stage: saveDocumentation @@ -528,7 +504,6 @@ backupData: - mv $TESTROOT/performance/time.png $BACKUP/${CI_PIPELINE_ID}_${CI_COMMIT_SHA}/ - mv $TESTROOT/performance/memory.png $BACKUP/${CI_PIPELINE_ID}_${CI_COMMIT_SHA}/ - mv $DAMASKROOT/PRIVATE/documenting/DAMASK_* $BACKUP/${CI_PIPELINE_ID}_${CI_COMMIT_SHA}/ - - mv $DAMASKROOT/processing $BACKUP/${CI_PIPELINE_ID}_${CI_COMMIT_SHA}/ only: - development diff --git a/CONFIG b/CONFIG index 53e87b647..8da4d5b96 100644 --- a/CONFIG +++ b/CONFIG @@ -1,11 +1,7 @@ # "set"-syntax needed only for tcsh (but works with bash and zsh) -# DAMASK_ROOT will be expanded - set DAMASK_NUM_THREADS = 4 set MSC_ROOT = /opt/msc set MARC_VERSION = 2019 set ABAQUS_VERSION = 2019 - -set DAMASK_HDF5 = ON diff --git a/PRIVATE b/PRIVATE index 524e86c11..036faecca 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit 524e86c117d816e3bd873eed7663e258a6f2e139 +Subproject commit 036faecca39b46fd2328597ca858cbb04e37f79a diff --git a/VERSION b/VERSION index 1439ed27c..a7308c0ee 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.3-1237-g5a2053cd +v2.0.3-1406-g5fc1abae diff --git a/cmake/Compiler-GNU.cmake b/cmake/Compiler-GNU.cmake index 008c0c90e..6a9973bc6 100644 --- a/cmake/Compiler-GNU.cmake +++ b/cmake/Compiler-GNU.cmake @@ -2,129 +2,129 @@ # GNU Compiler ################################################################################################### - if (OPENMP) - set (OPENMP_FLAGS "-fopenmp") - endif () +if (OPENMP) + set (OPENMP_FLAGS "-fopenmp") +endif () - if (OPTIMIZATION STREQUAL "OFF") - set (OPTIMIZATION_FLAGS "-O0" ) - elseif (OPTIMIZATION STREQUAL "DEFENSIVE") - set (OPTIMIZATION_FLAGS "-O2") - elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") - set (OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -ftree-vectorize") - endif () +if (OPTIMIZATION STREQUAL "OFF") + set (OPTIMIZATION_FLAGS "-O0" ) +elseif (OPTIMIZATION STREQUAL "DEFENSIVE") + set (OPTIMIZATION_FLAGS "-O2") +elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") + set (OPTIMIZATION_FLAGS "-O3 -ffast-math -funroll-loops -ftree-vectorize") +endif () - set (STANDARD_CHECK "-std=f2008ts -pedantic-errors" ) - set (LINKER_FLAGS "${LINKER_FLAGS} -Wl") - # options parsed directly to the linker - set (LINKER_FLAGS "${LINKER_FLAGS},-undefined,dynamic_lookup" ) - # ensure to link against dynamic libraries +set (STANDARD_CHECK "-std=f2008ts -pedantic-errors" ) +set (LINKER_FLAGS "${LINKER_FLAGS} -Wl") +# options parsed directly to the linker +set (LINKER_FLAGS "${LINKER_FLAGS},-undefined,dynamic_lookup" ) +# ensure to link against dynamic libraries #------------------------------------------------------------------------------------------------ # Fine tuning compilation options - set (COMPILE_FLAGS "${COMPILE_FLAGS} -xf95-cpp-input") - # preprocessor +set (COMPILE_FLAGS "${COMPILE_FLAGS} -xf95-cpp-input") +# preprocessor - set (COMPILE_FLAGS "${COMPILE_FLAGS} -ffree-line-length-132") - # restrict line length to the standard 132 characters (lattice.f90 require more characters) +set (COMPILE_FLAGS "${COMPILE_FLAGS} -ffree-line-length-132") +# restrict line length to the standard 132 characters (lattice.f90 require more characters) - set (COMPILE_FLAGS "${COMPILE_FLAGS} -fimplicit-none") - # assume "implicit none" even if not present in source +set (COMPILE_FLAGS "${COMPILE_FLAGS} -fimplicit-none") +# assume "implicit none" even if not present in source - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wall") - # sets the following Fortran options: - # -Waliasing: warn about possible aliasing of dummy arguments. Specifically, it warns if the same actual argument is associated with a dummy argument with "INTENT(IN)" and a dummy argument with "INTENT(OUT)" in a call with an explicit interface. - # -Wampersand: checks if a character expression is continued proberly by an ampersand at the end of the line and at the beginning of the new line - # -Warray-bounds: checks if array reference is out of bounds at compile time. use -fcheck-bounds to also check during runtime - # -Wconversion: warn about implicit conversions between different type - # -Wsurprising: warn when "suspicious" code constructs are encountered. While technically legal these usually indicate that an error has been made. - # -Wc-binding-type: - # -Wintrinsics-std: only standard intrisics are available, e.g. "call flush(6)" will cause an error - # -Wno-tabs: do not allow tabs in source - # -Wintrinsic-shadow: warn if a user-defined procedure or module procedure has the same name as an intrinsic - # -Wline-truncation: - # -Wtarget-lifetime: - # -Wreal-q-constant: warn about real-literal-constants with 'q' exponent-letter - # -Wunused: a number of unused-xxx warnings - # and sets the general (non-Fortran options) options: - # -Waddress - # -Warray-bounds (only with -O2) - # -Wc++11-compat - # -Wchar-subscripts - # -Wcomment - # -Wformat - # -Wmaybe-uninitialized - # -Wnonnull - # -Wparentheses - # -Wpointer-sign - # -Wreorder - # -Wreturn-type - # -Wsequence-point - # -Wstrict-aliasing - # -Wstrict-overflow=1 - # -Wswitch - # -Wtrigraphs - # -Wuninitialized - # -Wunknown-pragmas - # -Wunused-function - # -Wunused-label - # -Wunused-value - # -Wunused-variable - # -Wvolatile-register-var +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wall") +# sets the following Fortran options: +# -Waliasing: warn about possible aliasing of dummy arguments. Specifically, it warns if the same actual argument is associated with a dummy argument with "INTENT(IN)" and a dummy argument with "INTENT(OUT)" in a call with an explicit interface. +# -Wampersand: checks if a character expression is continued proberly by an ampersand at the end of the line and at the beginning of the new line +# -Warray-bounds: checks if array reference is out of bounds at compile time. use -fcheck-bounds to also check during runtime +# -Wconversion: warn about implicit conversions between different type +# -Wsurprising: warn when "suspicious" code constructs are encountered. While technically legal these usually indicate that an error has been made. +# -Wc-binding-type: +# -Wintrinsics-std: only standard intrisics are available, e.g. "call flush(6)" will cause an error +# -Wno-tabs: do not allow tabs in source +# -Wintrinsic-shadow: warn if a user-defined procedure or module procedure has the same name as an intrinsic +# -Wline-truncation: +# -Wtarget-lifetime: +# -Wreal-q-constant: warn about real-literal-constants with 'q' exponent-letter +# -Wunused: a number of unused-xxx warnings +# and sets the general (non-Fortran options) options: +# -Waddress +# -Warray-bounds (only with -O2) +# -Wc++11-compat +# -Wchar-subscripts +# -Wcomment +# -Wformat +# -Wmaybe-uninitialized +# -Wnonnull +# -Wparentheses +# -Wpointer-sign +# -Wreorder +# -Wreturn-type +# -Wsequence-point +# -Wstrict-aliasing +# -Wstrict-overflow=1 +# -Wswitch +# -Wtrigraphs +# -Wuninitialized +# -Wunknown-pragmas +# -Wunused-function +# -Wunused-label +# -Wunused-value +# -Wunused-variable +# -Wvolatile-register-var - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wextra") - # sets the following Fortran options: - # -Wunuses-parameter: - # -Wcompare-reals: - # and sets the general (non-Fortran options) options: - # -Wclobbered - # -Wempty-body - # -Wignored-qualifiers - # -Wmissing-field-initializers - # -Woverride-init - # -Wsign-compare - # -Wtype-limits - # -Wuninitialized - # -Wunused-but-set-parameter (only with -Wunused or -Wall) - # -Wno-globals +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wextra") +# sets the following Fortran options: +# -Wunuses-parameter: +# -Wcompare-reals: +# and sets the general (non-Fortran options) options: +# -Wclobbered +# -Wempty-body +# -Wignored-qualifiers +# -Wmissing-field-initializers +# -Woverride-init +# -Wsign-compare +# -Wtype-limits +# -Wuninitialized +# -Wunused-but-set-parameter (only with -Wunused or -Wall) +# -Wno-globals - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wcharacter-truncation") - # warn if character expressions (strings) are truncated +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wcharacter-truncation") +# warn if character expressions (strings) are truncated - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wunderflow") - # produce a warning when numerical constant expressions are encountered, which yield an UNDERFLOW during compilation +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wunderflow") +# produce a warning when numerical constant expressions are encountered, which yield an UNDERFLOW during compilation - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wsuggest-attribute=pure") - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wsuggest-attribute=noreturn") - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wconversion-extra") - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wimplicit-procedure") - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-unused-parameter") - set (COMPILE_FLAGS "${COMPILE_FLAGS} -ffpe-summary=all") - # print summary of floating point exeptions (invalid,zero,overflow,underflow,inexact,denormal) +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wsuggest-attribute=pure") +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wsuggest-attribute=noreturn") +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wconversion-extra") +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wimplicit-procedure") +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-unused-parameter") +set (COMPILE_FLAGS "${COMPILE_FLAGS} -ffpe-summary=all") +# print summary of floating point exeptions (invalid,zero,overflow,underflow,inexact,denormal) - # Additional options - # -Warray-temporarieswarnings: because we have many temporary arrays (performance issue?): - # -Wimplicit-interface: no interfaces for lapack/MPI routines - # -Wunsafe-loop-optimizations: warn if the loop cannot be optimized due to nontrivial assumptions. +# Additional options +# -Warray-temporarieswarnings: because we have many temporary arrays (performance issue?): +# -Wimplicit-interface: no interfaces for lapack/MPI routines +# -Wunsafe-loop-optimizations: warn if the loop cannot be optimized due to nontrivial assumptions. #------------------------------------------------------------------------------------------------ # Runtime debugging - set (DEBUG_FLAGS "${DEBUG_FLAGS} -ffpe-trap=invalid,zero,overflow") - # stop execution if floating point exception is detected (NaN is silent) +set (DEBUG_FLAGS "${DEBUG_FLAGS} -ffpe-trap=invalid,zero,overflow") +# stop execution if floating point exception is detected (NaN is silent) - set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") - # Generate symbolic debugging information in the object file +set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") +# Generate symbolic debugging information in the object file - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fbacktrace") - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fdump-core") - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fcheck=all") - # checks for (array-temps,bounds,do,mem,pointer,recursion) +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fbacktrace") +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fdump-core") +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fcheck=all") +# checks for (array-temps,bounds,do,mem,pointer,recursion) - # Additional options - # -ffpe-trap=precision,denormal,underflow +# Additional options +# -ffpe-trap=precision,denormal,underflow #------------------------------------------------------------------------------------------------ # precision settings - set (PRECISION_FLAGS "${PRECISION_FLAGS} -fdefault-real-8") - # set precision to 8 bytes for standard real (=8 for pReal). Will set size of double to 16 bytes as long as -fdefault-double-8 is not set - set (PRECISION_FLAGS "${PRECISION_FLAGS} -fdefault-double-8") - # set precision to 8 bytes for double real, would be 16 bytes if -fdefault-real-8 is used +set (PRECISION_FLAGS "${PRECISION_FLAGS} -fdefault-real-8") +# set precision to 8 bytes for standard real (=8 for pReal). Will set size of double to 16 bytes as long as -fdefault-double-8 is not set +set (PRECISION_FLAGS "${PRECISION_FLAGS} -fdefault-double-8") +# set precision to 8 bytes for double real, would be 16 bytes if -fdefault-real-8 is used diff --git a/cmake/Compiler-Intel.cmake b/cmake/Compiler-Intel.cmake index 60ed46cbc..1a2c2c455 100644 --- a/cmake/Compiler-Intel.cmake +++ b/cmake/Compiler-Intel.cmake @@ -1,116 +1,116 @@ ################################################################################################### # Intel Compiler ################################################################################################### - if (OPENMP) - set (OPENMP_FLAGS "-qopenmp -parallel") - endif () +if (OPENMP) + set (OPENMP_FLAGS "-qopenmp -parallel") +endif () - if (OPTIMIZATION STREQUAL "OFF") - set (OPTIMIZATION_FLAGS "-O0 -no-ip") - elseif (OPTIMIZATION STREQUAL "DEFENSIVE") - set (OPTIMIZATION_FLAGS "-O2") - elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") - set (OPTIMIZATION_FLAGS "-ipo -O3 -no-prec-div -fp-model fast=2 -xHost") - # -fast = -ipo, -O3, -no-prec-div, -static, -fp-model fast=2, and -xHost" - endif () +if (OPTIMIZATION STREQUAL "OFF") + set (OPTIMIZATION_FLAGS "-O0 -no-ip") +elseif (OPTIMIZATION STREQUAL "DEFENSIVE") + set (OPTIMIZATION_FLAGS "-O2") +elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") + set (OPTIMIZATION_FLAGS "-ipo -O3 -no-prec-div -fp-model fast=2 -xHost") + # -fast = -ipo, -O3, -no-prec-div, -static, -fp-model fast=2, and -xHost" +endif () - # -assume std_mod_proc_name (included in -standard-semantics) causes problems if other modules - # (PETSc, HDF5) are not compiled with this option (https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/62172) - set (STANDARD_CHECK "-stand f15 -standard-semantics -assume nostd_mod_proc_name") - set (LINKER_FLAGS "${LINKER_FLAGS} -shared-intel") - # Link against shared Intel libraries instead of static ones +# -assume std_mod_proc_name (included in -standard-semantics) causes problems if other modules +# (PETSc, HDF5) are not compiled with this option (https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/62172) +set (STANDARD_CHECK "-stand f15 -standard-semantics -assume nostd_mod_proc_name") +set (LINKER_FLAGS "${LINKER_FLAGS} -shared-intel") +# Link against shared Intel libraries instead of static ones #------------------------------------------------------------------------------------------------ # Fine tuning compilation options - set (COMPILE_FLAGS "${COMPILE_FLAGS} -fpp") - # preprocessor +set (COMPILE_FLAGS "${COMPILE_FLAGS} -fpp") +# preprocessor - set (COMPILE_FLAGS "${COMPILE_FLAGS} -ftz") - # flush underflow to zero, automatically set if -O[1,2,3] +set (COMPILE_FLAGS "${COMPILE_FLAGS} -ftz") +# flush underflow to zero, automatically set if -O[1,2,3] - set (COMPILE_FLAGS "${COMPILE_FLAGS} -diag-disable") - # disables warnings ... - set (COMPILE_FLAGS "${COMPILE_FLAGS} 5268") - # ... the text exceeds right hand column allowed on the line (we have only comments there) - set (COMPILE_FLAGS "${COMPILE_FLAGS},7624") - # ... about deprecated forall (has nice syntax and most likely a performance advantage) +set (COMPILE_FLAGS "${COMPILE_FLAGS} -diag-disable") +# disables warnings ... +set (COMPILE_FLAGS "${COMPILE_FLAGS} 5268") +# ... the text exceeds right hand column allowed on the line (we have only comments there) +set (COMPILE_FLAGS "${COMPILE_FLAGS},7624") +# ... about deprecated forall (has nice syntax and most likely a performance advantage) - set (COMPILE_FLAGS "${COMPILE_FLAGS} -warn") - # enables warnings ... - set (COMPILE_FLAGS "${COMPILE_FLAGS} declarations") - # ... any undeclared names (alternative name: -implicitnone) - set (COMPILE_FLAGS "${COMPILE_FLAGS},general") - # ... warning messages and informational messages are issued by the compiler - set (COMPILE_FLAGS "${COMPILE_FLAGS},usage") - # ... questionable programming practices - set (COMPILE_FLAGS "${COMPILE_FLAGS},interfaces") - # ... checks the interfaces of all SUBROUTINEs called and FUNCTIONs invoked in your compilation against an external set of interface blocks - set (COMPILE_FLAGS "${COMPILE_FLAGS},ignore_loc") - # ... %LOC is stripped from an actual argument - set (COMPILE_FLAGS "${COMPILE_FLAGS},alignments") - # ... data that is not naturally aligned - set (COMPILE_FLAGS "${COMPILE_FLAGS},unused") - # ... declared variables that are never used +set (COMPILE_FLAGS "${COMPILE_FLAGS} -warn") +# enables warnings ... +set (COMPILE_FLAGS "${COMPILE_FLAGS} declarations") +# ... any undeclared names (alternative name: -implicitnone) +set (COMPILE_FLAGS "${COMPILE_FLAGS},general") +# ... warning messages and informational messages are issued by the compiler +set (COMPILE_FLAGS "${COMPILE_FLAGS},usage") +# ... questionable programming practices +set (COMPILE_FLAGS "${COMPILE_FLAGS},interfaces") +# ... checks the interfaces of all SUBROUTINEs called and FUNCTIONs invoked in your compilation against an external set of interface blocks +set (COMPILE_FLAGS "${COMPILE_FLAGS},ignore_loc") +# ... %LOC is stripped from an actual argument +set (COMPILE_FLAGS "${COMPILE_FLAGS},alignments") +# ... data that is not naturally aligned +set (COMPILE_FLAGS "${COMPILE_FLAGS},unused") +# ... declared variables that are never used - # Additional options - # -warn: enables warnings, where - # truncated_source: Determines whether warnings occur when source exceeds the maximum column width in fixed-format files. - # (too many warnings because we have comments beyond character 132) - # uncalled: Determines whether warnings occur when a statement function is never called - # all: - # -name as_is: case sensitive Fortran! +# Additional options +# -warn: enables warnings, where +# truncated_source: Determines whether warnings occur when source exceeds the maximum column width in fixed-format files. +# (too many warnings because we have comments beyond character 132) +# uncalled: Determines whether warnings occur when a statement function is never called +# all: +# -name as_is: case sensitive Fortran! #------------------------------------------------------------------------------------------------ # Runtime debugging - set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") - # Generate symbolic debugging information in the object file +set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") +# Generate symbolic debugging information in the object file - set (DEBUG_FLAGS "${DEBUG_FLAGS} -traceback") - # Generate extra information in the object file to provide source file traceback information when a severe error occurs at run time +set (DEBUG_FLAGS "${DEBUG_FLAGS} -traceback") +# Generate extra information in the object file to provide source file traceback information when a severe error occurs at run time - set (DEBUG_FLAGS "${DEBUG_FLAGS} -gen-interfaces") - # Generate an interface block for each routine. http://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-explicit-again/ +set (DEBUG_FLAGS "${DEBUG_FLAGS} -gen-interfaces") +# Generate an interface block for each routine. http://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-explicit-again/ - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fp-stack-check") - # Generate extra code after every function call to ensure that the floating-point (FP) stack is in the expected state +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fp-stack-check") +# Generate extra code after every function call to ensure that the floating-point (FP) stack is in the expected state - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fp-model strict") - # Trap uninitalized variables +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fp-model strict") +# Trap uninitalized variables - set (DEBUG_FLAGS "${DEBUG_FLAGS} -check" ) - # Checks at runtime ... - set (DEBUG_FLAGS "${DEBUG_FLAGS} bounds") - # ... if an array index is too small (<1) or too large! - set (DEBUG_FLAGS "${DEBUG_FLAGS},format") - # ... for the data type of an item being formatted for output. - set (DEBUG_FLAGS "${DEBUG_FLAGS},output_conversion") - # ... for the fit of data items within a designated format descriptor field. - set (DEBUG_FLAGS "${DEBUG_FLAGS},pointers") - # ... for certain disassociated or uninitialized pointers or unallocated allocatable objects. - set (DEBUG_FLAGS "${DEBUG_FLAGS},uninit") - # ... for uninitialized variables. - set (DEBUG_FLAGS "${DEBUG_FLAGS} -ftrapuv") - # ... initializes stack local variables to an unusual value to aid error detection - set (DEBUG_FLAGS "${DEBUG_FLAGS} -fpe-all=0") - # ... capture all floating-point exceptions, sets -ftz automatically +set (DEBUG_FLAGS "${DEBUG_FLAGS} -check" ) +# Checks at runtime ... +set (DEBUG_FLAGS "${DEBUG_FLAGS} bounds") +# ... if an array index is too small (<1) or too large! +set (DEBUG_FLAGS "${DEBUG_FLAGS},format") +# ... for the data type of an item being formatted for output. +set (DEBUG_FLAGS "${DEBUG_FLAGS},output_conversion") +# ... for the fit of data items within a designated format descriptor field. +set (DEBUG_FLAGS "${DEBUG_FLAGS},pointers") +# ... for certain disassociated or uninitialized pointers or unallocated allocatable objects. +set (DEBUG_FLAGS "${DEBUG_FLAGS},uninit") +# ... for uninitialized variables. +set (DEBUG_FLAGS "${DEBUG_FLAGS} -ftrapuv") +# ... initializes stack local variables to an unusual value to aid error detection +set (DEBUG_FLAGS "${DEBUG_FLAGS} -fpe-all=0") +# ... capture all floating-point exceptions, sets -ftz automatically - set (DEBUG_FLAGS "${DEBUG_FLAGS} -warn") - # enables warnings ... - set (DEBUG_FLAGS "${DEBUG_FLAGS} errors") - # ... warnings are changed to errors - set (DEBUG_FLAGS "${DEBUG_FLAGS},stderrors") - # ... warnings about Fortran standard violations are changed to errors +set (DEBUG_FLAGS "${DEBUG_FLAGS} -warn") +# enables warnings ... +set (DEBUG_FLAGS "${DEBUG_FLAGS} errors") +# ... warnings are changed to errors +set (DEBUG_FLAGS "${DEBUG_FLAGS},stderrors") +# ... warnings about Fortran standard violations are changed to errors - set (DEBUG_FLAGS "${DEBUG_FLAGS} -debug-parameters all") - # generate debug information for parameters +set (DEBUG_FLAGS "${DEBUG_FLAGS} -debug-parameters all") +# generate debug information for parameters - # Additional options - # -heap-arrays: Should not be done for OpenMP, but set "ulimit -s unlimited" on shell. Probably it helps also to unlimit other limits - # -check: Checks at runtime, where - # arg_temp_created: will cause a lot of warnings because we create a bunch of temporary arrays (performance?) - # stack: +# Additional options +# -heap-arrays: Should not be done for OpenMP, but set "ulimit -s unlimited" on shell. Probably it helps also to unlimit other limits +# -check: Checks at runtime, where +# arg_temp_created: will cause a lot of warnings because we create a bunch of temporary arrays (performance?) +# stack: #------------------------------------------------------------------------------------------------ # precision settings - set (PRECISION_FLAGS "${PRECISION_FLAGS} -real-size 64") - # set precision for standard real to 32 | 64 | 128 (= 4 | 8 | 16 bytes, type pReal is always 8 bytes) +set (PRECISION_FLAGS "${PRECISION_FLAGS} -real-size 64") +# set precision for standard real to 32 | 64 | 128 (= 4 | 8 | 16 bytes, type pReal is always 8 bytes) diff --git a/cmake/Compiler-PGI.cmake b/cmake/Compiler-PGI.cmake index bca76f648..39d9b092f 100644 --- a/cmake/Compiler-PGI.cmake +++ b/cmake/Compiler-PGI.cmake @@ -1,25 +1,24 @@ ################################################################################################### # PGI Compiler ################################################################################################### -elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "PGI") - if (OPTIMIZATION STREQUAL "OFF") - set (OPTIMIZATION_FLAGS "-O0" ) - elseif (OPTIMIZATION STREQUAL "DEFENSIVE") - set (OPTIMIZATION_FLAGS "-O2") - elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") - set (OPTIMIZATION_FLAGS "-O3") - endif () +if (OPTIMIZATION STREQUAL "OFF") + set (OPTIMIZATION_FLAGS "-O0" ) +elseif (OPTIMIZATION STREQUAL "DEFENSIVE") + set (OPTIMIZATION_FLAGS "-O2") +elseif (OPTIMIZATION STREQUAL "AGGRESSIVE") + set (OPTIMIZATION_FLAGS "-O3") +endif () #------------------------------------------------------------------------------------------------ # Fine tuning compilation options - set (COMPILE_FLAGS "${COMPILE_FLAGS} -Mpreprocess") - # preprocessor +set (COMPILE_FLAGS "${COMPILE_FLAGS} -Mpreprocess") +# preprocessor - set (STANDARD_CHECK "-Mallocatable=03") +set (STANDARD_CHECK "-Mallocatable=03") #------------------------------------------------------------------------------------------------ # Runtime debugging - set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") - # Includes debugging information in the object module; sets the optimization level to zero unless a -⁠O option is present on the command line +set (DEBUG_FLAGS "${DEBUG_FLAGS} -g") +# Includes debugging information in the object module; sets the optimization level to zero unless a -⁠O option is present on the command line diff --git a/env/DAMASK.csh b/env/DAMASK.csh index d223d885a..b1b9dfb98 100644 --- a/env/DAMASK.csh +++ b/env/DAMASK.csh @@ -7,12 +7,6 @@ set DAMASK_ROOT=`python -c "import os,sys; print(os.path.realpath(os.path.expand source $DAMASK_ROOT/CONFIG -# add BRANCH if DAMASK_ROOT is a git repository -cd $DAMASK_ROOT >/dev/null -set BRANCH = `git branch 2>/dev/null| grep -E '^\* ')` -cd - >/dev/null - -# if DAMASK_BIN is present set path = ($DAMASK_ROOT/bin $path) set SOLVER=`which DAMASK_spectral` @@ -21,20 +15,12 @@ if ( "x$DAMASK_NUM_THREADS" == "x" ) then set DAMASK_NUM_THREADS=1 endif -# currently, there is no information that unlimited causes problems +# currently, there is no information that unlimited stack size causes problems # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # more info https://jblevins.org/log/segfault # https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap -# http://superuser.com/questions/220059/what-parameters-has-ulimit -limit datasize unlimited # maximum heap size (kB) +# http://superuser.com/questions/220059/what-parameters-has-ulimit limit stacksize unlimited # maximum stack size (kB) -endif -if ( `limit | grep memoryuse` != "" ) then - limit memoryuse unlimited # maximum physical memory size -endif -if ( `limit | grep vmemoryuse` != "" ) then - limit vmemoryuse unlimited # maximum virtual memory size -endif # disable output in case of scp if ( $?prompt ) then @@ -44,8 +30,8 @@ if ( $?prompt ) then echo https://damask.mpie.de echo echo Using environment with ... - echo "DAMASK $DAMASK_ROOT $BRANCH" - echo "Spectral Solver $SOLVER" + echo "DAMASK $DAMASK_ROOT" + echo "Grid Solver $SOLVER" echo "Post Processing $PROCESSING" if ( $?PETSC_DIR) then echo "PETSc location $PETSC_DIR" diff --git a/env/DAMASK.sh b/env/DAMASK.sh index 1b4bea86a..50760b76d 100644 --- a/env/DAMASK.sh +++ b/env/DAMASK.sh @@ -43,15 +43,12 @@ PROCESSING=$(type -p postResults || true 2>/dev/null) [ "x$DAMASK_NUM_THREADS" == "x" ] && DAMASK_NUM_THREADS=1 -# currently, there is no information that unlimited causes problems +# currently, there is no information that unlimited stack size causes problems # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # more info https://jblevins.org/log/segfault # https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap -# http://superuser.com/questions/220059/what-parameters-has-ulimit -ulimit -d unlimited 2>/dev/null # maximum heap size (kB) +# http://superuser.com/questions/220059/what-parameters-has-ulimit ulimit -s unlimited 2>/dev/null # maximum stack size (kB) -ulimit -v unlimited 2>/dev/null # maximum virtual memory size -ulimit -m unlimited 2>/dev/null # maximum physical memory size # disable output in case of scp if [ ! -z "$PS1" ]; then @@ -62,7 +59,7 @@ if [ ! -z "$PS1" ]; then echo echo Using environment with ... echo "DAMASK $DAMASK_ROOT $BRANCH" - echo "Spectral Solver $SOLVER" + echo "Grid Solver $SOLVER" echo "Post Processing $PROCESSING" if [ "x$PETSC_DIR" != "x" ]; then echo -n "PETSc location " @@ -96,7 +93,7 @@ fi export DAMASK_NUM_THREADS export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH -for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN BRANCH; do +for var in BASE STAT SOLVER PROCESSING BRANCH; do unset "${var}" done for var in DAMASK MSC; do diff --git a/env/DAMASK.zsh b/env/DAMASK.zsh index 5449007f9..066d56dd6 100644 --- a/env/DAMASK.zsh +++ b/env/DAMASK.zsh @@ -24,7 +24,6 @@ unset -f set # add BRANCH if DAMASK_ROOT is a git repository cd $DAMASK_ROOT >/dev/null; BRANCH=$(git branch 2>/dev/null| grep -E '^\* '); cd - >/dev/null -# add DAMASK_BIN if present PATH=${DAMASK_ROOT}/bin:$PATH SOLVER=$(which DAMASK_spectral || true 2>/dev/null) @@ -35,15 +34,12 @@ PROCESSING=$(which postResults || true 2>/dev/null) [[ "x$DAMASK_NUM_THREADS" == "x" ]] && DAMASK_NUM_THREADS=1 -# currently, there is no information that unlimited causes problems +# currently, there is no information that unlimited stack size causes problems # still, http://software.intel.com/en-us/forums/topic/501500 suggest to fix it # more info https://jblevins.org/log/segfault # https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap -# http://superuser.com/questions/220059/what-parameters-has-ulimit -ulimit -d unlimited 2>/dev/null # maximum heap size (kB) +# http://superuser.com/questions/220059/what-parameters-has-ulimit ulimit -s unlimited 2>/dev/null # maximum stack size (kB) -ulimit -v unlimited 2>/dev/null # maximum virtual memory size -ulimit -m unlimited 2>/dev/null # maximum physical memory size # disable output in case of scp if [ ! -z "$PS1" ]; then @@ -54,7 +50,7 @@ if [ ! -z "$PS1" ]; then echo echo "Using environment with ..." echo "DAMASK $DAMASK_ROOT $BRANCH" - echo "Spectral Solver $SOLVER" + echo "Grid Solver $SOLVER" echo "Post Processing $PROCESSING" if [ "x$PETSC_DIR" != "x" ]; then echo -n "PETSc location " @@ -90,7 +86,7 @@ fi export DAMASK_NUM_THREADS export PYTHONPATH=$DAMASK_ROOT/python:$PYTHONPATH -for var in BASE STAT SOLVER PROCESSING FREE DAMASK_BIN BRANCH; do +for var in SOLVER PROCESSING BRANCH; do unset "${var}" done for var in DAMASK MSC; do diff --git a/examples/ConfigFiles/Homogenization_Thermal_Conduction.config b/examples/ConfigFiles/Homogenization_Thermal_Conduction.config index 48ad9ddc6..36fc7ea6e 100644 --- a/examples/ConfigFiles/Homogenization_Thermal_Conduction.config +++ b/examples/ConfigFiles/Homogenization_Thermal_Conduction.config @@ -1,3 +1,3 @@ thermal conduction -initialT 300.0 +t0 270.0 (output) temperature diff --git a/examples/SpectralMethod/EshelbyInclusion/material.config b/examples/SpectralMethod/EshelbyInclusion/material.config index e002584b0..d1ea80964 100644 --- a/examples/SpectralMethod/EshelbyInclusion/material.config +++ b/examples/SpectralMethod/EshelbyInclusion/material.config @@ -6,7 +6,7 @@ mech none # isostrain 1 grain thermal adiabatic # thermal strain (stress) induced mass transport -initialT 300.0 +t0 330.0 (output) temperature #-------------------# diff --git a/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 index 10a796e47..8adabaff1 100644 --- a/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2018.1/Marc_tools/include_linux64 @@ -99,14 +99,9 @@ else fi # DAMASK uses the HDF5 compiler wrapper around the Intel compiler -if test "$DAMASK_HDF5" = "ON";then - H5FC="$(h5fc -shlib -show)" - HDF5_LIB=${H5FC//ifort/} - FCOMP="$H5FC -DDAMASK_HDF5" - echo $FCOMP -else - FCOMP=ifort -fi +H5FC="$(h5fc -shlib -show)" +HDF5_LIB=${H5FC//ifort/} +FCOMP="$H5FC -DDAMASK_HDF5" # AEM if test "$MARCDLLOUTDIR" = ""; then diff --git a/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 index 694dccee3..c99313a30 100644 --- a/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2018/Marc_tools/include_linux64 @@ -99,14 +99,9 @@ else fi # DAMASK uses the HDF5 compiler wrapper around the Intel compiler -if test "$DAMASK_HDF5" = "ON";then - H5FC="$(h5fc -shlib -show)" - HDF5_LIB=${H5FC//ifort/} - FCOMP="$H5FC -DDAMASK_HDF5" - echo $FCOMP -else - FCOMP=ifort -fi +H5FC="$(h5fc -shlib -show)" +HDF5_LIB=${H5FC//ifort/} +FCOMP="$H5FC -DDAMASK_HDF5" # AEM if test "$MARCDLLOUTDIR" = ""; then diff --git a/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 b/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 index 6d630bd1d..2dba03961 100644 --- a/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 +++ b/installation/mods_MarcMentat/2019/Marc_tools/include_linux64 @@ -100,11 +100,9 @@ else fi # DAMASK uses the HDF5 compiler wrapper around the Intel compiler -if test "$DAMASK_HDF5" = "ON";then - H5FC="$(h5fc -shlib -show)" - HDF5_LIB=${H5FC//ifort/} - FCOMP="$H5FC -DDAMASK_HDF5" -fi +H5FC="$(h5fc -shlib -show)" +HDF5_LIB=${H5FC//ifort/} +FCOMP="$H5FC -DDAMASK_HDF5" # AEM if test "$MARCDLLOUTDIR" = ""; then diff --git a/processing/misc/ang_toTable.py b/processing/misc/ang_toTable.py index 19fdcd55b..5579f2466 100755 --- a/processing/misc/ang_toTable.py +++ b/processing/misc/ang_toTable.py @@ -1,8 +1,10 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- +#!/usr/bin/env python3 import os +import sys +from io import StringIO from optparse import OptionParser + import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -19,47 +21,10 @@ Convert TSL/EDAX *.ang file to ASCIItable """, version = scriptID) (options, filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.splitext(name)[0]+'.txt' if name else name, - buffered = False, labeled = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# --- interpret header ----------------------------------------------------------------------------- - - table.head_read() - -# --- read comments -------------------------------------------------------------------------------- - - table.info_clear() - while table.data_read(advance = False) and table.line.startswith('#'): # cautiously (non-progressing) read header - table.info_append(table.line) # add comment to info part - table.data_read() # wind forward - - table.labels_clear() - table.labels_append(['1_Euler','2_Euler','3_Euler', - '1_pos','2_pos', - 'IQ','CI','PhaseID','Intensity','Fit', - ], # OIM Analysis 7.2 Manual, p 403 (of 517) - reset = True) - -# ------------------------------------------ assemble header --------------------------------------- - - table.head_write() - -#--- write remainder of data file ------------------------------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): - outputAlive = table.data_write() - -# ------------------------------------------ finalize output --------------------------------------- - - table.close() + table = damask.Table.from_ang(StringIO(''.join(sys.stdin.read())) if name is None else name) + table.to_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'.txt') diff --git a/processing/misc/yieldSurface.py b/processing/misc/yieldSurface.py deleted file mode 100755 index 28f52062f..000000000 --- a/processing/misc/yieldSurface.py +++ /dev/null @@ -1,1431 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import threading,time,os -import numpy as np -from optparse import OptionParser -import damask -from damask.util import leastsqBound - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -def runFit(exponent, eqStress, dimension, criterion): - global threads, myFit, myLoad - global fitResidual - global Guess, dDim - - dDim = dimension - 3 - nParas = len(fitCriteria[criterion]['bound'][dDim]) - nExpo = fitCriteria[criterion]['nExpo'] - - if exponent > 0.0: # User defined exponents - nParas = nParas-nExpo - fitCriteria[criterion]['bound'][dDim] = fitCriteria[criterion]['bound'][dDim][:nParas] - - for i in range(nParas): - temp = fitCriteria[criterion]['bound'][dDim][i] - if fitCriteria[criterion]['bound'][dDim][i] == (None,None): - Guess.append(1.0) - else: - g = (temp[0]+temp[1])/2.0 - if g == 0: g = temp[1]*0.5 - Guess.append(g) - - myLoad = Loadcase(options.load[0],options.load[1],options.load[2], - nSet = 10, dimension = dimension, vegter = options.criterion=='vegter') - - - myFit = Criterion(exponent,eqStress, dimension, criterion) - for t in range(options.threads): - threads.append(myThread(t)) - threads[t].start() - - for t in range(options.threads): - threads[t].join() - damask.util.croak('Residuals') - damask.util.croak(fitResidual) - -def principalStresses(sigmas): - """ - Computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses. - - sorted in descending order. - """ - lambdas=np.zeros(0,'d') - for i in range(np.shape(sigmas)[1]): - eigenvalues = np.linalg.eigvalsh(sym6toT33(sigmas[:,i])) - lambdas = np.append(lambdas,np.sort(eigenvalues)[::-1]) #append eigenvalues in descending order - lambdas = np.transpose(lambdas.reshape(np.shape(sigmas)[1],3)) - return lambdas - -def principalStress(p): - I = invariant(p) - - I1s3I2= (I[0]**2 - 3.0*I[1])**0.5 - numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2] - denom = 2.0*I1s3I2**3 - cs = numer/denom - - phi = np.arccos(cs)/3.0 - t1 = I[0]/3.0; t2 = 2.0/3.0*I1s3I2 - return np.array( [t1 + t2*np.cos(phi), - t1 + t2*np.cos(phi+np.pi*2.0/3.0), - t1 + t2*np.cos(phi+np.pi*4.0/3.0)]) - -def principalStrs_Der(p, s, dim, Karafillis=False): - """Derivative of principal stress with respect to stress""" - third = 1.0/3.0 - third2 = 2.0*third - - I = invariant(p) - I1s3I2= np.sqrt(I[0]**2 - 3.0*I[1]) - numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2] - denom = 2.0*I1s3I2**3 - cs = numer/denom - phi = np.arccos(cs)/3.0 - - dphidcs = -third/np.sqrt(1.0 - cs**2) - dcsddenom = 0.5*numer*(-1.5)*I1s3I2**(-5.0) - dcsdI1 = (6.0*I[0]**2 - 9.0*I[1])*denom + dcsddenom*(2.0*I[0]) - dcsdI2 = ( - 9.0*I[0])*denom + dcsddenom*(-3.0) - dcsdI3 = 27.0*denom - dphidI1, dphidI2, dphidI3 = dphidcs*dcsdI1, dphidcs*dcsdI2, dphidcs*dcsdI3 - - dI1s3I2dI1 = I[0]/I1s3I2 - dI1s3I2dI2 = -1.5/I1s3I2 - tcoeff = third2*I1s3I2 - - dSidIj = lambda theta : ( tcoeff*(-np.sin(theta))*dphidI1 + third2*dI1s3I2dI1*np.cos(theta) + third, - tcoeff*(-np.sin(theta))*dphidI2 + third2*dI1s3I2dI2*np.cos(theta), - tcoeff*(-np.sin(theta))*dphidI3) - dSdI = np.array([dSidIj(phi),dSidIj(phi+np.pi*2.0/3.0),dSidIj(phi+np.pi*4.0/3.0)]) # i=1,2,3; j=1,2,3 - -# calculate the derivation of principal stress with regards to the anisotropic coefficients - one = np.ones_like(s); zero = np.zeros_like(s); num = len(s) - dIdp = np.array([[one, one, one, zero, zero, zero], - [p[1]+p[2], p[2]+p[0], p[0]+p[1], -2.0*p[3], -2.0*p[4], -2.0*p[5]], - [p[1]*p[2]-p[4]**2, p[2]*p[0]-p[5]**2, p[0]*p[1]-p[3]**2, - -2.0*p[3]*p[2]+2.0*p[4]*p[5], -2.0*p[4]*p[0]+2.0*p[5]*p[3], -2.0*p[5]*p[1]+2.0*p[3]*p[4]] ]) - if Karafillis: - dpdc = np.array([[zero,s[0]-s[2],s[0]-s[1]], [s[1]-s[2],zero,s[1]-s[0]], [s[2]-s[1],s[2]-s[0],zero]])/3.0 - dSdp = np.array([np.dot(dSdI[:,:,i],dIdp[:,:,i]).T for i in range(num)]).T - if dim == 2: - temp = np.vstack([dSdp[:,3]*s[3]]).T.reshape(num,1,3).T - else: - temp = np.vstack([dSdp[:,3]*s[3],dSdp[:,4]*s[4],dSdp[:,5]*s[5]]).T.reshape(num,3,3).T - - return np.concatenate((np.array([np.dot(dSdp[:,0:3,i], dpdc[:,:,i]).T for i in range(num)]).T, - temp), axis=1) - else: - if dim == 2: - dIdc=np.array([[-dIdp[i,0]*s[1], -dIdp[i,1]*s[0], -dIdp[i,1]*s[2], - -dIdp[i,2]*s[1], -dIdp[i,2]*s[0], -dIdp[i,0]*s[2], - dIdp[i,3]*s[3] ] for i in range(3)]) - else: - dIdc=np.array([[-dIdp[i,0]*s[1], -dIdp[i,1]*s[0], -dIdp[i,1]*s[2], - -dIdp[i,2]*s[1], -dIdp[i,2]*s[0], -dIdp[i,0]*s[2], - dIdp[i,3]*s[3], dIdp[i,4]*s[4], dIdp[i,5]*s[5] ] for i in range(3)]) - return np.array([np.dot(dSdI[:,:,i],dIdc[:,:,i]).T for i in range(num)]).T - -def invariant(sigmas): - I = np.zeros(3) - s11,s22,s33,s12,s23,s31 = sigmas - I[0] = s11 + s22 + s33 - I[1] = s11*s22 + s22*s33 + s33*s11 - s12**2 - s23**2 - s31**2 - I[2] = s11*s22*s33 + 2.0*s12*s23*s31 - s12**2*s33 - s23**2*s11 - s31**2*s22 - return I - -def math_ln(x): - return np.log(x + 1.0e-32) - -def sym6toT33(sym6): - """Shape the symmetric stress tensor(6) into (3,3)""" - return np.array([[sym6[0],sym6[3],sym6[5]], - [sym6[3],sym6[1],sym6[4]], - [sym6[5],sym6[4],sym6[2]]]) - -def t33toSym6(t33): - """Shape the stress tensor(3,3) into symmetric (6)""" - return np.array([ t33[0,0], - t33[1,1], - t33[2,2], - (t33[0,1] + t33[1,0])/2.0, # 0 3 5 - (t33[1,2] + t33[2,1])/2.0, # * 1 4 - (t33[2,0] + t33[0,2])/2.0,]) # * * 2 - -class Criteria(object): - def __init__(self, criterion, uniaxialStress,exponent, dimension): - self.stress0 = uniaxialStress - if exponent < 0.0: # Fitting exponent m - self.mFix = [False, exponent] - else: # fixed exponent m - self.mFix = [True, exponent] - self.func = fitCriteria[criterion]['func'] - self.criteria = criterion - self.dim = dimension - def fun(self, paras, ydata, sigmas): - return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim) - def jac(self, paras, ydata, sigmas): - return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim,Jac=True) - -class Vegter(object): - """Vegter yield criterion""" - - def __init__(self, refPts, refNormals,nspace=11): - self.refPts, self.refNormals = self._getRefPointsNormals(refPts, refNormals) - self.hingePts = self._getHingePoints() - self.nspace = nspace - def _getRefPointsNormals(self,refPtsQtr,refNormalsQtr): - if len(refPtsQtr) == 12: - refPts = refPtsQtr - refNormals = refNormalsQtr - else: - refPts = np.empty([13,2]) - refNormals = np.empty([13,2]) - refPts[12] = refPtsQtr[0] - refNormals[12] = refNormalsQtr[0] - for i in range(3): - refPts[i] = refPtsQtr[i] - refPts[i+3] = refPtsQtr[3-i][::-1] - refPts[i+6] =-refPtsQtr[i] - refPts[i+9] =-refPtsQtr[3-i][::-1] - refNormals[i] = refNormalsQtr[i] - refNormals[i+3] = refNormalsQtr[3-i][::-1] - refNormals[i+6] =-refNormalsQtr[i] - refNormals[i+9] =-refNormalsQtr[3-i][::-1] - return refPts,refNormals - - def _getHingePoints(self): - """ - Calculate the hinge point B according to the reference points A,C and the normals n,m - - refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]); - refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]]) - """ - def hingPoint(points, normals): - A1 = points[0][0]; A2 = points[0][1] - C1 = points[1][0]; C2 = points[1][1] - n1 = normals[0][0]; n2 = normals[0][1] - m1 = normals[1][0]; m2 = normals[1][1] - B1 = (m2*(n1*A1 + n2*A2) - n2*(m1*C1 + m2*C2))/(n1*m2-m1*n2) - B2 = (n1*(m1*C1 + m2*C2) - m1*(n1*A1 + n2*A2))/(n1*m2-m1*n2) - return np.array([B1,B2]) - return np.array([hingPoint(self.refPts[i:i+2],self.refNormals[i:i+2]) for i in range(len(self.refPts)-1)]) - - def getBezier(self): - def bezier(R,H): - b = [] - for mu in np.linspace(0.0,1.0,self.nspace): - b.append(np.array(R[0]*np.ones_like(mu) + 2.0*mu*(H - R[0]) + mu**2*(R[0]+R[1] - 2.0*H))) - return b - return np.array([bezier(self.refPts[i:i+2],self.hingePts[i]) for i in range(len(self.refPts)-1)]) - -def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0): - """0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial""" - def getFourierParas(r): - # get the value after Fourier transformation - nset = len(r) - lmatrix = np.empty([nset,nset]) - theta = np.linspace(0.0,np.pi/2,nset) - for i,th in enumerate(theta): - lmatrix[i] = np.array([np.cos(2*j*th) for j in range(nset)]) - return np.linalg.solve(lmatrix, r) - - nps = len(stress) - if nps%4 != 0: - damask.util.croak('Warning: the number of stress points is uncorrect, stress points of %s are missing in set %i'%( - ['eq-biaxial, plane strain & uniaxial', 'eq-biaxial & plane strain','eq-biaxial'][nps%4-1],nps/4+1)) - else: - nset = nps/4 - strsSet = stress.reshape(nset,4,2) - refPts = np.empty([4,2]) - - fouriercoeffs = np.array([np.cos(2.0*i*theta) for i in range(nset)]) - for i in range(2): - refPts[3,i] = sum(strsSet[:,3,i])/nset - for j in range(3): - refPts[j,i] = np.dot(getFourierParas(strsSet[:,j,i]), fouriercoeffs) - - -def Tresca(eqStress=None, #not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None, #not needed/supported - dim=3, - Jac=False): - """ - Tresca yield criterion - - the fitted parameter is paras(sigma0) - """ - if not Jac: - lambdas = principalStresses(sigmas) - r = np.amax(np.array([abs(lambdas[2,:]-lambdas[1,:]),\ - abs(lambdas[1,:]-lambdas[0,:]),\ - abs(lambdas[0,:]-lambdas[2,:])]),0) - paras - return r.ravel() - else: - return -np.ones(len(sigmas)) - -def Cazacu_Barlat(eqStress=None, - paras=None, - sigmas=None, - mFix=None,#not needed/supported - criteria=None, - dim=3, #2D also possible - Jac=False): - """ - Cazacu-Barlat (CB) yield criterion - - the fitted parameters are: - a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress - a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case - mFix is ignored - """ - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: - (a1,a2,a3,a4), (b1,b2,b3,b4,b5,b10), c = paras[0:4],paras[4:10],paras[10] - a5 = a6 = b6 = b7 = b8 = b9 = b11 = 0.0 - s33 = s23 = s31 = np.zeros_like(s11) - else: - (a1,a2,a3,a4,a5,a6), (b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11), c = paras[0:6],paras[6:17],paras[17] - - s1_2, s2_2, s3_2, s12_2, s23_2, s31_2 = np.array([s11,s22,s33,s12,s23,s31])**2 - s1_3, s2_3, s3_3, s123, s321 = s11*s1_2, s22*s2_2, s33*s3_2,s11*s22*s33, s12*s23*s31 - d12_2,d23_2,d31_2 = (s11-s22)**2, (s22-s33)**2, (s33-s11)**2 - - J20 = ( a1*d12_2 + a2*d23_2 + a3*d31_2 )/6.0 + a4*s12_2 + a5*s23_2 + a6*s31_2 - J30 = ( (b1 +b2 )*s1_3 + (b3 +b4 )*s2_3 + ( b1+b4-b2 + b1+b4-b3 )*s3_3 )/27.0- \ - ( (b1*s22+b2*s33)*s1_2 + (b3*s33+b4*s11)*s2_2 + ((b1+b4-b2)*s11 + (b1+b4-b3)*s22)*s3_2 )/9.0 + \ - ( (b1+b4)*s123/9.0 + b11*s321 )*2.0 - \ - ( ( 2.0*b9 *s22 - b8*s33 - (2.0*b9 -b8)*s11 )*s31_2 + - ( 2.0*b10*s33 - b5*s22 - (2.0*b10-b5)*s11 )*s12_2 + - ( (b6+b7)*s11 - b6*s22 - b7*s33 )*s23_2 - )/3.0 - f0 = J20**3 - c*J30**2 - r = f0**(1.0/6.0)*np.sqrt(3.0)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - drdf = r/f0/6.0 - dj2, dj3 = drdf*3.0*J20**2, -drdf*2.0*J30*c - jc = -drdf*J30**2 - - ja1,ja2,ja3 = dj2*d12_2/6.0, dj2*d23_2/6.0, dj2*d31_2/6.0 - ja4,ja5,ja6 = dj2*s12_2, dj2*s23_2, dj2*s31_2 - jb1 = dj3*( (s1_3 + 2.0*s3_3)/27.0 - s22*s1_2/9.0 - (s11+s22)*s3_2/9.0 + s123/4.5 ) - jb2 = dj3*( (s1_3 - s3_3)/27.0 - s33*s1_2/9.0 + s11 *s3_2/9.0 ) - jb3 = dj3*( (s2_3 - s3_3)/27.0 - s33*s2_2/9.0 + s22 *s3_2/9.0 ) - jb4 = dj3*( (s2_3 + 2.0*s3_3)/27.0 - s11*s2_2/9.0 - (s11+s22)*s3_2/9.0 + s123/4.5 ) - - jb5, jb10 = dj3*(s22 - s11)*s12_2/3.0, dj3*(s11 - s33)*s12_2/1.5 - jb6, jb7 = dj3*(s22 - s11)*s23_2/3.0, dj3*(s33 - s11)*s23_2/3.0 - jb8, jb9 = dj3*(s33 - s11)*s31_2/3.0, dj3*(s11 - s22)*s31_2/1.5 - jb11 = dj3*s321*2.0 - if dim == 2: - return np.vstack((ja1,ja2,ja3,ja4,jb1,jb2,jb3,jb4,jb5,jb10,jc)).T - else: - return np.vstack((ja1,ja2,ja3,ja4,ja5,ja6,jb1,jb2,jb3,jb4,jb5,jb6,jb7,jb8,jb9,jb10,jb11,jc)).T - -def Drucker(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None, - dim=3, - Jac=False): - """ - Drucker yield criterion - - the fitted parameters are - sigma0, C_D for Drucker(p=1); - sigma0, C_D, p for general Drucker - eqStress, mFix are invalid inputs - """ - if criteria == 'drucker': - sigma0, C_D= paras - p = 1.0 - else: - sigma0, C_D = paras[0:2] - if mFix[0]: p = mFix[1] - else: p = paras[-1] - I = invariant(sigmas) - J = np.zeros([3]) - J[1] = I[0]**2/3.0 - I[1] - J[2] = I[0]**3/13.5 - I[0]*I[1]/3.0 + I[2] - J2_3p = J[1]**(3.0*p) - J3_2p = J[2]**(2.0*p) - left = J2_3p - C_D*J3_2p - r = left**(1.0/(6.0*p))*3.0**0.5/sigma0 - - if not Jac: - return (r - 1.0).ravel() - else: - drdl = r/left/(6.0*p) - if criteria == 'drucker': - return np.vstack((-r/sigma0, -drdl*J3_2p)).T - else: - dldp = 3.0*J2_3p*math_ln(J[1]) - 2.0*C_D*J3_2p*math_ln(J[2]) - jp = drdl*dldp + r*math_ln(left)/(-6.0*p*p) - - if mFix[0]: return np.vstack((-r/sigma0, -drdl*J3_2p)).T - else: return np.vstack((-r/sigma0, -drdl*J3_2p, jp)).T - -def Hill1948(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None,#not needed/supported - dim=3, - Jac=False): - """ - Hill 1948 yield criterion - - the fitted parameters are: - F, G, H, L, M, N for 3D - F, G, H, N for 2D - """ - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: # plane stress - jac = np.array([ s22**2, s11**2, (s11-s22)**2, 2.0*s12**2]) - else: # general case - jac = np.array([(s22-s33)**2,(s33-s11)**2,(s11-s22)**2, 2.0*s23**2,2.0*s31**2,2.0*s12**2]) - - if not Jac: - return (np.dot(paras,jac)/2.0-0.5).ravel() - else: - return jac.T - -def Hill1979(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, - criteria=None,#not needed/supported - dim=3, - Jac=False): - """ - Hill 1979 yield criterion - - the fitted parameters are: f,g,h,a,b,c,m - """ - if mFix[0]: - m = mFix[1] - else: - m = paras[-1] - - coeff = paras[0:6] - s = principalStresses(sigmas) - diffs = np.array([s[1]-s[2], s[2]-s[0], s[0]-s[1],\ - 2.0*s[0]-s[1]-s[2], 2.0*s[1]-s[2]-s[0], 2.0*s[2]-s[0]-s[1]])**2 - - diffsm = diffs**(m/2.0) - left = np.dot(coeff,diffsm) - r = (0.5*left)**(1.0/m)/eqStress #left = base**mi - - if not Jac: - return (r-1.0).ravel() - else: - drdl, dldm = r/left/m, np.dot(coeff,diffsm*math_ln(diffs))*0.5 - jm = drdl*dldm + r*math_ln(0.5*left)*(-1.0/m/m) #/(-m**2) - - if mFix[0]: return np.vstack((drdl*diffsm)).T - else: return np.vstack((drdl*diffsm, jm)).T - -def Hosford(eqStress=None, - paras=None, - sigmas=None, - mFix=None, - criteria=None, - dim=3, - Jac=False): - """ - Hosford family criteria - - the fitted parameters are: - von Mises: sigma0 - Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed - general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed - """ - if criteria == 'vonmises': - sigma0 = paras - coeff = np.ones(3) - a = 2.0 - elif criteria == 'hershey': - sigma0 = paras[0] - coeff = np.ones(3) - if mFix[0]: a = mFix[1] - else: a = paras[1] - else: - sigma0 = eqStress - coeff = paras[0:3] - if mFix[0]: a = mFix[1] - else: a = paras[3] - - s = principalStresses(sigmas) - diffs = np.array([s[1]-s[2], s[2]-s[0], s[0]-s[1]])**2 - diffsm = diffs**(a/2.0) - left = np.dot(coeff,diffsm) - r = (0.5*left)**(1.0/a)/sigma0 - - if not Jac: - return (r-1.0).ravel() - else: - if criteria == 'vonmises': # von Mises - return -r/sigma0 - else: - drdl, dlda = r/left/a, np.dot(coeff,diffsm*math_ln(diffs))*0.5 - ja = drdl*dlda + r*math_ln(0.5*left)*(-1.0/a/a) - if criteria == 'hershey': # Hershey - if mFix[0]: return -r/sigma0 - else: return np.vstack((-r/sigma0, ja)).T - else: # Anisotropic Hosford - if mFix[0]: return np.vstack((drdl*diffsm)).T - else: return np.vstack((drdl*diffsm, ja)).T - -def Barlat1989(eqStress=None, - paras=None, - sigmas=None, - mFix=None, - criteria=None, - dim=3, - Jac=False): - """ - Barlat-Lian 1989 yield criteria - - the fitted parameters are: - Anisotropic: a, h, p, m; m is optional - """ - a, h, p = paras[0:3] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - c = 2.0-a - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k1,k2 = 0.5*(s11 + h*s22), (0.25*(s11 - h*s22)**2 + (p*s12)**2)**0.5 - fs = np.array([ (k1+k2)**2, (k1-k2)**2, 4.0*k2**2 ]); fm = fs**(m/2.0) - left = np.dot(np.array([a,a,c]),fm) - r = (0.5*left)**(1.0/m)/eqStress - - if not Jac: - return (r-1.0).ravel() - else: - dk1dh = 0.5*s22 - dk2dh, dk2dp = 0.25*(s11-h*s22)*(-s22)/k2, p*s12**2/k2 - dlda, dldc = fm[0]+fm[1], fm[2] - fm1 = fs**(m/2.0-1.0)*m - dldk1, dldk2 = a*fm1[0]*(k1+k2)+a*fm1[1]*(k1-k2), a*fm1[0]*(k1+k2)-a*fm1[1]*(k1-k2)+c*fm1[2]*k2*4.0 - drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) - dldm = np.dot(np.array([a,a,c]),fm*math_ln(fs))*0.5 - - ja,jc = drdl*dlda, drdl*dldc - jh,jp = drdl*(dldk1*dk1dh + dldk2*dk2dh), drdl*dldk2*dk2dp - jm = drdl*dldm + drdm - - if mFix[0]: return np.vstack((ja,jc,jh,jp)).T - else: return np.vstack((ja,jc,jh,jp,jm)).T - -def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Barlat 1991 criteria - - the fitted parameters are: - Anisotropic: a, b, c, f, g, h, m for 3D - a, b, c, h, m for plane stress - m is optional - """ - if dim == 2: coeff = paras[0:4] # plane stress - else: coeff = paras[0:6] # general case - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: - dXdx = np.array([s22,-s11,s11-s22,s12]) - A,B,C,H = np.array(coeff)[:,None]*dXdx; F=G=0.0 - else: - dXdx = np.array([s22-s33,s33-s11,s11-s22,s23,s31,s12]) - A,B,C,F,G,H = np.array(coeff)[:,None]*dXdx - - I2 = (F*F + G*G + H*H)/3.0+ ((A-C)**2+(C-B)**2+(B-A)**2)/54.0 - I3 = (C-B)*(A-C)*(B-A)/54.0 + F*G*H - ((C-B)*F*F + (A-C)*G*G + (B-A)*H*H)/6.0 - phi1 = np.arccos(I3/I2**1.5)/3.0 + np.pi/6.0; absc1 = 2.0*np.abs(np.cos(phi1)) - phi2 = phi1 + np.pi/3.0; absc2 = 2.0*np.abs(np.cos(phi2)) - phi3 = phi2 + np.pi/3.0; absc3 = 2.0*np.abs(np.cos(phi3)) - left = ( absc1**m + absc2**m + absc3**m ) - r = (0.5*left)**(1.0/m)*np.sqrt(3.0*I2)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - dfdl = r/left/m - jm = r*math_ln(0.5*left)*(-1.0/m/m) + dfdl*0.5*( - absc1**m*math_ln(absc1) + absc2**m*math_ln(absc2) + absc3**m*math_ln(absc3) ) - - da,db,dc = (2.0*A-B-C)/18.0, (2.0*B-C-A)/18.0, (2.0*C-A-B)/18.0 - if dim == 2: - dI2dx = np.array([da, db, dc, H])/1.5*dXdx - dI3dx = np.array([ da*(B-C) + (H**2-G**2)/2.0, - db*(C-A) + (F**2-H**2)/2.0, - dc*(A-B) + (G**2-F**2)/2.0, - (G*F + (A-B))*H ])/3.0*dXdx - else: - dI2dx = np.array([da, db, dc, F,G,H])/1.5*dXdx - dI3dx = np.array([ da*(B-C) + (H**2-G**2)/2.0, - db*(C-A) + (F**2-H**2)/2.0, - dc*(A-B) + (G**2-F**2)/2.0, - (H*G*3.0 + (B-C))*F, - (F*H*3.0 + (C-A))*G, - (G*F*3.0 + (A-B))*H ])/3.0*dXdx - darccos = -1.0/np.sqrt(1.0 - I3**2/I2**3) - - dfdcos = lambda phi : dfdl*m*(2.0*abs(np.cos(phi)))**(m-1.0)*np.sign(np.cos(phi))*(-np.sin(phi)/1.5) - - dfdthe= (dfdcos(phi1) + dfdcos(phi2) + dfdcos(phi3)) - dfdI2, dfdI3 = dfdthe*darccos*I3*(-1.5)*I2**(-2.5)+r/2.0/I2, dfdthe*darccos*I2**(-1.5) - - if mFix[0]: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx)).T - else: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx, jm)).T - -def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2000 yield criterion - - the fitted parameters are - d,e,f,g, b,c,a, k; k is optional - criteria are invalid input - """ - d,e,f,g, b,c,a= paras[0:7] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k2 = 2.0*k; k1 = k - 1.0 - M,N,P,Q,R = d+e, e+f, (d-e)/2.0, (e-f)/2.0, g**2 - Gamma = M*s11 + N*s22 - Psi = ( (P*s11 + Q*s22)**2 + s12**2*R )**0.5 - - l1, l2, l3 = b*Gamma + c*Psi, b*Gamma - c*Psi, 2.0*c*Psi - l1s,l2s,l3s = l1**2, l2**2, l3**2 - - left = a*l1s**k + a*l2s**k + (1-a)*l3s**k - r = left**(1.0/k2)/eqStress - if not Jac: - return (r - 1.0).ravel() - else: - drdl,drdk = r/left/k2, r*math_ln(left)*(-1.0/k2/k) - dldl1,dldl2,dldl3 = a*k2*(l1s**k1)*l1, a*k2*(l2s**k1)*l2, (1-a)*k2*(l3s**k1)*l3 - dldGama, dldPsi = (dldl1 + dldl2)*b, (dldl1 - dldl2 + 2.0*dldl3)*c - temp = (P*s11 + Q*s22)/Psi - dPsidP, dPsidQ, dPsidR = temp*s11, temp*s22, 0.5*s12**2/Psi - dlda = l1s**k + l2s**k - l3s**k - dldb = dldl1*Gamma + dldl2*Gamma - dldc = dldl1*Psi - dldl2*Psi + dldl3*2.0*Psi - dldk = a*math_ln(l1s)*l1s**k + a*math_ln(l2s)*l2s**k + (1-a)*math_ln(l3s)*l3s**k - - J = drdl*np.array([dldGama*s11+dldPsi*dPsidP*0.5, dldGama*(s11+s22)+dldPsi*(-dPsidP+dPsidQ)*0.5, #jd,je - dldGama*s22-dldPsi*dPsidQ*0.5, dldPsi*dPsidR*2.0*g, #jf,jg - dldb, dldc, dlda]) #jb,jc,ja - if mFix[0]: return np.vstack(J).T - else: return np.vstack((J, drdl*dldk + drdk)).T - - -def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2003 yield criterion - - the fitted parameters are - M,N,P,Q,R,S,T,a, k; k is optional - criteria are invalid input - """ - M,N,P,Q,R,S,T,a = paras[0:8] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k2 = 2.0*k; k1 = k - 1.0 - Gamma = 0.5 * (s11 + M*s22) - Psi = ( 0.25*(N*s11 - P*s22)**2 + Q*Q*s12**2 )**0.5 - Lambda = ( 0.25*(R*s11 - S*s22)**2 + T*T*s12**2 )**0.5 - - l1, l2, l3 = Gamma + Psi, Gamma - Psi, 2.0*Lambda - l1s,l2s,l3s = l1**2, l2**2, l3**2 - left = a*l1s**k + a*l2s**k + (1-a)*l3s**k - r = left**(1.0/k2)/eqStress - if not Jac: - return (r - 1.0).ravel() - else: - drdl,drdk = r/left/k2, r*math_ln(left)*(-1.0/k2/k) - dldl1,dldl2,dldl3 = a*k2*(l1s**k1)*l1, a*k2*(l2s**k1)*l2, (1-a)*k2*(l3s**k1)*l3 - - dldGamma, dldPsi, dldLambda = dldl1+dldl2, dldl1-dldl2, 2.0*dldl3 - temp = 0.25/Psi*(N*s11 - P*s22) - dPsidN, dPsidP, dPsidQ = s11*temp, -s22*temp, Q*s12**2/Psi - temp = 0.25/Lambda*(R*s11 - S*s22) - dLambdadR, dLambdadS, dLambdadT = s11*temp, -s22*temp, T*s12**2/Psi - dldk = a*math_ln(l1s)*l1s**k + a*math_ln(l2s)*l2s**k + (1-a)*math_ln(l3s)*l3s**k - - J = drdl * np.array([dldGamma*s22*0.5, #jM - dldPsi*dPsidN, dldPsi*dPsidP, dldPsi*dPsidQ, #jN, jP, jQ - dldLambda*dLambdadR, dldLambda*dLambdadS, dldLambda*dLambdadT, #jR, jS, jT - l1s**k + l2s**k - l3s**k ]) #ja - - if mFix[0]: return np.vstack(J).T - else : return np.vstack((J, drdl*dldk+drdk)).T - -def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2005 yield criterion - - the fitted parameters are - a, b, L ,M, N, P, Q, R, k k are optional - criteria is invalid input - """ - a,b,L, M, N, P, Q, R = paras[0:8] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11 = sigmas[0]; s22 = sigmas[1]; s12 = sigmas[3] - k2 = 2.0*k - Gamma = L*s11 + M*s22 - Lambda = ( (N*s11 - P*s22)**2 + s12**2 )**0.5 - Psi = ( (Q*s11 - R*s22)**2 + s12**2 )**0.5 - - l1 = Lambda + Gamma; l2 = Lambda - Gamma; l3 = Lambda + Psi; l4 = Lambda - Psi - l1s = l1**2; l2s = l2**2; l3s = l3**2; l4s = l4**2 - left = a*l1s**k + a*l2s**k + b*l3s**k + b*l4s**k - sBar = left**(1.0/k2); r = sBar/eqStress - 1.0 - if not Jac: - return r.ravel() - else: - ln = lambda x : np.log(x + 1.0e-32) - expo = 0.5/k; k1 = k-1.0 - - dsBardl = expo*sBar/left/eqStress - dsBarde = sBar*ln(left); dedk = expo/(-k) - dldl1 = a*k*(l1s**k1)*(2.0*l1) - dldl2 = a*k*(l2s**k1)*(2.0*l2) - dldl3 = b*k*(l3s**k1)*(2.0*l3) - dldl4 = b*k*(l4s**k1)*(2.0*l4) - - dldLambda = dldl1 + dldl2 + dldl3 + dldl4 - dldGama = dldl1 - dldl2 - dldPsi = dldl3 - dldl4 - temp = (N*s11 - P*s22)/Lambda - dLambdadN = s11*temp; dLambdadP = -s22*temp - temp = (Q*s11 - R*s22)/Psi - dPsidQ = s11*temp; dPsidR = -s22*temp - dldk = a*ln(l1s)*l1s**k + a*ln(l2s)*l2s**k + b*ln(l3s)*l3s**k + b*ln(l4s)*l4s**k - - J = dsBardl * np.array( [ - l1s**k+l2s**k, l3s**k+l4s**k,dldGama*s11,dldGama*s22,dldLambda*dLambdadN, - dldLambda*dLambdadP, dldPsi*dPsidQ, dldPsi*dPsidR]) - - if mFix[0]: return np.vstack(J).T - else : return np.vstack(J, dldk+dsBarde*dedk).T - -def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Yld2000 yield criterion - - C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS - D: d11,d12,d21,d22,d66 - """ - C,D = paras[0:3], paras[3:8] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - s11, s22, s12 = sigmas[0],sigmas[1],sigmas[3] - X = np.array([ 2.0*C[0]*s11-C[0]*s22, 2.0*C[1]*s22-C[1]*s11, 3.0*C[2]*s12 ])/3.0 # a1,a2,a7 - Y = np.array([ (8.0*D[2]-2.0*D[0]-2.0*D[3]+2.0*D[1])*s11 + (4.0*D[3]-4.0*D[1]-4.0*D[2]+ D[0])*s22, - (4.0*D[0]-4.0*D[2]-4.0*D[1]+ D[3])*s11 + (8.0*D[1]-2.0*D[3]-2.0*D[0]+2.0*D[2])*s22, - 9.0*D[4]*s12 ])/9.0 - - def priStrs(s): - temp = np.sqrt( (s[0]-s[1])**2 + 4.0*s[2]**2 ) - return 0.5*(s[0]+s[1] + temp), 0.5*(s[0]+s[1] - temp) - m2 = m/2.0; m21 = m2 - 1.0 - (X1,X2), (Y1,Y2) = priStrs(X), priStrs(Y) # Principal values of X, Y - phi1s, phi21s, phi22s = (X1-X2)**2, (2.0*Y2+Y1)**2, (2.0*Y1+Y2)**2 - phi1, phi21, phi22 = phi1s**m2, phi21s**m2, phi22s**m2 - left = phi1 + phi21 + phi22 - r = (0.5*left)**(1.0/m)/eqStress - - if not Jac: - return (r-1.0).ravel() - else: - drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) #/(-m*m) - dldm = ( phi1*math_ln(phi1s) + phi21*math_ln(phi21s) + phi22*math_ln(phi22s) )*0.5 - zero = np.zeros_like(s11); num = len(s11) - def dPrincipalds(X): - """Derivative of principla with respect to stress""" - temp = 1.0/np.sqrt( (X[0]-X[1])**2 + 4.0*X[2]**2 ) - dP1dsi = 0.5*np.array([ 1.0+temp*(X[0]-X[1]), 1.0-temp*(X[0]-X[1]), temp*4.0*X[2]]) - dP2dsi = 0.5*np.array([ 1.0-temp*(X[0]-X[1]), 1.0+temp*(X[0]-X[1]), -temp*4.0*X[2]]) - return np.array([dP1dsi, dP2dsi]) - - dXdXi, dYdYi = dPrincipalds(X), dPrincipalds(Y) - dXidC = np.array([ [ 2.0*s11-s22, zero, zero ], #dX11dC - [ zero, 2.0*s22-s11, zero ], #dX22dC - [ zero, zero, 3.0*s12 ] ])/3.0 #dX12dC - dYidD = np.array([ [ -2.0*s11+ s22, 2.0*s11-4.0*s22, 8.0*s11-4.0*s22, -2.0*s11+4.0*s22, zero ], #dY11dD - [ 4.0*s11-2.0*s22, -4.0*s11+8.0*s22, -4.0*s11+2.0*s22, s11-2.0*s22, zero ], #dY22dD - [ zero, zero, zero, zero, 9.0*s12 ] ])/9.0 #dY12dD - - dXdC=np.array([np.dot(dXdXi[:,:,i], dXidC[:,:,i]).T for i in range(num)]).T - dYdD=np.array([np.dot(dYdYi[:,:,i], dYidD[:,:,i]).T for i in range(num)]).T - - dldX = m*np.array([ phi1s**m21*(X1-X2), phi1s**m21*(X2-X1)]) - dldY = m*np.array([phi21s**m21*(2.0*Y2+Y1) + 2.0*phi22s**m21*(2.0*Y1+Y2), \ - phi22s**m21*(2.0*Y1+Y2) + 2.0*phi21s**m21*(2.0*Y2+Y1) ]) - jC = drdl*np.array([np.dot(dldX[:,i], dXdC[:,:,i]) for i in range(num)]).T - jD = drdl*np.array([np.dot(dldY[:,i], dYdD[:,:,i]) for i in range(num)]).T - - jm = drdl*dldm + drdm - if mFix[0]: return np.vstack((jC,jD)).T - else: return np.vstack((jC,jD,jm)).T - -def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Yld2004-18p yield criterion - - the fitted parameters are - C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D - C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D - and m, m are optional - criteria is ignored - """ - if dim == 2: C,D = np.append(paras[0:7],[0.0,0.0]), np.append(paras[7:14],[0.0,0.0]) - else: C,D = paras[0:9], paras[9:18] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - sv = (sigmas[0] + sigmas[1] + sigmas[2])/3.0 - sdev = np.vstack((sigmas[0:3]-sv,sigmas[3:6])) - ys = lambda sdev, C: np.array([-C[0]*sdev[1]-C[5]*sdev[2], -C[1]*sdev[0]-C[2]*sdev[2], - -C[4]*sdev[0]-C[3]*sdev[1], C[6]*sdev[3], C[7]*sdev[4], C[8]*sdev[5]]) - p,q = ys(sdev, C), ys(sdev, D) - pLambdas, qLambdas = principalStress(p), principalStress(q) # no sort - - m2 = m/2.0; x3 = range(3); num = len(sv) - PiQj = np.array([(pLambdas[i,:]-qLambdas[j,:]) for i in x3 for j in x3]) - QiPj = np.array([(qLambdas[i,:]-pLambdas[j,:]) for i in x3 for j in x3]).reshape(3,3,num) - PiQjs = PiQj**2 - left = np.sum(PiQjs**m2,axis=0) - r = (0.25*left)**(1.0/m)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - drdl, drdm = r/m/left, r*math_ln(0.25*left)*(-1.0/m/m) - dldm = np.sum(PiQjs**m2*math_ln(PiQjs),axis=0)*0.5 - dPdc, dQdd = principalStrs_Der(p, sdev, dim), principalStrs_Der(q, sdev, dim) - PiQjs3d = ( PiQjs**(m2-1.0) ).reshape(3,3,num) - dldP = -m*np.array([np.diag(np.dot(PiQjs3d[:,:,i], QiPj [:,:,i])) for i in range(num)]).T - dldQ = m*np.array([np.diag(np.dot(QiPj [:,:,i], PiQjs3d[:,:,i])) for i in range(num)]).T - - jm = drdl*dldm + drdm - jc = drdl*np.sum([dldP[i]*dPdc[i] for i in x3],axis=0) - jd = drdl*np.sum([dldQ[i]*dQdd[i] for i in x3],axis=0) - - if mFix[0]: return np.vstack((jc,jd)).T - else: return np.vstack((jc,jd,jm)).T - -def KarafillisBoyce(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Karafillis-Boyce - - the fitted parameters are - c11,c12,c13,c14,c15,c16,c,m for 3D - c11,c12,c13,c14,c,m for plane stress - 0 1 and self.dimen == 2: - return fitCriteria[self.name]['labels'][1] - else: - return fitCriteria[self.name]['labels'][0] - - def report_name(self): - return fitCriteria[self.name]['name'] - - def fit(self,stress): - global fitResults; fitErrors; fitResidual - if options.exponent > 0.0: nExponent = options.exponent - else: nExponent = 0 - nameCriterion = self.name.lower() - criteria = Criteria(nameCriterion,self.uniaxial,self.expo, self.dimen) - bounds = fitCriteria[nameCriterion]['bound'][dDim] # Default bounds, no bound - guess0 = Guess # Default initial guess, depends on bounds - - if fitResults == []: - initialguess = guess0 - else: - initialguess = np.array(fitResults[-1]) - - ydata = np.zeros(np.shape(stress)[1]) - try: - popt, pcov, infodict, errmsg, ierr = \ - leastsqBound (criteria.fun, initialguess, args=(ydata,stress), - bounds=bounds, Dfun=criteria.jac, full_output=True) - if ierr not in [1, 2, 3, 4]: - raise RuntimeError("Optimal parameters not found: "+errmsg) - else: - residual = criteria.fun(popt, ydata, stress) - fitResidual.append(np.linalg.norm(residual)/np.sqrt(len(residual))) - if (len(ydata) > len(initialguess)) and pcov is not None: - s_sq = (criteria.fun(popt, *(ydata,stress))**2).sum()/(len(ydata)-len(initialguess)) - pcov = pcov * s_sq - perr = np.sqrt(np.diag(pcov)) - fitResults.append(popt.tolist()) - fitErrors .append(perr.tolist()) - - popt = np.concatenate((np.array(popt), np.repeat(options.exponent,nExponent))) - perr = np.concatenate((np.array(perr), np.repeat(0.0,nExponent))) - - damask.util.croak('Needed {} function calls for fitting'.format(infodict['nfev'])) - except Exception as detail: - damask.util.croak(detail) - pass - return popt - -#--------------------------------------------------------------------------------------------------- -class myThread (threading.Thread): - """Runner""" - - def __init__(self, threadID): - threading.Thread.__init__(self) - self.threadID = threadID - def run(self): - semaphore.acquire() - conv=converged() - semaphore.release() - while not conv: - doSim(self.name) - semaphore.acquire() - conv=converged() - semaphore.release() - -def doSim(thread): - semaphore.acquire() - global myLoad - loadNo=loadcaseNo() - if not os.path.isfile('%s.load'%loadNo): - damask.util.croak('Generating load case for simulation %s (%s)'%(loadNo,thread)) - f=open('%s.load'%loadNo,'w') - f.write(myLoad.getLoadcase(loadNo)) - f.close() - semaphore.release() - else: semaphore.release() - -# if spectralOut does not exist, run simulation - semaphore.acquire() - if not os.path.isfile('%s_%i.spectralOut'%(options.geometry,loadNo)): - damask.util.croak('Starting simulation %i (%s)'%(loadNo,thread)) - semaphore.release() - damask.util.execute('DAMASK_spectral -g %s -l %i'%(options.geometry,loadNo)) - else: semaphore.release() - -# if ASCII tables do not exist, run postprocessing - semaphore.acquire() - if not os.path.isfile('./postProc/%s_%i.txt'%(options.geometry,loadNo)): - damask.util.croak('Starting post processing for simulation %i (%s)'%(loadNo,thread)) - semaphore.release() - try: - damask.util.execute('postResults --cr f,p --co totalshear %s_%i.spectralOut'%(options.geometry,loadNo)) - except: - damask.util.execute('postResults --cr f,p %s_%i.spectralOut'%(options.geometry,loadNo)) - damask.util.execute('addCauchy ./postProc/%s_%i.txt'%(options.geometry,loadNo)) - damask.util.execute('addStrainTensors -0 -v ./postProc/%s_%i.txt'%(options.geometry,loadNo)) - damask.util.execute('addMises -s Cauchy -e ln(V) ./postProc/%s_%i.txt'%(options.geometry,loadNo)) - else: semaphore.release() - -# reading values from ASCII table (including linear interpolation between points) - semaphore.acquire() - damask.util.croak('Reading values from simulation %i (%s)'%(loadNo,thread)) - refFile = './postProc/%s_%i.txt'%(options.geometry,loadNo) - table = damask.ASCIItable(refFile,readonly=True) - table.head_read() - - thresholdKey = {'equivalentStrain':'Mises(ln(V))', - 'totalshear': 'totalshear', - }[options.fitting] - - for l in [thresholdKey,'1_Cauchy']: - if l not in table.labels(raw = True): damask.util.croak('%s not found'%l) - semaphore.release() - - table.data_readArray(['%i_Cauchy'%(i+1) for i in range(9)]+[thresholdKey]+['%i_ln(V)'%(i+1) for i in range(9)]) - - validity = np.zeros((int(options.yieldValue[2])), dtype=bool) # found data for desired threshold - yieldStress = np.empty((int(options.yieldValue[2]),6),'d') - deformationRate = np.empty((int(options.yieldValue[2]),6),'d') - - line = 0 - for i,threshold in enumerate(np.linspace(options.yieldValue[0],options.yieldValue[1],options.yieldValue[2])): - while line < np.shape(table.data)[0]: - if abs(table.data[line,9])>= threshold: - upper,lower = abs(table.data[line,9]),abs(table.data[line-1,9]) # values for linear interpolation - stress = np.array(table.data[line-1,0:9] * (upper-threshold)/(upper-lower) + \ - table.data[line ,0:9] * (threshold-lower)/(upper-lower)).reshape(3,3) # linear interpolation of stress values - yieldStress[i,:] = t33toSym6(stress) - - dstrain= np.array(table.data[line,10:] - table.data[line-1,10:]).reshape(3,3) - deformationRate[i,:] = t33toSym6(dstrain) - - validity[i] = True - break - else: - line+=1 - if not validity[i]: - semaphore.acquire() - damask.util.croak('The data of result %i at the threshold %f is invalid,'%(loadNo,threshold)\ - +'the fitting at this point is skipped') - semaphore.release() - -# do the actual fitting procedure and write results to file - semaphore.acquire() - global stressAll, strainAll - f=open(options.geometry+'_'+options.criterion+'_'+str(time.time())+'.txt','w') - f.write(' '.join([options.fitting]+myFit.report_labels())+'\n') - try: - for i,threshold in enumerate(np.linspace(options.yieldValue[0],options.yieldValue[1],options.yieldValue[2])): - if validity[i]: - stressAll[i]=np.append(stressAll[i], yieldStress[i]/stressUnit) - strainAll[i]=np.append(strainAll[i], deformationRate[i]) - f.write( str(threshold)+' '+ - ' '.join(map(str,myFit.fit(stressAll[i].reshape(len(stressAll[i])//6,6).transpose())))+'\n') - except Exception: - damask.util.croak('Could not fit results of simulation (%s)'%thread) - semaphore.release() - return - damask.util.croak('\n') - semaphore.release() - -def loadcaseNo(): - global N_simulations - N_simulations+=1 - return N_simulations - -def converged(): - global N_simulations; fitResidual - - if N_simulations < options.max: - if len(fitResidual) > 5 and N_simulations >= options.min: - residualList = np.array(fitResidual[len(fitResidual)-5:]) - if np.std(residualList)/np.max(residualList) < 0.05: - return True - return False - else: - return True - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Performs calculations with various loads on given geometry file and fits yield surface. - -""", version = scriptID) - -# maybe make an option to specifiy if 2D/3D fitting should be done? - -parser.add_option('-l','--load' , dest='load', type='float', nargs=3, - help='load: final strain; increments; time %default', metavar='float int float') -parser.add_option('-g','--geometry', dest='geometry', type='string', - help='name of the geometry file [%default]', metavar='string') -parser.add_option('-c','--criterion', dest='criterion', choices=fitCriteria.keys(), - help='criterion for stopping simulations [%default]', metavar='string') -parser.add_option('-f','--fitting', dest='fitting', choices=thresholdParameter, - help='yield criterion [%default]', metavar='string') -parser.add_option('-y','--yieldvalue', dest='yieldValue', type='float', nargs=3, - help='yield points: start; end; count %default', metavar='float float int') -parser.add_option('--min', dest='min', type='int', - help='minimum number of simulations [%default]', metavar='int') -parser.add_option('--max', dest='max', type='int', - help='maximum number of iterations [%default]', metavar='int') -parser.add_option('-t','--threads', dest='threads', type='int', - help='number of parallel executions [%default]', metavar='int') -parser.add_option('-b','--bound', dest='bounds', type='float', nargs=2, - help='yield points: start; end; count %default', metavar='float float') -parser.add_option('-d','--dimension', dest='dimension', type='choice', choices=['2','3'], - help='dimension of the virtual test [%default]', metavar='int') -parser.add_option('-e', '--exponent', dest='exponent', type='float', - help='exponent of non-quadratic criteria', metavar='int') -parser.add_option('-u', '--uniaxial', dest='eqStress', type='float', - help='Equivalent stress', metavar='float') - -parser.set_defaults(min = 12, - max = 30, - threads = 4, - yieldValue = (0.002,0.004,2), - load = (0.010,100,100.0), - criterion = 'vonmises', - fitting = 'totalshear', - geometry = '20grains16x16x16', - bounds = None, - dimension = '3', - exponent = -1.0, - ) - -options = parser.parse_args()[0] - -if options.threads < 1: - parser.error('invalid number of threads {}'.format(options.threads)) -if options.min < 0: - parser.error('invalid minimum number of simulations {}'.format(options.min)) -if options.max < options.min: - parser.error('invalid maximum number of simulations (below minimum)') -if options.yieldValue[0] > options.yieldValue[1]: - parser.error('invalid yield start (below yield end)') -if options.yieldValue[2] != int(options.yieldValue[2]): - parser.error('count must be an integer') - -for check in [options.geometry+'.geom','numerics.config','material.config']: - if not os.path.isfile(check): - damask.util.croak('"{}" file not found'.format(check)) - -options.dimension = int(options.dimension) - -stressUnit = 1.0e9 if options.criterion == 'hill1948' else 1.0e6 - - -if options.dimension not in fitCriteria[options.criterion]['dimen']: - parser.error('invalid dimension for selected criterion') - -if options.criterion not in ['vonmises','tresca','drucker','hill1948'] and options.eqStress is None: - parser.error('please specify an equivalent stress (e.g. fitting to von Mises)') - -# global variables -fitResults = [] -fitErrors = [] -fitResidual = [] -stressAll= [np.zeros(0,'d').reshape(0,0) for i in range(int(options.yieldValue[2]))] -strainAll= [np.zeros(0,'d').reshape(0,0) for i in range(int(options.yieldValue[2]))] -N_simulations=0 -Guess = [] -threads=[] -semaphore=threading.Semaphore(1) -dDim = None -myLoad = None -myFit = None - -run = runFit(options.exponent, options.eqStress, options.dimension, options.criterion) - -damask.util.croak('Finished fitting to yield criteria') diff --git a/processing/misc/yieldSurfaceFast.py b/processing/misc/yieldSurfaceFast.py deleted file mode 100755 index c58dca733..000000000 --- a/processing/misc/yieldSurfaceFast.py +++ /dev/null @@ -1,1513 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import threading,time,os -import numpy as np -from optparse import OptionParser -import damask -from damask.util import leastsqBound -from scipy.optimize import nnls - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -def runFit(exponent, eqStress, dimension, criterion): - global threads, myFit, myLoad - global fitResidual - global Guess, dDim - - if options.criterion!='facet': - dDim = dimension - 3 - nParas = len(fitCriteria[criterion]['bound'][dDim]) - nExpo = fitCriteria[criterion]['nExpo'] - - if exponent > 0.0: # User defined exponents - nParas = nParas-nExpo - fitCriteria[criterion]['bound'][dDim] = fitCriteria[criterion]['bound'][dDim][:nParas] - - for i in range(nParas): - temp = fitCriteria[criterion]['bound'][dDim][i] - if fitCriteria[criterion]['bound'][dDim][i] == (None,None): - Guess.append(1.0) - else: - g = (temp[0]+temp[1])/2.0 - if g == 0: g = temp[1]*0.5 - Guess.append(g) - - myLoad = Loadcase(options.load[0],options.load[1],options.load[2],options.flag,options.yieldValue, - nSet = 10, dimension = dimension, vegter = options.criterion=='vegter') - - - myFit = Criterion(exponent,eqStress, dimension, criterion) - for t in range(options.threads): - threads.append(myThread(t)) - threads[t].start() - - for t in range(options.threads): - threads[t].join() - - if options.criterion=='facet': - doFacetFit() - - damask.util.croak('Residuals') - damask.util.croak(fitResidual) - -def doFacetFit(): - n = options.order - Data = np.zeros((options.numpoints, 10)) - for i in range(options.numpoints): - fileName = options.geometry + '_' + str(i+1) + '.yield' - data_i = np.loadtxt(fileName) - - sv = (data_i[0,0] + data_i[1,1] + data_i[2,2])/3.0 - - #convert stress and strain form the 6D to 5D space - S1 = np.sqrt(2.0)*(data_i[0,0] - data_i[1,1])/2.0 - S2 = np.sqrt(6.0)*(data_i[0,0] + data_i[1,1] - 2.0*sv)/2.0 - S3 = np.sqrt(2.0)*data_i[1,2] - S4 = np.sqrt(2.0)*data_i[2,0] - S5 = np.sqrt(2.0)*data_i[0,1] - - E1 = np.sqrt(2.0)*(data_i[3,0]-data_i[4,1])/2.0 - E2 = np.sqrt(6.0)*(data_i[3,0]+data_i[4,1])/2.0 - E3 = np.sqrt(2.0)*data_i[4,2] - E4 = np.sqrt(2.0)*data_i[5,0] - E5 = np.sqrt(2.0)*data_i[3,1] - - Data[i,:] = [E1,E2,E3,E4,E5,S1,S2,S3,S4,S5] - - Data[:,5:] = Data[:,5:] / 100000000.0 - - path=os.path.join(os.getcwd(),'final.mmm') - np.savetxt(path, Data, header='', comments='', fmt='% 15.10f') - - if options.dimension == 2: - reducedIndices = [0,1,4,5,6,9] - elif options.dimension == 3: - reducedIndices = [i for i in range(10)] - - numDirections = Data.shape[0] - Indices = np.arange(numDirections) - sdPairs = Data[:,reducedIndices][Indices,:] - numPairs = sdPairs.shape[0] - dimensionality = sdPairs.shape[1] / 2 - ds = sdPairs[:,0:dimensionality] - s = sdPairs[:,dimensionality::] - - A = np.zeros((numPairs, numPairs)) - B = np.ones((numPairs,)) - for i in range(numPairs): - for j in range(numPairs): - lamb = 1.0 - s_i = s[i,:] - ds_j = ds[j,:] - A[i,j] = lamb * (np.dot(s_i.ravel(), ds_j.ravel()) ** n) - - lambdas, residuals = nnls(A, B) - nonZeroTerms = np.logical_not(np.isclose(lambdas, 0.)) - numNonZeroTerms = np.sum(nonZeroTerms) - dataOut = np.zeros((numNonZeroTerms, 6)) - - if options.dimension == 2: - dataOut[:,0] = lambdas[nonZeroTerms] - dataOut[:,1] = ds[nonZeroTerms,:][:,0] - dataOut[:,2] = ds[nonZeroTerms,:][:,1] - dataOut[:,5] = ds[nonZeroTerms,:][:,2] - elif options.dimension == 3: - dataOut[:,0] = lambdas[nonZeroTerms] - dataOut[:,1] = ds[nonZeroTerms,:][:,0] - dataOut[:,2] = ds[nonZeroTerms,:][:,1] - dataOut[:,3] = ds[nonZeroTerms,:][:,2] - dataOut[:,4] = ds[nonZeroTerms,:][:,3] - dataOut[:,5] = ds[nonZeroTerms,:][:,4] - - headerText = 'facet\n 1 \n F \n {0:<3d} \n {1:<3d} '.format(n, numNonZeroTerms) - path=os.path.join(os.getcwd(),'facet_o{0}.fac'.format(n)) - np.savetxt(path, dataOut, header=headerText, comments='', fmt='% 15.10f') - -def principalStresses(sigmas): - """ - Computes principal stresses (i.e. eigenvalues) for a set of Cauchy stresses. - - sorted in descending order. - """ - lambdas=np.zeros(0,'d') - for i in range(np.shape(sigmas)[1]): - eigenvalues = np.linalg.eigvalsh(sym6toT33(sigmas[:,i])) - lambdas = np.append(lambdas,np.sort(eigenvalues)[::-1]) #append eigenvalues in descending order - lambdas = np.transpose(lambdas.reshape(np.shape(sigmas)[1],3)) - return lambdas - -def principalStress(p): - I = invariant(p) - - I1s3I2= (I[0]**2 - 3.0*I[1])**0.5 - numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2] - denom = 2.0*I1s3I2**3 - cs = numer/denom - - phi = np.arccos(cs)/3.0 - t1 = I[0]/3.0; t2 = 2.0/3.0*I1s3I2 - return np.array( [t1 + t2*np.cos(phi), - t1 + t2*np.cos(phi+np.pi*2.0/3.0), - t1 + t2*np.cos(phi+np.pi*4.0/3.0)]) - -def principalStrs_Der(p, s, dim, Karafillis=False): - """Derivative of principal stress with respect to stress""" - third = 1.0/3.0 - third2 = 2.0*third - - I = invariant(p) - I1s3I2= np.sqrt(I[0]**2 - 3.0*I[1]) - numer = 2.0*I[0]**3 - 9.0*I[0]*I[1] + 27.0*I[2] - denom = 2.0*I1s3I2**3 - cs = numer/denom - phi = np.arccos(cs)/3.0 - - dphidcs = -third/np.sqrt(1.0 - cs**2) - dcsddenom = 0.5*numer*(-1.5)*I1s3I2**(-5.0) - dcsdI1 = (6.0*I[0]**2 - 9.0*I[1])*denom + dcsddenom*(2.0*I[0]) - dcsdI2 = ( - 9.0*I[0])*denom + dcsddenom*(-3.0) - dcsdI3 = 27.0*denom - dphidI1, dphidI2, dphidI3 = dphidcs*dcsdI1, dphidcs*dcsdI2, dphidcs*dcsdI3 - - dI1s3I2dI1 = I[0]/I1s3I2 - dI1s3I2dI2 = -1.5/I1s3I2 - tcoeff = third2*I1s3I2 - - dSidIj = lambda theta : ( tcoeff*(-np.sin(theta))*dphidI1 + third2*dI1s3I2dI1*np.cos(theta) + third, - tcoeff*(-np.sin(theta))*dphidI2 + third2*dI1s3I2dI2*np.cos(theta), - tcoeff*(-np.sin(theta))*dphidI3) - dSdI = np.array([dSidIj(phi),dSidIj(phi+np.pi*2.0/3.0),dSidIj(phi+np.pi*4.0/3.0)]) # i=1,2,3; j=1,2,3 - -# calculate the derivation of principal stress with regards to the anisotropic coefficients - one = np.ones_like(s); zero = np.zeros_like(s); num = len(s) - dIdp = np.array([[one, one, one, zero, zero, zero], - [p[1]+p[2], p[2]+p[0], p[0]+p[1], -2.0*p[3], -2.0*p[4], -2.0*p[5]], - [p[1]*p[2]-p[4]**2, p[2]*p[0]-p[5]**2, p[0]*p[1]-p[3]**2, - -2.0*p[3]*p[2]+2.0*p[4]*p[5], -2.0*p[4]*p[0]+2.0*p[5]*p[3], -2.0*p[5]*p[1]+2.0*p[3]*p[4]] ]) - if Karafillis: - dpdc = np.array([[zero,s[0]-s[2],s[0]-s[1]], [s[1]-s[2],zero,s[1]-s[0]], [s[2]-s[1],s[2]-s[0],zero]])/3.0 - dSdp = np.array([np.dot(dSdI[:,:,i],dIdp[:,:,i]).T for i in range(num)]).T - if dim == 2: - temp = np.vstack([dSdp[:,3]*s[3]]).T.reshape(num,1,3).T - else: - temp = np.vstack([dSdp[:,3]*s[3],dSdp[:,4]*s[4],dSdp[:,5]*s[5]]).T.reshape(num,3,3).T - - return np.concatenate((np.array([np.dot(dSdp[:,0:3,i], dpdc[:,:,i]).T for i in range(num)]).T, - temp), axis=1) - else: - if dim == 2: - dIdc=np.array([[-dIdp[i,0]*s[1], -dIdp[i,1]*s[0], -dIdp[i,1]*s[2], - -dIdp[i,2]*s[1], -dIdp[i,2]*s[0], -dIdp[i,0]*s[2], - dIdp[i,3]*s[3] ] for i in range(3)]) - else: - dIdc=np.array([[-dIdp[i,0]*s[1], -dIdp[i,1]*s[0], -dIdp[i,1]*s[2], - -dIdp[i,2]*s[1], -dIdp[i,2]*s[0], -dIdp[i,0]*s[2], - dIdp[i,3]*s[3], dIdp[i,4]*s[4], dIdp[i,5]*s[5] ] for i in range(3)]) - return np.array([np.dot(dSdI[:,:,i],dIdc[:,:,i]).T for i in range(num)]).T - -def invariant(sigmas): - I = np.zeros(3) - s11,s22,s33,s12,s23,s31 = sigmas - I[0] = s11 + s22 + s33 - I[1] = s11*s22 + s22*s33 + s33*s11 - s12**2 - s23**2 - s31**2 - I[2] = s11*s22*s33 + 2.0*s12*s23*s31 - s12**2*s33 - s23**2*s11 - s31**2*s22 - return I - -def math_ln(x): - return np.log(x + 1.0e-32) - -def sym6toT33(sym6): - """Shape the symmetric stress tensor(6) into (3,3)""" - return np.array([[sym6[0],sym6[3],sym6[5]], - [sym6[3],sym6[1],sym6[4]], - [sym6[5],sym6[4],sym6[2]]]) - -def t33toSym6(t33): - """Shape the stress tensor(3,3) into symmetric (6)""" - return np.array([ t33[0,0], - t33[1,1], - t33[2,2], - (t33[0,1] + t33[1,0])/2.0, # 0 3 5 - (t33[1,2] + t33[2,1])/2.0, # * 1 4 - (t33[2,0] + t33[0,2])/2.0,]) # * * 2 - -class Criteria(object): - def __init__(self, criterion, uniaxialStress,exponent, dimension): - self.stress0 = uniaxialStress - if exponent < 0.0: # Fitting exponent m - self.mFix = [False, exponent] - else: # fixed exponent m - self.mFix = [True, exponent] - self.func = fitCriteria[criterion]['func'] - self.criteria = criterion - self.dim = dimension - def fun(self, paras, ydata, sigmas): - return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim) - def jac(self, paras, ydata, sigmas): - return self.func(self.stress0, paras, sigmas,self.mFix,self.criteria,self.dim,Jac=True) - -class Vegter(object): - """Vegter yield criterion""" - - def __init__(self, refPts, refNormals,nspace=11): - self.refPts, self.refNormals = self._getRefPointsNormals(refPts, refNormals) - self.hingePts = self._getHingePoints() - self.nspace = nspace - def _getRefPointsNormals(self,refPtsQtr,refNormalsQtr): - if len(refPtsQtr) == 12: - refPts = refPtsQtr - refNormals = refNormalsQtr - else: - refPts = np.empty([13,2]) - refNormals = np.empty([13,2]) - refPts[12] = refPtsQtr[0] - refNormals[12] = refNormalsQtr[0] - for i in range(3): - refPts[i] = refPtsQtr[i] - refPts[i+3] = refPtsQtr[3-i][::-1] - refPts[i+6] =-refPtsQtr[i] - refPts[i+9] =-refPtsQtr[3-i][::-1] - refNormals[i] = refNormalsQtr[i] - refNormals[i+3] = refNormalsQtr[3-i][::-1] - refNormals[i+6] =-refNormalsQtr[i] - refNormals[i+9] =-refNormalsQtr[3-i][::-1] - return refPts,refNormals - - def _getHingePoints(self): - """ - Calculate the hinge point B according to the reference points A,C and the normals n,m - - refPoints = np.array([[p1_x, p1_y], [p2_x, p2_y]]); - refNormals = np.array([[n1_x, n1_y], [n2_x, n2_y]]) - """ - def hingPoint(points, normals): - A1 = points[0][0]; A2 = points[0][1] - C1 = points[1][0]; C2 = points[1][1] - n1 = normals[0][0]; n2 = normals[0][1] - m1 = normals[1][0]; m2 = normals[1][1] - B1 = (m2*(n1*A1 + n2*A2) - n2*(m1*C1 + m2*C2))/(n1*m2-m1*n2) - B2 = (n1*(m1*C1 + m2*C2) - m1*(n1*A1 + n2*A2))/(n1*m2-m1*n2) - return np.array([B1,B2]) - return np.array([hingPoint(self.refPts[i:i+2],self.refNormals[i:i+2]) for i in range(len(self.refPts)-1)]) - - def getBezier(self): - def bezier(R,H): - b = [] - for mu in np.linspace(0.0,1.0,self.nspace): - b.append(np.array(R[0]*np.ones_like(mu) + 2.0*mu*(H - R[0]) + mu**2*(R[0]+R[1] - 2.0*H))) - return b - return np.array([bezier(self.refPts[i:i+2],self.hingePts[i]) for i in range(len(self.refPts)-1)]) - -def VetgerCriterion(stress,lankford, rhoBi0, theta=0.0): - """0-pure shear; 1-uniaxial; 2-plane strain; 3-equi-biaxial""" - def getFourierParas(r): - # get the value after Fourier transformation - nset = len(r) - lmatrix = np.empty([nset,nset]) - theta = np.linspace(0.0,np.pi/2,nset) - for i,th in enumerate(theta): - lmatrix[i] = np.array([np.cos(2*j*th) for j in range(nset)]) - return np.linalg.solve(lmatrix, r) - - nps = len(stress) - if nps%4 != 0: - damask.util.croak('Warning: the number of stress points is uncorrect, stress points of %s are missing in set %i'%( - ['eq-biaxial, plane strain & uniaxial', 'eq-biaxial & plane strain','eq-biaxial'][nps%4-1],nps/4+1)) - else: - nset = nps/4 - strsSet = stress.reshape(nset,4,2) - refPts = np.empty([4,2]) - - fouriercoeffs = np.array([np.cos(2.0*i*theta) for i in range(nset)]) - for i in range(2): - refPts[3,i] = sum(strsSet[:,3,i])/nset - for j in range(3): - refPts[j,i] = np.dot(getFourierParas(strsSet[:,j,i]), fouriercoeffs) - - -def Tresca(eqStress=None, #not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None, #not needed/supported - dim=3, - Jac=False): - """ - Tresca yield criterion - - the fitted parameter is paras(sigma0) - """ - if not Jac: - lambdas = principalStresses(sigmas) - r = np.amax(np.array([abs(lambdas[2,:]-lambdas[1,:]),\ - abs(lambdas[1,:]-lambdas[0,:]),\ - abs(lambdas[0,:]-lambdas[2,:])]),0) - paras - return r.ravel() - else: - return -np.ones(len(sigmas)) - -def Cazacu_Barlat(eqStress=None, - paras=None, - sigmas=None, - mFix=None,#not needed/supported - criteria=None, - dim=3, #2D also possible - Jac=False): - """ - Cazacu-Barlat (CB) yield criterion - - the fitted parameters are: - a1,a2,a3,a6; b1,b2,b3,b4,b5,b10; c for plane stress - a1,a2,a3,a4,a5,a6; b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11; c: for general case - mFix is ignored - """ - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: - (a1,a2,a3,a4), (b1,b2,b3,b4,b5,b10), c = paras[0:4],paras[4:10],paras[10] - a5 = a6 = b6 = b7 = b8 = b9 = b11 = 0.0 - s33 = s23 = s31 = np.zeros_like(s11) - else: - (a1,a2,a3,a4,a5,a6), (b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11), c = paras[0:6],paras[6:17],paras[17] - - s1_2, s2_2, s3_2, s12_2, s23_2, s31_2 = np.array([s11,s22,s33,s12,s23,s31])**2 - s1_3, s2_3, s3_3, s123, s321 = s11*s1_2, s22*s2_2, s33*s3_2,s11*s22*s33, s12*s23*s31 - d12_2,d23_2,d31_2 = (s11-s22)**2, (s22-s33)**2, (s33-s11)**2 - - J20 = ( a1*d12_2 + a2*d23_2 + a3*d31_2 )/6.0 + a4*s12_2 + a5*s23_2 + a6*s31_2 - J30 = ( (b1 +b2 )*s1_3 + (b3 +b4 )*s2_3 + ( b1+b4-b2 + b1+b4-b3 )*s3_3 )/27.0- \ - ( (b1*s22+b2*s33)*s1_2 + (b3*s33+b4*s11)*s2_2 + ((b1+b4-b2)*s11 + (b1+b4-b3)*s22)*s3_2 )/9.0 + \ - ( (b1+b4)*s123/9.0 + b11*s321 )*2.0 - \ - ( ( 2.0*b9 *s22 - b8*s33 - (2.0*b9 -b8)*s11 )*s31_2 + - ( 2.0*b10*s33 - b5*s22 - (2.0*b10-b5)*s11 )*s12_2 + - ( (b6+b7)*s11 - b6*s22 - b7*s33 )*s23_2 - )/3.0 - f0 = J20**3 - c*J30**2 - r = f0**(1.0/6.0)*np.sqrt(3.0)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - drdf = r/f0/6.0 - dj2, dj3 = drdf*3.0*J20**2, -drdf*2.0*J30*c - jc = -drdf*J30**2 - - ja1,ja2,ja3 = dj2*d12_2/6.0, dj2*d23_2/6.0, dj2*d31_2/6.0 - ja4,ja5,ja6 = dj2*s12_2, dj2*s23_2, dj2*s31_2 - jb1 = dj3*( (s1_3 + 2.0*s3_3)/27.0 - s22*s1_2/9.0 - (s11+s22)*s3_2/9.0 + s123/4.5 ) - jb2 = dj3*( (s1_3 - s3_3)/27.0 - s33*s1_2/9.0 + s11 *s3_2/9.0 ) - jb3 = dj3*( (s2_3 - s3_3)/27.0 - s33*s2_2/9.0 + s22 *s3_2/9.0 ) - jb4 = dj3*( (s2_3 + 2.0*s3_3)/27.0 - s11*s2_2/9.0 - (s11+s22)*s3_2/9.0 + s123/4.5 ) - - jb5, jb10 = dj3*(s22 - s11)*s12_2/3.0, dj3*(s11 - s33)*s12_2/1.5 - jb6, jb7 = dj3*(s22 - s11)*s23_2/3.0, dj3*(s33 - s11)*s23_2/3.0 - jb8, jb9 = dj3*(s33 - s11)*s31_2/3.0, dj3*(s11 - s22)*s31_2/1.5 - jb11 = dj3*s321*2.0 - if dim == 2: - return np.vstack((ja1,ja2,ja3,ja4,jb1,jb2,jb3,jb4,jb5,jb10,jc)).T - else: - return np.vstack((ja1,ja2,ja3,ja4,ja5,ja6,jb1,jb2,jb3,jb4,jb5,jb6,jb7,jb8,jb9,jb10,jb11,jc)).T - -def Drucker(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None, - dim=3, - Jac=False): - """ - Drucker yield criterion - - the fitted parameters are - sigma0, C_D for Drucker(p=1); - sigma0, C_D, p for general Drucker - eqStress, mFix are invalid inputs - """ - if criteria == 'drucker': - sigma0, C_D= paras - p = 1.0 - else: - sigma0, C_D = paras[0:2] - if mFix[0]: p = mFix[1] - else: p = paras[-1] - I = invariant(sigmas) - J = np.zeros([3]) - J[1] = I[0]**2/3.0 - I[1] - J[2] = I[0]**3/13.5 - I[0]*I[1]/3.0 + I[2] - J2_3p = J[1]**(3.0*p) - J3_2p = J[2]**(2.0*p) - left = J2_3p - C_D*J3_2p - r = left**(1.0/(6.0*p))*3.0**0.5/sigma0 - - if not Jac: - return (r - 1.0).ravel() - else: - drdl = r/left/(6.0*p) - if criteria == 'drucker': - return np.vstack((-r/sigma0, -drdl*J3_2p)).T - else: - dldp = 3.0*J2_3p*math_ln(J[1]) - 2.0*C_D*J3_2p*math_ln(J[2]) - jp = drdl*dldp + r*math_ln(left)/(-6.0*p*p) - - if mFix[0]: return np.vstack((-r/sigma0, -drdl*J3_2p)).T - else: return np.vstack((-r/sigma0, -drdl*J3_2p, jp)).T - -def Hill1948(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, #not needed/supported - criteria=None,#not needed/supported - dim=3, - Jac=False): - """ - Hill 1948 yield criterion - - the fitted parameters are: - F, G, H, L, M, N for 3D - F, G, H, N for 2D - """ - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: # plane stress - jac = np.array([ s22**2, s11**2, (s11-s22)**2, 2.0*s12**2]) - else: # general case - jac = np.array([(s22-s33)**2,(s33-s11)**2,(s11-s22)**2, 2.0*s23**2,2.0*s31**2,2.0*s12**2]) - - if not Jac: - return (np.dot(paras,jac)/2.0-0.5).ravel() - else: - return jac.T - -def Hill1979(eqStress=None,#not needed/supported - paras=None, - sigmas=None, - mFix=None, - criteria=None,#not needed/supported - dim=3, - Jac=False): - """ - Hill 1979 yield criterion - - the fitted parameters are: f,g,h,a,b,c,m - """ - if mFix[0]: - m = mFix[1] - else: - m = paras[-1] - - coeff = paras[0:6] - s = principalStresses(sigmas) - diffs = np.array([s[1]-s[2], s[2]-s[0], s[0]-s[1],\ - 2.0*s[0]-s[1]-s[2], 2.0*s[1]-s[2]-s[0], 2.0*s[2]-s[0]-s[1]])**2 - - diffsm = diffs**(m/2.0) - left = np.dot(coeff,diffsm) - r = (0.5*left)**(1.0/m)/eqStress #left = base**mi - - if not Jac: - return (r-1.0).ravel() - else: - drdl, dldm = r/left/m, np.dot(coeff,diffsm*math_ln(diffs))*0.5 - jm = drdl*dldm + r*math_ln(0.5*left)*(-1.0/m/m) #/(-m**2) - - if mFix[0]: return np.vstack((drdl*diffsm)).T - else: return np.vstack((drdl*diffsm, jm)).T - -def Hosford(eqStress=None, - paras=None, - sigmas=None, - mFix=None, - criteria=None, - dim=3, - Jac=False): - """ - Hosford family criteria - - the fitted parameters are: - von Mises: sigma0 - Hershey: (1) sigma0, a, when a is not fixed; (2) sigma0, when a is fixed - general Hosford: (1) F,G,H, a, when a is not fixed; (2) F,G,H, when a is fixed - """ - if criteria == 'vonmises': - sigma0 = paras - coeff = np.ones(3) - a = 2.0 - elif criteria == 'hershey': - sigma0 = paras[0] - coeff = np.ones(3) - if mFix[0]: a = mFix[1] - else: a = paras[1] - else: - sigma0 = eqStress - coeff = paras[0:3] - if mFix[0]: a = mFix[1] - else: a = paras[3] - - s = principalStresses(sigmas) - diffs = np.array([s[1]-s[2], s[2]-s[0], s[0]-s[1]])**2 - diffsm = diffs**(a/2.0) - left = np.dot(coeff,diffsm) - r = (0.5*left)**(1.0/a)/sigma0 - - if not Jac: - return (r-1.0).ravel() - else: - if criteria == 'vonmises': # von Mises - return -r/sigma0 - else: - drdl, dlda = r/left/a, np.dot(coeff,diffsm*math_ln(diffs))*0.5 - ja = drdl*dlda + r*math_ln(0.5*left)*(-1.0/a/a) - if criteria == 'hershey': # Hershey - if mFix[0]: return -r/sigma0 - else: return np.vstack((-r/sigma0, ja)).T - else: # Anisotropic Hosford - if mFix[0]: return np.vstack((drdl*diffsm)).T - else: return np.vstack((drdl*diffsm, ja)).T - -def Barlat1989(eqStress=None, - paras=None, - sigmas=None, - mFix=None, - criteria=None, - dim=3, - Jac=False): - """ - Barlat-Lian 1989 yield criteria - - the fitted parameters are: - Anisotropic: a, h, p, m; m is optional - """ - a, h, p = paras[0:3] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - c = 2.0-a - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k1,k2 = 0.5*(s11 + h*s22), (0.25*(s11 - h*s22)**2 + (p*s12)**2)**0.5 - fs = np.array([ (k1+k2)**2, (k1-k2)**2, 4.0*k2**2 ]); fm = fs**(m/2.0) - left = np.dot(np.array([a,a,c]),fm) - r = (0.5*left)**(1.0/m)/eqStress - - if not Jac: - return (r-1.0).ravel() - else: - dk1dh = 0.5*s22 - dk2dh, dk2dp = 0.25*(s11-h*s22)*(-s22)/k2, p*s12**2/k2 - dlda, dldc = fm[0]+fm[1], fm[2] - fm1 = fs**(m/2.0-1.0)*m - dldk1, dldk2 = a*fm1[0]*(k1+k2)+a*fm1[1]*(k1-k2), a*fm1[0]*(k1+k2)-a*fm1[1]*(k1-k2)+c*fm1[2]*k2*4.0 - drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) - dldm = np.dot(np.array([a,a,c]),fm*math_ln(fs))*0.5 - - ja,jc = drdl*dlda, drdl*dldc - jh,jp = drdl*(dldk1*dk1dh + dldk2*dk2dh), drdl*dldk2*dk2dp - jm = drdl*dldm + drdm - - if mFix[0]: return np.vstack((ja,jc,jh,jp)).T - else: return np.vstack((ja,jc,jh,jp,jm)).T - -def Barlat1991(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Barlat 1991 criteria - - the fitted parameters are: - Anisotropic: a, b, c, f, g, h, m for 3D - a, b, c, h, m for plane stress - m is optional - """ - if dim == 2: coeff = paras[0:4] # plane stress - else: coeff = paras[0:6] # general case - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - s11,s22,s33,s12,s23,s31 = sigmas - if dim == 2: - dXdx = np.array([s22,-s11,s11-s22,s12]) - A,B,C,H = np.array(coeff)[:,None]*dXdx; F=G=0.0 - else: - dXdx = np.array([s22-s33,s33-s11,s11-s22,s23,s31,s12]) - A,B,C,F,G,H = np.array(coeff)[:,None]*dXdx - - I2 = (F*F + G*G + H*H)/3.0+ ((A-C)**2+(C-B)**2+(B-A)**2)/54.0 - I3 = (C-B)*(A-C)*(B-A)/54.0 + F*G*H - ((C-B)*F*F + (A-C)*G*G + (B-A)*H*H)/6.0 - phi1 = np.arccos(I3/I2**1.5)/3.0 + np.pi/6.0; absc1 = 2.0*np.abs(np.cos(phi1)) - phi2 = phi1 + np.pi/3.0; absc2 = 2.0*np.abs(np.cos(phi2)) - phi3 = phi2 + np.pi/3.0; absc3 = 2.0*np.abs(np.cos(phi3)) - left = ( absc1**m + absc2**m + absc3**m ) - r = (0.5*left)**(1.0/m)*np.sqrt(3.0*I2)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - dfdl = r/left/m - jm = r*math_ln(0.5*left)*(-1.0/m/m) + dfdl*0.5*( - absc1**m*math_ln(absc1) + absc2**m*math_ln(absc2) + absc3**m*math_ln(absc3) ) - - da,db,dc = (2.0*A-B-C)/18.0, (2.0*B-C-A)/18.0, (2.0*C-A-B)/18.0 - if dim == 2: - dI2dx = np.array([da, db, dc, H])/1.5*dXdx - dI3dx = np.array([ da*(B-C) + (H**2-G**2)/2.0, - db*(C-A) + (F**2-H**2)/2.0, - dc*(A-B) + (G**2-F**2)/2.0, - (G*F + (A-B))*H ])/3.0*dXdx - else: - dI2dx = np.array([da, db, dc, F,G,H])/1.5*dXdx - dI3dx = np.array([ da*(B-C) + (H**2-G**2)/2.0, - db*(C-A) + (F**2-H**2)/2.0, - dc*(A-B) + (G**2-F**2)/2.0, - (H*G*3.0 + (B-C))*F, - (F*H*3.0 + (C-A))*G, - (G*F*3.0 + (A-B))*H ])/3.0*dXdx - darccos = -1.0/np.sqrt(1.0 - I3**2/I2**3) - - dfdcos = lambda phi : dfdl*m*(2.0*abs(np.cos(phi)))**(m-1.0)*np.sign(np.cos(phi))*(-np.sin(phi)/1.5) - - dfdthe= (dfdcos(phi1) + dfdcos(phi2) + dfdcos(phi3)) - dfdI2, dfdI3 = dfdthe*darccos*I3*(-1.5)*I2**(-2.5)+r/2.0/I2, dfdthe*darccos*I2**(-1.5) - - if mFix[0]: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx)).T - else: return np.vstack((dfdI2*dI2dx + dfdI3*dI3dx, jm)).T - -def BBC2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2000 yield criterion - - the fitted parameters are - d,e,f,g, b,c,a, k; k is optional - criteria are invalid input - """ - d,e,f,g, b,c,a= paras[0:7] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k2 = 2.0*k; k1 = k - 1.0 - M,N,P,Q,R = d+e, e+f, (d-e)/2.0, (e-f)/2.0, g**2 - Gamma = M*s11 + N*s22 - Psi = ( (P*s11 + Q*s22)**2 + s12**2*R )**0.5 - - l1, l2, l3 = b*Gamma + c*Psi, b*Gamma - c*Psi, 2.0*c*Psi - l1s,l2s,l3s = l1**2, l2**2, l3**2 - - left = a*l1s**k + a*l2s**k + (1-a)*l3s**k - r = left**(1.0/k2)/eqStress - if not Jac: - return (r - 1.0).ravel() - else: - drdl,drdk = r/left/k2, r*math_ln(left)*(-1.0/k2/k) - dldl1,dldl2,dldl3 = a*k2*(l1s**k1)*l1, a*k2*(l2s**k1)*l2, (1-a)*k2*(l3s**k1)*l3 - dldGama, dldPsi = (dldl1 + dldl2)*b, (dldl1 - dldl2 + 2.0*dldl3)*c - temp = (P*s11 + Q*s22)/Psi - dPsidP, dPsidQ, dPsidR = temp*s11, temp*s22, 0.5*s12**2/Psi - dlda = l1s**k + l2s**k - l3s**k - dldb = dldl1*Gamma + dldl2*Gamma - dldc = dldl1*Psi - dldl2*Psi + dldl3*2.0*Psi - dldk = a*math_ln(l1s)*l1s**k + a*math_ln(l2s)*l2s**k + (1-a)*math_ln(l3s)*l3s**k - - J = drdl*np.array([dldGama*s11+dldPsi*dPsidP*0.5, dldGama*(s11+s22)+dldPsi*(-dPsidP+dPsidQ)*0.5, #jd,je - dldGama*s22-dldPsi*dPsidQ*0.5, dldPsi*dPsidR*2.0*g, #jf,jg - dldb, dldc, dlda]) #jb,jc,ja - if mFix[0]: return np.vstack(J).T - else: return np.vstack((J, drdl*dldk + drdk)).T - - -def BBC2003(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2003 yield criterion - - the fitted parameters are - M,N,P,Q,R,S,T,a, k; k is optional - criteria are invalid input - """ - M,N,P,Q,R,S,T,a = paras[0:8] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11,s22,s12 = sigmas[0], sigmas[1], sigmas[3] - k2 = 2.0*k; k1 = k - 1.0 - Gamma = 0.5 * (s11 + M*s22) - Psi = ( 0.25*(N*s11 - P*s22)**2 + Q*Q*s12**2 )**0.5 - Lambda = ( 0.25*(R*s11 - S*s22)**2 + T*T*s12**2 )**0.5 - - l1, l2, l3 = Gamma + Psi, Gamma - Psi, 2.0*Lambda - l1s,l2s,l3s = l1**2, l2**2, l3**2 - left = a*l1s**k + a*l2s**k + (1-a)*l3s**k - r = left**(1.0/k2)/eqStress - if not Jac: - return (r - 1.0).ravel() - else: - drdl,drdk = r/left/k2, r*math_ln(left)*(-1.0/k2/k) - dldl1,dldl2,dldl3 = a*k2*(l1s**k1)*l1, a*k2*(l2s**k1)*l2, (1-a)*k2*(l3s**k1)*l3 - - dldGamma, dldPsi, dldLambda = dldl1+dldl2, dldl1-dldl2, 2.0*dldl3 - temp = 0.25/Psi*(N*s11 - P*s22) - dPsidN, dPsidP, dPsidQ = s11*temp, -s22*temp, Q*s12**2/Psi - temp = 0.25/Lambda*(R*s11 - S*s22) - dLambdadR, dLambdadS, dLambdadT = s11*temp, -s22*temp, T*s12**2/Psi - dldk = a*math_ln(l1s)*l1s**k + a*math_ln(l2s)*l2s**k + (1-a)*math_ln(l3s)*l3s**k - - J = drdl * np.array([dldGamma*s22*0.5, #jM - dldPsi*dPsidN, dldPsi*dPsidP, dldPsi*dPsidQ, #jN, jP, jQ - dldLambda*dLambdadR, dldLambda*dLambdadS, dldLambda*dLambdadT, #jR, jS, jT - l1s**k + l2s**k - l3s**k ]) #ja - - if mFix[0]: return np.vstack(J).T - else : return np.vstack((J, drdl*dldk+drdk)).T - -def BBC2005(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - BBC2005 yield criterion - - the fitted parameters are - a, b, L ,M, N, P, Q, R, k k are optional - criteria is invalid input - """ - a,b,L, M, N, P, Q, R = paras[0:8] - if mFix[0]: k = mFix[1] - else: k = paras[-1] - - s11 = sigmas[0]; s22 = sigmas[1]; s12 = sigmas[3] - k2 = 2.0*k - Gamma = L*s11 + M*s22 - Lambda = ( (N*s11 - P*s22)**2 + s12**2 )**0.5 - Psi = ( (Q*s11 - R*s22)**2 + s12**2 )**0.5 - - l1 = Lambda + Gamma; l2 = Lambda - Gamma; l3 = Lambda + Psi; l4 = Lambda - Psi - l1s = l1**2; l2s = l2**2; l3s = l3**2; l4s = l4**2 - left = a*l1s**k + a*l2s**k + b*l3s**k + b*l4s**k - sBar = left**(1.0/k2); r = sBar/eqStress - 1.0 - if not Jac: - return r.ravel() - else: - ln = lambda x : np.log(x + 1.0e-32) - expo = 0.5/k; k1 = k-1.0 - - dsBardl = expo*sBar/left/eqStress - dsBarde = sBar*ln(left); dedk = expo/(-k) - dldl1 = a*k*(l1s**k1)*(2.0*l1) - dldl2 = a*k*(l2s**k1)*(2.0*l2) - dldl3 = b*k*(l3s**k1)*(2.0*l3) - dldl4 = b*k*(l4s**k1)*(2.0*l4) - - dldLambda = dldl1 + dldl2 + dldl3 + dldl4 - dldGama = dldl1 - dldl2 - dldPsi = dldl3 - dldl4 - temp = (N*s11 - P*s22)/Lambda - dLambdadN = s11*temp; dLambdadP = -s22*temp - temp = (Q*s11 - R*s22)/Psi - dPsidQ = s11*temp; dPsidR = -s22*temp - dldk = a*ln(l1s)*l1s**k + a*ln(l2s)*l2s**k + b*ln(l3s)*l3s**k + b*ln(l4s)*l4s**k - - J = dsBardl * np.array( [ - l1s**k+l2s**k, l3s**k+l4s**k,dldGama*s11,dldGama*s22,dldLambda*dLambdadN, - dldLambda*dLambdadP, dldPsi*dPsidQ, dldPsi*dPsidR]) - - if mFix[0]: return np.vstack(J).T - else : return np.vstack(J, dldk+dsBarde*dedk).T - -def Yld2000(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Yld2000 yield criterion - - C: c11,c22,c66 c12=c21=1.0 JAC NOT PASS - D: d11,d12,d21,d22,d66 - """ - C,D = paras[0:3], paras[3:8] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - s11, s22, s12 = sigmas[0],sigmas[1],sigmas[3] - X = np.array([ 2.0*C[0]*s11-C[0]*s22, 2.0*C[1]*s22-C[1]*s11, 3.0*C[2]*s12 ])/3.0 # a1,a2,a7 - Y = np.array([ (8.0*D[2]-2.0*D[0]-2.0*D[3]+2.0*D[1])*s11 + (4.0*D[3]-4.0*D[1]-4.0*D[2]+ D[0])*s22, - (4.0*D[0]-4.0*D[2]-4.0*D[1]+ D[3])*s11 + (8.0*D[1]-2.0*D[3]-2.0*D[0]+2.0*D[2])*s22, - 9.0*D[4]*s12 ])/9.0 - - def priStrs(s): - temp = np.sqrt( (s[0]-s[1])**2 + 4.0*s[2]**2 ) - return 0.5*(s[0]+s[1] + temp), 0.5*(s[0]+s[1] - temp) - m2 = m/2.0; m21 = m2 - 1.0 - (X1,X2), (Y1,Y2) = priStrs(X), priStrs(Y) # Principal values of X, Y - phi1s, phi21s, phi22s = (X1-X2)**2, (2.0*Y2+Y1)**2, (2.0*Y1+Y2)**2 - phi1, phi21, phi22 = phi1s**m2, phi21s**m2, phi22s**m2 - left = phi1 + phi21 + phi22 - r = (0.5*left)**(1.0/m)/eqStress - - if not Jac: - return (r-1.0).ravel() - else: - drdl, drdm = r/m/left, r*math_ln(0.5*left)*(-1.0/m/m) #/(-m*m) - dldm = ( phi1*math_ln(phi1s) + phi21*math_ln(phi21s) + phi22*math_ln(phi22s) )*0.5 - zero = np.zeros_like(s11); num = len(s11) - def dPrincipalds(X): - """Derivative of principla with respect to stress""" - temp = 1.0/np.sqrt( (X[0]-X[1])**2 + 4.0*X[2]**2 ) - dP1dsi = 0.5*np.array([ 1.0+temp*(X[0]-X[1]), 1.0-temp*(X[0]-X[1]), temp*4.0*X[2]]) - dP2dsi = 0.5*np.array([ 1.0-temp*(X[0]-X[1]), 1.0+temp*(X[0]-X[1]), -temp*4.0*X[2]]) - return np.array([dP1dsi, dP2dsi]) - - dXdXi, dYdYi = dPrincipalds(X), dPrincipalds(Y) - dXidC = np.array([ [ 2.0*s11-s22, zero, zero ], #dX11dC - [ zero, 2.0*s22-s11, zero ], #dX22dC - [ zero, zero, 3.0*s12 ] ])/3.0 #dX12dC - dYidD = np.array([ [ -2.0*s11+ s22, 2.0*s11-4.0*s22, 8.0*s11-4.0*s22, -2.0*s11+4.0*s22, zero ], #dY11dD - [ 4.0*s11-2.0*s22, -4.0*s11+8.0*s22, -4.0*s11+2.0*s22, s11-2.0*s22, zero ], #dY22dD - [ zero, zero, zero, zero, 9.0*s12 ] ])/9.0 #dY12dD - - dXdC=np.array([np.dot(dXdXi[:,:,i], dXidC[:,:,i]).T for i in range(num)]).T - dYdD=np.array([np.dot(dYdYi[:,:,i], dYidD[:,:,i]).T for i in range(num)]).T - - dldX = m*np.array([ phi1s**m21*(X1-X2), phi1s**m21*(X2-X1)]) - dldY = m*np.array([phi21s**m21*(2.0*Y2+Y1) + 2.0*phi22s**m21*(2.0*Y1+Y2), \ - phi22s**m21*(2.0*Y1+Y2) + 2.0*phi21s**m21*(2.0*Y2+Y1) ]) - jC = drdl*np.array([np.dot(dldX[:,i], dXdC[:,:,i]) for i in range(num)]).T - jD = drdl*np.array([np.dot(dldY[:,i], dYdD[:,:,i]) for i in range(num)]).T - - jm = drdl*dldm + drdm - if mFix[0]: return np.vstack((jC,jD)).T - else: return np.vstack((jC,jD,jm)).T - -def Yld200418p(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Yld2004-18p yield criterion - - the fitted parameters are - C: c12,c21,c23,c32,c31,c13,c44,c55,c66; D: d12,d21,d23,d32,d31,d13,d44,d55,d66 for 3D - C: c12,c21,c23,c32,c31,c13,c44; D: d12,d21,d23,d32,d31,d13,d44 for 2D - and m, m are optional - criteria is ignored - """ - if dim == 2: C,D = np.append(paras[0:7],[0.0,0.0]), np.append(paras[7:14],[0.0,0.0]) - else: C,D = paras[0:9], paras[9:18] - if mFix[0]: m = mFix[1] - else: m = paras[-1] - - sv = (sigmas[0] + sigmas[1] + sigmas[2])/3.0 - sdev = np.vstack((sigmas[0:3]-sv,sigmas[3:6])) - ys = lambda sdev, C: np.array([-C[0]*sdev[1]-C[5]*sdev[2], -C[1]*sdev[0]-C[2]*sdev[2], - -C[4]*sdev[0]-C[3]*sdev[1], C[6]*sdev[3], C[7]*sdev[4], C[8]*sdev[5]]) - p,q = ys(sdev, C), ys(sdev, D) - pLambdas, qLambdas = principalStress(p), principalStress(q) # no sort - - m2 = m/2.0; x3 = range(3); num = len(sv) - PiQj = np.array([(pLambdas[i,:]-qLambdas[j,:]) for i in x3 for j in x3]) - QiPj = np.array([(qLambdas[i,:]-pLambdas[j,:]) for i in x3 for j in x3]).reshape(3,3,num) - PiQjs = PiQj**2 - left = np.sum(PiQjs**m2,axis=0) - r = (0.25*left)**(1.0/m)/eqStress - - if not Jac: - return (r - 1.0).ravel() - else: - drdl, drdm = r/m/left, r*math_ln(0.25*left)*(-1.0/m/m) - dldm = np.sum(PiQjs**m2*math_ln(PiQjs),axis=0)*0.5 - dPdc, dQdd = principalStrs_Der(p, sdev, dim), principalStrs_Der(q, sdev, dim) - PiQjs3d = ( PiQjs**(m2-1.0) ).reshape(3,3,num) - dldP = -m*np.array([np.diag(np.dot(PiQjs3d[:,:,i], QiPj [:,:,i])) for i in range(num)]).T - dldQ = m*np.array([np.diag(np.dot(QiPj [:,:,i], PiQjs3d[:,:,i])) for i in range(num)]).T - - jm = drdl*dldm + drdm - jc = drdl*np.sum([dldP[i]*dPdc[i] for i in x3],axis=0) - jd = drdl*np.sum([dldQ[i]*dQdd[i] for i in x3],axis=0) - - if mFix[0]: return np.vstack((jc,jd)).T - else: return np.vstack((jc,jd,jm)).T - -def KarafillisBoyce(eqStress, paras, sigmas, mFix, criteria, dim, Jac=False): - """ - Karafillis-Boyce - - the fitted parameters are - c11,c12,c13,c14,c15,c16,c,m for 3D - c11,c12,c13,c14,c,m for plane stress - 0 1 and self.dimen == 2: - return fitCriteria[self.name]['labels'][1] - else: - return fitCriteria[self.name]['labels'][0] - - def report_name(self): - return fitCriteria[self.name]['name'] - - def fit(self,stress): - global fitResults; fitErrors; fitResidual - if options.exponent > 0.0: nExponent = options.exponent - else: nExponent = 0 - nameCriterion = self.name.lower() - criteria = Criteria(nameCriterion,self.uniaxial,self.expo, self.dimen) - bounds = fitCriteria[nameCriterion]['bound'][dDim] # Default bounds, no bound - guess0 = Guess # Default initial guess, depends on bounds - - if fitResults == []: - initialguess = guess0 - else: - initialguess = np.array(fitResults[-1]) - - ydata = np.zeros(np.shape(stress)[1]) - try: - popt, pcov, infodict, errmsg, ierr = \ - leastsqBound (criteria.fun, initialguess, args=(ydata,stress), - bounds=bounds, Dfun=criteria.jac, full_output=True) - if ierr not in [1, 2, 3, 4]: - raise RuntimeError("Optimal parameters not found: "+errmsg) - else: - residual = criteria.fun(popt, ydata, stress) - fitResidual.append(np.linalg.norm(residual)/np.sqrt(len(residual))) - if (len(ydata) > len(initialguess)) and pcov is not None: - s_sq = (criteria.fun(popt, *(ydata,stress))**2).sum()/(len(ydata)-len(initialguess)) - pcov = pcov * s_sq - perr = np.sqrt(np.diag(pcov)) - fitResults.append(popt.tolist()) - fitErrors .append(perr.tolist()) - - popt = np.concatenate((np.array(popt), np.repeat(options.exponent,nExponent))) - perr = np.concatenate((np.array(perr), np.repeat(0.0,nExponent))) - - damask.util.croak('Needed {} function calls for fitting'.format(infodict['nfev'])) - except Exception as detail: - damask.util.croak(detail) - pass - return popt - -#--------------------------------------------------------------------------------------------------- -class myThread (threading.Thread): - """Runner""" - - def __init__(self, threadID): - threading.Thread.__init__(self) - self.threadID = threadID - def run(self): - semaphore.acquire() - conv=converged() - semaphore.release() - while not conv: - if options.criterion=='facet': - doSimForFacet(self.name) - else: - doSim(self.name) - semaphore.acquire() - conv=converged() - semaphore.release() - -def doSim(thread): - semaphore.acquire() - global myLoad - loadNo=loadcaseNo() - if not os.path.isfile('%s.load'%loadNo): - damask.util.croak('Generating load case for simulation %s (%s)'%(loadNo,thread)) - f=open('%s.load'%loadNo,'w') - f.write(myLoad.getLoadcase(loadNo)) - f.close() - semaphore.release() - else: semaphore.release() - -# if spectralOut does not exist, run simulation - semaphore.acquire() - if not os.path.isfile('%s_%i.spectralOut'%(options.geometry,loadNo)): - damask.util.croak('Starting simulation %i (%s)'%(loadNo,thread)) - semaphore.release() - damask.util.execute('DAMASK_spectral -g %s -l %i'%(options.geometry,loadNo)) - else: semaphore.release() - -# reading values from ASCII file - semaphore.acquire() - damask.util.croak('Reading values from simulation %i (%s)'%(loadNo,thread)) - semaphore.release() - refFile = '%s_%i.yield'%(options.geometry,loadNo) - yieldStress = np.empty((6),'d') - if not os.path.isfile(refFile): - validity = False - else: - validity = True - yieldData = np.loadtxt(refFile) - stress = yieldData[:3] - yieldStress = t33toSym6(stress) -# do the actual fitting procedure and write results to file - semaphore.acquire() - global stressAll - f=open(options.geometry+'_'+options.criterion+'_'+str(time.time())+'.txt','w') - f.write(' '.join([options.fitting]+myFit.report_labels())+'\n') - try: - if validity: - stressAll=np.append(stressAll, yieldStress/stressUnit) - f.write(' '.join(map(str,myFit.fit(stressAll.reshape(len(stressAll)//6,6).transpose())))+'\n') - except Exception: - damask.util.croak('Could not fit results of simulation (%s)'%thread) - semaphore.release() - return - damask.util.croak('\n') - semaphore.release() - -def doSimForFacet(thread): - semaphore.acquire() - global myLoad - loadNo=loadcaseNo() - if not os.path.isfile('%s.load'%loadNo): - damask.util.croak('Generating load case for simulation %s (%s)'%(loadNo,thread)) - f=open('%s.load'%loadNo,'w') - f.write(myLoad.getLoadcase(loadNo)) - f.close() - semaphore.release() - else: semaphore.release() - -# if spectralOut does not exist, run simulation - semaphore.acquire() - if not os.path.isfile('%s_%i.spectralOut'%(options.geometry,loadNo)): - damask.util.croak('Starting simulation %i (%s)'%(loadNo,thread)) - semaphore.release() - damask.util.execute('DAMASK_spectral -g %s -l %i'%(options.geometry,loadNo)) - else: semaphore.release() - -def loadcaseNo(): - global N_simulations - N_simulations+=1 - return N_simulations - -def converged(): - global N_simulations; fitResidual - - if options.criterion=='facet': - if N_simulations == options.numpoints: - return True - else: - return False - else: - if N_simulations < options.max: - if len(fitResidual) > 5 and N_simulations >= options.min: - residualList = np.array(fitResidual[len(fitResidual)-5:]) - if np.std(residualList)/np.max(residualList) < 0.05: - return True - return False - else: - return True - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- - -parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Performs calculations with various loads on given geometry file and fits yield surface. - -""", version = scriptID) - -# maybe make an option to specifiy if 2D/3D fitting should be done? - -parser.add_option('-l','--load' , dest='load', type='float', nargs=3, - help='load: final strain; increments; time %default', metavar='float int float') -parser.add_option('-g','--geometry', dest='geometry', type='string', - help='name of the geometry file [%default]', metavar='string') -parser.add_option('-c','--criterion', dest='criterion', choices=fitCriteria.keys(), - help='criterion for stopping simulations [%default]', metavar='string') -parser.add_option('-f','--fitting', dest='fitting', choices=thresholdParameter, - help='yield criterion [%default]', metavar='string') -parser.add_option('-y','--yieldvalue', dest='yieldValue', type='float', - help='yield points %default', metavar='float') -parser.add_option('--min', dest='min', type='int', - help='minimum number of simulations [%default]', metavar='int') -parser.add_option('--max', dest='max', type='int', - help='maximum number of iterations [%default]', metavar='int') -parser.add_option('-t','--threads', dest='threads', type='int', - help='number of parallel executions [%default]', metavar='int') -parser.add_option('-b','--bound', dest='bounds', type='float', nargs=2, - help='yield points: start; end; count %default', metavar='float float') -parser.add_option('-d','--dimension', dest='dimension', type='choice', choices=['2','3'], - help='dimension of the virtual test [%default]', metavar='int') -parser.add_option('-e', '--exponent', dest='exponent', type='float', - help='exponent of non-quadratic criteria', metavar='int') -parser.add_option('-u', '--uniaxial', dest='eqStress', type='float', - help='Equivalent stress', metavar='float') -parser.add_option('--flag', dest='flag', type='string', - help='yield stop flag, totalStrain, plasticStrain or plasticWork', metavar='string') -parser.add_option('--numpoints', dest='numpoints', type='int', - help='number of yield points to fit facet potential [%default]', metavar='int') -parser.add_option('--order', dest='order', type='int', - help='order of facet potential [%default]', metavar='int') - -parser.set_defaults(min = 12, - max = 20, - threads = 4, - yieldValue = 0.002, - load = (0.010,100,100.0), - criterion = 'vonmises', - fitting = 'totalshear', - geometry = '20grains16x16x16', - bounds = None, - dimension = '3', - exponent = -1.0, - flag = 'totalStrain', - numpoints = 100, - order = 8 - ) - -options = parser.parse_args()[0] - -if options.threads < 1: - parser.error('invalid number of threads {}'.format(options.threads)) -if options.min < 0: - parser.error('invalid minimum number of simulations {}'.format(options.min)) -if options.max < options.min: - parser.error('invalid maximum number of simulations (below minimum)') - -for check in [options.geometry+'.geom','numerics.config','material.config']: - if not os.path.isfile(check): - damask.util.croak('"{}" file not found'.format(check)) - -options.dimension = int(options.dimension) - -stressUnit = 1.0e9 if options.criterion == 'hill1948' else 1.0e6 - - -if options.dimension not in fitCriteria[options.criterion]['dimen']: - parser.error('invalid dimension for selected criterion') - -if options.criterion not in ['vonmises','tresca','drucker','hill1948'] and options.eqStress is None: - parser.error('please specify an equivalent stress (e.g. fitting to von Mises)') - -# global variables -fitResults = [] -fitErrors = [] -fitResidual = [] -stressAll= np.zeros(0,'d').reshape(0,0) -N_simulations=0 -Guess = [] -threads=[] -semaphore=threading.Semaphore(1) -dDim = None -myLoad = None -myFit = None - -if options.criterion == 'facet': - run = runFit(options.exponent, options.eqStress, options.dimension, options.criterion) -else: - run = runFit(options.exponent, options.eqStress, options.dimension, options.criterion) - -damask.util.croak('Finished fitting to yield criteria') diff --git a/processing/post/DADF5_postResults.py b/processing/post/DADF5_postResults.py index efbf84b98..a6dc0b34a 100755 --- a/processing/post/DADF5_postResults.py +++ b/processing/post/DADF5_postResults.py @@ -39,61 +39,36 @@ for filename in options.filenames: results = damask.DADF5(filename) if not results.structured: continue - delta = results.size/results.grid*0.5 - x, y, z = np.meshgrid(np.linspace(delta[2],results.size[2]-delta[2],results.grid[2]), - np.linspace(delta[1],results.size[1]-delta[1],results.grid[1]), - np.linspace(delta[0],results.size[0]-delta[0],results.grid[0]), - indexing = 'ij') - - coords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) + if results.version_major == 0 and results.version_minor >= 5: + coords = damask.grid_filters.cell_coord0(results.grid,results.size,results.origin) + else: + coords = damask.grid_filters.cell_coord0(results.grid,results.size) N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 N_digits = 5 # hack to keep test intact for i,inc in enumerate(results.iter_visible('increments')): print('Output step {}/{}'.format(i+1,len(results.increments))) - header = '1 header\n' - - data = np.array([int(inc[3:]) for j in range(np.product(results.grid))]).reshape([np.product(results.grid),1]) - header+= 'inc' - - coords = coords.reshape([np.product(results.grid),3]) - data = np.concatenate((data,coords),1) - header+=' 1_pos 2_pos 3_pos' + table = damask.Table(np.ones(np.product(results.grid),dtype=int)*int(inc[3:]),{'inc':(1,)}) + table.add('pos',coords.reshape((-1,3))) results.set_visible('materialpoints',False) results.set_visible('constituents', True) for label in options.con: x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0,plain=True) - d = np.product(np.shape(array)[1:]) - data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) - - if d>1: - header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) - else: - header+=' '+label + if len(x) != 0: + table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1))) results.set_visible('constituents', False) results.set_visible('materialpoints',True) for label in options.mat: x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0,plain=True) - d = np.product(np.shape(array)[1:]) - data = np.concatenate((data,np.reshape(array,[np.product(results.grid),d])),1) - - if d>1: - header+= ''.join([' {}_{}'.format(j+1,label) for j in range(d)]) - else: - header+=' '+label + if len(x) != 0: + table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1))) dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) if not os.path.isdir(dirname): os.mkdir(dirname,0o755) file_out = '{}_inc{}.txt'.format(os.path.splitext(os.path.split(filename)[-1])[0], inc[3:].zfill(N_digits)) - np.savetxt(os.path.join(dirname,file_out),data,header=header,comments='') + table.to_ASCII(os.path.join(dirname,file_out)) diff --git a/processing/post/DADF5_vtk_cells.py b/processing/post/DADF5_vtk_cells.py deleted file mode 100755 index b8875f4e9..000000000 --- a/processing/post/DADF5_vtk_cells.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 - -import os -import argparse - -import h5py -import numpy as np -import vtk -from vtk.util import numpy_support - -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- -parser = argparse.ArgumentParser() - -#ToDo: We need to decide on a way of handling arguments of variable lentght -#https://stackoverflow.com/questions/15459997/passing-integer-lists-to-python - -#parser.add_argument('--version', action='version', version='%(prog)s {}'.format(scriptID)) -parser.add_argument('filenames', nargs='+', - help='DADF5 files') -parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string', - help='name of subdirectory relative to the location of the DADF5 file to hold output') -parser.add_argument('--mat', nargs='+', - help='labels for materialpoint',dest='mat') -parser.add_argument('--con', nargs='+', - help='labels for constituent',dest='con') - -options = parser.parse_args() - -if options.mat is None: options.mat=[] -if options.con is None: options.con=[] - -# --- loop over input files ------------------------------------------------------------------------ - -for filename in options.filenames: - results = damask.DADF5(filename) - - if results.structured: # for grid solvers use rectilinear grid - grid = vtk.vtkRectilinearGrid() - coordArray = [vtk.vtkDoubleArray(), - vtk.vtkDoubleArray(), - vtk.vtkDoubleArray(), - ] - - grid.SetDimensions(*(results.grid+1)) - for dim in [0,1,2]: - for c in np.linspace(0,results.size[dim],1+results.grid[dim]): - coordArray[dim].InsertNextValue(c) - - grid.SetXCoordinates(coordArray[0]) - grid.SetYCoordinates(coordArray[1]) - grid.SetZCoordinates(coordArray[2]) - else: - nodes = vtk.vtkPoints() - with h5py.File(filename) as f: - nodes.SetData(numpy_support.numpy_to_vtk(f['/geometry/x_n'][()],deep=True)) - grid = vtk.vtkUnstructuredGrid() - grid.SetPoints(nodes) - grid.Allocate(f['/geometry/T_c'].shape[0]) - for i in f['/geometry/T_c']: - grid.InsertNextCell(vtk.VTK_HEXAHEDRON,8,i-1) - - N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 - for i,inc in enumerate(results.iter_visible('increments')): - print('Output step {}/{}'.format(i+1,len(results.increments))) - vtk_data = [] - - results.set_visible('materialpoints',False) - results.set_visible('constituents', True) - for label in options.con: - for p in results.iter_visible('con_physics'): - if p != 'generic': - for c in results.iter_visible('constituents'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - grid.GetCellData().AddArray(vtk_data[-1]) - else: - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - grid.GetCellData().AddArray(vtk_data[-1]) - - results.set_visible('constituents', False) - results.set_visible('materialpoints',True) - for label in options.mat: - for p in results.iter_visible('mat_physics'): - if p != 'generic': - for m in results.iter_visible('materialpoints'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - grid.GetCellData().AddArray(vtk_data[-1]) - else: - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - grid.GetCellData().AddArray(vtk_data[-1]) - - writer = vtk.vtkXMLRectilinearGridWriter() if results.structured else \ - vtk.vtkXMLUnstructuredGridWriter() - - results.set_visible('constituents', False) - results.set_visible('materialpoints',False) - x = results.get_dataset_location('u_n') - vtk_data.append(numpy_support.numpy_to_vtk(num_array=results.read_dataset(x,0),deep=True,array_type=vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('u') - grid.GetPointData().AddArray(vtk_data[-1]) - - dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) - if not os.path.isdir(dirname): - os.mkdir(dirname,0o755) - file_out = '{}_inc{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0], - inc[3:].zfill(N_digits), - writer.GetDefaultFileExtension()) - - writer.SetCompressorTypeToZLib() - writer.SetDataModeToBinary() - writer.SetFileName(os.path.join(dirname,file_out)) - writer.SetInputData(grid) - - writer.Write() diff --git a/processing/post/DADF5_vtk_points.py b/processing/post/DADF5_vtk_points.py deleted file mode 100755 index 9265cc3a0..000000000 --- a/processing/post/DADF5_vtk_points.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 - -import os -import argparse - -import numpy as np -import vtk -from vtk.util import numpy_support - -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - -# -------------------------------------------------------------------- -# MAIN -# -------------------------------------------------------------------- -parser = argparse.ArgumentParser() - -#ToDo: We need to decide on a way of handling arguments of variable lentght -#https://stackoverflow.com/questions/15459997/passing-integer-lists-to-python - -#parser.add_argument('--version', action='version', version='%(prog)s {}'.format(scriptID)) -parser.add_argument('filenames', nargs='+', - help='DADF5 files') -parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string', - help='name of subdirectory relative to the location of the DADF5 file to hold output') -parser.add_argument('--mat', nargs='+', - help='labels for materialpoint',dest='mat') -parser.add_argument('--con', nargs='+', - help='labels for constituent',dest='con') - -options = parser.parse_args() - -if options.mat is None: options.mat=[] -if options.con is None: options.con=[] - -# --- loop over input files ------------------------------------------------------------------------ - -for filename in options.filenames: - results = damask.DADF5(filename) - - Points = vtk.vtkPoints() - Vertices = vtk.vtkCellArray() - for c in results.cell_coordinates(): - pointID = Points.InsertNextPoint(c) - Vertices.InsertNextCell(1) - Vertices.InsertCellPoint(pointID) - - Polydata = vtk.vtkPolyData() - Polydata.SetPoints(Points) - Polydata.SetVerts(Vertices) - Polydata.Modified() - - N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 - for i,inc in enumerate(results.iter_visible('increments')): - print('Output step {}/{}'.format(i+1,len(results.increments))) - vtk_data = [] - - results.set_visible('materialpoints',False) - results.set_visible('constituents', True) - for label in options.con: - - for p in results.iter_visible('con_physics'): - if p != 'generic': - for c in results.iter_visible('constituents'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - Polydata.GetCellData().AddArray(vtk_data[-1]) - else: - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - Polydata.GetCellData().AddArray(vtk_data[-1]) - - results.set_visible('constituents', False) - results.set_visible('materialpoints',True) - for label in options.mat: - for p in results.iter_visible('mat_physics'): - if p != 'generic': - for m in results.iter_visible('materialpoints'): - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - Polydata.GetCellData().AddArray(vtk_data[-1]) - else: - x = results.get_dataset_location(label) - if len(x) == 0: - continue - array = results.read_dataset(x,0) - shape = [array.shape[0],np.product(array.shape[1:])] - vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape),deep=True,array_type= vtk.VTK_DOUBLE)) - vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) - Polydata.GetCellData().AddArray(vtk_data[-1]) - - writer = vtk.vtkXMLPolyDataWriter() - - - dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) - if not os.path.isdir(dirname): - os.mkdir(dirname,0o755) - file_out = '{}_inc{}.{}'.format(os.path.splitext(os.path.split(filename)[-1])[0], - inc[3:].zfill(N_digits), - writer.GetDefaultFileExtension()) - - writer.SetCompressorTypeToZLib() - writer.SetDataModeToBinary() - writer.SetFileName(os.path.join(dirname,file_out)) - writer.SetInputData(Polydata) - - writer.Write() diff --git a/processing/post/addCalculation.py b/processing/post/addCalculation.py index db0428753..b1eed3c6d 100755 --- a/processing/post/addCalculation.py +++ b/processing/post/addCalculation.py @@ -4,7 +4,7 @@ import os import sys from optparse import OptionParser import re -import collections +from collections.abc import Iterable import math # noqa import scipy # noqa @@ -18,7 +18,7 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) def listify(x): - return x if isinstance(x, collections.Iterable) else [x] + return x if isinstance(x, Iterable) else [x] # -------------------------------------------------------------------- @@ -65,9 +65,10 @@ for i in range(len(options.formulas)): if filenames == []: filenames = [None] for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue + try: + table = damask.ASCIItable(name = name, buffered = False) + except IOError: + continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------- diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index 7556cb863..29e874614 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 import os -import math +import sys +from io import StringIO from optparse import OptionParser import numpy as np -import scipy.ndimage import damask @@ -13,78 +13,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -#-------------------------------------------------------------------------------------------------- -def cell2node(cellData,grid): - - nodeData = 0.0 - datalen = np.array(cellData.shape[3:]).prod() - - for i in range(datalen): - node = scipy.ndimage.convolve(cellData.reshape(tuple(grid[::-1])+(datalen,))[...,i], - np.ones((2,2,2))/8., # 2x2x2 neighborhood of cells - mode = 'wrap', - origin = -1, # offset to have cell origin as center - ) # now averaged at cell origins - node = np.append(node,node[np.newaxis,0,:,:,...],axis=0) # wrap along z - node = np.append(node,node[:,0,np.newaxis,:,...],axis=1) # wrap along y - node = np.append(node,node[:,:,0,np.newaxis,...],axis=2) # wrap along x - - nodeData = node[...,np.newaxis] if i==0 else np.concatenate((nodeData,node[...,np.newaxis]),axis=-1) - - return nodeData - -#-------------------------------------------------------------------------------------------------- -def deformationAvgFFT(F,grid,size,nodal=False,transformed=False): - """Calculate average cell center (or nodal) deformation for deformation gradient field specified in each grid cell""" - if nodal: - x, y, z = np.meshgrid(np.linspace(0,size[2],1+grid[2]), - np.linspace(0,size[1],1+grid[1]), - np.linspace(0,size[0],1+grid[0]), - indexing = 'ij') - else: - x, y, z = np.meshgrid(np.linspace(size[2]/grid[2]/2.,size[2]-size[2]/grid[2]/2.,grid[2]), - np.linspace(size[1]/grid[1]/2.,size[1]-size[1]/grid[1]/2.,grid[1]), - np.linspace(size[0]/grid[0]/2.,size[0]-size[0]/grid[0]/2.,grid[0]), - indexing = 'ij') - - origCoords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) - - F_fourier = F if transformed else np.fft.rfftn(F,axes=(0,1,2)) # transform or use provided data - Favg = np.real(F_fourier[0,0,0,:,:])/grid.prod() # take zero freq for average - avgDeformation = np.einsum('ml,ijkl->ijkm',Favg,origCoords) # dX = Favg.X - - return avgDeformation - -#-------------------------------------------------------------------------------------------------- -def displacementFluctFFT(F,grid,size,nodal=False,transformed=False): - """Calculate cell center (or nodal) displacement for deformation gradient field specified in each grid cell""" - integrator = 0.5j * size / math.pi - - kk, kj, ki = np.meshgrid(np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2])), - np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1])), - np.arange(grid[0]//2+1), - indexing = 'ij') - k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3) - k_sSquared = np.einsum('...l,...l',k_s,k_s) - k_sSquared[0,0,0] = 1.0 # ignore global average frequency - -#-------------------------------------------------------------------------------------------------- -# integration in Fourier space - - displacement_fourier = -np.einsum('ijkml,ijkl,l->ijkm', - F if transformed else np.fft.rfftn(F,axes=(0,1,2)), - k_s, - integrator, - ) / k_sSquared[...,np.newaxis] - -#-------------------------------------------------------------------------------------------------- -# backtransformation to real space - - displacement = np.fft.irfftn(displacement_fourier,grid[::-1],axes=(0,1,2)) - - return cell2node(displacement,grid) if nodal else displacement - - def volTetrahedron(coords): """ Return the volume of the tetrahedron with given vertices or sides. @@ -133,10 +61,10 @@ def volTetrahedron(coords): def volumeMismatch(size,F,nodes): """ - Calculates the volume mismatch + Calculates the volume mismatch. volume mismatch is defined as the difference between volume of reconstructed - (compatible) cube and determinant of defgrad at the FP + (compatible) cube and determinant of deformation gradient at Fourier point. """ coords = np.empty([8,3]) vMismatch = np.empty(grid[::-1]) @@ -169,11 +97,11 @@ def volumeMismatch(size,F,nodes): def shapeMismatch(size,F,nodes,centres): """ - Routine to calculate the shape mismatch + Routine to calculate the shape mismatch. shape mismatch is defined as difference between the vectors from the central point to the corners of reconstructed (combatible) volume element and the vectors calculated by deforming - the initial volume element with the current deformation gradient + the initial volume element with the current deformation gradient. """ coordsInitial = np.empty([8,3]) sMismatch = np.empty(grid[::-1]) @@ -241,92 +169,29 @@ parser.set_defaults(pos = 'pos', ) (options,filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] + for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue damask.util.report(scriptName,name) - -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - if table.label_dimension(options.defgrad) != 9: - errors.append('deformation gradient "{}" is not a 3x3 tensor.'.format(options.defgrad)) + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) - coordDim = table.label_dimension(options.pos) - if not 3 >= coordDim >= 1: - errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - elif coordDim < 3: - remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim, - 's' if coordDim < 2 else '', - options.pos)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray([options.defgrad,options.pos]) - table.data_rewind() - - if table.data[:,9:].shape[1] < 3: - table.data = np.hstack((table.data, - np.zeros((table.data.shape[0], - 3-table.data[:,9:].shape[1]),dtype='f'))) # fill coords up to 3D with zeros - - grid,size = damask.util.coordGridAndSize(table.data[:,9:12]) - N = grid.prod() - - if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid)) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue + F = table.get(options.defgrad).reshape(grid[2],grid[1],grid[0],3,3) + nodes = damask.grid_filters.node_coord(size,F) -# -----------------------------process data and assemble header ------------------------------------- - - F_fourier = np.fft.rfftn(table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),axes=(0,1,2)) # perform transform only once... - nodes = displacementFluctFFT(F_fourier,grid,size,True,transformed=True)\ - + deformationAvgFFT (F_fourier,grid,size,True,transformed=True) - if options.shape: - table.labels_append(['shapeMismatch({})'.format(options.defgrad)]) - centres = displacementFluctFFT(F_fourier,grid,size,False,transformed=True)\ - + deformationAvgFFT (F_fourier,grid,size,False,transformed=True) - + centers = damask.grid_filters.cell_coord(size,F) + shapeMismatch = shapeMismatch( size,table.get(options.defgrad).reshape(grid[2],grid[1],grid[0],3,3),nodes,centers) + table.add('shapeMismatch(({}))'.format(options.defgrad), + shapeMismatch.reshape((-1,1)), + scriptID+' '+' '.join(sys.argv[1:])) + if options.volume: - table.labels_append(['volMismatch({})'.format(options.defgrad)]) + volumeMismatch = volumeMismatch(size,table.get(options.defgrad).reshape(grid[2],grid[1],grid[0],3,3),nodes) + table.add('volMismatch(({}))'.format(options.defgrad), + volumeMismatch.reshape((-1,1)), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_write() - if options.shape: - shapeMismatch = shapeMismatch( size,table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),nodes,centres) - if options.volume: - volumeMismatch = volumeMismatch(size,table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),nodes) - -# ------------------------------------------ output data ------------------------------------------- - for i in range(grid[2]): - for j in range(grid[1]): - for k in range(grid[0]): - table.data_read() - if options.shape: table.data_append(shapeMismatch[i,j,k]) - if options.volume: table.data_append(volumeMismatch[i,j,k]) - table.data_write() - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addCumulative.py b/processing/post/addCumulative.py index b81a9d14f..958c6a70a 100755 --- a/processing/post/addCumulative.py +++ b/processing/post/addCumulative.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -22,79 +23,26 @@ Add cumulative (sum of first to current row) values for given label(s). """, version = scriptID) parser.add_option('-l','--label', - dest='label', + dest='labels', action = 'extend', metavar = '', help = 'columns to cumulate') - parser.add_option('-p','--product', dest='product', action = 'store_true', help = 'product of values instead of sum') (options,filenames) = parser.parse_args() - -if options.label is None: - parser.error('no data column(s) specified.') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.labels is None: + parser.error('no data column(s) specified.') + for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except IOError: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for label in options.labels: + table.add('cum_{}({})'.format('prod' if options.product else 'sum',label), + np.cumprod(table.get(label),0) if options.product else np.cumsum(table.get(label),0), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - columns = [] - dims = [] - how = 'prod' if options.product else 'sum' - - for what in options.label: - dim = table.label_dimension(what) - if dim < 0: remarks.append('column {} not found...'.format(what)) - else: - dims.append(dim) - columns.append(table.label_index(what)) - table.labels_append('cum_{}({})'.format(how,what) if dim == 1 else - ['{}_cum_{}({})'.format(i+1,how,what) for i in range(dim)] ) # extend ASCII header with new labels - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - mask = [] - for col,dim in zip(columns,dims): mask += range(col,col+dim) # isolate data columns to cumulate - cumulated = np.ones(len(mask)) if options.product else np.zeros(len(mask)) # prepare output field - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - if options.product: - for i,col in enumerate(mask): - cumulated[i] *= float(table.data[col]) # cumulate values (multiplication) - else: - for i,col in enumerate(mask): - cumulated[i] += float(table.data[col]) # cumulate values (addition) - table.data_append(cumulated) - - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index 484af9677..25639dc7c 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -12,48 +13,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def merge_dicts(*dict_args): - """Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts.""" - result = {} - for dictionary in dict_args: - result.update(dictionary) - return result - -def curlFFT(geomdim,field): - """Calculate curl of a vector or tensor field by transforming into Fourier space.""" - shapeFFT = np.array(np.shape(field))[0:3] - grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size - - field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT) - curl_fourier = np.empty(field_fourier.shape,'c16') - - # differentiation in Fourier space - TWOPIIMG = 2.0j*np.pi - einsums = { - 3:'slm,ijkl,ijkm->ijks', # vector, 3 -> 3 - 9:'slm,ijkl,ijknm->ijksn', # tensor, 3x3 -> 3x3 - } - k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0] - if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1] - if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_si = np.arange(grid[0]//2+1)/geomdim[2] - - kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij') - k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16') - - e = np.zeros((3, 3, 3)) - e[0, 1, 2] = e[1, 2, 0] = e[2, 0, 1] = 1.0 # Levi-Civita symbols - e[0, 2, 1] = e[2, 1, 0] = e[1, 0, 2] = -1.0 - - curl_fourier = np.einsum(einsums[n],e,k_s,field_fourier)*TWOPIIMG - - return np.fft.irfftn(curl_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,n]) - # -------------------------------------------------------------------- # MAIN @@ -61,8 +20,7 @@ def curlFFT(geomdim,field): parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ Add column(s) containing curl of requested column(s). -Operates on periodic ordered three-dimensional data sets -of vector and tensor fields. +Operates on periodic ordered three-dimensional data sets of vector and tensor fields. """, version = scriptID) parser.add_option('-p','--pos','--periodiccellcenter', @@ -70,93 +28,30 @@ parser.add_option('-p','--pos','--periodiccellcenter', type = 'string', metavar = 'string', help = 'label of coordinates [%default]') parser.add_option('-l','--label', - dest = 'data', + dest = 'labels', action = 'extend', metavar = '', help = 'label(s) of field values') parser.set_defaults(pos = 'pos', ) - (options,filenames) = parser.parse_args() - -if options.data is None: parser.error('no data column specified.') - -# --- define possible data types ------------------------------------------------------------------- - -datatypes = { - 3: {'name': 'vector', - 'shape': [3], - }, - 9: {'name': 'tensor', - 'shape': [3,3], - }, - } - -# --- loop over input files ------------------------------------------------------------------------ - if filenames == []: filenames = [None] +if options.labels is None: parser.error('no data column specified.') + for name in filenames: - try: table = damask.ASCIItable(name = name,buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# --- interpret header ---------------------------------------------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) - table.head_read() - - remarks = [] - errors = [] - active = [] - - coordDim = table.label_dimension(options.pos) - if coordDim != 3: - errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos)) - else: coordCol = table.label_index(options.pos) - - for me in options.data: - dim = table.label_dimension(me) - if dim in datatypes: - active.append(merge_dicts({'label':me},datatypes[dim])) - remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me)) - else: - remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \ - '"{}" not found...'.format(me) ) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for data in active: - table.labels_append(['{}_curlFFT({})'.format(i+1,data['label']) - for i in range(np.prod(np.array(data['shape'])))]) # extend ASCII header with new labels - table.head_write() - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) - -# ------------------------------------------ process value field ----------------------------------- - - stack = [table.data] - for data in active: - # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation - stack.append(curlFFT(size[::-1], - table.data[:,table.label_indexrange(data['label'])]. - reshape(grid[::-1].tolist()+data['shape']))) - -# ------------------------------------------ output result ----------------------------------------- - - if len(stack) > 1: table.data = np.hstack(tuple(stack)) - table.data_writeArray('%.12g') - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + for label in options.labels: + field = table.get(label) + shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor + field = field.reshape(np.append(grid[::-1],shape)) + table.add('curlFFT({})'.format(label), + damask.grid_filters.curl(size[::-1],field).reshape((-1,np.prod(shape))), + scriptID+' '+' '.join(sys.argv[1:])) + + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addDerivative.py b/processing/post/addDerivative.py index 8ebfdf2da..4e9410794 100755 --- a/processing/post/addDerivative.py +++ b/processing/post/addDerivative.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -30,7 +31,7 @@ def derivative(coordinates,what): (coordinates[0] - coordinates[1]) result[-1,:] = (what[-1,:] - what[-2,:]) / \ (coordinates[-1] - coordinates[-2]) - + return result @@ -48,78 +49,26 @@ parser.add_option('-c','--coordinates', type = 'string', metavar='string', help = 'heading of coordinate column') parser.add_option('-l','--label', - dest = 'label', + dest = 'labels', action = 'extend', metavar = '', help = 'heading of column(s) to differentiate') (options,filenames) = parser.parse_args() - -if options.coordinates is None: - parser.error('no coordinate column specified.') -if options.label is None: - parser.error('no data column specified.') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.coordinates is None: + parser.error('no coordinate column specified.') +if options.labels is None: + parser.error('no data column specified.') + for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for label in options.labels: + table.add('d({})/d({})'.format(label,options.coordinates), + derivative(table.get(options.coordinates),table.get(label)), + scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - columns = [] - dims = [] - - if table.label_dimension(options.coordinates) != 1: - errors.append('coordinate column {} is not scalar.'.format(options.coordinates)) - - for what in options.label: - dim = table.label_dimension(what) - if dim < 0: remarks.append('column {} not found...'.format(what)) - else: - dims.append(dim) - columns.append(table.label_index(what)) - table.labels_append('d({})/d({})'.format(what,options.coordinates) if dim == 1 else - ['{}_d({})/d({})'.format(i+1,what,options.coordinates) for i in range(dim)] ) # extend ASCII header with new labels - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - table.data_readArray() - - mask = [] - for col,dim in zip(columns,dims): mask += range(col,col+dim) # isolate data columns to differentiate - - differentiated = derivative(table.data[:,table.label_index(options.coordinates)].reshape((len(table.data),1)), - table.data[:,mask]) # calculate numerical derivative - - table.data = np.hstack((table.data,differentiated)) - -# ------------------------------------------ output result ----------------------------------------- - - table.data_writeArray() - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addDisplacement.py b/processing/post/addDisplacement.py index 99d07fd18..59630a6c6 100755 --- a/processing/post/addDisplacement.py +++ b/processing/post/addDisplacement.py @@ -2,10 +2,10 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np -import scipy.ndimage import damask @@ -14,79 +14,6 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -#-------------------------------------------------------------------------------------------------- -def cell2node(cellData,grid): - - nodeData = 0.0 - datalen = np.array(cellData.shape[3:]).prod() - - for i in range(datalen): - node = scipy.ndimage.convolve(cellData.reshape(tuple(grid[::-1])+(datalen,))[...,i], - np.ones((2,2,2))/8., # 2x2x2 neighborhood of cells - mode = 'wrap', - origin = -1, # offset to have cell origin as center - ) # now averaged at cell origins - node = np.append(node,node[np.newaxis,0,:,:,...],axis=0) # wrap along z - node = np.append(node,node[:,0,np.newaxis,:,...],axis=1) # wrap along y - node = np.append(node,node[:,:,0,np.newaxis,...],axis=2) # wrap along x - - nodeData = node[...,np.newaxis] if i==0 else np.concatenate((nodeData,node[...,np.newaxis]),axis=-1) - - return nodeData - -#-------------------------------------------------------------------------------------------------- -def displacementAvgFFT(F,grid,size,nodal=False,transformed=False): - """Calculate average cell center (or nodal) displacement for deformation gradient field specified in each grid cell""" - if nodal: - x, y, z = np.meshgrid(np.linspace(0,size[2],1+grid[2]), - np.linspace(0,size[1],1+grid[1]), - np.linspace(0,size[0],1+grid[0]), - indexing = 'ij') - else: - delta = size/grid*0.5 - x, y, z = np.meshgrid(np.linspace(delta[2],size[2]-delta[2],grid[2]), - np.linspace(delta[1],size[1]-delta[1],grid[1]), - np.linspace(delta[0],size[0]-delta[0],grid[0]), - indexing = 'ij') - - origCoords = np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) - - F_fourier = F if transformed else np.fft.rfftn(F,axes=(0,1,2)) # transform or use provided data - Favg = np.real(F_fourier[0,0,0,:,:])/grid.prod() # take zero freq for average - avgDisplacement = np.einsum('ml,ijkl->ijkm',Favg-np.eye(3),origCoords) # dX = Favg.X - - return avgDisplacement - -#-------------------------------------------------------------------------------------------------- -def displacementFluctFFT(F,grid,size,nodal=False,transformed=False): - """Calculate cell center (or nodal) displacement for deformation gradient field specified in each grid cell""" - integrator = 0.5j * size / np.pi - - kk, kj, ki = np.meshgrid(np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2])), - np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1])), - np.arange(grid[0]//2+1), - indexing = 'ij') - k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3) - k_sSquared = np.einsum('...l,...l',k_s,k_s) - k_sSquared[0,0,0] = 1.0 # ignore global average frequency - -#-------------------------------------------------------------------------------------------------- -# integration in Fourier space - - displacement_fourier = -np.einsum('ijkml,ijkl,l->ijkm', - F if transformed else np.fft.rfftn(F,axes=(0,1,2)), - k_s, - integrator, - ) / k_sSquared[...,np.newaxis] - -#-------------------------------------------------------------------------------------------------- -# backtransformation to real space - - displacement = np.fft.irfftn(displacement_fourier,grid[::-1],axes=(0,1,2)) - - return cell2node(displacement,grid) if nodal else displacement - - # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- @@ -100,7 +27,7 @@ Outputs at cell centers or cell nodes (into separate file). parser.add_option('-f', '--defgrad', - dest = 'defgrad', + dest = 'f', metavar = 'string', help = 'label of deformation gradient [%default]') parser.add_option('-p', @@ -113,108 +40,34 @@ parser.add_option('--nodal', action = 'store_true', help = 'output nodal (instead of cell-centered) displacements') -parser.set_defaults(defgrad = 'f', - pos = 'pos', +parser.set_defaults(f = 'f', + pos = 'pos', ) (options,filenames) = parser.parse_args() -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - outname = (os.path.splitext(name)[0] + - '_nodal' + - os.path.splitext(name)[1]) if (options.nodal and name) else None - try: table = damask.ASCIItable(name = name, - outname = outname, - buffered = False) - except: continue - damask.util.report(scriptName,'{}{}'.format(name if name else '', - ' --> {}'.format(outname) if outname else '')) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - - if table.label_dimension(options.defgrad) != 9: - errors.append('deformation gradient "{}" is not a 3x3 tensor.'.format(options.defgrad)) - - coordDim = table.label_dimension(options.pos) - if not 3 >= coordDim >= 1: - errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - elif coordDim < 3: - remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim, - 's' if coordDim < 2 else '', - options.pos)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray([options.defgrad,options.pos]) - table.data_rewind() - - if len(table.data.shape) < 2: table.data.shape += (1,) # expand to 2D shape - if table.data[:,9:].shape[1] < 3: - table.data = np.hstack((table.data, - np.zeros((table.data.shape[0], - 3-table.data[:,9:].shape[1]),dtype='f'))) # fill coords up to 3D with zeros - - grid,size = damask.util.coordGridAndSize(table.data[:,9:12]) - N = grid.prod() - - if N != len(table.data): errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*grid)) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ process data ------------------------------------------ - - F_fourier = np.fft.rfftn(table.data[:,:9].reshape(grid[2],grid[1],grid[0],3,3),axes=(0,1,2)) # perform transform only once... - - fluctDisplacement = displacementFluctFFT(F_fourier,grid,size,options.nodal,transformed=True) - avgDisplacement = displacementAvgFFT (F_fourier,grid,size,options.nodal,transformed=True) - -# ------------------------------------------ assemble header --------------------------------------- - - if options.nodal: - table.info_clear() - table.labels_clear() - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append((['{}_pos' .format(i+1) for i in range(3)] if options.nodal else []) + - ['{}_avg({}).{}' .format(i+1,options.defgrad,options.pos) for i in range(3)] + - ['{}_fluct({}).{}'.format(i+1,options.defgrad,options.pos) for i in range(3)] ) - table.head_write() - -# ------------------------------------------ output data ------------------------------------------- - - Zrange = np.linspace(0,size[2],1+grid[2]) if options.nodal else range(grid[2]) - Yrange = np.linspace(0,size[1],1+grid[1]) if options.nodal else range(grid[1]) - Xrange = np.linspace(0,size[0],1+grid[0]) if options.nodal else range(grid[0]) - - for i,z in enumerate(Zrange): - for j,y in enumerate(Yrange): - for k,x in enumerate(Xrange): - if options.nodal: table.data_clear() - else: table.data_read() - table.data_append([x,y,z] if options.nodal else []) - table.data_append(list( avgDisplacement[i,j,k,:])) - table.data_append(list(fluctDisplacement[i,j,k,:])) - table.data_write() - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) + + F = table.get(options.f).reshape(np.append(grid[::-1],(3,3))) + if options.nodal: + table = damask.Table(damask.grid_filters.node_coord0(grid[::-1],size[::-1]).reshape((-1,3)), + {'pos':(3,)}) + table.add('avg({}).{}'.format(options.f,options.pos), + damask.grid_filters.node_displacement_avg(size[::-1],F).reshape((-1,3)), + scriptID+' '+' '.join(sys.argv[1:])) + table.add('fluct({}).{}'.format(options.f,options.pos), + damask.grid_filters.node_displacement_fluct(size[::-1],F).reshape((-1,3)), + scriptID+' '+' '.join(sys.argv[1:])) + table.to_ASCII(sys.stdout if name is None else os.path.splitext(name)[0]+'_nodal.txt') + else: + table.add('avg({}).{}'.format(options.f,options.pos), + damask.grid_filters.cell_displacement_avg(size[::-1],F).reshape((-1,3)), + scriptID+' '+' '.join(sys.argv[1:])) + table.add('fluct({}).{}'.format(options.f,options.pos), + damask.grid_filters.cell_displacement_fluct(size[::-1],F).reshape((-1,3)), + scriptID+' '+' '.join(sys.argv[1:])) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addDivergence.py b/processing/post/addDivergence.py index 31a18f8e1..585ebb5a5 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -12,53 +13,14 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def merge_dicts(*dict_args): - """Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts.""" - result = {} - for dictionary in dict_args: - result.update(dictionary) - return result - -def divFFT(geomdim,field): - """Calculate divergence of a vector or tensor field by transforming into Fourier space.""" - shapeFFT = np.array(np.shape(field))[0:3] - grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size - - field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT) - div_fourier = np.empty(field_fourier.shape[0:len(np.shape(field))-1],'c16') - - # differentiation in Fourier space - TWOPIIMG = 2.0j*np.pi - einsums = { - 3:'ijkl,ijkl->ijk', # vector, 3 -> 1 - 9:'ijkm,ijklm->ijkl', # tensor, 3x3 -> 3 - } - k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0] - if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1] - if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_si = np.arange(grid[0]//2+1)/geomdim[2] - - kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij') - k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16') - - div_fourier = np.einsum(einsums[n],k_s,field_fourier)*TWOPIIMG - - return np.fft.irfftn(div_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,n//3]) - # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog option(s) [ASCIItable(s)]', description = """ -Add column(s) containing curl of requested column(s). -Operates on periodic ordered three-dimensional data sets -of vector and tensor fields. +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ +Add column(s) containing divergence of requested column(s). +Operates on periodic ordered three-dimensional data sets of vector and tensor fields. """, version = scriptID) parser.add_option('-p','--pos','--periodiccellcenter', @@ -66,95 +28,30 @@ parser.add_option('-p','--pos','--periodiccellcenter', type = 'string', metavar = 'string', help = 'label of coordinates [%default]') parser.add_option('-l','--label', - dest = 'data', + dest = 'labels', action = 'extend', metavar = '', help = 'label(s) of field values') parser.set_defaults(pos = 'pos', ) - (options,filenames) = parser.parse_args() - -if options.data is None: parser.error('no data column specified.') - -# --- define possible data types ------------------------------------------------------------------- - -datatypes = { - 3: {'name': 'vector', - 'shape': [3], - }, - 9: {'name': 'tensor', - 'shape': [3,3], - }, - } - -# --- loop over input files ------------------------------------------------------------------------ - if filenames == []: filenames = [None] +if options.labels is None: parser.error('no data column specified.') + for name in filenames: - try: table = damask.ASCIItable(name = name,buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# --- interpret header ---------------------------------------------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) - table.head_read() - - remarks = [] - errors = [] - active = [] - - coordDim = table.label_dimension(options.pos) - if coordDim != 3: - errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos)) - else: coordCol = table.label_index(options.pos) - - for me in options.data: - dim = table.label_dimension(me) - if dim in datatypes: - active.append(merge_dicts({'label':me},datatypes[dim])) - remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me)) - else: - remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \ - '"{}" not found...'.format(me) ) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for data in active: - table.labels_append(['divFFT({})'.format(data['label']) if data['shape'] == [3] \ - else '{}_divFFT({})'.format(i+1,data['label']) - for i in range(np.prod(np.array(data['shape']))//3)]) # extend ASCII header with new labels - table.head_write() - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) - -# ------------------------------------------ process value field ----------------------------------- - - stack = [table.data] - for data in active: - # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation - stack.append(divFFT(size[::-1], - table.data[:,table.label_indexrange(data['label'])]. - reshape(grid[::-1].tolist()+data['shape']))) - -# ------------------------------------------ output result ----------------------------------------- - - if len(stack) > 1: table.data = np.hstack(tuple(stack)) - table.data_writeArray('%.12g') - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + for label in options.labels: + field = table.get(label) + shape = (3,) if np.prod(field.shape)//np.prod(grid) == 3 else (3,3) # vector or tensor + field = field.reshape(np.append(grid[::-1],shape)) + table.add('divFFT({})'.format(label), + damask.grid_filters.divergence(size[::-1],field).reshape((-1,np.prod(shape)//3)), + scriptID+' '+' '.join(sys.argv[1:])) + + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addEuclideanDistance.py b/processing/post/addEuclideanDistance.py index 1ca2169f6..eaf91b894 100755 --- a/processing/post/addEuclideanDistance.py +++ b/processing/post/addEuclideanDistance.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import itertools @@ -121,13 +122,14 @@ parser.set_defaults(pos = 'pos', ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.type is None: - parser.error('no feature type selected.') + parser.error('no feature type selected.') if not set(options.type).issubset(set(list(itertools.chain(*map(lambda x: x['names'],features))))): - parser.error('type must be chosen from (%s).'%(', '.join(map(lambda x:'|'.join(x['names']),features))) ) + parser.error('type must be chosen from (%s).'%(', '.join(map(lambda x:'|'.join(x['names']),features))) ) if 'biplane' in options.type and 'boundary' in options.type: - parser.error('only one from aliases "biplane" and "boundary" possible.') + parser.error('only one from aliases "biplane" and "boundary" possible.') feature_list = [] for i,feature in enumerate(features): @@ -137,104 +139,49 @@ for i,feature in enumerate(features): feature_list.append(i) # remember valid features break -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - try: table = damask.ASCIItable(name = name, buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) - table.head_read() + neighborhood = neighborhoods[options.neighborhood] + diffToNeighbor = np.empty(list(grid+2)+[len(neighborhood)],'i') + microstructure = periodic_3Dpad(table.get(options.id).astype('i').reshape(grid,order='F')) -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - - if not 3 >= table.label_dimension(options.pos) >= 1: - errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - - if table.label_dimension(options.id) != 1: errors.append('grain identifier {} not found.'.format(options.id)) - else: idCol = table.label_index(options.id) - - if remarks != []: - damask.util.croak(remarks) - remarks = [] - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for feature in feature_list: - table.labels_append('ED_{}({})'.format(features[feature]['names'][0],options.id)) # extend ASCII header with new labels - table.head_write() - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) - N = grid.prod() - - if N != len(table.data): errors.append('data count {} does not match grid {}.'.format(N,'x'.join(map(str,grid)))) - else: remarks.append('grid: {}x{}x{}'.format(*grid)) - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ process value field ----------------------------------- - - stack = [table.data] - - neighborhood = neighborhoods[options.neighborhood] - diffToNeighbor = np.empty(list(grid+2)+[len(neighborhood)],'i') - microstructure = periodic_3Dpad(table.data[:,idCol].astype('i').reshape(grid,order='F')) - - for i,p in enumerate(neighborhood): - stencil = np.zeros((3,3,3),'i') - stencil[1,1,1] = -1 - stencil[p[0]+1, - p[1]+1, - p[2]+1] = 1 - diffToNeighbor[:,:,:,i] = ndimage.convolve(microstructure,stencil) # compare ID at each point... + for i,p in enumerate(neighborhood): + stencil = np.zeros((3,3,3),'i') + stencil[1,1,1] = -1 + stencil[p[0]+1, + p[1]+1, + p[2]+1] = 1 + diffToNeighbor[:,:,:,i] = ndimage.convolve(microstructure,stencil) # compare ID at each point... # ...to every one in the specified neighborhood # for same IDs at both locations ==> 0 - diffToNeighbor = np.sort(diffToNeighbor) # sort diff such that number of changes in diff (steps)... + diffToNeighbor = np.sort(diffToNeighbor) # sort diff such that number of changes in diff (steps)... # ...reflects number of unique neighbors - uniques = np.where(diffToNeighbor[1:-1,1:-1,1:-1,0] != 0, 1,0) # initialize unique value counter (exclude myself [= 0]) + uniques = np.where(diffToNeighbor[1:-1,1:-1,1:-1,0] != 0, 1,0) # initialize unique value counter (exclude myself [= 0]) - for i in range(1,len(neighborhood)): # check remaining points in neighborhood - uniques += np.where(np.logical_and( - diffToNeighbor[1:-1,1:-1,1:-1,i] != 0, # not myself? - diffToNeighbor[1:-1,1:-1,1:-1,i] != diffToNeighbor[1:-1,1:-1,1:-1,i-1], - ), # flip of ID difference detected? - 1,0) # count that flip + for i in range(1,len(neighborhood)): # check remaining points in neighborhood + uniques += np.where(np.logical_and( + diffToNeighbor[1:-1,1:-1,1:-1,i] != 0, # not myself? + diffToNeighbor[1:-1,1:-1,1:-1,i] != diffToNeighbor[1:-1,1:-1,1:-1,i-1], + ), # flip of ID difference detected? + 1,0) # count that flip - distance = np.ones((len(feature_list),grid[0],grid[1],grid[2]),'d') + distance = np.ones((len(feature_list),grid[0],grid[1],grid[2]),'d') - for i,feature_id in enumerate(feature_list): - distance[i,:,:,:] = np.where(uniques >= features[feature_id]['aliens'],0.0,1.0) # seed with 0.0 when enough unique neighbor IDs are present - distance[i,:,:,:] = ndimage.morphology.distance_transform_edt(distance[i,:,:,:])*[options.scale]*3 + for i,feature_id in enumerate(feature_list): + distance[i,:,:,:] = np.where(uniques >= features[feature_id]['aliens'],0.0,1.0) # seed with 0.0 when enough unique neighbor IDs are present + distance[i,:,:,:] = ndimage.morphology.distance_transform_edt(distance[i,:,:,:])*[options.scale]*3 - distance = distance.reshape([len(feature_list),grid.prod(),1],order='F') - for i in range(len(feature_list)): - stack.append(distance[i,:]) + distance = distance.reshape([len(feature_list),grid.prod(),1],order='F') -# ------------------------------------------ output result ----------------------------------------- - if len(stack) > 1: table.data = np.hstack(tuple(stack)) - table.data_writeArray('%.12g') + for i,feature in enumerate(feature_list): + table.add('ED_{}({})'.format(features[feature]['names'][0],options.id), + distance[i,:], + scriptID+' '+' '.join(sys.argv[1:])) -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addGaussian.py b/processing/post/addGaussian.py index 9b601a1dc..5f3ec5d60 100755 --- a/processing/post/addGaussian.py +++ b/processing/post/addGaussian.py @@ -2,9 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np from scipy import ndimage import damask @@ -30,7 +30,7 @@ parser.add_option('-p','--pos','--periodiccellcenter', type = 'string', metavar = 'string', help = 'label of coordinates [%default]') parser.add_option('-s','--scalar', - dest = 'scalar', + dest = 'labels', action = 'extend', metavar = '', help = 'label(s) of scalar field values') parser.add_option('-o','--order', @@ -56,78 +56,21 @@ parser.set_defaults(pos = 'pos', ) (options,filenames) = parser.parse_args() - -if options.scalar is None: - parser.error('no data column specified.') - -# --- loop over input files ------------------------------------------------------------------------ - if filenames == []: filenames = [None] +if options.labels is None: parser.error('no data column specified.') + for name in filenames: - try: table = damask.ASCIItable(name = name,buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + damask.grid_filters.coord0_check(table.get(options.pos)) - table.head_read() + for label in options.labels: + table.add('Gauss{}({})'.format(options.sigma,label), + ndimage.filters.gaussian_filter(table.get(label).reshape((-1)), + options.sigma,options.order, + mode = 'wrap' if options.periodic else 'nearest'), + scriptID+' '+' '.join(sys.argv[1:])) -# ------------------------------------------ sanity checks ---------------------------------------- - - items = { - 'scalar': {'dim': 1, 'shape': [1], 'labels':options.scalar, 'active':[], 'column': []}, - } - errors = [] - remarks = [] - column = {} - - if table.label_dimension(options.pos) != 3: errors.append('coordinates {} are not a vector.'.format(options.pos)) - else: colCoord = table.label_index(options.pos) - - for type, data in items.items(): - for what in (data['labels'] if data['labels'] is not None else []): - dim = table.label_dimension(what) - if dim != data['dim']: remarks.append('column {} is not a {}.'.format(what,type)) - else: - items[type]['active'].append(what) - items[type]['column'].append(table.label_index(what)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for type, data in items.items(): - for label in data['active']: - table.labels_append(['Gauss{}({})'.format(options.sigma,label)]) # extend ASCII header with new labels - table.head_write() - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) - -# ------------------------------------------ process value field ----------------------------------- - - stack = [table.data] - for type, data in items.items(): - for i,label in enumerate(data['active']): - stack.append(ndimage.filters.gaussian_filter(table.data[:,data['column'][i]], - options.sigma,options.order, - mode = 'wrap' if options.periodic else 'nearest' - ).reshape([table.data.shape[0],1]) - ) - -# ------------------------------------------ output result ----------------------------------------- - if len(stack) > 1: table.data = np.hstack(tuple(stack)) - table.data_writeArray('%.12g') - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py index bfadb578e..54b80ed26 100755 --- a/processing/post/addGradient.py +++ b/processing/post/addGradient.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -12,44 +13,6 @@ import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def merge_dicts(*dict_args): - """Given any number of dicts, shallow copy and merge into a new dict, with precedence going to key value pairs in latter dicts.""" - result = {} - for dictionary in dict_args: - result.update(dictionary) - return result - -def gradFFT(geomdim,field): - """Calculate gradient of a vector or scalar field by transforming into Fourier space.""" - shapeFFT = np.array(np.shape(field))[0:3] - grid = np.array(np.shape(field)[2::-1]) - N = grid.prod() # field size - n = np.array(np.shape(field)[3:]).prod() # data size - - field_fourier = np.fft.rfftn(field,axes=(0,1,2),s=shapeFFT) - grad_fourier = np.empty(field_fourier.shape+(3,),'c16') - - # differentiation in Fourier space - TWOPIIMG = 2.0j*np.pi - einsums = { - 1:'ijkl,ijkm->ijkm', # scalar, 1 -> 3 - 3:'ijkl,ijkm->ijklm', # vector, 3 -> 3x3 - } - - k_sk = np.where(np.arange(grid[2])>grid[2]//2,np.arange(grid[2])-grid[2],np.arange(grid[2]))/geomdim[0] - if grid[2]%2 == 0: k_sk[grid[2]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/geomdim[1] - if grid[1]%2 == 0: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) - - k_si = np.arange(grid[0]//2+1)/geomdim[2] - - kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij') - k_s = np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3).astype('c16') - grad_fourier = np.einsum(einsums[n],field_fourier,k_s)*TWOPIIMG - - return np.fft.irfftn(grad_fourier,axes=(0,1,2),s=shapeFFT).reshape([N,3*n]) - # -------------------------------------------------------------------- # MAIN @@ -57,9 +20,7 @@ def gradFFT(geomdim,field): parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [ASCIItable(s)]', description = """ Add column(s) containing gradient of requested column(s). -Operates on periodic ordered three-dimensional data sets -of vector and scalar fields. - +Operates on periodic ordered three-dimensional data sets of scalar and vector fields. """, version = scriptID) parser.add_option('-p','--pos','--periodiccellcenter', @@ -67,7 +28,7 @@ parser.add_option('-p','--pos','--periodiccellcenter', type = 'string', metavar = 'string', help = 'label of coordinates [%default]') parser.add_option('-l','--label', - dest = 'data', + dest = 'labels', action = 'extend', metavar = '', help = 'label(s) of field values') @@ -75,85 +36,22 @@ parser.set_defaults(pos = 'pos', ) (options,filenames) = parser.parse_args() - -if options.data is None: parser.error('no data column specified.') - -# --- define possible data types ------------------------------------------------------------------- - -datatypes = { - 1: {'name': 'scalar', - 'shape': [1], - }, - 3: {'name': 'vector', - 'shape': [3], - }, - } - -# --- loop over input files ------------------------------------------------------------------------ - if filenames == []: filenames = [None] +if options.labels is None: parser.error('no data column specified.') + for name in filenames: - try: table = damask.ASCIItable(name = name,buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# --- interpret header ---------------------------------------------------------------------------- + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.get(options.pos)) - table.head_read() - - remarks = [] - errors = [] - active = [] - - coordDim = table.label_dimension(options.pos) - if coordDim != 3: - errors.append('coordinates "{}" must be three-dimensional.'.format(options.pos)) - else: coordCol = table.label_index(options.pos) - - for me in options.data: - dim = table.label_dimension(me) - if dim in datatypes: - active.append(merge_dicts({'label':me},datatypes[dim])) - remarks.append('differentiating {} "{}"...'.format(datatypes[dim]['name'],me)) - else: - remarks.append('skipping "{}" of dimension {}...'.format(me,dim) if dim != -1 else \ - '"{}" not found...'.format(me) ) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - for data in active: - table.labels_append(['{}_gradFFT({})'.format(i+1,data['label']) - for i in range(coordDim*np.prod(np.array(data['shape'])))]) # extend ASCII header with new labels - table.head_write() - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray() - - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) - -# ------------------------------------------ process value field ----------------------------------- - - stack = [table.data] - for data in active: - # we need to reverse order here, because x is fastest,ie rightmost, but leftmost in our x,y,z notation - stack.append(gradFFT(size[::-1], - table.data[:,table.label_indexrange(data['label'])]. - reshape(grid[::-1].tolist()+data['shape']))) - -# ------------------------------------------ output result ----------------------------------------- - - if len(stack) > 1: table.data = np.hstack(tuple(stack)) - table.data_writeArray('%.12g') - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + for label in options.labels: + field = table.get(label) + shape = (1,) if np.prod(field.shape)//np.prod(grid) == 1 else (3,) # scalar or vector + field = field.reshape(np.append(grid[::-1],shape)) + table.add('gradFFT({})'.format(label), + damask.grid_filters.gradient(size[::-1],field).reshape((-1,np.prod(shape)*3)), + scriptID+' '+' '.join(sys.argv[1:])) + + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addIPFcolor.py b/processing/post/addIPFcolor.py index 0149dd078..014b0147d 100755 --- a/processing/post/addIPFcolor.py +++ b/processing/post/addIPFcolor.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -43,54 +44,25 @@ parser.set_defaults(pole = (0.0,0.0,1.0), ) (options, filenames) = parser.parse_args() +if filenames == []: filenames = [None] # damask.Orientation requires Bravais lattice, but we are only interested in symmetry -symmetry2lattice={'cubic':'bcc','hexagonal':'hex','tetragonal':'bct'} +symmetry2lattice={'cubic':'fcc','hexagonal':'hex','tetragonal':'bct'} lattice = symmetry2lattice[options.symmetry] pole = np.array(options.pole) pole /= np.linalg.norm(pole) -# --- loop over input files ------------------------------------------------------------------------ - -if filenames == []: filenames = [None] - for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - if not table.label_dimension(options.quaternion) == 4: - damask.util.croak('input {} does not have dimension 4.'.format(options.quaternion)) - table.close(dismiss = True) # close ASCIItable and remove empty file - continue - - column = table.label_index(options.quaternion) - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{}_IPF_{:g}{:g}{:g}_{sym}'.format(i+1,*options.pole,sym = options.symmetry.lower()) for i in range(3)]) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - o = damask.Orientation(np.array(list(map(float,table.data[column:column+4]))), - lattice = lattice).reduced() - - table.data_append(o.IPFcolor(pole)) - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + orientation = table.get(options.quaternion) + color = np.empty((orientation.shape[0],3)) + for i,o in enumerate(orientation): + color[i] = damask.Orientation(o,lattice = lattice).IPFcolor(pole) + + table.add('IPF_{:g}{:g}{:g}_{sym}'.format(*options.pole,sym = options.symmetry.lower()), + color, + scriptID+' '+' '.join(sys.argv[1:])) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addNorm.py b/processing/post/addNorm.py index c8c0b05bf..4ac2bf899 100755 --- a/processing/post/addNorm.py +++ b/processing/post/addNorm.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -42,7 +43,7 @@ parser.add_option('-n','--norm', type = 'choice', choices = normChoices, metavar='string', help = 'type of element-wise p-norm [frobenius] {%s}'%(','.join(map(str,normChoices)))) parser.add_option('-l','--label', - dest = 'label', + dest = 'labels', action = 'extend', metavar = '', help = 'heading of column(s) to calculate norm of') @@ -50,62 +51,25 @@ parser.set_defaults(norm = 'frobenius', ) (options,filenames) = parser.parse_args() - -if options.norm.lower() not in normChoices: - parser.error('invalid norm ({}) specified.'.format(options.norm)) -if options.label is None: - parser.error('no data column specified.') - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +if options.norm.lower() not in normChoices: + parser.error('invalid norm ({}) specified.'.format(options.norm)) +if options.labels is None: + parser.error('no data column specified.') + for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + for label in options.labels: + data = table.get(label) + data_norm = np.empty((data.shape[0],1)) + for i,d in enumerate(data): + data_norm[i] = norm(options.norm.capitalize(),d) - table.head_read() + table.add('norm{}({})'.format(options.norm.capitalize(),label), + data_norm, + scriptID+' '+' '.join(sys.argv[1:])) -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - columns = [] - dims = [] - - for what in options.label: - dim = table.label_dimension(what) - if dim < 0: remarks.append('column {} not found...'.format(what)) - else: - dims.append(dim) - columns.append(table.label_index(what)) - table.labels_append('norm{}({})'.format(options.norm.capitalize(),what)) # extend ASCII header with new labels - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# ------------------------------------------ assemble header -------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - for column,dim in zip(columns,dims): - table.data_append(norm(options.norm.capitalize(), - map(float,table.data[column:column+dim]))) - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close input ASCII table (works for stdin) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addOrientations.py b/processing/post/addOrientations.py index 31ce6aeb3..2c46ee5ee 100755 --- a/processing/post/addOrientations.py +++ b/processing/post/addOrientations.py @@ -125,9 +125,10 @@ R = damask.Rotation.fromAxisAngle(np.array(options.labrotation),options.degrees, if filenames == []: filenames = [None] for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False) - except Exception: continue + try: + table = damask.ASCIItable(name = name, buffered = False) + except IOError: + continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ diff --git a/processing/post/addPole.py b/processing/post/addPole.py index c8b83b106..58f9235dc 100755 --- a/processing/post/addPole.py +++ b/processing/post/addPole.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -42,52 +43,23 @@ parser.set_defaults(pole = (1.0,0.0,0.0), ) (options, filenames) = parser.parse_args() +if filenames == []: filenames = [None] pole = np.array(options.pole) pole /= np.linalg.norm(pole) -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - if not table.label_dimension(options.quaternion) == 4: - damask.util.croak('input {} does not have dimension 4.'.format(options.quaternion)) - table.close(dismiss = True) # close ASCIItable and remove empty file - continue - - column = table.label_index(options.quaternion) - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{}_pole_{}{}{}'.format(i+1,*options.pole) for i in range(2)]) - table.head_write() - -# ------------------------------------------ process data ------------------------------------------ - outputAlive = True - while outputAlive and table.data_read(): # read next data line of ASCII table - o = damask.Rotation(np.array(list(map(float,table.data[column:column+4])))) - - rotatedPole = o*pole # rotate pole according to crystal orientation - (x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection - - table.data_append([np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y]) # cartesian coordinates - - outputAlive = table.data_write() # output processed line - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + orientation = table.get(options.quaternion) + poles = np.empty((orientation.shape[0],2)) + for i,o in enumerate(orientation): + rotatedPole = damask.Rotation(o)*pole # rotate pole according to crystal orientation + (x,y) = rotatedPole[0:2]/(1.+abs(pole[2])) # stereographic projection + poles[i] = [np.sqrt(x*x+y*y),np.arctan2(y,x)] if options.polar else [x,y] # cartesian coordinates + + table.add('pole_{}{}{}'.format(*options.pole), + poles, + scriptID+' '+' '.join(sys.argv[1:])) + table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/averageDown.py b/processing/post/averageDown.py index d94bc8dbd..d4e2a3529 100755 --- a/processing/post/averageDown.py +++ b/processing/post/averageDown.py @@ -65,7 +65,8 @@ for name in filenames: outname = os.path.join(os.path.dirname(name), prefix+os.path.basename(name)) if name else name, buffered = False) - except: continue + except IOError: + continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ @@ -95,7 +96,7 @@ for name in filenames: table.data_readArray() if (options.grid is None or options.size is None): - grid,size = damask.util.coordGridAndSize(table.data[:,table.label_indexrange(options.pos)]) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.data[:,table.label_indexrange(options.pos)]) else: grid = np.array(options.grid,'i') size = np.array(options.size,'d') diff --git a/processing/post/blowUp.py b/processing/post/blowUp.py index 3dccb1aaf..32cc1909d 100755 --- a/processing/post/blowUp.py +++ b/processing/post/blowUp.py @@ -55,7 +55,8 @@ for name in filenames: outname = os.path.join(os.path.dirname(name), prefix+os.path.basename(name)) if name else name, buffered = False) - except: continue + except IOError: + continue damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ @@ -82,7 +83,7 @@ for name in filenames: table.data_readArray(options.pos) table.data_rewind() - grid,size = damask.util.coordGridAndSize(table.data) + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.data) packing = np.array(options.packing,'i') outSize = grid*packing diff --git a/processing/post/vtk_pointCloud.py b/processing/post/vtk_pointCloud.py index 06aad0aca..44f719267 100755 --- a/processing/post/vtk_pointCloud.py +++ b/processing/post/vtk_pointCloud.py @@ -2,10 +2,10 @@ import os import sys +from io import StringIO from optparse import OptionParser import vtk -import numpy as np import damask @@ -33,49 +33,20 @@ parser.set_defaults(pos = 'pos', ) (options, filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False, - readonly = True) - except: continue damask.util.report(scriptName,name) -# --- interpret header ---------------------------------------------------------------------------- - - table.head_read() - - errors = [] - remarks = [] - coordDim = table.label_dimension(options.pos) - if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - elif coordDim < 3: remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim, - 's' if coordDim < 2 else '', - options.pos)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) # ------------------------------------------ process data --------------------------------------- - table.data_readArray(options.pos) - if table.data.shape[1] < 3: - table.data = np.hstack((table.data, - np.zeros((table.data.shape[0], - 3-table.data.shape[1]),dtype='f'))) # fill coords up to 3D with zeros - Polydata = vtk.vtkPolyData() Points = vtk.vtkPoints() Vertices = vtk.vtkCellArray() - for p in table.data: + for p in table.get(options.pos): pointID = Points.InsertNextPoint(p) Vertices.InsertNextCell(1) Vertices.InsertCellPoint(pointID) @@ -104,5 +75,3 @@ for name in filenames: writer.Write() if name is None: sys.stdout.write(writer.GetOutputString()) - - table.close() diff --git a/processing/post/vtk_rectilinearGrid.py b/processing/post/vtk_rectilinearGrid.py index bb29a5d4c..2ccad6319 100755 --- a/processing/post/vtk_rectilinearGrid.py +++ b/processing/post/vtk_rectilinearGrid.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import vtk @@ -40,48 +41,14 @@ parser.set_defaults(mode = 'cell', ) (options, filenames) = parser.parse_args() - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: table = damask.ASCIItable(name = name, - buffered = False, - labeled = True, - readonly = True, - ) - except: continue damask.util.report(scriptName,name) -# --- interpret header ---------------------------------------------------------------------------- - - table.head_read() - - remarks = [] - errors = [] - coordDim = table.label_dimension(options.pos) - if not 3 >= coordDim >= 1: errors.append('coordinates "{}" need to have one, two, or three dimensions.'.format(options.pos)) - elif coordDim < 3: remarks.append('appending {} dimension{} to coordinates "{}"...'.format(3-coordDim, - 's' if coordDim < 2 else '', - options.pos)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue - -# --------------- figure out size and grid --------------------------------------------------------- - - table.data_readArray(options.pos) - if table.data.shape[1] < 3: - table.data = np.hstack((table.data, - np.zeros((table.data.shape[0], - 3-table.data.shape[1]),dtype='f'))) # fill coords up to 3D with zeros - - coords = [np.unique(table.data[:,i]) for i in range(3)] + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + coords = [np.unique(table.get(options.pos)[:,i]) for i in range(3)] if options.mode == 'cell': coords = [0.5 * np.array([3.0 * coords[i][0] - coords[i][0 + int(len(coords[i]) > 1)]] + \ [coords[i][j-1] + coords[i][j] for j in range(1,len(coords[i]))] + \ @@ -90,13 +57,6 @@ for name in filenames: grid = np.array(list(map(len,coords)),'i') N = grid.prod() if options.mode == 'point' else (grid-1).prod() - if N != len(table.data): - errors.append('data count {} does not match grid {}x{}x{}.'.format(N,*(grid - (options.mode == 'cell')) )) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - # ------------------------------------------ process data --------------------------------------- rGrid = vtk.vtkRectilinearGrid() @@ -135,5 +95,3 @@ for name in filenames: writer.Write() if name is None: sys.stdout.write(writer.GetOutputString()) - - table.close() diff --git a/processing/pre/geom_fromDREAM3D.py b/processing/pre/geom_fromDREAM3D.py index 159793cd8..7d5b1442d 100755 --- a/processing/pre/geom_fromDREAM3D.py +++ b/processing/pre/geom_fromDREAM3D.py @@ -145,7 +145,6 @@ for name in filenames: config_header += [''] for i in range(np.nanmax(microstructure)): config_header += ['[{}{}]'.format(label,i+1), - 'crystallite 1', '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(phase[i],i+1), ] diff --git a/processing/pre/geom_fromOsteonGeometry.py b/processing/pre/geom_fromOsteonGeometry.py index 499a8867f..627d92728 100755 --- a/processing/pre/geom_fromOsteonGeometry.py +++ b/processing/pre/geom_fromOsteonGeometry.py @@ -126,15 +126,12 @@ for i in range(3,np.max(microstructure)): config_header = ['', '[canal]', - 'crystallite 1', '(constituent)\tphase 1\ttexture 1\tfraction 1.0', '[interstitial]', - 'crystallite 1', '(constituent)\tphase 2\ttexture 2\tfraction 1.0' ] for i in range(3,np.max(microstructure)): config_header += ['[Point{}]'.format(i-2), - 'crystallite 1', '(constituent)\tphase 3\ttexture {}\tfraction 1.0'.format(i) ] diff --git a/processing/pre/geom_fromTable.py b/processing/pre/geom_fromTable.py index f513c4834..40fd17437 100755 --- a/processing/pre/geom_fromTable.py +++ b/processing/pre/geom_fromTable.py @@ -78,36 +78,15 @@ for name in filenames: table = damask.ASCIItable(name = name,readonly=True) table.head_read() # read ASCII header info -# ------------------------------------------ sanity checks --------------------------------------- - - coordDim = table.label_dimension(options.pos) - - errors = [] - if not 3 >= coordDim >= 2: - errors.append('coordinates "{}" need to have two or three dimensions.'.format(options.pos)) - if not np.all(table.label_dimension(label) == dim): - errors.append('input "{}" needs to have dimension {}.'.format(label,dim)) - if options.phase and table.label_dimension(options.phase) != 1: - errors.append('phase column "{}" is not scalar.'.format(options.phase)) - - if errors != []: - damask.util.croak(errors) - continue table.data_readArray([options.pos] \ + (label if isinstance(label, list) else [label]) \ + ([options.phase] if options.phase else [])) - if coordDim == 2: - table.data = np.insert(table.data,2,np.zeros(len(table.data)),axis=1) # add zero z coordinate for two-dimensional input if options.phase is None: table.data = np.column_stack((table.data,np.ones(len(table.data)))) # add single phase if no phase column given - grid,size = damask.util.coordGridAndSize(table.data[:,0:3]) - coords = [np.unique(table.data[:,i]) for i in range(3)] - mincorner = np.array(list(map(min,coords))) - origin = mincorner - 0.5*size/grid # shift from cell center to corner - + grid,size,origin = damask.grid_filters.cell_coord0_2_DNA(table.data[:,0:3]) indices = np.lexsort((table.data[:,0],table.data[:,1],table.data[:,2])) # indices of position when sorting x fast, z slow microstructure = np.empty(grid,dtype = int) # initialize empty microstructure @@ -142,7 +121,6 @@ for name in filenames: config_header += [''] for i,data in enumerate(unique): config_header += ['[Grain{}]'.format(i+1), - 'crystallite 1', '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(int(data[4]),i+1), ] diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index 28e215f85..d5ec43701 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -290,7 +290,6 @@ for name in filenames: config_header += [''] for ID in grainIDs: config_header += ['[Grain{}]'.format(ID), - 'crystallite 1', '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,ID) ] diff --git a/processing/pre/geom_toTable.py b/processing/pre/geom_toTable.py index ed33d9c85..3d955ad53 100755 --- a/processing/pre/geom_toTable.py +++ b/processing/pre/geom_toTable.py @@ -2,10 +2,8 @@ import os import sys -from optparse import OptionParser from io import StringIO - -import numpy as np +from optparse import OptionParser import damask @@ -24,38 +22,25 @@ Translate geom description into ASCIItable containing position and microstructur """, version = scriptID) (options, filenames) = parser.parse_args() - - if filenames == []: filenames = [None] for name in filenames: - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) - geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) + geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) + damask.util.croak(geom) - damask.util.croak(geom) + coord0 = damask.grid_filters.cell_coord0(geom.grid,geom.size,geom.origin).reshape((-1,3),order='F') -# --- generate grid -------------------------------------------------------------------------------- + comments = geom.comments \ + + [scriptID + ' ' + ' '.join(sys.argv[1:]), + "grid\ta {}\tb {}\tc {}".format(*geom.grid), + "size\tx {}\ty {}\tz {}".format(*geom.size), + "origin\tx {}\ty {}\tz {}".format(*geom.origin), + "homogenization\t{}".format(geom.homogenization)] - grid = geom.get_grid() - size = geom.get_size() - origin = geom.get_origin() + table = damask.Table(coord0,{'pos':(3,)},comments) + table.add('microstructure',geom.microstructure.reshape((-1,1))) - x = (0.5 + np.arange(grid[0],dtype=float))/grid[0]*size[0]+origin[0] - y = (0.5 + np.arange(grid[1],dtype=float))/grid[1]*size[1]+origin[1] - z = (0.5 + np.arange(grid[2],dtype=float))/grid[2]*size[2]+origin[2] - - xx = np.tile( x, grid[1]* grid[2]) - yy = np.tile(np.repeat(y,grid[0] ),grid[2]) - zz = np.repeat(z,grid[0]*grid[1]) - -# --- create ASCII table -------------------------------------------------------------------------- - - table = damask.ASCIItable(outname = os.path.splitext(name)[0]+'.txt' if name else name) - table.info_append(geom.get_comments() + [scriptID + '\t' + ' '.join(sys.argv[1:])]) - table.labels_append(['{}_{}'.format(1+i,'pos') for i in range(3)]+['microstructure']) - table.head_write() - table.output_flush() - table.data = np.squeeze(np.dstack((xx,yy,zz,geom.microstructure.flatten('F'))),axis=0) - table.data_writeArray() - table.close() + table.to_ASCII(sys.stdout if name is None else \ + os.path.splitext(name)[0]+'.txt') diff --git a/processing/pre/hybridIA_linODFsampling.py b/processing/pre/hybridIA_linODFsampling.py index cf1a473cf..80d82a458 100755 --- a/processing/pre/hybridIA_linODFsampling.py +++ b/processing/pre/hybridIA_linODFsampling.py @@ -19,7 +19,7 @@ def integerFactorization(i): return j def binAsBins(bin,intervals): - """Explode compound bin into 3D bins list""" + """Explode compound bin into 3D bins list.""" bins = [0]*3 bins[0] = (bin//(intervals[1] * intervals[2])) % intervals[0] bins[1] = (bin//intervals[2]) % intervals[1] @@ -27,17 +27,17 @@ def binAsBins(bin,intervals): return bins def binsAsBin(bins,intervals): - """Implode 3D bins into compound bin""" + """Implode 3D bins into compound bin.""" return (bins[0]*intervals[1] + bins[1])*intervals[2] + bins[2] def EulersAsBins(Eulers,intervals,deltas,center): - """Return list of Eulers translated into 3D bins list""" + """Return list of Eulers translated into 3D bins list.""" return [int((euler+(0.5-center)*delta)//delta)%interval \ for euler,delta,interval in zip(Eulers,deltas,intervals) \ ] def binAsEulers(bin,intervals,deltas,center): - """Compound bin number translated into list of Eulers""" + """Compound bin number translated into list of Eulers.""" Eulers = [0.0]*3 Eulers[2] = (bin%intervals[2] + center)*deltas[2] Eulers[1] = (bin//intervals[2]%intervals[1] + center)*deltas[1] @@ -45,7 +45,7 @@ def binAsEulers(bin,intervals,deltas,center): return Eulers def directInvRepetitions(probability,scale): - """Calculate number of samples drawn by direct inversion""" + """Calculate number of samples drawn by direct inversion.""" nDirectInv = 0 for bin in range(len(probability)): # loop over bins nDirectInv += int(round(probability[bin]*scale)) # calc repetition @@ -56,7 +56,7 @@ def directInvRepetitions(probability,scale): # ----- efficient algorithm --------- def directInversion (ODF,nSamples): - """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians).""" nOptSamples = max(ODF['nNonZero'],nSamples) # random subsampling if too little samples requested nInvSamples = 0 @@ -118,7 +118,7 @@ def directInversion (ODF,nSamples): # ----- trial and error algorithms --------- def MonteCarloEulers (ODF,nSamples): - """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians).""" countMC = 0 maxdV_V = max(ODF['dV_V']) orientations = np.zeros((nSamples,3),'f') @@ -141,7 +141,7 @@ def MonteCarloEulers (ODF,nSamples): def MonteCarloBins (ODF,nSamples): - """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians).""" countMC = 0 maxdV_V = max(ODF['dV_V']) orientations = np.zeros((nSamples,3),'f') @@ -163,7 +163,7 @@ def MonteCarloBins (ODF,nSamples): def TothVanHoutteSTAT (ODF,nSamples): - """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians)""" + """ODF contains 'dV_V' (normalized to 1), 'center', 'intervals', 'limits' (in radians).""" orientations = np.zeros((nSamples,3),'f') reconstructedODF = np.zeros(ODF['nBins'],'f') unitInc = 1.0/nSamples @@ -211,10 +211,6 @@ parser.add_option('-p','--phase', dest = 'phase', type = 'int', metavar = 'int', help = 'phase index to be used [%default]') -parser.add_option('--crystallite', - dest = 'crystallite', - type = 'int', metavar = 'int', - help = 'crystallite index to be used [%default]') parser.add_option('-r', '--rnd', dest = 'randomSeed', type = 'int', metavar = 'int', \ @@ -223,7 +219,6 @@ parser.set_defaults(randomSeed = None, number = 500, algorithm = 'IA', phase = 1, - crystallite = 1, ang = True, ) @@ -240,7 +235,7 @@ if filenames == []: filenames = [None] for name in filenames: try: table = damask.ASCIItable(name = name, buffered = False, readonly=True) - except: + except IOError: continue damask.util.report(scriptName,name) @@ -351,7 +346,6 @@ for name in filenames: for i,ID in enumerate(range(nSamples)): materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)), - 'crystallite %i'%options.crystallite, '(constituent) phase %i texture %s fraction 1.0'%(options.phase,str(ID+1).rjust(formatwidth)), ] diff --git a/processing/pre/mentat_spectralBox.py b/processing/pre/mentat_spectralBox.py index 89f4a7a43..a61bef57a 100755 --- a/processing/pre/mentat_spectralBox.py +++ b/processing/pre/mentat_spectralBox.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- -import os,sys -import numpy as np +import os +import sys +from io import StringIO from optparse import OptionParser + import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -191,78 +192,45 @@ parser.add_option('-p', '--port', dest = 'port', type = 'int', metavar = 'int', help = 'Mentat connection port [%default]') -parser.add_option('--homogenization', - dest = 'homogenization', - type = 'int', metavar = 'int', - help = 'homogenization index to be used [auto]') -parser.set_defaults(port = None, - homogenization = None, -) +parser.set_defaults(port = None, + ) (options, filenames) = parser.parse_args() -if options.port: - try: - import py_mentat - except: - parser.error('no valid Mentat release found.') +if options.port is not None: + try: + import py_mentat + except ImportError: + parser.error('no valid Mentat release found.') # --- loop over input files ------------------------------------------------------------------------ if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.splitext(name)[0]+'.proc' if name else name, - buffered = False, labeled = False) - except: continue - damask.util.report(scriptName,name) - -# --- interpret header ---------------------------------------------------------------------------- - - table.head_read() - info,extra_header = table.head_getGeom() - if options.homogenization: info['homogenization'] = options.homogenization + damask.util.report(scriptName,name) - damask.util.croak(['grid a b c: %s'%(' x '.join(map(str,info['grid']))), - 'size x y z: %s'%(' x '.join(map(str,info['size']))), - 'origin x y z: %s'%(' : '.join(map(str,info['origin']))), - 'homogenization: %i'%info['homogenization'], - 'microstructures: %i'%info['microstructures'], - ]) + geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) + microstructure = geom.get_microstructure().flatten(order='F') - errors = [] - if np.any(info['grid'] < 1): errors.append('invalid grid a b c.') - if np.any(info['size'] <= 0.0): errors.append('invalid size x y z.') - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# --- read data ------------------------------------------------------------------------------------ - - microstructure = table.microstructure_read(info['grid']).reshape(info['grid'].prod(),order='F') # read microstructure - - cmds = [\ - init(), - mesh(info['grid'],info['size']), - material(), - geometry(), - initial_conditions(info['homogenization'],microstructure), - '*identify_sets', - '*show_model', - '*redraw', - '*draw_automatic', - ] - - outputLocals = {} - if options.port: - py_mentat.py_connect('',options.port) - output(cmds,outputLocals,'Mentat') - py_mentat.py_disconnect() - else: - output(cmds,outputLocals,table.__IO__['out']) # bad hack into internals of table class... - - table.close() + cmds = [\ + init(), + mesh(geom.grid,geom.size), + material(), + geometry(), + initial_conditions(geom.homogenization,microstructure), + '*identify_sets', + '*show_model', + '*redraw', + '*draw_automatic', + ] + + outputLocals = {} + if options.port: + py_mentat.py_connect('',options.port) + output(cmds,outputLocals,'Mentat') + py_mentat.py_disconnect() + else: + with sys.stdout if name is None else open(os.path.splitext(name)[0]+'.proc','w') as f: + output(cmds,outputLocals,f) diff --git a/processing/pre/patchFromReconstructedBoundaries.py b/processing/pre/patchFromReconstructedBoundaries.py index fabec0fdf..b710fb2cb 100755 --- a/processing/pre/patchFromReconstructedBoundaries.py +++ b/processing/pre/patchFromReconstructedBoundaries.py @@ -78,13 +78,11 @@ def rcbOrientationParser(content,idcolumn): damask.util.croak('You might not have chosen the correct column for the grain IDs! '+ 'Please check the "--id" option.') raise - except: - raise return grains def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): - """Parser for TSL-OIM reconstructed boundary files""" + """Parser for TSL-OIM reconstructed boundary files.""" # find bounding box boxX = [1.*sys.maxint,-1.*sys.maxint] boxY = [1.*sys.maxint,-1.*sys.maxint] @@ -99,8 +97,6 @@ def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): damask.util.croak('You might not have chosen the correct column for the segment end points! '+ 'Please check the "--segment" option.') raise - except: - raise (x[0],y[0]) = (M[0]*x[0]+M[1]*y[0],M[2]*x[0]+M[3]*y[0]) # apply transformation to coordinates (x[1],y[1]) = (M[0]*x[1]+M[1]*y[1],M[2]*x[1]+M[3]*y[1]) # to get rcb --> Euler system boxX[0] = min(boxX[0],x[0],x[1]) @@ -728,7 +724,7 @@ def image(name,imgsize,marginX,marginY,rcData): # ------------------------- def inside(x,y,points): - """Tests whether point(x,y) is within polygon described by points""" + """Tests whether point(x,y) is within polygon described by points.""" inside = False npoints=len(points) (x1,y1) = points[npoints-1] # start with last point of points @@ -750,7 +746,7 @@ def inside(x,y,points): # ------------------------- def fftbuild(rcData,height,xframe,yframe,grid,extrusion): - """Build array of grain numbers""" + """Build array of grain numbers.""" maxX = -1.*sys.maxint maxY = -1.*sys.maxint for line in rcData['point']: # find data range @@ -883,7 +879,7 @@ try: boundaryFile = open(args[0]) boundarySegments = boundaryFile.readlines() boundaryFile.close() -except: +except IOError: damask.util.croak('unable to read boundary file "{}".'.format(args[0])) raise @@ -941,19 +937,15 @@ if any(output in options.output for output in ['spectral','mentat']): for i,grain in enumerate(rcData['grainMapping']): config+=['[grain{}]'.format(grain), - 'crystallite\t1', '(constituent)\tphase 1\ttexture {}\tfraction 1.0'.format(i+1)] if (options.xmargin > 0.0): config+=['[x-margin]', - 'crystallite\t1', '(constituent)\tphase 2\ttexture {}\tfraction 1.0\n'.format(len(rcData['grainMapping'])+1)] if (options.ymargin > 0.0): config+=['[y-margin]', - 'crystallite\t1', '(constituent)\tphase 2\ttexture {}\tfraction 1.0\n'.format(len(rcData['grainMapping'])+1)] if (options.xmargin > 0.0 and options.ymargin > 0.0): config+=['[xy-margin]', - 'crystallite\t1', '(constituent)\tphase 2\ttexture {}\tfraction 1.0\n'.format(len(rcData['grainMapping'])+1)] if (options.xmargin > 0.0 or options.ymargin > 0.0): diff --git a/processing/pre/seeds_check.sh b/processing/pre/seeds_check.sh index 025c9eb90..502a19024 100755 --- a/processing/pre/seeds_check.sh +++ b/processing/pre/seeds_check.sh @@ -6,7 +6,6 @@ do vtk_addPointCloudData $seeds \ --data microstructure,weight \ - --inplace \ --vtk ${seeds%.*}.vtp \ done diff --git a/processing/pre/seeds_fromGeom.py b/processing/pre/seeds_fromGeom.py index 889ef6146..2118f049d 100755 --- a/processing/pre/seeds_fromGeom.py +++ b/processing/pre/seeds_fromGeom.py @@ -1,9 +1,12 @@ #!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- -import os,sys -import numpy as np +import os +import sys +from io import StringIO from optparse import OptionParser + +import numpy as np + import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -29,88 +32,39 @@ parser.add_option('-b', action = 'extend', metavar = '', dest = 'blacklist', help = 'blacklist of grain IDs') -parser.add_option('-p', - '--pos', '--seedposition', - dest = 'pos', - type = 'string', metavar = 'string', - help = 'label of coordinates [%default]') parser.set_defaults(whitelist = [], blacklist = [], - pos = 'pos', ) (options,filenames) = parser.parse_args() - -options.whitelist = list(map(int,options.whitelist)) -options.blacklist = list(map(int,options.blacklist)) - -# --- loop over output files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +options.whitelist = [int(i) for i in options.whitelist] +options.blacklist = [int(i) for i in options.blacklist] + for name in filenames: - try: table = damask.ASCIItable(name = name, - outname = os.path.splitext(name)[0]+'.seeds' if name else name, - buffered = False, - labeled = False) - except: continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) + + geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) + microstructure = geom.get_microstructure().reshape((-1,1),order='F') -# --- interpret header ---------------------------------------------------------------------------- + mask = np.logical_and(np.in1d(microstructure,options.whitelist,invert=False) if options.whitelist else \ + np.full(geom.grid.prod(),True,dtype=bool), + np.in1d(microstructure,options.blacklist,invert=True) if options.blacklist else \ + np.full(geom.grid.prod(),True,dtype=bool)) + + seeds = np.concatenate((damask.grid_filters.cell_coord0(geom.grid,geom.size).reshape((-1,3)), + microstructure), + axis=1)[mask] + + comments = geom.comments \ + + [scriptID + ' ' + ' '.join(sys.argv[1:]), + "grid\ta {}\tb {}\tc {}".format(*geom.grid), + "size\tx {}\ty {}\tz {}".format(*geom.size), + "origin\tx {}\ty {}\tz {}".format(*geom.origin), + "homogenization\t{}".format(geom.homogenization)] - table.head_read() - info,extra_header = table.head_getGeom() - damask.util.report_geom(info) - - errors = [] - if np.any(info['grid'] < 1): errors.append('invalid grid a b c.') - if np.any(info['size'] <= 0.0): errors.append('invalid size x y z.') - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# --- read data ------------------------------------------------------------------------------------ - - microstructure = table.microstructure_read(info['grid']) # read (linear) microstructure - -# --- generate grid -------------------------------------------------------------------------------- - - x = (0.5 + np.arange(info['grid'][0],dtype=float))/info['grid'][0]*info['size'][0]+info['origin'][0] - y = (0.5 + np.arange(info['grid'][1],dtype=float))/info['grid'][1]*info['size'][1]+info['origin'][1] - z = (0.5 + np.arange(info['grid'][2],dtype=float))/info['grid'][2]*info['size'][2]+info['origin'][2] - - xx = np.tile( x, info['grid'][1]* info['grid'][2]) - yy = np.tile(np.repeat(y,info['grid'][0] ),info['grid'][2]) - zz = np.repeat(z,info['grid'][0]*info['grid'][1]) - - mask = np.logical_and(np.in1d(microstructure,options.whitelist,invert=False) if options.whitelist != [] - else np.full_like(microstructure,True,dtype=bool), - np.in1d(microstructure,options.blacklist,invert=True ) if options.blacklist != [] - else np.full_like(microstructure,True,dtype=bool)) - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_clear() - table.info_append(extra_header+[ - scriptID + ' ' + ' '.join(sys.argv[1:]), - "grid\ta {}\tb {}\tc {}".format(*info['grid']), - "size\tx {}\ty {}\tz {}".format(*info['size']), - "origin\tx {}\ty {}\tz {}".format(*info['origin']), - "homogenization\t{}".format(info['homogenization']), - "microstructures\t{}".format(info['microstructures']), - ]) - table.labels_clear() - table.labels_append(['{dim}_{label}'.format(dim = 1+i,label = options.pos) for i in range(3)]+['microstructure']) - table.head_write() - table.output_flush() - -# --- write seeds information ------------------------------------------------------------ - - table.data = np.squeeze(np.dstack((xx,yy,zz,microstructure)))[mask] - table.data_writeArray() - -# ------------------------------------------ finalize output --------------------------------------- - - table.close() + table = damask.Table(seeds,{'pos':(3,),'microstructure':(1,)},comments) + table.to_ASCII(sys.stdout if name is None else \ + os.path.splitext(name)[0]+'.seeds') diff --git a/processing/pre/seeds_fromPokes.py b/processing/pre/seeds_fromPokes.py index 08e600ffe..1436841d0 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -1,11 +1,14 @@ #!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- -import os,math,sys -import numpy as np -import damask +import os +import sys +from io import StringIO from optparse import OptionParser +import numpy as np + +import damask + scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -35,117 +38,58 @@ parser.add_option('-y', action = 'store_true', dest = 'y', help = 'poke 45 deg along y') -parser.add_option('-p','--position', - dest = 'position', - type = 'string', metavar = 'string', - help = 'column label for coordinates [%default]') parser.set_defaults(x = False, y = False, box = [0.0,1.0,0.0,1.0,0.0,1.0], N = 16, - position = 'pos', ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] options.box = np.array(options.box).reshape(3,2) -# --- loop over output files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.splitext(name)[-2]+'_poked_{}.seeds'.format(options.N) if name else name, - buffered = False, labeled = False) - except: continue - damask.util.report(scriptName,name) - -# --- interpret header ---------------------------------------------------------------------------- - - table.head_read() - info,extra_header = table.head_getGeom() - - damask.util.croak(['grid a b c: %s'%(' x '.join(map(str,info['grid']))), - 'size x y z: %s'%(' x '.join(map(str,info['size']))), - 'origin x y z: %s'%(' : '.join(map(str,info['origin']))), - 'homogenization: %i'%info['homogenization'], - 'microstructures: %i'%info['microstructures'], - ]) - - errors = [] - if np.any(info['grid'] < 1): errors.append('invalid grid a b c.') - if np.any(info['size'] <= 0.0): errors.append('invalid size x y z.') - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# --- read data ------------------------------------------------------------------------------------ - - microstructure = table.microstructure_read(info['grid']).reshape(info['grid'],order='F') # read microstructure - -# --- do work ------------------------------------------------------------------------------------ - - newInfo = { - 'microstructures': 0, - } - offset = (np.amin(options.box, axis=1)*info['grid']/info['size']).astype(int) - box = np.amax(options.box, axis=1) - np.amin(options.box, axis=1) - - Nx = int(options.N/math.sqrt(options.N*info['size'][1]*box[1]/info['size'][0]/box[0])) - Ny = int(options.N/math.sqrt(options.N*info['size'][0]*box[0]/info['size'][1]/box[1])) - Nz = int(box[2]*info['grid'][2]) - - damask.util.croak('poking {} x {} x {} in box {} {} {}...'.format(Nx,Ny,Nz,*box)) - - seeds = np.zeros((Nx*Ny*Nz,4),'d') - grid = np.zeros(3,'i') - - n = 0 - for i in range(Nx): - for j in range(Ny): - grid[0] = round((i+0.5)*box[0]*info['grid'][0]/Nx-0.5)+offset[0] - grid[1] = round((j+0.5)*box[1]*info['grid'][1]/Ny-0.5)+offset[1] - for k in range(Nz): - grid[2] = k + offset[2] - grid %= info['grid'] - seeds[n,0:3] = (0.5+grid)/info['grid'] # normalize coordinates to box - seeds[n, 3] = microstructure[grid[0],grid[1],grid[2]] - if options.x: grid[0] += 1 - if options.y: grid[1] += 1 - n += 1 - - newInfo['microstructures'] = len(np.unique(seeds[:,3])) - -# --- report --------------------------------------------------------------------------------------- - if (newInfo['microstructures'] != info['microstructures']): - damask.util.croak('--> microstructures: %i'%newInfo['microstructures']) - - -# ------------------------------------------ assemble header --------------------------------------- - table.info_clear() - table.info_append(extra_header+[ - scriptID + ' ' + ' '.join(sys.argv[1:]), - "poking\ta {}\tb {}\tc {}".format(Nx,Ny,Nz), - "grid\ta {}\tb {}\tc {}".format(*info['grid']), - "size\tx {}\ty {}\tz {}".format(*info['size']), - "origin\tx {}\ty {}\tz {}".format(*info['origin']), - "homogenization\t{}".format(info['homogenization']), - "microstructures\t{}".format(newInfo['microstructures']), - ]) - table.labels_clear() - table.labels_append(['{dim}_{label}'.format(dim = 1+i,label = options.position) for i in range(3)]+['microstructure']) - table.head_write() - table.output_flush() - -# --- write seeds information ------------------------------------------------------------ - - table.data = seeds - table.data_writeArray() + damask.util.report(scriptName,name) + geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) -# --- output finalization -------------------------------------------------------------------------- - - table.close() # close ASCII table + offset =(np.amin(options.box, axis=1)*geom.grid/geom.size).astype(int) + box = np.amax(options.box, axis=1) \ + - np.amin(options.box, axis=1) + + Nx = int(options.N/np.sqrt(options.N*geom.size[1]*box[1]/geom.size[0]/box[0])) + Ny = int(options.N/np.sqrt(options.N*geom.size[0]*box[0]/geom.size[1]/box[1])) + Nz = int(box[2]*geom.grid[2]) + + damask.util.croak('poking {} x {} x {} in box {} {} {}...'.format(Nx,Ny,Nz,*box)) + + seeds = np.zeros((Nx*Ny*Nz,4),'d') + g = np.zeros(3,'i') + + n = 0 + for i in range(Nx): + for j in range(Ny): + g[0] = round((i+0.5)*box[0]*geom.grid[0]/Nx-0.5)+offset[0] + g[1] = round((j+0.5)*box[1]*geom.grid[1]/Ny-0.5)+offset[1] + for k in range(Nz): + g[2] = k + offset[2] + g %= geom.grid + seeds[n,0:3] = (g+0.5)/geom.grid # normalize coordinates to box + seeds[n, 3] = geom.microstructure[g[0],g[1],g[2]] + if options.x: g[0] += 1 + if options.y: g[1] += 1 + n += 1 + + + comments = geom.comments \ + + [scriptID + ' ' + ' '.join(sys.argv[1:]), + "poking\ta {}\tb {}\tc {}".format(Nx,Ny,Nz), + "grid\ta {}\tb {}\tc {}".format(*geom.grid), + "size\tx {}\ty {}\tz {}".format(*geom.size), + "origin\tx {}\ty {}\tz {}".format(*geom.origin), + "homogenization\t{}".format(geom.homogenization)] + + table = damask.Table(seeds,{'pos':(3,),'microstructure':(1,)},comments) + table.to_ASCII(sys.stdout if name is None else \ + os.path.splitext(name)[0]+'_poked_{}.seeds'.format(options.N)) diff --git a/python/damask/__init__.py b/python/damask/__init__.py index 2e94d51ba..30fb37ced 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -1,9 +1,10 @@ """Main aggregator.""" import os +import re name = 'damask' with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f: - version = f.readline().strip() + version = re.sub(r'^v','',f.readline().strip()) # classes from .environment import Environment # noqa @@ -13,7 +14,7 @@ from .asciitable import ASCIItable # noqa from .config import Material # noqa from .colormaps import Colormap, Color # noqa from .orientation import Symmetry, Lattice, Rotation, Orientation # noqa -from .dadf5 import DADF5 # noqa +from .dadf5 import DADF5 # noqa from .geom import Geom # noqa from .solver import Solver # noqa @@ -22,7 +23,9 @@ from .util import extendableOption # noqa # functions in modules from . import mechanics # noqa +from . import grid_filters # noqa # clean temporary variables del os +del re del f diff --git a/python/damask/dadf5.py b/python/damask/dadf5.py index beced188d..edba4515c 100644 --- a/python/damask/dadf5.py +++ b/python/damask/dadf5.py @@ -1,7 +1,10 @@ from queue import Queue import re import glob +import os +import vtk +from vtk.util import numpy_support import h5py import numpy as np @@ -37,7 +40,7 @@ class DADF5(): self.version_major = f.attrs['DADF5-major'] self.version_minor = f.attrs['DADF5-minor'] - if self.version_major != 0 or not 2 <= self.version_minor <= 4: + if self.version_major != 0 or not 2 <= self.version_minor <= 5: raise TypeError('Unsupported DADF5 version {} '.format(f.attrs['DADF5-version'])) self.structured = 'grid' in f['geometry'].attrs.keys() @@ -45,6 +48,9 @@ class DADF5(): if self.structured: self.grid = f['geometry'].attrs['grid'] self.size = f['geometry'].attrs['size'] + if self.version_major == 0 and self.version_minor >= 5: + self.origin = f['geometry'].attrs['origin'] + r=re.compile('inc[0-9]+') increments_unsorted = {int(i[3:]):i for i in f.keys() if r.match(i)} @@ -360,7 +366,7 @@ class DADF5(): f[k] path.append(k) except KeyError as e: - print('unable to locate geometry dataset: {}'.format(str(e))) + pass for o,p in zip(['constituents','materialpoints'],['con_physics','mat_physics']): for oo in self.iter_visible(o): for pp in self.iter_visible(p): @@ -369,7 +375,7 @@ class DADF5(): f[k] path.append(k) except KeyError as e: - print('unable to locate {} dataset: {}'.format(o,str(e))) + pass return path @@ -433,7 +439,7 @@ class DADF5(): np.linspace(delta[1],self.size[1]-delta[1],self.grid[1]), np.linspace(delta[0],self.size[0]-delta[0],self.grid[0]), ) - return np.concatenate((x[:,:,:,None],y[:,:,:,None],y[:,:,:,None]),axis = 3).reshape([np.product(self.grid),3]) + return np.concatenate((x[:,:,:,None],y[:,:,:,None],z[:,:,:,None]),axis = 3).reshape([np.product(self.grid),3]) else: with h5py.File(self.fname,'r') as f: return f['geometry/x_c'][()] @@ -830,7 +836,7 @@ class DADF5(): N_not_calculated = len(todo) while N_not_calculated > 0: result = results.get() - with h5py.File(self.fname,'a') as f: # write to file + with h5py.File(self.fname,'a') as f: # write to file dataset_out = f[result['group']].create_dataset(result['label'],data=result['data']) for k in result['meta'].keys(): dataset_out.attrs[k] = result['meta'][k].encode() @@ -841,3 +847,142 @@ class DADF5(): N_added +=1 pool.wait_completion() + + + def to_vtk(self,labels,mode='Cell'): + """ + Export to vtk cell/point data. + + Parameters + ---------- + labels : list of str + Labels of the datasets to be exported. + mode : str, either 'Cell' or 'Point' + Export in cell format or point format. + Default value is 'Cell'. + + """ + if mode=='Cell': + + if self.structured: + + coordArray = [vtk.vtkDoubleArray(),vtk.vtkDoubleArray(),vtk.vtkDoubleArray()] + for dim in [0,1,2]: + for c in np.linspace(0,self.size[dim],1+self.grid[dim]): + coordArray[dim].InsertNextValue(c) + + vtk_geom = vtk.vtkRectilinearGrid() + vtk_geom.SetDimensions(*(self.grid+1)) + vtk_geom.SetXCoordinates(coordArray[0]) + vtk_geom.SetYCoordinates(coordArray[1]) + vtk_geom.SetZCoordinates(coordArray[2]) + + else: + + nodes = vtk.vtkPoints() + with h5py.File(self.fname) as f: + nodes.SetData(numpy_support.numpy_to_vtk(f['/geometry/x_n'][()],deep=True)) + + vtk_geom = vtk.vtkUnstructuredGrid() + vtk_geom.SetPoints(nodes) + vtk_geom.Allocate(f['/geometry/T_c'].shape[0]) + for i in f['/geometry/T_c']: + vtk_geom.InsertNextCell(vtk.VTK_HEXAHEDRON,8,i-1) # not for all elements! + elif mode == 'Point': + Points = vtk.vtkPoints() + Vertices = vtk.vtkCellArray() + for c in self.cell_coordinates(): + pointID = Points.InsertNextPoint(c) + Vertices.InsertNextCell(1) + Vertices.InsertCellPoint(pointID) + + vtk_geom = vtk.vtkPolyData() + vtk_geom.SetPoints(Points) + vtk_geom.SetVerts(Vertices) + vtk_geom.Modified() + + N_digits = int(np.floor(np.log10(int(self.increments[-1][3:]))))+1 + + for i,inc in enumerate(self.iter_visible('increments')): + vtk_data = [] + + materialpoints_backup = self.visible['materialpoints'].copy() + self.set_visible('materialpoints',False) + for label in labels: + for p in self.iter_visible('con_physics'): + if p != 'generic': + for c in self.iter_visible('constituents'): + x = self.get_dataset_location(label) + if len(x) == 0: + continue + array = self.read_dataset(x,0) + shape = [array.shape[0],np.product(array.shape[1:])] + vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape), + deep=True,array_type= vtk.VTK_DOUBLE)) + vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) #ToDo: hard coded 1! + vtk_geom.GetCellData().AddArray(vtk_data[-1]) + + else: + x = self.get_dataset_location(label) + if len(x) == 0: + continue + array = self.read_dataset(x,0) + shape = [array.shape[0],np.product(array.shape[1:])] + vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape), + deep=True,array_type= vtk.VTK_DOUBLE)) + ph_name = re.compile(r'(?<=(constituent\/))(.*?)(?=(generic))') # identify phase name + dset_name = '1_' + re.sub(ph_name,r'',x[0].split('/',1)[1]) # removing phase name + vtk_data[-1].SetName(dset_name) + vtk_geom.GetCellData().AddArray(vtk_data[-1]) + + self.set_visible('materialpoints',materialpoints_backup) + + constituents_backup = self.visible['constituents'].copy() + self.set_visible('constituents',False) + for label in labels: + for p in self.iter_visible('mat_physics'): + if p != 'generic': + for m in self.iter_visible('materialpoints'): + x = self.get_dataset_location(label) + if len(x) == 0: + continue + array = self.read_dataset(x,0) + shape = [array.shape[0],np.product(array.shape[1:])] + vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape), + deep=True,array_type= vtk.VTK_DOUBLE)) + vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) #ToDo: why 1_? + vtk_geom.GetCellData().AddArray(vtk_data[-1]) + else: + x = self.get_dataset_location(label) + if len(x) == 0: + continue + array = self.read_dataset(x,0) + shape = [array.shape[0],np.product(array.shape[1:])] + vtk_data.append(numpy_support.numpy_to_vtk(num_array=array.reshape(shape), + deep=True,array_type= vtk.VTK_DOUBLE)) + vtk_data[-1].SetName('1_'+x[0].split('/',1)[1]) + vtk_geom.GetCellData().AddArray(vtk_data[-1]) + self.set_visible('constituents',constituents_backup) + + if mode=='Cell': + writer = vtk.vtkXMLRectilinearGridWriter() if self.structured else \ + vtk.vtkXMLUnstructuredGridWriter() + x = self.get_dataset_location('u_n') + vtk_data.append(numpy_support.numpy_to_vtk(num_array=self.read_dataset(x,0), + deep=True,array_type=vtk.VTK_DOUBLE)) + vtk_data[-1].SetName('u') + vtk_geom.GetPointData().AddArray(vtk_data[-1]) + elif mode == 'Point': + writer = vtk.vtkXMLPolyDataWriter() + + + file_out = '{}_inc{}.{}'.format(os.path.splitext(os.path.basename(self.fname))[0], + inc[3:].zfill(N_digits), + writer.GetDefaultFileExtension()) + + writer.SetCompressorTypeToZLib() + writer.SetDataModeToBinary() + writer.SetFileName(file_out) + writer.SetInputData(vtk_geom) + + writer.Write() diff --git a/python/damask/geom.py b/python/damask/geom.py index 32ea2ed89..63ce20115 100644 --- a/python/damask/geom.py +++ b/python/damask/geom.py @@ -205,6 +205,9 @@ class Geom(): else: self.homogenization = homogenization + @property + def grid(self): + return self.get_grid() def get_microstructure(self): """Return the microstructure representation.""" diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py new file mode 100644 index 000000000..93e61f5d8 --- /dev/null +++ b/python/damask/grid_filters.py @@ -0,0 +1,375 @@ +from scipy import spatial +import numpy as np + +def __ks(size,grid,first_order=False): + """ + Get wave numbers operator. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + + """ + k_sk = np.where(np.arange(grid[0])>grid[0]//2,np.arange(grid[0])-grid[0],np.arange(grid[0]))/size[0] + if grid[0]%2 == 0 and first_order: k_sk[grid[0]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) + + k_sj = np.where(np.arange(grid[1])>grid[1]//2,np.arange(grid[1])-grid[1],np.arange(grid[1]))/size[1] + if grid[1]%2 == 0 and first_order: k_sj[grid[1]//2] = 0 # Nyquist freq=0 for even grid (Johnson, MIT, 2011) + + k_si = np.arange(grid[2]//2+1)/size[2] + + kk, kj, ki = np.meshgrid(k_sk,k_sj,k_si,indexing = 'ij') + return np.concatenate((ki[:,:,:,None],kj[:,:,:,None],kk[:,:,:,None]),axis = 3) + + +def curl(size,field): + """ + Calculate curl of a vector or tensor field in Fourier space. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + + """ + n = np.prod(field.shape[3:]) + k_s = __ks(size,field.shape[:3],True) + + e = np.zeros((3, 3, 3)) + e[0, 1, 2] = e[1, 2, 0] = e[2, 0, 1] = +1.0 # Levi-Civita symbol + e[0, 2, 1] = e[2, 1, 0] = e[1, 0, 2] = -1.0 + + field_fourier = np.fft.rfftn(field,axes=(0,1,2)) + curl = (np.einsum('slm,ijkl,ijkm ->ijks', e,k_s,field_fourier)*2.0j*np.pi if n == 3 else # vector, 3 -> 3 + np.einsum('slm,ijkl,ijknm->ijksn',e,k_s,field_fourier)*2.0j*np.pi) # tensor, 3x3 -> 3x3 + + return np.fft.irfftn(curl,axes=(0,1,2),s=field.shape[:3]) + + +def divergence(size,field): + """ + Calculate divergence of a vector or tensor field in Fourier space. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + + """ + n = np.prod(field.shape[3:]) + k_s = __ks(size,field.shape[:3],True) + + field_fourier = np.fft.rfftn(field,axes=(0,1,2)) + divergence = (np.einsum('ijkl,ijkl ->ijk', k_s,field_fourier)*2.0j*np.pi if n == 3 else # vector, 3 -> 1 + np.einsum('ijkm,ijklm->ijkl',k_s,field_fourier)*2.0j*np.pi) # tensor, 3x3 -> 3 + + return np.fft.irfftn(divergence,axes=(0,1,2),s=field.shape[:3]) + + +def gradient(size,field): + """ + Calculate gradient of a vector or scalar field in Fourier space. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + + """ + n = np.prod(field.shape[3:]) + k_s = __ks(size,field.shape[:3],True) + + field_fourier = np.fft.rfftn(field,axes=(0,1,2)) + gradient = (np.einsum('ijkl,ijkm->ijkm', field_fourier,k_s)*2.0j*np.pi if n == 1 else # scalar, 1 -> 3 + np.einsum('ijkl,ijkm->ijklm',field_fourier,k_s)*2.0j*np.pi) # vector, 3 -> 3x3 + + return np.fft.irfftn(gradient,axes=(0,1,2),s=field.shape[:3]) + + +def cell_coord0(grid,size,origin=np.zeros(3)): + """ + Cell center positions (undeformed). + + Parameters + ---------- + grid : numpy.ndarray + number of grid points. + size : numpy.ndarray + physical size of the periodic field. + origin : numpy.ndarray, optional + physical origin of the periodic field. Default is [0.0,0.0,0.0]. + + """ + start = origin + size/grid*.5 + end = origin - size/grid*.5 + size + x, y, z = np.meshgrid(np.linspace(start[2],end[2],grid[2]), + np.linspace(start[1],end[1],grid[1]), + np.linspace(start[0],end[0],grid[0]), + indexing = 'ij') + + return np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) + +def cell_displacement_fluct(size,F): + """ + Cell center displacement field from fluctuation part of the deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + integrator = 0.5j*size/np.pi + + k_s = __ks(size,F.shape[:3],False) + k_s_squared = np.einsum('...l,...l',k_s,k_s) + k_s_squared[0,0,0] = 1.0 + + displacement = -np.einsum('ijkml,ijkl,l->ijkm', + np.fft.rfftn(F,axes=(0,1,2)), + k_s, + integrator, + ) / k_s_squared[...,np.newaxis] + + return np.fft.irfftn(displacement,axes=(0,1,2),s=F.shape[:3]) + +def cell_displacement_avg(size,F): + """ + Cell center displacement field from average part of the deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + F_avg = np.average(F,axis=(0,1,2)) + return np.einsum('ml,ijkl->ijkm',F_avg-np.eye(3),cell_coord0(F.shape[:3][::-1],size)) + +def cell_displacement(size,F): + """ + Cell center displacement field from deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + return cell_displacement_avg(size,F) + cell_displacement_fluct(size,F) + +def cell_coord(size,F,origin=np.zeros(3)): + """ + Cell center positions. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + origin : numpy.ndarray, optional + physical origin of the periodic field. Default is [0.0,0.0,0.0]. + + """ + return cell_coord0(F.shape[:3][::-1],size,origin) + cell_displacement(size,F) + +def cell_coord0_2_DNA(coord0,ordered=True): + """ + Return grid 'DNA', i.e. grid, size, and origin from array of cell positions. + + Parameters + ---------- + coord0 : numpy.ndarray + array of undeformed cell coordinates. + ordered : bool, optional + expect coord0 data to be ordered (x fast, z slow). + + """ + coords = [np.unique(coord0[:,i]) for i in range(3)] + mincorner = np.array(list(map(min,coords))) + maxcorner = np.array(list(map(max,coords))) + grid = np.array(list(map(len,coords)),'i') + size = grid/np.maximum(grid-1,1) * (maxcorner-mincorner) + delta = size/grid + origin = mincorner - delta*.5 + + if grid.prod() != len(coord0): + raise ValueError('Data count {} does not match grid {}.'.format(len(coord0),grid)) + + start = origin + delta*.5 + end = origin - delta*.5 + size + + if not np.allclose(coords[0],np.linspace(start[0],end[0],grid[0])) and \ + np.allclose(coords[1],np.linspace(start[1],end[1],grid[1])) and \ + np.allclose(coords[2],np.linspace(start[2],end[2],grid[2])): + raise ValueError('Regular grid spacing violated.') + + if ordered and not np.allclose(coord0.reshape(tuple(grid[::-1])+(3,)),cell_coord0(grid,size,origin)): + raise ValueError('Input data is not a regular grid.') + + return (grid,size,origin) + +def coord0_check(coord0): + """ + Check whether coordinates lie on a regular grid. + + Parameters + ---------- + coord0 : numpy.ndarray + array of undeformed cell coordinates. + + """ + cell_coord0_2_DNA(coord0,ordered=True) + + + +def node_coord0(grid,size,origin=np.zeros(3)): + """ + Nodal positions (undeformed). + + Parameters + ---------- + grid : numpy.ndarray + number of grid points. + size : numpy.ndarray + physical size of the periodic field. + origin : numpy.ndarray, optional + physical origin of the periodic field. Default is [0.0,0.0,0.0]. + + """ + x, y, z = np.meshgrid(np.linspace(origin[2],size[2]+origin[2],1+grid[2]), + np.linspace(origin[1],size[1]+origin[1],1+grid[1]), + np.linspace(origin[0],size[0]+origin[0],1+grid[0]), + indexing = 'ij') + + return np.concatenate((z[:,:,:,None],y[:,:,:,None],x[:,:,:,None]),axis = 3) + +def node_displacement_fluct(size,F): + """ + Nodal displacement field from fluctuation part of the deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + return cell_2_node(cell_displacement_fluct(size,F)) + +def node_displacement_avg(size,F): + """ + Nodal displacement field from average part of the deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + F_avg = np.average(F,axis=(0,1,2)) + return np.einsum('ml,ijkl->ijkm',F_avg-np.eye(3),node_coord0(F.shape[:3][::-1],size)) + +def node_displacement(size,F): + """ + Nodal displacement field from deformation gradient field. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + + """ + return node_displacement_avg(size,F) + node_displacement_fluct(size,F) + +def node_coord(size,F,origin=np.zeros(3)): + """ + Nodal positions. + + Parameters + ---------- + size : numpy.ndarray + physical size of the periodic field. + F : numpy.ndarray + deformation gradient field. + origin : numpy.ndarray, optional + physical origin of the periodic field. Default is [0.0,0.0,0.0]. + + """ + return node_coord0(F.shape[:3][::-1],size,origin) + node_displacement(size,F) + +def cell_2_node(cell_data): + """Interpolate periodic cell data to nodal data.""" + n = ( cell_data + np.roll(cell_data,1,(0,1,2)) + + np.roll(cell_data,1,(0,)) + np.roll(cell_data,1,(1,)) + np.roll(cell_data,1,(2,)) + + np.roll(cell_data,1,(0,1)) + np.roll(cell_data,1,(1,2)) + np.roll(cell_data,1,(2,0)))*0.125 + + return np.pad(n,((0,1),(0,1),(0,1))+((0,0),)*len(cell_data.shape[3:]),mode='wrap') + +def node_2_cell(node_data): + """Interpolate periodic nodal data to cell data.""" + c = ( node_data + np.roll(node_data,1,(0,1,2)) + + np.roll(node_data,1,(0,)) + np.roll(node_data,1,(1,)) + np.roll(node_data,1,(2,)) + + np.roll(node_data,1,(0,1)) + np.roll(node_data,1,(1,2)) + np.roll(node_data,1,(2,0)))*0.125 + + return c[:-1,:-1,:-1] + +def node_coord0_2_DNA(coord0,ordered=False): + """ + Return grid 'DNA', i.e. grid, size, and origin from array of nodal positions. + + Parameters + ---------- + coord0 : numpy.ndarray + array of undeformed nodal coordinates + ordered : bool, optional + expect coord0 data to be ordered (x fast, z slow). + + """ + coords = [np.unique(coord0[:,i]) for i in range(3)] + mincorner = np.array(list(map(min,coords))) + maxcorner = np.array(list(map(max,coords))) + grid = np.array(list(map(len,coords)),'i') - 1 + size = maxcorner-mincorner + origin = mincorner + + if (grid+1).prod() != len(coord0): + raise ValueError('Data count {} does not match grid {}.'.format(len(coord0),grid)) + + if not np.allclose(coords[0],np.linspace(mincorner[0],maxcorner[0],grid[0]+1)) and \ + np.allclose(coords[1],np.linspace(mincorner[1],maxcorner[1],grid[1]+1)) and \ + np.allclose(coords[2],np.linspace(mincorner[2],maxcorner[2],grid[2]+1)): + raise ValueError('Regular grid spacing violated.') + + if ordered and not np.allclose(coord0.reshape(tuple((grid+1)[::-1])+(3,)),node_coord0(grid,size,origin)): + raise ValueError('Input data is not a regular grid.') + + return (grid,size,origin) + + +def regrid(size,F,new_grid): + """tbd.""" + c = cell_coord0(F.shape[:3][::-1],size) \ + + cell_displacement_avg(size,F) \ + + cell_displacement_fluct(size,F) + + outer = np.dot(np.average(F,axis=(0,1,2)),size) + for d in range(3): + c[np.where(c[:,:,:,d]<0)] += outer[d] + c[np.where(c[:,:,:,d]>outer[d])] -= outer[d] + + tree = spatial.cKDTree(c.reshape((-1,3)),boxsize=outer) + return tree.query(cell_coord0(new_grid,outer))[1] diff --git a/python/damask/orientation.py b/python/damask/orientation.py index 85a5c1866..a86ba9331 100644 --- a/python/damask/orientation.py +++ b/python/damask/orientation.py @@ -170,9 +170,18 @@ class Rotation: ################################################################################################ # convert to different orientation representations (numpy arrays) - def asQuaternion(self): - """Unit quaternion: (q, p_1, p_2, p_3).""" - return self.quaternion.asArray() + def asQuaternion(self, + quaternion = False): + """ + Unit quaternion [q, p_1, p_2, p_3] unless quaternion == True: damask.quaternion object. + + Parameters + ---------- + quaternion : bool, optional + return quaternion as DAMASK object. + + """ + return self.quaternion if quaternion else self.quaternion.asArray() def asEulers(self, degrees = False): @@ -190,33 +199,36 @@ class Rotation: return eu def asAxisAngle(self, - degrees = False): + degrees = False, + pair = False): """ - Axis angle pair: ([n_1, n_2, n_3], ω). + Axis angle representation [n_1, n_2, n_3, ω] unless pair == True: ([n_1, n_2, n_3], ω). Parameters ---------- degrees : bool, optional return rotation angle in degrees. + pair : bool, optional + return tuple of axis and angle. """ ax = qu2ax(self.quaternion.asArray()) if degrees: ax[3] = np.degrees(ax[3]) - return ax + return (ax[:3],np.degrees(ax[3])) if pair else ax def asMatrix(self): """Rotation matrix.""" return qu2om(self.quaternion.asArray()) def asRodrigues(self, - vector=False): + vector = False): """ - Rodrigues-Frank vector: ([n_1, n_2, n_3], tan(ω/2)). + Rodrigues-Frank vector representation [n_1, n_2, n_3, tan(ω/2)] unless vector == True: [n_1, n_2, n_3] * tan(ω/2). Parameters ---------- vector : bool, optional - return as array of length 3, i.e. scale the unit vector giving the rotation axis. + return as actual Rodrigues--Frank vector, i.e. rotation axis scaled by tan(ω/2). """ ro = qu2ro(self.quaternion.asArray()) @@ -252,8 +264,8 @@ class Rotation: acceptHomomorph = False, P = -1): - qu = quaternion if isinstance(quaternion, np.ndarray) and quaternion.dtype == np.dtype(float) \ - else np.array(quaternion,dtype=float) + qu = quaternion if isinstance(quaternion, np.ndarray) and quaternion.dtype == np.dtype(float) \ + else np.array(quaternion,dtype=float) if P > 0: qu[1:4] *= -1 # convert from P=1 to P=-1 if qu[0] < 0.0: if acceptHomomorph: @@ -701,14 +713,14 @@ class Symmetry: v = np.array(vector,dtype=float) if proper: # check both improper ... - theComponents = np.dot(basis['improper'],v) + theComponents = np.around(np.dot(basis['improper'],v),12) inSST = np.all(theComponents >= 0.0) if not inSST: # ... and proper SST - theComponents = np.dot(basis['proper'],v) + theComponents = np.around(np.dot(basis['proper'],v),12) inSST = np.all(theComponents >= 0.0) else: v[2] = abs(v[2]) # z component projects identical - theComponents = np.dot(basis['improper'],v) # for positive and negative values + theComponents = np.around(np.dot(basis['improper'],v),12) # for positive and negative values inSST = np.all(theComponents >= 0.0) if color: # have to return color array @@ -875,7 +887,7 @@ class Lattice: [[ 17, 12, 5],[ 17, 7, 17]], [[ 5, 17, 12],[ 17, 17, 7]], [[ 12, -5,-17],[ 7,-17,-17]], - [[-17,-12, 5],[-17, 7, 17]]],dtype='float')} + [[-17,-12, 5],[-17,-7, 17]]],dtype='float')} # Greninger--Troiano' orientation relationship for fcc <-> bcc transformation # from Y. He et al., Journal of Applied Crystallography 39:72-81, 2006 @@ -901,7 +913,7 @@ class Lattice: [[-17,-17, 7],[-17, -5, 12]], [[ 7,-17,-17],[ 12,-17, -5]], [[ 17, -7,-17],[ 5, -12,-17]], - [[ 17,-17, 7],[ 17, -5,-12]], + [[ 17,-17, -7],[ 17, -5,-12]], [[ -7, 17,-17],[-12, 17, -5]], [[-17, 7,-17],[ -5, 12,-17]], [[-17, 17, -7],[-17, 5,-12]]],dtype='float'), @@ -957,7 +969,7 @@ class Lattice: [[ 2, 1, -1],[ 0, -1, 1]], [[ -1, -2, -1],[ 0, -1, 1]], [[ -1, 1, 2],[ 0, -1, 1]], - [[ -1, 2, 1],[ 0, -1, 1]], + [[ 2, -1, 1],[ 0, -1, 1]], #It is wrong in the paper, but matrix is correct [[ -1, 2, 1],[ 0, -1, 1]], [[ -1, -1, -2],[ 0, -1, 1]]],dtype='float')} @@ -1025,7 +1037,7 @@ class Lattice: https://doi.org/10.1016/j.actamat.2004.11.021 """ - models={'KS':self.KS, 'GT':self.GT, "GT'":self.GTprime, + models={'KS':self.KS, 'GT':self.GT, 'GT_prime':self.GTprime, 'NW':self.NW, 'Pitsch': self.Pitsch, 'Bain':self.Bain} try: relationship = models[model] @@ -1046,13 +1058,13 @@ class Lattice: for miller in np.hstack((relationship['planes'],relationship['directions'])): myPlane = miller[myPlane_id]/ np.linalg.norm(miller[myPlane_id]) myDir = miller[myDir_id]/ np.linalg.norm(miller[myDir_id]) - myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]).T + myMatrix = np.array([myDir,np.cross(myPlane,myDir),myPlane]) otherPlane = miller[otherPlane_id]/ np.linalg.norm(miller[otherPlane_id]) otherDir = miller[otherDir_id]/ np.linalg.norm(miller[otherDir_id]) - otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]).T + otherMatrix = np.array([otherDir,np.cross(otherPlane,otherDir),otherPlane]) - r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix,myMatrix.T))) + r['rotations'].append(Rotation.fromMatrix(np.dot(otherMatrix.T,myMatrix))) return r @@ -1126,10 +1138,9 @@ class Orientation: return (Orientation(r,self.lattice), i,j, k == 1) if symmetries else r # disorientation ... # ... own sym, other sym, # self-->other: True, self<--other: False - - def inFZ(self): return self.lattice.symmetry.inFZ(self.rotation.asRodrigues(vector=True)) + def equivalentOrientations(self,members=[]): """List of orientations which are symmetrically equivalent.""" @@ -1144,7 +1155,8 @@ class Orientation: def relatedOrientations(self,model): """List of orientations related by the given orientation relationship.""" r = self.lattice.relationOperations(model) - return [self.__class__(self.rotation*o,r['lattice']) for o in r['rotations']] + return [self.__class__(o*self.rotation,r['lattice']) for o in r['rotations']] + def reduced(self): """Transform orientation to fall into fundamental zone according to symmetry.""" @@ -1152,7 +1164,8 @@ class Orientation: if self.lattice.symmetry.inFZ(me.rotation.asRodrigues(vector=True)): break return self.__class__(me.rotation,self.lattice) - + + def inversePole(self, axis, proper = False, @@ -1192,9 +1205,9 @@ class Orientation: ref = orientations[0] for o in orientations: closest.append(o.equivalentOrientations( - ref.disorientation(o, - SST = False, # select (o[ther]'s) sym orientation - symmetries = True)[2]).rotation) # with lowest misorientation + ref.disorientation(o, + SST = False, # select (o[ther]'s) sym orientation + symmetries = True)[2]).rotation) # with lowest misorientation return Orientation(Rotation.fromAverage(closest,weights),ref.lattice) diff --git a/python/damask/table.py b/python/damask/table.py index 6181fdb1f..a5ce50237 100644 --- a/python/damask/table.py +++ b/python/damask/table.py @@ -3,6 +3,8 @@ import re import pandas as pd import numpy as np +from . import version + class Table(): """Store spreadsheet-like data.""" @@ -20,7 +22,7 @@ class Table(): Additional, human-readable information. """ - self.comments = [] if comments is None else [c for c in comments] + self.comments = ['table.py v {}'.format(version)] if not comments else [c for c in comments] self.data = pd.DataFrame(data=data) self.shapes = shapes self.__label_condensed() @@ -69,13 +71,16 @@ class Table(): f = open(fname) except TypeError: f = fname + f.seek(0) header,keyword = f.readline().split() if keyword == 'header': header = int(header) else: raise Exception - comments = [f.readline()[:-1] for i in range(1,header)] + + comments = ['table.py:from_ASCII v {}'.format(version)] + comments+= [f.readline()[:-1] for i in range(1,header)] labels = f.readline().split() shapes = {} @@ -95,9 +100,49 @@ class Table(): return Table(data,shapes,comments) + @staticmethod + def from_ang(fname): + """ + Create table from TSL ang file. + + A valid TSL ang file needs to contains the following columns: + * Euler angles (Bunge notation) in radians, 3 floats, label 'eu'. + * Spatial position in meters, 2 floats, label 'pos'. + * Image quality, 1 float, label 'IQ'. + * Confidence index, 1 float, label 'CI'. + * Phase ID, 1 int, label 'ID'. + * SEM signal, 1 float, label 'intensity'. + * Fit, 1 float, label 'fit'. + + Parameters + ---------- + fname : file, str, or pathlib.Path + Filename or file for reading. + + """ + shapes = {'eu':(3,), 'pos':(2,), + 'IQ':(1,), 'CI':(1,), 'ID':(1,), 'intensity':(1,), 'fit':(1,)} + try: + f = open(fname) + except TypeError: + f = fname + f.seek(0) + + content = f.readlines() + + comments = ['table.py:from_ang v {}'.format(version)] + for line in content: + if line.startswith('#'): + comments.append(line.strip()) + else: + break + + data = np.loadtxt(content) + + return Table(data,shapes,comments) + @property def labels(self): - """Return the labels of all columns.""" return list(self.shapes.keys()) @@ -203,7 +248,7 @@ class Table(): '' if info is None else ': {}'.format(info), )) - self.shapes[label_new] = self.shapes.pop(label_old) + self.shapes = {(label if label is not label_old else label_new):self.shapes[label] for label in self.shapes} def sort_by(self,labels,ascending=True): @@ -234,8 +279,9 @@ class Table(): Filename or file for reading. """ + seen = set() labels = [] - for l in self.shapes: + for l in [x for x in self.data.columns if not (x in seen or seen.add(x))]: if(self.shapes[l] == (1,)): labels.append('{}'.format(l)) elif(len(self.shapes[l]) == 1): diff --git a/python/damask/util.py b/python/damask/util.py index 63b9aed65..0065daba5 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -7,9 +7,6 @@ from optparse import Option from queue import Queue from threading import Thread - -import numpy as np - class bcolors: """ ASCII Colors (Blender code). @@ -64,19 +61,6 @@ def report(who = None, croak( (emph(who)+': ' if who is not None else '') + (what if what is not None else '') + '\n' ) -# ----------------------------- -def report_geom(info, - what = ['grid','size','origin','homogenization','microstructures']): - """Reports (selected) geometry information.""" - output = { - 'grid' : 'grid a b c: {}'.format(' x '.join(list(map(str,info['grid' ])))), - 'size' : 'size x y z: {}'.format(' x '.join(list(map(str,info['size' ])))), - 'origin' : 'origin x y z: {}'.format(' : '.join(list(map(str,info['origin'])))), - 'homogenization' : 'homogenization: {}'.format(info['homogenization']), - 'microstructures' : 'microstructures: {}'.format(info['microstructures']), - } - for item in what: croak(output[item.lower()]) - # ----------------------------- def emph(what): """Formats string with emphasis.""" @@ -119,30 +103,6 @@ def execute(cmd, if process.returncode != 0: raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) return out,error -def coordGridAndSize(coordinates): - """Determines grid count and overall physical size along each dimension of an ordered array of coordinates.""" - dim = coordinates.shape[1] - coords = [np.unique(coordinates[:,i]) for i in range(dim)] - mincorner = np.array(list(map(min,coords))) - maxcorner = np.array(list(map(max,coords))) - grid = np.array(list(map(len,coords)),'i') - size = grid/np.maximum(np.ones(dim,'d'), grid-1.0) * (maxcorner-mincorner) # size from edge to edge = dim * n/(n-1) - size = np.where(grid > 1, size, min(size[grid > 1]/grid[grid > 1])) # spacing for grid==1 equal to smallest among other ones - delta = size/grid - - N = grid.prod() - - if N != len(coordinates): - raise ValueError('Data count {} does not match grid {}.'.format(len(coordinates),' x '.join(map(repr,grid)))) - - if np.any(np.abs(np.log10((coords[0][1:]-coords[0][:-1])/delta[0])) > 0.01) \ - or np.any(np.abs(np.log10((coords[1][1:]-coords[1][:-1])/delta[1])) > 0.01): - raise ValueError('regular grid spacing {} violated.'.format(' x '.join(map(repr,delta)))) - if dim==3 and np.any(np.abs(np.log10((coords[2][1:]-coords[2][:-1])/delta[2])) > 0.01): - raise ValueError('regular grid spacing {} violated.'.format(' x '.join(map(repr,delta)))) - - return grid,size - # ----------------------------- class extendableOption(Option): """ @@ -221,263 +181,6 @@ class return_message(): return srepr(self.message) -def leastsqBound(func, x0, args=(), bounds=None, Dfun=None, full_output=0, - col_deriv=0, ftol=1.49012e-8, xtol=1.49012e-8, - gtol=0.0, maxfev=0, epsfcn=None, factor=100, diag=None): - from scipy.optimize import _minpack - """ - Non-linear least square fitting (Levenberg-Marquardt method) with - bounded parameters. - the codes of transformation between int <-> ext refers to the work of - Jonathan J. Helmus: https://github.com/jjhelmus/leastsqbound-scipy - other codes refer to the source code of minpack.py: - - An internal parameter list is used to enforce contraints on the fitting - parameters. The transfomation is based on that of MINUIT package. - please see: F. James and M. Winkler. MINUIT User's Guide, 2004. - - bounds : list - (min, max) pairs for each parameter, use None for 'min' or 'max' - when there is no bound in that direction. - For example: if there are two parameters needed to be fitting, then - bounds is [(min1,max1), (min2,max2)] - - This function is based on 'leastsq' of minpack.py, the annotation of - other parameters can be found in 'least_squares.py'. - """ - - def _check_func(checker, argname, thefunc, x0, args, numinputs, - output_shape=None): - from numpy import shape - """The same as that of minpack.py""" - res = np.atleast_1d(thefunc(*((x0[:numinputs],) + args))) - if (output_shape is not None) and (shape(res) != output_shape): - if (output_shape[0] != 1): - if len(output_shape) > 1: - if output_shape[1] == 1: - return shape(res) - msg = "%s: there is a mismatch between the input and output " \ - "shape of the '%s' argument" % (checker, argname) - func_name = getattr(thefunc, '__name__', None) - if func_name: - msg += " '%s'." % func_name - else: - msg += "." - raise TypeError(msg) - if np.issubdtype(res.dtype, np.inexact): - dt = res.dtype - else: - dt = dtype(float) - return shape(res), dt - - def _int2extGrad(p_int, bounds): - """Calculate the gradients of transforming the internal (unconstrained) to external (constrained) parameter.""" - grad = np.empty_like(p_int) - for i, (x, bound) in enumerate(zip(p_int, bounds)): - lower, upper = bound - if lower is None and upper is None: # No constraints - grad[i] = 1.0 - elif upper is None: # only lower bound - grad[i] = x/np.sqrt(x*x + 1.0) - elif lower is None: # only upper bound - grad[i] = -x/np.sqrt(x*x + 1.0) - else: # lower and upper bounds - grad[i] = (upper - lower)*np.cos(x)/2.0 - return grad - - def _int2extFunc(bounds): - """Transform internal parameters into external parameters.""" - local = [_int2extLocal(b) for b in bounds] - - def _transform_i2e(p_int): - p_ext = np.empty_like(p_int) - p_ext[:] = [i(j) for i, j in zip(local, p_int)] - return p_ext - return _transform_i2e - - def _ext2intFunc(bounds): - """Transform external parameters into internal parameters.""" - local = [_ext2intLocal(b) for b in bounds] - - def _transform_e2i(p_ext): - p_int = np.empty_like(p_ext) - p_int[:] = [i(j) for i, j in zip(local, p_ext)] - return p_int - return _transform_e2i - - def _int2extLocal(bound): - """Transform a single internal parameter to an external parameter.""" - lower, upper = bound - if lower is None and upper is None: # no constraints - return lambda x: x - elif upper is None: # only lower bound - return lambda x: lower - 1.0 + np.sqrt(x*x + 1.0) - elif lower is None: # only upper bound - return lambda x: upper + 1.0 - np.sqrt(x*x + 1.0) - else: - return lambda x: lower + ((upper - lower)/2.0)*(np.sin(x) + 1.0) - - def _ext2intLocal(bound): - """Transform a single external parameter to an internal parameter.""" - lower, upper = bound - if lower is None and upper is None: # no constraints - return lambda x: x - elif upper is None: # only lower bound - return lambda x: np.sqrt((x - lower + 1.0)**2 - 1.0) - elif lower is None: # only upper bound - return lambda x: np.sqrt((x - upper - 1.0)**2 - 1.0) - else: - return lambda x: np.arcsin((2.0*(x - lower)/(upper - lower)) - 1.0) - - i2e = _int2extFunc(bounds) - e2i = _ext2intFunc(bounds) - - x0 = np.asarray(x0).flatten() - n = len(x0) - - if len(bounds) != n: - raise ValueError('the length of bounds is inconsistent with the number of parameters ') - - if not isinstance(args, tuple): - args = (args,) - - shape, dtype = _check_func('leastsq', 'func', func, x0, args, n) - m = shape[0] - - if n > m: - raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m)) - if epsfcn is None: - epsfcn = np.finfo(dtype).eps - - def funcWarp(x, *args): - return func(i2e(x), *args) - - xi0 = e2i(x0) - - if Dfun is None: - if maxfev == 0: - maxfev = 200*(n + 1) - retval = _minpack._lmdif(funcWarp, xi0, args, full_output, ftol, xtol, - gtol, maxfev, epsfcn, factor, diag) - else: - if col_deriv: - _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (n, m)) - else: - _check_func('leastsq', 'Dfun', Dfun, x0, args, n, (m, n)) - if maxfev == 0: - maxfev = 100*(n + 1) - - def DfunWarp(x, *args): - return Dfun(i2e(x), *args) - - retval = _minpack._lmder(funcWarp, DfunWarp, xi0, args, full_output, col_deriv, - ftol, xtol, gtol, maxfev, factor, diag) - - errors = {0: ["Improper input parameters.", TypeError], - 1: ["Both actual and predicted relative reductions " - "in the sum of squares\n are at most %f" % ftol, None], - 2: ["The relative error between two consecutive " - "iterates is at most %f" % xtol, None], - 3: ["Both actual and predicted relative reductions in " - "the sum of squares\n are at most %f and the " - "relative error between two consecutive " - "iterates is at \n most %f" % (ftol, xtol), None], - 4: ["The cosine of the angle between func(x) and any " - "column of the\n Jacobian is at most %f in " - "absolute value" % gtol, None], - 5: ["Number of calls to function has reached " - "maxfev = %d." % maxfev, ValueError], - 6: ["ftol=%f is too small, no further reduction " - "in the sum of squares\n is possible.""" % ftol, - ValueError], - 7: ["xtol=%f is too small, no further improvement in " - "the approximate\n solution is possible." % xtol, - ValueError], - 8: ["gtol=%f is too small, func(x) is orthogonal to the " - "columns of\n the Jacobian to machine " - "precision." % gtol, ValueError], - 'unknown': ["Unknown error.", TypeError]} - - info = retval[-1] # The FORTRAN return value - - if info not in [1, 2, 3, 4] and not full_output: - if info in [5, 6, 7, 8]: - np.warnings.warn(errors[info][0], RuntimeWarning) - else: - try: - raise errors[info][1](errors[info][0]) - except KeyError: - raise errors['unknown'][1](errors['unknown'][0]) - - mesg = errors[info][0] - x = i2e(retval[0]) - - if full_output: - grad = _int2extGrad(retval[0], bounds) - retval[1]['fjac'] = (retval[1]['fjac'].T / np.take(grad, - retval[1]['ipvt'] - 1)).T - cov_x = None - if info in [1, 2, 3, 4]: - from numpy.dual import inv - from numpy.linalg import LinAlgError - perm = np.take(np.eye(n), retval[1]['ipvt'] - 1, 0) - r = np.triu(np.transpose(retval[1]['fjac'])[:n, :]) - R = np.dot(r, perm) - try: - cov_x = inv(np.dot(np.transpose(R), R)) - except LinAlgError as inverror: - print(inverror) - pass - return (x, cov_x) + retval[1:-1] + (mesg, info) - else: - return (x, info) - -def _general_function(params, ydata, xdata, function): - return function(xdata, *params) - ydata -def _weighted_general_function(params, ydata, xdata, function, weights): - return (function(xdata, *params) - ydata)*weights - -def curve_fit_bound(f, xdata, ydata, p0=None, sigma=None, bounds=None, **kw): - """Similar as 'curve_fit' in minpack.py.""" - if p0 is None: - # determine number of parameters by inspecting the function - import inspect - args, varargs, varkw, defaults = inspect.getargspec(f) - if len(args) < 2: - msg = "Unable to determine number of fit parameters." - raise ValueError(msg) - if 'self' in args: - p0 = [1.0] * (len(args)-2) - else: - p0 = [1.0] * (len(args)-1) - - if np.isscalar(p0): - p0 = np.array([p0]) - - args = (ydata, xdata, f) - if sigma is None: - func = _general_function - else: - func = _weighted_general_function - args += (1.0/np.asarray(sigma),) - - return_full = kw.pop('full_output', False) - res = leastsqBound(func, p0, args=args, bounds = bounds, full_output=True, **kw) - (popt, pcov, infodict, errmsg, ier) = res - - if ier not in [1, 2, 3, 4]: - msg = "Optimal parameters not found: " + errmsg - raise RuntimeError(msg) - - if (len(ydata) > len(p0)) and pcov is not None: - s_sq = (func(popt, *args)**2).sum()/(len(ydata)-len(p0)) - pcov = pcov * s_sq - else: - pcov = np.inf - - return (popt, pcov, infodict, errmsg, ier) if return_full else (popt, pcov) - - class ThreadPool: """Pool of threads consuming tasks from a queue.""" diff --git a/python/setup.py b/python/setup.py index 7324a6840..8126d1331 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,8 +1,9 @@ import setuptools import os +import re with open(os.path.join(os.path.dirname(__file__),'damask/VERSION')) as f: - version = f.readline().strip() + version = re.sub(r'^v','',f.readline().strip()) setuptools.setup( name="damask", @@ -15,9 +16,8 @@ setuptools.setup( packages=setuptools.find_packages(), include_package_data=True, install_requires = [ - "numpy", - "scipy", "pandas", + "scipy", "h5py", "vtk", ], diff --git a/python/tests/reference/Rotation/1_BCC.pdf b/python/tests/reference/Rotation/1_BCC.pdf new file mode 100644 index 000000000..445f1d250 Binary files /dev/null and b/python/tests/reference/Rotation/1_BCC.pdf differ diff --git a/python/tests/reference/Rotation/1_FCC.pdf b/python/tests/reference/Rotation/1_FCC.pdf new file mode 100644 index 000000000..1dade6b60 Binary files /dev/null and b/python/tests/reference/Rotation/1_FCC.pdf differ diff --git a/python/tests/reference/Rotation/2_BCC.pdf b/python/tests/reference/Rotation/2_BCC.pdf new file mode 100644 index 000000000..423bc645d Binary files /dev/null and b/python/tests/reference/Rotation/2_BCC.pdf differ diff --git a/python/tests/reference/Rotation/2_FCC.pdf b/python/tests/reference/Rotation/2_FCC.pdf new file mode 100644 index 000000000..813076c61 Binary files /dev/null and b/python/tests/reference/Rotation/2_FCC.pdf differ diff --git a/python/tests/reference/Rotation/PoleFigures_OR.m b/python/tests/reference/Rotation/PoleFigures_OR.m new file mode 100644 index 000000000..1e57ca01d --- /dev/null +++ b/python/tests/reference/Rotation/PoleFigures_OR.m @@ -0,0 +1,38 @@ +% Start MTEX first in Matlab + +tmp = matlab.desktop.editor.getActive; +cd(fileparts(tmp.Filename)); + +symmetry = {crystalSymmetry('m-3m', [1 1 1], 'mineral', 'Iron', 'color', 'light blue')} + +% plotting convention +setMTEXpref('xAxisDirection','north'); +setMTEXpref('zAxisDirection','outOfPlane'); + + +lattice_types = {'BCC','FCC'}; +models = {'Bain','GT','GT_prime','KS','NW','Pitsch'}; + +rotation = containers.Map; +rotation('BCC') = 'Passive Rotation'; +rotation('FCC') = 'Active Rotation'; + +for lattice = lattice_types + for p = 0:length(models)/3-1 + EBSD_data = {loadEBSD(strcat(lattice,'_',models{p*3+1},'.txt'),symmetry,'interface','generic',... + 'ColumnNames', { 'phi1' 'Phi' 'phi2' 'x' 'y'}, 'Bunge', rotation(char(lattice))), + loadEBSD(strcat(lattice,'_',models{p*3+2},'.txt'),symmetry,'interface','generic',... + 'ColumnNames', { 'phi1' 'Phi' 'phi2' 'x' 'y'}, 'Bunge', rotation(char(lattice))), + loadEBSD(strcat(lattice,'_',models{p*3+3},'.txt'),symmetry,'interface','generic',... + 'ColumnNames', { 'phi1' 'Phi' 'phi2' 'x' 'y'}, 'Bunge', rotation(char(lattice)))} + h = [Miller(1,0,0,symmetry{1}),Miller(1,1,0,symmetry{1}),Miller(1,1,1,symmetry{1})]; % 3 pole figures + plotPDF(EBSD_data{1}.orientations,h,'MarkerSize',5,'MarkerColor','r','DisplayName',models{p*3+1}) + hold on + plotPDF(EBSD_data{2}.orientations,h,'MarkerSize',4,'MarkerColor','b','DisplayName',models{p*3+2}) + plotPDF(EBSD_data{3}.orientations,h,'MarkerSize',3,'MarkerColor','g','DisplayName',models{p*3+3}) + legend('show','location','southoutside','Interpreter', 'none') + orient('landscape') + print('-bestfit',strcat(int2str(p+1),'_',char(lattice),'.pdf'),'-dpdf') + close + end +end \ No newline at end of file diff --git a/python/tests/reference/Rotation/bcc_Bain.txt b/python/tests/reference/Rotation/bcc_Bain.txt new file mode 100644 index 000000000..e0bc4f6c7 --- /dev/null +++ b/python/tests/reference/Rotation/bcc_Bain.txt @@ -0,0 +1,5 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +0.0 45.00000000000001 0.0 1 1 +90.0 45.00000000000001 270.0 1 2 +45.00000000000001 0.0 0.0 1 3 diff --git a/python/tests/reference/Rotation/bcc_GT.txt b/python/tests/reference/Rotation/bcc_GT.txt new file mode 100644 index 000000000..5d5102698 --- /dev/null +++ b/python/tests/reference/Rotation/bcc_GT.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +283.60440567265294 9.976439066337804 33.24637065555936 1 1 +167.8261034151001 43.397849654402556 183.40022280897963 1 2 +262.1156357053931 43.82007387041961 104.07478363123654 1 3 +103.604405672653 9.976439066337804 213.24637065555936 1 4 +347.8261034151001 43.39784965440255 3.400222808979685 1 5 +82.11563570539313 43.82007387041961 284.0747836312365 1 6 +76.39559432734703 9.976439066337806 326.75362934444064 1 7 +192.17389658489986 43.397849654402556 176.59977719102034 1 8 +97.88436429460687 43.82007387041961 255.92521636876344 1 9 +256.395594327347 9.976439066337804 146.75362934444064 1 10 +12.173896584899929 43.39784965440254 356.59977719102034 1 11 +277.8843642946069 43.82007387041961 75.92521636876346 1 12 +102.17389658489992 43.39784965440254 266.59977719102034 1 13 +346.395594327347 9.976439066337804 56.75362934444064 1 14 +7.884364294606862 43.82007387041961 345.9252163687635 1 15 +282.17389658489986 43.39784965440254 86.59977719102032 1 16 +166.39559432734703 9.976439066337804 236.75362934444058 1 17 +187.88436429460683 43.82007387041961 165.92521636876344 1 18 +257.8261034151001 43.39784965440255 93.40022280897969 1 19 +13.604405672652977 9.976439066337804 303.24637065555936 1 20 +352.1156357053931 43.82007387041961 14.074783631236542 1 21 +77.82610341510008 43.397849654402556 273.4002228089796 1 22 +193.60440567265297 9.976439066337806 123.24637065555939 1 23 +172.11563570539317 43.82007387041961 194.07478363123653 1 24 diff --git a/python/tests/reference/Rotation/bcc_GT_prime.txt b/python/tests/reference/Rotation/bcc_GT_prime.txt new file mode 100644 index 000000000..e398d3139 --- /dev/null +++ b/python/tests/reference/Rotation/bcc_GT_prime.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +303.24637065555936 9.976439066337804 13.604405672652977 1 1 +165.92521636876344 43.82007387041961 187.88436429460683 1 2 +266.59977719102034 43.39784965440254 102.17389658489992 1 3 +123.24637065555939 9.976439066337804 193.604405672653 1 4 +345.9252163687635 43.82007387041961 7.884364294606862 1 5 +86.59977719102032 43.39784965440254 282.17389658489986 1 6 +56.75362934444064 9.976439066337804 346.395594327347 1 7 +194.07478363123653 43.82007387041961 172.11563570539317 1 8 +93.40022280897969 43.39784965440255 257.8261034151001 1 9 +236.75362934444058 9.976439066337804 166.39559432734697 1 10 +14.074783631236542 43.82007387041961 352.1156357053931 1 11 +273.4002228089796 43.397849654402556 77.82610341510008 1 12 +104.07478363123654 43.82007387041961 262.1156357053931 1 13 +326.75362934444064 9.976439066337806 76.39559432734703 1 14 +3.400222808979685 43.39784965440255 347.8261034151001 1 15 +284.0747836312365 43.82007387041961 82.11563570539313 1 16 +146.75362934444064 9.976439066337804 256.395594327347 1 17 +183.40022280897963 43.397849654402556 167.8261034151001 1 18 +255.92521636876344 43.82007387041961 97.88436429460687 1 19 +33.24637065555936 9.976439066337804 283.60440567265294 1 20 +356.59977719102034 43.39784965440254 12.173896584899929 1 21 +75.92521636876346 43.82007387041961 277.8843642946069 1 22 +213.24637065555936 9.976439066337804 103.604405672653 1 23 +176.59977719102034 43.397849654402556 192.17389658489986 1 24 diff --git a/python/tests/reference/Rotation/bcc_KS.txt b/python/tests/reference/Rotation/bcc_KS.txt new file mode 100644 index 000000000..34b393358 --- /dev/null +++ b/python/tests/reference/Rotation/bcc_KS.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +335.7965716606702 10.528779365509317 65.79657166067024 1 1 +228.77270547567446 80.40593177313953 85.64260312151849 1 2 +131.22729452432552 80.40593177313954 4.357396878481506 1 3 +24.20342833932977 10.52877936550932 24.20342833932976 1 4 +221.95489158457983 85.70366403943002 80.37863910890589 1 5 +138.04510841542015 85.70366403943004 9.621360891094124 1 6 +131.22729452432552 80.40593177313953 94.35739687848151 1 7 +24.203428339329765 10.52877936550932 114.20342833932976 1 8 +221.95489158457983 85.70366403943004 170.37863910890587 1 9 +138.04510841542015 85.70366403943004 99.62136089109411 1 10 +335.7965716606702 10.52877936550932 155.79657166067025 1 11 +228.77270547567448 80.40593177313954 175.6426031215185 1 12 +335.7965716606702 10.52877936550932 335.7965716606702 1 13 +228.77270547567448 80.40593177313954 355.6426031215185 1 14 +131.2272945243255 80.40593177313954 274.35739687848144 1 15 +24.203428339329747 10.52877936550932 294.2034283393298 1 16 +221.95489158457985 85.70366403943004 350.3786391089059 1 17 +138.04510841542015 85.70366403943004 279.6213608910941 1 18 +41.95489158457986 94.29633596056998 9.621360891094133 1 19 +318.04510841542015 94.29633596056996 80.37863910890589 1 20 +155.79657166067025 169.4712206344907 24.203428339329754 1 21 +48.77270547567448 99.59406822686046 4.357396878481504 1 22 +311.2272945243255 99.59406822686046 85.64260312151852 1 23 +204.20342833932975 169.4712206344907 65.79657166067024 1 24 diff --git a/python/tests/reference/Rotation/bcc_NW.txt b/python/tests/reference/Rotation/bcc_NW.txt new file mode 100644 index 000000000..754c69bba --- /dev/null +++ b/python/tests/reference/Rotation/bcc_NW.txt @@ -0,0 +1,14 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +225.41555594321144 83.13253115922213 83.08266205989301 1 1 +134.58444405678856 83.13253115922211 6.917337940107012 1 2 +4.702125169424418e-15 9.735610317245317 45.0 1 3 +134.58444405678856 83.13253115922213 276.91733794010696 1 4 +225.4155559432114 83.13253115922213 353.082662059893 1 5 +0.0 9.735610317245317 315.0 1 6 +134.58444405678858 83.13253115922213 96.91733794010702 1 7 +225.41555594321142 83.13253115922213 173.082662059893 1 8 +0.0 9.735610317245317 135.0 1 9 +99.59803029876785 45.81931182053557 166.36129272052355 1 10 +260.40196970123213 45.81931182053556 283.6387072794765 1 11 +180.0 99.73561031724535 225.0 1 12 diff --git a/python/tests/reference/Rotation/bcc_Pitsch.txt b/python/tests/reference/Rotation/bcc_Pitsch.txt new file mode 100644 index 000000000..ef28bbb4d --- /dev/null +++ b/python/tests/reference/Rotation/bcc_Pitsch.txt @@ -0,0 +1,14 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +6.9173379401070045 83.13253115922213 44.58444405678856 1 1 +45.0 89.99999999999999 279.7356103172453 1 2 +166.36129272052352 45.819311820535574 279.59803029876787 1 3 +83.08266205989301 83.13253115922213 225.41555594321144 1 4 +256.3612927205235 45.819311820535574 189.59803029876787 1 5 +315.0 90.0 9.735610317245369 1 6 +186.917337940107 83.13253115922213 224.58444405678856 1 7 +315.0 90.0 80.26438968275463 1 8 +13.638707279476478 45.81931182053557 260.40196970123213 1 9 +263.082662059893 83.13253115922213 45.415555943211444 1 10 +103.63870727947646 45.819311820535574 170.40196970123213 1 11 +224.99999999999997 90.0 170.26438968275465 1 12 diff --git a/python/tests/reference/Rotation/fcc_Bain.txt b/python/tests/reference/Rotation/fcc_Bain.txt new file mode 100644 index 000000000..876cf3888 --- /dev/null +++ b/python/tests/reference/Rotation/fcc_Bain.txt @@ -0,0 +1,5 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +180.0 45.00000000000001 180.0 1 1 +270.0 45.00000000000001 90.0 1 2 +315.0 0.0 0.0 1 3 diff --git a/python/tests/reference/Rotation/fcc_GT.txt b/python/tests/reference/Rotation/fcc_GT.txt new file mode 100644 index 000000000..cefae431a --- /dev/null +++ b/python/tests/reference/Rotation/fcc_GT.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +146.75362934444064 9.976439066337804 256.395594327347 1 1 +356.59977719102034 43.39784965440254 12.173896584899929 1 2 +75.92521636876346 43.82007387041961 277.8843642946069 1 3 +326.75362934444064 9.976439066337806 76.39559432734703 1 4 +176.59977719102034 43.397849654402556 192.17389658489986 1 5 +255.92521636876344 43.82007387041961 97.88436429460687 1 6 +213.24637065555936 9.976439066337804 103.604405672653 1 7 +3.400222808979685 43.39784965440255 347.8261034151001 1 8 +284.0747836312365 43.82007387041961 82.11563570539313 1 9 +33.24637065555936 9.976439066337804 283.60440567265294 1 10 +183.40022280897963 43.397849654402556 167.8261034151001 1 11 +104.07478363123654 43.82007387041961 262.1156357053931 1 12 +273.4002228089796 43.397849654402556 77.82610341510008 1 13 +123.24637065555939 9.976439066337806 193.60440567265297 1 14 +194.07478363123653 43.82007387041961 172.11563570539317 1 15 +93.40022280897969 43.39784965440255 257.8261034151001 1 16 +303.24637065555936 9.976439066337804 13.604405672652977 1 17 +14.074783631236542 43.82007387041961 352.1156357053931 1 18 +86.59977719102032 43.39784965440254 282.17389658489986 1 19 +236.75362934444058 9.976439066337804 166.39559432734703 1 20 +165.92521636876344 43.82007387041961 187.88436429460683 1 21 +266.59977719102034 43.39784965440254 102.17389658489992 1 22 +56.75362934444064 9.976439066337804 346.395594327347 1 23 +345.9252163687635 43.82007387041961 7.884364294606862 1 24 diff --git a/python/tests/reference/Rotation/fcc_GT_prime.txt b/python/tests/reference/Rotation/fcc_GT_prime.txt new file mode 100644 index 000000000..44a9b25ec --- /dev/null +++ b/python/tests/reference/Rotation/fcc_GT_prime.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +166.39559432734697 9.976439066337804 236.75362934444058 1 1 +352.1156357053931 43.82007387041961 14.074783631236542 1 2 +77.82610341510008 43.397849654402556 273.4002228089796 1 3 +346.395594327347 9.976439066337804 56.75362934444064 1 4 +172.11563570539317 43.82007387041961 194.07478363123653 1 5 +257.8261034151001 43.39784965440255 93.40022280897969 1 6 +193.604405672653 9.976439066337804 123.24637065555939 1 7 +7.884364294606862 43.82007387041961 345.9252163687635 1 8 +282.17389658489986 43.39784965440254 86.59977719102032 1 9 +13.604405672652977 9.976439066337804 303.24637065555936 1 10 +187.88436429460683 43.82007387041961 165.92521636876344 1 11 +102.17389658489992 43.39784965440254 266.59977719102034 1 12 +277.8843642946069 43.82007387041961 75.92521636876346 1 13 +103.604405672653 9.976439066337804 213.24637065555936 1 14 +192.17389658489986 43.397849654402556 176.59977719102034 1 15 +97.88436429460687 43.82007387041961 255.92521636876344 1 16 +283.60440567265294 9.976439066337804 33.24637065555936 1 17 +12.173896584899929 43.39784965440254 356.59977719102034 1 18 +82.11563570539313 43.82007387041961 284.0747836312365 1 19 +256.395594327347 9.976439066337804 146.75362934444064 1 20 +167.8261034151001 43.397849654402556 183.40022280897963 1 21 +262.1156357053931 43.82007387041961 104.07478363123654 1 22 +76.39559432734703 9.976439066337806 326.75362934444064 1 23 +347.8261034151001 43.39784965440255 3.400222808979685 1 24 diff --git a/python/tests/reference/Rotation/fcc_KS.txt b/python/tests/reference/Rotation/fcc_KS.txt new file mode 100644 index 000000000..93fdcf07e --- /dev/null +++ b/python/tests/reference/Rotation/fcc_KS.txt @@ -0,0 +1,26 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +114.20342833932975 10.52877936550932 204.20342833932972 1 1 +94.3573968784815 80.40593177313954 311.22729452432543 1 2 +175.6426031215185 80.40593177313954 48.77270547567447 1 3 +155.79657166067025 10.52877936550932 155.79657166067025 1 4 +99.62136089109411 85.70366403943004 318.04510841542015 1 5 +170.37863910890587 85.70366403943002 41.954891584579855 1 6 +85.64260312151852 80.40593177313954 48.77270547567448 1 7 +65.79657166067024 10.52877936550932 155.79657166067025 1 8 +9.621360891094124 85.70366403943004 318.04510841542015 1 9 +80.37863910890587 85.70366403943004 41.95489158457987 1 10 +24.203428339329758 10.52877936550932 204.20342833932975 1 11 +4.357396878481486 80.40593177313954 311.2272945243255 1 12 +204.20342833932972 10.52877936550932 204.20342833932972 1 13 +184.35739687848147 80.40593177313954 311.2272945243255 1 14 +265.64260312151845 80.40593177313953 48.77270547567449 1 15 +245.79657166067025 10.528779365509317 155.79657166067025 1 16 +189.62136089109413 85.70366403943004 318.04510841542015 1 17 +260.3786391089059 85.70366403943002 41.954891584579855 1 18 +170.37863910890587 94.29633596056996 138.04510841542015 1 19 +99.62136089109411 94.29633596056998 221.95489158457983 1 20 +155.79657166067025 169.4712206344907 24.203428339329754 1 21 +175.64260312151848 99.59406822686046 131.22729452432552 1 22 +94.35739687848151 99.59406822686046 228.77270547567446 1 23 +114.20342833932975 169.4712206344907 335.7965716606702 1 24 diff --git a/python/tests/reference/Rotation/fcc_NW.txt b/python/tests/reference/Rotation/fcc_NW.txt new file mode 100644 index 000000000..cc9c95a05 --- /dev/null +++ b/python/tests/reference/Rotation/fcc_NW.txt @@ -0,0 +1,14 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +96.91733794010702 83.13253115922213 314.5844440567886 1 1 +173.082662059893 83.13253115922211 45.41555594321143 1 2 +135.0 9.735610317245317 180.0 1 3 +263.082662059893 83.13253115922213 45.415555943211444 1 4 +186.91733794010702 83.13253115922211 314.5844440567886 1 5 +224.99999999999997 9.735610317245317 180.0 1 6 +83.082662059893 83.13253115922213 45.415555943211444 1 7 +6.917337940106983 83.13253115922211 314.5844440567886 1 8 +45.0 9.73561031724532 180.0 1 9 +13.638707279476469 45.81931182053557 80.40196970123216 1 10 +256.36129272052347 45.81931182053556 279.59803029876775 1 11 +315.0 99.73561031724536 0.0 1 12 diff --git a/python/tests/reference/Rotation/fcc_Pitsch.txt b/python/tests/reference/Rotation/fcc_Pitsch.txt new file mode 100644 index 000000000..aa0c32365 --- /dev/null +++ b/python/tests/reference/Rotation/fcc_Pitsch.txt @@ -0,0 +1,14 @@ +1 header +1_Eulers 2_Eulers 3_Eulers 1_pos 2_pos +135.41555594321144 83.13253115922213 173.082662059893 1 1 +260.26438968275465 90.0 135.0 1 2 +260.40196970123213 45.81931182053557 13.638707279476478 1 3 +314.5844440567886 83.13253115922213 96.91733794010702 1 4 +350.40196970123213 45.81931182053557 283.6387072794765 1 5 +170.26438968275465 90.0 224.99999999999997 1 6 +315.4155559432114 83.13253115922213 353.08266205989304 1 7 +99.73561031724536 90.0 225.0 1 8 +279.59803029876787 45.819311820535574 166.36129272052352 1 9 +134.58444405678856 83.13253115922213 276.91733794010696 1 10 +9.598030298767851 45.819311820535574 76.36129272052355 1 11 +9.735610317245369 90.0 315.0 1 12 diff --git a/python/tests/reference/Table/simple.ang b/python/tests/reference/Table/simple.ang new file mode 100644 index 000000000..8e009e2dc --- /dev/null +++ b/python/tests/reference/Table/simple.ang @@ -0,0 +1,138 @@ +# TEM_PIXperUM 1.000000 +# x-star 240.000000 +# y-star 240.000000 +# z-star 240.000000 +# WorkingDistance 20.000000 +# +# Phase 1 +# MaterialName Iron(Alpha) +# Formula +# Info +# Symmetry 43 +# LatticeConstants 2.870 2.870 2.870 90.000 90.000 90.000 +# NumberFamilies 100 +# hklFamilies 9223440 0 2 32763 0.000000 32763 +# hklFamilies 0 0 0 9218712 0.000000 9218712 +# hklFamilies 0 0 3801155 0 0.000000 0 +# hklFamilies 5570652 6619251 7536754 -1203738484 0.000000 -1203738484 +# hklFamilies 7143516 5111900 7864421 32763 0.000000 32763 +# hklFamilies 6488180 7274604 6553717 9220480 0.000000 9220480 +# hklFamilies 3145820 2949169 3145777 0 0.000000 0 +# hklFamilies 3014704 7209057 103 9220488 0.000000 9220488 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9220032 0.000000 9220032 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 -1203728363 0.000000 -1203728363 +# hklFamilies 0 0 0 32763 0.000000 32763 +# hklFamilies 0 0 0 9218628 0.000000 9218628 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9218504 0.000000 9218504 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9219904 0.000000 9219904 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 0 -0.000046 0 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 256 0.000000 256 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 -1203753636 0.000000 -1203753636 +# hklFamilies 0 0 0 32763 0.000000 32763 +# hklFamilies 0 0 0 9220576 0.000000 9220576 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9218736 0.000000 9218736 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 103219574 0.000000 103219574 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9220576 0.000000 9220576 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9220692 0.000000 9220692 +# hklFamilies 1434293657 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9218584 0.000000 9218584 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 9219976 0.000000 9219976 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 0 0 256 0.000000 256 +# hklFamilies 0 0 69473872 0 0.000000 0 +# hklFamilies 0 1889785611 -1546188227 -1203753636 -0.000046 -1203753636 +# hklFamilies 9224144 0 1434294456 32763 0.000000 32763 +# hklFamilies 0 9224160 0 9220672 0.000000 9220672 +# hklFamilies -1168390977 32763 851982 0 0.000000 0 +# hklFamilies 0 304 0 9218816 0.000000 9218816 +# hklFamilies 27030208 0 1434297593 0 0.000000 0 +# hklFamilies 0 9224160 0 101654020 0.000000 101654020 +# hklFamilies 9224064 0 0 0 0.000000 0 +# hklFamilies 0 25563456 0 9220672 0.000000 9220672 +# hklFamilies 9224544 0 25559040 0 0.000000 0 +# hklFamilies 0 25559788 0 9220788 0.000000 9220788 +# hklFamilies 176 0 304 24 0.000000 24 +# hklFamilies 0 25562304 0 4 0.000000 4 +# hklFamilies 9224208 0 0 0 0.000000 0 +# hklFamilies 0 281 0 9220032 0.000000 9220032 +# hklFamilies 0 0 0 0 0.000000 0 +# hklFamilies 0 -1168390977 32763 9220660 0.000000 9220660 +# hklFamilies 21 0 -1168390977 8 0.000000 8 +# hklFamilies 32763 2490388 0 24 0.000000 24 +# hklFamilies 48 0 69650048 25 0.000000 25 +# hklFamilies 0 -1216995621 32763 65535 -0.000046 65535 +# hklFamilies 0 0 25562688 1 0.000000 1 +# hklFamilies 0 0 21776 0 -0.000058 0 +# hklFamilies 25562688 0 25559724 0 0.000000 0 +# hklFamilies 0 25559040 0 1179652 0.000000 1179652 +# hklFamilies 25559724 0 25562304 32763 0.000000 32763 +# hklFamilies 0 48 0 9219904 0.000000 9219904 +# hklFamilies 25562304 0 28 0 0.000000 0 +# hklFamilies 0 0 0 8781958 0.000000 8781958 +# hklFamilies 31 0 0 0 0.000000 0 +# hklFamilies 0 0 0 103304392 0.000000 103304392 +# hklFamilies 3 0 48 0 0.000000 0 +# hklFamilies 0 9224505 0 103219694 -0.000046 103219694 +# hklFamilies 27000832 0 -1168393705 0 0.000000 0 +# hklFamilies 32763 25559040 0 9220192 0.000000 9220192 +# hklFamilies 0 32763 31 0 0.000000 0 +# hklFamilies 0 0 0 9219872 0.000000 9219872 +# hklFamilies 69729712 0 9224640 0 0.000000 0 +# hklFamilies 0 69729904 0 1397706823 0.000000 1397706823 +# hklFamilies 69911504 0 0 59 0.000000 59 +# hklFamilies 0 27007968 0 103219200 0.000000 103219200 +# hklFamilies 0 0 -1216843775 0 0.000000 0 +# hklFamilies 32763 69911504 0 0 0.000000 0 +# hklFamilies -1168296496 32763 9225328 0 0.000000 0 +# hklFamilies 0 1434343267 0 9632160 0.000000 9632160 +# hklFamilies 69908840 0 -1216995621 0 0.000000 0 +# hklFamilies 32763 256 0 9632112 0.000000 9632112 +# hklFamilies 0 0 399376220 0 0.000000 0 +# hklFamilies 21776 1966087 4456474 262148 0.000000 262148 +# hklFamilies 9224704 0 1434198234 0 0.000000 0 +# hklFamilies 0 0 0 9704044 0.000000 9704044 +# hklFamilies -1168373699 32763 1 0 0.000000 0 +# hklFamilies 0 69911504 0 94961568 -0.000046 94961568 +# hklFamilies 1 0 69911504 0 0.000000 0 +# hklFamilies 0 10 0 9220016 0.000000 9220016 +# hklFamilies -1 0 27030208 0 0.000000 0 +# hklFamilies 0 1434488087 18 9219992 -0.000046 9219992 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# ElasticConstants 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# Categories1 1 1 1 1 +# +# GRID: SqrGrid +# XSTEP: 0.050000 +# YSTEP: 0.050000 +# NCOLS_ODD: 2 +# NCOLS_EVEN: 2 +# NROWS: 2 +# +# OPERATOR: +# +# SAMPLEID: +# +# SCANID: +# +0.0 0.0 0.0 0.00 0.00 60.0 20.0 1 2.0 1.5 +0.0 2.0 0.0 0.05 0.00 60.0 20.0 1 2.0 1.5 +0.0 2.0 0.0 0.00 0.05 60.0 20.0 1 2.0 1.5 +0.0 0.0 1.0 0.05 0.05 60.0 20.0 1 2.0 1.5 diff --git a/python/tests/test_Rotation.py b/python/tests/test_Rotation.py index 72956c013..08d543554 100644 --- a/python/tests/test_Rotation.py +++ b/python/tests/test_Rotation.py @@ -1,7 +1,11 @@ +import os + import pytest import numpy as np +import damask from damask import Rotation +from damask import Orientation n = 1000 @@ -10,6 +14,11 @@ def default(): """A set of n random rotations.""" return [Rotation.fromRandom() for r in range(n)] +@pytest.fixture +def reference_dir(reference_dir_base): + """Directory containing reference results.""" + return os.path.join(reference_dir_base,'Rotation') + class TestRotation: @@ -18,38 +27,55 @@ class TestRotation: assert np.allclose(rot.asQuaternion(), Rotation.fromEulers(rot.asEulers()).asQuaternion()) - def test_AxisAngle(self,default): for rot in default: assert np.allclose(rot.asEulers(), Rotation.fromAxisAngle(rot.asAxisAngle()).asEulers()) - def test_Matrix(self,default): for rot in default: assert np.allclose(rot.asAxisAngle(), Rotation.fromMatrix(rot.asMatrix()).asAxisAngle()) - def test_Rodriques(self,default): for rot in default: assert np.allclose(rot.asMatrix(), Rotation.fromRodrigues(rot.asRodrigues()).asMatrix()) - def test_Homochoric(self,default): for rot in default: assert np.allclose(rot.asRodrigues(), Rotation.fromHomochoric(rot.asHomochoric()).asRodrigues()) - def test_Cubochoric(self,default): for rot in default: assert np.allclose(rot.asHomochoric(), Rotation.fromCubochoric(rot.asCubochoric()).asHomochoric()) - def test_Quaternion(self,default): for rot in default: assert np.allclose(rot.asCubochoric(), Rotation.fromQuaternion(rot.asQuaternion()).asCubochoric()) + + + @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch']) + @pytest.mark.parametrize('lattice',['fcc','bcc']) + def test_relationship_forward_backward(self,model,lattice): + ori = Orientation(Rotation.fromRandom(),lattice) + for i,r in enumerate(ori.relatedOrientations(model)): + ori2 = r.relatedOrientations(model)[i] + misorientation = ori.rotation.misorientation(ori2.rotation) + assert misorientation.asAxisAngle(degrees=True)[3]<1.0e-5 + + @pytest.mark.parametrize('model',['Bain','KS','GT','GT_prime','NW','Pitsch']) + @pytest.mark.parametrize('lattice',['fcc','bcc']) + def test_relationship_reference(self,update,reference_dir,model,lattice): + reference = os.path.join(reference_dir,'{}_{}.txt'.format(lattice,model)) + ori = Orientation(Rotation(),lattice) + eu = np.array([o.rotation.asEulers(degrees=True) for o in ori.relatedOrientations(model)]) + if update: + coords = np.array([(1,i+1) for i,x in enumerate(eu)]) + table = damask.Table(eu,{'Eulers':(3,)}) + table.add('pos',coords) + table.to_ASCII(reference) + assert np.allclose(eu,damask.Table.from_ASCII(reference).get('Eulers')) diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index a0dc31975..818a55f40 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -47,6 +47,17 @@ class TestTable: new = Table.from_ASCII(f) assert all(default.data==new.data) + def test_read_ang_str(self,reference_dir): + new = Table.from_ang(os.path.join(reference_dir,'simple.ang')) + assert new.data.shape == (4,10) and \ + new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit'] + + def test_read_ang_file(self,reference_dir): + f = open(os.path.join(reference_dir,'simple.ang')) + new = Table.from_ang(f) + assert new.data.shape == (4,10) and \ + new.labels == ['eu', 'pos', 'IQ', 'CI', 'ID', 'intensity', 'fit'] + @pytest.mark.parametrize('fname',['datatype-mix.txt','whitespace-mix.txt']) def test_read_strange(self,reference_dir,fname): with open(os.path.join(reference_dir,fname)) as f: @@ -65,11 +76,13 @@ class TestTable: default.add('nine',d,'random data') assert np.allclose(d,default.get('nine')) - def test_rename_equivalent(self,default): - v = default.get('v') - default.rename('v','u') - u = default.get('u') - assert np.all(v == u) + def test_rename_equivalent(self): + x = np.random.random((5,13)) + t = Table(x,{'F':(3,3),'v':(3,),'s':(1,)},['random test data']) + s = t.get('s') + t.rename('s','u') + u = t.get('u') + assert np.all(s == u) def test_rename_gone(self,default): default.rename('v','V') diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py new file mode 100644 index 000000000..fdddaf3a1 --- /dev/null +++ b/python/tests/test_grid_filters.py @@ -0,0 +1,79 @@ +import pytest +import numpy as np + +from damask import grid_filters + +class TestGridFilters: + + def test_cell_coord0(self): + size = np.random.random(3) + grid = np.random.randint(8,32,(3)) + coord = grid_filters.cell_coord0(grid,size) + assert np.allclose(coord[0,0,0],size/grid*.5) and coord.shape == tuple(grid[::-1]) + (3,) + + def test_node_coord0(self): + size = np.random.random(3) + grid = np.random.randint(8,32,(3)) + coord = grid_filters.node_coord0(grid,size) + assert np.allclose(coord[-1,-1,-1],size) and coord.shape == tuple(grid[::-1]+1) + (3,) + + def test_coord0(self): + size = np.random.random(3) + grid = np.random.randint(8,32,(3)) + c = grid_filters.cell_coord0(grid+1,size+size/grid) + n = grid_filters.node_coord0(grid,size) + size/grid*.5 + assert np.allclose(c,n) + + @pytest.mark.parametrize('mode',[('cell'),('node')]) + def test_grid_DNA(self,mode): + """Ensure that xx_coord0_2_DNA is the inverse of xx_coord0.""" + grid = np.random.randint(8,32,(3)) + size = np.random.random(3) + origin = np.random.random(3) + coord0 = eval('grid_filters.{}_coord0(grid,size,origin)'.format(mode)) # noqa + _grid,_size,_origin = eval('grid_filters.{}_coord0_2_DNA(coord0.reshape((-1,3)))'.format(mode)) + assert np.allclose(grid,_grid) and np.allclose(size,_size) and np.allclose(origin,_origin) + + def test_displacement_fluct_equivalence(self): + """Ensure that fluctuations are periodic.""" + size = np.random.random(3) + grid = np.random.randint(8,32,(3)) + F = np.random.random(tuple(grid)+(3,3)) + assert np.allclose(grid_filters.node_displacement_fluct(size,F), + grid_filters.cell_2_node(grid_filters.cell_displacement_fluct(size,F))) + + def test_interpolation_nonperiodic(self): + size = np.random.random(3) + grid = np.random.randint(8,32,(3)) + F = np.random.random(tuple(grid)+(3,3)) + assert np.allclose(grid_filters.node_coord(size,F) [1:-1,1:-1,1:-1],grid_filters.cell_2_node( + grid_filters.cell_coord(size,F))[1:-1,1:-1,1:-1]) + + @pytest.mark.parametrize('mode',[('cell'),('node')]) + def test_coord0_origin(self,mode): + origin= np.random.random(3) + size = np.random.random(3) # noqa + grid = np.random.randint(8,32,(3)) + shifted = eval('grid_filters.{}_coord0(grid,size,origin)'.format(mode)) + unshifted = eval('grid_filters.{}_coord0(grid,size)'.format(mode)) + if mode == 'cell': + assert np.allclose(shifted,unshifted+np.broadcast_to(origin,tuple(grid[::-1]) +(3,))) + elif mode == 'node': + assert np.allclose(shifted,unshifted+np.broadcast_to(origin,tuple(grid[::-1]+1)+(3,))) + + @pytest.mark.parametrize('mode',[('cell'),('node')]) + def test_displacement_avg_vanishes(self,mode): + """Ensure that random fluctuations in F do not result in average displacement.""" + size = np.random.random(3) # noqa + grid = np.random.randint(8,32,(3)) + F = np.random.random(tuple(grid)+(3,3)) + F += np.eye(3) - np.average(F,axis=(0,1,2)) + assert np.allclose(eval('grid_filters.{}_displacement_avg(size,F)'.format(mode)),0.0) + + @pytest.mark.parametrize('mode',[('cell'),('node')]) + def test_displacement_fluct_vanishes(self,mode): + """Ensure that constant F does not result in fluctuating displacement.""" + size = np.random.random(3) # noqa + grid = np.random.randint(8,32,(3)) + F = np.broadcast_to(np.random.random((3,3)), tuple(grid)+(3,3)) # noqa + assert np.allclose(eval('grid_filters.{}_displacement_fluct(size,F)'.format(mode)),0.0) diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index 9bf8c547c..3a7f35633 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -87,10 +87,8 @@ subroutine CPFEM_initAll(el,ip) call math_init call rotations_init call FE_init -#ifdef DAMASK_HDF5 call HDF5_utilities_init call results_init -#endif call mesh_init(ip, el) call lattice_init call material_init @@ -374,7 +372,6 @@ subroutine CPFEM_results(inc,time) integer(pInt), intent(in) :: inc real(pReal), intent(in) :: time -#ifdef DAMASK_HDF5 call results_openJobFile call results_addIncrement(inc,time) call constitutive_results @@ -382,7 +379,6 @@ subroutine CPFEM_results(inc,time) call homogenization_results call results_removeLink('current') ! ToDo: put this into closeJobFile call results_closeJobFile -#endif end subroutine CPFEM_results diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 9edb61d33..52b96cf70 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -14,10 +14,10 @@ module CPFEM2 use material use lattice use IO - use HDF5 use DAMASK_interface use results use discretization + use HDF5 use HDF5_utilities use homogenization use constitutive @@ -65,7 +65,6 @@ subroutine CPFEM_initAll call constitutive_init call crystallite_init call homogenization_init - call materialpoint_postResults call CPFEM_init end subroutine CPFEM_initAll diff --git a/src/DAMASK_abaqus.f b/src/DAMASK_abaqus.f index e2c56a06e..0f663dde3 100644 --- a/src/DAMASK_abaqus.f +++ b/src/DAMASK_abaqus.f @@ -143,9 +143,6 @@ subroutine UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD,& outdatedByNewInc, & outdatedFFN1, & lastStep - use homogenization, only: & - materialpoint_sizeResults, & - materialpoint_results implicit none integer(pInt), intent(in) :: & @@ -332,7 +329,7 @@ subroutine UMAT(STRESS,STATEV,DDSDDE,SSE,SPD,SCD,& ddsdde(6,:) = ddsdde_h(5,:) end if - statev = materialpoint_results(1:min(nstatv,materialpoint_sizeResults),npt,mesh_FEasCP('elem', noel)) + statev = 0 if (terminallyIll) pnewdt = 0.5_pReal ! force cutback directly ? !$ call omp_set_num_threads(defaultNumThreadsInt) ! reset number of threads to stored default value diff --git a/src/HDF5_utilities.f90 b/src/HDF5_utilities.f90 index e4819431e..02e575d98 100644 --- a/src/HDF5_utilities.f90 +++ b/src/HDF5_utilities.f90 @@ -5,9 +5,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !-------------------------------------------------------------------------------------------------- module HDF5_utilities -#if defined(PETSc) || defined(DAMASK_HDF5) use HDF5 -#endif #ifdef PETSc use PETSC #endif @@ -20,7 +18,6 @@ module HDF5_utilities implicit none public -#if defined(PETSc) || defined(DAMASK_HDF5) !-------------------------------------------------------------------------------------------------- !> @brief reads integer or float data of defined shape from file ! ToDo: order of arguments wrong !> @details for parallel IO, all dimension except for the last need to match @@ -279,8 +276,8 @@ logical function HDF5_objectExists(loc_id,path) integer(HID_T), intent(in) :: loc_id character(len=*), intent(in), optional :: path - integer :: hdferr - character(len=256) :: p + integer :: hdferr + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -308,10 +305,10 @@ subroutine HDF5_addAttribute_str(loc_id,attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel, attrValue character(len=*), intent(in), optional :: path - integer :: hdferr - integer(HID_T) :: attr_id, space_id, type_id - logical :: attrExists - character(len=256) :: p + integer :: hdferr + integer(HID_T) :: attr_id, space_id, type_id + logical :: attrExists + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -355,10 +352,10 @@ subroutine HDF5_addAttribute_int(loc_id,attrLabel,attrValue,path) integer, intent(in) :: attrValue character(len=*), intent(in), optional :: path - integer :: hdferr - integer(HID_T) :: attr_id, space_id - logical :: attrExists - character(len=256) :: p + integer :: hdferr + integer(HID_T) :: attr_id, space_id + logical :: attrExists + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -396,10 +393,10 @@ subroutine HDF5_addAttribute_real(loc_id,attrLabel,attrValue,path) real(pReal), intent(in) :: attrValue character(len=*), intent(in), optional :: path - integer :: hdferr - integer(HID_T) :: attr_id, space_id - logical :: attrExists - character(len=256) :: p + integer :: hdferr + integer(HID_T) :: attr_id, space_id + logical :: attrExists + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -441,7 +438,7 @@ subroutine HDF5_addAttribute_int_array(loc_id,attrLabel,attrValue,path) integer(HID_T) :: attr_id, space_id integer(HSIZE_T),dimension(1) :: array_size logical :: attrExists - character(len=256) :: p + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -485,7 +482,7 @@ subroutine HDF5_addAttribute_real_array(loc_id,attrLabel,attrValue,path) integer(HID_T) :: attr_id, space_id integer(HSIZE_T),dimension(1) :: array_size logical :: attrExists - character(len=256) :: p + character(len=pStringLen) :: p if (present(path)) then p = trim(path) @@ -1928,6 +1925,5 @@ subroutine finalize_write(plist_id, dset_id, filespace_id, memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='finalize_write: h5sclose_f/memspace_id') end subroutine finalize_write -#endif end module HDF5_Utilities diff --git a/src/IO.f90 b/src/IO.f90 index 8973860c2..8926e1e21 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -11,9 +11,9 @@ module IO implicit none private - character(len=5), parameter, public :: & + character(len=*), parameter, public :: & IO_EOF = '#EOF#' !< end of file string - character(len=207), parameter, private :: & + character(len=*), parameter, private :: & IO_DIVIDER = '───────────────────'//& '───────────────────'//& '───────────────────'//& @@ -32,8 +32,7 @@ module IO IO_intValue, & IO_lc, & IO_error, & - IO_warning, & - IO_intOut + IO_warning #if defined(Marc4DAMASK) || defined(Abaqus) public :: & IO_open_inputFile, & @@ -244,12 +243,12 @@ subroutine IO_open_inputFile(fileUnit) integer, allocatable, dimension(:) :: chunkPos - character(len=65536) :: line,fname + character(len=pStringLen :: line,fname logical :: createSuccess,fexist do - read(unit2,'(A65536)',END=220) line + read(unit2,'(A256)',END=220) line chunkPos = IO_stringPos(line) if (IO_lc(IO_StringValue(line,chunkPos,1))=='*include') then @@ -402,7 +401,7 @@ function IO_stringValue(string,chunkPos,myChunk,silent) character(len=:), allocatable :: IO_stringValue logical, optional,intent(in) :: silent !< switch to trigger verbosity - character(len=16), parameter :: MYNAME = 'IO_stringValue: ' + character(len=*), parameter :: MYNAME = 'IO_stringValue: ' logical :: warn @@ -430,8 +429,8 @@ real(pReal) function IO_floatValue (string,chunkPos,myChunk) integer, dimension(:), intent(in) :: chunkPos !< positions of start and end of each tag/chunk in given string integer, intent(in) :: myChunk !< position number of desired chunk character(len=*), intent(in) :: string !< raw input with known start and end of each chunk - character(len=15), parameter :: MYNAME = 'IO_floatValue: ' - character(len=17), parameter :: VALIDCHARACTERS = '0123456789eEdD.+-' + character(len=*), parameter :: MYNAME = 'IO_floatValue: ' + character(len=*), parameter :: VALIDCHARACTERS = '0123456789eEdD.+-' IO_floatValue = 0.0_pReal @@ -454,8 +453,8 @@ integer function IO_intValue(string,chunkPos,myChunk) character(len=*), intent(in) :: string !< raw input with known start and end of each chunk integer, intent(in) :: myChunk !< position number of desired chunk integer, dimension(:), intent(in) :: chunkPos !< positions of start and end of each tag/chunk in given string - character(len=13), parameter :: MYNAME = 'IO_intValue: ' - character(len=12), parameter :: VALIDCHARACTERS = '0123456789+-' + character(len=*), parameter :: MYNAME = 'IO_intValue: ' + character(len=*), parameter :: VALIDCHARACTERS = '0123456789+-' IO_intValue = 0 @@ -478,9 +477,9 @@ real(pReal) function IO_fixedNoEFloatValue (string,ends,myChunk) character(len=*), intent(in) :: string !< raw input with known ends of each chunk integer, intent(in) :: myChunk !< position number of desired chunk integer, dimension(:), intent(in) :: ends !< positions of end of each tag/chunk in given string - character(len=22), parameter :: MYNAME = 'IO_fixedNoEFloatValue ' - character(len=13), parameter :: VALIDBASE = '0123456789.+-' - character(len=12), parameter :: VALIDEXP = '0123456789+-' + character(len=*), parameter :: MYNAME = 'IO_fixedNoEFloatValue ' + character(len=*), parameter :: VALIDBASE = '0123456789.+-' + character(len=*), parameter :: VALIDEXP = '0123456789+-' real(pReal) :: base integer :: expon @@ -510,8 +509,8 @@ integer function IO_fixedIntValue(string,ends,myChunk) character(len=*), intent(in) :: string !< raw input with known ends of each chunk integer, intent(in) :: myChunk !< position number of desired chunk integer, dimension(:), intent(in) :: ends !< positions of end of each tag/chunk in given string - character(len=20), parameter :: MYNAME = 'IO_fixedIntValue: ' - character(len=12), parameter :: VALIDCHARACTERS = '0123456789+-' + character(len=*), parameter :: MYNAME = 'IO_fixedIntValue: ' + character(len=*), parameter :: VALIDCHARACTERS = '0123456789+-' IO_fixedIntValue = IO_verifyIntValue(trim(adjustl(string(ends(myChunk)+1:ends(myChunk+1)))),& VALIDCHARACTERS,MYNAME) @@ -542,26 +541,6 @@ pure function IO_lc(string) end function IO_lc -!-------------------------------------------------------------------------------------------------- -!> @brief returns format string for integer values without leading zeros -!> @details deprecated, use '(i0)' format specifier -!-------------------------------------------------------------------------------------------------- -pure function IO_intOut(intToPrint) - - integer, intent(in) :: intToPrint - character(len=41) :: IO_intOut - integer :: N_digits - character(len=19) :: width ! maximum digits for 64 bit integer - character(len=20) :: min_width ! longer for negative values - - N_digits = 1 + int(log10(real(max(abs(intToPrint),1)))) - write(width, '(I19.19)') N_digits - write(min_width, '(I20.20)') N_digits + merge(1,0,intToPrint < 0) - IO_intOut = 'I'//trim(min_width)//'.'//trim(width) - -end function IO_intOut - - !-------------------------------------------------------------------------------------------------- !> @brief write error statements to standard out and terminate the Marc/spectral run with exit #9xxx !> in ABAQUS either time step is reduced or execution terminated @@ -905,7 +884,7 @@ end subroutine IO_warning !-------------------------------------------------------------------------------------------------- function IO_read(fileUnit) result(line) - integer, intent(in) :: fileUnit !< file unit + integer, intent(in) :: fileUnit !< file unit character(len=pStringLen) :: line @@ -945,7 +924,7 @@ integer function IO_countDataLines(fileUnit) integer, allocatable, dimension(:) :: chunkPos - character(len=65536) :: line, & + character(len=pStringLen) :: line, & tmp IO_countDataLines = 0 @@ -977,7 +956,7 @@ integer function IO_countNumericalDataLines(fileUnit) integer, allocatable, dimension(:) :: chunkPos - character(len=65536) :: line, & + character(len=pStringLen) :: line, & tmp IO_countNumericalDataLines = 0 @@ -1012,7 +991,7 @@ integer function IO_countContinuousIntValues(fileUnit) integer :: l,c #endif integer, allocatable, dimension(:) :: chunkPos - character(len=65536) :: line + character(len=pStringLen) :: line IO_countContinuousIntValues = 0 line = '' @@ -1069,21 +1048,21 @@ function IO_continuousIntValues(fileUnit,maxN,lookupName,lookupMap,lookupMaxN) integer, intent(in) :: fileUnit, & lookupMaxN integer, dimension(:,:), intent(in) :: lookupMap - character(len=64), dimension(:), intent(in) :: lookupName + character(len=*), dimension(:), intent(in) :: lookupName integer :: i,first,last #ifdef Abaqus integer :: j,l,c #endif integer, allocatable, dimension(:) :: chunkPos - character(len=65536) line - logical rangeGeneration + character(len=pStringLen) :: line + logical :: rangeGeneration IO_continuousIntValues = 0 rangeGeneration = .false. #if defined(Marc4DAMASK) do - read(fileUnit,'(A65536)',end=100) line + read(fileUnit,'(A256)',end=100) line chunkPos = IO_stringPos(line) if (chunkPos(1) < 1) then ! empty line exit @@ -1124,14 +1103,14 @@ function IO_continuousIntValues(fileUnit,maxN,lookupName,lookupMap,lookupMaxN) !-------------------------------------------------------------------------------------------------- ! check if the element values in the elset are auto generated backspace(fileUnit) - read(fileUnit,'(A65536)',end=100) line + read(fileUnit,'(A256)',end=100) line chunkPos = IO_stringPos(line) do i = 1,chunkPos(1) if (IO_lc(IO_stringValue(line,chunkPos,i)) == 'generate') rangeGeneration = .true. enddo do l = 1,c - read(fileUnit,'(A65536)',end=100) line + read(fileUnit,'(A256)',end=100) line chunkPos = IO_stringPos(line) if (verify(IO_stringValue(line,chunkPos,1),'0123456789') > 0) then ! a non-int, i.e. set names follow on this line do i = 1,chunkPos(1) ! loop over set names in line diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 4067c026a..977c80337 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -37,7 +37,6 @@ module constitutive integer, public, protected :: & constitutive_plasticity_maxSizeDotState, & - constitutive_source_maxSizePostResults, & constitutive_source_maxSizeDotState public :: & @@ -50,7 +49,6 @@ module constitutive constitutive_SandItsTangents, & constitutive_collectDotState, & constitutive_collectDeltaState, & - constitutive_postResults, & constitutive_results contains @@ -61,17 +59,9 @@ contains !-------------------------------------------------------------------------------------------------- subroutine constitutive_init - integer, parameter :: FILEUNIT = 204 integer :: & - o, & !< counter in output loop ph, & !< counter in phase loop - s, & !< counter in source loop - ins !< instance of plasticity/source - - integer, dimension(:,:), pointer :: thisSize - character(len=64), dimension(:,:), pointer :: thisOutput - character(len=32) :: outputName !< name of output, intermediate fix until HDF5 output is ready - logical :: knownSource + s !< counter in source loop !-------------------------------------------------------------------------------------------------- ! initialized plasticity @@ -101,58 +91,10 @@ subroutine constitutive_init if (any(phase_kinematics == KINEMATICS_slipplane_opening_ID)) call kinematics_slipplane_opening_init if (any(phase_kinematics == KINEMATICS_thermal_expansion_ID)) call kinematics_thermal_expansion_init - write(6,'(/,a)') ' <<<+- constitutive init -+>>>' - - mainProcess: if (worldrank == 0) then -!-------------------------------------------------------------------------------------------------- -! write description file for constitutive output - call IO_write_jobFile(FILEUNIT,'outputConstitutive') - PhaseLoop: do ph = 1,material_Nphase - activePhase: if (any(material_phaseAt == ph)) then - write(FILEUNIT,'(/,a,/)') '['//trim(config_name_phase(ph))//']' - - SourceLoop: do s = 1, phase_Nsources(ph) - knownSource = .true. ! assume valid - sourceType: select case (phase_source(s,ph)) - case (SOURCE_damage_isoBrittle_ID) sourceType - ins = source_damage_isoBrittle_instance(ph) - outputName = SOURCE_damage_isoBrittle_label - thisOutput => source_damage_isoBrittle_output - thisSize => source_damage_isoBrittle_sizePostResult - case (SOURCE_damage_isoDuctile_ID) sourceType - ins = source_damage_isoDuctile_instance(ph) - outputName = SOURCE_damage_isoDuctile_label - thisOutput => source_damage_isoDuctile_output - thisSize => source_damage_isoDuctile_sizePostResult - case (SOURCE_damage_anisoBrittle_ID) sourceType - ins = source_damage_anisoBrittle_instance(ph) - outputName = SOURCE_damage_anisoBrittle_label - thisOutput => source_damage_anisoBrittle_output - thisSize => source_damage_anisoBrittle_sizePostResult - case (SOURCE_damage_anisoDuctile_ID) sourceType - ins = source_damage_anisoDuctile_instance(ph) - outputName = SOURCE_damage_anisoDuctile_label - thisOutput => source_damage_anisoDuctile_output - thisSize => source_damage_anisoDuctile_sizePostResult - case default sourceType - knownSource = .false. - end select sourceType - if (knownSource) then - write(FILEUNIT,'(a)') '(source)'//char(9)//trim(outputName) - OutputSourceLoop: do o = 1,size(thisOutput(:,ins)) - if(len_trim(thisOutput(o,ins)) > 0) & - write(FILEUNIT,'(a,i4)') trim(thisOutput(o,ins))//char(9),thisSize(o,ins) - enddo OutputSourceLoop - endif - enddo SourceLoop - endif activePhase - enddo PhaseLoop - close(FILEUNIT) - endif mainProcess + write(6,'(/,a)') ' <<<+- constitutive init -+>>>'; flush(6) constitutive_plasticity_maxSizeDotState = 0 constitutive_source_maxSizeDotState = 0 - constitutive_source_maxSizePostResults = 0 PhaseLoop2:do ph = 1,material_Nphase !-------------------------------------------------------------------------------------------------- @@ -169,11 +111,8 @@ subroutine constitutive_init plasticState(ph)%sizeDotState) constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & maxval(sourceState(ph)%p(:)%sizeDotState)) - constitutive_source_maxSizePostResults = max(constitutive_source_maxSizePostResults, & - maxval(sourceState(ph)%p(:)%sizePostResults)) enddo PhaseLoop2 - end subroutine constitutive_init @@ -639,58 +578,13 @@ subroutine constitutive_collectDeltaState(S, Fe, Fi, ipc, ip, el) end subroutine constitutive_collectDeltaState -!-------------------------------------------------------------------------------------------------- -!> @brief returns array of constitutive results -!-------------------------------------------------------------------------------------------------- -function constitutive_postResults(S, Fi, ipc, ip, el) - - integer, intent(in) :: & - ipc, & !< component-ID of integration point - ip, & !< integration point - el !< element - real(pReal), dimension(sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & - constitutive_postResults - real(pReal), intent(in), dimension(3,3) :: & - Fi !< intermediate deformation gradient - real(pReal), intent(in), dimension(3,3) :: & - S !< 2nd Piola Kirchhoff stress - integer :: & - startPos, endPos - integer :: & - i, of, instance !< counter in source loop - - constitutive_postResults = 0.0_pReal - - - endPos = 0 - - SourceLoop: do i = 1, phase_Nsources(material_phaseAt(ipc,el)) - startPos = endPos + 1 - endPos = endPos + sourceState(material_phaseAt(ipc,el))%p(i)%sizePostResults - of = material_phasememberAt(ipc,ip,el) - sourceType: select case (phase_source(i,material_phaseAt(ipc,el))) - case (SOURCE_damage_isoBrittle_ID) sourceType - constitutive_postResults(startPos:endPos) = source_damage_isoBrittle_postResults(material_phaseAt(ipc,el),of) - case (SOURCE_damage_isoDuctile_ID) sourceType - constitutive_postResults(startPos:endPos) = source_damage_isoDuctile_postResults(material_phaseAt(ipc,el),of) - case (SOURCE_damage_anisoBrittle_ID) sourceType - constitutive_postResults(startPos:endPos) = source_damage_anisoBrittle_postResults(material_phaseAt(ipc,el),of) - case (SOURCE_damage_anisoDuctile_ID) sourceType - constitutive_postResults(startPos:endPos) = source_damage_anisoDuctile_postResults(material_phaseAt(ipc,el),of) - end select sourceType - - enddo SourceLoop - -end function constitutive_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes constitutive results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine constitutive_results -#if defined(PETSc) || defined(DAMASK_HDF5) + integer :: p - character(len=256) :: group + character(len=pStringLen) :: group do p=1,size(config_name_phase) group = trim('current/constituent')//'/'//trim(config_name_phase(p)) call HDF5_closeGroup(results_addGroup(group)) @@ -719,8 +613,8 @@ subroutine constitutive_results call plastic_nonlocal_results(phase_plasticityInstance(p),group) end select - enddo -#endif + enddo + end subroutine constitutive_results end module constitutive diff --git a/src/crystallite.f90 b/src/crystallite.f90 index 292241001..d33e774e9 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -77,7 +77,7 @@ module crystallite crystallite_localPlasticity !< indicates this grain to have purely local constitutive law type :: tOutput !< new requested output (per phase) - character(len=65536), allocatable, dimension(:) :: & + character(len=pStringLen), allocatable, dimension(:) :: & label end type tOutput type(tOutput), allocatable, dimension(:) :: output_constituent @@ -108,7 +108,6 @@ module crystallite crystallite_stressTangent, & crystallite_orientations, & crystallite_push33ToRef, & - crystallite_postResults, & crystallite_results contains @@ -119,7 +118,6 @@ contains !-------------------------------------------------------------------------------------------------- subroutine crystallite_init - integer, parameter :: FILEUNIT=434 logical, dimension(:,:), allocatable :: devNull integer :: & c, & !< counter in integration point component loop @@ -233,13 +231,6 @@ subroutine crystallite_init #endif enddo -!-------------------------------------------------------------------------------------------------- -! write description file for crystallite output - if (worldrank == 0) then - call IO_write_jobFile(FILEUNIT,'outputCrystallite') - write(FILEUNIT,'(/,a,/)') '[not supported anymore]' - close(FILEUNIT) - endif call config_deallocate('material.config/phase') !-------------------------------------------------------------------------------------------------- @@ -732,42 +723,11 @@ function crystallite_push33ToRef(ipc,ip,el, tensor33) end function crystallite_push33ToRef -!-------------------------------------------------------------------------------------------------- -!> @brief return results of particular grain -!-------------------------------------------------------------------------------------------------- -function crystallite_postResults(ipc, ip, el) - - integer, intent(in):: & - el, & !< element index - ip, & !< integration point index - ipc !< grain index - - real(pReal), dimension(1+ & - 1+sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults)) :: & - crystallite_postResults - integer :: & - c - - - crystallite_postResults = 0.0_pReal - crystallite_postResults(1) = 0.0_pReal ! header-like information (length) - c = 1 - - crystallite_postResults(c+1) = real(sum(sourceState(material_phaseAt(ipc,el))%p(:)%sizePostResults),pReal) ! size of constitutive results - c = c + 1 - if (size(crystallite_postResults)-c > 0) & - crystallite_postResults(c+1:size(crystallite_postResults)) = & - constitutive_postResults(crystallite_S(1:3,1:3,ipc,ip,el), crystallite_Fi(1:3,1:3,ipc,ip,el), & - ipc, ip, el) - -end function crystallite_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes crystallite results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine crystallite_results -#if defined(PETSc) || defined(DAMASK_HDF5) + integer :: p,o real(pReal), allocatable, dimension(:,:,:) :: selected_tensors type(rotation), allocatable, dimension(:) :: selected_rotations @@ -888,7 +848,7 @@ subroutine crystallite_results enddo end function select_rotations -#endif + end subroutine crystallite_results diff --git a/src/damage_local.f90 b/src/damage_local.f90 index 74ad47c9b..6cb45a391 100644 --- a/src/damage_local.f90 +++ b/src/damage_local.f90 @@ -5,22 +5,16 @@ module damage_local use prec use material - use numerics use config + use numerics use source_damage_isoBrittle use source_damage_isoDuctile use source_damage_anisoBrittle use source_damage_anisoDuctile + use results implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - damage_local_sizePostResult - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_local_output - integer, dimension(:), allocatable, target, public :: & - damage_local_Noutput enum, bind(c) enumerator :: & @@ -28,9 +22,6 @@ module damage_local damage_ID end enum - integer(kind(undefined_ID)), dimension(:,:), allocatable :: & - damage_local_outputID !< ID of each post result output - type :: tParameters integer(kind(undefined_ID)), dimension(:), allocatable :: & outputID @@ -42,7 +33,7 @@ module damage_local public :: & damage_local_init, & damage_local_updateState, & - damage_local_postResults + damage_local_Results contains @@ -52,70 +43,41 @@ contains !-------------------------------------------------------------------------------------------------- subroutine damage_local_init - integer :: maxNinstance,homog,instance,i - integer :: sizeState - integer :: NofMyHomog, h - integer(kind(undefined_ID)) :: & - outputID - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - character(len=65536), dimension(:), allocatable :: & - outputs + integer :: maxNinstance,o,NofMyHomog,h + character(len=pStringLen), dimension(:), allocatable :: outputs - write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_local_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_local_label//' init -+>>>'; flush(6) maxNinstance = count(damage_type == DAMAGE_local_ID) if (maxNinstance == 0) return - allocate(damage_local_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0) - allocate(damage_local_output (maxval(homogenization_Noutput),maxNinstance)) - damage_local_output = '' - allocate(damage_local_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) - allocate(damage_local_Noutput (maxNinstance), source=0) - allocate(param(maxNinstance)) do h = 1, size(damage_type) if (damage_type(h) /= DAMAGE_LOCAL_ID) cycle - associate(prm => param(damage_typeInstance(h)), & - config => config_homogenization(h)) + associate(prm => param(damage_typeInstance(h)),config => config_homogenization(h)) - outputs = config%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) - do i=1, size(outputs) - outputID = undefined_ID - select case(outputs(i)) - - case ('damage') - damage_local_output(i,damage_typeInstance(h)) = outputs(i) - damage_local_Noutput(instance) = damage_local_Noutput(instance) + 1 - damage_local_sizePostResult(i,damage_typeInstance(h)) = 1 - prm%outputID = [prm%outputID , damage_ID] - end select - + do o=1, size(outputs) + select case(outputs(o)) + case ('damage') + prm%outputID = [prm%outputID , damage_ID] + end select enddo - - homog = h - - NofMyHomog = count(material_homogenizationAt == homog) - instance = damage_typeInstance(homog) - - -! allocate state arrays - sizeState = 1 - damageState(homog)%sizeState = sizeState - damageState(homog)%sizePostResults = sum(damage_local_sizePostResult(:,instance)) - allocate(damageState(homog)%state0 (sizeState,NofMyHomog), source=damage_initialPhi(homog)) - allocate(damageState(homog)%subState0(sizeState,NofMyHomog), source=damage_initialPhi(homog)) - allocate(damageState(homog)%state (sizeState,NofMyHomog), source=damage_initialPhi(homog)) + NofMyHomog = count(material_homogenizationAt == h) + damageState(h)%sizeState = 1 + allocate(damageState(h)%state0 (1,NofMyHomog), source=damage_initialPhi(h)) + allocate(damageState(h)%subState0(1,NofMyHomog), source=damage_initialPhi(h)) + allocate(damageState(h)%state (1,NofMyHomog), source=damage_initialPhi(h)) - nullify(damageMapping(homog)%p) - damageMapping(homog)%p => mappingHomogenization(1,:,:) - deallocate(damage(homog)%p) - damage(homog)%p => damageState(homog)%state(1,:) - + nullify(damageMapping(h)%p) + damageMapping(h)%p => mappingHomogenization(1,:,:) + deallocate(damage(h)%p) + damage(h)%p => damageState(h)%state(1,:) + end associate enddo @@ -211,35 +173,27 @@ end subroutine damage_local_getSourceAndItsTangent !-------------------------------------------------------------------------------------------------- -!> @brief return array of damage results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function damage_local_postResults(ip,el) +subroutine damage_local_results(homog,group) - integer, intent(in) :: & - ip, & !< integration point - el !< element - real(pReal), dimension(sum(damage_local_sizePostResult(:,damage_typeInstance(material_homogenizationAt(el))))) :: & - damage_local_postResults - - integer :: instance, homog, offset, o, c - - homog = material_homogenizationAt(el) - offset = damageMapping(homog)%p(ip,el) - instance = damage_typeInstance(homog) - associate(prm => param(instance)) - c = 0 + integer, intent(in) :: homog + character(len=*), intent(in) :: group + integer :: o + + associate(prm => param(damage_typeInstance(homog))) outputsLoop: do o = 1,size(prm%outputID) select case(prm%outputID(o)) - - case (damage_ID) - damage_local_postResults(c+1) = damage(homog)%p(offset) - c = c + 1 - end select + + case (damage_ID) + call results_writeDataset(group,damage(homog)%p,'phi',& + 'damage indicator','-') + end select enddo outputsLoop - end associate -end function damage_local_postResults +end subroutine damage_local_results + end module damage_local diff --git a/src/damage_none.f90 b/src/damage_none.f90 index 62d2cc0eb..d3b1b73c5 100644 --- a/src/damage_none.f90 +++ b/src/damage_none.f90 @@ -19,26 +19,23 @@ contains !-------------------------------------------------------------------------------------------------- subroutine damage_none_init - integer :: & - homog, & - NofMyHomog + integer :: h,NofMyHomog - write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_NONE_LABEL//' init -+>>>' + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_NONE_LABEL//' init -+>>>'; flush(6) - initializeInstances: do homog = 1, size(config_homogenization) + do h = 1, size(config_homogenization) + if (damage_type(h) /= DAMAGE_NONE_ID) cycle + + NofMyHomog = count(material_homogenizationAt == h) + damageState(h)%sizeState = 0 + allocate(damageState(h)%state0 (0,NofMyHomog)) + allocate(damageState(h)%subState0(0,NofMyHomog)) + allocate(damageState(h)%state (0,NofMyHomog)) - myhomog: if (damage_type(homog) == DAMAGE_NONE_ID) then - NofMyHomog = count(material_homogenizationAt == homog) - damageState(homog)%sizeState = 0 - allocate(damageState(homog)%state0 (0,NofMyHomog)) - allocate(damageState(homog)%subState0(0,NofMyHomog)) - allocate(damageState(homog)%state (0,NofMyHomog)) + deallocate(damage(h)%p) + allocate (damage(h)%p(1), source=damage_initialPhi(h)) - deallocate(damage(homog)%p) - allocate (damage(homog)%p(1), source=damage_initialPhi(homog)) - - endif myhomog - enddo initializeInstances + enddo end subroutine damage_none_init diff --git a/src/damage_nonlocal.f90 b/src/damage_nonlocal.f90 index 0a8a3c867..17bdecaca 100644 --- a/src/damage_nonlocal.f90 +++ b/src/damage_nonlocal.f90 @@ -1,29 +1,22 @@ !-------------------------------------------------------------------------------------------------- !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief material subroutine for non-locally evolving damage field -!> @details to be done !-------------------------------------------------------------------------------------------------- module damage_nonlocal use prec use material - use numerics use config + use numerics use crystallite use lattice use source_damage_isoBrittle use source_damage_isoDuctile use source_damage_anisoBrittle use source_damage_anisoDuctile + use results implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - damage_nonlocal_sizePostResult - character(len=64), dimension(:,:), allocatable, target, public :: & - damage_nonlocal_output - integer, dimension(:), allocatable, target, public :: & - damage_nonlocal_Noutput enum, bind(c) enumerator :: & @@ -45,7 +38,7 @@ module damage_nonlocal damage_nonlocal_getDiffusion33, & damage_nonlocal_getMobility, & damage_nonlocal_putNonLocalDamage, & - damage_nonlocal_postResults + damage_nonlocal_Results contains @@ -55,70 +48,44 @@ contains !-------------------------------------------------------------------------------------------------- subroutine damage_nonlocal_init - integer :: maxNinstance,homog,instance,o,i - integer :: sizeState - integer :: NofMyHomog, h - integer(kind(undefined_ID)) :: & - outputID - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - character(len=65536), dimension(:), allocatable :: & - outputs + integer :: maxNinstance,o,NofMyHomog,h + character(len=pStringLen), dimension(:), allocatable :: outputs - write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_nonlocal_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- damage_'//DAMAGE_nonlocal_label//' init -+>>>'; flush(6) maxNinstance = count(damage_type == DAMAGE_nonlocal_ID) if (maxNinstance == 0) return - - allocate(damage_nonlocal_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0) - allocate(damage_nonlocal_output (maxval(homogenization_Noutput),maxNinstance)) - damage_nonlocal_output = '' - allocate(damage_nonlocal_Noutput (maxNinstance), source=0) allocate(param(maxNinstance)) do h = 1, size(damage_type) if (damage_type(h) /= DAMAGE_NONLOCAL_ID) cycle - associate(prm => param(damage_typeInstance(h)), & - config => config_homogenization(h)) + associate(prm => param(damage_typeInstance(h)),config => config_homogenization(h)) - instance = damage_typeInstance(h) outputs = config%getStrings('(output)',defaultVal=emptyStringArray) allocate(prm%outputID(0)) - do i=1, size(outputs) - outputID = undefined_ID - select case(outputs(i)) - - case ('damage') - damage_nonlocal_output(i,damage_typeInstance(h)) = outputs(i) - damage_nonlocal_Noutput(instance) = damage_nonlocal_Noutput(instance) + 1 - damage_nonlocal_sizePostResult(i,damage_typeInstance(h)) = 1 - prm%outputID = [prm%outputID , damage_ID] - end select - + do o=1, size(outputs) + select case(outputs(o)) + case ('damage') + prm%outputID = [prm%outputID, damage_ID] + end select enddo - homog = h + NofMyHomog = count(material_homogenizationAt == h) + damageState(h)%sizeState = 1 + allocate(damageState(h)%state0 (1,NofMyHomog), source=damage_initialPhi(h)) + allocate(damageState(h)%subState0(1,NofMyHomog), source=damage_initialPhi(h)) + allocate(damageState(h)%state (1,NofMyHomog), source=damage_initialPhi(h)) - NofMyHomog = count(material_homogenizationAt == homog) - instance = damage_typeInstance(homog) - - -! allocate state arrays - sizeState = 1 - damageState(homog)%sizeState = sizeState - damageState(homog)%sizePostResults = sum(damage_nonlocal_sizePostResult(:,instance)) - allocate(damageState(homog)%state0 (sizeState,NofMyHomog), source=damage_initialPhi(homog)) - allocate(damageState(homog)%subState0(sizeState,NofMyHomog), source=damage_initialPhi(homog)) - allocate(damageState(homog)%state (sizeState,NofMyHomog), source=damage_initialPhi(homog)) - - nullify(damageMapping(homog)%p) - damageMapping(homog)%p => mappingHomogenization(1,:,:) - deallocate(damage(homog)%p) - damage(homog)%p => damageState(homog)%state(1,:) - + nullify(damageMapping(h)%p) + damageMapping(h)%p => mappingHomogenization(1,:,:) + deallocate(damage(h)%p) + damage(h)%p => damageState(h)%state(1,:) + end associate enddo + end subroutine damage_nonlocal_init @@ -247,35 +214,26 @@ end subroutine damage_nonlocal_putNonLocalDamage !-------------------------------------------------------------------------------------------------- -!> @brief return array of damage results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function damage_nonlocal_postResults(ip,el) +subroutine damage_nonlocal_results(homog,group) - integer, intent(in) :: & - ip, & !< integration point - el !< element - real(pReal), dimension(sum(damage_nonlocal_sizePostResult(:,damage_typeInstance(material_homogenizationAt(el))))) :: & - damage_nonlocal_postResults - - integer :: & - instance, homog, offset, o, c - - homog = material_homogenizationAt(el) - offset = damageMapping(homog)%p(ip,el) - instance = damage_typeInstance(homog) - associate(prm => param(instance)) - c = 0 + integer, intent(in) :: homog + character(len=*), intent(in) :: group + integer :: o + + associate(prm => param(damage_typeInstance(homog))) outputsLoop: do o = 1,size(prm%outputID) select case(prm%outputID(o)) - - case (damage_ID) - damage_nonlocal_postResults(c+1) = damage(homog)%p(offset) - c = c + 1 - end select + + case (damage_ID) + call results_writeDataset(group,damage(homog)%p,'phi',& + 'damage indicator','-') + end select enddo outputsLoop - end associate -end function damage_nonlocal_postResults + +end subroutine damage_nonlocal_results end module damage_nonlocal diff --git a/src/discretization.f90 b/src/discretization.f90 index 873148666..5f9d3f521 100644 --- a/src/discretization.f90 +++ b/src/discretization.f90 @@ -78,7 +78,7 @@ end subroutine discretization_init !> @brief write the displacements !-------------------------------------------------------------------------------------------------- subroutine discretization_results -#if defined(PETSc) || defined(DAMASK_HDF5) + real(pReal), dimension(:,:), allocatable :: u call results_closeGroup(results_addGroup(trim('current/geometry'))) @@ -90,7 +90,7 @@ subroutine discretization_results u = discretization_IPcoords & - discretization_IPcoords0 call results_writeDataset('current/geometry',u,'u_c','cell center displacements','m') -#endif + end subroutine discretization_results diff --git a/src/future.f90 b/src/future.f90 index 354a522e4..b7eb3fec9 100644 --- a/src/future.f90 +++ b/src/future.f90 @@ -10,7 +10,7 @@ module future contains -#if defined(__GFORTRAN__) && __GNUC__<9 || __INTEL_COMPILER<1800 +#if defined(__GFORTRAN__) && __GNUC__<9 || defined(__INTEL_COMPILER) && INTEL_COMPILER<1800 !-------------------------------------------------------------------------------------------------- !> @brief substitute for the findloc intrinsic (only for integer, dimension(:) at the moment) !-------------------------------------------------------------------------------------------------- diff --git a/src/geometry_plastic_nonlocal.f90 b/src/geometry_plastic_nonlocal.f90 index 408306b2b..b69ab2eff 100644 --- a/src/geometry_plastic_nonlocal.f90 +++ b/src/geometry_plastic_nonlocal.f90 @@ -122,7 +122,6 @@ subroutine geometry_plastic_nonlocal_results integer, dimension(:), allocatable :: shp -#if defined(PETSc) || defined(DAMASK_HDF5) call results_openJobFile writeVolume: block @@ -151,7 +150,6 @@ subroutine geometry_plastic_nonlocal_results call results_closeJobFile -#endif end subroutine geometry_plastic_nonlocal_results diff --git a/src/grid/DAMASK_grid.f90 b/src/grid/DAMASK_grid.f90 index 7fe8d82c4..b324a5afc 100644 --- a/src/grid/DAMASK_grid.f90 +++ b/src/grid/DAMASK_grid.f90 @@ -15,11 +15,7 @@ program DAMASK_spectral use config use debug use math - use mesh_grid use CPFEM2 - use FEsolving - use numerics - use homogenization use material use spectral_utilities use grid_mech_spectral_basic @@ -40,7 +36,7 @@ program DAMASK_spectral N_t = 0, & !< # of time indicators found in load case file N_n = 0, & !< # of increment specifiers found in load case file N_def = 0 !< # of rate of deformation specifiers found in load case file - character(len=65536) :: & + character(len=pStringLen) :: & line !-------------------------------------------------------------------------------------------------- @@ -80,12 +76,6 @@ program DAMASK_spectral type(tLoadCase), allocatable, dimension(:) :: loadCases !< array of all load cases type(tLoadCase) :: newLoadCase type(tSolutionState), allocatable, dimension(:) :: solres - integer(MPI_OFFSET_KIND) :: fileOffset - integer(MPI_OFFSET_KIND), dimension(:), allocatable :: outputSize - integer, parameter :: maxByteOut = 2147483647-4096 !< limit of one file output write https://trac.mpich.org/projects/mpich/ticket/1742 - integer, parameter :: maxRealOut = maxByteOut/pReal - integer(pLongInt), dimension(2) :: outputIndex - PetscErrorCode :: ierr procedure(grid_mech_spectral_basic_init), pointer :: & mech_init procedure(grid_mech_spectral_basic_forward), pointer :: & @@ -257,7 +247,7 @@ program DAMASK_spectral reportAndCheck: if (worldrank == 0) then write (loadcase_string, '(i6)' ) currentLoadCase - write(6,'(/,1x,a,i6)') 'load case: ', currentLoadCase + write(6,'(/,1x,a,i0)') 'load case: ', currentLoadCase if (.not. newLoadCase%followFormerTrajectory) write(6,'(2x,a)') 'drop guessing along trajectory' if (newLoadCase%deformation%myType == 'l') then do j = 1, 3 @@ -280,10 +270,8 @@ program DAMASK_spectral enddo if (any(newLoadCase%stress%maskLogical .eqv. & newLoadCase%deformation%maskLogical)) errorID = 831 ! exclusive or masking only - if (any(newLoadCase%stress%maskLogical .and. & - transpose(newLoadCase%stress%maskLogical) .and. & - reshape([ .false.,.true.,.true.,.true.,.false.,.true.,.true.,.true.,.false.],[ 3,3]))) & - errorID = 838 ! no rotation is allowed by stress BC + if (any(newLoadCase%stress%maskLogical .and. transpose(newLoadCase%stress%maskLogical) & + .and. (math_I3<1))) errorID = 838 ! no rotation is allowed by stress BC write(6,'(2x,a)') 'stress / GPa:' do i = 1, 3; do j = 1, 3 if(newLoadCase%stress%maskLogical(i,j)) then @@ -300,14 +288,14 @@ program DAMASK_spectral write(6,'(2x,a,/,3(3(3x,f12.7,1x)/))',advance='no') 'rotation of loadframe:',& transpose(newLoadCase%rot%asMatrix()) if (newLoadCase%time < 0.0_pReal) errorID = 834 ! negative time increment - write(6,'(2x,a,f12.6)') 'time: ', newLoadCase%time + write(6,'(2x,a,f0.3)') 'time: ', newLoadCase%time if (newLoadCase%incs < 1) errorID = 835 ! non-positive incs count - write(6,'(2x,a,i5)') 'increments: ', newLoadCase%incs + write(6,'(2x,a,i0)') 'increments: ', newLoadCase%incs if (newLoadCase%outputfrequency < 1) errorID = 836 ! non-positive result frequency - write(6,'(2x,a,i5)') 'output frequency: ', newLoadCase%outputfrequency + write(6,'(2x,a,i0)') 'output frequency: ', newLoadCase%outputfrequency if (newLoadCase%restartfrequency < 1) errorID = 839 ! non-positive restart frequency if (newLoadCase%restartfrequency < huge(0)) & - write(6,'(2x,a,i5)') 'restart frequency: ', newLoadCase%restartfrequency + write(6,'(2x,a,i0)') 'restart frequency: ', newLoadCase%restartfrequency if (errorID > 0) call IO_error(error_ID = errorID, ext_msg = loadcase_string) ! exit with error message endif reportAndCheck loadCases = [loadCases,newLoadCase] ! load case is ok, append it @@ -335,26 +323,10 @@ program DAMASK_spectral ! write header of output file if (worldrank == 0) then writeHeader: if (interface_restartInc < 1) then - open(newunit=fileUnit,file=trim(getSolverJobName())//& - '.spectralOut',form='UNFORMATTED',status='REPLACE') - write(fileUnit) 'load:', trim(loadCaseFile) ! ... and write header - write(fileUnit) 'workingdir:', 'n/a' - write(fileUnit) 'geometry:', trim(geometryFile) - write(fileUnit) 'grid:', grid - write(fileUnit) 'size:', geomSize - write(fileUnit) 'materialpoint_sizeResults:', materialpoint_sizeResults - write(fileUnit) 'loadcases:', size(loadCases) - write(fileUnit) 'frequencies:', loadCases%outputfrequency ! one entry per LoadCase - write(fileUnit) 'times:', loadCases%time ! one entry per LoadCase - write(fileUnit) 'logscales:', loadCases%logscale - write(fileUnit) 'increments:', loadCases%incs ! one entry per LoadCase - write(fileUnit) 'startingIncrement:', interface_restartInc ! start with writing out the previous inc - write(fileUnit) 'eoh' - close(fileUnit) ! end of header open(newunit=statUnit,file=trim(getSolverJobName())//'.sta',form='FORMATTED',status='REPLACE') write(statUnit,'(a)') 'Increment Time CutbackLevel Converged IterationsNeeded' ! statistics file if (iand(debug_level(debug_spectral),debug_levelBasic) /= 0) & - write(6,'(/,a)') ' header of result and statistics file written out' + write(6,'(/,a)') ' header of statistics file written out' flush(6) else writeHeader open(newunit=statUnit,file=trim(getSolverJobName())//& @@ -362,40 +334,11 @@ program DAMASK_spectral endif writeHeader endif -!-------------------------------------------------------------------------------------------------- -! prepare MPI parallel out (including opening of file) - allocate(outputSize(worldsize), source = 0_MPI_OFFSET_KIND) - outputSize(worldrank+1) = size(materialpoint_results,kind=MPI_OFFSET_KIND)*int(pReal,MPI_OFFSET_KIND) - call MPI_allreduce(MPI_IN_PLACE,outputSize,worldsize,MPI_LONG,MPI_SUM,PETSC_COMM_WORLD,ierr) ! get total output size over each process - if (ierr /= 0) call IO_error(error_ID=894, ext_msg='MPI_allreduce') - call MPI_file_open(PETSC_COMM_WORLD, trim(getSolverJobName())//'.spectralOut', & - MPI_MODE_WRONLY + MPI_MODE_APPEND, & - MPI_INFO_NULL, & - fileUnit, & - ierr) - if (ierr /= 0) call IO_error(error_ID=894, ext_msg='MPI_file_open') - call MPI_file_get_position(fileUnit,fileOffset,ierr) ! get offset from header - if (ierr /= 0) call IO_error(error_ID=894, ext_msg='MPI_file_get_position') - fileOffset = fileOffset + sum(outputSize(1:worldrank)) ! offset of my process in file (header + processes before me) - call MPI_file_seek (fileUnit,fileOffset,MPI_SEEK_SET,ierr) - if (ierr /= 0) call IO_error(error_ID=894, ext_msg='MPI_file_seek') - writeUndeformed: if (interface_restartInc < 1) then write(6,'(1/,a)') ' ... writing initial configuration to file ........................' call CPFEM_results(0,0.0_pReal) - do i = 1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output - outputIndex = int([(i-1)*((maxRealOut)/materialpoint_sizeResults)+1, & - min(i*((maxRealOut)/materialpoint_sizeResults),size(materialpoint_results,3))],pLongInt) - call MPI_file_write(fileUnit,reshape(materialpoint_results(:,:,outputIndex(1):outputIndex(2)), & - [(outputIndex(2)-outputIndex(1)+1)*int(materialpoint_sizeResults,pLongInt)]), & - int((outputIndex(2)-outputIndex(1)+1)*int(materialpoint_sizeResults,pLongInt)), & - MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) - if (ierr /= 0) call IO_error(error_ID=894, ext_msg='MPI_file_write') - enddo - fileOffset = fileOffset + sum(outputSize) ! forward to current file position endif writeUndeformed - loadCaseLooping: do currentLoadCase = 1, size(loadCases) time0 = time ! load case start time guess = loadCases(currentLoadCase)%followFormerTrajectory ! change of load case? homogeneous guess for the first inc @@ -519,7 +462,6 @@ program DAMASK_spectral write(6,'(/,a)') ' cutting back ' else ! no more options to continue call IO_warning(850) - call MPI_File_close(fileUnit,ierr) close(statUnit) call quit(0) ! quit endif @@ -537,19 +479,6 @@ program DAMASK_spectral if (mod(inc,loadCases(currentLoadCase)%outputFrequency) == 0) then ! at output frequency write(6,'(1/,a)') ' ... writing results to file ......................................' flush(6) - call materialpoint_postResults() - call MPI_File_seek (fileUnit,fileOffset,MPI_SEEK_SET,ierr) - if (ierr /= 0) call IO_error(894, ext_msg='MPI_file_seek') - do i=1, size(materialpoint_results,3)/(maxByteOut/(materialpoint_sizeResults*pReal))+1 ! slice the output of my process in chunks not exceeding the limit for one output - outputIndex=int([(i-1)*((maxRealOut)/materialpoint_sizeResults)+1, & - min(i*((maxRealOut)/materialpoint_sizeResults),size(materialpoint_results,3))],pLongInt) - call MPI_file_write(fileUnit,reshape(materialpoint_results(:,:,outputIndex(1):outputIndex(2)),& - [(outputIndex(2)-outputIndex(1)+1)*int(materialpoint_sizeResults,pLongInt)]), & - int((outputIndex(2)-outputIndex(1)+1)*int(materialpoint_sizeResults,pLongInt)),& - MPI_DOUBLE, MPI_STATUS_IGNORE, ierr) - if(ierr /=0) call IO_error(894, ext_msg='MPI_file_write') - enddo - fileOffset = fileOffset + sum(outputSize) ! forward to current file position call CPFEM_results(totalIncsCounter,time) endif if (mod(inc,loadCases(currentLoadCase)%restartFrequency) == 0) then @@ -566,7 +495,6 @@ program DAMASK_spectral !-------------------------------------------------------------------------------------------------- ! report summary of whole calculation write(6,'(/,a)') ' ###########################################################################' - call MPI_file_close(fileUnit,ierr) close(statUnit) call quit(0) ! no complains ;) diff --git a/src/grid/grid_mech_FEM.f90 b/src/grid/grid_mech_FEM.f90 index f6074fee9..a34d880f7 100644 --- a/src/grid/grid_mech_FEM.f90 +++ b/src/grid/grid_mech_FEM.f90 @@ -476,8 +476,7 @@ subroutine formResidual(da_local,x_local, & ! begin of new iteration newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 - write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') & - trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter+1, '≤', itmax + write(6,'(1x,a,3(a,i0))') trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter+1, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) diff --git a/src/grid/grid_mech_spectral_basic.f90 b/src/grid/grid_mech_spectral_basic.f90 index fb69427e3..f05f9bc93 100644 --- a/src/grid/grid_mech_spectral_basic.f90 +++ b/src/grid/grid_mech_spectral_basic.f90 @@ -440,8 +440,7 @@ subroutine formResidual(in, F, & ! begin of new iteration newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 - write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') & - trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax + write(6,'(1x,a,3(a,i0))') trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) diff --git a/src/grid/grid_mech_spectral_polarisation.f90 b/src/grid/grid_mech_spectral_polarisation.f90 index ed2e0e1a9..33c3e4e72 100644 --- a/src/grid/grid_mech_spectral_polarisation.f90 +++ b/src/grid/grid_mech_spectral_polarisation.f90 @@ -509,8 +509,7 @@ subroutine formResidual(in, FandF_tau, & ! begin of new iteration newIteration: if (totalIter <= PETScIter) then totalIter = totalIter + 1 - write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') & - trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax + write(6,'(1x,a,3(a,i0))') trim(incInfo), ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax if (iand(debug_level(debug_spectral),debug_spectralRotation) /= 0) & write(6,'(/,a,/,3(3(f12.7,1x)/))',advance='no') & ' deformation gradient aim (lab) =', transpose(params%rotation_BC%rotTensor2(F_aim,active=.true.)) diff --git a/src/homogenization.f90 b/src/homogenization.f90 index 0112f9cf5..18148e1e0 100644 --- a/src/homogenization.f90 +++ b/src/homogenization.f90 @@ -23,7 +23,6 @@ module homogenization use damage_local use damage_nonlocal use results - use HDF5_utilities implicit none private @@ -36,12 +35,6 @@ module homogenization materialpoint_P !< first P--K stress of IP real(pReal), dimension(:,:,:,:,:,:), allocatable, public :: & materialpoint_dPdF !< tangent of first P--K stress at IP - real(pReal), dimension(:,:,:), allocatable, public :: & - materialpoint_results !< results array of material point - integer, public, protected :: & - materialpoint_sizeResults, & - thermal_maxSizePostResults, & - damage_maxSizePostResults real(pReal), dimension(:,:,:,:), allocatable :: & materialpoint_subF0, & !< def grad of IP at beginning of homogenization increment @@ -126,7 +119,6 @@ module homogenization public :: & homogenization_init, & materialpoint_stressAndItsTangent, & - materialpoint_postResults, & homogenization_results contains @@ -137,14 +129,6 @@ contains !-------------------------------------------------------------------------------------------------- subroutine homogenization_init - integer, parameter :: FILEUNIT = 200 - integer :: e,i,p - integer, dimension(:,:), pointer :: thisSize - integer, dimension(:) , pointer :: thisNoutput - character(len=64), dimension(:,:), pointer :: thisOutput - character(len=32) :: outputName !< name of output, intermediate fix until HDF5 output is ready - logical :: valid - if (any(homogenization_type == HOMOGENIZATION_NONE_ID)) call mech_none_init if (any(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID)) call mech_isostrain_init if (any(homogenization_type == HOMOGENIZATION_RGC_ID)) call mech_RGC_init @@ -157,80 +141,6 @@ subroutine homogenization_init if (any(damage_type == DAMAGE_local_ID)) call damage_local_init if (any(damage_type == DAMAGE_nonlocal_ID)) call damage_nonlocal_init -!-------------------------------------------------------------------------------------------------- -! write description file for homogenization output - mainProcess: if (worldrank == 0) then - call IO_write_jobFile(FILEUNIT,'outputHomogenization') - do p = 1,size(config_homogenization) - if (any(material_homogenizationAt == p)) then - write(FILEUNIT,'(/,a,/)') '['//trim(config_name_homogenization(p))//']' - write(FILEUNIT,'(a)') '(type) n/a' - write(FILEUNIT,'(a,i4)') '(ngrains)'//char(9),homogenization_Ngrains(p) - - i = thermal_typeInstance(p) ! which instance of this thermal type - valid = .true. ! assume valid - select case(thermal_type(p)) ! split per thermal type - case (THERMAL_isothermal_ID) - outputName = THERMAL_isothermal_label - thisNoutput => null() - thisOutput => null() - thisSize => null() - case (THERMAL_adiabatic_ID) - outputName = THERMAL_adiabatic_label - thisNoutput => thermal_adiabatic_Noutput - thisOutput => thermal_adiabatic_output - thisSize => thermal_adiabatic_sizePostResult - case (THERMAL_conduction_ID) - outputName = THERMAL_conduction_label - thisNoutput => thermal_conduction_Noutput - thisOutput => thermal_conduction_output - thisSize => thermal_conduction_sizePostResult - case default - valid = .false. - end select - if (valid) then - write(FILEUNIT,'(a)') '(thermal)'//char(9)//trim(outputName) - if (thermal_type(p) /= THERMAL_isothermal_ID) then - do e = 1,thisNoutput(i) - write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) - enddo - endif - endif - - i = damage_typeInstance(p) ! which instance of this damage type - valid = .true. ! assume valid - select case(damage_type(p)) ! split per damage type - case (DAMAGE_none_ID) - outputName = DAMAGE_none_label - thisNoutput => null() - thisOutput => null() - thisSize => null() - case (DAMAGE_local_ID) - outputName = DAMAGE_local_label - thisNoutput => damage_local_Noutput - thisOutput => damage_local_output - thisSize => damage_local_sizePostResult - case (DAMAGE_nonlocal_ID) - outputName = DAMAGE_nonlocal_label - thisNoutput => damage_nonlocal_Noutput - thisOutput => damage_nonlocal_output - thisSize => damage_nonlocal_sizePostResult - case default - valid = .false. - end select - if (valid) then - write(FILEUNIT,'(a)') '(damage)'//char(9)//trim(outputName) - if (damage_type(p) /= DAMAGE_none_ID) then - do e = 1,thisNoutput(i) - write(FILEUNIT,'(a,i4)') trim(thisOutput(e,i))//char(9),thisSize(e,i) - enddo - endif - endif - endif - enddo - close(FILEUNIT) - endif mainProcess - call config_deallocate('material.config/homogenization') !-------------------------------------------------------------------------------------------------- @@ -250,23 +160,7 @@ subroutine homogenization_init allocate(materialpoint_converged(discretization_nIP,discretization_nElem), source=.true.) allocate(materialpoint_doneAndHappy(2,discretization_nIP,discretization_nElem), source=.true.) -!-------------------------------------------------------------------------------------------------- -! allocate and initialize global state and postresutls variables - thermal_maxSizePostResults = 0 - damage_maxSizePostResults = 0 - do p = 1,size(config_homogenization) - thermal_maxSizePostResults = max(thermal_maxSizePostResults, thermalState(p)%sizePostResults) - damage_maxSizePostResults = max(damage_maxSizePostResults, damageState (p)%sizePostResults) - enddo - - materialpoint_sizeResults = 1 & ! grain count - + 1 + thermal_maxSizePostResults & - + damage_maxSizePostResults & - + homogenization_maxNgrains * ( 1 & ! crystallite size - + 1 + constitutive_source_maxSizePostResults) - allocate(materialpoint_results(materialpoint_sizeResults,discretization_nIP,discretization_nElem)) - - write(6,'(/,a)') ' <<<+- homogenization init -+>>>' + write(6,'(/,a)') ' <<<+- homogenization init -+>>>'; flush(6) if (iand(debug_level(debug_homogenization), debug_levelBasic) /= 0) then write(6,'(a32,1x,7(i8,1x))') 'materialpoint_dPdF: ', shape(materialpoint_dPdF) @@ -582,52 +476,6 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) end subroutine materialpoint_stressAndItsTangent -!-------------------------------------------------------------------------------------------------- -!> @brief parallelized calculation of result array at material points -!-------------------------------------------------------------------------------------------------- -subroutine materialpoint_postResults - - integer :: & - thePos, & - theSize, & - myNgrains, & - g, & !< grain number - i, & !< integration point number - e !< element number - - !$OMP PARALLEL DO PRIVATE(myNgrains,thePos,theSize) - elementLooping: do e = FEsolving_execElem(1),FEsolving_execElem(2) - myNgrains = homogenization_Ngrains(material_homogenizationAt(e)) - IpLooping: do i = FEsolving_execIP(1,e),FEsolving_execIP(2,e) - thePos = 0 - - theSize = thermalState (material_homogenizationAt(e))%sizePostResults & - + damageState (material_homogenizationAt(e))%sizePostResults - materialpoint_results(thePos+1,i,e) = real(theSize,pReal) ! tell size of homogenization results - thePos = thePos + 1 - - if (theSize > 0) then ! any homogenization results to mention? - materialpoint_results(thePos+1:thePos+theSize,i,e) = postResults(i,e) - thePos = thePos + theSize - endif - - materialpoint_results(thePos+1,i,e) = real(myNgrains,pReal) ! tell number of grains at materialpoint - thePos = thePos + 1 - - grainLooping :do g = 1,myNgrains - theSize = 1 + & - 1 + & - sum(sourceState(material_phaseAt(g,e))%p(:)%sizePostResults) - materialpoint_results(thePos+1:thePos+theSize,i,e) = crystallite_postResults(g,i,e) ! tell crystallite results - thePos = thePos + theSize - enddo grainLooping - enddo IpLooping - enddo elementLooping - !$OMP END PARALLEL DO - -end subroutine materialpoint_postResults - - !-------------------------------------------------------------------------------------------------- !> @brief partition material point def grad onto constituents !-------------------------------------------------------------------------------------------------- @@ -739,90 +587,58 @@ subroutine averageStressAndItsTangent(ip,el) end subroutine averageStressAndItsTangent -!-------------------------------------------------------------------------------------------------- -!> @brief return array of homogenization results for post file inclusion. call only, -!> if homogenization_sizePostResults(i,e) > 0 !! -!-------------------------------------------------------------------------------------------------- -function postResults(ip,el) - - integer, intent(in) :: & - ip, & !< integration point - el !< element number - real(pReal), dimension( thermalState (material_homogenizationAt(el))%sizePostResults & - + damageState (material_homogenizationAt(el))%sizePostResults) :: & - postResults - integer :: & - startPos, endPos ,& - homog - - - postResults = 0.0_pReal - startPos = 1 - endPos = thermalState(material_homogenizationAt(el))%sizePostResults - chosenThermal: select case (thermal_type(material_homogenizationAt(el))) - - case (THERMAL_adiabatic_ID) chosenThermal - homog = material_homogenizationAt(el) - postResults(startPos:endPos) = & - thermal_adiabatic_postResults(homog,thermal_typeInstance(homog),thermalMapping(homog)%p(ip,el)) - case (THERMAL_conduction_ID) chosenThermal - homog = material_homogenizationAt(el) - postResults(startPos:endPos) = & - thermal_conduction_postResults(homog,thermal_typeInstance(homog),thermalMapping(homog)%p(ip,el)) - - end select chosenThermal - - startPos = endPos + 1 - endPos = endPos + damageState(material_homogenizationAt(el))%sizePostResults - chosenDamage: select case (damage_type(material_homogenizationAt(el))) - - case (DAMAGE_local_ID) chosenDamage - postResults(startPos:endPos) = damage_local_postResults(ip, el) - case (DAMAGE_nonlocal_ID) chosenDamage - postResults(startPos:endPos) = damage_nonlocal_postResults(ip, el) - - end select chosenDamage - -end function postResults - - !-------------------------------------------------------------------------------------------------- !> @brief writes homogenization results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine homogenization_results -#if defined(PETSc) || defined(DAMASK_HDF5) use material, only: & material_homogenization_type => homogenization_type integer :: p - character(len=256) :: group + character(len=pStringLen) :: group_base,group !real(pReal), dimension(:,:,:), allocatable :: temp do p=1,size(config_name_homogenization) - group = trim('current/materialpoint')//'/'//trim(config_name_homogenization(p)) - call HDF5_closeGroup(results_addGroup(group)) - - group = trim(group)//'/mech' - - call HDF5_closeGroup(results_addGroup(group)) - select case(material_homogenization_type(p)) - case(HOMOGENIZATION_rgc_ID) - call mech_RGC_results(homogenization_typeInstance(p),group) - end select - - group = trim('current/materialpoint')//'/'//trim(config_name_homogenization(p))//'/generic' - call HDF5_closeGroup(results_addGroup(group)) + group_base = 'current/materialpoint/'//trim(config_name_homogenization(p)) + call results_closeGroup(results_addGroup(group_base)) + group = trim(group_base)//'/generic' + call results_closeGroup(results_addGroup(group)) !temp = reshape(materialpoint_F,[3,3,discretization_nIP*discretization_nElem]) !call results_writeDataset(group,temp,'F',& ! 'deformation gradient','1') !temp = reshape(materialpoint_P,[3,3,discretization_nIP*discretization_nElem]) !call results_writeDataset(group,temp,'P',& ! '1st Piola-Kirchoff stress','Pa') + + group = trim(group_base)//'/mech' + call results_closeGroup(results_addGroup(group)) + select case(material_homogenization_type(p)) + case(HOMOGENIZATION_rgc_ID) + call mech_RGC_results(homogenization_typeInstance(p),group) + end select + + group = trim(group_base)//'/damage' + call results_closeGroup(results_addGroup(group)) + select case(damage_type(p)) + case(DAMAGE_LOCAL_ID) + call damage_local_results(p,group) + case(DAMAGE_NONLOCAL_ID) + call damage_nonlocal_results(p,group) + end select + + group = trim(group_base)//'/thermal' + call results_closeGroup(results_addGroup(group)) + select case(thermal_type(p)) + case(THERMAL_ADIABATIC_ID) + call thermal_adiabatic_results(p,group) + case(THERMAL_CONDUCTION_ID) + call thermal_conduction_results(p,group) + end select + + enddo - enddo -#endif end subroutine homogenization_results end module homogenization diff --git a/src/homogenization_mech_RGC.f90 b/src/homogenization_mech_RGC.f90 index 61a1997cd..c493c4190 100644 --- a/src/homogenization_mech_RGC.f90 +++ b/src/homogenization_mech_RGC.f90 @@ -74,12 +74,10 @@ module subroutine mech_RGC_init NofMyHomog, & sizeState, nIntFaceTot - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_RGC_label//' init -+>>>' @@ -928,7 +926,6 @@ end subroutine mech_RGC_averageStressAndItsTangent !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- module subroutine mech_RGC_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*), intent(in) :: group @@ -962,11 +959,6 @@ module subroutine mech_RGC_results(instance,group) enddo outputsLoop end associate -#else - integer, intent(in) :: instance - character(len=*), intent(in) :: group -#endif - end subroutine mech_RGC_results diff --git a/src/homogenization_mech_isostrain.f90 b/src/homogenization_mech_isostrain.f90 index cdc078925..9345d1eda 100644 --- a/src/homogenization_mech_isostrain.f90 +++ b/src/homogenization_mech_isostrain.f90 @@ -33,7 +33,7 @@ module subroutine mech_isostrain_init Ninstance, & h, & NofMyHomog - character(len=65536) :: & + character(len=pStringLen) :: & tag = '' write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_ISOSTRAIN_label//' init -+>>>' diff --git a/src/lattice.f90 b/src/lattice.f90 index fada61392..025a1f8a5 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -492,7 +492,7 @@ contains subroutine lattice_init integer :: Nphases - character(len=65536) :: & + character(len=pStringLen) :: & tag = '' integer :: i,p real(pReal), dimension(:), allocatable :: & diff --git a/src/list.f90 b/src/list.f90 index 79eafc964..689227545 100644 --- a/src/list.f90 +++ b/src/list.f90 @@ -261,7 +261,7 @@ end function getInt !! error unless default is given. If raw is true, the the complete string is returned, otherwise !! the individual chunks are returned !-------------------------------------------------------------------------------------------------- -character(len=65536) function getString(this,key,defaultVal,raw) +character(len=pStringLen) function getString(this,key,defaultVal,raw) class(tPartitionedStringList), target, intent(in) :: this character(len=*), intent(in) :: key @@ -400,13 +400,13 @@ end function getInts !-------------------------------------------------------------------------------------------------- function getStrings(this,key,defaultVal,raw) - character(len=65536),dimension(:), allocatable :: getStrings + character(len=pStringLen),dimension(:), allocatable :: getStrings class(tPartitionedStringList),target, intent(in) :: this character(len=*), intent(in) :: key character(len=*), dimension(:), intent(in), optional :: defaultVal logical, intent(in), optional :: raw type(tPartitionedStringList), pointer :: item - character(len=65536) :: str + character(len=pStringLen) :: str integer :: i logical :: found, & whole, & diff --git a/src/material.f90 b/src/material.f90 index 8aeab5dec..a4494ed6e 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -354,12 +354,10 @@ subroutine material_init call config_deallocate('material.config/microstructure') call config_deallocate('material.config/texture') -#if defined(PETSc) || defined(DAMASK_HDF5) call results_openJobFile call results_mapping_constituent(material_phaseAt,material_phaseMemberAt,config_name_phase) call results_mapping_materialpoint(material_homogenizationAt,material_homogenizationMemberAt,config_name_homogenization) call results_closeJobFile -#endif !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -393,8 +391,8 @@ end subroutine material_init !-------------------------------------------------------------------------------------------------- subroutine material_parseHomogenization - integer :: h - character(len=65536) :: tag + integer :: h + character(len=pStringLen) :: tag allocate(homogenization_type(size(config_homogenization)), source=HOMOGENIZATION_undefined_ID) allocate(thermal_type(size(config_homogenization)), source=THERMAL_isothermal_ID) @@ -484,11 +482,11 @@ end subroutine material_parseHomogenization !-------------------------------------------------------------------------------------------------- subroutine material_parseMicrostructure - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & strings integer, allocatable, dimension(:) :: chunkPos integer :: e, m, c, i - character(len=65536) :: & + character(len=pStringLen) :: & tag allocate(microstructure_Nconstituents(size(config_microstructure)), source=0) @@ -542,7 +540,7 @@ end subroutine material_parseMicrostructure subroutine material_parsePhase integer :: sourceCtr, kinematicsCtr, stiffDegradationCtr, p - character(len=65536), dimension(:), allocatable :: str + character(len=pStringLen), dimension(:), allocatable :: str allocate(phase_elasticity(size(config_phase)),source=ELASTICITY_undefined_ID) @@ -596,9 +594,9 @@ subroutine material_parsePhase #if defined(__GFORTRAN__) || defined(__PGI) str = ['GfortranBug86277'] str = config_phase(p)%getStrings('(source)',defaultVal=str) - if (str(1) == 'GfortranBug86277') str = [character(len=65536)::] + if (str(1) == 'GfortranBug86277') str = [character(len=pStringLen)::] #else - str = config_phase(p)%getStrings('(source)',defaultVal=[character(len=65536)::]) + str = config_phase(p)%getStrings('(source)',defaultVal=[character(len=pStringLen)::]) #endif do sourceCtr = 1, size(str) select case (trim(str(sourceCtr))) @@ -620,9 +618,9 @@ subroutine material_parsePhase #if defined(__GFORTRAN__) || defined(__PGI) str = ['GfortranBug86277'] str = config_phase(p)%getStrings('(kinematics)',defaultVal=str) - if (str(1) == 'GfortranBug86277') str = [character(len=65536)::] + if (str(1) == 'GfortranBug86277') str = [character(len=pStringLen)::] #else - str = config_phase(p)%getStrings('(kinematics)',defaultVal=[character(len=65536)::]) + str = config_phase(p)%getStrings('(kinematics)',defaultVal=[character(len=pStringLen)::]) #endif do kinematicsCtr = 1, size(str) select case (trim(str(kinematicsCtr))) @@ -637,9 +635,9 @@ subroutine material_parsePhase #if defined(__GFORTRAN__) || defined(__PGI) str = ['GfortranBug86277'] str = config_phase(p)%getStrings('(stiffness_degradation)',defaultVal=str) - if (str(1) == 'GfortranBug86277') str = [character(len=65536)::] + if (str(1) == 'GfortranBug86277') str = [character(len=pStringLen)::] #else - str = config_phase(p)%getStrings('(stiffness_degradation)',defaultVal=[character(len=65536)::]) + str = config_phase(p)%getStrings('(stiffness_degradation)',defaultVal=[character(len=pStringLen)::]) #endif do stiffDegradationCtr = 1, size(str) select case (trim(str(stiffDegradationCtr))) @@ -665,8 +663,8 @@ end subroutine material_parsePhase !-------------------------------------------------------------------------------------------------- subroutine material_parseTexture - integer :: j, t - character(len=65536), dimension(:), allocatable :: strings ! Values for given key in material config + integer :: j,t + character(len=pStringLen), dimension(:), allocatable :: strings ! Values for given key in material config integer, dimension(:), allocatable :: chunkPos real(pReal), dimension(3,3) :: transformation ! maps texture to microstructure coordinate system real(pReal), dimension(3) :: Eulers ! Euler angles in degrees from file @@ -702,29 +700,27 @@ subroutine material_parseTexture do j = 1, 3 ! look for "x", "y", and "z" entries select case (strings(j)) case('x', '+x') - transformation(j,1:3) = [ 1.0_pReal, 0.0_pReal, 0.0_pReal] ! original axis is now +x-axis + transformation(j,1:3) = [ 1.0_pReal, 0.0_pReal, 0.0_pReal] ! original axis is now +x-axis case('-x') - transformation(j,1:3) = [-1.0_pReal, 0.0_pReal, 0.0_pReal] ! original axis is now -x-axis + transformation(j,1:3) = [-1.0_pReal, 0.0_pReal, 0.0_pReal] ! original axis is now -x-axis case('y', '+y') - transformation(j,1:3) = [ 0.0_pReal, 1.0_pReal, 0.0_pReal] ! original axis is now +y-axis + transformation(j,1:3) = [ 0.0_pReal, 1.0_pReal, 0.0_pReal] ! original axis is now +y-axis case('-y') - transformation(j,1:3) = [ 0.0_pReal,-1.0_pReal, 0.0_pReal] ! original axis is now -y-axis + transformation(j,1:3) = [ 0.0_pReal,-1.0_pReal, 0.0_pReal] ! original axis is now -y-axis case('z', '+z') - transformation(j,1:3) = [ 0.0_pReal, 0.0_pReal, 1.0_pReal] ! original axis is now +z-axis + transformation(j,1:3) = [ 0.0_pReal, 0.0_pReal, 1.0_pReal] ! original axis is now +z-axis case('-z') - transformation(j,1:3) = [ 0.0_pReal, 0.0_pReal,-1.0_pReal] ! original axis is now -z-axis + transformation(j,1:3) = [ 0.0_pReal, 0.0_pReal,-1.0_pReal] ! original axis is now -z-axis case default call IO_error(157,t) end select enddo - if(dNeq(math_det33(transformation),1.0_pReal)) call IO_error(157,t) call transformation_%fromMatrix(transformation) texture_orientation(t) = texture_orientation(t) * transformation_ endif enddo - end subroutine material_parseTexture @@ -732,18 +728,14 @@ end subroutine material_parseTexture !> @brief allocates the plastic state of a phase !-------------------------------------------------------------------------------------------------- subroutine material_allocatePlasticState(phase,NofMyPhase,& - sizeState,sizeDotState,sizeDeltaState,& - Nslip,Ntwin,Ntrans) + sizeState,sizeDotState,sizeDeltaState) integer, intent(in) :: & phase, & NofMyPhase, & sizeState, & sizeDotState, & - sizeDeltaState, & - Nslip, & - Ntwin, & - Ntrans + sizeDeltaState plasticState(phase)%sizeState = sizeState plasticState(phase)%sizeDotState = sizeDotState diff --git a/src/mesh/DAMASK_FEM.f90 b/src/mesh/DAMASK_FEM.f90 index cd0bcacb1..9b9b95b91 100644 --- a/src/mesh/DAMASK_FEM.f90 +++ b/src/mesh/DAMASK_FEM.f90 @@ -27,7 +27,7 @@ program DAMASK_FEM integer, allocatable, dimension(:) :: chunkPos ! this is longer than needed for geometry parsing integer :: & N_def = 0 !< # of rate of deformation specifiers found in load case file - character(len=65536) :: & + character(len=pStringLen) :: & line !-------------------------------------------------------------------------------------------------- diff --git a/src/mesh_grid.f90 b/src/mesh_grid.f90 index 2b337f047..62ce67397 100644 --- a/src/mesh_grid.f90 +++ b/src/mesh_grid.f90 @@ -27,9 +27,8 @@ module mesh_grid integer, public, protected :: & grid3, & !< (local) grid in 3rd direction grid3Offset !< (local) grid offset in 3rd direction - real(pReal), dimension(3), public, protected :: & - geomSize + geomSize !< (global) physical size real(pReal), public, protected :: & size3, & !< (local) size in 3rd direction size3offset !< (local) size offset in 3rd direction @@ -49,7 +48,8 @@ subroutine mesh_init(ip,el) include 'fftw3-mpi.f03' real(pReal), dimension(3) :: & - mySize !< domain size of this process + mySize, & !< domain size of this process + origin !< (global) distance to origin integer, dimension(3) :: & myGrid !< domain grid of this process @@ -61,9 +61,9 @@ subroutine mesh_init(ip,el) integer(C_INTPTR_T) :: & devNull, z, z_offset - write(6,'(/,a)') ' <<<+- mesh_grid init -+>>>' + write(6,'(/,a)') ' <<<+- mesh_grid init -+>>>'; flush(6) - call readGeom(grid,geomSize,microstructureAt,homogenizationAt) + call readGeom(grid,geomSize,origin,microstructureAt,homogenizationAt) !-------------------------------------------------------------------------------------------------- ! grid solver specific quantities @@ -104,8 +104,9 @@ subroutine mesh_init(ip,el) ! store geometry information for post processing call results_openJobFile call results_closeGroup(results_addGroup('geometry')) - call results_addAttribute('grid',grid,'geometry') - call results_addAttribute('size',geomSize,'geometry') + call results_addAttribute('grid', grid, 'geometry') + call results_addAttribute('size', geomSize,'geometry') + call results_addAttribute('origin',origin, 'geometry') call results_closeJobFile !-------------------------------------------------------------------------------------------------- @@ -129,10 +130,13 @@ end subroutine mesh_init !> @details important variables have an implicit "save" attribute. Therefore, this function is ! supposed to be called only once! !-------------------------------------------------------------------------------------------------- -subroutine readGeom(grid,geomSize,microstructure,homogenization) +subroutine readGeom(grid,geomSize,origin,microstructure,homogenization) - integer, dimension(3), intent(out) :: grid ! grid (for all processes!) - real(pReal), dimension(3), intent(out) :: geomSize ! size (for all processes!) + integer, dimension(3), intent(out) :: & + grid ! grid (for all processes!) + real(pReal), dimension(3), intent(out) :: & + geomSize, & ! size (for all processes!) + origin ! origin (for all processes!) integer, dimension(:), intent(out), allocatable :: & microstructure, & homogenization @@ -181,6 +185,7 @@ subroutine readGeom(grid,geomSize,microstructure,homogenization) !-------------------------------------------------------------------------------------------------- ! read and interprete header + origin = 0.0_pReal l = 0 do while (l < headerLength .and. startPos < len(rawData)) endPos = startPos + index(rawData(startPos:),new_line('')) - 1 @@ -221,8 +226,23 @@ subroutine readGeom(grid,geomSize,microstructure,homogenization) enddo endif + case ('origin') + if (chunkPos(1) > 6) then + do j = 2,6,2 + select case (IO_lc(IO_stringValue(line,chunkPos,j))) + case('x') + origin(1) = IO_floatValue(line,chunkPos,j+1) + case('y') + origin(2) = IO_floatValue(line,chunkPos,j+1) + case('z') + origin(3) = IO_floatValue(line,chunkPos,j+1) + end select + enddo + endif + case ('homogenization') if (chunkPos(1) > 1) h = IO_intValue(line,chunkPos,2) + end select enddo @@ -276,7 +296,7 @@ end subroutine readGeom !--------------------------------------------------------------------------------------------------- -!> @brief Calculate undeformed position of IPs/cell centres (pretend to be an element) +!> @brief Calculate undeformed position of IPs/cell centers (pretend to be an element) !--------------------------------------------------------------------------------------------------- function IPcoordinates0(grid,geomSize,grid3Offset) @@ -347,7 +367,7 @@ pure function cellEdgeNormal(nElems) integer, intent(in) :: nElems - real, dimension(3,6,1,nElems) :: cellEdgeNormal + real(pReal), dimension(3,6,1,nElems) :: cellEdgeNormal cellEdgeNormal(1:3,1,1,:) = spread([+1.0_pReal, 0.0_pReal, 0.0_pReal],2,nElems) cellEdgeNormal(1:3,2,1,:) = spread([-1.0_pReal, 0.0_pReal, 0.0_pReal],2,nElems) diff --git a/src/mesh_marc.f90 b/src/mesh_marc.f90 index f640baa72..cebe844e7 100644 --- a/src/mesh_marc.f90 +++ b/src/mesh_marc.f90 @@ -18,7 +18,6 @@ module mesh use element use discretization use geometry_plastic_nonlocal - use HDF5_utilities use results implicit none @@ -150,9 +149,8 @@ subroutine writeGeometry(elemType, & real(pReal), dimension(:,:), allocatable :: & coordinates_temp -#if defined(DAMASK_HDF5) call results_openJobFile - call HDF5_closeGroup(results_addGroup('geometry')) + call results_closeGroup(results_addGroup('geometry')) connectivity_temp = connectivity_elem call results_writeDataset('geometry',connectivity_temp,'T_e',& @@ -171,7 +169,6 @@ subroutine writeGeometry(elemType, & 'coordinates of the material points','m') call results_closeJobFile -#endif end subroutine writeGeometry diff --git a/src/plastic_disloUCLA.f90 b/src/plastic_disloUCLA.f90 index 29ef0fcc9..d1291d853 100644 --- a/src/plastic_disloUCLA.f90 +++ b/src/plastic_disloUCLA.f90 @@ -121,16 +121,12 @@ subroutine plastic_disloUCLA_init() sizeState, sizeDotState, & startIndex, endIndex - integer, dimension(0), parameter :: emptyIntArray = [integer::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_label//' init -+>>>' @@ -290,8 +286,7 @@ subroutine plastic_disloUCLA_init() sizeDotState = size(['rho_mob ','rho_dip ','gamma_sl']) * prm%sum_N_sl sizeState = sizeDotState - call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & - prm%sum_N_sl,0,0) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -463,7 +458,6 @@ end subroutine plastic_disloUCLA_dependentState !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_disloUCLA_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*), intent(in) :: group @@ -491,11 +485,6 @@ subroutine plastic_disloUCLA_results(instance,group) end select enddo outputsLoop end associate - -#else - integer, intent(in) :: instance - character(len=*), intent(in) :: group -#endif end subroutine plastic_disloUCLA_results diff --git a/src/plastic_dislotwin.f90 b/src/plastic_dislotwin.f90 index 1f731a891..ae89dcc1c 100644 --- a/src/plastic_dislotwin.f90 +++ b/src/plastic_dislotwin.f90 @@ -180,16 +180,12 @@ subroutine plastic_dislotwin_init sizeState, sizeDotState, & startIndex, endIndex - integer, dimension(0), parameter :: emptyIntArray = [integer::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_label//' init -+>>>' @@ -510,8 +506,7 @@ subroutine plastic_dislotwin_init + size(['f_tr']) * prm%sum_N_tr sizeState = sizeDotState - call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & - prm%sum_N_sl,prm%sum_N_tw,prm%sum_N_tr) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -926,7 +921,6 @@ end subroutine plastic_dislotwin_dependentState !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_dislotwin_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*) :: group @@ -969,11 +963,6 @@ subroutine plastic_dislotwin_results(instance,group) end select enddo outputsLoop end associate - -#else - integer, intent(in) :: instance - character(len=*) :: group -#endif end subroutine plastic_dislotwin_results diff --git a/src/plastic_isotropic.f90 b/src/plastic_isotropic.f90 index 9beb2262b..96d70be4a 100644 --- a/src/plastic_isotropic.f90 +++ b/src/plastic_isotropic.f90 @@ -85,14 +85,12 @@ subroutine plastic_isotropic_init NipcMyPhase, & sizeState, sizeDotState - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_label//' init -+>>>' @@ -181,8 +179,7 @@ subroutine plastic_isotropic_init sizeDotState = size(['xi ','accumulated_shear']) sizeState = sizeDotState - call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & - 1,0,0) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -373,7 +370,6 @@ end subroutine plastic_isotropic_dotState !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_isotropic_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*), intent(in) :: group @@ -388,10 +384,6 @@ subroutine plastic_isotropic_results(instance,group) end select enddo outputsLoop end associate -#else - integer, intent(in) :: instance - character(len=*) :: group -#endif end subroutine plastic_isotropic_results diff --git a/src/plastic_kinematichardening.f90 b/src/plastic_kinematichardening.f90 index 2a3dc4640..721073746 100644 --- a/src/plastic_kinematichardening.f90 +++ b/src/plastic_kinematichardening.f90 @@ -103,16 +103,12 @@ subroutine plastic_kinehardening_init sizeState, sizeDeltaState, sizeDotState, & startIndex, endIndex - integer, dimension(0), parameter :: emptyIntArray = [integer::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_label//' init -+>>>' @@ -249,8 +245,7 @@ subroutine plastic_kinehardening_init sizeDeltaState = size(['sense ', 'chi0 ', 'gamma0' ]) * prm%totalNslip sizeState = sizeDotState + sizeDeltaState - call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState, & - prm%totalNslip,0,0) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -437,7 +432,6 @@ end subroutine plastic_kinehardening_deltaState !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_kinehardening_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*) :: group @@ -470,10 +464,6 @@ subroutine plastic_kinehardening_results(instance,group) end select enddo outputsLoop end associate -#else - integer, intent(in) :: instance - character(len=*) :: group -#endif end subroutine plastic_kinehardening_results diff --git a/src/plastic_none.f90 b/src/plastic_none.f90 index a4979bb2c..f77b19c09 100644 --- a/src/plastic_none.f90 +++ b/src/plastic_none.f90 @@ -38,8 +38,8 @@ subroutine plastic_none_init if (phase_plasticity(p) /= PLASTICITY_NONE_ID) cycle NipcMyPhase = count(material_phaseAt == p) * discretization_nIP - call material_allocatePlasticState(p,NipcMyPhase,0,0,0, & - 0,0,0) + call material_allocatePlasticState(p,NipcMyPhase,0,0,0) + enddo end subroutine plastic_none_init diff --git a/src/plastic_nonlocal.f90 b/src/plastic_nonlocal.f90 index 5375aba49..3977f1fa7 100644 --- a/src/plastic_nonlocal.f90 +++ b/src/plastic_nonlocal.f90 @@ -12,6 +12,7 @@ module plastic_nonlocal use material use lattice use rotations + use results use config use lattice use discretization @@ -27,9 +28,6 @@ module plastic_nonlocal real(pReal), parameter :: & KB = 1.38e-23_pReal !< Physical parameter, Boltzmann constant in J/Kelvin - character(len=64), dimension(:,:), allocatable :: & - plastic_nonlocal_output !< name of each post result output - ! storage order of dislocation types integer, dimension(8), parameter :: & sgl = [1,2,3,4,5,6,7,8] !< signed (single) @@ -201,9 +199,6 @@ module plastic_nonlocal type(tNonlocalMicrostructure), dimension(:), allocatable :: microstructure - integer(kind(undefined_ID)), dimension(:,:), allocatable :: & - plastic_nonlocal_outputID !< ID of each post result output - public :: & plastic_nonlocal_init, & plastic_nonlocal_dependentState, & @@ -224,10 +219,6 @@ contains !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_init - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer, dimension(0), parameter :: emptyIntArray = [integer::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] - integer :: & sizeState, sizeDotState,sizeDependentState, sizeDeltaState, & maxNinstances, & @@ -240,10 +231,10 @@ subroutine plastic_nonlocal_init integer(kind(undefined_ID)) :: & outputID - character(len=512) :: & + character(len=pStringLen) :: & extmsg = '', & structure - character(len=65536), dimension(:), allocatable :: outputs + character(len=pStringLen), dimension(:), allocatable :: outputs integer :: NofMyPhase write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>' @@ -264,9 +255,6 @@ subroutine plastic_nonlocal_init allocate(deltaState(maxNinstances)) allocate(microstructure(maxNinstances)) - allocate(plastic_nonlocal_output(maxval(phase_Noutput), maxNinstances)) - plastic_nonlocal_output = '' - allocate(plastic_nonlocal_outputID(maxval(phase_Noutput), maxNinstances), source=undefined_ID) allocate(totalNslip(maxNinstances), source=0) @@ -492,7 +480,6 @@ subroutine plastic_nonlocal_init end select if (outputID /= undefined_ID) then - plastic_nonlocal_output(i,phase_plasticityInstance(p)) = outputs(i) prm%outputID = [prm%outputID , outputID] endif @@ -514,8 +501,8 @@ subroutine plastic_nonlocal_init 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]) * prm%totalNslip !< other dependent state variables that are not updated by microstructure sizeDeltaState = sizeDotState - call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState, & - prm%totalNslip,0,0) + call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState) + plasticState(p)%nonlocal = .true. plasticState(p)%offsetDeltaState = 0 ! ToDo: state structure does not follow convention @@ -1974,9 +1961,6 @@ end function getRho !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_nonlocal_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) - use results, only: & - results_writeDataset integer, intent(in) :: instance character(len=*) :: group @@ -2039,10 +2023,6 @@ subroutine plastic_nonlocal_results(instance,group) end select enddo outputsLoop end associate -#else - integer, intent(in) :: instance - character(len=*) :: group -#endif end subroutine plastic_nonlocal_results diff --git a/src/plastic_phenopowerlaw.f90 b/src/plastic_phenopowerlaw.f90 index b8f5c8306..a8e459f63 100644 --- a/src/plastic_phenopowerlaw.f90 +++ b/src/plastic_phenopowerlaw.f90 @@ -113,16 +113,12 @@ subroutine plastic_phenopowerlaw_init sizeState, sizeDotState, & startIndex, endIndex - integer, dimension(0), parameter :: emptyIntArray = [integer::] - real(pReal), dimension(0), parameter :: emptyRealArray = [real(pReal)::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>' @@ -308,8 +304,7 @@ subroutine plastic_phenopowerlaw_init + size(['tau_twin ','gamma_twin']) * prm%totalNtwin sizeState = sizeDotState - call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0, & - prm%totalNslip,prm%totalNtwin,0) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- ! locally defined state aliases and initialization of state0 and aTolState @@ -464,7 +459,6 @@ end subroutine plastic_phenopowerlaw_dotState !> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- subroutine plastic_phenopowerlaw_results(instance,group) -#if defined(PETSc) || defined(DAMASK_HDF5) integer, intent(in) :: instance character(len=*), intent(in) :: group @@ -492,11 +486,6 @@ subroutine plastic_phenopowerlaw_results(instance,group) end select enddo outputsLoop end associate - -#else - integer, intent(in) :: instance - character(len=*), intent(in) :: group -#endif end subroutine plastic_phenopowerlaw_results diff --git a/src/prec.f90 b/src/prec.f90 index b6d5d4fdf..2f0f20a00 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -42,8 +42,7 @@ module prec sizeState = 0, & !< size of state sizeDotState = 0, & !< size of dot state, i.e. state(1:sizeDot) follows time evolution by dotState rates offsetDeltaState = 0, & !< index offset of delta state - sizeDeltaState = 0, & !< size of delta state, i.e. state(offset+1:offset+sizeDelta) follows time evolution by deltaState increments - sizePostResults = 0 !< size of output data + sizeDeltaState = 0 !< size of delta state, i.e. state(offset+1:offset+sizeDelta) follows time evolution by deltaState increments real(pReal), pointer, dimension(:), contiguous :: & atolState real(pReal), pointer, dimension(:,:), contiguous :: & ! a pointer is needed here because we might point to state/doState. However, they will never point to something, but are rather allocated and, hence, contiguous @@ -80,6 +79,10 @@ module prec real(pReal), private, parameter :: PREAL_EPSILON = epsilon(0.0_pReal) !< minimum positive number such that 1.0 + EPSILON /= 1.0. real(pReal), private, parameter :: PREAL_MIN = tiny(0.0_pReal) !< smallest normalized floating point number + integer, dimension(0), parameter, public :: emptyIntArray = [integer::] + real(pReal), dimension(0), parameter, public :: emptyRealArray = [real(pReal)::] + character(len=pStringLen), dimension(0), parameter, public :: emptyStringArray = [character(len=pStringLen)::] + private :: & unitTest diff --git a/src/quaternions.f90 b/src/quaternions.f90 index 8efb985ed..0ca404880 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -1,37 +1,9 @@ -! ################################################################### -! Copyright (c) 2013-2015, Marc De Graef/Carnegie Mellon University -! Modified 2017-2019, Martin Diehl/Max-Planck-Institut für Eisenforschung GmbH -! All rights reserved. -! -! Redistribution and use in source and binary forms, with or without modification, are -! permitted provided that the following conditions are met: -! -! - Redistributions of source code must retain the above copyright notice, this list -! of conditions and the following disclaimer. -! - Redistributions in binary form must reproduce the above copyright notice, this -! list of conditions and the following disclaimer in the documentation and/or -! other materials provided with the distribution. -! - Neither the names of Marc De Graef, Carnegie Mellon University nor the names -! of its contributors may be used to endorse or promote products derived from -! this software without specific prior written permission. -! -! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -! USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -! ################################################################### - !--------------------------------------------------------------------------------------------------- -!> @author Marc De Graef, Carnegie Mellon University !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH +!> @author Philip Eisenlohr, Michigan State University !> @brief general quaternion math, not limited to unit quaternions -!> @details w is the real part, (x, y, z) are the imaginary parts. +!> @details w is the real part, (x, y, z) are the imaginary parts. +!> @details https://en.wikipedia.org/wiki/Quaternion !--------------------------------------------------------------------------------------------------- module quaternions use prec @@ -78,15 +50,16 @@ module quaternions procedure, public :: abs__ procedure, public :: dot_product__ - procedure, public :: conjg__ procedure, public :: exp__ procedure, public :: log__ - - procedure, public :: homomorphed => quat_homomorphed - procedure, public :: asArray + procedure, public :: conjg => conjg__ procedure, public :: real => real__ procedure, public :: aimag => aimag__ + procedure, public :: homomorphed + procedure, public :: asArray + procedure, public :: inverse + end type interface assignment (=) @@ -117,6 +90,14 @@ module quaternions interface log module procedure log__ end interface log + + interface real + module procedure real__ + end interface real + + interface aimag + module procedure aimag__ + end interface aimag private :: & unitTest @@ -125,49 +106,46 @@ contains !-------------------------------------------------------------------------------------------------- -!> @brief doing self test +!> @brief do self test !-------------------------------------------------------------------------------------------------- subroutine quaternions_init - write(6,'(/,a)') ' <<<+- quaternions init -+>>>' + write(6,'(/,a)') ' <<<+- quaternions init -+>>>'; flush(6) call unitTest end subroutine quaternions_init !--------------------------------------------------------------------------------------------------- -!> constructor for a quaternion from a 4-vector +!> construct a quaternion from a 4-vector !--------------------------------------------------------------------------------------------------- type(quaternion) pure function init__(array) real(pReal), intent(in), dimension(4) :: array - init__%w=array(1) - init__%x=array(2) - init__%y=array(3) - init__%z=array(4) + init__%w = array(1) + init__%x = array(2) + init__%y = array(3) + init__%z = array(4) end function init__ !--------------------------------------------------------------------------------------------------- -!> assing a quaternion +!> assign a quaternion !--------------------------------------------------------------------------------------------------- elemental pure subroutine assign_quat__(self,other) type(quaternion), intent(out) :: self type(quaternion), intent(in) :: other - self%w = other%w - self%x = other%x - self%y = other%y - self%z = other%z - + self = [other%w,other%x,other%y,other%z] + end subroutine assign_quat__ !--------------------------------------------------------------------------------------------------- -!> assing a 4-vector +!> assign a 4-vector !--------------------------------------------------------------------------------------------------- pure subroutine assign_vec__(self,other) @@ -183,67 +161,57 @@ end subroutine assign_vec__ !--------------------------------------------------------------------------------------------------- -!> addition of two quaternions +!> add a quaternion !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function add__(self,other) class(quaternion), intent(in) :: self,other - add__%w = self%w + other%w - add__%x = self%x + other%x - add__%y = self%y + other%y - add__%z = self%z + other%z - + add__ = [ self%w, self%x, self%y ,self%z] & + + [other%w, other%x, other%y,other%z] + end function add__ !--------------------------------------------------------------------------------------------------- -!> unary positive operator +!> return (unary positive operator) !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function pos__(self) class(quaternion), intent(in) :: self - pos__%w = self%w - pos__%x = self%x - pos__%y = self%y - pos__%z = self%z - + pos__ = self * (+1.0_pReal) + end function pos__ !--------------------------------------------------------------------------------------------------- -!> subtraction of two quaternions +!> subtract a quaternion !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function sub__(self,other) class(quaternion), intent(in) :: self,other - sub__%w = self%w - other%w - sub__%x = self%x - other%x - sub__%y = self%y - other%y - sub__%z = self%z - other%z - + sub__ = [ self%w, self%x, self%y ,self%z] & + - [other%w, other%x, other%y,other%z] + end function sub__ !--------------------------------------------------------------------------------------------------- -!> unary positive operator +!> negate (unary negative operator) !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function neg__(self) class(quaternion), intent(in) :: self - neg__%w = -self%w - neg__%x = -self%x - neg__%y = -self%y - neg__%z = -self%z - + neg__ = self * (-1.0_pReal) + end function neg__ !--------------------------------------------------------------------------------------------------- -!> multiplication of two quaternions +!> multiply with a quaternion !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function mul_quat__(self,other) @@ -258,23 +226,20 @@ end function mul_quat__ !--------------------------------------------------------------------------------------------------- -!> multiplication of quaternions with scalar +!> multiply with a scalar !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function mul_scal__(self,scal) class(quaternion), intent(in) :: self - real(pReal), intent(in) :: scal - - mul_scal__%w = self%w*scal - mul_scal__%x = self%x*scal - mul_scal__%y = self%y*scal - mul_scal__%z = self%z*scal + real(pReal), intent(in) :: scal + mul_scal__ = [self%w,self%x,self%y,self%z]*scal + end function mul_scal__ !--------------------------------------------------------------------------------------------------- -!> division of two quaternions +!> divide by a quaternion !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function div_quat__(self,other) @@ -286,12 +251,12 @@ end function div_quat__ !--------------------------------------------------------------------------------------------------- -!> divisiont of quaternions by scalar +!> divide by a scalar !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function div_scal__(self,scal) class(quaternion), intent(in) :: self - real(pReal), intent(in) :: scal + real(pReal), intent(in) :: scal div_scal__ = [self%w,self%x,self%y,self%z]/scal @@ -299,7 +264,7 @@ end function div_scal__ !--------------------------------------------------------------------------------------------------- -!> equality of two quaternions +!> test equality !--------------------------------------------------------------------------------------------------- logical elemental pure function eq__(self,other) @@ -312,7 +277,7 @@ end function eq__ !--------------------------------------------------------------------------------------------------- -!> inequality of two quaternions +!> test inequality !--------------------------------------------------------------------------------------------------- logical elemental pure function neq__(self,other) @@ -324,20 +289,7 @@ end function neq__ !--------------------------------------------------------------------------------------------------- -!> quaternion to the power of a scalar -!--------------------------------------------------------------------------------------------------- -type(quaternion) elemental pure function pow_scal__(self,expon) - - class(quaternion), intent(in) :: self - real(pReal), intent(in) :: expon - - pow_scal__ = exp(log(self)*expon) - -end function pow_scal__ - - -!--------------------------------------------------------------------------------------------------- -!> quaternion to the power of a quaternion +!> raise to the power of a quaternion !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function pow_quat__(self,expon) @@ -350,45 +302,60 @@ end function pow_quat__ !--------------------------------------------------------------------------------------------------- -!> exponential of a quaternion -!> ToDo: Lacks any check for invalid operations +!> raise to the power of a scalar +!--------------------------------------------------------------------------------------------------- +type(quaternion) elemental pure function pow_scal__(self,expon) + + class(quaternion), intent(in) :: self + real(pReal), intent(in) :: expon + + pow_scal__ = exp(log(self)*expon) + +end function pow_scal__ + + +!--------------------------------------------------------------------------------------------------- +!> take exponential !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function exp__(self) class(quaternion), intent(in) :: self real(pReal) :: absImag - absImag = norm2([self%x, self%y, self%z]) + absImag = norm2(aimag(self)) - exp__ = exp(self%w) * [ cos(absImag), & - self%x/absImag * sin(absImag), & - self%y/absImag * sin(absImag), & - self%z/absImag * sin(absImag)] + exp__ = merge(exp(self%w) * [ cos(absImag), & + self%x/absImag * sin(absImag), & + self%y/absImag * sin(absImag), & + self%z/absImag * sin(absImag)], & + IEEE_value(1.0_pReal,IEEE_SIGNALING_NAN), & + dNeq0(absImag)) end function exp__ !--------------------------------------------------------------------------------------------------- -!> logarithm of a quaternion -!> ToDo: Lacks any check for invalid operations +!> take logarithm !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function log__(self) class(quaternion), intent(in) :: self real(pReal) :: absImag - absImag = norm2([self%x, self%y, self%z]) + absImag = norm2(aimag(self)) - log__ = [log(abs(self)), & - self%x/absImag * acos(self%w/abs(self)), & - self%y/absImag * acos(self%w/abs(self)), & - self%z/absImag * acos(self%w/abs(self))] + log__ = merge([log(abs(self)), & + self%x/absImag * acos(self%w/abs(self)), & + self%y/absImag * acos(self%w/abs(self)), & + self%z/absImag * acos(self%w/abs(self))], & + IEEE_value(1.0_pReal,IEEE_SIGNALING_NAN), & + dNeq0(absImag)) end function log__ !--------------------------------------------------------------------------------------------------- -!> norm of a quaternion +!> return norm !--------------------------------------------------------------------------------------------------- real(pReal) elemental pure function abs__(a) @@ -400,7 +367,7 @@ end function abs__ !--------------------------------------------------------------------------------------------------- -!> dot product of two quaternions +!> calculate dot product !--------------------------------------------------------------------------------------------------- real(pReal) elemental pure function dot_product__(a,b) @@ -412,31 +379,31 @@ end function dot_product__ !--------------------------------------------------------------------------------------------------- -!> conjugate complex of a quaternion +!> take conjugate complex !--------------------------------------------------------------------------------------------------- type(quaternion) elemental pure function conjg__(a) class(quaternion), intent(in) :: a - conjg__ = quaternion([a%w, -a%x, -a%y, -a%z]) + conjg__ = [a%w, -a%x, -a%y, -a%z] end function conjg__ !--------------------------------------------------------------------------------------------------- -!> homomorphed quaternion of a quaternion +!> homomorph !--------------------------------------------------------------------------------------------------- -type(quaternion) elemental pure function quat_homomorphed(self) +type(quaternion) elemental pure function homomorphed(self) class(quaternion), intent(in) :: self - quat_homomorphed = quaternion(-[self%w,self%x,self%y,self%z]) + homomorphed = - self -end function quat_homomorphed +end function homomorphed !--------------------------------------------------------------------------------------------------- -!> quaternion as plain array +!> return as plain array !--------------------------------------------------------------------------------------------------- pure function asArray(self) @@ -449,7 +416,7 @@ end function asArray !--------------------------------------------------------------------------------------------------- -!> real part of a quaternion +!> real part (scalar) !--------------------------------------------------------------------------------------------------- pure function real__(self) @@ -462,7 +429,7 @@ end function real__ !--------------------------------------------------------------------------------------------------- -!> imaginary part of a quaternion +!> imaginary part (3-vector) !--------------------------------------------------------------------------------------------------- pure function aimag__(self) @@ -474,46 +441,87 @@ pure function aimag__(self) end function aimag__ +!--------------------------------------------------------------------------------------------------- +!> inverse +!--------------------------------------------------------------------------------------------------- +type(quaternion) elemental pure function inverse(self) + + class(quaternion), intent(in) :: self + + inverse = conjg(self)/abs(self)**2.0_pReal + +end function inverse + + !-------------------------------------------------------------------------------------------------- !> @brief check correctness of (some) quaternions functions !-------------------------------------------------------------------------------------------------- subroutine unitTest real(pReal), dimension(4) :: qu - type(quaternion) :: q, q_2 call random_number(qu) - q = qu + qu = (qu-0.5_pReal) * 2.0_pReal + q = quaternion(qu) - q_2 = q + q - if(any(dNeq(q_2%asArray(),2.0_pReal*qu))) call IO_error(401,ext_msg='add__') - - q_2 = q - q - if(any(dNeq0(q_2%asArray()))) call IO_error(401,ext_msg='sub__') - - q_2 = q * 5.0_preal - if(any(dNeq(q_2%asArray(),5.0_pReal*qu))) call IO_error(401,ext_msg='mul__') - - q_2 = q / 0.5_preal - if(any(dNeq(q_2%asArray(),2.0_pReal*qu))) call IO_error(401,ext_msg='div__') - - q_2 = q - if(q_2 /= q) call IO_error(401,ext_msg='eq__') + q_2= qu + if(any(dNeq(q%asArray(),q_2%asArray()))) call IO_error(401,ext_msg='assign_vec__') - if(any(dNeq(q%asArray(),qu))) call IO_error(401,ext_msg='eq__') - if(dNeq(q%real(), qu(1))) call IO_error(401,ext_msg='real()') - if(any(dNeq(q%aimag(), qu(2:4)))) call IO_error(401,ext_msg='aimag()') + q_2 = q + q + if(any(dNeq(q_2%asArray(),2.0_pReal*qu))) call IO_error(401,ext_msg='add__') + + q_2 = q - q + if(any(dNeq0(q_2%asArray()))) call IO_error(401,ext_msg='sub__') + + q_2 = q * 5.0_pReal + if(any(dNeq(q_2%asArray(),5.0_pReal*qu))) call IO_error(401,ext_msg='mul__') + + q_2 = q / 0.5_pReal + if(any(dNeq(q_2%asArray(),2.0_pReal*qu))) call IO_error(401,ext_msg='div__') + q_2 = q * 0.3_pReal + if(dNeq0(abs(q)) .and. q_2 == q) call IO_error(401,ext_msg='eq__') + + q_2 = q + if(q_2 /= q) call IO_error(401,ext_msg='neq__') + + if(dNeq(abs(q),norm2(qu))) call IO_error(401,ext_msg='abs__') + if(dNeq(abs(q)**2.0_pReal, real(q*q%conjg()),1.0e-14_pReal)) & + call IO_error(401,ext_msg='abs__/*conjg') + + if(any(dNeq(q%asArray(),qu))) call IO_error(401,ext_msg='eq__') + if(dNeq(q%real(), qu(1))) call IO_error(401,ext_msg='real()') + if(any(dNeq(q%aimag(), qu(2:4)))) call IO_error(401,ext_msg='aimag()') + q_2 = q%homomorphed() - if(q /= q_2* (-1.0_pReal)) call IO_error(401,ext_msg='homomorphed') - if(dNeq(q_2%real(), qu(1)* (-1.0_pReal))) call IO_error(401,ext_msg='homomorphed/real') - if(any(dNeq(q_2%aimag(),qu(2:4)*(-1.0_pReal)))) call IO_error(401,ext_msg='homomorphed/aimag') - + if(q /= q_2* (-1.0_pReal)) call IO_error(401,ext_msg='homomorphed') + if(dNeq(q_2%real(), qu(1)* (-1.0_pReal))) call IO_error(401,ext_msg='homomorphed/real') + if(any(dNeq(q_2%aimag(),qu(2:4)*(-1.0_pReal)))) call IO_error(401,ext_msg='homomorphed/aimag') + q_2 = conjg(q) - if(dNeq(q_2%real(), q%real())) call IO_error(401,ext_msg='conjg/real') - if(any(dNeq(q_2%aimag(),q%aimag()*(-1.0_pReal)))) call IO_error(401,ext_msg='conjg/aimag') - + if(dNeq(abs(q),abs(q_2))) call IO_error(401,ext_msg='conjg/abs') + if(q /= conjg(q_2)) call IO_error(401,ext_msg='conjg/involution') + if(dNeq(q_2%real(), q%real())) call IO_error(401,ext_msg='conjg/real') + if(any(dNeq(q_2%aimag(),q%aimag()*(-1.0_pReal)))) call IO_error(401,ext_msg='conjg/aimag') + + if(abs(q) > 0.0_pReal) then + q_2 = q * q%inverse() + if( dNeq(real(q_2), 1.0_pReal,1.0e-15_pReal)) call IO_error(401,ext_msg='inverse/real') + if(any(dNeq0(aimag(q_2), 1.0e-15_pReal))) call IO_error(401,ext_msg='inverse/aimag') + + q_2 = q/abs(q) + q_2 = conjg(q_2) - inverse(q_2) + if(any(dNeq0(q_2%asArray(),1.0e-15_pReal))) call IO_error(401,ext_msg='inverse/conjg') + endif + +#if !(defined(__GFORTRAN__) && __GNUC__ < 9) + if (norm2(aimag(q)) > 0.0_pReal) then + if (dNeq0(abs(q-exp(log(q))),1.0e-13_pReal)) call IO_error(401,ext_msg='exp/log') + if (dNeq0(abs(q-log(exp(q))),1.0e-13_pReal)) call IO_error(401,ext_msg='log/exp') + endif +#endif + end subroutine unitTest diff --git a/src/results.f90 b/src/results.f90 index 8fb7e134d..d38e629ec 100644 --- a/src/results.f90 +++ b/src/results.f90 @@ -16,7 +16,6 @@ module results implicit none private -#if defined(PETSc) || defined(DAMASK_HDF5) integer(HID_T) :: resultsFile interface results_writeDataset @@ -70,7 +69,7 @@ subroutine results_init resultsFile = HDF5_openFile(trim(getSolverJobName())//'.hdf5','w',.true.) call HDF5_addAttribute(resultsFile,'DADF5_version_major',0) - call HDF5_addAttribute(resultsFile,'DADF5_version_minor',4) + call HDF5_addAttribute(resultsFile,'DADF5_version_minor',5) call HDF5_addAttribute(resultsFile,'DAMASK_version',DAMASKVERSION) call get_command(commandLine) call HDF5_addAttribute(resultsFile,'call',trim(commandLine)) @@ -978,5 +977,4 @@ end subroutine results_mapping_materialpoint !end subroutine HDF5_mappingCells -#endif end module results diff --git a/src/rotations.f90 b/src/rotations.f90 index a4a0bac88..5deb02a20 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -596,7 +596,7 @@ function om2ax(om) result(ax) else call dgeev('N','V',3,om_,3,Wr,Wi,devNull,3,VR,3,work,size(work,1),ierr) if (ierr /= 0) call IO_error(0,ext_msg='Error in om2ax: DGEEV return not zero') -#if defined(__GFORTRAN__) && __GNUC__ < 9 || __INTEL_COMPILER < 1800 +#if defined(__GFORTRAN__) && __GNUC__<9 || defined(__INTEL_COMPILER) && INTEL_COMPILER<1800 i = maxloc(merge(1,0,cEq(cmplx(Wr,Wi,pReal),cmplx(1.0_pReal,0.0_pReal,pReal),tol=1.0e-14_pReal)),dim=1) #else i = findloc(cEq(cmplx(Wr,Wi,pReal),cmplx(1.0_pReal,0.0_pReal,pReal),tol=1.0e-14_pReal),.true.,dim=1) !find eigenvalue (1,0) diff --git a/src/source_damage_anisoBrittle.f90 b/src/source_damage_anisoBrittle.f90 index 9997f81e5..e5ed05799 100644 --- a/src/source_damage_anisoBrittle.f90 +++ b/src/source_damage_anisoBrittle.f90 @@ -13,19 +13,14 @@ module source_damage_anisoBrittle use discretization use config use lattice + use results implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_damage_anisoBrittle_offset, & !< which source is my current source mechanism? source_damage_anisoBrittle_instance !< instance of source mechanism - - integer, dimension(:,:), allocatable, target, public :: & - source_damage_anisoBrittle_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - source_damage_anisoBrittle_output !< name of each post result output integer, dimension(:,:), allocatable :: & source_damage_anisoBrittle_Ncleavage !< number of cleavage systems per family @@ -61,7 +56,7 @@ module source_damage_anisoBrittle source_damage_anisoBrittle_init, & source_damage_anisoBrittle_dotState, & source_damage_anisobrittle_getRateAndItsTangent, & - source_damage_anisoBrittle_postResults + source_damage_anisoBrittle_results contains @@ -74,17 +69,15 @@ subroutine source_damage_anisoBrittle_init integer :: Ninstance,phase,instance,source,sourceOffset integer :: NofMyPhase,p ,i - integer, dimension(0), parameter :: emptyIntArray = [integer::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs - write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISOBRITTLE_LABEL//' init -+>>>' + write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISOBRITTLE_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_source == SOURCE_damage_anisoBrittle_ID) if (Ninstance == 0) return @@ -102,10 +95,6 @@ subroutine source_damage_anisoBrittle_init enddo enddo - allocate(source_damage_anisoBrittle_sizePostResult(maxval(phase_Noutput),Ninstance), source=0) - allocate(source_damage_anisoBrittle_output(maxval(phase_Noutput),Ninstance)) - source_damage_anisoBrittle_output = '' - allocate(source_damage_anisoBrittle_Ncleavage(lattice_maxNcleavageFamily,Ninstance), source=0) allocate(param(Ninstance)) @@ -154,8 +143,6 @@ subroutine source_damage_anisoBrittle_init select case(outputs(i)) case ('anisobrittle_drivingforce') - source_damage_anisoBrittle_sizePostResult(i,source_damage_anisoBrittle_instance(p)) = 1 - source_damage_anisoBrittle_output(i,source_damage_anisoBrittle_instance(p)) = outputs(i) prm%outputID = [prm%outputID, damage_drivingforce_ID] end select @@ -171,7 +158,6 @@ subroutine source_damage_anisoBrittle_init call material_allocateSourceState(phase,sourceOffset,NofMyPhase,1,1,0) - sourceState(phase)%p(sourceOffset)%sizePostResults = sum(source_damage_anisoBrittle_sizePostResult(:,instance)) sourceState(phase)%p(sourceOffset)%aTolState=param(instance)%aTol @@ -262,39 +248,30 @@ subroutine source_damage_anisobrittle_getRateAndItsTangent(localphiDot, dLocalph dLocalphiDot_dPhi = -sourceState(phase)%p(sourceOffset)%state(1,constituent) -end subroutine source_damage_anisobrittle_getRateAndItsTangent +end subroutine source_damage_anisoBrittle_getRateAndItsTangent !-------------------------------------------------------------------------------------------------- -!> @brief return array of local damage results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function source_damage_anisoBrittle_postResults(phase, constituent) +subroutine source_damage_anisoBrittle_results(phase,group) - integer, intent(in) :: & - phase, & - constituent - - real(pReal), dimension(sum(source_damage_anisoBrittle_sizePostResult(:, & - source_damage_anisoBrittle_instance(phase)))) :: & - source_damage_anisoBrittle_postResults - - integer :: & - instance, sourceOffset, o, c - - instance = source_damage_anisoBrittle_instance(phase) + integer, intent(in) :: phase + character(len=*), intent(in) :: group + integer :: sourceOffset, o, instance + + instance = source_damage_anisoBrittle_instance(phase) sourceOffset = source_damage_anisoBrittle_offset(phase) - c = 0 - - do o = 1,size(param(instance)%outputID) - select case(param(instance)%outputID(o)) + associate(prm => param(instance), stt => sourceState(phase)%p(sourceOffset)%state) + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) case (damage_drivingforce_ID) - source_damage_anisoBrittle_postResults(c+1) = & - sourceState(phase)%p(sourceOffset)%state(1,constituent) - c = c + 1 - + call results_writeDataset(group,stt,'tbd','driving force','tbd') end select - enddo -end function source_damage_anisoBrittle_postResults + enddo outputsLoop + end associate + +end subroutine source_damage_anisoBrittle_results end module source_damage_anisoBrittle diff --git a/src/source_damage_anisoDuctile.f90 b/src/source_damage_anisoDuctile.f90 index 409466e48..fef897914 100644 --- a/src/source_damage_anisoDuctile.f90 +++ b/src/source_damage_anisoDuctile.f90 @@ -12,21 +12,15 @@ module source_damage_anisoDuctile use discretization use material use config + use results implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_damage_anisoDuctile_offset, & !< which source is my current damage mechanism? source_damage_anisoDuctile_instance !< instance of damage source mechanism - integer, dimension(:,:), allocatable, target, public :: & - source_damage_anisoDuctile_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - source_damage_anisoDuctile_output !< name of each post result output - - enum, bind(c) enumerator :: undefined_ID, & damage_drivingforce_ID @@ -54,7 +48,7 @@ module source_damage_anisoDuctile source_damage_anisoDuctile_init, & source_damage_anisoDuctile_dotState, & source_damage_anisoDuctile_getRateAndItsTangent, & - source_damage_anisoDuctile_postResults + source_damage_anisoDuctile_results contains @@ -68,17 +62,15 @@ subroutine source_damage_anisoDuctile_init integer :: Ninstance,phase,instance,source,sourceOffset integer :: NofMyPhase,p ,i - integer, dimension(0), parameter :: emptyIntArray = [integer::] - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs - write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISODUCTILE_LABEL//' init -+>>>' + write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISODUCTILE_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_source == SOURCE_damage_anisoDuctile_ID) if (Ninstance == 0) return @@ -95,11 +87,6 @@ subroutine source_damage_anisoDuctile_init source_damage_anisoDuctile_offset(phase) = source enddo enddo - - allocate(source_damage_anisoDuctile_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(source_damage_anisoDuctile_output(maxval(phase_Noutput),Ninstance)) - source_damage_anisoDuctile_output = '' - allocate(param(Ninstance)) @@ -139,8 +126,6 @@ subroutine source_damage_anisoDuctile_init select case(outputs(i)) case ('anisoductile_drivingforce') - source_damage_anisoDuctile_sizePostResult(i,source_damage_anisoDuctile_instance(p)) = 1 - source_damage_anisoDuctile_output(i,source_damage_anisoDuctile_instance(p)) = outputs(i) prm%outputID = [prm%outputID, damage_drivingforce_ID] end select @@ -156,8 +141,7 @@ subroutine source_damage_anisoDuctile_init sourceOffset = source_damage_anisoDuctile_offset(phase) call material_allocateSourceState(phase,sourceOffset,NofMyPhase,1,1,0) - sourceState(phase)%p(sourceOffset)%sizePostResults = sum(source_damage_anisoDuctile_sizePostResult(:,instance)) - sourceState(phase)%p(sourceOffset)%aTolState=param(instance)%aTol + sourceState(phase)%p(sourceOffset)%aTolState=param(instance)%aTol enddo @@ -226,35 +210,26 @@ end subroutine source_damage_anisoDuctile_getRateAndItsTangent !-------------------------------------------------------------------------------------------------- -!> @brief return array of local damage results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function source_damage_anisoDuctile_postResults(phase, constituent) +subroutine source_damage_anisoDuctile_results(phase,group) - integer, intent(in) :: & - phase, & - constituent - real(pReal), dimension(sum(source_damage_anisoDuctile_sizePostResult(:, & - source_damage_anisoDuctile_instance(phase)))) :: & - source_damage_anisoDuctile_postResults - - integer :: & - instance, sourceOffset, o, c - - instance = source_damage_anisoDuctile_instance(phase) + integer, intent(in) :: phase + character(len=*), intent(in) :: group + integer :: sourceOffset, o, instance + + instance = source_damage_anisoDuctile_instance(phase) sourceOffset = source_damage_anisoDuctile_offset(phase) - - c = 0 - - do o = 1,size(param(instance)%outputID) - select case(param(instance)%outputID(o)) - case (damage_drivingforce_ID) - source_damage_anisoDuctile_postResults(c+1) = & - sourceState(phase)%p(sourceOffset)%state(1,constituent) - c = c + 1 - - end select - enddo -end function source_damage_anisoDuctile_postResults + associate(prm => param(instance), stt => sourceState(phase)%p(sourceOffset)%state) + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) + case (damage_drivingforce_ID) + call results_writeDataset(group,stt,'tbd','driving force','tbd') + end select + enddo outputsLoop + end associate + +end subroutine source_damage_anisoDuctile_results end module source_damage_anisoDuctile diff --git a/src/source_damage_isoBrittle.f90 b/src/source_damage_isoBrittle.f90 index 89f5a038c..53c0b77a7 100644 --- a/src/source_damage_isoBrittle.f90 +++ b/src/source_damage_isoBrittle.f90 @@ -12,16 +12,13 @@ module source_damage_isoBrittle use discretization use material use config + use results implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_damage_isoBrittle_offset, & source_damage_isoBrittle_instance - integer, dimension(:,:), allocatable, target, public :: & - source_damage_isoBrittle_sizePostResult - character(len=64), dimension(:,:), allocatable, target, public :: & - source_damage_isoBrittle_output enum, bind(c) enumerator :: & @@ -46,7 +43,7 @@ module source_damage_isoBrittle source_damage_isoBrittle_init, & source_damage_isoBrittle_deltaState, & source_damage_isoBrittle_getRateAndItsTangent, & - source_damage_isoBrittle_postResults + source_damage_isoBrittle_Results contains @@ -59,16 +56,15 @@ subroutine source_damage_isoBrittle_init integer :: Ninstance,phase,instance,source,sourceOffset integer :: NofMyPhase,p,i - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs - write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ISOBRITTLE_LABEL//' init -+>>>' + write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ISOBRITTLE_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_source == SOURCE_damage_isoBrittle_ID) if (Ninstance == 0) return @@ -85,10 +81,6 @@ subroutine source_damage_isoBrittle_init source_damage_isoBrittle_offset(phase) = source enddo enddo - - allocate(source_damage_isoBrittle_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(source_damage_isoBrittle_output(maxval(phase_Noutput),Ninstance)) - source_damage_isoBrittle_output = '' allocate(param(Ninstance)) @@ -122,8 +114,6 @@ subroutine source_damage_isoBrittle_init select case(outputs(i)) case ('isobrittle_drivingforce') - source_damage_isoBrittle_sizePostResult(i,source_damage_isoBrittle_instance(p)) = 1 - source_damage_isoBrittle_output(i,source_damage_isoBrittle_instance(p)) = outputs(i) prm%outputID = [prm%outputID, damage_drivingforce_ID] end select @@ -139,7 +129,6 @@ subroutine source_damage_isoBrittle_init sourceOffset = source_damage_isoBrittle_offset(phase) call material_allocateSourceState(phase,sourceOffset,NofMyPhase,1,1,1) - sourceState(phase)%p(sourceOffset)%sizePostResults = sum(source_damage_isoBrittle_sizePostResult(:,instance)) sourceState(phase)%p(sourceOffset)%aTolState=param(instance)%aTol enddo @@ -214,35 +203,29 @@ subroutine source_damage_isoBrittle_getRateAndItsTangent(localphiDot, dLocalphiD - sourceState(phase)%p(sourceOffset)%state(1,constituent) end subroutine source_damage_isoBrittle_getRateAndItsTangent - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of local damage results -!-------------------------------------------------------------------------------------------------- -function source_damage_isoBrittle_postResults(phase, constituent) - integer, intent(in) :: & - phase, & - constituent - real(pReal), dimension(sum(source_damage_isoBrittle_sizePostResult(:, & - source_damage_isoBrittle_instance(phase)))) :: & - source_damage_isoBrittle_postResults - integer :: & - instance, sourceOffset, o, c - - instance = source_damage_isoBrittle_instance(phase) +!-------------------------------------------------------------------------------------------------- +!> @brief writes results to HDF5 output file +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoBrittle_results(phase,group) + + integer, intent(in) :: phase + character(len=*), intent(in) :: group + integer :: sourceOffset, o, instance + + instance = source_damage_isoBrittle_instance(phase) sourceOffset = source_damage_isoBrittle_offset(phase) - c = 0 - - do o = 1,size(param(instance)%outputID) - select case(param(instance)%outputID(o)) + associate(prm => param(instance), stt => sourceState(phase)%p(sourceOffset)%state) + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) case (damage_drivingforce_ID) - source_damage_isoBrittle_postResults(c+1) = sourceState(phase)%p(sourceOffset)%state(1,constituent) - c = c + 1 - + call results_writeDataset(group,stt,'tbd','driving force','tbd') end select - enddo -end function source_damage_isoBrittle_postResults + enddo outputsLoop + end associate + +end subroutine source_damage_isoBrittle_results end module source_damage_isoBrittle diff --git a/src/source_damage_isoDuctile.f90 b/src/source_damage_isoDuctile.f90 index 65930cd07..6ee588d0c 100644 --- a/src/source_damage_isoDuctile.f90 +++ b/src/source_damage_isoDuctile.f90 @@ -11,24 +11,18 @@ module source_damage_isoDuctile use discretization use material use config + use results implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_damage_isoDuctile_offset, & !< which source is my current damage mechanism? source_damage_isoDuctile_instance !< instance of damage source mechanism - integer, dimension(:,:), allocatable, target, public :: & - source_damage_isoDuctile_sizePostResult !< size of each post result output - - character(len=64), dimension(:,:), allocatable, target, public :: & - source_damage_isoDuctile_output !< name of each post result output - - enum, bind(c) enumerator :: undefined_ID, & damage_drivingforce_ID - end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11 ToDo + end enum !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ToDo type, private :: tParameters !< container type for internal constitutive parameters real(pReal) :: & @@ -46,7 +40,7 @@ module source_damage_isoDuctile source_damage_isoDuctile_init, & source_damage_isoDuctile_dotState, & source_damage_isoDuctile_getRateAndItsTangent, & - source_damage_isoDuctile_postResults + source_damage_isoDuctile_Results contains @@ -59,13 +53,12 @@ subroutine source_damage_isoDuctile_init integer :: Ninstance,phase,instance,source,sourceOffset integer :: NofMyPhase,p,i - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] integer(kind(undefined_ID)) :: & outputID character(len=pStringLen) :: & extmsg = '' - character(len=65536), dimension(:), allocatable :: & + character(len=pStringLen), dimension(:), allocatable :: & outputs write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ISODUCTILE_LABEL//' init -+>>>' @@ -85,10 +78,6 @@ subroutine source_damage_isoDuctile_init source_damage_isoDuctile_offset(phase) = source enddo enddo - - allocate(source_damage_isoDuctile_sizePostResult(maxval(phase_Noutput),Ninstance),source=0) - allocate(source_damage_isoDuctile_output(maxval(phase_Noutput),Ninstance)) - source_damage_isoDuctile_output = '' allocate(param(Ninstance)) @@ -122,8 +111,6 @@ subroutine source_damage_isoDuctile_init select case(outputs(i)) case ('isoductile_drivingforce') - source_damage_isoDuctile_sizePostResult(i,source_damage_isoDuctile_instance(p)) = 1 - source_damage_isoDuctile_output(i,source_damage_isoDuctile_instance(p)) = outputs(i) prm%outputID = [prm%outputID, damage_drivingforce_ID] end select @@ -138,9 +125,7 @@ subroutine source_damage_isoDuctile_init sourceOffset = source_damage_isoDuctile_offset(phase) call material_allocateSourceState(phase,sourceOffset,NofMyPhase,1,1,0) - sourceState(phase)%p(sourceOffset)%sizePostResults = sum(source_damage_isoDuctile_sizePostResult(:,instance)) sourceState(phase)%p(sourceOffset)%aTolState=param(instance)%aTol - enddo @@ -196,35 +181,30 @@ subroutine source_damage_isoDuctile_getRateAndItsTangent(localphiDot, dLocalphiD dLocalphiDot_dPhi = -sourceState(phase)%p(sourceOffset)%state(1,constituent) end subroutine source_damage_isoDuctile_getRateAndItsTangent - -!-------------------------------------------------------------------------------------------------- -!> @brief return array of local damage results -!-------------------------------------------------------------------------------------------------- -function source_damage_isoDuctile_postResults(phase, constituent) - integer, intent(in) :: & - phase, & - constituent - real(pReal), dimension(sum(source_damage_isoDuctile_sizePostResult(:, & - source_damage_isoDuctile_instance(phase)))) :: & - source_damage_isoDuctile_postResults - integer :: & - instance, sourceOffset, o, c +!-------------------------------------------------------------------------------------------------- +!> @brief writes results to HDF5 output file +!-------------------------------------------------------------------------------------------------- +subroutine source_damage_isoDuctile_results(phase,group) + + integer, intent(in) :: phase + character(len=*), intent(in) :: group + integer :: sourceOffset, o, instance - instance = source_damage_isoDuctile_instance(phase) - sourceOffset = source_damage_isoDuctile_offset(phase) + instance = source_damage_isoDuctile_instance(phase) + sourceOffset = source_damage_isoDuctile_offset(phase) - c = 0 + associate(prm => param(instance), stt => sourceState(phase)%p(sourceOffset)%state) + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) + case (damage_drivingforce_ID) + call results_writeDataset(group,stt,'tbd','driving force','tbd') + end select + enddo outputsLoop + end associate - do o = 1,size(param(instance)%outputID) - select case(param(instance)%outputID(o)) - case (damage_drivingforce_ID) - source_damage_isoDuctile_postResults(c+1) = sourceState(phase)%p(sourceOffset)%state(1,constituent) - c = c + 1 +end subroutine source_damage_isoDuctile_results - end select - enddo -end function source_damage_isoDuctile_postResults end module source_damage_isoDuctile diff --git a/src/source_thermal_dissipation.f90 b/src/source_thermal_dissipation.f90 index 0d16a9171..e13742a90 100644 --- a/src/source_thermal_dissipation.f90 +++ b/src/source_thermal_dissipation.f90 @@ -14,7 +14,7 @@ module source_thermal_dissipation implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_thermal_dissipation_offset, & !< which source is my current thermal dissipation mechanism? source_thermal_dissipation_instance !< instance of thermal dissipation source mechanism @@ -39,10 +39,9 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_thermal_dissipation_init - integer :: Ninstance,instance,source,sourceOffset - integer :: NofMyPhase,p + integer :: Ninstance,instance,source,sourceOffset,NofMyPhase,p - write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_dissipation_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_dissipation_label//' init -+>>>'; flush(6) Ninstance = count(phase_source == SOURCE_thermal_dissipation_ID) diff --git a/src/source_thermal_externalheat.f90 b/src/source_thermal_externalheat.f90 index 00e6da6bf..7ae37f037 100644 --- a/src/source_thermal_externalheat.f90 +++ b/src/source_thermal_externalheat.f90 @@ -14,7 +14,7 @@ module source_thermal_externalheat implicit none private - integer, dimension(:), allocatable, public, protected :: & + integer, dimension(:), allocatable :: & source_thermal_externalheat_offset, & !< which source is my current thermal dissipation mechanism? source_thermal_externalheat_instance !< instance of thermal dissipation source mechanism @@ -43,9 +43,9 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_thermal_externalheat_init - integer :: maxNinstance,instance,source,sourceOffset,NofMyPhase,p + integer :: maxNinstance,instance,source,sourceOffset,NofMyPhase,p - write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_externalheat_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_externalheat_label//' init -+>>>'; flush(6) maxNinstance = count(phase_source == SOURCE_thermal_externalheat_ID) diff --git a/src/thermal_adiabatic.f90 b/src/thermal_adiabatic.f90 index 2aa69bec5..d96604e59 100644 --- a/src/thermal_adiabatic.f90 +++ b/src/thermal_adiabatic.f90 @@ -7,6 +7,7 @@ module thermal_adiabatic use config use numerics use material + use results use source_thermal_dissipation use source_thermal_externalheat use crystallite @@ -14,22 +15,19 @@ module thermal_adiabatic implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - thermal_adiabatic_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - thermal_adiabatic_output !< name of each post result output - - integer, dimension(:), allocatable, target, public :: & - thermal_adiabatic_Noutput !< number of outputs per instance of this thermal model - + enum, bind(c) enumerator :: undefined_ID, & temperature_ID end enum - integer(kind(undefined_ID)), dimension(:,:), allocatable :: & - thermal_adiabatic_outputID !< ID of each post result output - + + type :: tParameters + integer(kind(undefined_ID)), dimension(:), allocatable :: & + outputID + end type tParameters + + type(tparameters), dimension(:), allocatable :: & + param public :: & thermal_adiabatic_init, & @@ -37,7 +35,7 @@ module thermal_adiabatic thermal_adiabatic_getSourceAndItsTangent, & thermal_adiabatic_getSpecificHeat, & thermal_adiabatic_getMassDensity, & - thermal_adiabatic_postResults + thermal_adiabatic_results contains @@ -48,53 +46,45 @@ contains !-------------------------------------------------------------------------------------------------- subroutine thermal_adiabatic_init - integer :: maxNinstance,section,instance,i,sizeState,NofMyHomog - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - character(len=65536), dimension(:), allocatable :: outputs + integer :: maxNinstance,o,h,NofMyHomog + character(len=pStringLen), dimension(:), allocatable :: outputs - write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_ADIABATIC_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_ADIABATIC_label//' init -+>>>'; flush(6) maxNinstance = count(thermal_type == THERMAL_adiabatic_ID) if (maxNinstance == 0) return - allocate(thermal_adiabatic_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0) - allocate(thermal_adiabatic_output (maxval(homogenization_Noutput),maxNinstance)) - thermal_adiabatic_output = '' - allocate(thermal_adiabatic_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) - allocate(thermal_adiabatic_Noutput (maxNinstance), source=0) - + allocate(param(maxNinstance)) - initializeInstances: do section = 1, size(thermal_type) - if (thermal_type(section) /= THERMAL_adiabatic_ID) cycle - NofMyHomog=count(material_homogenizationAt==section) - instance = thermal_typeInstance(section) - outputs = config_homogenization(section)%getStrings('(output)',defaultVal=emptyStringArray) - do i=1, size(outputs) - select case(outputs(i)) + do h = 1, size(thermal_type) + if (thermal_type(h) /= THERMAL_adiabatic_ID) cycle + associate(prm => param(thermal_typeInstance(h)),config => config_homogenization(h)) + + outputs = config%getStrings('(output)',defaultVal=emptyStringArray) + allocate(prm%outputID(0)) + + do o=1, size(outputs) + select case(outputs(o)) case('temperature') - thermal_adiabatic_Noutput(instance) = thermal_adiabatic_Noutput(instance) + 1 - thermal_adiabatic_outputID(thermal_adiabatic_Noutput(instance),instance) = temperature_ID - thermal_adiabatic_output(thermal_adiabatic_Noutput(instance),instance) = outputs(i) - thermal_adiabatic_sizePostResult(thermal_adiabatic_Noutput(instance),instance) = 1 + prm%outputID = [prm%outputID, temperature_ID] end select enddo + + NofMyHomog=count(material_homogenizationAt==h) + thermalState(h)%sizeState = 1 + allocate(thermalState(h)%state0 (1,NofMyHomog), source=thermal_initialT(h)) + allocate(thermalState(h)%subState0(1,NofMyHomog), source=thermal_initialT(h)) + allocate(thermalState(h)%state (1,NofMyHomog), source=thermal_initialT(h)) - ! allocate state arrays - sizeState = 1 - thermalState(section)%sizeState = sizeState - thermalState(section)%sizePostResults = sum(thermal_adiabatic_sizePostResult(:,instance)) - allocate(thermalState(section)%state0 (sizeState,NofMyHomog), source=thermal_initialT(section)) - allocate(thermalState(section)%subState0(sizeState,NofMyHomog), source=thermal_initialT(section)) - allocate(thermalState(section)%state (sizeState,NofMyHomog), source=thermal_initialT(section)) - - nullify(thermalMapping(section)%p) - thermalMapping(section)%p => mappingHomogenization(1,:,:) - deallocate(temperature(section)%p) - temperature(section)%p => thermalState(section)%state(1,:) - deallocate(temperatureRate(section)%p) - allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal) - - enddo initializeInstances + nullify(thermalMapping(h)%p) + thermalMapping(h)%p => mappingHomogenization(1,:,:) + deallocate(temperature(h)%p) + temperature(h)%p => thermalState(h)%state(1,:) + deallocate(temperatureRate(h)%p) + allocate (temperatureRate(h)%p(NofMyHomog), source=0.0_pReal) + + end associate + enddo end subroutine thermal_adiabatic_init @@ -252,32 +242,26 @@ end function thermal_adiabatic_getMassDensity !-------------------------------------------------------------------------------------------------- -!> @brief return array of thermal results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function thermal_adiabatic_postResults(homog,instance,of) result(postResults) - - integer, intent(in) :: & - homog, & - instance, & - of - - real(pReal), dimension(sum(thermal_adiabatic_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o, c - - c = 0 - - do o = 1,thermal_adiabatic_Noutput(instance) - select case(thermal_adiabatic_outputID(o,instance)) +subroutine thermal_adiabatic_results(homog,group) + + integer, intent(in) :: homog + character(len=*), intent(in) :: group + integer :: o - case (temperature_ID) - postResults(c+1) = temperature(homog)%p(of) - c = c + 1 - end select - enddo - -end function thermal_adiabatic_postResults + associate(prm => param(damage_typeInstance(homog))) + + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) + + case (temperature_ID) + call results_writeDataset(group,temperature(homog)%p,'T',& + 'temperature','K') + end select + enddo outputsLoop + end associate + +end subroutine thermal_adiabatic_results end module thermal_adiabatic diff --git a/src/thermal_conduction.f90 b/src/thermal_conduction.f90 index e513d709f..537b0366b 100644 --- a/src/thermal_conduction.f90 +++ b/src/thermal_conduction.f90 @@ -7,28 +7,27 @@ module thermal_conduction use material use config use lattice + use results use crystallite use source_thermal_dissipation use source_thermal_externalheat implicit none private - - integer, dimension(:,:), allocatable, target, public :: & - thermal_conduction_sizePostResult !< size of each post result output - character(len=64), dimension(:,:), allocatable, target, public :: & - thermal_conduction_output !< name of each post result output - - integer, dimension(:), allocatable, target, public :: & - thermal_conduction_Noutput !< number of outputs per instance of this damage - + enum, bind(c) - enumerator :: undefined_ID, & - temperature_ID + enumerator :: & + undefined_ID, & + temperature_ID end enum - integer(kind(undefined_ID)), dimension(:,:), allocatable, private :: & - thermal_conduction_outputID !< ID of each post result output - + + type :: tParameters + integer(kind(undefined_ID)), dimension(:), allocatable :: & + outputID + end type tParameters + + type(tparameters), dimension(:), allocatable :: & + param public :: & thermal_conduction_init, & @@ -37,7 +36,7 @@ module thermal_conduction thermal_conduction_getSpecificHeat, & thermal_conduction_getMassDensity, & thermal_conduction_putTemperatureAndItsRate, & - thermal_conduction_postResults + thermal_conduction_results contains @@ -49,56 +48,45 @@ contains subroutine thermal_conduction_init - integer :: maxNinstance,section,instance,i - integer :: sizeState - integer :: NofMyHomog - character(len=65536), dimension(0), parameter :: emptyStringArray = [character(len=65536)::] - character(len=65536), dimension(:), allocatable :: outputs + integer :: maxNinstance,o,NofMyHomog,h + character(len=pStringLen), dimension(:), allocatable :: outputs - write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_CONDUCTION_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_CONDUCTION_label//' init -+>>>'; flush(6) maxNinstance = count(thermal_type == THERMAL_conduction_ID) if (maxNinstance == 0) return - allocate(thermal_conduction_sizePostResult (maxval(homogenization_Noutput),maxNinstance),source=0) - allocate(thermal_conduction_output (maxval(homogenization_Noutput),maxNinstance)) - thermal_conduction_output = '' - allocate(thermal_conduction_outputID (maxval(homogenization_Noutput),maxNinstance),source=undefined_ID) - allocate(thermal_conduction_Noutput (maxNinstance), source=0) - + allocate(param(maxNinstance)) - initializeInstances: do section = 1, size(thermal_type) - if (thermal_type(section) /= THERMAL_conduction_ID) cycle - NofMyHomog=count(material_homogenizationAt==section) - instance = thermal_typeInstance(section) - outputs = config_homogenization(section)%getStrings('(output)',defaultVal=emptyStringArray) - do i=1, size(outputs) - select case(outputs(i)) + do h = 1, size(thermal_type) + if (thermal_type(h) /= THERMAL_conduction_ID) cycle + associate(prm => param(thermal_typeInstance(h)),config => config_homogenization(h)) + + outputs = config%getStrings('(output)',defaultVal=emptyStringArray) + allocate(prm%outputID(0)) + + do o=1, size(outputs) + select case(outputs(o)) case('temperature') - thermal_conduction_Noutput(instance) = thermal_conduction_Noutput(instance) + 1 - thermal_conduction_outputID(thermal_conduction_Noutput(instance),instance) = temperature_ID - thermal_conduction_output(thermal_conduction_Noutput(instance),instance) = outputs(i) - thermal_conduction_sizePostResult(thermal_conduction_Noutput(instance),instance) = 1 + prm%outputID = [prm%outputID, temperature_ID] end select enddo + + NofMyHomog=count(material_homogenizationAt==h) + thermalState(h)%sizeState = 0 + allocate(thermalState(h)%state0 (0,NofMyHomog)) + allocate(thermalState(h)%subState0(0,NofMyHomog)) + allocate(thermalState(h)%state (0,NofMyHomog)) - - ! allocate state arrays - sizeState = 0 - thermalState(section)%sizeState = sizeState - thermalState(section)%sizePostResults = sum(thermal_conduction_sizePostResult(:,instance)) - allocate(thermalState(section)%state0 (sizeState,NofMyHomog)) - allocate(thermalState(section)%subState0(sizeState,NofMyHomog)) - allocate(thermalState(section)%state (sizeState,NofMyHomog)) - - nullify(thermalMapping(section)%p) - thermalMapping(section)%p => mappingHomogenization(1,:,:) - deallocate(temperature (section)%p) - allocate (temperature (section)%p(NofMyHomog), source=thermal_initialT(section)) - deallocate(temperatureRate(section)%p) - allocate (temperatureRate(section)%p(NofMyHomog), source=0.0_pReal) - - enddo initializeInstances + nullify(thermalMapping(h)%p) + thermalMapping(h)%p => mappingHomogenization(1,:,:) + deallocate(temperature (h)%p) + allocate (temperature (h)%p(NofMyHomog), source=thermal_initialT(h)) + deallocate(temperatureRate(h)%p) + allocate (temperatureRate(h)%p(NofMyHomog), source=0.0_pReal) + + end associate + enddo end subroutine thermal_conduction_init @@ -213,7 +201,8 @@ function thermal_conduction_getSpecificHeat(ip,el) thermal_conduction_getSpecificHeat/real(homogenization_Ngrains(material_homogenizationAt(el)),pReal) end function thermal_conduction_getSpecificHeat - + + !-------------------------------------------------------------------------------------------------- !> @brief returns homogenized mass density !-------------------------------------------------------------------------------------------------- @@ -263,33 +252,28 @@ subroutine thermal_conduction_putTemperatureAndItsRate(T,Tdot,ip,el) end subroutine thermal_conduction_putTemperatureAndItsRate - + !-------------------------------------------------------------------------------------------------- -!> @brief return array of thermal results +!> @brief writes results to HDF5 output file !-------------------------------------------------------------------------------------------------- -function thermal_conduction_postResults(homog,instance,of) result(postResults) - - integer, intent(in) :: & - homog, & - instance, & - of - - real(pReal), dimension(sum(thermal_conduction_sizePostResult(:,instance))) :: & - postResults - - integer :: & - o, c - - c = 0 - do o = 1,thermal_conduction_Noutput(instance) - select case(thermal_conduction_outputID(o,instance)) +subroutine thermal_conduction_results(homog,group) + + integer, intent(in) :: homog + character(len=*), intent(in) :: group + integer :: o - case (temperature_ID) - postResults(c+1) = temperature(homog)%p(of) - c = c + 1 - end select - enddo - -end function thermal_conduction_postResults + associate(prm => param(damage_typeInstance(homog))) + + outputsLoop: do o = 1,size(prm%outputID) + select case(prm%outputID(o)) + + case (temperature_ID) + call results_writeDataset(group,temperature(homog)%p,'T',& + 'temperature','K') + end select + enddo outputsLoop + end associate + +end subroutine thermal_conduction_results end module thermal_conduction diff --git a/src/thermal_isothermal.f90 b/src/thermal_isothermal.f90 index f06239944..3cafc6402 100644 --- a/src/thermal_isothermal.f90 +++ b/src/thermal_isothermal.f90 @@ -3,7 +3,6 @@ !> @brief material subroutine for isothermal temperature field !-------------------------------------------------------------------------------------------------- module thermal_isothermal - use prec use config use material @@ -20,27 +19,25 @@ contains !-------------------------------------------------------------------------------------------------- subroutine thermal_isothermal_init - integer :: & - homog, & - NofMyHomog + integer :: h,NofMyHomog - write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_isothermal_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- thermal_'//THERMAL_isothermal_label//' init -+>>>'; flush(6) - initializeInstances: do homog = 1, material_Nhomogenization - - if (thermal_type(homog) /= THERMAL_isothermal_ID) cycle - NofMyHomog = count(material_homogenizationAt == homog) - thermalState(homog)%sizeState = 0 - allocate(thermalState(homog)%state0 (0,NofMyHomog), source=0.0_pReal) - allocate(thermalState(homog)%subState0(0,NofMyHomog), source=0.0_pReal) - allocate(thermalState(homog)%state (0,NofMyHomog), source=0.0_pReal) + do h = 1, size(config_homogenization) + if (thermal_type(h) /= THERMAL_isothermal_ID) cycle + + NofMyHomog = count(material_homogenizationAt == h) + thermalState(h)%sizeState = 0 + allocate(thermalState(h)%state0 (0,NofMyHomog)) + allocate(thermalState(h)%subState0(0,NofMyHomog)) + allocate(thermalState(h)%state (0,NofMyHomog)) - deallocate(temperature (homog)%p) - allocate (temperature (homog)%p(1), source=thermal_initialT(homog)) - deallocate(temperatureRate(homog)%p) - allocate (temperatureRate(homog)%p(1), source=0.0_pReal) + deallocate(temperature (h)%p) + allocate (temperature (h)%p(1), source=thermal_initialT(h)) + deallocate(temperatureRate(h)%p) + allocate (temperatureRate(h)%p(1)) - enddo initializeInstances + enddo end subroutine thermal_isothermal_init