From 0f2e22805a7d7c3fdd70a363d89faa26b3a99b77 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 10 Nov 2016 06:53:47 +0100 Subject: [PATCH 01/32] deallocate "axes" shuffling of orientation information --- code/material.f90 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/code/material.f90 b/code/material.f90 index e1a48bc1c..bd2bf3cda 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -1586,13 +1586,8 @@ subroutine material_populateGrains deallocate(phaseOfGrain) deallocate(textureOfGrain) deallocate(orientationOfGrain) + deallocate(texture_transformation) deallocate(Nelems) - !> @todo - causing segmentation fault: needs looking into - !do homog = 1,material_Nhomogenization - ! do micro = 1,material_Nmicrostructure - ! if (Nelems(homog,micro) > 0_pInt) deallocate(elemsOfHomogMicro(homog,micro)%p) - ! enddo - !enddo deallocate(elemsOfHomogMicro) end subroutine material_populateGrains From 08d9f0a4f351f0192534906e443e24c7ced3921e Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 16 Nov 2016 22:08:19 +0100 Subject: [PATCH 02/32] texture transformation should be a proper rotation at least, until the implications of using improper rotations are clear... --- code/material.f90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/material.f90 b/code/material.f90 index bd2bf3cda..cd1d21808 100644 --- a/code/material.f90 +++ b/code/material.f90 @@ -1051,6 +1051,8 @@ end subroutine material_parsePhase !> @brief parses the texture part in the material configuration file !-------------------------------------------------------------------------------------------------- subroutine material_parseTexture(fileUnit,myPart) + use prec, only: & + dNeq use IO, only: & IO_read, & IO_globalTagInPart, & @@ -1069,6 +1071,7 @@ subroutine material_parseTexture(fileUnit,myPart) inRad, & math_sampleRandomOri, & math_I3, & + math_det33, & math_inv33 implicit none @@ -1154,6 +1157,9 @@ subroutine material_parseTexture(fileUnit,myPart) end select enddo + if(dNeq(math_det33(texture_transformation(1:3,1:3,section)),1.0_pReal)) & + call IO_error(157_pInt,section) + case ('hybridia') textureType texture_ODFfile(section) = IO_stringValue(line,chunkPos,2_pInt) From 1346efbef00e78ae2b62528843acc60802728232 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 16 Nov 2016 12:15:01 +0100 Subject: [PATCH 03/32] pyeuclid moved from google code to github --- lib/damask/orientation.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index ef1d8be22..101841ce4 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -744,27 +744,27 @@ class Symmetry: if self.lattice == 'cubic': basis = {'improper':np.array([ [-1. , 0. , 1. ], - [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], - [ 0. , np.sqrt(3.) , 0. ] ]), + [ np.sqrt(2.) , -np.sqrt(2.) , 0. ], + [ 0. , np.sqrt(3.) , 0. ] ]), 'proper':np.array([ [ 0. , -1. , 1. ], - [-np.sqrt(2.) , np.sqrt(2.) , 0. ], - [ np.sqrt(3. ) , 0. , 0. ] ]), + [-np.sqrt(2.) , np.sqrt(2.) , 0. ], + [ np.sqrt(3.) , 0. , 0. ] ]), } elif self.lattice == 'hexagonal': basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -np.sqrt(3.) , 0. ], - [ 0. , 2. , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , np.sqrt(3.) , 0. ], - [ np.sqrt(3) , -1. , 0. ] ]), + [ 1. , -np.sqrt(3.) , 0. ], + [ 0. , 2. , 0. ] ]), + 'proper':np.array([ [ 0. , 0. , 1. ], + [-1. , np.sqrt(3.) , 0. ], + [ np.sqrt(3.) , -1. , 0. ] ]), } elif self.lattice == 'tetragonal': basis = {'improper':np.array([ [ 0. , 0. , 1. ], - [ 1. , -1. , 0. ], - [ 0. , np.sqrt(2.) , 0. ] ]), - 'proper':np.array([ [ 0. , 0. , 1. ], - [-1. , 1. , 0. ], - [ np.sqrt(2.) , 0. , 0. ] ]), + [ 1. , -1. , 0. ], + [ 0. , np.sqrt(2.) , 0. ] ]), + 'proper':np.array([ [ 0. , 0. , 1. ], + [-1. , 1. , 0. ], + [ np.sqrt(2.) , 0. , 0. ] ]), } elif self.lattice == 'orthorhombic': basis = {'improper':np.array([ [ 0., 0., 1.], @@ -806,7 +806,7 @@ class Symmetry: else: return inSST -# code derived from http://pyeuclid.googlecode.com/svn/trunk/euclid.py +# code derived from https://github.com/ezag/pyeuclid # suggested reading: http://web.mit.edu/2.998/www/QuaternionReport1.pdf From b128b15abf4f2e5c6a82c172bb851d83692837c5 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Wed, 16 Nov 2016 12:28:38 +0100 Subject: [PATCH 04/32] fixed strange behavior for inSST without given symmetry np.all() on dict (with keys 'proper' and 'improper') always returns 'False', and not, as (most likely) intended 'True' in the case of no symmetry. Removed this comparison and simply setting inSST=False for no symmetry, color will be (0,0,0) in that case --- lib/damask/orientation.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index 101841ce4..655f5cbba 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -774,26 +774,23 @@ class Symmetry: [-1., 0., 0.], [ 0., 1., 0.] ]), } - else: - basis = {'improper': np.zeros((3,3),dtype=float), - 'proper': np.zeros((3,3),dtype=float), - } + else: # direct exit for unspecified symmetry + if color: + return (True,np.zeros(3,'d')) + else: + return True - if np.all(basis == 0.0): - theComponents = -np.ones(3,'d') + v = np.array(vector,dtype = float) + if proper: # check both improper ... + theComponents = np.dot(basis['improper'],v) inSST = np.all(theComponents >= 0.0) - else: - v = np.array(vector,dtype = float) - if proper: # check both improper ... - theComponents = np.dot(basis['improper'],v) - inSST = np.all(theComponents >= 0.0) - if not inSST: # ... and proper SST - theComponents = np.dot(basis['proper'],v) - 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 + if not inSST: # ... and proper SST + theComponents = np.dot(basis['proper'],v) 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 + inSST = np.all(theComponents >= 0.0) if color: # have to return color array if inSST: From ad14f527565c87d3c0a350560344cd68953f17bc Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 17 Nov 2016 04:40:12 +0100 Subject: [PATCH 05/32] updated version information after successful test of v2.0.1-311-gb128b15 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 8e45698bd..db558a42a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-306-g2d0193e +v2.0.1-311-gb128b15 From 1c68cf1fd31b28001ab480a9898cc99f3982b256 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Mon, 21 Nov 2016 21:06:52 +0100 Subject: [PATCH 06/32] using cubic symmetry as default for orientation relationships --- lib/damask/orientation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index 655f5cbba..0ef6725cf 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -993,7 +993,7 @@ class Orientation: def related(self, relationModel, direction, - targetSymmetry = None): + targetSymmetry = 'cubic'): """ Orientation relationship @@ -1241,4 +1241,4 @@ class Orientation: rot=np.dot(otherMatrix,myMatrix.T) - return Orientation(matrix=np.dot(rot,self.asMatrix())) # no symmetry information ?? + return Orientation(matrix=np.dot(rot,self.asMatrix()),symmetry=targetSymmetry) From 03262429a7885781b9d7dbd4b08d07dd3306ba08 Mon Sep 17 00:00:00 2001 From: Test User Date: Tue, 22 Nov 2016 04:34:05 +0100 Subject: [PATCH 07/32] updated version information after successful test of v2.0.1-313-g1c68cf1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index db558a42a..08b2fee0c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-311-gb128b15 +v2.0.1-313-g1c68cf1 From dc988dd6b1f3a5d8d060e0ab5ec658ef62c7faf6 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 24 Nov 2016 09:37:27 -0500 Subject: [PATCH 08/32] removed unneccesary line continuation --- lib/damask/asciitable.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 4710686b2..947a5a2e0 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -513,14 +513,15 @@ class ASCIItable(): columns = [] for i,(c,d) in enumerate(zip(indices[present],dimensions[present])): # for all valid labels ... # ... transparently add all components unless column referenced by number or with explicit dimension - columns += list(range(c,c + \ - (d if str(c) != str(labels[present[i]]) else \ + columns += list(range(c,c + + (d if str(c) != str(labels[present[i]]) else 1))) use = np.array(columns) if len(columns) > 0 else None self.tags = list(np.array(self.tags)[use]) # update labels with valid subset self.data = np.loadtxt(self.__IO__['in'],usecols=use,ndmin=2) +# self.data = np.genfromtxt(self.__IO__['in'],dtype=None,names=self.tags,usecols=use) return labels_missing From c3f58fd208ae48c70be404ba694743abcae56a27 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 24 Nov 2016 09:37:57 -0500 Subject: [PATCH 09/32] unified processing order of quaternion properties to w,x,y,z --- lib/damask/orientation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/damask/orientation.py b/lib/damask/orientation.py index 0ef6725cf..7d97d2c81 100644 --- a/lib/damask/orientation.py +++ b/lib/damask/orientation.py @@ -137,18 +137,18 @@ class Quaternion: def __imul__(self, other): """In-place multiplication""" try: # Quaternion + Aw = self.w Ax = self.x Ay = self.y Az = self.z - Aw = self.w + Bw = other.w Bx = other.x By = other.y Bz = other.z - Bw = other.w - self.x = Ax * Bw + Ay * Bz - Az * By + Aw * Bx - self.y = -Ax * Bz + Ay * Bw + Az * Bx + Aw * By - self.z = Ax * By - Ay * Bx + Az * Bw + Aw * Bz - self.w = -Ax * Bx - Ay * By - Az * Bz + Aw * Bw + self.w = - Ax * Bx - Ay * By - Az * Bz + Aw * Bw + self.x = + Ax * Bw + Ay * Bz - Az * By + Aw * Bx + self.y = - Ax * Bz + Ay * Bw + Az * Bx + Aw * By + self.z = + Ax * By - Ay * Bx + Az * Bw + Aw * Bz except: pass return self From d6baa71ee4957d52e045a16ed0c0b43a5e6fc253 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 24 Nov 2016 09:51:21 -0500 Subject: [PATCH 10/32] added temporary patch for PETSc 3.7.x compatibility apply with "patch -p1 < installation/patch/petsc3.7" --- installation/patch/petsc3.7 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 installation/patch/petsc3.7 diff --git a/installation/patch/petsc3.7 b/installation/patch/petsc3.7 new file mode 100644 index 000000000..b5fd696fb --- /dev/null +++ b/installation/patch/petsc3.7 @@ -0,0 +1,22 @@ +diff --git a/code/spectral_utilities.f90 b/code/spectral_utilities.f90 +index 34eb0ea..a33c7a9 100644 +--- a/code/spectral_utilities.f90 ++++ b/code/spectral_utilities.f90 +@@ -227,12 +227,13 @@ subroutine utilities_init() + trim(PETScDebug), & + ' add more using the PETSc_Options keyword in numerics.config '; flush(6) + +- call PetscOptionsClear(ierr); CHKERRQ(ierr) +- if(debugPETSc) call PetscOptionsInsertString(trim(PETSCDEBUG),ierr) ++ call PetscOptionsClear(PETSC_NULL_OBJECT,ierr) + CHKERRQ(ierr) +- call PetscOptionsInsertString(trim(petsc_defaultOptions),ierr) ++ if(debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OBJECT,trim(PETSCDEBUG),ierr) + CHKERRQ(ierr) +- call PetscOptionsInsertString(trim(petsc_options),ierr) ++ call PetscOptionsInsertString(PETSC_NULL_OBJECT,trim(petsc_defaultOptions),ierr) ++ CHKERRQ(ierr) ++ call PetscOptionsInsertString(PETSC_NULL_OBJECT,trim(petsc_options),ierr) + CHKERRQ(ierr) + + grid1Red = grid(1)/2_pInt + 1_pInt From 3fd8fb9f14c881bb6d8e8ee6b828a7f5a977350f Mon Sep 17 00:00:00 2001 From: Test User Date: Fri, 25 Nov 2016 04:40:34 +0100 Subject: [PATCH 11/32] updated version information after successful test of v2.0.1-317-gd6baa71 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 08b2fee0c..badc23c91 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-313-g1c68cf1 +v2.0.1-317-gd6baa71 From c9ec2e0f460cb624613a8936f9eaabfc1a798d23 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 09:29:26 -0500 Subject: [PATCH 12/32] New table mapping based on shared column values renamed old addMapped to addRowMapped to better reflect true functionality. --- .../post/{addMapped.py => addRowMapped.py} | 11 +- processing/post/addValueMapped.py | 108 ++++++++++++++++++ 2 files changed, 113 insertions(+), 6 deletions(-) rename processing/post/{addMapped.py => addRowMapped.py} (92%) create mode 100755 processing/post/addValueMapped.py diff --git a/processing/post/addMapped.py b/processing/post/addRowMapped.py similarity index 92% rename from processing/post/addMapped.py rename to processing/post/addRowMapped.py index f67d88d15..16250aa1f 100755 --- a/processing/post/addMapped.py +++ b/processing/post/addRowMapped.py @@ -14,14 +14,14 @@ scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add data in column(s) of second ASCIItable selected from row that is given by the value in a mapping column. +Add data in column(s) of second ASCIItable selected from the row indexed by the value in a mapping column. """, version = scriptID) parser.add_option('-c','--map', dest = 'map', type = 'string', metavar = 'string', - help = 'heading of column containing row mapping') + help = 'column label containing row mapping') parser.add_option('-o','--offset', dest = 'offset', type = 'int', metavar = 'int', @@ -29,11 +29,11 @@ parser.add_option('-o','--offset', parser.add_option('-l','--label', dest = 'label', action = 'extend', metavar = '', - help='column label(s) to be mapped') + help='column label(s) to be appended') parser.add_option('-a','--asciitable', dest = 'asciitable', type = 'string', metavar = 'string', - help = 'mapped ASCIItable') + help = 'indexed ASCIItable') parser.set_defaults(offset = 0, ) @@ -54,6 +54,7 @@ if options.asciitable is not None and os.path.isfile(options.asciitable): readonly = True) mappedTable.head_read() # read ASCII header info of mapped table missing_labels = mappedTable.data_readArray(options.label) + mappedTable.close() # close mapped input ASCII table if len(missing_labels) > 0: damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) @@ -106,5 +107,3 @@ for name in filenames: # ------------------------------------------ output finalization ----------------------------------- table.close() # close ASCII tables - -mappedTable.close() # close mapped input ASCII table diff --git a/processing/post/addValueMapped.py b/processing/post/addValueMapped.py new file mode 100755 index 000000000..cd0f50d0d --- /dev/null +++ b/processing/post/addValueMapped.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python2.7 +# -*- coding: UTF-8 no BOM -*- + +import os,sys +import numpy as np +from optparse import OptionParser +import damask + +scriptName = os.path.splitext(os.path.basename(__file__))[0] +scriptID = ' '.join([scriptName,damask.version]) + +# -------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------- + +parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ +Add data of selected column(s) from (first) row of second ASCIItable that shares the mapping column value. + +""", version = scriptID) + +parser.add_option('-c','--map', + dest = 'map', nargs = 2, + type = 'string', metavar = 'string string', + help = 'column labels containing linked values') +parser.add_option('-l','--label', + dest = 'label', + action = 'extend', metavar = '', + help='column label(s) to be appended') +parser.add_option('-a','--asciitable', + dest = 'asciitable', + type = 'string', metavar = 'string', + help = 'indexed ASCIItable') + +parser.set_defaults() + +(options,filenames) = parser.parse_args() + +if options.label is None: + parser.error('no data columns specified.') +if options.map is None: + parser.error('no mapping columns given.') + +# ------------------------------------------ process mapping ASCIItable --------------------------- + +if options.asciitable is not None and os.path.isfile(options.asciitable): + + mappedTable = damask.ASCIItable(name = options.asciitable, + buffered = False, + readonly = True) + mappedTable.head_read() # read ASCII header info of mapped table + if mappedTable.label_dimension(options.map[1]) != 1: + parser.error('mapping column {} needs to be scalar valued.'.format(options.map[1])) + + missing_labels = mappedTable.data_readArray([options.map[1]]+options.label) + mappedTable.close() # close mapped input ASCII table + + if len(missing_labels) > 0: + damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) + +else: + parser.error('no indexed ASCIItable given.') + +# --- 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 = [] + + mappedColumn = table.label_index(options.map[0]) + if mappedColumn < 0: errors.append('mapping column {} not found.'.format(options.map[0])) + + if errors != []: + damask.util.croak(errors) + table.close(dismiss = True) + continue + +# ------------------------------------------ assemble header -------------------------------------- + + table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) + table.labels_append(mappedTable.labels(raw = True)[1:]) # extend with new labels (except for mapped column) + table.head_write() + +# ------------------------------------------ process data ------------------------------------------ + + outputAlive = True + while outputAlive and table.data_read(): # read next data line of ASCII table + try: + table.data_append(mappedTable.data[np.argwhere(mappedTable.data[:,0] == + float(table.data[mappedColumn]))[0]]) # add data from first matching line + except IndexError: + table.data_append(np.nan*np.ones_like(mappedTable.data[0])) # or add NaNs + outputAlive = table.data_write() # output processed line + +# ------------------------------------------ output finalization ----------------------------------- + + table.close() # close ASCII tables From 94c934c8bdd0964f25334146e4eeb5881357513d Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 09:52:14 -0500 Subject: [PATCH 13/32] added patch to switch to fwbw_derivative --- installation/patch/README.md | 17 +++++++++++++++++ installation/patch/fwbw_derivative | 13 +++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 installation/patch/README.md create mode 100644 installation/patch/fwbw_derivative diff --git a/installation/patch/README.md b/installation/patch/README.md new file mode 100644 index 000000000..17fe041c4 --- /dev/null +++ b/installation/patch/README.md @@ -0,0 +1,17 @@ +# DAMASK patching + +This folder contains patches that modify the functionality of the current version of DAMASK prior to the corresponding inclusion in the official release. + +## Usage + +```bash +cd DAMASK_ROOT +patch -p1 installation/patch/nameOfPatch +``` + +## Available patches + + * **fwbw_derivative** switches the default spatial derivative from continuous to forward/backward difference. + This generally reduces spurious oscillations in the result as the spatial accuracy of the derivative is then compatible with the underlying solution grid. + * **petsc3.7** adapts to API changes introduced between PETSc 3.6.x and 3.7.x for setting PETSc options. + Use this patch if your system runs PETSc 3.7.x. diff --git a/installation/patch/fwbw_derivative b/installation/patch/fwbw_derivative new file mode 100644 index 000000000..03d5be1c6 --- /dev/null +++ b/installation/patch/fwbw_derivative @@ -0,0 +1,13 @@ +diff --git a/code/numerics.f90 b/code/numerics.f90 +index 24bd190..c968c70 100644 +--- a/code/numerics.f90 ++++ b/code/numerics.f90 +@@ -110,7 +110,7 @@ module numerics + fftw_plan_mode = 'FFTW_PATIENT' !< reads the planing-rigor flag, see manual on www.fftw.org, Default FFTW_PATIENT: use patient planner flag + character(len=64), protected, public :: & + spectral_solver = 'basicpetsc' , & !< spectral solution method +- spectral_derivative = 'continuous' !< spectral spatial derivative method ++ spectral_derivative = 'fwbw_difference' !< spectral spatial derivative method + character(len=1024), protected, public :: & + petsc_defaultOptions = '-mech_snes_type ngmres & + &-damage_snes_type ngmres & From 20c5ccc112c392ef32dbe76bd575e5fa4c792468 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 10:02:07 -0500 Subject: [PATCH 14/32] corrected (my standard) mistake in README --- installation/patch/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation/patch/README.md b/installation/patch/README.md index 17fe041c4..86ed44f0d 100644 --- a/installation/patch/README.md +++ b/installation/patch/README.md @@ -6,7 +6,7 @@ This folder contains patches that modify the functionality of the current versio ```bash cd DAMASK_ROOT -patch -p1 installation/patch/nameOfPatch +patch -p1 < installation/patch/nameOfPatch ``` ## Available patches From 231f05e1429c9e74269752740acd4e6263c8864d Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 11:16:50 -0500 Subject: [PATCH 15/32] corrected bug that added index column values as first output --- processing/post/addValueMapped.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/processing/post/addValueMapped.py b/processing/post/addValueMapped.py index cd0f50d0d..852ce10b0 100755 --- a/processing/post/addValueMapped.py +++ b/processing/post/addValueMapped.py @@ -57,6 +57,8 @@ if options.asciitable is not None and os.path.isfile(options.asciitable): if len(missing_labels) > 0: damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) + index = mappedTable.data[:,0] + data = mappedTable.data[:,1:] else: parser.error('no indexed ASCIItable given.') @@ -90,6 +92,7 @@ for name in filenames: table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) table.labels_append(mappedTable.labels(raw = True)[1:]) # extend with new labels (except for mapped column) + table.head_write() # ------------------------------------------ process data ------------------------------------------ @@ -97,10 +100,9 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table try: - table.data_append(mappedTable.data[np.argwhere(mappedTable.data[:,0] == - float(table.data[mappedColumn]))[0]]) # add data from first matching line + table.data_append(data[np.argwhere(index == float(table.data[mappedColumn]))[0]]) # add data from first matching line except IndexError: - table.data_append(np.nan*np.ones_like(mappedTable.data[0])) # or add NaNs + table.data_append(np.nan*np.ones_like(data[0])) # or add NaNs outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- From 7ebd688885039562570493aa4ed697b2af728d39 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 14:35:30 -0500 Subject: [PATCH 16/32] return type-safe indexrange (for invalid queries) --- lib/damask/asciitable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/damask/asciitable.py b/lib/damask/asciitable.py index 947a5a2e0..771ae76a5 100644 --- a/lib/damask/asciitable.py +++ b/lib/damask/asciitable.py @@ -427,8 +427,8 @@ class ASCIItable(): start = self.label_index(labels) dim = self.label_dimension(labels) - return np.hstack([range(c[0],c[0]+c[1]) for c in zip(start,dim)]) \ - if isinstance(labels, Iterable) and not isinstance(labels, str) \ + return np.hstack([range(s,s+d) for s,d in zip(start,dim)]).astype(int) \ + if isinstance(labels, Iterable) and not isinstance(labels, str) \ else range(start,start+dim) # ------------------------------------------------------------------ From 43c18801954693e0130f27b708e48812725131f5 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 14:37:43 -0500 Subject: [PATCH 17/32] fixed periodic averaging to work with multi-dimensional data option --periodic now takes list of labels that undergo periodoc domain averaging, i.e. incompatible to former API! --- processing/post/groupTable.py | 42 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/processing/post/groupTable.py b/processing/post/groupTable.py index a1205eff4..67d07a7d1 100755 --- a/processing/post/groupTable.py +++ b/processing/post/groupTable.py @@ -7,14 +7,11 @@ import numpy as np from optparse import OptionParser, OptionGroup import damask -#"https://en.wikipedia.org/wiki/Center_of_mass#Systems_with_periodic_boundary_conditions" -def periodicAverage(Points, Box): - theta = (Points/Box[1]) * (2.0*np.pi) - xi = np.cos(theta) - zeta = np.sin(theta) - theta_avg = np.arctan2(-1.0*zeta.mean(), -1.0*xi.mean()) + np.pi - Pmean = Box[1] * theta_avg/(2.0*np.pi) - return Pmean +def periodicAverage(coords, limits): + """Centroid in periodic domain, see https://en.wikipedia.org/wiki/Center_of_mass#Systems_with_periodic_boundary_conditions""" + theta = 2.0*np.pi * (coords - limits[0])/(limits[1] - limits[0]) + theta_avg = np.pi + np.arctan2(-np.sin(theta).mean(axis=0), -np.cos(theta).mean(axis=0)) + return limits[0] + theta_avg * (limits[1] - limits[0])/2.0/np.pi scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -26,6 +23,7 @@ scriptID = ' '.join([scriptName,damask.version]) parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ Apply a user-specified function to condense all rows for which column 'label' has identical values into a single row. Output table will contain as many rows as there are different (unique) values in the grouping column. +Periodic domain averaging of coordinate values is supported. Examples: For grain averaged values, replace all rows of particular 'texture' with a single row containing their average. @@ -43,23 +41,22 @@ parser.add_option('-a','--all', dest = 'all', action = 'store_true', help = 'apply mapping function also to grouping column') - + group = OptionGroup(parser, "periodic averaging", "") -group.add_option('-p','--periodic', - dest = 'periodic', - action = 'store_true', - help = 'calculate average in periodic space defined by periodic length [%default]') -group.add_option('--boundary', - dest = 'boundary', metavar = 'MIN MAX', - type = 'float', nargs = 2, - help = 'define periodic box end points %default') +group.add_option ('-p','--periodic', + dest = 'periodic', + action = 'extend', metavar = '', + help = 'coordinate label(s) to average across periodic domain') +group.add_option ('--limits', + dest = 'boundary', + type = 'float', metavar = 'float float', nargs = 2, + help = 'min and max of periodic domain %default') parser.add_option_group(group) parser.set_defaults(function = 'np.average', all = False, - periodic = False, boundary = [0.0, 1.0]) (options,filenames) = parser.parse_args() @@ -108,6 +105,7 @@ for name in filenames: # ------------------------------------------ process data -------------------------------- table.data_readArray() + indexrange = table.label_indexrange(options.periodic) if options.periodic is not None else [] rows,cols = table.data.shape table.data = table.data[np.lexsort([table.data[:,grpColumn]])] # sort data by grpColumn @@ -117,10 +115,10 @@ for name in filenames: grpTable = np.empty((len(values), cols)) # initialize output for i in range(len(values)): # iterate over groups (unique values in grpColumn) - if options.periodic : - grpTable[i] = periodicAverage(table.data[index[i]:index[i+1]],options.boundary) # apply periodicAverage mapping function - else : - grpTable[i] = np.apply_along_axis(mapFunction,0,table.data[index[i]:index[i+1]]) # apply mapping function + grpTable[i] = np.apply_along_axis(mapFunction,0,table.data[index[i]:index[i+1]]) # apply (general) mapping function + grpTable[i,indexrange] = \ + periodicAverage(table.data[index[i]:index[i+1],indexrange],options.boundary) # apply periodicAverage mapping function + if not options.all: grpTable[i,grpColumn] = table.data[index[i],grpColumn] # restore grouping column value table.data = grpTable From 0f04ddd88ea1eba43427648c69e971a05fc3eccf Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 14:44:34 -0500 Subject: [PATCH 18/32] polishing of whitespace, usage help, etc. --- processing/post/addRowMapped.py | 4 ++-- processing/post/addValueMapped.py | 2 +- processing/post/filterTable.py | 5 ++--- processing/post/vtk_pointcloud.py | 7 +++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/processing/post/addRowMapped.py b/processing/post/addRowMapped.py index 16250aa1f..d9d51e2aa 100755 --- a/processing/post/addRowMapped.py +++ b/processing/post/addRowMapped.py @@ -29,7 +29,7 @@ parser.add_option('-o','--offset', parser.add_option('-l','--label', dest = 'label', action = 'extend', metavar = '', - help='column label(s) to be appended') + help = 'column label(s) to be appended') parser.add_option('-a','--asciitable', dest = 'asciitable', type = 'string', metavar = 'string', @@ -60,7 +60,7 @@ if options.asciitable is not None and os.path.isfile(options.asciitable): damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) else: - parser.error('no mapped ASCIItable given.') + parser.error('no indexed ASCIItable given.') # --- loop over input files ------------------------------------------------------------------------- diff --git a/processing/post/addValueMapped.py b/processing/post/addValueMapped.py index 852ce10b0..65568b2c7 100755 --- a/processing/post/addValueMapped.py +++ b/processing/post/addValueMapped.py @@ -25,7 +25,7 @@ parser.add_option('-c','--map', parser.add_option('-l','--label', dest = 'label', action = 'extend', metavar = '', - help='column label(s) to be appended') + help = 'column label(s) to be appended') parser.add_option('-a','--asciitable', dest = 'asciitable', type = 'string', metavar = 'string', diff --git a/processing/post/filterTable.py b/processing/post/filterTable.py index 231c52960..52d23194b 100755 --- a/processing/post/filterTable.py +++ b/processing/post/filterTable.py @@ -61,9 +61,8 @@ parser.set_defaults(condition = '', if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False) + try: table = damask.ASCIItable(name = name, + buffered = False) except: continue damask.util.report(scriptName,name) diff --git a/processing/post/vtk_pointcloud.py b/processing/post/vtk_pointcloud.py index 339ff2c17..5779b7540 100755 --- a/processing/post/vtk_pointcloud.py +++ b/processing/post/vtk_pointcloud.py @@ -34,10 +34,9 @@ parser.set_defaults(pos = 'pos', if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, - readonly = True) + try: table = damask.ASCIItable(name = name, + buffered = False, + readonly = True) except: continue damask.util.report(scriptName,name) From 814b05e2f625b4a76fdd51b47fb5b657847a16a3 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 16:30:07 -0500 Subject: [PATCH 19/32] renamed to hopefully clearer express functionality --- .../post/{addRowMapped.py => addIndexed.py} | 39 ++++++++--------- .../post/{addValueMapped.py => addLinked.py} | 42 +++++++++---------- 2 files changed, 41 insertions(+), 40 deletions(-) rename processing/post/{addRowMapped.py => addIndexed.py} (70%) rename processing/post/{addValueMapped.py => addLinked.py} (72%) diff --git a/processing/post/addRowMapped.py b/processing/post/addIndexed.py similarity index 70% rename from processing/post/addRowMapped.py rename to processing/post/addIndexed.py index d9d51e2aa..a713ac4f5 100755 --- a/processing/post/addRowMapped.py +++ b/processing/post/addIndexed.py @@ -14,18 +14,19 @@ scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add data in column(s) of second ASCIItable selected from the row indexed by the value in a mapping column. +Add data in column(s) of mapped ASCIItable selected from the row indexed by the value in a mapping column. +Row numbers start at 1. """, version = scriptID) -parser.add_option('-c','--map', - dest = 'map', +parser.add_option('--index', + dest = 'index', type = 'string', metavar = 'string', - help = 'column label containing row mapping') + help = 'column label containing row index') parser.add_option('-o','--offset', dest = 'offset', type = 'int', metavar = 'int', - help = 'offset between mapping column value and actual row in mapped table [%default]') + help = 'constant offset for index column value [%default]') parser.add_option('-l','--label', dest = 'label', action = 'extend', metavar = '', @@ -42,19 +43,19 @@ parser.set_defaults(offset = 0, if options.label is None: parser.error('no data columns specified.') -if options.map is None: - parser.error('no mapping column given.') +if options.index is None: + parser.error('no index column given.') -# ------------------------------------------ process mapping ASCIItable --------------------------- +# ------------------------------------------ process indexed ASCIItable --------------------------- if options.asciitable is not None and os.path.isfile(options.asciitable): - mappedTable = damask.ASCIItable(name = options.asciitable, - buffered = False, - readonly = True) - mappedTable.head_read() # read ASCII header info of mapped table - missing_labels = mappedTable.data_readArray(options.label) - mappedTable.close() # close mapped input ASCII table + indexedTable = damask.ASCIItable(name = options.asciitable, + buffered = False, + readonly = True) + indexedTable.head_read() # read ASCII header info of indexed table + missing_labels = indexedTable.data_readArray(options.label) + indexedTable.close() # close input ASCII table if len(missing_labels) > 0: damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) @@ -80,8 +81,8 @@ for name in filenames: errors = [] - mappedColumn = table.label_index(options.map) - if mappedColumn < 0: errors.append('mapping column {} not found.'.format(options.map)) + indexColumn = table.label_index(options.index) + if indexColumn < 0: errors.append('index column {} not found.'.format(options.index)) if errors != []: damask.util.croak(errors) @@ -91,7 +92,7 @@ for name in filenames: # ------------------------------------------ assemble header -------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(mappedTable.labels(raw = True)) # extend ASCII header with new labels + table.labels_append(indexedTable.labels(raw = True)) # extend ASCII header with new labels table.head_write() # ------------------------------------------ process data ------------------------------------------ @@ -99,9 +100,9 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table try: - table.data_append(mappedTable.data[int(round(float(table.data[mappedColumn])))+options.offset-1]) # add all mapped data types + table.data_append(indexedTable.data[int(round(float(table.data[indexColumn])))+options.offset-1]) # add all mapped data types except IndexError: - table.data_append(np.nan*np.ones_like(mappedTable.data[0])) + table.data_append(np.nan*np.ones_like(indexedTable.data[0])) outputAlive = table.data_write() # output processed line # ------------------------------------------ output finalization ----------------------------------- diff --git a/processing/post/addValueMapped.py b/processing/post/addLinked.py similarity index 72% rename from processing/post/addValueMapped.py rename to processing/post/addLinked.py index 65568b2c7..5ea9abe43 100755 --- a/processing/post/addValueMapped.py +++ b/processing/post/addLinked.py @@ -14,12 +14,12 @@ scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options [file[s]]', description = """ -Add data of selected column(s) from (first) row of second ASCIItable that shares the mapping column value. +Add data of selected column(s) from (first) row of second ASCIItable that shares the linking column value. """, version = scriptID) -parser.add_option('-c','--map', - dest = 'map', nargs = 2, +parser.add_option('--link', + dest = 'link', nargs = 2, type = 'string', metavar = 'string string', help = 'column labels containing linked values') parser.add_option('-l','--label', @@ -29,7 +29,7 @@ parser.add_option('-l','--label', parser.add_option('-a','--asciitable', dest = 'asciitable', type = 'string', metavar = 'string', - help = 'indexed ASCIItable') + help = 'linked ASCIItable') parser.set_defaults() @@ -37,32 +37,32 @@ parser.set_defaults() if options.label is None: parser.error('no data columns specified.') -if options.map is None: - parser.error('no mapping columns given.') +if options.link is None: + parser.error('no linking columns given.') -# ------------------------------------------ process mapping ASCIItable --------------------------- +# -------------------------------------- process linked ASCIItable -------------------------------- if options.asciitable is not None and os.path.isfile(options.asciitable): - mappedTable = damask.ASCIItable(name = options.asciitable, + linkedTable = damask.ASCIItable(name = options.asciitable, buffered = False, readonly = True) - mappedTable.head_read() # read ASCII header info of mapped table - if mappedTable.label_dimension(options.map[1]) != 1: - parser.error('mapping column {} needs to be scalar valued.'.format(options.map[1])) + linkedTable.head_read() # read ASCII header info of linked table + if linkedTable.label_dimension(options.link[1]) != 1: + parser.error('linking column {} needs to be scalar valued.'.format(options.link[1])) - missing_labels = mappedTable.data_readArray([options.map[1]]+options.label) - mappedTable.close() # close mapped input ASCII table + missing_labels = linkedTable.data_readArray([options.link[1]]+options.label) + linkedTable.close() # close linked ASCII table if len(missing_labels) > 0: damask.util.croak('column{} {} not found...'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) - index = mappedTable.data[:,0] - data = mappedTable.data[:,1:] + index = linkedTable.data[:,0] + data = linkedTable.data[:,1:] else: - parser.error('no indexed ASCIItable given.') + parser.error('no linked ASCIItable given.') -# --- loop over input files ------------------------------------------------------------------------- +# --- loop over input files ----------------------------------------------------------------------- if filenames == []: filenames = [None] @@ -80,8 +80,8 @@ for name in filenames: errors = [] - mappedColumn = table.label_index(options.map[0]) - if mappedColumn < 0: errors.append('mapping column {} not found.'.format(options.map[0])) + linkColumn = table.label_index(options.link[0]) + if linkColumn < 0: errors.append('linking column {} not found.'.format(options.link[0])) if errors != []: damask.util.croak(errors) @@ -91,7 +91,7 @@ for name in filenames: # ------------------------------------------ assemble header -------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(mappedTable.labels(raw = True)[1:]) # extend with new labels (except for mapped column) + table.labels_append(linkedTable.labels(raw = True)[1:]) # extend with new labels (except for linked column) table.head_write() @@ -100,7 +100,7 @@ for name in filenames: outputAlive = True while outputAlive and table.data_read(): # read next data line of ASCII table try: - table.data_append(data[np.argwhere(index == float(table.data[mappedColumn]))[0]]) # add data from first matching line + table.data_append(data[np.argwhere(index == float(table.data[linkColumn]))[0]]) # add data from first matching line except IndexError: table.data_append(np.nan*np.ones_like(data[0])) # or add NaNs outputAlive = table.data_write() # output processed line From 40de6910b88987c5bd1f9da1ddab46b066d8e225 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 29 Nov 2016 23:59:13 -0500 Subject: [PATCH 20/32] added --float option to translate real-valued grid data --- processing/pre/geom_check.sh | 11 +++++++++-- processing/pre/geom_toTable.py | 11 ++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/processing/pre/geom_check.sh b/processing/pre/geom_check.sh index 5a39d4fc7..4342f93e6 100755 --- a/processing/pre/geom_check.sh +++ b/processing/pre/geom_check.sh @@ -1,13 +1,20 @@ #!/usr/bin/env bash +if [[ "$1" == "-f" || "$1" == "--float" ]]; then + shift + arg='--float' +else + arg='' +fi + for geom in "$@" do - geom_toTable \ + geom_toTable $arg \ < $geom \ | \ vtk_rectilinearGrid > ${geom%.*}.vtk - geom_toTable \ + geom_toTable $arg \ < $geom \ | \ vtk_addRectilinearGridData \ diff --git a/processing/pre/geom_toTable.py b/processing/pre/geom_toTable.py index beb4987d8..eb6bdde61 100755 --- a/processing/pre/geom_toTable.py +++ b/processing/pre/geom_toTable.py @@ -19,8 +19,17 @@ Translate geom description into ASCIItable containing position and microstructur """, version = scriptID) +parser.add_option('--float', + dest = 'real', + action = 'store_true', + help = 'use float input') + +parser.set_defaults(real = False, + ) (options, filenames) = parser.parse_args() +datatype = 'f' if options.real else 'i' + # --- loop over input files ------------------------------------------------------------------------- if filenames == []: filenames = [None] @@ -56,7 +65,7 @@ for name in filenames: # --- read data ------------------------------------------------------------------------------------ - microstructure = table.microstructure_read(info['grid']) + microstructure = table.microstructure_read(info['grid'],datatype) # ------------------------------------------ assemble header --------------------------------------- From cb95f3b2447caa829f2fa4a2d47ca18d6a7fbdc6 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 30 Nov 2016 09:39:13 -0500 Subject: [PATCH 21/32] fixed systematic drift of grain structure along -[1,1,1] correction of periodic Gauss kernel extension, inclusion of ndimage.gaussian_filter alternative (same runtime as FFT), proper output handling of grids <3D --- processing/pre/geom_grainGrowth.py | 171 +++++++++++++++++------------ 1 file changed, 103 insertions(+), 68 deletions(-) diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index b6c1953c4..9b354762c 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -22,32 +22,46 @@ The final geometry is assembled by selecting at each voxel that grain index for """, version = scriptID) -parser.add_option('-d', '--distance', dest='d', type='int', metavar='int', - help='diffusion distance in voxels [%default]') -parser.add_option('-N', '--smooth', dest='N', type='int', metavar='int', - help='N for curvature flow [%default]') -parser.add_option('-r', '--renumber', dest='renumber', action='store_true', - help='renumber microstructure indices from 1...N [%default]') -parser.add_option('-i', '--immutable', action='extend', dest='immutable', metavar = '', - help='list of immutable microstructures') +parser.add_option('-d', '--distance', + dest = 'd', + type = 'float', metavar = 'float', + help = 'diffusion distance in voxels [%default]') +parser.add_option('-N', '--iterations', + dest = 'N', + type = 'int', metavar = 'int', + help = 'curvature flow iterations [%default]') +parser.add_option('-i', '--immutable', + action = 'extend', dest = 'immutable', metavar = '', + help = 'list of immutable microstructure indices') +parser.add_option('-r', '--renumber', + dest = 'renumber', action='store_true', + help = 'output consecutive microstructure indices') +parser.add_option('--ndimage', + dest = 'ndimage', action='store_true', + help = 'use ndimage.gaussian_filter in lieu of explicit FFT') -parser.set_defaults(d = 1) -parser.set_defaults(N = 1) -parser.set_defaults(renumber = False) -parser.set_defaults(immutable = []) +parser.set_defaults(d = 1, + N = 1, + immutable = [], + renumber = False, + ndimage = False, + ) (options, filenames) = parser.parse_args() options.immutable = map(int,options.immutable) -# --- loop over input files ------------------------------------------------------------------------- +getInterfaceEnergy = lambda A,B: (A*B != 0)*(A != B)*1.0 # 1.0 if A & B are distinct & nonzero, 0.0 otherwise +struc = ndimage.generate_binary_structure(3,1) # 3D von Neumann neighborhood + +# --- loop over input files ----------------------------------------------------------------------- if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, - buffered = False, labeled = False) + try: table = damask.ASCIItable(name = name, + buffered = False, + labeled = False) except: continue damask.util.report(scriptName,name) @@ -56,12 +70,12 @@ for name in filenames: 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'], - ]) + damask.util.croak(['grid a b c: {}'.format(' x '.join(map(str,info['grid']))), + 'size x y z: {}'.format(' x '.join(map(str,info['size']))), + 'origin x y z: {}'.format(' : '.join(map(str,info['origin']))), + 'homogenization: {}'.format(info['homogenization']), + 'microstructures: {}'.format(info['microstructures']), + ]) errors = [] if np.any(info['grid'] < 1): errors.append('invalid grid a b c.') @@ -71,39 +85,35 @@ for name in filenames: table.close(dismiss = True) continue -# --- read data ------------------------------------------------------------------------------------ - microstructure = np.tile(np.array(table.microstructure_read(info['grid']),'i').reshape(info['grid'],order='F'), - np.where(info['grid'] == 1, 2,1)) # make one copy along dimensions with grid == 1 +# --- read data ----------------------------------------------------------------------------------- + microstructure = np.tile(table.microstructure_read(info['grid']).reshape(info['grid'],order='F'), + np.where(info['grid'] == 1, 2,1)) # make one copy along dimensions with grid == 1 grid = np.array(microstructure.shape) -#--- initialize support data ----------------------------------------------------------------------- - +# --- initialize support data --------------------------------------------------------------------- # store a copy the initial microstructure to find locations of immutable indices microstructure_original = np.copy(microstructure) - X,Y,Z = np.mgrid[0:grid[0],0:grid[1],0:grid[2]] + if not options.ndimage: + X,Y,Z = np.mgrid[0:grid[0],0:grid[1],0:grid[2]] - # Calculates gaussian weights for simulating 3d diffusion - gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d))/math.pow(2.0*np.pi*options.d*options.d,1.5) - gauss[:,:,grid[2]/2::] = gauss[:,:,int(round(grid[2]/2.))-1::-1] # trying to cope with uneven (odd) grid size - gauss[:,grid[1]/2::,:] = gauss[:,int(round(grid[1]/2.))-1::-1,:] - gauss[grid[0]/2::,:,:] = gauss[int(round(grid[0]/2.))-1::-1,:,:] - gauss = np.fft.rfftn(gauss) - - getInterfaceEnergy = lambda A,B: (A*B != 0)*(A != B)*1.0 # 1.0 if A & B are distinct & nonzero, 0.0 otherwise - struc = ndimage.generate_binary_structure(3,1) # 3D von Neumann neighborhood + # Calculates gaussian weights for simulating 3d diffusion + gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d)) \ + /math.pow(2.0*np.pi*options.d*options.d,(3.0 - np.count_nonzero(info['grid'] == 1))/2.) + + gauss[:,:,:grid[2]/2:-1] = gauss[:,:,1:(grid[2]+1)/2] # trying to cope with uneven (odd) grid size + gauss[:,:grid[1]/2:-1,:] = gauss[:,1:(grid[1]+1)/2,:] + gauss[:grid[0]/2:-1,:,:] = gauss[1:(grid[0]+1)/2,:,:] + gauss = np.fft.rfftn(gauss) for smoothIter in range(options.N): - periodic_microstructure = np.tile(microstructure,(3,3,3))[grid[0]/2:-grid[0]/2, - grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # periodically extend the microstructure interfaceEnergy = np.zeros(microstructure.shape) for i in (-1,0,1): for j in (-1,0,1): for k in (-1,0,1): - # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood) + # assign interfacial energy to all voxels that have a differing neighbor (in Moore neighborhood) interfaceEnergy = np.maximum(interfaceEnergy, getInterfaceEnergy(microstructure,np.roll(np.roll(np.roll( microstructure,i,axis=0), j,axis=1), k,axis=2))) @@ -112,44 +122,65 @@ for name in filenames: periodic_interfaceEnergy = np.tile(interfaceEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, grid[2]/2:-grid[2]/2] - # transform bulk volume (i.e. where interfacial energy is zero) + + # transform bulk volume (i.e. where interfacial energy remained zero), store index of closest boundary voxel index = ndimage.morphology.distance_transform_edt(periodic_interfaceEnergy == 0., return_distances = False, return_indices = True) + # want array index of nearest voxel on periodically extended boundary periodic_bulkEnergy = periodic_interfaceEnergy[index[0], index[1], - index[2]].reshape(2*grid) # fill bulk with energy of nearest interface - diffusedEnergy = np.fft.irfftn(np.fft.rfftn( - np.where( - ndimage.morphology.binary_dilation(interfaceEnergy > 0., - structure = struc, - iterations = options.d/2 + 1), # fat boundary | PE: why 2d-1? I would argue for d/2 + 1 - periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... - grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2], # ...and zero everywhere else - 0.))*gauss) - periodic_diffusedEnergy = np.tile(diffusedEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, - grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # periodically extend the smoothed bulk energy - # transform voxels close to interface region | question PE: what motivates 1/2 (could be any small number, or)? - index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5, + index[2]].reshape(2*grid) # fill bulk with energy of nearest interface + if options.ndimage: + periodic_diffusedEnergy = ndimage.gaussian_filter( + np.where(ndimage.morphology.binary_dilation(periodic_interfaceEnergy > 0., + structure = struc, + iterations = int(round(options.d*2.)), # fat boundary + ), + periodic_bulkEnergy, # ...and zero everywhere else + 0.), + sigma = options.d) + else: + diffusedEnergy = np.fft.irfftn(np.fft.rfftn( + np.where( + ndimage.morphology.binary_dilation(interfaceEnergy > 0., + structure = struc, + iterations = int(round(options.d*2.))),# fat boundary + periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... + grid[1]/2:-grid[1]/2, + grid[2]/2:-grid[2]/2], # ...and zero everywhere else + 0.))*gauss) + + periodic_diffusedEnergy = np.tile(diffusedEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, + grid[1]/2:-grid[1]/2, + grid[2]/2:-grid[2]/2] # periodically extend the smoothed bulk energy + + + # transform voxels close to interface region + index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5*np.amax(periodic_diffusedEnergy), return_distances = False, - return_indices = True) # want index of closest bulk grain + return_indices = True) # want index of closest bulk grain + + periodic_microstructure = np.tile(microstructure,(3,3,3))[grid[0]/2:-grid[0]/2, + grid[1]/2:-grid[1]/2, + grid[2]/2:-grid[2]/2] # periodically extend the microstructure + microstructure = periodic_microstructure[index[0], index[1], index[2]].reshape(2*grid)[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, - grid[2]/2:-grid[2]/2] # extent grains into interface region + grid[2]/2:-grid[2]/2] # extent grains into interface region immutable = np.zeros(microstructure.shape, dtype=bool) # find locations where immutable microstructures have been or are now for micro in options.immutable: - immutable += np.logical_or(microstructure == micro, microstructure_original == micro) - # undo any changes involving immutable microstructures - microstructure = np.where(immutable, microstructure_original,microstructure) + immutable += np.logical_or(microstructure == micro, microstructure_original == micro) -# --- renumber to sequence 1...Ngrains if requested ------------------------------------------------ + # undo any changes involving immutable microstructures + microstructure = np.where(immutable, microstructure_original,microstructure) + +# --- renumber to sequence 1...Ngrains if requested ----------------------------------------------- # http://stackoverflow.com/questions/10741346/np-frequency-counts-for-unique-values-in-an-array if options.renumber: @@ -162,13 +193,14 @@ for name in filenames: newInfo = {'microstructures': 0,} newInfo['microstructures'] = microstructure.max() -# --- report --------------------------------------------------------------------------------------- +# --- report -------------------------------------------------------------------------------------- remarks = [] - if (newInfo['microstructures'] != info['microstructures']): remarks.append('--> microstructures: %i'%newInfo['microstructures']) + if newInfo['microstructures'] != info['microstructures']: + remarks.append('--> microstructures: {}'.format(newInfo['microstructures'])) if remarks != []: damask.util.croak(remarks) -# --- write header --------------------------------------------------------------------------------- +# --- write header -------------------------------------------------------------------------------- table.labels_clear() table.info_clear() @@ -185,8 +217,11 @@ for name in filenames: # --- write microstructure information ------------------------------------------------------------ formatwidth = int(math.floor(math.log10(microstructure.max())+1)) - table.data = microstructure.reshape((info['grid'][0],info['grid'][1]*info['grid'][2]),order='F').transpose() - table.data_writeArray('%%%ii'%(formatwidth),delimiter = ' ') + table.data = microstructure[::1 if info['grid'][0]>1 else 2, + ::1 if info['grid'][1]>1 else 2, + ::1 if info['grid'][2]>1 else 2,].\ + reshape((info['grid'][0],info['grid'][1]*info['grid'][2]),order='F').transpose() + table.data_writeArray('%{}i'.format(formatwidth),delimiter = ' ') # --- output finalization -------------------------------------------------------------------------- From e42db0ea2537ef34a06640e4afffaad3f2d0d07d Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Wed, 30 Nov 2016 18:18:03 -0500 Subject: [PATCH 22/32] Individual test can be selected by sequence number polishing, slightly more elaborate debugging --- lib/damask/test/test.py | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/lib/damask/test/test.py b/lib/damask/test/test.py index 223b21b78..5445ee443 100644 --- a/lib/damask/test/test.py +++ b/lib/damask/test/test.py @@ -58,11 +58,11 @@ class Test(): self.parser.add_option("--ok", "--accept", action = "store_true", dest = "accept", - help = "calculate results but always consider test as successfull") + help = "calculate results but always consider test as successful") self.parser.add_option("-l", "--list", action = "store_true", dest = "show", - help = "show all test variants and do no calculation") + help = "show all test variants without actual calculation") self.parser.add_option("-s", "--select", dest = "select", help = "run test of given name only") @@ -83,8 +83,9 @@ class Test(): for variant,name in enumerate(self.variants): if self.options.show: - logging.critical('{}: {}'.format(variant,name)) - elif self.options.select is not None and name != self.options.select: + logging.critical('{}: {}'.format(variant+1,name)) + elif self.options.select is not None \ + and not (name == self.options.select or str(variant+1) == self.options.select): pass else: try: @@ -93,14 +94,15 @@ class Test(): self.run(variant) self.postprocess(variant) - + self.compare(variant) + if self.options.update: if self.update(variant) != 0: logging.critical('update for "{}" failed.'.format(name)) elif not (self.options.accept or self.compare(variant)): # no update, do comparison return variant+1 # return culprit - except Exception as e : - logging.critical('exception during variant execution: {}'.format(e)) + except Exception as e: + logging.critical('exception during variant execution: "{}"'.format(e.message)) return variant+1 # return culprit return 0 @@ -465,7 +467,7 @@ class Test(): mean = np.amax(np.abs(np.mean(normedDelta,0))) std = np.amax(np.std(normedDelta,0)) logging.info('mean: {:f}'.format(mean)) - logging.info('std: {:f}'.format(std)) + logging.info('std: {:f}'.format(std)) return (mean atol + rtol*np.absolute(data[1]) + logging.info('shape of violators: {}'.format(violators.shape)) + for j,culprits in enumerate(violators): + goodguys = np.logical_not(culprits) + if culprits.any(): + logging.info('{} has {}'.format(j,np.sum(culprits))) + logging.info('deviation: {}'.format(np.absolute(data[0][j]-data[1][j])[culprits])) + logging.info('data : {}'.format(np.absolute(data[1][j])[culprits])) + logging.info('deviation: {}'.format(np.absolute(data[0][j]-data[1][j])[goodguys])) + logging.info('data : {}'.format(np.absolute(data[1][j])[goodguys])) +# for ok,valA,valB in zip(allclose,data[0],data[1]): +# logging.debug('{}:\n{}\n{}'.format(ok,valA,valB)) allclose = True # start optimistic for i in range(1,len(data)): @@ -565,7 +576,7 @@ class Test(): ret = culprit if culprit == 0: - msg = 'The test passed' if len(self.variants) == 1 \ + msg = 'The test passed.' if (self.options.select is not None or len(self.variants) == 1) \ else 'All {} tests passed.'.format(len(self.variants)) elif culprit == -1: msg = 'Warning: Could not start test...' From f5a10ae480c7d011c1cf22b4eb696e5ad2f68970 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 1 Dec 2016 04:41:39 +0100 Subject: [PATCH 23/32] updated version information after successful test of v2.0.1-329-ge42db0e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index badc23c91..0bc79fadb 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-317-gd6baa71 +v2.0.1-329-ge42db0e From a2db7e9ba182eebd1365f9cfd8e3738fa3e73cf0 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 6 Dec 2016 21:36:25 -0500 Subject: [PATCH 24/32] added option to suppress writing of material.config part in header --- .../pre/geom_fromVoronoiTessellation.py | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index dfb68d896..9c16a6213 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -178,6 +178,10 @@ parser.add_option_group(group) group = OptionGroup(parser, "Configuration","") +group.add_option('--no-config', + dest = 'config', + action = 'store_false', + help = 'omit material configuration header') group.add_option('--homogenization', dest = 'homogenization', type = 'int', metavar = 'int', @@ -203,6 +207,7 @@ parser.set_defaults(pos = 'pos', cpus = 2, laguerre = False, nonperiodic = False, + config = True, ) (options,filenames) = parser.parse_args() @@ -303,20 +308,21 @@ for name in filenames: config_header = [] formatwidth = 1+int(math.log10(NgrainIDs)) - config_header += [''] - for i,ID in enumerate(grainIDs): - config_header += ['[Grain{}]'.format(str(ID).zfill(formatwidth)), - 'crystallite {}'.format(options.crystallite), - '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,str(ID).rjust(formatwidth)), - ] - if hasEulers: - config_header += [''] - for ID in grainIDs: - eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id + if options.config: + config_header += [''] + for i,ID in enumerate(grainIDs): config_header += ['[Grain{}]'.format(str(ID).zfill(formatwidth)), - '(gauss)\tphi1 {:g}\tPhi {:g}\tphi2 {:g}\tscatter 0.0\tfraction 1.0'.format(*eulers[eulerID]) + 'crystallite {}'.format(options.crystallite), + '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,str(ID).rjust(formatwidth)), ] - if options.axes is not None: config_header.append('axes\t{} {} {}'.format(*options.axes)) + if hasEulers: + config_header += [''] + for ID in grainIDs: + eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id + config_header += ['[Grain{}]'.format(str(ID).zfill(formatwidth)), + '(gauss)\tphi1 {:g}\tPhi {:g}\tphi2 {:g}\tscatter 0.0\tfraction 1.0'.format(*eulers[eulerID]) + ] + if options.axes is not None: config_header.append('axes\t{} {} {}'.format(*options.axes)) table.labels_clear() table.info_clear() From 9bb4f89e78bf425df74902c5cbfded19e5f94ef9 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Tue, 6 Dec 2016 21:36:45 -0500 Subject: [PATCH 25/32] removed leftover debug output --- processing/pre/seeds_fromPokes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/processing/pre/seeds_fromPokes.py b/processing/pre/seeds_fromPokes.py index d3ea632fc..3e831e906 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -109,7 +109,6 @@ for name in filenames: 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] - damask.util.croak('x,y coord on surface: {},{}...'.format(*grid[:2])) for k in range(Nz): grid[2] = k + offset[2] grid %= info['grid'] From ebfc16b94ece244c0077e57758553d4c5e8fcc60 Mon Sep 17 00:00:00 2001 From: Test User Date: Wed, 7 Dec 2016 16:41:07 +0100 Subject: [PATCH 26/32] updated version information after successful test of v2.0.1-332-g9bb4f89 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 0bc79fadb..a90fe5295 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-329-ge42db0e +v2.0.1-332-g9bb4f89 From 4b7030362524f932be3b2de0f4a2f93cd85700c4 Mon Sep 17 00:00:00 2001 From: Martin Diehl Date: Thu, 8 Dec 2016 10:21:12 +0100 Subject: [PATCH 27/32] some variants of the bar code --- ...{DAMASK QR-Code.png => DAMASK_QR-Code.png} | Bin misc/DAMASK_QR-CodeBW.png | Bin 0 -> 5662 bytes misc/DAMASK_QR-CodeBW.svg | 31 ++++++++++++++++++ 3 files changed, 31 insertions(+) rename misc/{DAMASK QR-Code.png => DAMASK_QR-Code.png} (100%) create mode 100644 misc/DAMASK_QR-CodeBW.png create mode 100644 misc/DAMASK_QR-CodeBW.svg diff --git a/misc/DAMASK QR-Code.png b/misc/DAMASK_QR-Code.png similarity index 100% rename from misc/DAMASK QR-Code.png rename to misc/DAMASK_QR-Code.png diff --git a/misc/DAMASK_QR-CodeBW.png b/misc/DAMASK_QR-CodeBW.png new file mode 100644 index 0000000000000000000000000000000000000000..b9e46a2ca783ec9ef7374099cbb914a8d65a612b GIT binary patch literal 5662 zcmd5=dr(tX8b3h9P(>28YZa9UxNO&5S;c}>gkXZ0K|yz{Y#%(dh@*;! z-|zg+_qu2A>d0`{S7y9|5OU?LVE+{%iU9wp6nJubZqN$&bKDRS&PKzz`)-Kg&Lw%p z+bIa`{~G@sItvbZ!o%^YoK<1tl@lG^7WrL}gr*|&Y88hax|Y}WuwzYO`|^olYc5|i zB~8~0V$3V%o;oqxU*2Cf?kGF|-g~UF?J-%Ge0#rs^KQ>^{adx>GPf4L{q@rw5CbEj zBa-2WXl#V|RK%n?AS&1krTn&oWxcT`eoW4roSM$1`iyd-u2K=#rstXhJ%Z9rtpMsV z;A99sK`$F9kV6)ANEPwi?_3@LqcTkkPPXY||s-8~@} z*-eU4#;3PAL`#V5n7kH!a`4Qm-f=BWQo9TEo}LJW0J?`NQsDcdY+$m5GiIDy5$?#vW_BIu2;;0xdT3!uL$UhZ^f#2p^MML(ZxODX8 z+n<@!FFAx#7#~5{F+L(IdS;lHX0)ByqD^s?ssc>B3ZnVyzV4Kh*LEAeGJGyEa8y@v zsLJZs`Kf#=bLvjULPxZQ0wrTqKp}n@Gkg+qqTaA=01OMe!h6O8<^o>TR$bRRpG3$8Z8E3T@4$<$G!%WlVj2_L==1I zWb>1NH8n+Q#WyKc#X?QVqt?YqNABfy656|!|Ij{;%+5X+F|#Ctm7UGtay)tCLn(EP z{GfeKR8Qs%?YmbR^QaU$`Ikbht$yJrnFY?r@3p9R7H_(hdD*oaTp_lC&3795%$1(Z z{M{|hg&;Julfou58wrSG(MMzwM}Olc@$+cMVsY3%w%PO#N`ffv$Z>(f2~ zT;rxGu}@%8f_tgHu0T)tgD!w{S>hQrq7V7qsf@h{J zY)OghIFuE9IAn1}nz+Jjwj~*AcX2;>7&b7d>2e2!H^Iu&d`j{R;zgRNc;{>|{57SC z7%ruNj{3S!Z2=y@f#L&3L4XecHc_#{50)YlUOyIUK{}#9-t@iz~WCif^ zmVbHsx?ydp!zf!=PlHDNAn6;goQekvos_e5yB_EaGEFH_w;2a368QXV!({B3Z)MlY z=kPJ`<>w%8?W&^LoXOT^i;6;;sAHHEN!8+IT`oAlM_X}HXbedlWg&i^I29r|-Y<#< z9{IGzJo_WXw)LXo@MAVVL28-r;w*iT>HBMEa_2?I`Oc2KpQSsli>;9=^aF;Ebpank zzd{2|TN5f>uu}1Qn@1&__P~LZR?e`ckhCAC+5DT_I{T=zb$!*V-S>!RI?lE^d3zqzI@QqxQ8uIrm@goY zY#Y>Ulk_XbaR}aoP|DVb15&ZE5Y|FQ|Gr>4+HY)`h2kz_w0NHz6R`y*hHVkp4GsbU zU@zAejr>+O*#3OX&~pOuzHFzW;Pp!=J|bN4;A6+QpncBbJ+@v_DUrKf3e4Q-%*bJs zSWqm&4X#2_{tu<}XFPi(&;0Tb9(hx+{m86jZCgw47g?6?M&seQ?9DArshc$^ zb(<7XQnk*XjhI1@pztC_-h#!AhS~oQ%!{a1CUCWV0rHw5vYnGo=q`pdn~jm;*gM0? z;^B0=!zxQ8C*=2EC{u7W5eDNI9!sjGL3hr8++Zm#FN;KLUA1gna&>JRZHOC_r<)=T zNy0}5#={Y%ih?Q((SV`s+)sQ;~tgW3x-t2(dgdATypul@aC%j_?lPJC)V zC50Dm#25Cos?xQ+CxY*uk>u)yrX3NradvmYC4=)KQPb*hp;Dw-V&X~fDz>P7)zRwc z{x?j-MivEKox+CF2j4Bvgdt@47iMEj=kq_FHAbdY5tp{G#+kp{=&U}{t + + + + + image/svg+xml + + + + + + + + From 67457b9c652bc99689dcd28f7215428b6bda2fa5 Mon Sep 17 00:00:00 2001 From: Franz Roters Date: Thu, 8 Dec 2016 11:20:51 +0100 Subject: [PATCH 28/32] also remove *.optrpt during clean and tidy --- code/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/Makefile b/code/Makefile index a3d50d6ef..49ce9c50e 100644 --- a/code/Makefile +++ b/code/Makefile @@ -712,6 +712,7 @@ C_routines.o: C_routines.c tidy: @rm -rf *.o @rm -rf *.mod + @rm -rf *.optrpt @rm -rf *.inst.f90 # for instrumentation @rm -rf *.pomp.f90 # for instrumentation @rm -rf *.pp.f90 # for instrumentation @@ -724,6 +725,7 @@ cleanDAMASK: @rm -rf *.marc @rm -rf *.o @rm -rf *.mod + @rm -rf *.optrpt @rm -rf *.inst.f90 # for instrumentation @rm -rf *.pomp.f90 # for instrumentation @rm -rf *.pp.f90 # for instrumentation From c8f321356d88bcbace8cc4eead7e285a0348f382 Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 8 Dec 2016 09:47:20 -0500 Subject: [PATCH 29/32] prefill immutable indices with closest mutable one Retain only orginially immutable locations, not those where immutability bled into. Changed threshold for change from 0.5 to 0.95 of max diffusedEnergy. --- processing/pre/geom_grainGrowth.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index 9b354762c..20aab4cbb 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -109,6 +109,15 @@ for name in filenames: for smoothIter in range(options.N): + + # replace immutable microstructures with closest mutable ones + index = ndimage.morphology.distance_transform_edt(np.in1d(microstructure,options.immutable).reshape(grid), + return_distances = False, + return_indices = True) + microstructure = microstructure[index[0], + index[1], + index[2]] + interfaceEnergy = np.zeros(microstructure.shape) for i in (-1,0,1): for j in (-1,0,1): @@ -146,7 +155,7 @@ for name in filenames: np.where( ndimage.morphology.binary_dilation(interfaceEnergy > 0., structure = struc, - iterations = int(round(options.d*2.))),# fat boundary + iterations = int(round(options.d*2.))-1),# fat boundary periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... grid[1]/2:-grid[1]/2, grid[2]/2:-grid[2]/2], # ...and zero everywhere else @@ -158,7 +167,7 @@ for name in filenames: # transform voxels close to interface region - index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.5*np.amax(periodic_diffusedEnergy), + index = ndimage.morphology.distance_transform_edt(periodic_diffusedEnergy >= 0.95*np.amax(periodic_diffusedEnergy), return_distances = False, return_indices = True) # want index of closest bulk grain @@ -173,9 +182,9 @@ for name in filenames: grid[2]/2:-grid[2]/2] # extent grains into interface region immutable = np.zeros(microstructure.shape, dtype=bool) - # find locations where immutable microstructures have been or are now + # find locations where immutable microstructures have been (or are now) for micro in options.immutable: - immutable += np.logical_or(microstructure == micro, microstructure_original == micro) + immutable += microstructure_original == micro # undo any changes involving immutable microstructures microstructure = np.where(immutable, microstructure_original,microstructure) From 9829db31e4486748054e87cae0a44225a9623a91 Mon Sep 17 00:00:00 2001 From: Test User Date: Thu, 8 Dec 2016 16:42:03 +0100 Subject: [PATCH 30/32] updated version information after successful test of v2.0.1-335-g67457b9 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a90fe5295..a6001a603 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-332-g9bb4f89 +v2.0.1-335-g67457b9 From d67be0e3f3f320a3b0f98c948ac9bf6bd5af4eef Mon Sep 17 00:00:00 2001 From: Philip Eisenlohr Date: Thu, 8 Dec 2016 23:34:43 -0500 Subject: [PATCH 31/32] reduced memory footprint (substantially) by switching to 32bit precision --- processing/pre/geom_grainGrowth.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/processing/pre/geom_grainGrowth.py b/processing/pre/geom_grainGrowth.py index 20aab4cbb..90c24219c 100755 --- a/processing/pre/geom_grainGrowth.py +++ b/processing/pre/geom_grainGrowth.py @@ -51,7 +51,7 @@ parser.set_defaults(d = 1, options.immutable = map(int,options.immutable) -getInterfaceEnergy = lambda A,B: (A*B != 0)*(A != B)*1.0 # 1.0 if A & B are distinct & nonzero, 0.0 otherwise +getInterfaceEnergy = lambda A,B: np.float32((A*B != 0)*(A != B)*1.0) # 1.0 if A & B are distinct & nonzero, 0.0 otherwise struc = ndimage.generate_binary_structure(3,1) # 3D von Neumann neighborhood # --- loop over input files ----------------------------------------------------------------------- @@ -99,14 +99,13 @@ for name in filenames: X,Y,Z = np.mgrid[0:grid[0],0:grid[1],0:grid[2]] # Calculates gaussian weights for simulating 3d diffusion - gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d)) \ - /math.pow(2.0*np.pi*options.d*options.d,(3.0 - np.count_nonzero(info['grid'] == 1))/2.) + gauss = np.exp(-(X*X + Y*Y + Z*Z)/(2.0*options.d*options.d),dtype=np.float32) \ + /np.power(2.0*np.pi*options.d*options.d,(3.0 - np.count_nonzero(info['grid'] == 1))/2.,dtype=np.float32) gauss[:,:,:grid[2]/2:-1] = gauss[:,:,1:(grid[2]+1)/2] # trying to cope with uneven (odd) grid size gauss[:,:grid[1]/2:-1,:] = gauss[:,1:(grid[1]+1)/2,:] gauss[:grid[0]/2:-1,:,:] = gauss[1:(grid[0]+1)/2,:,:] - gauss = np.fft.rfftn(gauss) - + gauss = np.fft.rfftn(gauss).astype(np.complex64) for smoothIter in range(options.N): @@ -118,7 +117,7 @@ for name in filenames: index[1], index[2]] - interfaceEnergy = np.zeros(microstructure.shape) + interfaceEnergy = np.zeros(microstructure.shape,dtype=np.float32) for i in (-1,0,1): for j in (-1,0,1): for k in (-1,0,1): @@ -141,11 +140,12 @@ for name in filenames: periodic_bulkEnergy = periodic_interfaceEnergy[index[0], index[1], index[2]].reshape(2*grid) # fill bulk with energy of nearest interface + if options.ndimage: periodic_diffusedEnergy = ndimage.gaussian_filter( np.where(ndimage.morphology.binary_dilation(periodic_interfaceEnergy > 0., structure = struc, - iterations = int(round(options.d*2.)), # fat boundary + iterations = int(round(options.d*2.))-1, # fat boundary ), periodic_bulkEnergy, # ...and zero everywhere else 0.), @@ -159,7 +159,8 @@ for name in filenames: periodic_bulkEnergy[grid[0]/2:-grid[0]/2, # retain filled energy on fat boundary... grid[1]/2:-grid[1]/2, grid[2]/2:-grid[2]/2], # ...and zero everywhere else - 0.))*gauss) + 0.)).astype(np.complex64) * + gauss).astype(np.float32) periodic_diffusedEnergy = np.tile(diffusedEnergy,(3,3,3))[grid[0]/2:-grid[0]/2, grid[1]/2:-grid[1]/2, @@ -181,7 +182,7 @@ for name in filenames: grid[1]/2:-grid[1]/2, grid[2]/2:-grid[2]/2] # extent grains into interface region - immutable = np.zeros(microstructure.shape, dtype=bool) + immutable = np.zeros(microstructure.shape, dtype=np.bool) # find locations where immutable microstructures have been (or are now) for micro in options.immutable: immutable += microstructure_original == micro From cbef4034a4f0a4cc0bd0d3367f50b2b0ccae926e Mon Sep 17 00:00:00 2001 From: Test User Date: Mon, 12 Dec 2016 04:41:17 +0100 Subject: [PATCH 32/32] updated version information after successful test of v2.0.1-339-gd67be0e --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a6001a603..3440f8734 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.0.1-335-g67457b9 +v2.0.1-339-gd67be0e