diff --git a/.gitignore b/.gitignore index beb8dfa88..5be00ff8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -*.pyc -*.hdf5 -*.xdmf *.bak *~ .DS_Store diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ed16394ed..dd20c8baa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,9 +77,9 @@ variables: IntelMarc: "$IntelCompiler17_8" HDF5Marc: "HDF5/1.10.5/Intel-17.8" # ++++++++++++ Documentation ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Doxygen1_8_15: "Documentation/Doxygen/1.8.15" + Doxygen1_8_17: "Documentation/Doxygen/1.8.17" # ------------ Defaults ---------------------------------------------- - Doxygen: "$Doxygen1_8_15" + Doxygen: "$Doxygen1_8_17" ################################################################################################### @@ -490,7 +490,7 @@ GridSolver: stage: createDocumentation script: - module load $IntelCompiler $MPICH_Intel $PETSc_MPICH_Intel $Doxygen - - $DAMASKROOT/PRIVATE/documenting/runDoxygen.sh $DAMASKROOT spectral + - $DAMASKROOT/PRIVATE/documenting/runDoxygen.sh $DAMASKROOT grid except: - master - release diff --git a/Makefile b/Makefile index 7e7b105ec..34ce18c52 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,13 @@ all: grid mesh processing .PHONY: grid grid: build/grid - @(cd build/grid;make -j4 all install;) + @(cd build/grid;make -j${DAMASK_NUM_THREADS} all install;) .PHONY: spectral spectral: grid .PHONY: mesh mesh: build/mesh - @(cd build/mesh; make -j4 all install;) + @(cd build/mesh; make -j${DAMASK_NUM_THREADS} all install;) .PHONY: FEM FEM: mesh diff --git a/PRIVATE b/PRIVATE index d0d5b5a22..62bd5ede5 160000 --- a/PRIVATE +++ b/PRIVATE @@ -1 +1 @@ -Subproject commit d0d5b5a22be9778187b100214c782747793bb956 +Subproject commit 62bd5ede5260cd4e0e3d1c3930c474c1e045aeef diff --git a/examples/.gitignore b/examples/.gitignore index 883b9d0de..3cb6b9820 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,9 +1,8 @@ *.C_ref -*.mesh -*.outputConstitutive -*.outputCrystallite -*.outputHomogenization -*.spectralOut +*.hdf5 +*.xdmf *.sta *.vt* +*.geom +*.seeds postProc diff --git a/examples/ConfigFiles/Phase_Dislotwin_TWIP-Steel-FeMnC.config b/examples/ConfigFiles/Phase_Dislotwin_TWIP-Steel-FeMnC.config index 0330e6f4a..3ca635d73 100644 --- a/examples/ConfigFiles/Phase_Dislotwin_TWIP-Steel-FeMnC.config +++ b/examples/ConfigFiles/Phase_Dislotwin_TWIP-Steel-FeMnC.config @@ -3,23 +3,16 @@ elasticity hooke plasticity dislotwin -#(output) edge_density -#(output) dipole_density -#(output) shearrate_slip -#(output) accumulated_shear_slip -#(output) mfp_slip -#(output) resolved_stress_slip -#(output) threshold_stress_slip -#(output) twin_fraction -#(output) shearrate_twin -#(output) accumulated_shear_twin -#(output) mfp_twin -#(output) resolved_stress_twin -#(output) threshold_stress_twin -#(output) shearrate_shearband -#(output) resolved_stress_shearband -#(output) sb_eigenvalues -#(output) sb_eigenvectors +(output) rho_mob +(output) rho_dip +(output) gamma_sl +(output) lambda_sl +(output) tau_pass +(output) f_tw +(output) lambda_tw +(output) tau_hat_tw +(output) f_tr + ### Material parameters ### lattice_structure fcc @@ -45,7 +38,6 @@ D0 4.0e-5 # Vacancy diffusion prefactor [m**2/s] Qsd 4.5e-19 # Activation energy for climb [J] Catomicvolume 1.0 # Adj. parameter controlling the atomic volume [in b^3] Cedgedipmindistance 1.0 # Adj. parameter controlling the minimum dipole distance [in b] -atol_rho 1.0 interactionSlipSlip 0.122 0.122 0.625 0.07 0.137 0.122 # Interaction coefficients (Kubin et al. 2008) ### Shearband parameters ### @@ -68,6 +60,5 @@ Cmfptwin 1.0 # Adj. parameter controlling twin mean free Cthresholdtwin 1.0 # Adj. parameter controlling twin threshold stress interactionSlipTwin 0.0 1.0 1.0 # Dislocation-Twin interaction coefficients interactionTwinTwin 0.0 1.0 # Twin-Twin interaction coefficients -atol_twinFrac 1.0e-7 SFE_0K -0.0396 # stacking fault energy at zero K; TWIP steel: -0.0526; Cu: -0.0396 dSFE_dT 0.0002 # temperature dependance of stacking fault energy diff --git a/examples/ConfigFiles/Phase_Isotropic_AluminumIsotropic.config b/examples/ConfigFiles/Phase_Isotropic_AluminumIsotropic.config index b2199da85..3a91035ea 100644 --- a/examples/ConfigFiles/Phase_Isotropic_AluminumIsotropic.config +++ b/examples/ConfigFiles/Phase_Isotropic_AluminumIsotropic.config @@ -18,4 +18,3 @@ n 20 h0 75e6 tausat 63e6 a 2.25 -atol_resistance 1 diff --git a/examples/ConfigFiles/Phase_Isotropic_FreeSurface.config b/examples/ConfigFiles/Phase_Isotropic_FreeSurface.config index ee009da3a..9a01c5a35 100644 --- a/examples/ConfigFiles/Phase_Isotropic_FreeSurface.config +++ b/examples/ConfigFiles/Phase_Isotropic_FreeSurface.config @@ -22,4 +22,3 @@ h0 1e6 n 5 m 3 a 2 -atol_resistance 1 diff --git a/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config b/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config index fd18aa719..2af3a2b8b 100644 --- a/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config +++ b/examples/ConfigFiles/Phase_Nonlocal_Aluminum.config @@ -66,6 +66,4 @@ cutoffRadius 1e-3 # cutoff radius for dislocation CFLfactor 2.0 # safety factor for CFL flux check (numerical parameter) significantRho 1e6 # minimum dislocation density considered relevant in m/m**3 #significantN 0.1 # minimum dislocation number per ip considered relevant -aTol_density 1e4 # absolute tolerance for dislocation density in m/m**3 -aTol_shear 1e-20 # absolute tolerance for plasgtic shear randomMultiplication 0 # switch for probabilistic extension of multiplication rate diff --git a/examples/ConfigFiles/Phase_Nonlocal_Nickel.config b/examples/ConfigFiles/Phase_Nonlocal_Nickel.config index 3cba4d975..ab6505c50 100644 --- a/examples/ConfigFiles/Phase_Nonlocal_Nickel.config +++ b/examples/ConfigFiles/Phase_Nonlocal_Nickel.config @@ -27,7 +27,7 @@ Nslip 12 # number of slip systems per family c11 246.5e9 c12 147.3e9 c44 124.7e9 -burgers 2.48e-10 0 0 0 # Burgers vector in m +burgers 2.48e-10 # Burgers vector in m rhoSglEdgePos0 6e10 # Initial positive edge single dislocation density in m/m**3 rhoSglEdgeNeg0 6e10 # Initial negative edge single dislocation density in m/m**3 rhoSglScrewPos0 6e10 # Initial positive screw single dislocation density in m/m**3 @@ -55,8 +55,6 @@ q 1 # exponent for thermal barrier attackFrequency 50e9 # attack frequency in Hz surfaceTransmissivity 1.0 # transmissivity of free surfaces for dislocation flux grainBoundaryTransmissivity 0.0 -aTol_rho 1e100 # absolute tolerance for dislocation density in m/m**3 -aTol_shear 1e10 # absolute tolerance for dislocation density in m/m**3 significantRho 1e8 # dislocation density considered relevant in m/m**3 significantN 1 shortRangeStressCorrection 0 diff --git a/examples/ConfigFiles/Phase_Phenopowerlaw_Aluminum.config b/examples/ConfigFiles/Phase_Phenopowerlaw_Aluminum.config index 938961d8e..72421a640 100644 --- a/examples/ConfigFiles/Phase_Phenopowerlaw_Aluminum.config +++ b/examples/ConfigFiles/Phase_Phenopowerlaw_Aluminum.config @@ -3,13 +3,10 @@ elasticity hooke plasticity phenopowerlaw (output) resistance_slip -(output) shearrate_slip -(output) resolvedstress_slip -(output) accumulated_shear_slip +(output) accumulatedshear_slip lattice_structure fcc Nslip 12 # per family -Ntwin 0 # per family c11 106.75e9 c12 60.41e9 @@ -22,4 +19,3 @@ tausat_slip 63e6 # per family a_slip 2.25 h0_slipslip 75e6 interaction_slipslip 1 1 1.4 1.4 1.4 1.4 -atol_resistance 1 diff --git a/examples/ConfigFiles/Phase_Phenopowerlaw_Gold.config b/examples/ConfigFiles/Phase_Phenopowerlaw_Gold.config index bb6f8fc83..c7fc670ac 100644 --- a/examples/ConfigFiles/Phase_Phenopowerlaw_Gold.config +++ b/examples/ConfigFiles/Phase_Phenopowerlaw_Gold.config @@ -1,5 +1,3 @@ - - # parameters fitted by D. Ma to: # I. Kovács, G. Vörös # On the mathematical description of the tensile stress-strain curves of polycrystalline face centered cubic metals @@ -7,20 +5,13 @@ # DOI: 10.1016/S0749-6419(95)00043-7 [gold_phenopowerlaw] -# slip only elasticity hooke plasticity phenopowerlaw (output) resistance_slip -(output) shearrate_slip -(output) resolvedstress_slip -(output) resistance_twin -(output) shearrate_twin -(output) resolvedstress_twin lattice_structure fcc Nslip 12 # per family -Ntwin 0 # per family c11 191.0e9 c12 162.0e9 @@ -31,9 +22,6 @@ n_slip 83.3 tau0_slip 26.25e6 # per family tausat_slip 53.00e6 # per family a_slip 1.0 -gdot0_twin 0.001 -n_twin 20 h0_slipslip 75e6 interaction_slipslip 1 1 1.4 1.4 1.4 1.4 -atol_resistance 1 diff --git a/examples/ConfigFiles/Phase_Phenopowerlaw_Magnesium.config b/examples/ConfigFiles/Phase_Phenopowerlaw_Magnesium.config index 7f14174cc..4647a868f 100644 --- a/examples/ConfigFiles/Phase_Phenopowerlaw_Magnesium.config +++ b/examples/ConfigFiles/Phase_Phenopowerlaw_Magnesium.config @@ -7,11 +7,7 @@ plasticity phenopowerlaw elasticity hooke (output) resistance_slip -(output) shearrate_slip -(output) resolvedstress_slip (output) resistance_twin -(output) shearrate_twin -(output) resolvedstress_twin lattice_structure hex c/a 1.62350 # from Tromans 2011, Elastic Anisotropy of HCP Metal Crystals and Polycrystals @@ -45,9 +41,6 @@ interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 #################################################### # open for discussion #################################################### -atol_resistance 1 -atol_shear 1e-6 -atol_twinfrac 1e-6 n_twin 20 n_slip 20 diff --git a/examples/ConfigFiles/Phase_Phenopowerlaw_cpTi-alpha.config b/examples/ConfigFiles/Phase_Phenopowerlaw_cpTi-alpha.config index 565cf02d9..93d45def7 100644 --- a/examples/ConfigFiles/Phase_Phenopowerlaw_cpTi-alpha.config +++ b/examples/ConfigFiles/Phase_Phenopowerlaw_cpTi-alpha.config @@ -2,13 +2,6 @@ plasticity phenopowerlaw elasticity hooke -# (output) resistance_slip -# (output) shearrate_slip -# (output) resolvedstress_slip -# (output) resistance_twin -# (output) shearrate_twin -# (output) resolvedstress_twin - lattice_structure hex covera_ratio 1.587 @@ -21,28 +14,10 @@ c44 46.5e9 # C. Zambaldi, "Orientation informed nanoindentation of a-titanium: Indentation pileup in hexagonal metals deforming by prismatic slip", J. Mater. Res., Vol. 27, No. 1, Jan 14, 2012 gdot0_slip 0.001 n_slip 20 -nslip 3 3 0 6 0 0 -tau0_slip 349.3e6 150e6 0 1107.9e6 0 0 -tausat_slip 568.6e6 1502.2e6 0 3420.1e6 0 0 +nslip 3 3 0 6 +tau0_slip 349.3e6 150e6 0 1107.9e6 +tausat_slip 568.6e6 1502.2e6 0 3420.1e6 a_slip 2 -ntwin 0 0 0 0 -gdot0_twin 0.001 0 0 0 -n_twin 20 -tau0_twin 31e6 0 0 0 0 -s_pr 0 -twin_b 0 -twin_c 0 -twin_d 0 -twin_e 0 h0_slipslip 15e6 -h0_twinslip 15e6 -h0_twintwin 15e6 -atol_resistance 1 -#atol_shear 1e-6 -#atol_twinfrac 1e-7 interaction_slipslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -#nonschmid_coefficients 0 diff --git a/examples/FEM/polyXtal/material.config b/examples/FEM/polyXtal/material.config index 71e5350dc..c2d1f4ad7 100644 --- a/examples/FEM/polyXtal/material.config +++ b/examples/FEM/polyXtal/material.config @@ -14,7 +14,6 @@ plasticity phenopowerlaw lattice_structure fcc Nslip 12 # per family -Ntwin 0 # per family c11 106.75e9 c12 60.41e9 @@ -25,22 +24,8 @@ n_slip 20 tau0_slip 31e6 # per family tausat_slip 63e6 # per family a_slip 2.25 -gdot0_twin 0.001 -n_twin 20 -tau0_twin 31e6 # per family -s_pr 0 # push-up factor for slip saturation due to twinning -twin_b 0 -twin_c 0 -twin_d 0 -twin_e 0 h0_slipslip 75e6 -h0_twinslip 0 -h0_twintwin 0 interaction_slipslip 1 1 1.4 1.4 1.4 1.4 -interaction_sliptwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -interaction_twinslip 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -interaction_twintwin 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -atol_resistance 1 (output) f (output) p diff --git a/examples/SpectralMethod/Polycrystal/20grains.seeds b/examples/SpectralMethod/Polycrystal/20grains.seeds index 9543d0296..d6b1c4f65 100644 --- a/examples/SpectralMethod/Polycrystal/20grains.seeds +++ b/examples/SpectralMethod/Polycrystal/20grains.seeds @@ -1,8 +1,7 @@ -4 header +3 header grid a 16 b 16 c 16 -microstructures 20 random seed 0 -1_pos 2_pos 3_pos 1_eulerangels 2_eulerangels 3_eulerangels +1_pos 2_pos 3_pos 1_euler 2_euler 3_euler 0.375488 0.161813 0.891040 197.572861 16.816409 129.422844 0.187988 0.849313 0.953540 257.468172 53.250534 157.331503 0.750488 0.349313 0.953540 216.994815 94.418518 251.147231 diff --git a/examples/SpectralMethod/Polycrystal/material.config b/examples/SpectralMethod/Polycrystal/material.config index 44e8b8c1d..ca2824301 100644 --- a/examples/SpectralMethod/Polycrystal/material.config +++ b/examples/SpectralMethod/Polycrystal/material.config @@ -12,16 +12,7 @@ mech none elasticity hooke plasticity phenopowerlaw -(output) resistance_slip -(output) shearrate_slip -(output) resolvedstress_slip -(output) accumulatedshear_slip -(output) resistance_twin -(output) shearrate_twin -(output) resolvedstress_twin -(output) accumulatedshear_twin - -# only for HDF5 out +(output) resistance_slip (output) orientation # quaternion (output) F # deformation gradient tensor (output) Fe # elastic deformation gradient tensor @@ -32,7 +23,6 @@ plasticity phenopowerlaw lattice_structure fcc Nslip 12 # per family -Ntwin 0 # per family c11 106.75e9 c12 60.41e9 @@ -45,7 +35,6 @@ tausat_slip 63e6 # per family a_slip 2.25 h0_slipslip 75e6 interaction_slipslip 1 1 1.4 1.4 1.4 1.4 -atol_resistance 1 #-------------------# diff --git a/processing/post/DADF5_postResults.py b/processing/post/DADF5_postResults.py index 4fa237df8..70c883aeb 100755 --- a/processing/post/DADF5_postResults.py +++ b/processing/post/DADF5_postResults.py @@ -15,10 +15,6 @@ scriptID = ' '.join([scriptName,damask.version]) # -------------------------------------------------------------------- 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', @@ -33,42 +29,35 @@ 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 not results.structured: continue - 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))) + results = damask.Result(filename) - table = damask.Table(np.ones(np.product(results.grid),dtype=int)*int(inc[3:]),{'inc':(1,)}) - table.add('pos',coords.reshape((-1,3))) + if not results.structured: continue + coords = damask.grid_filters.cell_coord0(results.grid,results.size,results.origin) - results.pick('materialpoints',False) - results.pick('constituents', True) - for label in options.con: - x = results.get_dataset_location(label) - if len(x) != 0: - table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1))) + N_digits = int(np.floor(np.log10(int(results.increments[-1][3:]))))+1 + N_digits = 5 # hack to keep test intact + for inc in damask.util.show_progress(results.iterate('increments'),len(results.increments)): + table = damask.Table(np.ones(np.product(results.grid),dtype=int)*int(inc[3:]),{'inc':(1,)}) + table.add('pos',coords.reshape(-1,3)) - results.pick('constituents', False) - results.pick('materialpoints',True) - for label in options.mat: - x = results.get_dataset_location(label) - if len(x) != 0: - table.add(label,results.read_dataset(x,0,plain=True).reshape((results.grid.prod(),-1))) + results.pick('materialpoints',False) + results.pick('constituents', True) + for label in options.con: + x = results.get_dataset_location(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)) - table.to_ASCII(os.path.join(dirname,file_out)) + results.pick('constituents', False) + results.pick('materialpoints',True) + for label in options.mat: + x = results.get_dataset_location(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)) + table.to_ASCII(os.path.join(dirname,file_out)) diff --git a/processing/post/DADF5toDREAM3D.py b/processing/post/DADF5toDREAM3D.py index 7ab04b934..95b62c7ce 100755 --- a/processing/post/DADF5toDREAM3D.py +++ b/processing/post/DADF5toDREAM3D.py @@ -8,18 +8,18 @@ import numpy as np import damask -class AttributeManagerNullterm(h5py.AttributeManager): +class AttributeManagerNullterm(h5py.AttributeManager): """ Attribute management for DREAM.3D hdf5 files. - + String attribute values are stored as fixed-length string with NULLTERM - + References ---------- https://stackoverflow.com/questions/38267076 https://stackoverflow.com/questions/52750232 - """ + """ def create(self, name, data, shape=None, dtype=None): if isinstance(data,str): @@ -28,7 +28,7 @@ class AttributeManagerNullterm(h5py.AttributeManager): super().create(name=name,data=data+' ',dtype = h5py.Datatype(tid)) else: super().create(name=name,data=data,shape=shape,dtype=dtype) - + h5py._hl.attrs.AttributeManager = AttributeManagerNullterm # 'Monkey patch' @@ -48,101 +48,91 @@ Phase_types = {'Primary': 0} #further additions to these can be done by looking # MAIN # -------------------------------------------------------------------- parser = argparse.ArgumentParser(description='Creating a file for DREAM3D from DAMASK data') -parser.add_argument('filenames',nargs='+',help='HDF5 based output file') -parser.add_argument('--inc',nargs='+',help='Increment for which DREAM3D to be used, eg. 25',type=int) +parser.add_argument('filenames', nargs='+', + help='DADF5 files') parser.add_argument('-d','--dir', dest='dir',default='postProc',metavar='string', - help='name of subdirectory to hold output') + help='name of subdirectory relative to the location of the DADF5 file to hold output') +parser.add_argument('--inc',nargs='+', + help='Increment for which DREAM3D to be used, eg. 25',type=int) options = parser.parse_args() -# -------------------------------------------------------------------- -# loop over input files for filename in options.filenames: - f = damask.DADF5(filename) #DAMASK output file - for increment in options.inc: - f.set_by_increment(increment,increment) - if len(f.visible['increments']) == 0: - continue + f = damask.Result(filename) + N_digits = int(np.floor(np.log10(int(f.increments[-1][3:]))))+1 - #-------output file creation------------------------------------- - dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) - try: - os.mkdir(dirname) - except FileExistsError: - pass + f.pick('increments',options.inc) + for inc in damask.util.show_progress(f.iterate('increments'),len(f.selection['increments'])): + dirname = os.path.abspath(os.path.join(os.path.dirname(filename),options.dir)) + try: + os.mkdir(dirname) + except FileExistsError: + pass - o = h5py.File(dirname + '/' + os.path.splitext(filename)[0] + '_{}.dream3D'.format(increment),'w') - #----------------------------------------------------------------- - o.attrs['DADF5toDREAM3D'] = '1.0' - o.attrs['FileVersion'] = '7.0' - #----------------------------------------------------------------- - + o = h5py.File(dirname + '/' + os.path.splitext(filename)[0] \ + + '_inc_{}.dream3D'.format(inc[3:].zfill(N_digits)),'w') + o.attrs['DADF5toDREAM3D'] = '1.0' + o.attrs['FileVersion'] = '7.0' - for g in ['DataContainerBundles','Pipeline']: # empty groups (needed) - o.create_group(g) + for g in ['DataContainerBundles','Pipeline']: # empty groups (needed) + o.create_group(g) - data_container_label = 'DataContainers/ImageDataContainer' - cell_data_label = data_container_label + '/CellData' + data_container_label = 'DataContainers/ImageDataContainer' + cell_data_label = data_container_label + '/CellData' + # Phase information of DREAM.3D is constituent ID in DAMASK + o[cell_data_label + '/Phases'] = f.get_constituent_ID().reshape(tuple(f.grid)+(1,)) + DAMASK_quaternion = f.read_dataset(f.get_dataset_location('orientation')) + # Convert: DAMASK uses P = -1, DREAM.3D uses P = +1. Also change position of imagninary part + DREAM_3D_quaternion = np.hstack((-DAMASK_quaternion['x'],-DAMASK_quaternion['y'],-DAMASK_quaternion['z'], + DAMASK_quaternion['w'])).astype(np.float32) + o[cell_data_label + '/Quats'] = DREAM_3D_quaternion.reshape(tuple(f.grid)+(4,)) - # Phase information of DREAM.3D is constituent ID in DAMASK - o[cell_data_label + '/Phases'] = f.get_constituent_ID().reshape(tuple(f.grid)+(1,)) - # Data quaternions - DAMASK_quaternion = f.read_dataset(f.get_dataset_location('orientation')) - # Convert: DAMASK uses P = -1, DREAM.3D uses P = +1. Also change position of imagninary part - DREAM_3D_quaternion = np.hstack((-DAMASK_quaternion['x'],-DAMASK_quaternion['y'],-DAMASK_quaternion['z'], - DAMASK_quaternion['w'])).astype(np.float32) - o[cell_data_label + '/Quats'] = DREAM_3D_quaternion.reshape(tuple(f.grid)+(4,)) - - # Attributes to CellData group - o[cell_data_label].attrs['AttributeMatrixType'] = np.array([3],np.uint32) - o[cell_data_label].attrs['TupleDimensions'] = f.grid.astype(np.uint64) - - # Common Attributes for groups in CellData - for group in ['/Phases','/Quats']: - o[cell_data_label + group].attrs['DataArrayVersion'] = np.array([2],np.int32) - o[cell_data_label + group].attrs['Tuple Axis Dimensions'] = 'x={},y={},z={}'.format(*f.grid) - - # phase attributes - o[cell_data_label + '/Phases'].attrs['ComponentDimensions'] = np.array([1],np.uint64) - o[cell_data_label + '/Phases'].attrs['ObjectType'] = 'DataArray' - o[cell_data_label + '/Phases'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) - - # Quats attributes - o[cell_data_label + '/Quats'].attrs['ComponentDimensions'] = np.array([4],np.uint64) - o[cell_data_label + '/Quats'].attrs['ObjectType'] = 'DataArray' - o[cell_data_label + '/Quats'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) - - # Create EnsembleAttributeMatrix - ensemble_label = data_container_label + '/EnsembleAttributeMatrix' - - # Data CrystalStructures - o[ensemble_label + '/CrystalStructures'] = np.uint32(np.array([999,\ - Crystal_structures[f.get_crystal_structure()]])).reshape((2,1)) - o[ensemble_label + '/PhaseTypes'] = np.uint32(np.array([999,Phase_types['Primary']])).reshape((2,1)) # ToDo - - # Attributes Ensemble Matrix - o[ensemble_label].attrs['AttributeMatrixType'] = np.array([11],np.uint32) - o[ensemble_label].attrs['TupleDimensions'] = np.array([2], np.uint64) - - # Attributes for data in Ensemble matrix - for group in ['CrystalStructures','PhaseTypes']: # 'PhaseName' not required MD: But would be nice to take the phase name mapping - o[ensemble_label+'/'+group].attrs['ComponentDimensions'] = np.array([1],np.uint64) - o[ensemble_label+'/'+group].attrs['Tuple Axis Dimensions'] = 'x=2' - o[ensemble_label+'/'+group].attrs['DataArrayVersion'] = np.array([2],np.int32) - o[ensemble_label+'/'+group].attrs['ObjectType'] = 'DataArray' - o[ensemble_label+'/'+group].attrs['TupleDimensions'] = np.array([2],np.uint64) - - - # Create geometry info - geom_label = data_container_label + '/_SIMPL_GEOMETRY' - - o[geom_label + '/DIMENSIONS'] = np.int64(f.grid) - o[geom_label + '/ORIGIN'] = np.float32(np.zeros(3)) - o[geom_label + '/SPACING'] = np.float32(f.size) - - o[geom_label].attrs['GeometryName'] = 'ImageGeometry' - o[geom_label].attrs['GeometryTypeName'] = 'ImageGeometry' - o[geom_label].attrs['GeometryType'] = np.array([0],np.uint32) - o[geom_label].attrs['SpatialDimensionality'] = np.array([3],np.uint32) - o[geom_label].attrs['UnitDimensionality'] = np.array([3],np.uint32) + # Attributes to CellData group + o[cell_data_label].attrs['AttributeMatrixType'] = np.array([3],np.uint32) + o[cell_data_label].attrs['TupleDimensions'] = f.grid.astype(np.uint64) + + # Common Attributes for groups in CellData + for group in ['/Phases','/Quats']: + o[cell_data_label + group].attrs['DataArrayVersion'] = np.array([2],np.int32) + o[cell_data_label + group].attrs['Tuple Axis Dimensions'] = 'x={},y={},z={}'.format(*f.grid) + + o[cell_data_label + '/Phases'].attrs['ComponentDimensions'] = np.array([1],np.uint64) + o[cell_data_label + '/Phases'].attrs['ObjectType'] = 'DataArray' + o[cell_data_label + '/Phases'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) + + o[cell_data_label + '/Quats'].attrs['ComponentDimensions'] = np.array([4],np.uint64) + o[cell_data_label + '/Quats'].attrs['ObjectType'] = 'DataArray' + o[cell_data_label + '/Quats'].attrs['TupleDimensions'] = f.grid.astype(np.uint64) + + # Create EnsembleAttributeMatrix + ensemble_label = data_container_label + '/EnsembleAttributeMatrix' + + # Data CrystalStructures + o[ensemble_label + '/CrystalStructures'] = np.uint32(np.array([999,\ + Crystal_structures[f.get_crystal_structure()]])).reshape(2,1) + o[ensemble_label + '/PhaseTypes'] = np.uint32(np.array([999,Phase_types['Primary']])).reshape(2,1) # ToDo + + # Attributes Ensemble Matrix + o[ensemble_label].attrs['AttributeMatrixType'] = np.array([11],np.uint32) + o[ensemble_label].attrs['TupleDimensions'] = np.array([2], np.uint64) + + # Attributes for data in Ensemble matrix + for group in ['CrystalStructures','PhaseTypes']: # 'PhaseName' not required MD: But would be nice to take the phase name mapping + o[ensemble_label+'/'+group].attrs['ComponentDimensions'] = np.array([1],np.uint64) + o[ensemble_label+'/'+group].attrs['Tuple Axis Dimensions'] = 'x=2' + o[ensemble_label+'/'+group].attrs['DataArrayVersion'] = np.array([2],np.int32) + o[ensemble_label+'/'+group].attrs['ObjectType'] = 'DataArray' + o[ensemble_label+'/'+group].attrs['TupleDimensions'] = np.array([2],np.uint64) + + geom_label = data_container_label + '/_SIMPL_GEOMETRY' + + o[geom_label + '/DIMENSIONS'] = np.int64(f.grid) + o[geom_label + '/ORIGIN'] = np.float32(np.zeros(3)) + o[geom_label + '/SPACING'] = np.float32(f.size) + + o[geom_label].attrs['GeometryName'] = 'ImageGeometry' + o[geom_label].attrs['GeometryTypeName'] = 'ImageGeometry' + o[geom_label].attrs['GeometryType'] = np.array([0],np.uint32) + o[geom_label].attrs['SpatialDimensionality'] = np.array([3],np.uint32) + o[geom_label].attrs['UnitDimensionality'] = np.array([3],np.uint32) diff --git a/processing/post/addCompatibilityMismatch.py b/processing/post/addCompatibilityMismatch.py index c7c5086ca..0678e78ba 100755 --- a/processing/post/addCompatibilityMismatch.py +++ b/processing/post/addCompatibilityMismatch.py @@ -40,7 +40,7 @@ def volTetrahedron(coords): # Get all the squares of all side lengths from the differences between # the 6 different pairs of vertex positions - vertices = np.concatenate((coords[0],coords[1],coords[2],coords[3])).reshape([4,3]) + vertices = np.concatenate((coords[0],coords[1],coords[2],coords[3])).reshape(4,3) vertex1, vertex2 = vertex_pair_indexes[:,0], vertex_pair_indexes[:,1] sides_squared = np.sum((vertices[vertex1] - vertices[vertex2])**2,axis=-1) @@ -185,13 +185,13 @@ for name in filenames: 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)), + shapeMismatch.reshape(-1,1), scriptID+' '+' '.join(sys.argv[1:])) if options.volume: 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)), + volumeMismatch.reshape(-1,1), scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addCurl.py b/processing/post/addCurl.py index f106054b3..87d1ab2f6 100755 --- a/processing/post/addCurl.py +++ b/processing/post/addCurl.py @@ -51,7 +51,7 @@ for name in filenames: 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))), + 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/addDeviator.py b/processing/post/addDeviator.py index ca06034b3..9a532caec 100755 --- a/processing/post/addDeviator.py +++ b/processing/post/addDeviator.py @@ -41,7 +41,7 @@ for name in filenames: table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) for tensor in options.tensor: table.add('dev({})'.format(tensor), - damask.mechanics.deviatoric_part(table.get(tensor).reshape(-1,3,3)).reshape((-1,9)), + damask.mechanics.deviatoric_part(table.get(tensor).reshape(-1,3,3)).reshape(-1,9), scriptID+' '+' '.join(sys.argv[1:])) if options.spherical: table.add('sph({})'.format(tensor), diff --git a/processing/post/addDisplacement.py b/processing/post/addDisplacement.py index faabc795f..f74d876bc 100755 --- a/processing/post/addDisplacement.py +++ b/processing/post/addDisplacement.py @@ -54,20 +54,20 @@ for name in filenames: 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)), + 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)), + 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)), + 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)), + 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)), + 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 cb9486990..2619bc499 100755 --- a/processing/post/addDivergence.py +++ b/processing/post/addDivergence.py @@ -51,7 +51,7 @@ for name in filenames: 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)), + 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/addGaussian.py b/processing/post/addGaussian.py index 5f3ec5d60..86552deca 100755 --- a/processing/post/addGaussian.py +++ b/processing/post/addGaussian.py @@ -68,7 +68,7 @@ for name in filenames: for label in options.labels: table.add('Gauss{}({})'.format(options.sigma,label), - ndimage.filters.gaussian_filter(table.get(label).reshape((-1)), + 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:])) diff --git a/processing/post/addGradient.py b/processing/post/addGradient.py index 8620c123b..409b2ce6d 100755 --- a/processing/post/addGradient.py +++ b/processing/post/addGradient.py @@ -51,7 +51,7 @@ for name in filenames: 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)), + 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/addIndexed.py b/processing/post/addIndexed.py index fde7d7eb7..98fed597b 100755 --- a/processing/post/addIndexed.py +++ b/processing/post/addIndexed.py @@ -59,6 +59,6 @@ for name in filenames: idx = np.reshape(table.get(options.index).astype(int) + options.offset,(-1))-1 for data in options.label: - table.add(data+'addIndexed',indexedTable.get(data)[idx],scriptID+' '+' '.join(sys.argv[1:])) + table.add(data+'_addIndexed',indexedTable.get(data)[idx],scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addSchmidfactors.py b/processing/post/addSchmidfactors.py index 670824064..94c062766 100755 --- a/processing/post/addSchmidfactors.py +++ b/processing/post/addSchmidfactors.py @@ -203,13 +203,11 @@ for name in filenames: # ------------------------------------------ assemble header --------------------------------------- table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_append(['{id}_' - 'S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]' + table.labels_append(['S[{direction[0]:.1g}_{direction[1]:.1g}_{direction[2]:.1g}]' '({normal[0]:.1g}_{normal[1]:.1g}_{normal[2]:.1g})'\ - .format( id = i+1, - normal = theNormal, + .format(normal = theNormal, direction = theDirection, - ) for i,(theNormal,theDirection) in enumerate(zip(slip_normal,slip_direction))]) + ) for theNormal,theDirection in zip(slip_normal,slip_direction)]) table.head_write() # ------------------------------------------ process data ------------------------------------------ diff --git a/processing/post/addSpectralDecomposition.py b/processing/post/addSpectralDecomposition.py index 5909ca147..01371cede 100755 --- a/processing/post/addSpectralDecomposition.py +++ b/processing/post/addSpectralDecomposition.py @@ -50,11 +50,9 @@ for name in filenames: if options.rh: v[np.linalg.det(v) < 0.0,:,2] *= -1.0 for i,o in enumerate(['Min','Mid','Max']): - table.add('eigval{}({})'.format(o,tensor),u[:,i], - scriptID+' '+' '.join(sys.argv[1:])) + table.add('eigval{}({})'.format(o,tensor),u[:,i], scriptID+' '+' '.join(sys.argv[1:])) for i,o in enumerate(['Min','Mid','Max']): - table.add('eigvec{}({})'.format(o,tensor),v[:,:,i], - scriptID+' '+' '.join(sys.argv[1:])) + table.add('eigvec{}({})'.format(o,tensor),v[:,:,i],scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/addStrainTensors.py b/processing/post/addStrainTensors.py index 77015a91f..84c460b00 100755 --- a/processing/post/addStrainTensors.py +++ b/processing/post/addStrainTensors.py @@ -86,13 +86,13 @@ for name in filenames: table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) for defgrad in options.defgrad: - F = table.get(defgrad).reshape((-1,3,3)) + F = table.get(defgrad).reshape(-1,3,3) for theStretch in stretches: for theStrain in strains: (t,m) = parameters(theStretch,theStrain) label = '{}({}){}'.format(theStrain,theStretch,defgrad if defgrad != 'f' else '') table.add(label, - damask.mechanics.strain_tensor(F,t,m).reshape((-1,9)), + damask.mechanics.strain_tensor(F,t,m).reshape(-1,9), 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 0d3948251..39d925d19 100755 --- a/processing/post/averageDown.py +++ b/processing/post/averageDown.py @@ -91,7 +91,7 @@ for name in filenames: table = damask.Table(averagedDown,table.shapes,table.comments) coords = damask.grid_filters.cell_coord0(packedGrid,size,shift/packedGrid*size+origin) - table.set(options.pos, coords.reshape((-1,3))) + table.set(options.pos, coords.reshape(-1,3)) outname = os.path.join(os.path.dirname(name),prefix+os.path.basename(name)) diff --git a/processing/post/binXY.py b/processing/post/binXY.py index e9924a28a..860b70027 100755 --- a/processing/post/binXY.py +++ b/processing/post/binXY.py @@ -2,6 +2,7 @@ import os import sys +from io import StringIO from optparse import OptionParser import numpy as np @@ -71,60 +72,30 @@ parser.set_defaults(bins = (10,10), ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] -minmax = np.array([np.array(options.xrange), - np.array(options.yrange), - np.array(options.zrange)]) -grid = np.zeros(options.bins,'f') -result = np.zeros((options.bins[0],options.bins[1],3),'f') +minmax = np.array([options.xrange,options.yrange,options.zrange]) +result = np.empty((options.bins[0],options.bins[1],3),'f') if options.data is None: parser.error('no data columns specified.') -labels = list(options.data) - - -if options.weight is not None: labels += [options.weight] # prevent character splitting of single string value - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: - try: - table = damask.ASCIItable(name = name, - outname = os.path.join(os.path.dirname(name), - 'binned-{}-{}_'.format(*options.data) + - ('weighted-{}_'.format(options.weight) if options.weight else '') + - os.path.basename(name)) if name else name) - except IOError: - continue damask.util.report(scriptName,name) -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - missing_labels = table.data_readArray(labels) - - if len(missing_labels) > 0: - damask.util.croak('column{} {} not found.'.format('s' if len(missing_labels) > 1 else '',', '.join(missing_labels))) - table.close(dismiss = True) - continue + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + data = np.hstack((table.get(options.data[0]),table.get(options.data[1]))) for c in (0,1): # check data minmax for x and y (i = 0 and 1) - if (minmax[c] == 0.0).all(): minmax[c] = [table.data[:,c].min(),table.data[:,c].max()] + if (minmax[c] == 0.0).all(): minmax[c] = [data[:,c].min(),data[:,c].max()] if options.type[c].lower() == 'log': # if log scale - table.data[:,c] = np.log(table.data[:,c]) # change x,y coordinates to log + data[:,c] = np.log(data[:,c]) # change x,y coordinates to log minmax[c] = np.log(minmax[c]) # change minmax to log, too delta = minmax[:,1]-minmax[:,0] - (grid,xedges,yedges) = np.histogram2d(table.data[:,0],table.data[:,1], + (grid,xedges,yedges) = np.histogram2d(data[:,0],data[:,1], bins=options.bins, range=minmax[:2], - weights=None if options.weight is None else table.data[:,2]) - + weights=table.get(options.weight) if options.weight else None) if options.normCol: for x in range(options.bins[0]): sum = np.sum(grid[x,:]) @@ -153,24 +124,20 @@ for name in filenames: for y in range(options.bins[1]): result[x,y,:] = [minmax[0,0]+delta[0]/options.bins[0]*(x+0.5), minmax[1,0]+delta[1]/options.bins[1]*(y+0.5), - min(1.0,max(0.0,(grid[x,y]-minmax[2,0])/delta[2]))] + np.clip((grid[x,y]-minmax[2,0])/delta[2],0.0,1.0)] for c in (0,1): if options.type[c].lower() == 'log': result[:,:,c] = np.exp(result[:,:,c]) if options.invert: result[:,:,2] = 1.0 - result[:,:,2] -# --- assemble header ------------------------------------------------------------------------------- - - table.info_clear() - table.info_append(scriptID + '\t' + ' '.join(sys.argv[1:])) - table.labels_clear() - table.labels_append(['bin_%s'%options.data[0],'bin_%s'%options.data[1],'z']) - table.head_write() - -# --- output result --------------------------------------------------------------------------------- - - table.data = result.reshape(options.bins[0]*options.bins[1],3) - table.data_writeArray() - - table.close() + comments = scriptID + '\t' + ' '.join(sys.argv[1:]) + shapes = {'bin_%s'%options.data[0]:(1,),'bin_%s'%options.data[1]:(1,),'z':(1,)} + table = damask.Table(result.reshape(options.bins[0]*options.bins[1],3),shapes,[comments]) + if name: + outname = os.path.join(os.path.dirname(name),'binned-{}-{}_'.format(*options.data) + + ('weighted-{}_'.format(options.weight) if options.weight else '') + + os.path.basename(name)) + table.to_ASCII(outname) + else: + table.to_ASCII(sys.stdout) diff --git a/processing/post/blowUp.py b/processing/post/blowUp.py index 718858e1c..316b74753 100755 --- a/processing/post/blowUp.py +++ b/processing/post/blowUp.py @@ -60,12 +60,12 @@ for name in filenames: outSize = grid*packing data = table.data.values.reshape(tuple(grid)+(-1,)) - blownUp = ndimage.interpolation.zoom(data,tuple(packing)+(1,),order=0,mode='nearest').reshape((outSize.prod(),-1)) + blownUp = ndimage.interpolation.zoom(data,tuple(packing)+(1,),order=0,mode='nearest').reshape(outSize.prod(),-1) table = damask.Table(blownUp,table.shapes,table.comments) coords = damask.grid_filters.cell_coord0(outSize,size,origin) - table.set(options.pos,coords.reshape((-1,3))) + table.set(options.pos,coords.reshape(-1,3)) table.set('elem',np.arange(1,outSize.prod()+1)) outname = os.path.join(os.path.dirname(name),prefix+os.path.basename(name)) diff --git a/processing/post/histogram.py b/processing/post/histogram.py deleted file mode 100755 index 20e377116..000000000 --- a/processing/post/histogram.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python2.7 - -import os -import sys -from optparse import OptionParser - -import numpy as np - -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 = """ -Generate histogram of N bins in given data range. - -""", version = scriptID) - -parser.add_option('-d','--data', - dest = 'data', - type = 'string', metavar = 'string', - help = 'column heading for data') -parser.add_option('-w','--weights', - dest = 'weights', - type = 'string', metavar = 'string', - help = 'column heading for weights') -parser.add_option('--range', - dest = 'range', - type = 'float', nargs = 2, metavar = 'float float', - help = 'data range of histogram [min - max]') -parser.add_option('-N', - dest = 'N', - type = 'int', metavar = 'int', - help = 'number of bins') -parser.add_option('--density', - dest = 'density', - action = 'store_true', - help = 'report probability density') -parser.add_option('--logarithmic', - dest = 'log', - action = 'store_true', - help = 'logarithmically spaced bins') -parser.set_defaults(data = None, - weights = None, - range = None, - N = None, - density = False, - log = False, - ) - -(options,filenames) = parser.parse_args() - -if not options.data: parser.error('no data specified.') -if not options.N: parser.error('no bin number specified.') - -if options.log: - def forward(x): - return np.log(x) - def reverse(x): - return np.exp(x) -else: - def forward(x): - return x - def reverse(x): - return x - - -# --- loop over input files ------------------------------------------------------------------------ - -if filenames == []: filenames = [None] - -for name in filenames: - try: - table = damask.ASCIItable(name = name, readonly = True) - except IOError: - continue - damask.util.report(scriptName,name) - -# ------------------------------------------ read header ------------------------------------------ - - table.head_read() - -# ------------------------------------------ sanity checks ---------------------------------------- - - errors = [] - remarks = [] - - if table.label_dimension(options.data) != 1: errors.append('data {} are not scalar.'.format(options.data)) - if options.weights and \ - table.label_dimension(options.data) != 1: errors.append('weights {} are not scalar.'.format(options.weights)) - - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - -# --------------- read data ---------------------------------------------------------------- - - table.data_readArray([options.data,options.weights]) - -# --------------- auto range --------------------------------------------------------------- - - if options.range is None: - rangeMin,rangeMax = min(table.data[:,0]),max(table.data[:,0]) - else: - rangeMin,rangeMax = min(options.range),max(options.range) - -# --------------- bin data ---------------------------------------------------------------- - - count,edges = np.histogram(table.data[:,0], - bins = reverse(forward(rangeMin) + np.arange(options.N+1) * - (forward(rangeMax)-forward(rangeMin))/options.N), - range = (rangeMin,rangeMax), - weights = None if options.weights is None else table.data[:,1], - density = options.density, - ) - bincenter = reverse(forward(rangeMin) + (0.5+np.arange(options.N)) * - (forward(rangeMax)-forward(rangeMin))/options.N) # determine center of bins - -# ------------------------------------------ assemble header --------------------------------------- - - table.info_clear() - table.info_append([scriptID + '\t' + ' '.join(sys.argv[1:]), - scriptID + ':\t' + - 'data range {} -- {}'.format(rangeMin,rangeMax) + - (' (log)' if options.log else ''), - ]) - table.labels_clear() - table.labels_append(['bincenter','count']) - table.head_write() - -# ------------------------------------------ output result ----------------------------------------- - - table.data = np.squeeze(np.dstack((bincenter,count))) - table.data_writeArray() - -# ------------------------------------------ output finalization ----------------------------------- - - table.close() # close ASCII tables diff --git a/processing/post/imageData.py b/processing/post/imageData.py index 2ca3ef6e7..51547d4eb 100755 --- a/processing/post/imageData.py +++ b/processing/post/imageData.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3 import os import sys @@ -102,6 +102,7 @@ parser.set_defaults(label = None, ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.pixelsize > 1: (options.pixelsizex,options.pixelsizey) = [options.pixelsize]*2 @@ -112,9 +113,6 @@ if options.invert: theMap = theMap.invert() theColors = np.uint8(np.array(theMap.export(format = 'list',steps = 256))*255) # --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: try: table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True) diff --git a/processing/post/imageDataDeformed.py b/processing/post/imageDataDeformed.py index 79f81e29e..b9219ac47 100755 --- a/processing/post/imageDataDeformed.py +++ b/processing/post/imageDataDeformed.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3 import os import sys @@ -95,6 +95,7 @@ parser.set_defaults(label = None, ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] options.size = np.array(options.size) options.dimension = np.array(options.dimension) @@ -109,16 +110,12 @@ if options.invert: theMap = theMap.invert() theColors = np.uint8(np.array(theMap.export(format='list',steps=256))*255) # --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: try: - table = damask.ASCIItable(name = name, readonly = True, - labeled = options.label is not None) + table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True) except IOError: continue - table.report_name(scriptName,name) + damask.util.report(scriptName,name) # ------------------------------------------ read header ------------------------------------------ diff --git a/processing/post/imageDataRGB.py b/processing/post/imageDataRGB.py index 4a1d521b2..a34a48f4f 100755 --- a/processing/post/imageDataRGB.py +++ b/processing/post/imageDataRGB.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3 import os import sys @@ -72,18 +72,15 @@ parser.set_defaults(label = None, ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.dimension == []: parser.error('dimension of data array missing') if options.pixelsize > 1: (options.pixelsizex,options.pixelsizey) = [options.pixelsize]*2 # --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] - for name in filenames: try: - table = damask.ASCIItable(name = name, readonly = True, - labeled = options.label is not None) + table = damask.ASCIItable(name = name, labeled = options.label is not None, readonly = True) except IOError: continue damask.util.report(scriptName,name) diff --git a/processing/post/reLabel.py b/processing/post/reLabel.py index 85d16acea..da608e994 100755 --- a/processing/post/reLabel.py +++ b/processing/post/reLabel.py @@ -44,9 +44,7 @@ for name in filenames: damask.util.report(scriptName,name) table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - for i,label in enumerate(options.label): - table.rename(label, - options.substitute[i], - scriptID+' '+' '.join(sys.argv[1:])) + for label,substitute in zip(options.label,options.substitute): + table.rename(label,substitute,scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/rotateData.py b/processing/post/rotateData.py index f56b04236..d270eb79e 100755 --- a/processing/post/rotateData.py +++ b/processing/post/rotateData.py @@ -2,10 +2,9 @@ import os import sys +from io import StringIO from optparse import OptionParser -import numpy as np - import damask @@ -40,65 +39,25 @@ parser.set_defaults(rotation = (1.,1.,1.,0), ) (options,filenames) = parser.parse_args() +if filenames == []: filenames = [None] if options.data is None: parser.error('no data column specified.') -r = damask.Rotation.fromAxisAngle(np.array(options.rotation),options.degrees,normalise=True) - -# --- loop over input files ------------------------------------------------------------------------- - -if filenames == []: filenames = [None] +r = damask.Rotation.fromAxisAngle(options.rotation,options.degrees,normalise=True) for name in filenames: - try: - table = damask.ASCIItable(name = name) - except IOError: - continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) + + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) -# --- interpret header ---------------------------------------------------------------------------- + for data in options.data: + d = table.get(data) + if table.shapes[data] == (9,): d=d.reshape(-1,3,3) + for i,l in enumerate(d): + d[i] = r*l + if table.shapes[data] == (9,): d=d.reshape(-1,9) + + table.set(data,d,scriptID+' '+' '.join(sys.argv[1:])) - table.head_read() - - errors = [] - remarks = [] - active = {'vector':[],'tensor':[]} - - for i,dim in enumerate(table.label_dimension(options.data)): - label = options.data[i] - if dim == -1: - remarks.append('"{}" not found...'.format(label)) - elif dim == 3: - remarks.append('adding vector "{}"...'.format(label)) - active['vector'].append(label) - elif dim == 9: - remarks.append('adding tensor "{}"...'.format(label)) - active['tensor'].append(label) - - 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 v in active['vector']: - column = table.label_index(v) - table.data[column:column+3] = r * np.array(list(map(float,table.data[column:column+3]))) - for t in active['tensor']: - column = table.label_index(t) - table.data[column:column+9] = (r * np.array(list(map(float,table.data[column:column+9]))).reshape((3,3))).reshape(9) - - 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/scaleData.py b/processing/post/scaleData.py index 58f853251..c6ce0a64e 100755 --- a/processing/post/scaleData.py +++ b/processing/post/scaleData.py @@ -43,9 +43,7 @@ for name in filenames: damask.util.report(scriptName,name) table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - for i,label in enumerate(options.labels): - table.set(label, - table.get(label)*float(options.factor[i]), - scriptID+' '+' '.join(sys.argv[1:])) + for label,factor in zip(options.labels,options.factor): + table.set(label,table.get(label)*float(factor),scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/shiftData.py b/processing/post/shiftData.py index 57b20fbd0..341a78c7e 100755 --- a/processing/post/shiftData.py +++ b/processing/post/shiftData.py @@ -43,9 +43,7 @@ for name in filenames: damask.util.report(scriptName,name) table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - for i,label in enumerate(options.labels): - table.set(label, - table.get(label)+float(options.offset[i]), - scriptID+' '+' '.join(sys.argv[1:])) + for label,offset in zip(options.labels,options.offset): + table.set(label,table.get(label)+float(offset),scriptID+' '+' '.join(sys.argv[1:])) table.to_ASCII(sys.stdout if name is None else name) diff --git a/processing/post/vtk_addData.py b/processing/post/vtk_addData.py new file mode 100755 index 000000000..25fcdada0 --- /dev/null +++ b/processing/post/vtk_addData.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +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]) + + +# -------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------- + +parser = OptionParser(option_class=damask.extendableOption, + usage='%prog options [ASCIItable(s)]', + description = 'Add scalars/vectors, tensors, and/or a RGB tuples from ASCIItable ' + + 'to existing VTK file (.vtr/.vtu/.vtp).', + version = scriptID) + +parser.add_option( '--vtk', + dest = 'vtk', + type = 'string', metavar = 'string', + help = 'VTK file name') +parser.add_option('-d', '--data', + dest = 'data', + action = 'extend', metavar = '', + help = 'scalar/vector value(s) label(s)') +parser.add_option('-t', '--tensor', + dest = 'tensor', + action = 'extend', metavar = '', + help = 'tensor (3x3) value label(s)') +parser.add_option('-c', '--color', + dest = 'color', + action = 'extend', metavar = '', + help = 'RGB color tuple label') + +parser.set_defaults(data = [], + tensor = [], + color = [], +) + +(options, filenames) = parser.parse_args() +if filenames == []: filenames = [None] + +if not options.vtk: + parser.error('No VTK file specified.') + +for name in filenames: + damask.util.report(scriptName,name) + + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + vtk = damask.VTK.from_file(options.vtk) + + for data in options.data+options.tensor: + vtk.add(table.get(data),data) + for color in options.color: + vtk.add((table.get(color)*255).astype(np.uint8),color) + + vtk.write(options.vtk) diff --git a/processing/post/vtk_addGridData.py b/processing/post/vtk_addGridData.py deleted file mode 100755 index 8e76cfca8..000000000 --- a/processing/post/vtk_addGridData.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from io import StringIO -from optparse import OptionParser - -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 = OptionParser(option_class=damask.extendableOption, - usage='%prog options [ASCIItable(s)]', - description = "Add scalars, vectors, tensors, and/or an RGB tuple from ASCIItable " - + "to existing VTK grid (.vtr/.vtk/.vtu).", - version = scriptID) - -parser.add_option( '--vtk', - dest = 'vtk', - type = 'string', metavar = 'string', - help = 'VTK file name') -parser.add_option('-r', '--render', - dest = 'render', - action = 'store_true', - help = 'open output in VTK render window') -parser.add_option('-d', '--data', - dest = 'data', - action = 'extend', metavar = '', - help = 'scalar/vector value(s) label(s)') -parser.add_option('-t', '--tensor', - dest = 'tensor', - action = 'extend', metavar = '', - help = 'tensor (3x3) value label(s)') -parser.add_option('-c', '--color', - dest = 'color', - action = 'extend', metavar = '', - help = 'RGB color tuple label') - -parser.set_defaults(data = [], - tensor = [], - color = [], -) - -(options, filenames) = parser.parse_args() -if filenames == []: filenames = [None] - -if not options.vtk: parser.error('No VTK file specified.') -if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') - -vtk_file,vtk_ext = os.path.splitext(options.vtk) - -if vtk_ext == '.vtr': - reader = vtk.vtkXMLRectilinearGridReader() - reader.SetFileName(options.vtk) - reader.Update() - rGrid = reader.GetOutput() - writer = vtk.vtkXMLRectilinearGridWriter() -elif vtk_ext == '.vtk': - reader = vtk.vtkGenericDataObjectReader() - reader.SetFileName(options.vtk) - reader.Update() - rGrid = reader.GetRectilinearGridOutput() - writer = vtk.vtkXMLRectilinearGridWriter() -elif vtk_ext == '.vtu': - reader = vtk.vtkXMLUnstructuredGridReader() - reader.SetFileName(options.vtk) - reader.Update() - rGrid = reader.GetOutput() - writer = vtk.vtkXMLUnstructuredGridWriter() -else: - parser.error('Unsupported VTK file type extension.') - -writer.SetFileName(vtk_file+'.'+writer.GetDefaultFileExtension()) - -Npoints = rGrid.GetNumberOfPoints() -Ncells = rGrid.GetNumberOfCells() - -damask.util.croak('{}: {} points and {} cells...'.format(options.vtk,Npoints,Ncells)) - -for name in filenames: - damask.util.report(scriptName,name) - - table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - - VTKarray = {} - for data in options.data: - VTKarray[data] = numpy_support.numpy_to_vtk(table.get(data).copy(), - deep=True,array_type=vtk.VTK_DOUBLE) - VTKarray[data].SetName(data) - - for color in options.color: - VTKarray[color] = numpy_support.numpy_to_vtk((table.get(color)*255).astype(int).copy(), - deep=True,array_type=vtk.VTK_UNSIGNED_CHAR) - VTKarray[color].SetName(color) - - for tensor in options.tensor: - data = damask.mechanics.symmetric(table.get(tensor).reshape((-1,3,3))).reshape((-1,9)) - VTKarray[tensor] = numpy_support.numpy_to_vtk(data.copy(), - deep=True,array_type=vtk.VTK_DOUBLE) - VTKarray[tensor].SetName(tensor) - - -# ------------------------------------------ add data --------------------------------------- - - if len(table.data) == Npoints: mode = 'point' - elif len(table.data) == Ncells: mode = 'cell' - else: - damask.util.croak('Data count is incompatible with grid...') - continue - - damask.util.croak('{} mode...'.format(mode)) - - for data in VTKarray: - if mode == 'cell': rGrid.GetCellData().AddArray(VTKarray[data]) - elif mode == 'point': rGrid.GetPointData().AddArray(VTKarray[data]) - rGrid.Modified() - -# ------------------------------------------ output result --------------------------------------- - - writer.SetDataModeToBinary() - writer.SetCompressorTypeToZLib() - writer.SetInputData(rGrid) - writer.Write() - -# ------------------------------------------ render result --------------------------------------- - -if options.render: - mapper = vtk.vtkDataSetMapper() - mapper.SetInputData(rGrid) - actor = vtk.vtkActor() - actor.SetMapper(mapper) - -# Create the graphics structure. The renderer renders into the -# render window. The render window interactively captures mouse events -# and will perform appropriate camera or actor manipulation -# depending on the nature of the events. - - ren = vtk.vtkRenderer() - - renWin = vtk.vtkRenderWindow() - renWin.AddRenderer(ren) - - ren.AddActor(actor) - ren.SetBackground(1, 1, 1) - renWin.SetSize(200, 200) - - iren = vtk.vtkRenderWindowInteractor() - iren.SetRenderWindow(renWin) - - iren.Initialize() - renWin.Render() - iren.Start() diff --git a/processing/post/vtk_addPointCloudData.py b/processing/post/vtk_addPointCloudData.py deleted file mode 100755 index 833bfc88e..000000000 --- a/processing/post/vtk_addPointCloudData.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -from io import StringIO -from optparse import OptionParser - -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 = OptionParser(option_class=damask.extendableOption, - usage='%prog options [ASCIItable(s)]', - description = "Add scalars, vectors, tensors, and/or an RGB tuple from ASCIItable " - + "VTK point cloud (.vtp).", - version = scriptID) - -parser.add_option( '--vtk', - dest = 'vtk', - type = 'string', metavar = 'string', - help = 'VTK file name') -parser.add_option('-r', '--render', - dest = 'render', - action = 'store_true', - help = 'open output in VTK render window') -parser.add_option('-d', '--data', - dest = 'data', - action = 'extend', metavar = '', - help = 'scalar/vector value(s) label(s)') -parser.add_option('-t', '--tensor', - dest = 'tensor', - action = 'extend', metavar = '', - help = 'tensor (3x3) value label(s)') -parser.add_option('-c', '--color', - dest = 'color', - action = 'extend', metavar = '', - help = 'RGB color tuple label') - -parser.set_defaults(data = [], - tensor = [], - color = [], -) - -(options, filenames) = parser.parse_args() -if filenames == []: filenames = [None] - -if not options.vtk: parser.error('No VTK file specified.') -if not os.path.exists(options.vtk): parser.error('VTK file does not exist.') - -vtk_file,vtk_ext = os.path.splitext(options.vtk) - -if vtk_ext == '.vtp': - reader = vtk.vtkXMLPolyDataReader() - reader.SetFileName(options.vtk) - reader.Update() - Polydata = reader.GetOutput() -elif vtk_ext == '.vtk': - reader = vtk.vtkGenericDataObjectReader() - reader.SetFileName(options.vtk) - reader.Update() - Polydata = reader.GetPolyDataOutput() -else: - parser.error('unsupported VTK file type extension.') - -Npoints = Polydata.GetNumberOfPoints() -Ncells = Polydata.GetNumberOfCells() -Nvertices = Polydata.GetNumberOfVerts() - -if Npoints != Ncells or Npoints != Nvertices: - parser.error('number of points, cells, and vertices in VTK differ from each other.') - -damask.util.croak('{}: {} points/vertices/cells...'.format(options.vtk,Npoints)) - -for name in filenames: - damask.util.report(scriptName,name) - - table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - - VTKarray = {} - for data in options.data: - VTKarray[data] = numpy_support.numpy_to_vtk(table.get(data).copy(), - deep=True,array_type=vtk.VTK_DOUBLE) - VTKarray[data].SetName(data) - - for color in options.color: - VTKarray[color] = numpy_support.numpy_to_vtk((table.get(color)*255).astype(int).copy(), - deep=True,array_type=vtk.VTK_UNSIGNED_CHAR) - VTKarray[color].SetName(color) - - for tensor in options.tensor: - data = damask.mechanics.symmetric(table.get(tensor).reshape((-1,3,3))).reshape((-1,9)) - VTKarray[tensor] = numpy_support.numpy_to_vtk(data.copy(), - deep=True,array_type=vtk.VTK_DOUBLE) - VTKarray[tensor].SetName(tensor) - - - for data in VTKarray: - Polydata.GetPointData().AddArray(VTKarray[data]) - Polydata.Modified() - -# ------------------------------------------ output result --------------------------------------- - - writer = vtk.vtkXMLPolyDataWriter() - writer.SetDataModeToBinary() - writer.SetCompressorTypeToZLib() - writer.SetFileName(vtk_file+'.'+writer.GetDefaultFileExtension()) - writer.SetInputData(Polydata) - writer.Write() - -# ------------------------------------------ render result --------------------------------------- - -if options.render: - mapper = vtk.vtkDataSetMapper() - mapper.SetInputData(Polydata) - actor = vtk.vtkActor() - actor.SetMapper(mapper) - -# Create the graphics structure. The renderer renders into the -# render window. The render window interactively captures mouse events -# and will perform appropriate camera or actor manipulation -# depending on the nature of the events. - - ren = vtk.vtkRenderer() - - renWin = vtk.vtkRenderWindow() - renWin.AddRenderer(ren) - - ren.AddActor(actor) - ren.SetBackground(1, 1, 1) - renWin.SetSize(200, 200) - - iren = vtk.vtkRenderWindowInteractor() - iren.SetRenderWindow(renWin) - - iren.Initialize() - renWin.Render() - iren.Start() diff --git a/processing/post/vtk_pointCloud.py b/processing/post/vtk_pointCloud.py index 44f719267..aae31d0ff 100755 --- a/processing/post/vtk_pointCloud.py +++ b/processing/post/vtk_pointCloud.py @@ -5,8 +5,6 @@ import sys from io import StringIO from optparse import OptionParser -import vtk - import damask @@ -36,42 +34,12 @@ parser.set_defaults(pos = 'pos', if filenames == []: filenames = [None] for name in filenames: - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) - table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + v = damask.VTK.from_polyData(table.get(options.pos)) -# ------------------------------------------ process data --------------------------------------- - - Polydata = vtk.vtkPolyData() - Points = vtk.vtkPoints() - Vertices = vtk.vtkCellArray() - - for p in table.get(options.pos): - pointID = Points.InsertNextPoint(p) - Vertices.InsertNextCell(1) - Vertices.InsertCellPoint(pointID) - - Polydata.SetPoints(Points) - Polydata.SetVerts(Vertices) - Polydata.Modified() - -# ------------------------------------------ output result --------------------------------------- - - if name: - writer = vtk.vtkXMLPolyDataWriter() - writer.SetCompressorTypeToZLib() - writer.SetDataModeToBinary() - writer.SetFileName(os.path.join(os.path.split(name)[0], - os.path.splitext(os.path.split(name)[1])[0] + - '.' + writer.GetDefaultFileExtension())) - else: - writer = vtk.vtkDataSetWriter() - writer.SetHeader('# powered by '+scriptID) - writer.WriteToOutputStringOn() - - - writer.SetInputData(Polydata) - - writer.Write() - - if name is None: sys.stdout.write(writer.GetOutputString()) + if name: + v.write(os.path.splitext(name)[0]) + else: + sys.stdout.write(v.__repr__()) diff --git a/processing/post/vtk_rectilinearGrid.py b/processing/post/vtk_rectilinearGrid.py index 2ccad6319..c8a7d1a6d 100755 --- a/processing/post/vtk_rectilinearGrid.py +++ b/processing/post/vtk_rectilinearGrid.py @@ -5,9 +5,6 @@ import sys from io import StringIO from optparse import OptionParser -import vtk -import numpy as np - import damask @@ -44,54 +41,18 @@ parser.set_defaults(mode = 'cell', if filenames == []: filenames = [None] for name in filenames: - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) - table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + 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]))] + \ - [3.0 * coords[i][-1] - coords[i][-1 - int(len(coords[i]) > 1)]]) for i in range(3)] + if options.mode == 'cell': + grid, size, origin = damask.grid_filters.cell_coord0_gridSizeOrigin(table.get(options.pos)) + elif options.mode == 'point': + grid, size, origin = damask.grid_filters.node_coord0_gridSizeOrigin(table.get(options.pos)) - grid = np.array(list(map(len,coords)),'i') - N = grid.prod() if options.mode == 'point' else (grid-1).prod() + v = damask.VTK.from_rectilinearGrid(grid,size,origin) -# ------------------------------------------ process data --------------------------------------- - - rGrid = vtk.vtkRectilinearGrid() - coordArray = [vtk.vtkDoubleArray(), - vtk.vtkDoubleArray(), - vtk.vtkDoubleArray(), - ] - - rGrid.SetDimensions(*grid) - for i,points in enumerate(coords): - for point in points: - coordArray[i].InsertNextValue(point) - - rGrid.SetXCoordinates(coordArray[0]) - rGrid.SetYCoordinates(coordArray[1]) - rGrid.SetZCoordinates(coordArray[2]) - - -# ------------------------------------------ output result --------------------------------------- - - if name: - writer = vtk.vtkXMLRectilinearGridWriter() - writer.SetCompressorTypeToZLib() - writer.SetDataModeToBinary() - writer.SetFileName(os.path.join(os.path.split(name)[0], - os.path.splitext(os.path.split(name)[1])[0] + - '_{}({})'.format(options.pos, options.mode) + - '.' + writer.GetDefaultFileExtension())) - else: - writer = vtk.vtkDataSetWriter() - writer.SetHeader('# powered by '+scriptID) - writer.WriteToOutputStringOn() - - writer.SetInputData(rGrid) - - writer.Write() - - if name is None: sys.stdout.write(writer.GetOutputString()) + if name: + v.write('{}_{}({})'.format(os.path.splitext(name)[0],options.pos,options.mode)) + else: + sys.stdout.write(v.__repr__()) diff --git a/processing/pre/geom_check.py b/processing/pre/geom_check.py index a79c7e1a4..e7e4d1009 100755 --- a/processing/pre/geom_check.py +++ b/processing/pre/geom_check.py @@ -22,18 +22,16 @@ Writes vtk file for visualization. """, 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) - - if name is None: - sys.stdout.write(geom.to_vtk()) - else: - geom.to_vtk(os.path.splitext(name)[0]) + damask.util.croak(geom) + + if name: + geom.to_vtk(os.path.splitext(name)[0]) + else: + sys.stdout.write(geom.to_vtk()) diff --git a/processing/pre/geom_fromVoronoiTessellation.py b/processing/pre/geom_fromVoronoiTessellation.py index d5ec43701..3ecf7c099 100755 --- a/processing/pre/geom_fromVoronoiTessellation.py +++ b/processing/pre/geom_fromVoronoiTessellation.py @@ -3,6 +3,8 @@ import os import sys import multiprocessing +from io import StringIO +from functools import partial from optparse import OptionParser,OptionGroup import numpy as np @@ -15,73 +17,40 @@ scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -def laguerreTessellation(undeformed, coords, weights, grains, periodic = True, cpus = 2): +def findClosestSeed(seeds, weights, point): + return np.argmin(np.sum((np.broadcast_to(point,(len(seeds),3))-seeds)**2,axis=1) - weights) - def findClosestSeed(fargs): - point, seeds, myWeights = fargs - tmp = np.repeat(point.reshape(3,1), len(seeds), axis=1).T - dist = np.sum((tmp - seeds)**2,axis=1) -myWeights - return np.argmin(dist) # seed point closest to point - copies = \ - np.array([ - [ -1,-1,-1 ], - [ 0,-1,-1 ], - [ 1,-1,-1 ], - [ -1, 0,-1 ], - [ 0, 0,-1 ], - [ 1, 0,-1 ], - [ -1, 1,-1 ], - [ 0, 1,-1 ], - [ 1, 1,-1 ], - [ -1,-1, 0 ], - [ 0,-1, 0 ], - [ 1,-1, 0 ], - [ -1, 0, 0 ], - [ 0, 0, 0 ], - [ 1, 0, 0 ], - [ -1, 1, 0 ], - [ 0, 1, 0 ], - [ 1, 1, 0 ], - [ -1,-1, 1 ], - [ 0,-1, 1 ], - [ 1,-1, 1 ], - [ -1, 0, 1 ], - [ 0, 0, 1 ], - [ 1, 0, 1 ], - [ -1, 1, 1 ], - [ 0, 1, 1 ], - [ 1, 1, 1 ], - ]).astype(float)*info['size'] if periodic else \ - np.array([ - [ 0, 0, 0 ], - ]).astype(float) +def Laguerre_tessellation(grid, seeds, grains, size, periodic, weights, cpus): - repeatweights = np.tile(weights,len(copies)).flatten(order='F') # Laguerre weights (1,2,3,1,2,3,...,1,2,3) - for i,vec in enumerate(copies): # periodic copies of seed points ... - try: seeds = np.append(seeds, coords+vec, axis=0) # ... (1+a,2+a,3+a,...,1+z,2+z,3+z) - except NameError: seeds = coords+vec - - if (repeatweights == 0.0).all(): # standard Voronoi (no weights, KD tree) - myKDTree = spatial.cKDTree(seeds) - devNull,closestSeeds = myKDTree.query(undeformed) - else: - damask.util.croak('...using {} cpu{}'.format(options.cpus, 's' if options.cpus > 1 else '')) - arguments = [[arg,seeds,repeatweights] for arg in list(undeformed)] - - if cpus > 1: # use multithreading - pool = multiprocessing.Pool(processes = cpus) # initialize workers - result = pool.map_async(findClosestSeed, arguments) # evaluate function in parallel - pool.close() - pool.join() - closestSeeds = np.array(result.get()).flatten() + if periodic: + weights_p = np.tile(weights,27).flatten(order='F') # Laguerre weights (1,2,3,1,2,3,...,1,2,3) + seeds_p = np.vstack((seeds -np.array([size[0],0.,0.]),seeds, seeds +np.array([size[0],0.,0.]))) + seeds_p = np.vstack((seeds_p-np.array([0.,size[1],0.]),seeds_p,seeds_p+np.array([0.,size[1],0.]))) + seeds_p = np.vstack((seeds_p-np.array([0.,0.,size[2]]),seeds_p,seeds_p+np.array([0.,0.,size[2]]))) else: - closestSeeds = np.zeros(len(arguments),dtype='i') - for i,arg in enumerate(arguments): - closestSeeds[i] = findClosestSeed(arg) + weights_p = weights.flatten() + seeds_p = seeds -# closestSeed is modulo number of original seed points (i.e. excluding periodic copies) - return grains[closestSeeds%coords.shape[0]] + if cpus > 1: + default_args = partial(findClosestSeed,seeds_p,weights_p) + pool = multiprocessing.Pool(processes = cpus) # initialize workers + result = pool.map_async(default_args, [point for point in grid]) # evaluate function in parallel + pool.close() + pool.join() + closestSeeds = np.array(result.get()).flatten() + else: + closestSeeds= np.array([findClosestSeed(seeds_p,weights_p,point) for point in grid]) + + return grains[closestSeeds%seeds.shape[0]] + + +def Voronoi_tessellation(grid, seeds, grains, size, periodic = True): + + KDTree = spatial.cKDTree(seeds,boxsize=size) if periodic else spatial.cKDTree(seeds) + devNull,closestSeeds = KDTree.query(grid) + + return grains[closestSeeds] # -------------------------------------------------------------------- @@ -123,16 +92,12 @@ group.add_option('-s', '--size', dest = 'size', type = 'float', nargs = 3, metavar=' '.join(['float']*3), - help = 'x,y,z size of hexahedral box') + help = 'x,y,z size of hexahedral box [1.0 1.0 1.0]') group.add_option('-o', '--origin', dest = 'origin', type = 'float', nargs = 3, metavar=' '.join(['float']*3), - help = 'origin of grid') -group.add_option('--nonnormalized', - dest = 'normalized', - action = 'store_false', - help = 'seed coordinates are not normalized to a unit cube') + help = 'origin of grid [0.0 0.0 0.0]') parser.add_option_group(group) @@ -191,114 +156,73 @@ parser.set_defaults(pos = 'pos', cpus = 2, laguerre = False, periodic = True, - normalized = True, config = True, ) (options,filenames) = parser.parse_args() - - if filenames == []: filenames = [None] for name in filenames: - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) - table = damask.ASCIItable(name = name, readonly = True) + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + size = np.ones(3) + origin = np.zeros(3) + for line in table.comments: + items = line.lower().strip().split() + key = items[0] if items else '' + if key == 'grid': + grid = np.array([ int(dict(zip(items[1::2],items[2::2]))[i]) for i in ['a','b','c']]) + elif key == 'size': + size = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) + elif key == 'origin': + origin = np.array([float(dict(zip(items[1::2],items[2::2]))[i]) for i in ['x','y','z']]) + if options.grid: grid = np.array(options.grid) + if options.size: size = np.array(options.size) + if options.origin: origin = np.array(options.origin) -# --- read header ---------------------------------------------------------------------------- + seeds = table.get(options.pos) - table.head_read() - info,extra_header = table.head_getGeom() + grains = table.get(options.microstructure) if options.microstructure in table.labels else np.arange(len(seeds))+1 + grainIDs = np.unique(grains).astype('i') + NgrainIDs = len(grainIDs) - if options.grid is not None: info['grid'] = options.grid - if options.size is not None: info['size'] = options.size - if options.origin is not None: info['origin'] = options.origin + if options.eulers in table.labels: + eulers = table.get(options.eulers) -# ------------------------------------------ sanity checks --------------------------------------- + coords = damask.grid_filters.cell_coord0(grid,size,-origin).reshape(-1,3,order='F') - remarks = [] - errors = [] - labels = [] + if options.laguerre: + indices = Laguerre_tessellation(coords,seeds,grains,size,options.periodic, + table.get(options.weight),options.cpus) + else: + indices = Voronoi_tessellation (coords,seeds,grains,size,options.periodic) - hasGrains = table.label_dimension(options.microstructure) == 1 - hasEulers = table.label_dimension(options.eulers) == 3 - hasWeights = table.label_dimension(options.weight) == 1 and options.laguerre + config_header = [] + if options.config: - for i in range(3): - if info['size'][i] <= 0.0: # any invalid size? - info['size'][i] = float(info['grid'][i])/max(info['grid']) # normalize to grid - remarks.append('rescaling size {} to {}...'.format(['x','y','z'][i],info['size'][i])) + if options.eulers in table.labels: + config_header += [''] + for ID in grainIDs: + eulerID = np.nonzero(grains == ID)[0][0] # find first occurrence of this grain id + config_header += ['[Grain{}]'.format(ID), + '(gauss)\tphi1 {:.2f}\tPhi {:.2f}\tphi2 {:.2f}'.format(*eulers[eulerID]) + ] + if options.axes: config_header += ['axes\t{} {} {}'.format(*options.axes)] - if table.label_dimension(options.pos) != 3: - errors.append('seed positions "{}" have dimension {}.'.format(options.pos, - table.label_dimension(options.pos))) - else: - labels += [options.pos] + config_header += [''] + for ID in grainIDs: + config_header += ['[Grain{}]'.format(ID), + '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,ID) + ] - if not options.normalized: remarks.append('using real-space seed coordinates...') - if not hasEulers: remarks.append('missing seed orientations...') - else: labels += [options.eulers] - if not hasGrains: remarks.append('missing seed microstructure indices...') - else: labels += [options.microstructure] - if options.laguerre and not hasWeights: remarks.append('missing seed weights...') - else: labels += [options.weight] + config_header += [''] - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - table.close(dismiss=True) - continue + header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\ + + config_header + geom = damask.Geom(indices.reshape(grid),size,origin, + homogenization=options.homogenization,comments=header) + damask.util.croak(geom) -# ------------------------------------------ read seeds --------------------------------------- - - table.data_readArray(labels) - coords = table.data[:,table.label_indexrange(options.pos)] * info['size'] if options.normalized \ - else table.data[:,table.label_indexrange(options.pos)] - info['origin'] - eulers = table.data[:,table.label_indexrange(options.eulers)] if hasEulers \ - else np.zeros(3*len(coords)) - grains = table.data[:,table.label_indexrange(options.microstructure)].astype(int) if hasGrains \ - else 1+np.arange(len(coords)) - weights = table.data[:,table.label_indexrange(options.weight)] if hasWeights \ - else np.zeros(len(coords)) - grainIDs = np.unique(grains).astype('i') - NgrainIDs = len(grainIDs) - -# --- tessellate microstructure ------------------------------------------------------------ - - x = (np.arange(info['grid'][0])+0.5)*info['size'][0]/info['grid'][0] - y = (np.arange(info['grid'][1])+0.5)*info['size'][1]/info['grid'][1] - z = (np.arange(info['grid'][2])+0.5)*info['size'][2]/info['grid'][2] - X,Y,Z = np.meshgrid(x, y, z,indexing='ij') - grid = np.stack((X,Y,Z),axis=-1).reshape((np.prod(info['grid']),3),order='F') - - damask.util.croak('tessellating...') - indices = laguerreTessellation(grid, coords, weights, grains, options.periodic, options.cpus) - - config_header = [] - if options.config: - - 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(ID), - '(gauss)\tphi1 {:.2f}\tPhi {:.2f}\tphi2 {:.2f}'.format(*eulers[eulerID]) - ] - if options.axes is not None: config_header += ['axes\t{} {} {}'.format(*options.axes)] - - config_header += [''] - for ID in grainIDs: - config_header += ['[Grain{}]'.format(ID), - '(constituent)\tphase {}\ttexture {}\tfraction 1.0'.format(options.phase,ID) - ] - - config_header += [''] - - header = [scriptID + ' ' + ' '.join(sys.argv[1:])]\ - + config_header - geom = damask.Geom(indices.reshape(info['grid'],order='F'),info['size'],info['origin'], - homogenization=options.homogenization,comments=header) - damask.util.croak(geom) - - geom.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',pack=False) + geom.to_file(sys.stdout if name is None else os.path.splitext(name)[0]+'.geom',pack=False) diff --git a/processing/pre/geom_toTable.py b/processing/pre/geom_toTable.py index 494bbaffa..f1b5b9555 100755 --- a/processing/pre/geom_toTable.py +++ b/processing/pre/geom_toTable.py @@ -30,17 +30,16 @@ for name in filenames: geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) damask.util.croak(geom) - coord0 = damask.grid_filters.cell_coord0(geom.grid,geom.size,geom.origin).reshape((-1,3)) + coord0 = damask.grid_filters.cell_coord0(geom.grid,geom.size,geom.origin).reshape(-1,3) 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\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(coord0,{'pos':(3,)},comments) table.add('microstructure',geom.microstructure.reshape((-1,1),order='F')) - table.to_ASCII(sys.stdout if name is None else \ - os.path.splitext(name)[0]+'.txt') + 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 78c70d89c..6f5827f8b 100755 --- a/processing/pre/hybridIA_linODFsampling.py +++ b/processing/pre/hybridIA_linODFsampling.py @@ -1,11 +1,17 @@ #!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- +import os +import sys +import math +import random +from io import StringIO from optparse import OptionParser -import damask -import os,sys,math,random + import numpy as np +import damask + + scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) @@ -223,54 +229,29 @@ parser.set_defaults(randomSeed = None, ) (options,filenames) = parser.parse_args() - -nSamples = options.number -methods = [options.algorithm] - - -# --- loop over input files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] for name in filenames: - try: - table = damask.ASCIItable(name = name, readonly=True) - except IOError: - continue damask.util.report(scriptName,name) + + table = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) - randomSeed = int(os.urandom(4).hex(), 16) if options.randomSeed is None else options.randomSeed # random seed per file for second phase + randomSeed = int(os.urandom(4).hex(),16) if options.randomSeed is None else options.randomSeed # random seed per file random.seed(randomSeed) -# ------------------------------------------ read header and data --------------------------------- - table.head_read() - - errors = [] - labels = ['1_euler','2_euler','3_euler','intensity'] - for i,index in enumerate(table.label_index(labels)): - if index < 0: errors.append('label {} not present.'.format(labels[i])) - - if errors != []: - damask.util.croak(errors) - table.close(dismiss = True) - continue - - table.data_readArray(labels) - # --------------- figure out limits (left/right), delta, and interval ----------------------------- - ODF = {} - limits = np.array([np.min(table.data[:,0:3],axis=0), - np.max(table.data[:,0:3],axis=0)]) # min/max euler angles in degrees + eulers = table.get('euler') + limits = np.array([np.min(eulers,axis=0),np.max(eulers,axis=0)]) # min/max euler angles in degrees ODF['limit'] = np.radians(limits[1,:]) # right hand limits in radians ODF['center'] = 0.0 if all(limits[0,:]<1e-8) else 0.5 # vertex or cell centered - ODF['interval'] = np.array(list(map(len,[np.unique(table.data[:,i]) for i in range(3)])),'i') # steps are number of distict values + ODF['interval'] = np.array(list(map(len,[np.unique(eulers[:,i]) for i in range(3)])),'i') # steps are number of distict values ODF['nBins'] = ODF['interval'].prod() ODF['delta'] = np.radians(np.array(limits[1,0:3]-limits[0,0:3])/(ODF['interval']-1)) # step size - if table.data.shape[0] != ODF['nBins']: - damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],table.data.shape[0])) + if eulers.shape[0] != ODF['nBins']: + damask.util.croak('expecting %i values but got %i'%(ODF['nBins'],eulers.shape[0])) continue # ----- build binnedODF array and normalize ------------------------------------------------------ @@ -278,9 +259,10 @@ for name in filenames: ODF['dV_V'] = [None]*ODF['nBins'] ODF['nNonZero'] = 0 dg = ODF['delta'][0]*2.0*math.sin(ODF['delta'][1]/2.0)*ODF['delta'][2] + intensity = table.get('intensity') for b in range(ODF['nBins']): ODF['dV_V'][b] = \ - max(0.0,table.data[b,table.label_index('intensity')]) * dg * \ + max(0.0,intensity[b,0]) * dg * \ math.sin(((b//ODF['interval'][2])%ODF['interval'][1]+ODF['center'])*ODF['delta'][1]) if ODF['dV_V'][b] > 0.0: sumdV_V += ODF['dV_V'][b] @@ -296,11 +278,10 @@ for name in filenames: 'Reference Integral: %12.11f\n'%(ODF['limit'][0]*ODF['limit'][2]*(1-math.cos(ODF['limit'][1]))), ]) -# call methods Functions = {'IA': 'directInversion', 'STAT': 'TothVanHoutteSTAT', 'MC': 'MonteCarloBins'} method = Functions[options.algorithm] - Orientations, ReconstructedODF = (globals()[method])(ODF,nSamples) + Orientations, ReconstructedODF = (globals()[method])(ODF,options.number) # calculate accuracy of sample squaredDiff = {'orig':0.0,method:0.0} @@ -319,7 +300,7 @@ for name in filenames: indivSum['orig'] += ODF['dV_V'][bin] indivSquaredSum['orig'] += ODF['dV_V'][bin]**2 - damask.util.croak(['sqrt(N*)RMSD of ODFs:\t %12.11f'% math.sqrt(nSamples*squaredDiff[method]), + damask.util.croak(['sqrt(N*)RMSD of ODFs:\t %12.11f'% math.sqrt(options.number*squaredDiff[method]), 'RMSrD of ODFs:\t %12.11f'%math.sqrt(squaredRelDiff[method]), 'rMSD of ODFs:\t %12.11f'%(squaredDiff[method]/indivSquaredSum['orig']), 'nNonZero correlation slope:\t %12.11f'\ @@ -331,10 +312,10 @@ for name in filenames: (indivSquaredSum[method]/ODF['nNonZero']-(indivSum[method]/ODF['nNonZero'])**2)))), ]) - if method == 'IA' and nSamples < ODF['nNonZero']: + if method == 'IA' and options.number < ODF['nNonZero']: strOpt = '(%i)'%ODF['nNonZero'] - formatwidth = 1+int(math.log10(nSamples)) + formatwidth = 1+int(math.log10(options.number)) materialConfig = [ '#' + scriptID + ' ' + ' '.join(sys.argv[1:]), @@ -344,7 +325,7 @@ for name in filenames: '#-------------------#', ] - for i,ID in enumerate(range(nSamples)): + for i,ID in enumerate(range(options.number)): materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)), '(constituent) phase %i texture %s fraction 1.0'%(options.phase,str(ID+1).rjust(formatwidth)), ] @@ -355,7 +336,7 @@ for name in filenames: '#-------------------#', ] - for ID in range(nSamples): + for ID in range(options.number): eulers = Orientations[ID] materialConfig += ['[Grain%s]'%(str(ID+1).zfill(formatwidth)), @@ -364,7 +345,5 @@ for name in filenames: #--- output finalization -------------------------------------------------------------------------- - with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(nSamples)+'_material.config','w')) as outfile: + with (open(os.path.splitext(name)[0]+'_'+method+'_'+str(options.number)+'_material.config','w')) as outfile: outfile.write('\n'.join(materialConfig)+'\n') - - table.close() diff --git a/processing/pre/patchFromReconstructedBoundaries.py b/processing/pre/patchFromReconstructedBoundaries.py deleted file mode 100755 index 5f25c3b0d..000000000 --- a/processing/pre/patchFromReconstructedBoundaries.py +++ /dev/null @@ -1,1028 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: UTF-8 no BOM -*- - -import sys,os,math,re -import numpy as np -from optparse import OptionParser -import damask - -scriptName = os.path.splitext(os.path.basename(__file__))[0] -scriptID = ' '.join([scriptName,damask.version]) - - -try: # check for Python Image Lib - from PIL import Image,ImageDraw - ImageCapability = True -except ImportError: - ImageCapability = False - -sys.path.append(damask.solver.Marc().libraryPath()) - -try: # check for MSC.Mentat Python interface - import py_mentat - MentatCapability = True -except ImportError: - MentatCapability = False - - -def outMentat(cmd,locals): - if cmd[0:3] == '(!)': - exec(cmd[3:]) - elif cmd[0:3] == '(?)': - cmd = eval(cmd[3:]) - py_mentat.py_send(cmd) - if 'log' in locals: locals['log'].append(cmd) - else: - py_mentat.py_send(cmd) - if 'log' in locals: locals['log'].append(cmd) - return - -def outStdout(cmd,locals): - if cmd[0:3] == '(!)': - exec(cmd[3:]) - elif cmd[0:3] == '(?)': - cmd = eval(cmd[3:]) - print(cmd) - else: - print(cmd) - return - - -def output(cmds,locals,dest): - for cmd in cmds: - if isinstance(cmd,list): - output(cmd,locals,dest) - else: - {\ - 'Mentat': outMentat,\ - 'Stdout': outStdout,\ - }[dest](cmd,locals) - return - - -def rcbOrientationParser(content,idcolumn): - - grains = [] - myOrientation = [0.0,0.0,0.0] - for j,line in enumerate(content): - if re.match(r'^\s*(#|$)',line): continue # skip comments and blank lines - for grain in range(2): - myID = int(line.split()[idcolumn+grain]) # get grain id - myOrientation = map(float,line.split())[3*grain:3+3*grain] # get orientation - if len(grains) < myID: - for i in range(myID-len(grains)): # extend list to necessary length - grains.append([0.0,0.0,0.0]) - try: - grains[myID-1] = myOrientation # store Euler angles - except IndexError: - damask.util.croak('You might not have chosen the correct column for the grain IDs! '+ - 'Please check the "--id" option.') - raise - - return grains - -def rcbParser(content,M,size,tolerance,idcolumn,segmentcolumn): - """Parser for TSL-OIM reconstructed boundary files.""" -# find bounding box - boxX = [1.*sys.maxint,-1.*sys.maxint] - boxY = [1.*sys.maxint,-1.*sys.maxint] - x = [0.,0.] - y = [0.,0.] - for line in content: - m = re.match(r'^\s*(#|$)',line) - if m: continue # skip comments and blank lines - try: - (x[0],y[0],x[1],y[1]) = map(float,line.split())[segmentcolumn:segmentcolumn+4] # get start and end coordinates of each segment. - except IndexError: - damask.util.croak('You might not have chosen the correct column for the segment end points! '+ - 'Please check the "--segment" option.') - 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]) - boxX[1] = max(boxX[1],x[0],x[1]) - boxY[0] = min(boxY[0],y[0],y[1]) - boxY[1] = max(boxY[1],y[0],y[1]) - dX = boxX[1]-boxX[0] - dY = boxY[1]-boxY[0] - - damask.util.croak(' bounding box {},{} -- {},{}'.format(boxX[0],boxY[0],boxX[1],boxY[1])) - damask.util.croak(' dimension {} x {}'.format(dX,dY)) - - if size > 0.0: scalePatch = size/dX - else: scalePatch = 1.0 - -# read segments - segment = 0 - connectivityXY = {"0": {"0":[],"%g"%dY:[],},\ - "%g"%dX: {"0":[],"%g"%dY:[],},} - connectivityYX = {"0": {"0":[],"%g"%dX:[],},\ - "%g"%dY: {"0":[],"%g"%dX:[],},} - grainNeighbors = [] - - for line in content: - if re.match(r'^\s*(#|$)',line): continue # skip comments and blank lines - (x[0],y[0],x[1],y[1]) = map(float,line.split())[segmentcolumn:segmentcolumn+4] # get start and end coordinates of each segment. - (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 - - x[0] -= boxX[0] # make relative to origin of bounding box - x[1] -= boxX[0] - y[0] -= boxY[0] - y[1] -= boxY[0] - grainNeighbors.append(map(int,line.split()[idcolumn:idcolumn+2])) # remember right and left grain per segment - for i in range(2): # store segment to both points - match = False # check whether point is already known (within a small range) - for posX in connectivityXY.keys(): - if (abs(float(posX)-x[i]) 0: - damask.util.croak(' culling {} duplicate segments...'.format(len(dupSegments))) - for rm in dupSegments: - segments[rm] = None - - crappyData = False - for pointId,point in enumerate(points): - if len(point['segments']) < 2: # point marks a dead end! - damask.util.croak('dead end at segment {} for point {} ({},{}).' - .format(point['segments'][0], - pointId, - boxX[0]+point['coords'][0]/scalePatch,boxY[0]+point['coords'][1]/scalePatch,)) - crappyData = True - - grains = {'draw': [], 'legs': []} - - if not crappyData: - - for pointId,point in enumerate(points): - while point['segments']: - myStart = pointId - grainDraw = [points[myStart]['coords']] - innerAngleSum = 0.0 - myWalk = point['segments'].pop() - grainLegs = [myWalk] - myEnd = segments[myWalk][1 if segments[myWalk][0] == myStart else 0] - while (myEnd != pointId): - myV = [points[myEnd]['coords'][0]-points[myStart]['coords'][0], - points[myEnd]['coords'][1]-points[myStart]['coords'][1]] - myLen = math.sqrt(myV[0]**2+myV[1]**2) - if myLen == 0.0: damask.util.croak('mylen is zero: point {} --> {}'.format(myStart,myEnd)) - best = {'product': -2.0, 'peek': -1, 'len': -1, 'point': -1} - for peek in points[myEnd]['segments']: # trying in turn all segments emanating from current end - if peek == myWalk: - continue # do not go back same path - peekEnd = segments[peek][1 if segments[peek][0] == myEnd else 0] - peekV = [points[peekEnd]['coords'][0]-points[myEnd]['coords'][0], - points[peekEnd]['coords'][1]-points[myEnd]['coords'][1]] - peekLen = math.sqrt(peekV[0]**2+peekV[1]**2) - if peekLen == 0.0: damask.util.croak('peeklen is zero: peek point {}'.format(peek)) - crossproduct = (myV[0]*peekV[1] - myV[1]*peekV[0])/myLen/peekLen - dotproduct = (myV[0]*peekV[0] + myV[1]*peekV[1])/myLen/peekLen - innerAngle = math.copysign(1.0,crossproduct)*(dotproduct-1.0) - if innerAngle >= best['product']: # takes sharpest left turn - best['product'] = innerAngle - best['peek'] = peek - best['point'] = peekEnd - - innerAngleSum += best['product'] - myWalk = best['peek'] - myStart = myEnd - myEnd = best['point'] - - if myWalk in points[myStart]['segments']: - points[myStart]['segments'].remove(myWalk) - else: - damask.util.croak('{} not in segments of point {}'.format(myWalk,myStart)) - grainDraw.append(points[myStart]['coords']) - grainLegs.append(myWalk) - - if innerAngleSum > 0.0: - grains['draw'].append(grainDraw) - grains['legs'].append(grainLegs) - else: - grains['box'] = grainLegs - -# build overall data structure - - rcData = {'dimension':[dX,dY], - 'bounds': [[boxX[0],boxY[0]],[boxX[1],boxY[1]]], - 'scale': scalePatch, - 'point': [], - 'segment': [], - 'neighbors': [], - 'grain': [], - 'grainMapping': [], - } - - for point in points: - rcData['point'].append(point['coords']) - damask.util.croak(' found {} points'.format(len(rcData['point']))) - - for segment in segments: - rcData['segment'].append(segment) - damask.util.croak(' built {} segments'.format(len(rcData['segment']))) - - for neighbors in grainNeighbors: - rcData['neighbors'].append(neighbors) - - for legs in grains['legs']: # loop over grains - rcData['grain'].append(legs) # store list of boundary segments - myNeighbors = {} - for leg in legs: # test each boundary segment - if leg < len(grainNeighbors): # a valid segment index? - for side in range(2): # look at both sides of the segment - if grainNeighbors[leg][side] in myNeighbors: # count occurrence of grain IDs - myNeighbors[grainNeighbors[leg][side]] += 1 - else: - myNeighbors[grainNeighbors[leg][side]] = 1 - if myNeighbors: # do I have any neighbors (i.e., non-bounding box segment) - candidateGrains = sorted(myNeighbors.items(), key=lambda p: (p[1],p[0]), reverse=True) # sort grain counting - # most frequent one not yet seen? - rcData['grainMapping'].append(candidateGrains[0 if candidateGrains[0][0] not in rcData['grainMapping'] else 1][0]) # must be me then - # special case of bi-crystal situation... - - damask.util.croak(' found {} grains'.format(len(rcData['grain']))) - - rcData['box'] = grains['box'] if 'box' in grains else [] - - return rcData - - -def init(): - return ["*new_model yes", - "*select_clear", - "*reset", - "*set_nodes off", - "*elements_solid", - "*show_view 4", - "*reset_view", - "*view_perspective", - "*redraw", - ] - - -def sample(size,aspect,n,xmargin,ymargin): - - cmds = [\ -# gauge - "*add_points %f %f %f"%(-size*(0.5+xmargin), size*(0.5*aspect+ymargin),0), - "*add_points %f %f %f"%( size*(0.5+xmargin), size*(0.5*aspect+ymargin),0), - "*add_points %f %f %f"%( size*(0.5+xmargin),-size*(0.5*aspect+ymargin),0), - "*add_points %f %f %f"%(-size*(0.5+xmargin),-size*(0.5*aspect+ymargin),0), - "*set_curve_type line", - "*add_curves %i %i"%(1,2), - "*add_curves %i %i"%(3,4), - "*set_curve_div_type_fix_ndiv", - "*set_curve_div_num %i"%n, - "*apply_curve_divisions", - "1 2 #", - "*add_curves %i %i"%(2,3), # right side - "*add_curves %i %i"%(4,1), # left side - "*set_curve_div_type_fix_ndiv", - "*set_curve_div_num %i"%n, - "*apply_curve_divisions", - "3 4 #", - ] - - return cmds - - -def patch(a,n,mesh,rcData): - cmds = [] - for l in range(len(rcData['point'])): # generate all points - cmds.append("*add_points %f %f %f"\ - %(rcData['point'][l][0]-a/2.0,rcData['point'][l][1]-a/rcData['dimension'][0]*rcData['dimension'][1]/2.0,0)) - - cmds.append(["*set_curve_type line", - "*set_curve_div_type_fix_ndiv", - ]) - for m in range(len(rcData['segment'])): # generate all curves and subdivide them for overall balanced piece length - start = rcData['segment'][m][0] - end = rcData['segment'][m][1] - cmds.append([\ - "*add_curves %i %i" %(start+rcData['offsetPoints'], - end +rcData['offsetPoints']), - "*set_curve_div_num %i"%(max(1,round(math.sqrt((rcData['point'][start][0]-rcData['point'][end][0])**2+\ - (rcData['point'][start][1]-rcData['point'][end][1])**2)/a*n))), - "*apply_curve_divisions", - "%i #"%(m+rcData['offsetSegments']), - ]) - - grain = 0 - cmds.append('(!)locals["last"] = py_get_int("nelements()")') - for g in rcData['grain']: - cmds.append([\ - '(!)locals["first"] = locals["last"]+1', - "*%s "%mesh+" ".join([str(rcData['offsetSegments']+x) for x in g])+" #", - '(!)locals["last"] = py_get_int("nelements()")', - "*select_elements", - '(?)"%i to %i #"%(locals["first"],locals["last"])', - "*store_elements grain_%i"%rcData['grainMapping'][grain], - "all_selected", - "*select_clear", - ]) - grain += 1 - - return cmds - - -def gage(mesh,rcData): - - return([\ - "*%s "%mesh + - " ".join([str(x) for x in range(1,rcData['offsetSegments'])]) + - " " + - " ".join([str(rcData['offsetSegments']+x)for x in rcData['box']]) + - " #", - "*select_reset", - "*select_clear", - "*select_elements", - "all_existing", - "*select_mode_except", - ['grain_%i'%rcData['grainMapping'][i] for i in range(len(rcData['grain']))], - "#", - "*store_elements matrix", - "all_selected", - "*select_mode_invert", - "*select_elements", - "all_existing", - "*store_elements _grains", - "all_selected", - "*select_clear", - "*select_reset", - ]) - - -def expand3D(thickness,steps): - return([\ - "*set_expand_translation z %f"%(thickness/steps), - "*set_expand_repetitions %i"%steps, - "*expand_elements", - "all_existing", - ]) - - -def initial_conditions(grainNumber,grainMapping): - cmds = [\ - "*new_icond", - "*icond_name _temperature", - "*icond_type state_variable", - "*icond_param_value state_var_id 1", - "*icond_dof_value var 300", - "*add_icond_elements", - "all_existing", - "*new_icond", - "*icond_name _homogenization", - "*icond_type state_variable", - "*icond_param_value state_var_id 2", - "*icond_dof_value var 1", - "*add_icond_elements", - "all_existing", - ] - - for grain in range(grainNumber): - cmds.append([\ - "*new_icond", - "*icond_name grain_%i"%grainMapping[grain], - "*icond_type state_variable", - "*icond_param_value state_var_id 3", - "*icond_dof_value var %i"%(grain+1), - "*add_icond_elements", - "grain_%i"%grainMapping[grain], - "", - ]) - cmds.append([\ - "*new_icond", - "*icond_name rim", - "*icond_type state_variable", - "*icond_param_value state_var_id 3", - "*icond_dof_value var %i"%(grainNumber+1), - "*add_icond_elements", - "matrix", - ]) - return cmds - - -def boundary_conditions(rate,thickness, size,aspect,xmargin,ymargin): - - inner = (1 - 1.0e-4) * size*(0.5+xmargin) - outer = (1 + 1.0e-4) * size*(0.5+xmargin) - lower = (1 - 1.0e-4) * size*(0.5*aspect+ymargin) - upper = (1 + 1.0e-4) * size*(0.5*aspect+ymargin) - - return [\ - "*new_md_table 1 1", - "*table_name linear", - "*set_md_table_type 1 time", - "*table_add", - "0 0", - "1 1", - "*select_method_box", - "*new_apply", - "*apply_name pull_bottom", - "*apply_type fixed_displacement", - "*apply_dof y", - "*apply_dof_value y %f"%(-rate*(lower+upper)/2.0), - "*apply_dof_table y linear", - "*select_clear_nodes", - "*select_nodes", - "%f %f"%(-outer,outer), - "%f %f"%(-upper,-lower), - "%f %f"%(-.0001*thickness,1.0001*thickness), - "*add_apply_nodes", - "all_selected", - "*new_apply", - "*apply_name pull_top", - "*apply_type fixed_displacement", - "*apply_dof y", - "*apply_dof_value y %f"%(rate*(lower+upper)/2.0), - "*apply_dof_table y linear", - "*select_clear_nodes", - "*select_nodes", - "%f %f"%(-outer,outer), - "%f %f"%(lower,upper), - "%f %f"%(-.0001*thickness,1.0001*thickness), - "*add_apply_nodes", - "all_selected", - "*new_apply", - "*apply_name fix_x", - "*apply_type fixed_displacement", - "*apply_dof x", - "*apply_dof_value x 0", - "*select_clear_nodes", - "*select_nodes", - "%f %f"%(-outer,-inner), - "%f %f"%(lower,upper), - "%f %f"%(-.0001*thickness,.0001*thickness), - "%f %f"%(-outer,-inner), - "%f %f"%(lower,upper), - "%f %f"%(0.9999*thickness,1.0001*thickness), - "%f %f"%(-outer,-inner), - "%f %f"%(-upper,-lower), - "%f %f"%(-.0001*thickness,.0001*thickness), - "%f %f"%(-outer,-inner), - "%f %f"%(-upper,-lower), - "%f %f"%(0.9999*thickness,1.0001*thickness), - "*add_apply_nodes", - "all_selected", - "*new_apply", - "*apply_name fix_z", - "*apply_type fixed_displacement", - "*apply_dof z", - "*apply_dof_value z 0", - "*select_clear_nodes", - "*select_nodes", - "%f %f"%(-outer,-inner), - "%f %f"%(lower,upper), - "%f %f"%(-.0001*thickness,.0001*thickness), - "%f %f"%(-outer,-inner), - "%f %f"%(-upper,-lower), - "%f %f"%(-.0001*thickness,.0001*thickness), - "%f %f"%(inner,outer), - "%f %f"%(lower,upper), - "%f %f"%(-.0001*thickness,.0001*thickness), - "%f %f"%(inner,outer), - "%f %f"%(-upper,-lower), - "%f %f"%(-.0001*thickness,.0001*thickness), - "*add_apply_nodes", - "all_selected", - "*select_clear", - "*select_reset", - ] - -def materials(): - return [\ - "*new_material", - "*material_name patch", - "*material_type mechanical:hypoelastic", - "*material_option hypoelastic:method:hypela2", - "*material_option hypoelastic:pass:def_rot", - "*add_material_elements", - "all_existing", - ] - - -def loadcase(time,incs,Ftol): - return [\ - "*new_loadcase", - "*loadcase_name puller", - "*loadcase_type static", - "*loadcase_value time", - "%g"%time, - "*loadcase_value nsteps", - "%i"%incs, - "*loadcase_value maxrec", - "20", - "*loadcase_value ntime_cuts", - "30", - "*loadcase_value force", - "%g"%Ftol, - ] - - -def job(grainNumber,grainMapping,twoD): - return [\ - "*new_job", - "*job_name pull", - "*job_class mechanical", - "*add_job_loadcases puller", - "*add_job_iconds homogenization", - ["*add_job_iconds grain_%i"%i for i in grainMapping[:grainNumber]], - "*add_job_iconds rim", - "*job_option dimen:%s | analysis dimension"%('two ' if twoD else 'three'), - "*job_option strain:large | finite strains", - "*job_option large_strn_proc:upd_lagrange | updated Lagrange framework", - "*job_option plas_proc:multiplicative | multiplicative decomp of F", - "*job_option solver_nonsym:on | nonsymmetrical solution", - "*job_option solver:mfront_sparse | multi-frontal sparse", - "*job_param stef_boltz 5.670400e-8", - "*job_param univ_gas_const 8.314472", - "*job_param planck_radiation_2 1.4387752e-2", - "*job_param speed_light_vacuum 299792458", - "*job_option user_source:compile_save", - ] - -# "*job_option large:on | large displacement", -# "*job_option plasticity:l_strn_mn_add | large strain additive", -# "*job_option cdilatation:on | constant dilatation", -# "*job_option update:on | updated lagrange procedure", -# "*job_option finite:on | large strains", -# "*job_option restart_mode:write | enable restarting", - - -def postprocess(): - return [\ - "*add_post_tensor stress", - "*add_post_tensor strain", - "*add_post_var von_mises", - "", - ] - - - -def cleanUp(a): - return [\ - "*remove_curves", - "all_existing", - "*remove_points", - "all_existing", - "*set_sweep_tolerance %f"%(1e-5*a), - "*sweep_all", - "*renumber_all", - ] - - -# ------------------------- -def image(name,imgsize,marginX,marginY,rcData): - - dX = max([coords[0] for coords in rcData['point']]) - dY = max([coords[1] for coords in rcData['point']]) - offsetX = imgsize*marginX - offsetY = imgsize*marginY - sizeX = int(imgsize*(1 +2*marginX)) - sizeY = int(imgsize*(dY/dX+2*marginY)) - - scaleImg = imgsize/dX # rescale from max x coord - - img = Image.new("RGB",(sizeX,sizeY),(255,255,255)) - draw = ImageDraw.Draw(img) - - for id,point in enumerate(rcData['point']): - draw.text([offsetX+point[0]*scaleImg,sizeY-(offsetY+point[1]*scaleImg)],"%i"%id,fill=(0,0,0)) - - for id,vertex in enumerate(rcData['segment']): - if vertex: - start = rcData['point'][vertex[0]] - end = rcData['point'][vertex[1]] - draw.text([offsetX+(start[0]+end[0])/2.0*scaleImg,sizeY-(offsetY+(start[1]+end[1])/2.0*scaleImg)],"%i"%id,fill=(255,0,128)) - draw.line([offsetX+start[0]*scaleImg,sizeY-(offsetY+start[1]*scaleImg), - offsetX+ end[0]*scaleImg,sizeY-(offsetY+ end[1]*scaleImg)],width=1,fill=(128,128,128)) - - for id,segment in enumerate(rcData['box']): - start = rcData['point'][rcData['segment'][segment][0]] - end = rcData['point'][rcData['segment'][segment][1]] - draw.line([offsetX+start[0]*scaleImg,sizeY-(offsetY+start[1]*scaleImg), - offsetX+ end[0]*scaleImg,sizeY-(offsetY+ end[1]*scaleImg)],width=3,fill=(128,128*(id%2),0)) - - for grain,origGrain in enumerate(rcData['grainMapping']): - center = [0.0,0.0] - for segment in rcData['grain'][grain]: # loop thru segments around grain - for point in rcData['segment'][segment]: # take start and end points - center[0] += rcData['point'][point][0] # build vector sum - center[1] += rcData['point'][point][1] - - center[0] /= len(rcData['grain'][grain])*2 # normalize by two times segment count, i.e. point count - center[1] /= len(rcData['grain'][grain])*2 - - draw.text([offsetX+center[0]*scaleImg,sizeY-(offsetY+center[1]*scaleImg)],'%i -> %i'%(grain,origGrain),fill=(128,32,32)) - - img.save(name+'.png',"PNG") - -# ------------------------- -def inside(x,y,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 - startover = (y1 >= y) # am I above testpoint? - for i in range(npoints): # loop through all points - (x2,y2) = points[i] # next point - endover = (y2 >= y) # am I above testpoint? - if (startover != endover): # one above one below testpoint? - if((y2 - y)*(x2 - x1) <= (y2 - y1)*(x2 - x)): # check for intersection - if (endover): - inside = not inside # found intersection - else: - if (not endover): - inside = not inside # found intersection - startover = endover # make second point first point - (x1,y1) = (x2,y2) - - return inside - -# ------------------------- -def fftbuild(rcData,height,xframe,yframe,grid,extrusion): - """Build array of grain numbers.""" - maxX = -1.*sys.maxint - maxY = -1.*sys.maxint - for line in rcData['point']: # find data range - (x,y) = line - maxX = max(maxX, x) - maxY = max(maxY, y) - xsize = maxX+2*xframe # add framsize - ysize = maxY+2*yframe - xres = int(grid) - yres = int(xres/xsize*ysize) - zres = extrusion - zsize = extrusion*min([xsize/xres,ysize/yres]) - - fftdata = {'fftpoints':[], \ - 'grid':(xres,yres,zres), \ - 'size':(xsize,ysize,zsize)} - - frameindex=len(rcData['grain'])+1 # calculate frame index as largest grain index plus one - dx = xsize/(xres) # calculate step sizes - dy = ysize/(yres) - - grainpoints = [] - for segments in rcData['grain']: # get segments of each grain - points = {} - for i,segment in enumerate(segments[:-1]): # loop thru segments except last (s=[start,end]) - points[rcData['segment'][segment][0]] = i # assign segment index to start point - points[rcData['segment'][segment][1]] = i # assigne segment index to endpoint - for i in range(2): # check points of last segment - if points[rcData['segment'][segments[-1]][i]] != 0: # not on first segment - points[rcData['segment'][segments[-1]][i]] = len(segments)-1 # assign segment index to last point - - grainpoints.append([]) # start out blank for current grain - for p in sorted(points, key=points.get): # loop thru set of sorted points - grainpoints[-1].append([rcData['point'][p][0],rcData['point'][p][1]]) # append x,y of point - bestGuess = 0 # assume grain 0 as best guess - for i in range(int(xres*yres)): # walk through all points in xy plane - xtest = -xframe+((i%xres)+0.5)*dx # calculate coordinates - ytest = -yframe+((i//xres)+0.5)*dy - if(xtest < 0 or xtest > maxX): # check wether part of frame - if( ytest < 0 or ytest > maxY): # part of edges - fftdata['fftpoints'].append(frameindex+2) # append frameindex to result array - else: # part of xframe - fftdata['fftpoints'].append(frameindex) # append frameindex to result array - elif( ytest < 0 or ytest > maxY): # part of yframe - fftdata['fftpoints'].append(frameindex+1) # append frameindex to result array - else: - if inside(xtest,ytest,grainpoints[bestGuess]): # check best guess first - fftdata['fftpoints'].append(bestGuess+1) - else: # no success - for g in range(len(grainpoints)): # test all - if inside(xtest,ytest,grainpoints[g]): - fftdata['fftpoints'].append(g+1) - bestGuess = g - break - - return fftdata - - -# ----------------------- MAIN ------------------------------- -parser = OptionParser(option_class=damask.extendableOption, usage='%prog [options] datafile[s]', description = """ -Produce image, spectral geometry description, and (auto) Mentat procedure from TSL/OIM -reconstructed boundary file - -""", version = scriptID) - -meshes=['dt_planar_trimesh','af_planar_trimesh','af_planar_quadmesh'] -parser.add_option('-o', '--output', action='extend', dest='output', metavar = '', - help='types of output {rcb, image, mentat, procedure, spectral}') -parser.add_option('-p', '--port', type='int', metavar = 'int', - dest='port', help='Mentat connection port [%default]') -parser.add_option('-2', '--twodimensional', action='store_true', - dest='twoD',help='use 2D model') -parser.add_option('-s','--patchsize', type='float', metavar = 'float', - dest='size', help='height of patch [%default]') -parser.add_option('-e', '--strain', type='float', metavar = 'float', - dest='strain', help='final strain to reach in simulation [%default]') -parser.add_option('--rate', type='float', metavar = 'float', - dest='strainrate', help='engineering strain rate to simulate [%default]') -parser.add_option('-N', '--increments', type='int', metavar = 'int', - dest='increments', help='number of increments to take [%default]') -parser.add_option('-t', '--tolerance', type='float', metavar = 'float', - dest='tolerance', help='relative tolerance of pixel positions to be swept [%default]') -parser.add_option('-m', '--mesh', choices = meshes, - metavar = '', dest='mesh', - help='algorithm and element type for automeshing {%s} [dt_planar_trimesh]'%(', '.join(meshes))) -parser.add_option('-x', '--xmargin', type='float', metavar = 'float', - dest='xmargin',help='margin in x in units of patch size [%default]') -parser.add_option('-y', '--ymargin', type='float', metavar = 'float', - dest='ymargin', help='margin in y in units of patch size [%default]') -parser.add_option('-g', '--grid', type='int', metavar = 'int', - dest='grid',help='number of Fourier points/Finite Elements across patch size + x_margin [%default]') -parser.add_option('-z', '--extrusion', type='int', metavar = 'int', - dest='extrusion', help='number of repetitions in z-direction [%default]') -parser.add_option('-i', '--imagesize', type='int', metavar = 'int', - dest='imgsize', help='size of PNG image [%default]') -parser.add_option('-M', '--coordtransformation', type='float', nargs=4, metavar = ' '.join(['float']*4), - dest='M', help='2x2 transformation from rcb to Euler coords [%default]') -parser.add_option('--scatter', type='float', metavar = 'float', - dest='scatter',help='orientation scatter [%default]') -parser.add_option('--segment', type='int', metavar = 'int', dest='segmentcolumn', - help='column holding the first entry for the segment end points in the rcb file [%default]') -parser.add_option('--id', type='int', dest='idcolumn', metavar = 'int', - help='column holding the right hand grain ID in the rcb file [%default]') - -parser.set_defaults(output = [], - size = 1.0, - port = 40007, - xmargin = 0.0, - ymargin = 0.0, - grid = 64, - extrusion = 2, - imgsize = 512, - M = (0.0,1.0,1.0,0.0), # M_11, M_12, M_21, M_22. x,y in RCB is y,x of Eulers!! - tolerance = 1.0e-3, - scatter = 0.0, - strain = 0.2, - strainrate = 1.0e-3, - increments = 200, - mesh = 'dt_planar_trimesh', - twoD = False, - segmentcolumn = 9, - idcolumn = 13) - -(options, args) = parser.parse_args() - -if not len(args): - parser.error('no boundary file specified.') - -try: - boundaryFile = open(args[0]) - boundarySegments = boundaryFile.readlines() - boundaryFile.close() -except IOError: - damask.util.croak('unable to read boundary file "{}".'.format(args[0])) - raise - -options.output = [s.lower() for s in options.output] # lower case -options.idcolumn -= 1 # python indexing starts with 0 -options.segmentcolumn -= 1 # python indexing starts with 0 - -myName = os.path.splitext(args[0])[0] -damask.util.report(scriptName,myName) - -orientationData = rcbOrientationParser(boundarySegments,options.idcolumn) -rcData = rcbParser(boundarySegments,options.M,options.size,options.tolerance,options.idcolumn,options.segmentcolumn) - -# ----- write corrected RCB ----- - -Minv = np.linalg.inv(np.array(options.M).reshape(2,2)) - -if 'rcb' in options.output: - print('# Header:\n'+ - '# \n'+ - '# Column 1-3: right hand average orientation (phi1, PHI, phi2 in radians)\n'+ - '# Column 4-6: left hand average orientation (phi1, PHI, phi2 in radians)\n'+ - '# Column 7: length (in microns)\n'+ - '# Column 8: trace angle (in degrees)\n'+ - '# Column 9-12: x,y coordinates of endpoints (in microns)\n'+ - '# Column 13-14: IDs of right hand and left hand grains') - for i,(left,right) in enumerate(rcData['neighbors']): - if rcData['segment'][i]: - first = np.dot(Minv,np.array([rcData['bounds'][0][0]+rcData['point'][rcData['segment'][i][0]][0]/rcData['scale'], - rcData['bounds'][0][1]+rcData['point'][rcData['segment'][i][0]][1]/rcData['scale'], - ])) - second = np.dot(Minv,np.array([rcData['bounds'][0][0]+rcData['point'][rcData['segment'][i][1]][0]/rcData['scale'], - rcData['bounds'][0][1]+rcData['point'][rcData['segment'][i][1]][1]/rcData['scale'], - ])) - print(' '.join(map(str,orientationData[left-1]+orientationData[right-1]))+ - str(np.linalg.norm(first-second))+ - '0'+ - ' '.join(map(str,first))+ - ' '.join(map(str,second))+ - ' '.join(map(str,[left,right]))) - -# ----- write image ----- - -if 'image' in options.output and options.imgsize > 0: - if ImageCapability: - image(myName,options.imgsize,options.xmargin,options.ymargin,rcData) - else: - damask.util.croak('...no image drawing possible (PIL missing)...') - -# ----- generate material.config ----- - -if any(output in options.output for output in ['spectral','mentat']): - config = [] - config.append('') - - for i,grain in enumerate(rcData['grainMapping']): - config+=['[grain{}]'.format(grain), - '(constituent)\tphase 1\ttexture {}\tfraction 1.0'.format(i+1)] - if (options.xmargin > 0.0): - config+=['[x-margin]', - '(constituent)\tphase 2\ttexture {}\tfraction 1.0\n'.format(len(rcData['grainMapping'])+1)] - if (options.ymargin > 0.0): - config+=['[y-margin]', - '(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]', - '(constituent)\tphase 2\ttexture {}\tfraction 1.0\n'.format(len(rcData['grainMapping'])+1)] - - if (options.xmargin > 0.0 or options.ymargin > 0.0): - config.append('[margin]') - - config.append('') - for grain in rcData['grainMapping']: - config+=['[grain{}]'.format(grain), - '(gauss)\tphi1\t%f\tphi\t%f\tphi2\t%f\tscatter\t%f\tfraction\t1.0'\ - %(math.degrees(orientationData[grain-1][0]),math.degrees(orientationData[grain-1][1]),\ - math.degrees(orientationData[grain-1][2]),options.scatter)] - if (options.xmargin > 0.0 or options.ymargin > 0.0): - config+=['[margin]', - '(random)\t\tscatter\t0.0\tfraction\t1.0'] - -# ----- write spectral geom ----- - -if 'spectral' in options.output: - fftdata = fftbuild(rcData, options.size, options.xmargin, options.ymargin, options.grid, options.extrusion) - - table = damask.ASCIItable(outname = myName+'_'+str(int(fftdata['grid'][0]))+'.geom', labeled = False) - table.labels_clear() - table.info_clear() - table.info_append([ - scriptID + ' ' + ' '.join(sys.argv[1:]), - "grid\ta {grid[0]}\tb {grid[1]}\tc {grid[2]}".format(grid=fftdata['grid']), - "size\tx {size[0]}\ty {size[1]}\tz {size[2]}".format(size=fftdata['size']), - "homogenization\t1", - ]) - table.info_append(config) - table.head_write() - - table.data = np.array(fftdata['fftpoints']*options.extrusion).\ - reshape(fftdata['grid'][1]*fftdata['grid'][2],fftdata['grid'][0]) - formatwidth = 1+int(math.log10(np.max(table.data))) - table.data_writeArray('%%%ii'%(formatwidth),delimiter=' ') - table.close() - - -if 'mentat' in options.output: - if MentatCapability: - rcData['offsetPoints'] = 1+4 # gage definition generates 4 points - rcData['offsetSegments'] = 1+4 # gage definition generates 4 segments - - cmds = [\ - init(), - sample(options.size,rcData['dimension'][1]/rcData['size'][0],12,options.xmargin,options.ymargin), - patch(options.size,options.grid,options.mesh,rcData), - gage(options.mesh,rcData), - ] - - if not options.twoD: - cmds += [expand3D(options.size*(1.0+2.0*options.xmargin)/options.grid*options.extrusion,options.extrusion),] - - cmds += [\ - cleanUp(options.size), - materials(), - initial_conditions(len(rcData['grain']),rcData['grainMapping']), - boundary_conditions(options.strainrate,options.size*(1.0+2.0*options.xmargin)/options.grid*options.extrusion,\ - options.size,rcData['dimension'][1]/rcData['dimension'][0],options.xmargin,options.ymargin), - loadcase(options.strain/options.strainrate,options.increments,0.01), - job(len(rcData['grain']),rcData['grainMapping'],options.twoD), - postprocess(), - ["*identify_sets","*regen","*fill_view","*save_as_model %s yes"%(myName)], - ] - - outputLocals = {'log':[]} - if (options.port is not None): - py_mentat.py_connect('',options.port) - try: - output(cmds,outputLocals,'Mentat') - finally: - py_mentat.py_disconnect() - if 'procedure' in options.output: - output(outputLocals['log'],outputLocals,'Stdout') - else: - damask.util.croak('...no interaction with Mentat possible...') - - with open(myName+'.config','w') as configFile: - configFile.write('\n'.join(config)) diff --git a/processing/pre/seeds_check.py b/processing/pre/seeds_check.py new file mode 100755 index 000000000..6ef808a0a --- /dev/null +++ b/processing/pre/seeds_check.py @@ -0,0 +1,39 @@ +#!/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] +scriptID = ' '.join([scriptName,damask.version]) + + +#-------------------------------------------------------------------------------------------------- +# MAIN +#-------------------------------------------------------------------------------------------------- + +parser = OptionParser(option_class=damask.extendableOption, usage='%prog [seedfile(s)]', description = """ +Writes vtk file for visualization. + +""", version = scriptID) + +(options, filenames) = parser.parse_args() +if filenames == []: filenames = [None] + +for name in filenames: + damask.util.report(scriptName,name) + + seeds = damask.Table.from_ASCII(StringIO(''.join(sys.stdin.read())) if name is None else name) + v = damask.VTK.from_polyData(seeds.get('pos')) + for label in seeds.shapes.keys(): + if label == 'pos': pass + v.add(seeds.get(label),label) + + if name: + v.write(os.path.splitext(name)[0]) + else: + sys.stdout.write(v.__repr__()) diff --git a/processing/pre/seeds_check.sh b/processing/pre/seeds_check.sh deleted file mode 100755 index 502a19024..000000000 --- a/processing/pre/seeds_check.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -for seeds in "$@" -do - vtk_pointCloud $seeds - - vtk_addPointCloudData $seeds \ - --data microstructure,weight \ - --vtk ${seeds%.*}.vtp \ - -done diff --git a/processing/pre/seeds_fromDistribution.py b/processing/pre/seeds_fromDistribution.py index 318598ba0..d00016865 100755 --- a/processing/pre/seeds_fromDistribution.py +++ b/processing/pre/seeds_fromDistribution.py @@ -1,9 +1,15 @@ #!/usr/bin/env python3 -import threading,time,os,sys,random -import numpy as np +import threading +import time +import os +import sys +import random from optparse import OptionParser from io import StringIO + +import numpy as np + import damask scriptName = os.path.splitext(os.path.basename(__file__))[0] @@ -35,11 +41,11 @@ class myThread (threading.Thread): s.acquire() bestMatch = match s.release() - + random.seed(options.randomSeed+self.threadID) # initializes to given seeds knownSeedsUpdate = bestSeedsUpdate -1.0 # trigger update of local best seeds randReset = True # aquire new direction - + myBestSeedsVFile = StringIO() # store local copy of best seeds file perturbedSeedsVFile = StringIO() # perturbed best seeds file perturbedGeomVFile = StringIO() # tessellated geom file @@ -49,14 +55,13 @@ class myThread (threading.Thread): s.acquire() # ensure only one thread acces global data if bestSeedsUpdate > knownSeedsUpdate: # write best fit to virtual file knownSeedsUpdate = bestSeedsUpdate - bestSeedsVFile.reset() + bestSeedsVFile.seek(0) myBestSeedsVFile.close() myBestSeedsVFile = StringIO() i=0 - for line in bestSeedsVFile: - myBestSeedsVFile.write(line) + myBestSeedsVFile.writelines(bestSeedsVFile.readlines()) s.release() - + if randReset: # new direction because current one led to worse fit randReset = False @@ -67,46 +72,38 @@ class myThread (threading.Thread): for i in range(NmoveGrains): selectedMs.append(random.randrange(1,nMicrostructures)) - direction.append(np.array(((random.random()-0.5)*delta[0], - (random.random()-0.5)*delta[1], - (random.random()-0.5)*delta[2]))) - + direction.append((np.random.random()-0.5)*delta) + perturbedSeedsVFile.close() # reset virtual file perturbedSeedsVFile = StringIO() - myBestSeedsVFile.reset() + myBestSeedsVFile.seek(0) - perturbedSeedsTable = damask.ASCIItable(myBestSeedsVFile,perturbedSeedsVFile,labeled=True) # write best fit to perturbed seed file - perturbedSeedsTable.head_read() - perturbedSeedsTable.head_write() - outputAlive=True - ms = 1 + perturbedSeedsTable = damask.Table.from_ASCII(myBestSeedsVFile) + coords = perturbedSeedsTable.get('pos') i = 0 - while outputAlive and perturbedSeedsTable.data_read(): # perturbe selected microstructure + for ms,coord in enumerate(coords): if ms in selectedMs: - newCoords=np.array(tuple(map(float,perturbedSeedsTable.data[0:3]))+direction[i]) + newCoords=coord+direction[i] newCoords=np.where(newCoords>=1.0,newCoords-1.0,newCoords) # ensure that the seeds remain in the box newCoords=np.where(newCoords <0.0,newCoords+1.0,newCoords) - perturbedSeedsTable.data[0:3]=[format(f, '8.6f') for f in newCoords] + coords[i]=newCoords direction[i]*=2. i+= 1 - ms+=1 - perturbedSeedsTable.data_write() -#--- do tesselation with perturbed seed file ---------------------------------------------------------- + perturbedSeedsTable.set('pos',coords) + perturbedSeedsTable.to_ASCII(perturbedSeedsVFile) + +#--- do tesselation with perturbed seed file ------------------------------------------------------ perturbedGeomVFile.close() perturbedGeomVFile = StringIO() - perturbedSeedsVFile.reset() + perturbedSeedsVFile.seek(0) perturbedGeomVFile.write(damask.util.execute('geom_fromVoronoiTessellation '+ ' -g '+' '.join(list(map(str, options.grid))),streamIn=perturbedSeedsVFile)[0]) - perturbedGeomVFile.reset() + perturbedGeomVFile.seek(0) -#--- evaluate current seeds file ---------------------------------------------------------------------- - perturbedGeomTable = damask.ASCIItable(perturbedGeomVFile,None,labeled=False,readonly=True) - perturbedGeomTable.head_read() - for i in perturbedGeomTable.info: - if i.startswith('microstructures'): myNmicrostructures = int(i.split('\t')[1]) - perturbedGeomTable.data_readArray() - perturbedGeomTable.output_flush() - currentData=np.bincount(perturbedGeomTable.data.astype(int).ravel())[1:]/points +#--- evaluate current seeds file ------------------------------------------------------------------ + perturbedGeom = damask.Geom.from_file(perturbedGeomVFile) + myNmicrostructures = len(np.unique(perturbedGeom.microstructure)) + currentData=np.bincount(perturbedGeom.microstructure.ravel())[1:]/points currentError=[] currentHist=[] for i in range(nMicrostructures): # calculate the deviation in all bins per histogram @@ -114,8 +111,8 @@ class myThread (threading.Thread): currentError.append(np.sqrt(np.square(np.array(target[i]['histogram']-currentHist[i])).sum())) # as long as not all grains are within the range of the target, use the deviation to left and right as error - if currentError[0]>0.0: - currentError[0] *=((target[0]['bins'][0]-np.min(currentData))**2.0+ + if currentError[0]>0.0: + currentError[0] *=((target[0]['bins'][0]-np.min(currentData))**2.0+ (target[0]['bins'][1]-np.max(currentData))**2.0)**0.5 # norm of deviations by number of usual bin deviation s.acquire() # do the evaluation serially bestMatch = match @@ -137,7 +134,7 @@ class myThread (threading.Thread): damask.util.croak(' target: '+np.array_str(target[i]['histogram'])) damask.util.croak(' best: '+np.array_str(currentHist[i])) currentSeedsName = baseFile+'_'+str(bestSeedsUpdate).replace('.','-') # name of new seed file (use time as unique identifier) - perturbedSeedsVFile.reset() + perturbedSeedsVFile.seek(0) bestSeedsVFile.close() bestSeedsVFile = StringIO() sys.stdout.flush() @@ -154,11 +151,10 @@ class myThread (threading.Thread): break if i == min(nMicrostructures,myMatch+options.bins)-1: # same quality as before: take it to keep on moving bestSeedsUpdate = time.time() - perturbedSeedsVFile.reset() + perturbedSeedsVFile.seek(0) bestSeedsVFile.close() bestSeedsVFile = StringIO() - for line in perturbedSeedsVFile: - bestSeedsVFile.write(line) + bestSeedsVFile.writelines(perturbedSeedsVFile.readlines()) for j in range(nMicrostructures): target[j]['error'] = currentError[j] randReset = True @@ -167,7 +163,7 @@ class myThread (threading.Thread): .format(self.threadID,myNmicrostructures)) randReset = True - + s.release() @@ -192,7 +188,7 @@ parser.add_option('--target', dest='target', metavar='string', help='name of the geom file with target distribution [%default]') parser.add_option('--tolerance', dest='threshold', type='int', metavar='int', help='stopping criterion (bin number) [%default]') -parser.add_option('--scale', dest='scale',type='float', metavar='float', +parser.add_option('--scale', dest='scale',type='float', metavar='float', help='maximum moving distance of perturbed seed in pixel [%default]') parser.add_option('--bins', dest='bins', type='int', metavar='int', help='bins to sort beyond current best fit [%default]') @@ -216,7 +212,7 @@ damask.util.report(scriptName,options.seedFile) if options.randomSeed is None: options.randomSeed = int(os.urandom(4).hex(),16) damask.util.croak(options.randomSeed) -delta = (options.scale/options.grid[0],options.scale/options.grid[1],options.scale/options.grid[2]) +delta = options.scale/np.array(options.grid) baseFile=os.path.splitext(os.path.basename(options.seedFile))[0] points = np.array(options.grid).prod().astype('float') @@ -257,7 +253,7 @@ for i in range(nMicrostructures): initialHist = np.histogram(initialData,bins=target[i]['bins'])[0] target[i]['error']=np.sqrt(np.square(np.array(target[i]['histogram']-initialHist)).sum()) -# as long as not all grain sizes are within the range, the error is the deviation to left and right +# as long as not all grain sizes are within the range, the error is the deviation to left and right if target[0]['error'] > 0.0: target[0]['error'] *=((target[0]['bins'][0]-np.min(initialData))**2.0+ (target[0]['bins'][1]-np.max(initialData))**2.0)**0.5 @@ -267,7 +263,7 @@ for i in range(nMicrostructures): match = i+1 -if options.maxseeds < 1: +if options.maxseeds < 1: maxSeeds = len(np.unique(initialGeom.microstructure)) else: maxSeeds = options.maxseeds diff --git a/processing/pre/seeds_fromGeom.py b/processing/pre/seeds_fromGeom.py index 2118f049d..80dc0d6f5 100755 --- a/processing/pre/seeds_fromGeom.py +++ b/processing/pre/seeds_fromGeom.py @@ -54,17 +54,16 @@ for name in filenames: 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] + seeds = damask.grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3) 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\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 = damask.Table(seeds[mask],{'pos':(3,)},comments) + table.add('microstructure',microstructure[mask]) 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 1436841d0..49bbe3429 100755 --- a/processing/pre/seeds_fromPokes.py +++ b/processing/pre/seeds_fromPokes.py @@ -32,7 +32,7 @@ parser.add_option('-b', '--box', help = 'bounding box as fraction in x, y, and z directions') parser.add_option('-x', action = 'store_true', - dest = 'x', + dest = 'x', help = 'poke 45 deg along x') parser.add_option('-y', action = 'store_true', @@ -53,20 +53,20 @@ options.box = np.array(options.box).reshape(3,2) for name in filenames: damask.util.report(scriptName,name) geom = damask.Geom.from_file(StringIO(''.join(sys.stdin.read())) if name is None else name) - + 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') - + + seeds = np.zeros((Nx*Ny*Nz,4)) + g = np.zeros(3,dtype=np.int) + n = 0 for i in range(Nx): for j in range(Ny): @@ -80,16 +80,17 @@ for name in filenames: 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)] - + '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.set('microstructure',table.get('microstructure').astype(np.int)) table.to_ASCII(sys.stdout if name is None else \ os.path.splitext(name)[0]+'_poked_{}.seeds'.format(options.N)) diff --git a/processing/pre/seeds_fromRandom.py b/processing/pre/seeds_fromRandom.py index c64e6cc4f..2de513c2c 100755 --- a/processing/pre/seeds_fromRandom.py +++ b/processing/pre/seeds_fromRandom.py @@ -1,36 +1,25 @@ #!/usr/bin/env python3 -# -*- coding: UTF-8 no BOM -*- -import os,sys,math,random -import numpy as np -import damask +import os +import sys from optparse import OptionParser,OptionGroup + +import numpy as np from scipy import spatial +import damask + scriptName = os.path.splitext(os.path.basename(__file__))[0] scriptID = ' '.join([scriptName,damask.version]) -# ------------------------------------------ aux functions --------------------------------- - -def kdtree_search(cloud, queryPoints): - """Find distances to nearest neighbor among cloud (N,d) for each of the queryPoints (n,d).""" - n = queryPoints.shape[0] - distances = np.zeros(n,dtype=float) - tree = spatial.cKDTree(cloud) - - for i in range(n): - distances[i], index = tree.query(queryPoints[i]) - - return distances - # -------------------------------------------------------------------- # MAIN # -------------------------------------------------------------------- parser = OptionParser(option_class=damask.extendableOption, usage='%prog options', description = """ -Distribute given number of points randomly within (a fraction of) the three-dimensional cube [0.0,0.0,0.0]--[1.0,1.0,1.0]. +Distribute given number of points randomly within rectangular cuboid. Reports positions with random crystal orientations in seeds file format to STDOUT. """, version = scriptID) @@ -39,11 +28,11 @@ parser.add_option('-N', dest = 'N', type = 'int', metavar = 'int', help = 'number of seed points [%default]') -parser.add_option('-f', - '--fraction', - dest = 'fraction', +parser.add_option('-s', + '--size', + dest = 'size', type = 'float', nargs = 3, metavar = 'float float float', - help='fractions along x,y,z of unit cube to fill %default') + help='size x,y,z of unit cube to fill %default') parser.add_option('-g', '--grid', dest = 'grid', @@ -58,9 +47,6 @@ parser.add_option('-r', '--rnd', dest = 'randomSeed', type = 'int', metavar = 'int', help = 'seed of random number generator [%default]') -parser.add_option('--format', - dest = 'format', type = 'string', metavar = 'string', - help = 'output number format [auto]') group = OptionGroup(parser, "Laguerre Tessellation", "Parameters determining shape of weight distribution of seed points" @@ -87,8 +73,7 @@ parser.add_option_group(group) group = OptionGroup(parser, "Selective Seeding", "More uniform distribution of seed points using Mitchell's Best Candidate Algorithm" ) -group.add_option( '-s', - '--selective', +group.add_option( '--selective', action = 'store_true', dest = 'selective', help = 'selective picking of seed points from random seed points') @@ -99,12 +84,12 @@ group.add_option( '--distance', group.add_option( '--numCandidates', dest = 'numCandidates', type = 'int', metavar = 'int', - help = 'size of point group to select best distance from [%default]') + help = 'size of point group to select best distance from [%default]') parser.add_option_group(group) parser.set_defaults(randomSeed = None, grid = (16,16,16), - fraction = (1.0,1.0,1.0), + size = (1.0,1.0,1.0), N = 20, weights = False, max = 0.0, @@ -114,116 +99,67 @@ parser.set_defaults(randomSeed = None, selective = False, distance = 0.2, numCandidates = 10, - format = None, ) (options,filenames) = parser.parse_args() - -options.fraction = np.array(options.fraction) -options.grid = np.array(options.grid) -gridSize = options.grid.prod() - -if options.randomSeed is None: options.randomSeed = int(os.urandom(4).hex(), 16) -np.random.seed(options.randomSeed) # init random generators -random.seed(options.randomSeed) - - -# --- loop over output files ------------------------------------------------------------------------- - if filenames == []: filenames = [None] +size = np.array(options.size) +grid = np.array(options.grid) +np.random.seed(int(os.urandom(4).hex(),16) if options.randomSeed is None else options.randomSeed) + for name in filenames: - try: - table = damask.ASCIItable(outname = name) - except IOError: - continue - damask.util.report(scriptName,name) + damask.util.report(scriptName,name) -# --- sanity checks ------------------------------------------------------------------------- + if options.N > np.prod(grid): + damask.util.croak('More seeds than grid positions.') + sys.exit() + if options.selective and options.distance < min(size/grid): + damask.util.croak('Distance must be larger than grid spacing.') + sys.exit() + if options.selective and options.distance**3*options.N > 0.5*np.prod(size): + damask.util.croak('Number of seeds for given size and distance should be < {}.'\ + .format(int(0.5*np.prod(size)/options.distance**3))) - remarks = [] - errors = [] - if gridSize == 0: - errors.append('zero grid dimension for {}.'.format(', '.join([['a','b','c'][x] for x in np.where(options.grid == 0)[0]]))) - if options.N > gridSize/10.: - remarks.append('seed count exceeds 0.1 of grid points.') - if options.selective and 4./3.*math.pi*(options.distance/2.)**3*options.N > 0.5: - remarks.append('maximum recommended seed point count for given distance is {}.{}'. - format(int(3./8./math.pi/(options.distance/2.)**3))) + eulers = np.random.rand(options.N,3) # create random Euler triplets + eulers[:,0] *= 360.0 # phi_1 is uniformly distributed + eulers[:,1] = np.degrees(np.arccos(2*eulers[:,1]-1.0)) # cos(Phi) is uniformly distributed + eulers[:,2] *= 360.0 # phi_2 is uniformly distributed - if remarks != []: damask.util.croak(remarks) - if errors != []: - damask.util.croak(errors) - sys.exit() -# --- do work ------------------------------------------------------------------------------------ - - grainEuler = np.random.rand(3,options.N) # create random Euler triplets - grainEuler[0,:] *= 360.0 # phi_1 is uniformly distributed - grainEuler[1,:] = np.degrees(np.arccos(2*grainEuler[1,:]-1)) # cos(Phi) is uniformly distributed - grainEuler[2,:] *= 360.0 # phi_2 is uniformly distributed + if not options.selective: + coords = damask.grid_filters.cell_coord0(grid,size).reshape(-1,3) + seeds = coords[np.random.choice(np.prod(grid), options.N, replace=False)] \ + + np.broadcast_to(size/grid,(options.N,3))*(np.random.rand(options.N,3)*.5-.25) # wobble without leaving grid + else: + seeds = np.empty((options.N,3)) + seeds[0] = np.random.random(3) * size - if not options.selective: - n = np.maximum(np.ones(3),np.array(options.grid*options.fraction), - dtype=int,casting='unsafe') # find max grid indices within fraction - meshgrid = np.meshgrid(*map(np.arange,n),indexing='ij') # create a meshgrid within fraction - coords = np.vstack((meshgrid[0],meshgrid[1],meshgrid[2])).reshape(3,n.prod()).T # assemble list of 3D coordinates - seeds = ((random.sample(list(coords),options.N)+np.random.random(options.N*3).reshape(options.N,3))\ - / \ - (n/options.fraction)).T # pick options.N of those, rattle position, - # and rescale to fall within fraction - else: - seeds = np.zeros((options.N,3),dtype=float) # seed positions array - seeds[0] = np.random.random(3)*options.grid/max(options.grid) - i = 1 # start out with one given point - if i%(options.N/100.) < 1: damask.util.croak('.',False) + i = 1 + progress = damask.util._ProgressBar(options.N,'',50) + while i < options.N: + candidates = np.random.rand(options.numCandidates,3)*np.broadcast_to(size,(options.numCandidates,3)) + tree = spatial.cKDTree(seeds[:i]) + distances, dev_null = tree.query(candidates) + best = distances.argmax() + if distances[best] > options.distance: # require minimum separation + seeds[i] = candidates[best] # maximum separation to existing point cloud + i += 1 + progress.update(i) - while i < options.N: - candidates = np.random.random(options.numCandidates*3).reshape(options.numCandidates,3) - distances = kdtree_search(seeds[:i],candidates) - best = distances.argmax() - if distances[best] > options.distance: # require minimum separation - seeds[i] = candidates[best] # maximum separation to existing point cloud - i += 1 - if i%(options.N/100.) < 1: damask.util.croak('.',False) - damask.util.croak('') - seeds = seeds.T # prepare shape for stacking + comments = [scriptID + ' ' + ' '.join(sys.argv[1:]), + 'grid\ta {}\tb {}\tc {}'.format(*grid), + 'size\tx {}\ty {}\tz {}'.format(*size), + 'randomSeed\t{}'.format(options.randomSeed), + ] - if options.weights: - weights = [np.random.uniform(low = 0, high = options.max, size = options.N)] if options.max > 0.0 \ - else [np.random.normal(loc = options.mean, scale = options.sigma, size = options.N)] - else: - weights = [] - seeds = np.transpose(np.vstack(tuple([seeds, - grainEuler, - np.arange(options.microstructure, - options.microstructure + options.N), - ] + weights - ))) + table = damask.Table(np.hstack((seeds,eulers)),{'pos':(3,),'euler':(3,)},comments) + table.add('microstructure',np.arange(options.microstructure,options.microstructure + options.N,dtype=int)) -# ------------------------------------------ assemble header --------------------------------------- + if options.weights: + weights = np.random.uniform(low = 0, high = options.max, size = options.N) if options.max > 0.0 \ + else np.random.normal(loc = options.mean, scale = options.sigma, size = options.N) + table.add('weight',weights) - table.info_clear() - table.info_append([ - scriptID + ' ' + ' '.join(sys.argv[1:]), - "grid\ta {}\tb {}\tc {}".format(*options.grid), - "microstructures\t{}".format(options.N), - "randomSeed\t{}".format(options.randomSeed), - ]) - table.labels_clear() - table.labels_append( ['{dim}_{label}'.format(dim = 1+k,label = 'pos') for k in range(3)] + - ['{dim}_{label}'.format(dim = 1+k,label = 'euler') for k in range(3)] + - ['microstructure'] + - (['weight'] if options.weights else [])) - table.head_write() - table.output_flush() - -# --- write seeds information ------------------------------------------------------------ - - table.data = seeds - table.data_writeArray(fmt = options.format) - -# --- output finalization -------------------------------------------------------------------------- - - table.close() # close ASCII table + table.to_ASCII(sys.stdout if name is None else name) diff --git a/python/.gitignore b/python/.gitignore index bd729dc2c..1cb7eb8a5 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -1,2 +1,3 @@ +*.pyc dist damask.egg-info diff --git a/python/damask/Lambert.py b/python/damask/_Lambert.py similarity index 98% rename from python/damask/Lambert.py rename to python/damask/_Lambert.py index 0ff177f9b..b3f159ff6 100644 --- a/python/damask/Lambert.py +++ b/python/damask/_Lambert.py @@ -36,7 +36,7 @@ sc = np.pi**(1./6.)/6.**(1./6.) beta = np.pi**(5./6.)/6.**(1./6.)/2. R1 = (3.*np.pi/4.)**(1./3.) -def CubeToBall(cube): +def cube_to_ball(cube): """ Map a point in a uniform refinable cubical grid to a point on a uniform refinable grid on a ball. @@ -59,7 +59,7 @@ def CubeToBall(cube): ball = np.zeros(3) else: # get pyramide and scale by grid parameter ratio - p = get_order(cube) + p = _get_order(cube) XYZ = cube[p] * sc # intercept all the points along the z-axis @@ -87,7 +87,7 @@ def CubeToBall(cube): return ball -def BallToCube(ball): +def ball_to_cube(ball): """ Map a point on a uniform refinable grid on a ball to a point in a uniform refinable cubical grid. @@ -109,7 +109,7 @@ def BallToCube(ball): if np.allclose(ball,0.0,rtol=0.0,atol=1.0e-300): cube = np.zeros(3) else: - p = get_order(ball) + p = _get_order(ball) xyz3 = ball[p] # inverse M_3 @@ -137,7 +137,7 @@ def BallToCube(ball): return cube -def get_order(xyz): +def _get_order(xyz): """ Get order of the coordinates. diff --git a/python/damask/__init__.py b/python/damask/__init__.py index d0ebd45a7..87c557721 100644 --- a/python/damask/__init__.py +++ b/python/damask/__init__.py @@ -1,37 +1,25 @@ """Main aggregator.""" -import os -import re +import os as _os +import re as _re name = 'damask' -with open(os.path.join(os.path.dirname(__file__),'VERSION')) as f: - version = re.sub(r'^v','',f.readline().strip()) +with open(_os.path.join(_os.path.dirname(__file__),'VERSION')) as _f: + version = _re.sub(r'^v','',_f.readline().strip()) # classes -from .environment import Environment # noqa -from .table import Table # noqa -from .ktv import VTK # noqa -from .colormaps import Colormap, Color # noqa -from .rotation import Rotation # noqa -from .lattice import Symmetry, Lattice# noqa -from .orientation import Orientation # noqa -from .result import Result # noqa -from .geom import Geom # noqa -from .solver import Solver # noqa - -# compatibility hack -from .result import Result as DADF5 # noqa +from ._environment import Environment # noqa +from ._table import Table # noqa +from ._vtk import VTK # noqa +from ._colormaps import Colormap, Color # noqa +from ._rotation import Rotation # noqa +from ._lattice import Symmetry, Lattice# noqa +from ._orientation import Orientation # noqa +from ._result import Result # noqa +from ._geom import Geom # noqa +from . import solver # noqa # deprecated -from .asciitable import ASCIItable # noqa -from .util import extendableOption # noqa -from .config import Material # noqa -from .test import Test # noqa - -# functions in modules -from . import mechanics # noqa -from . import grid_filters # noqa - -# clean temporary variables -del os -del re -del f +from ._asciitable import ASCIItable # noqa +from ._test import Test # noqa +from .config import Material # noqa +from .util import extendableOption # noqa diff --git a/python/damask/asciitable.py b/python/damask/_asciitable.py similarity index 88% rename from python/damask/asciitable.py rename to python/damask/_asciitable.py index d81c22530..8410b23a1 100644 --- a/python/damask/asciitable.py +++ b/python/damask/_asciitable.py @@ -14,11 +14,9 @@ class ASCIItable(): # ------------------------------------------------------------------ def __init__(self, - name = None, - outname = None, - buffered = False, # is ignored, only exists for compatibility reasons - labeled = True, # assume table has labels - readonly = False, # no reading from file + name, + labeled = True, # assume table has labels + readonly = False, # no reading from file ): """Read and write to ASCII tables.""" self.__IO__ = {'output': [], @@ -27,8 +25,9 @@ class ASCIItable(): 'dataStart': 0, } - self.__IO__['inPlace'] = not outname and name and not readonly - if self.__IO__['inPlace']: outname = name + self.tmpext # transparently create tmp file + self.__IO__['inPlace'] = name and not readonly + outname = name + self.tmpext if self.__IO__['inPlace'] else None # transparently create tmp file + try: self.__IO__['in'] = (open( name,'r') if os.access( name, os.R_OK) else None) if name else sys.stdin except TypeError: @@ -166,42 +165,6 @@ class ASCIItable(): return self.output_write(head) -# ------------------------------------------------------------------ - def head_getGeom(self): - """Interpret geom header.""" - identifiers = { - 'grid': ['a','b','c'], - 'size': ['x','y','z'], - 'origin': ['x','y','z'], - } - mappings = { - 'grid': lambda x: int(x), - 'size': lambda x: float(x), - 'origin': lambda x: float(x), - } - info = { - 'grid': np.zeros(3,'i'), - 'size': np.zeros(3,'d'), - 'origin': np.zeros(3,'d'), - } - extra_header = [] - - for header in self.info: - headitems = list(map(str.lower,header.split())) - if len(headitems) == 0: continue # skip blank lines - if headitems[0] in list(mappings.keys()): - if headitems[0] in list(identifiers.keys()): - for i in range(len(identifiers[headitems[0]])): - info[headitems[0]][i] = \ - mappings[headitems[0]](headitems[headitems.index(identifiers[headitems[0]][i])+1]) - else: - info[headitems[0]] = mappings[headitems[0]](headitems[1]) - else: - extra_header.append(header) - - return info,extra_header - - # ------------------------------------------------------------------ def labels_append(self, what, @@ -424,29 +387,26 @@ class ASCIItable(): return labels_missing # ------------------------------------------------------------------ - def data_write(self, - delimiter = '\t'): + def data_write(self): """Write current data array and report alive output back.""" if len(self.data) == 0: return True if isinstance(self.data[0],list): - return self.output_write([delimiter.join(map(self._quote,items)) for items in self.data]) + return self.output_write(['\t'.join(map(self._quote,items)) for items in self.data]) else: - return self.output_write( delimiter.join(map(self._quote,self.data))) + return self.output_write( '\t'.join(map(self._quote,self.data))) # ------------------------------------------------------------------ - def data_writeArray(self, - fmt = None, - delimiter = '\t'): + def data_writeArray(self): """Write whole numpy array data.""" for row in self.data: try: - output = [fmt % value for value in row] if fmt else list(map(repr,row)) + output = list(map(repr,row)) except Exception: - output = [fmt % row] if fmt else [repr(row)] + output = [repr(row)] try: - self.__IO__['out'].write(delimiter.join(output) + '\n') + self.__IO__['out'].write('\t'.join(output) + '\n') except Exception: pass diff --git a/python/damask/_colormaps.py b/python/damask/_colormaps.py new file mode 100644 index 000000000..2117b0b57 --- /dev/null +++ b/python/damask/_colormaps.py @@ -0,0 +1,541 @@ +import numpy as np + +class Color: + """Color representation in and conversion between different color-spaces.""" + + __slots__ = [ + 'model', + 'color', + '__dict__', + ] + + + def __init__(self, + model = 'RGB', + color = np.zeros(3)): + """ + Create a Color object. + + Parameters + ---------- + model : string + color model + color : numpy.ndarray + vector representing the color according to the selected model + + """ + self.__transforms__ = \ + {'HSV': {'index': 0, 'next': self._HSV2HSL}, + 'HSL': {'index': 1, 'next': self._HSL2RGB, 'prev': self._HSL2HSV}, + 'RGB': {'index': 2, 'next': self._RGB2XYZ, 'prev': self._RGB2HSL}, + 'XYZ': {'index': 3, 'next': self._XYZ2CIELAB, 'prev': self._XYZ2RGB}, + 'CIELAB': {'index': 4, 'next': self._CIELAB2MSH, 'prev': self._CIELAB2XYZ}, + 'MSH': {'index': 5, 'prev': self._MSH2CIELAB}, + } + + model = model.upper() + if model not in list(self.__transforms__.keys()): model = 'RGB' + if model == 'RGB' and max(color) > 1.0: # are we RGB255 ? + for i in range(3): + color[i] /= 255.0 # rescale to RGB + + if model == 'HSL': # are we HSL ? + if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue? + while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range + while color[0] < 0.0: color[0] += 1.0 # rewind to proper range + + self.model = model + self.color = np.array(color,'d') + + + def __repr__(self): + """Color model and values.""" + return 'Model: %s Color: %s'%(self.model,str(self.color)) + + + def __str__(self): + """Color model and values.""" + return self.__repr__() + + + def convert_to(self,toModel = 'RGB'): + """ + Change the color model permanently. + + Parameters + ---------- + toModel : string + color model + + """ + toModel = toModel.upper() + if toModel not in list(self.__transforms__.keys()): return + + sourcePos = self.__transforms__[self.model]['index'] + targetPos = self.__transforms__[toModel]['index'] + + while sourcePos < targetPos: + self.__transforms__[self.model]['next']() + sourcePos += 1 + + while sourcePos > targetPos: + self.__transforms__[self.model]['prev']() + sourcePos -= 1 + return self + + + def express_as(self,asModel = 'RGB'): + """ + Return the color in a different model. + + Parameters + ---------- + asModel : string + color model + + """ + return self.__class__(self.model,self.color).convert_to(asModel) + + + def _HSV2HSL(self): + """ + Convert H(ue) S(aturation) V(alue or brightness) to H(ue) S(aturation) L(uminance). + + All values are in the range [0,1] + http://codeitdown.com/hsl-hsb-hsv-color + """ + if self.model != 'HSV': return + + converted = Color('HSL',np.array([ + self.color[0], + 1. if self.color[2] == 0.0 or (self.color[1] == 0.0 and self.color[2] == 1.0) \ + else self.color[1]*self.color[2]/(1.-abs(self.color[2]*(2.-self.color[1])-1.)), + 0.5*self.color[2]*(2.-self.color[1]), + ])) + + self.model = converted.model + self.color = converted.color + + + def _HSL2HSV(self): + """ + Convert H(ue) S(aturation) L(uminance) to H(ue) S(aturation) V(alue or brightness). + + All values are in the range [0,1] + http://codeitdown.com/hsl-hsb-hsv-color + """ + if self.model != 'HSL': return + + h = self.color[0] + b = self.color[2]+0.5*(self.color[1]*(1.-abs(2*self.color[2]-1))) + s = 1.0 if b == 0.0 else 2.*(b-self.color[2])/b + + converted = Color('HSV',np.array([h,s,b])) + + self.model = converted.model + self.color = converted.color + + + def _HSL2RGB(self): + """ + Convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue). + + All values are in the range [0,1] + from http://en.wikipedia.org/wiki/HSL_and_HSV + """ + if self.model != 'HSL': return + + sextant = self.color[0]*6.0 + c = (1.0 - abs(2.0 * self.color[2] - 1.0))*self.color[1] + x = c*(1.0 - abs(sextant%2 - 1.0)) + m = self.color[2] - 0.5*c + + converted = Color('RGB',np.array([ + [c+m, x+m, m], + [x+m, c+m, m], + [m, c+m, x+m], + [m, x+m, c+m], + [x+m, m, c+m], + [c+m, m, x+m], + ][int(sextant)])) + self.model = converted.model + self.color = converted.color + + + def _RGB2HSL(self): + """ + Convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance). + + All values are in the range [0,1] + from http://130.113.54.154/~monger/hsl-rgb.html + """ + if self.model != 'RGB': return + + HSL = np.zeros(3) + maxcolor = self.color.max() + mincolor = self.color.min() + HSL[2] = (maxcolor + mincolor)/2.0 + if(mincolor == maxcolor): + HSL[0] = 0.0 + HSL[1] = 0.0 + else: + if (HSL[2]<0.5): + HSL[1] = (maxcolor - mincolor)/(maxcolor + mincolor) + else: + HSL[1] = (maxcolor - mincolor)/(2.0 - maxcolor - mincolor) + if (maxcolor == self.color[0]): + HSL[0] = 0.0 + (self.color[1] - self.color[2])/(maxcolor - mincolor) + elif (maxcolor == self.color[1]): + HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor) + elif (maxcolor == self.color[2]): + HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor) + HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values + if (HSL[0] < 0.0): + HSL[0] = HSL[0] + 360.0 + HSL[1:] = np.clip(HSL[1:],0.0,1.0) + + converted = Color('HSL', HSL) + self.model = converted.model + self.color = converted.color + + + def _RGB2XYZ(self): + """ + Convert R(ed) G(reen) B(lue) to CIE XYZ. + + All values are in the range [0,1] + from http://www.cs.rit.edu/~ncs/color/t_convert.html + """ + if self.model != 'RGB': return + + XYZ = np.zeros(3) + RGB_lin = np.zeros(3) + convert = np.array([[0.412453,0.357580,0.180423], + [0.212671,0.715160,0.072169], + [0.019334,0.119193,0.950227]]) + + for i in range(3): + if (self.color[i] > 0.04045): RGB_lin[i] = ((self.color[i]+0.0555)/1.0555)**2.4 + else: RGB_lin[i] = self.color[i] /12.92 + XYZ = np.dot(convert,RGB_lin) + XYZ = np.clip(XYZ,0.0,None) + + converted = Color('XYZ', XYZ) + self.model = converted.model + self.color = converted.color + + + def _XYZ2RGB(self): + """ + Convert CIE XYZ to R(ed) G(reen) B(lue). + + All values are in the range [0,1] + from http://www.cs.rit.edu/~ncs/color/t_convert.html + """ + if self.model != 'XYZ': return + + convert = np.array([[ 3.240479,-1.537150,-0.498535], + [-0.969256, 1.875992, 0.041556], + [ 0.055648,-0.204043, 1.057311]]) + RGB_lin = np.dot(convert,self.color) + RGB = np.zeros(3) + + for i in range(3): + if (RGB_lin[i] > 0.0031308): RGB[i] = ((RGB_lin[i])**(1.0/2.4))*1.0555-0.0555 + else: RGB[i] = RGB_lin[i] *12.92 + + RGB = np.clip(RGB,0.0,1.0) + + maxVal = max(RGB) # clipping colors according to the display gamut + if (maxVal > 1.0): RGB /= maxVal + + converted = Color('RGB', RGB) + self.model = converted.model + self.color = converted.color + + + def _CIELAB2XYZ(self): + """ + Convert CIE Lab to CIE XYZ. + + All values are in the range [0,1] + from http://www.easyrgb.com/index.php?X=MATH&H=07#text7 + """ + if self.model != 'CIELAB': return + + ref_white = np.array([.95047, 1.00000, 1.08883]) # Observer = 2, Illuminant = D65 + XYZ = np.zeros(3) + + XYZ[1] = (self.color[0] + 16.0 ) / 116.0 + XYZ[0] = XYZ[1] + self.color[1]/ 500.0 + XYZ[2] = XYZ[1] - self.color[2]/ 200.0 + + for i in range(len(XYZ)): + if (XYZ[i] > 6./29. ): XYZ[i] = XYZ[i]**3. + else: XYZ[i] = 108./841. * (XYZ[i] - 4./29.) + + converted = Color('XYZ', XYZ*ref_white) + self.model = converted.model + self.color = converted.color + + + def _XYZ2CIELAB(self): + """ + Convert CIE XYZ to CIE Lab. + + All values are in the range [0,1] + from http://en.wikipedia.org/wiki/Lab_color_space, + http://www.cs.rit.edu/~ncs/color/t_convert.html + """ + if self.model != 'XYZ': return + + ref_white = np.array([.95047, 1.00000, 1.08883]) # Observer = 2, Illuminant = D65 + XYZ = self.color/ref_white + + for i in range(len(XYZ)): + if (XYZ[i] > 216./24389 ): XYZ[i] = XYZ[i]**(1.0/3.0) + else: XYZ[i] = (841./108. * XYZ[i]) + 16.0/116.0 + + converted = Color('CIELAB', np.array([ 116.0 * XYZ[1] - 16.0, + 500.0 * (XYZ[0] - XYZ[1]), + 200.0 * (XYZ[1] - XYZ[2]) ])) + self.model = converted.model + self.color = converted.color + + + def _CIELAB2MSH(self): + """ + Convert CIE Lab to Msh colorspace. + + from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls + """ + if self.model != 'CIELAB': return + + Msh = np.zeros(3) + Msh[0] = np.sqrt(np.dot(self.color,self.color)) + if (Msh[0] > 0.001): + Msh[1] = np.arccos(self.color[0]/Msh[0]) + if (self.color[1] != 0.0): + Msh[2] = np.arctan2(self.color[2],self.color[1]) + + converted = Color('MSH', Msh) + self.model = converted.model + self.color = converted.color + + + def _MSH2CIELAB(self): + """ + Convert Msh colorspace to CIE Lab. + + with s,h in radians + from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls + """ + if self.model != 'MSH': return + + Lab = np.zeros(3) + Lab[0] = self.color[0] * np.cos(self.color[1]) + Lab[1] = self.color[0] * np.sin(self.color[1]) * np.cos(self.color[2]) + Lab[2] = self.color[0] * np.sin(self.color[1]) * np.sin(self.color[2]) + + converted = Color('CIELAB', Lab) + self.model = converted.model + self.color = converted.color + + +class Colormap: + """Perceptually uniform diverging or sequential colormap.""" + + __slots__ = [ + 'left', + 'right', + 'interpolate', + ] + __predefined__ = { + 'gray': {'left': Color('HSL',[0,1,1]), + 'right': Color('HSL',[0,0,0.15]), + 'interpolate': 'perceptualuniform'}, + 'grey': {'left': Color('HSL',[0,1,1]), + 'right': Color('HSL',[0,0,0.15]), + 'interpolate': 'perceptualuniform'}, + 'red': {'left': Color('HSL',[0,1,0.14]), + 'right': Color('HSL',[0,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'green': {'left': Color('HSL',[0.33333,1,0.14]), + 'right': Color('HSL',[0.33333,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'blue': {'left': Color('HSL',[0.66,1,0.14]), + 'right': Color('HSL',[0.66,0.35,0.91]), + 'interpolate': 'perceptualuniform'}, + 'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), + 'right': Color('HSL',[0.40000,0.1,0.9]), + 'interpolate': 'perceptualuniform'}, + 'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), + 'right': Color('HSL',[0.11,0.75,0.38]), + 'interpolate': 'perceptualuniform'}, + 'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), + 'right': Color('HSL',[0.33333,1.0,0.14]), + 'interpolate': 'perceptualuniform'}, + 'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), + 'right': Color('HSL',[0.97,0.96,0.36]), + 'interpolate': 'perceptualuniform'}, + 'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), + 'right': Color('HSL',[0,1,0.5]), + 'interpolate': 'linear' }, + 'orientation': {'left': Color('RGB',[0.933334,0.878432,0.878431]), + 'right': Color('RGB',[0.250980,0.007843,0.000000]), + 'interpolate': 'perceptualuniform'}, + 'strain': {'left': Color('RGB',[0.941177,0.941177,0.870588]), + 'right': Color('RGB',[0.266667,0.266667,0.000000]), + 'interpolate': 'perceptualuniform'}, + 'stress': {'left': Color('RGB',[0.878432,0.874511,0.949019]), + 'right': Color('RGB',[0.000002,0.000000,0.286275]), + 'interpolate': 'perceptualuniform'}, + } + + + def __init__(self, + left = Color('RGB',[1,1,1]), + right = Color('RGB',[0,0,0]), + interpolate = 'perceptualuniform', + predefined = None + ): + """ + Create a Colormap object. + + Parameters + ---------- + left : Color + left color (minimum value) + right : Color + right color (maximum value) + interpolate : str + interpolation scheme (either 'perceptualuniform' or 'linear') + predefined : bool + ignore other arguments and use predefined definition + + """ + if predefined is not None: + left = self.__predefined__[predefined.lower()]['left'] + right= self.__predefined__[predefined.lower()]['right'] + interpolate = self.__predefined__[predefined.lower()]['interpolate'] + + if left.__class__.__name__ != 'Color': + left = Color() + if right.__class__.__name__ != 'Color': + right = Color() + + self.left = left + self.right = right + self.interpolate = interpolate + + + def __repr__(self): + """Left and right value of colormap.""" + return 'Left: %s Right: %s'%(self.left,self.right) + + + def invert(self): + """Switch left/minimum with right/maximum.""" + (self.left, self.right) = (self.right, self.left) + return self + + + def show_predefined(self): + """Show the labels of the predefined colormaps.""" + print('\n'.join(self.__predefined__.keys())) + + def color(self,fraction = 0.5): + + def interpolate_Msh(lo, hi, frac): + + def rad_diff(a,b): + return abs(a[2]-b[2]) + + def adjust_hue(Msh_sat, Msh_unsat): + """If saturation of one of the two colors is too less than the other, hue of the less.""" + if Msh_sat[0] >= Msh_unsat[0]: + return Msh_sat[2] + else: + hSpin = Msh_sat[1]/np.sin(Msh_sat[1])*np.sqrt(Msh_unsat[0]**2.0-Msh_sat[0]**2)/Msh_sat[0] + if Msh_sat[2] < - np.pi/3.0: hSpin *= -1.0 + return Msh_sat[2] + hSpin + + Msh1 = np.array(lo[:]) + Msh2 = np.array(hi[:]) + + if (Msh1[1] > 0.05 and Msh2[1] > 0.05 and rad_diff(Msh1,Msh2) > np.pi/3.0): + M_mid = max(Msh1[0],Msh2[0],88.0) + if frac < 0.5: + Msh2 = np.array([M_mid,0.0,0.0]) + frac *= 2.0 + else: + Msh1 = np.array([M_mid,0.0,0.0]) + frac = 2.0*frac - 1.0 + if Msh1[1] < 0.05 and Msh2[1] > 0.05: Msh1[2] = adjust_hue(Msh2,Msh1) + elif Msh1[1] > 0.05 and Msh2[1] < 0.05: Msh2[2] = adjust_hue(Msh1,Msh2) + Msh = (1.0 - frac) * Msh1 + frac * Msh2 + + return Color('MSH',Msh) + + def interpolate_linear(lo, hi, frac): + """Linear interpolation between lo and hi color at given fraction; output in model of lo color.""" + interpolation = (1.0 - frac) * np.array(lo.color[:]) \ + + frac * np.array(hi.express_as(lo.model).color[:]) + + return Color(lo.model,interpolation) + + if self.interpolate == 'perceptualuniform': + return interpolate_Msh(self.left.express_as('MSH').color, + self.right.express_as('MSH').color,fraction) + elif self.interpolate == 'linear': + return interpolate_linear(self.left,self.right,fraction) + else: + raise NameError('unknown color interpolation method') + + + def export(self,name = 'uniformPerceptualColorMap',\ + format = 'paraview',\ + steps = 2,\ + crop = [-1.0,1.0], + model = 'RGB'): + """ + [RGB] colormap for use in paraview or gmsh, or as raw string, or array. + + Arguments: name, format, steps, crop. + Format is one of (paraview, gmsh, raw, list). + Crop selects a (sub)range in [-1.0,1.0]. + Generates sequential map if one limiting color is either white or black, + diverging map otherwise. + """ + format = format.lower() # consistent comparison basis + frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions + colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).express_as(model).color for i in range(steps)] + if format == 'paraview': + colormap = ['[\n {{\n "ColorSpace": "RGB", "Name": "{}", "DefaultMap": true,\n "RGBPoints" : ['.format(name)] \ + + [' {:4d},{:8.6f},{:8.6f},{:8.6f},'.format(i,color[0],color[1],color[2],) \ + for i,color in enumerate(colors[:-1])] \ + + [' {:4d},{:8.6f},{:8.6f},{:8.6f} '.format(len(colors),colors[-1][0],colors[-1][1],colors[-1][2],)] \ + + [' ]\n }\n]'] + + elif format == 'gmsh': + colormap = ['View.ColorTable = {'] \ + + [',\n'.join(['{%s}'%(','.join([str(x*255.0) for x in color])) for color in colors])] \ + + ['}'] + + elif format == 'gom': + colormap = ['1 1 ' + str(name) + + ' 9 ' + str(name) + + ' 0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' + + '30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 ' + str(len(colors)) + + ' '.join([' 0 %s 255 1'%(' '.join([str(int(x*255.0)) for x in color])) for color in reversed(colors)])] + + elif format == 'raw': + colormap = ['\t'.join(map(str,color)) for color in colors] + + elif format == 'list': + colormap = colors + + else: + raise NameError('unknown color export format') + + return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap diff --git a/python/damask/environment.py b/python/damask/_environment.py similarity index 91% rename from python/damask/environment.py rename to python/damask/_environment.py index a4e4ed7b3..df690314c 100644 --- a/python/damask/environment.py +++ b/python/damask/_environment.py @@ -1,16 +1,17 @@ import os +import tkinter -class Environment(): +class Environment: def __init__(self): """Read and provide values of DAMASK configuration.""" self.options = self._get_options() try: - import tkinter tk = tkinter.Tk() self.screen_width = tk.winfo_screenwidth() self.screen_height = tk.winfo_screenheight() - except Exception: + tk.destroy() + except tkinter.TclError: self.screen_width = 1024 self.screen_height = 768 diff --git a/python/damask/geom.py b/python/damask/_geom.py similarity index 97% rename from python/damask/geom.py rename to python/damask/_geom.py index a2b5249f2..6bc92e300 100644 --- a/python/damask/geom.py +++ b/python/damask/_geom.py @@ -8,7 +8,7 @@ from . import VTK from . import util -class Geom(): +class Geom: """Geometry definition for grid solvers.""" def __init__(self,microstructure,size,origin=[0.0,0.0,0.0],homogenization=1,comments=[]): @@ -47,6 +47,7 @@ class Geom(): 'max microstructure: {}'.format(np.nanmax(self.microstructure)), ]) + def update(self,microstructure=None,size=None,origin=None,rescale=False): """ Updates microstructure and size. @@ -109,6 +110,7 @@ class Geom(): return util.return_message(message) + def set_comments(self,comments): """ Replaces all existing comments. @@ -122,6 +124,7 @@ class Geom(): self.comments = [] self.add_comments(comments) + def add_comments(self,comments): """ Appends comments to existing comments. @@ -134,6 +137,7 @@ class Geom(): """ self.comments += [str(c) for c in comments] if isinstance(comments,list) else [str(comments)] + def set_microstructure(self,microstructure): """ Replaces the existing microstructure representation. @@ -152,6 +156,7 @@ class Geom(): else: self.microstructure = np.copy(microstructure) + def set_size(self,size): """ Replaces the existing size information. @@ -171,6 +176,7 @@ class Geom(): else: self.size = np.array(size) + def set_origin(self,origin): """ Replaces the existing origin information. @@ -187,6 +193,7 @@ class Geom(): else: self.origin = np.array(origin) + def set_homogenization(self,homogenization): """ Replaces the existing homogenization index. @@ -203,34 +210,47 @@ class Geom(): else: self.homogenization = homogenization + @property def grid(self): return self.get_grid() + + @property + def N_microstructure(self): + return len(np.unique(self.microstructure)) + + def get_microstructure(self): """Return the microstructure representation.""" return np.copy(self.microstructure) + def get_size(self): """Return the physical size in meter.""" return np.copy(self.size) + def get_origin(self): """Return the origin in meter.""" return np.copy(self.origin) + def get_grid(self): """Return the grid discretization.""" return np.array(self.microstructure.shape) + def get_homogenization(self): """Return the homogenization index.""" return self.homogenization + def get_comments(self): """Return the comments.""" return self.comments[:] + def get_header(self): """Return the full header (grid, size, origin, homogenization, comments).""" header = ['{} header'.format(len(self.comments)+4)] + self.comments @@ -240,6 +260,7 @@ class Geom(): header.append('homogenization {}'.format(self.get_homogenization())) return header + @staticmethod def from_file(fname): """ @@ -425,8 +446,8 @@ class Geom(): if 'x' in directions: ms = np.concatenate([ms,ms[limits[0]:limits[1]:-1,:,:]],0) + #self.add_comments('geom.py:mirror v{}'.format(version) return self.update(ms,rescale=True) - #self.add_comments('tbd') def scale(self,grid): @@ -439,6 +460,7 @@ class Geom(): new grid dimension """ + #self.add_comments('geom.py:scale v{}'.format(version) return self.update( ndimage.interpolation.zoom( self.microstructure, @@ -449,7 +471,6 @@ class Geom(): prefilter=False ) ) - #self.add_comments('tbd') def clean(self,stencil=3): @@ -466,13 +487,13 @@ class Geom(): unique, inverse = np.unique(arr, return_inverse=True) return unique[np.argmax(np.bincount(inverse))] + #self.add_comments('geom.py:clean v{}'.format(version) return self.update(ndimage.filters.generic_filter( self.microstructure, mostFrequent, size=(stencil,)*3 ).astype(self.microstructure.dtype) ) - #self.add_comments('tbd') def renumber(self): @@ -481,5 +502,5 @@ class Geom(): for i, oldID in enumerate(np.unique(self.microstructure)): renumbered = np.where(self.microstructure == oldID, i+1, renumbered) + #self.add_comments('geom.py:renumber v{}'.format(version) return self.update(renumbered) - #self.add_comments('tbd') diff --git a/python/damask/lattice.py b/python/damask/_lattice.py similarity index 99% rename from python/damask/lattice.py rename to python/damask/_lattice.py index 3c949b02c..42aa0e9bd 100644 --- a/python/damask/lattice.py +++ b/python/damask/_lattice.py @@ -1,10 +1,8 @@ import numpy as np -from .rotation import Rotation +from . import Rotation -P = -1 -# ****************************************************************************************** class Symmetry: """ Symmetry operations for lattice systems. diff --git a/python/damask/orientation.py b/python/damask/_orientation.py similarity index 72% rename from python/damask/orientation.py rename to python/damask/_orientation.py index 4916c1679..6cbe4f7d4 100644 --- a/python/damask/orientation.py +++ b/python/damask/_orientation.py @@ -1,7 +1,7 @@ import numpy as np -from .lattice import Lattice -from .rotation import Rotation +from . import Lattice +from . import Rotation class Orientation: """ @@ -50,23 +50,23 @@ class Orientation: Look into A. Heinz and P. Neumann 1991 for cases with differing sym.) """ if self.lattice.symmetry != other.lattice.symmetry: - raise NotImplementedError('disorientation between different symmetry classes not supported yet.') + raise NotImplementedError('disorientation between different symmetry classes not supported yet.') mySymEqs = self.equivalentOrientations() if SST else self.equivalentOrientations([0]) # take all or only first sym operation otherSymEqs = other.equivalentOrientations() for i,sA in enumerate(mySymEqs): - aInv = sA.rotation.inversed() - for j,sB in enumerate(otherSymEqs): - b = sB.rotation - r = b*aInv - for k in range(2): - r.inverse() - breaker = self.lattice.symmetry.inFZ(r.asRodrigues(vector=True)) \ - and (not SST or other.lattice.symmetry.inDisorientationSST(r.asRodrigues(vector=True))) - if breaker: break + aInv = sA.rotation.inversed() + for j,sB in enumerate(otherSymEqs): + b = sB.rotation + r = b*aInv + for k in range(2): + r.inverse() + breaker = self.lattice.symmetry.inFZ(r.asRodrigues(vector=True)) \ + and (not SST or other.lattice.symmetry.inDisorientationSST(r.asRodrigues(vector=True))) + if breaker: break + if breaker: break if breaker: break - if breaker: break return (Orientation(r,self.lattice), i,j, k == 1) if symmetries else r # disorientation ... # ... own sym, other sym, @@ -78,11 +78,11 @@ class Orientation: def equivalentOrientations(self,members=[]): """List of orientations which are symmetrically equivalent.""" try: - iter(members) # asking for (even empty) list of members? + iter(members) # asking for (even empty) list of members? except TypeError: - return self.__class__(self.lattice.symmetry.symmetryOperations(members)*self.rotation,self.lattice) # no, return rotation object + return self.__class__(self.lattice.symmetry.symmetryOperations(members)*self.rotation,self.lattice) # no, return rotation object else: - return [self.__class__(q*self.rotation,self.lattice) \ + return [self.__class__(q*self.rotation,self.lattice) \ for q in self.lattice.symmetry.symmetryOperations(members)] # yes, return list of rotations def relatedOrientations(self,model): @@ -94,7 +94,7 @@ class Orientation: def reduced(self): """Transform orientation to fall into fundamental zone according to symmetry.""" for me in self.equivalentOrientations(): - if self.lattice.symmetry.inFZ(me.rotation.asRodrigues(vector=True)): break + if self.lattice.symmetry.inFZ(me.rotation.asRodrigues(vector=True)): break return self.__class__(me.rotation,self.lattice) @@ -105,11 +105,11 @@ class Orientation: SST = True): """Axis rotated according to orientation (using crystal symmetry to ensure location falls into SST).""" if SST: # pole requested to be within SST - for i,o in enumerate(self.equivalentOrientations()): # test all symmetric equivalent quaternions - pole = o.rotation*axis # align crystal direction to axis - if self.lattice.symmetry.inSST(pole,proper): break # found SST version + for i,o in enumerate(self.equivalentOrientations()): # test all symmetric equivalent quaternions + pole = o.rotation*axis # align crystal direction to axis + if self.lattice.symmetry.inSST(pole,proper): break # found SST version else: - pole = self.rotation*axis # align crystal direction to axis + pole = self.rotation*axis # align crystal direction to axis return (pole,i if SST else 0) @@ -119,9 +119,9 @@ class Orientation: color = np.zeros(3,'d') for o in self.equivalentOrientations(): - pole = o.rotation*axis # align crystal direction to axis - inSST,color = self.lattice.symmetry.inSST(pole,color=True) - if inSST: break + pole = o.rotation*axis # align crystal direction to axis + inSST,color = self.lattice.symmetry.inSST(pole,color=True) + if inSST: break return color @@ -131,15 +131,15 @@ class Orientation: weights = []): """Create orientation from average of list of orientations.""" if not all(isinstance(item, Orientation) for item in orientations): - raise TypeError("Only instances of Orientation can be averaged.") + raise TypeError("Only instances of Orientation can be averaged.") closest = [] 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 + closest.append(o.equivalentOrientations( + 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/result.py b/python/damask/_result.py similarity index 88% rename from python/damask/result.py rename to python/damask/_result.py index 748ea63fd..6c9b4bdfa 100644 --- a/python/damask/result.py +++ b/python/damask/_result.py @@ -22,7 +22,7 @@ class Result: """ Read and write to DADF5 files. - DADF5 (DAKMASK HDF5) files contain DAMASK results. + DADF5 (DAMASK HDF5) files contain DAMASK results. """ def __init__(self,fname): @@ -32,7 +32,7 @@ class Result: Parameters ---------- fname : str - name of the DADF5 file to be openend. + name of the DADF5 file to be openend. """ with h5py.File(fname,'r') as f: @@ -85,7 +85,14 @@ class Result: def __repr__(self): """Show selected data.""" - return util.srepr(self.list_data()) + all_selected_increments = self.selection['increments'] + self.pick('increments',all_selected_increments[0:1]) + first = self.list_data() + self.pick('increments',all_selected_increments[-1:]) + last = self.list_data() + self.pick('increments',all_selected_increments) + in_between = ''.join(['\n{}\n ...\n'.format(inc) for inc in all_selected_increments[1:-2]]) + return util.srepr(first+ in_between + last) def _manage_selection(self,action,what,datasets): @@ -95,12 +102,12 @@ class Result: Parameters ---------- action : str - select from 'set', 'add', and 'del' + select from 'set', 'add', and 'del' what : str - attribute to change (must be from self.selection) + attribute to change (must be from self.selection) datasets : list of str or Boolean - name of datasets as list, supports ? and * wildcards. - True is equivalent to [*], False is equivalent to [] + name of datasets as list, supports ? and * wildcards. + True is equivalent to [*], False is equivalent to [] """ # allow True/False and string arguments @@ -167,17 +174,17 @@ class Result: Parameters ---------- what : str - attribute to change (must be from self.selection) + attribute to change (must be from self.selection) """ datasets = self.selection[what] - last_datasets = datasets.copy() + last_selection = datasets.copy() for dataset in datasets: - if last_datasets != self.selection[what]: + if last_selection != self.selection[what]: self._manage_selection('set',what,datasets) raise Exception self._manage_selection('set',what,dataset) - last_datasets = self.selection[what] + last_selection = self.selection[what] yield dataset self._manage_selection('set',what,datasets) @@ -189,10 +196,10 @@ class Result: Parameters ---------- what : str - attribute to change (must be from self.selection) + attribute to change (must be from self.selection) datasets : list of str or Boolean - name of datasets as list, supports ? and * wildcards. - True is equivalent to [*], False is equivalent to [] + name of datasets as list, supports ? and * wildcards. + True is equivalent to [*], False is equivalent to [] """ self._manage_selection('set',what,datasets) @@ -205,10 +212,10 @@ class Result: Parameters ---------- what : str - attribute to change (must be from self.selection) + attribute to change (must be from self.selection) datasets : list of str or Boolean - name of datasets as list, supports ? and * wildcards. - True is equivalent to [*], False is equivalent to [] + name of datasets as list, supports ? and * wildcards. + True is equivalent to [*], False is equivalent to [] """ self._manage_selection('add',what,datasets) @@ -221,10 +228,10 @@ class Result: Parameters ---------- what : str - attribute to change (must be from self.selection) + attribute to change (must be from self.selection) datasets : list of str or Boolean - name of datasets as list, supports ? and * wildcards. - True is equivalent to [*], False is equivalent to [] + name of datasets as list, supports ? and * wildcards. + True is equivalent to [*], False is equivalent to [] """ self._manage_selection('del',what,datasets) @@ -248,13 +255,13 @@ class Result: ---------- datasets : iterable or str component : int - homogenization component to consider for constituent data + homogenization component to consider for constituent data tagged : Boolean - tag Table.column name with '#component' - defaults to False + tag Table.column name with '#component' + defaults to False split : Boolean - split Table by increment and return dictionary of Tables - defaults to True + split Table by increment and return dictionary of Tables + defaults to True """ sets = datasets if hasattr(datasets,'__iter__') and not isinstance(datasets,str) \ @@ -313,17 +320,17 @@ class Result: Parameters ---------- - datasets : iterable or str or Boolean + datasets : iterable or str or Boolean Examples -------- - datasets = False matches no group - datasets = True matches all groups - datasets = ['F','P'] matches a group with ['F','P','sigma'] - datasets = ['*','P'] matches a group with ['F','P'] - datasets = ['*'] does not match a group with ['F','P','sigma'] - datasets = ['*','*'] does not match a group with ['F','P','sigma'] - datasets = ['*','*','*'] matches a group with ['F','P','sigma'] + datasets = False matches no group + datasets = True matches all groups + datasets = ['F','P'] matches a group with ['F','P','sigma'] + datasets = ['*','P'] matches a group with ['F','P'] + datasets = ['*'] does not match a group with ['F','P','sigma'] + datasets = ['*','*'] does not match a group with ['F','P','sigma'] + datasets = ['*','*','*'] matches a group with ['F','P','sigma'] """ if datasets is False: return [] @@ -471,7 +478,7 @@ class Result: Parameters ---------- x : str - Label of scalar, vector, or tensor dataset to take absolute value of. + Label of scalar, vector, or tensor dataset to take absolute value of. """ self._add_generic_pointwise(self._add_absolute,{'x':x}) @@ -501,13 +508,13 @@ class Result: label : str Label of resulting dataset. formula : str - Formula to calculate resulting dataset. Existing datasets are referenced by ‘#TheirLabel#‘. + Formula to calculate resulting dataset. Existing datasets are referenced by ‘#TheirLabel#‘. unit : str, optional - Physical unit of the result. + Physical unit of the result. description : str, optional - Human-readable description of the result. + Human-readable description of the result. vectorized : bool, optional - Indicate whether the formula can be used in vectorized form. Defaults to ‘True’. + Indicate whether the formula can be used in vectorized form. Defaults to ‘True’. """ if not vectorized: @@ -538,9 +545,9 @@ class Result: Parameters ---------- P : str, optional - Label of the dataset containing the first Piola-Kirchhoff stress. Defaults to ‘P’. + Label of the dataset containing the first Piola-Kirchhoff stress. Defaults to ‘P’. F : str, optional - Label of the dataset containing the deformation gradient. Defaults to ‘F’. + Label of the dataset containing the deformation gradient. Defaults to ‘F’. """ self._add_generic_pointwise(self._add_Cauchy,{'P':P,'F':F}) @@ -564,7 +571,7 @@ class Result: Parameters ---------- T : str - Label of tensor dataset. + Label of tensor dataset. """ self._add_generic_pointwise(self._add_determinant,{'T':T}) @@ -591,7 +598,7 @@ class Result: Parameters ---------- T : str - Label of tensor dataset. + Label of tensor dataset. """ self._add_generic_pointwise(self._add_deviator,{'T':T}) @@ -615,7 +622,7 @@ class Result: Parameters ---------- T_sym : str - Label of symmetric tensor dataset. + Label of symmetric tensor dataset. """ self._add_generic_pointwise(self._add_eigenvalue,{'T_sym':T_sym}) @@ -639,7 +646,7 @@ class Result: Parameters ---------- T_sym : str - Label of symmetric tensor dataset. + Label of symmetric tensor dataset. """ self._add_generic_pointwise(self._add_eigenvector,{'T_sym':T_sym}) @@ -664,7 +671,7 @@ class Result: 'meta' : { 'Unit': 'RGB (8bit)', 'Lattice': lattice, - 'Description': 'Inverse Pole Figure (IPF) colors for direction/plane [{} {} {})'.format(*m), + 'Description': 'Inverse Pole Figure (IPF) colors along sample direction [{} {} {}]'.format(*m), 'Creator': 'result.py:add_IPFcolor v{}'.format(version) } } @@ -675,9 +682,9 @@ class Result: Parameters ---------- q : str - Label of the dataset containing the crystallographic orientation as quaternions. + Label of the dataset containing the crystallographic orientation as quaternions. l : numpy.array of shape (3) - Lab frame direction for inverse pole figure. + Lab frame direction for inverse pole figure. """ self._add_generic_pointwise(self._add_IPFcolor,{'q':q},{'l':l}) @@ -701,7 +708,7 @@ class Result: Parameters ---------- T_sym : str - Label of symmetric tensor dataset. + Label of symmetric tensor dataset. """ self._add_generic_pointwise(self._add_maximum_shear,{'T_sym':T_sym}) @@ -728,7 +735,7 @@ class Result: Parameters ---------- T_sym : str - Label of symmetric tensorial stress or strain dataset. + Label of symmetric tensorial stress or strain dataset. """ self._add_generic_pointwise(self._add_Mises,{'T_sym':T_sym}) @@ -764,9 +771,9 @@ class Result: Parameters ---------- x : str - Label of vector or tensor dataset. + Label of vector or tensor dataset. ord : {non-zero int, inf, -inf, ‘fro’, ‘nuc’}, optional - Order of the norm. inf means NumPy’s inf object. For details refer to numpy.linalg.norm. + Order of the norm. inf means NumPy’s inf object. For details refer to numpy.linalg.norm. """ self._add_generic_pointwise(self._add_norm,{'x':x},{'ord':ord}) @@ -792,9 +799,9 @@ class Result: Parameters ---------- P : str, optional - Label first Piola-Kirchhoff stress dataset. Defaults to ‘P’. + Label first Piola-Kirchhoff stress dataset. Defaults to ‘P’. F : str, optional - Label of deformation gradient dataset. Defaults to ‘F’. + Label of deformation gradient dataset. Defaults to ‘F’. """ self._add_generic_pointwise(self._add_PK2,{'P':P,'F':F}) @@ -830,11 +837,11 @@ class Result: Parameters ---------- q : str - Label of the dataset containing the crystallographic orientation as quaternions. + Label of the dataset containing the crystallographic orientation as quaternions. p : numpy.array of shape (3) - Crystallographic direction or plane. + Crystallographic direction or plane. polar : bool, optional - Give pole in polar coordinates. Defaults to False. + Give pole in polar coordinates. Defaults to False. """ self._add_generic_pointwise(self._add_pole,{'q':q},{'p':p,'polar':polar}) @@ -860,7 +867,7 @@ class Result: Parameters ---------- F : str, optional - Label of deformation gradient dataset. + Label of deformation gradient dataset. """ self._add_generic_pointwise(self._add_rotational_part,{'F':F}) @@ -887,7 +894,7 @@ class Result: Parameters ---------- T : str - Label of tensor dataset. + Label of tensor dataset. """ self._add_generic_pointwise(self._add_spherical,{'T':T}) @@ -916,12 +923,12 @@ class Result: Parameters ---------- F : str, optional - Label of deformation gradient dataset. Defaults to ‘F’. + Label of deformation gradient dataset. Defaults to ‘F’. t : {‘V’, ‘U’}, optional - Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. - Defaults to ‘V’. + Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + Defaults to ‘V’. m : float, optional - Order of the strain calculation. Defaults to ‘0.0’. + Order of the strain calculation. Defaults to ‘0.0’. """ self._add_generic_pointwise(self._add_strain_tensor,{'F':F},{'t':t,'m':m}) @@ -949,10 +956,10 @@ class Result: Parameters ---------- F : str, optional - Label of deformation gradient dataset. Defaults to ‘F’. + Label of deformation gradient dataset. Defaults to ‘F’. t : {‘V’, ‘U’}, optional - Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. - Defaults to ‘V’. + Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + Defaults to ‘V’. """ self._add_generic_pointwise(self._add_stretch_tensor,{'F':F},{'t':t}) @@ -984,11 +991,11 @@ class Result: Parameters ---------- func : function - Callback function that calculates a new dataset from one or more datasets per HDF5 group. + Callback function that calculates a new dataset from one or more datasets per HDF5 group. datasets : dictionary - Details of the datasets to be used: label (in HDF5 file) and arg (argument to which the data is parsed in func). + Details of the datasets to be used: label (in HDF5 file) and arg (argument to which the data is parsed in func). args : dictionary, optional - Arguments parsed to func. + Arguments parsed to func. """ pool = multiprocessing.Pool(int(Environment().options['DAMASK_NUM_THREADS'])) @@ -1014,17 +1021,17 @@ class Result: pool.join() - def to_vtk(self,labels,mode='cell'): + def to_vtk(self,labels=[],mode='cell'): """ Export to vtk cell/point data. Parameters ---------- - labels : str or list of - Labels of the datasets to be exported. + labels : str or list of, optional + Labels of the datasets to be exported. mode : str, either 'cell' or 'point' - Export in cell format or point format. - Defaults to 'cell'. + Export in cell format or point format. + Defaults to 'cell'. """ if mode.lower()=='cell': @@ -1039,7 +1046,7 @@ class Result: elif mode.lower()=='point': v = VTK.from_polyData(self.cell_coordinates()) - N_digits = int(np.floor(np.log10(min(int(self.increments[-1][3:]),1))))+1 + N_digits = int(np.floor(np.log10(int(self.increments[-1][3:]))))+1 for i,inc in enumerate(util.show_progress(self.iterate('increments'),len(self.selection['increments']))): @@ -1093,9 +1100,6 @@ class Result: ################################################################################################### # BEGIN DEPRECATED - iter_visible = iterate - iter_selection = iterate - def _time_to_inc(self,start,end): selected = [] @@ -1118,21 +1122,3 @@ class Result: """ self._manage_selection('set','increments',self._time_to_inc(start,end)) - - - def set_by_increment(self,start,end): - """ - Set active time increments based on start and end increment. - - Parameters - ---------- - start : int - start increment (included) - end : int - end increment (included) - - """ - if self.version_minor >= 4: - self._manage_selection('set','increments',[ 'inc{}'.format(i) for i in range(start,end+1)]) - else: - self._manage_selection('set','increments',['inc{:05d}'.format(i) for i in range(start,end+1)]) diff --git a/python/damask/rotation.py b/python/damask/_rotation.py similarity index 97% rename from python/damask/rotation.py rename to python/damask/_rotation.py index 78686ab1f..0b481e149 100644 --- a/python/damask/rotation.py +++ b/python/damask/_rotation.py @@ -1,6 +1,6 @@ import numpy as np -from . import Lambert +from ._Lambert import ball_to_cube, cube_to_ball P = -1 @@ -304,7 +304,7 @@ class Rotation: reciprocal = False, ): - om = basis if isinstance(basis, np.ndarray) else np.array(basis).reshape((3,3)) + om = basis if isinstance(basis, np.ndarray) else np.array(basis).reshape(3,3) if reciprocal: om = np.linalg.inv(om.T/np.pi) # transform reciprocal basis set orthonormal = False # contains stretch @@ -338,7 +338,7 @@ class Rotation: if not np.isclose(np.linalg.norm(ro[0:3]), 1.0): raise ValueError('Rodrigues rotation axis is not of unit length.\n{} {} {}'.format(*ro[0:3])) if ro[3] < 0.0: - raise ValueError('Rodriques rotation angle not positive.\n'.format(ro[3])) + raise ValueError('Rodrigues rotation angle not positive.\n'.format(ro[3])) return Rotation(Rotation.ro2qu(ro)) @@ -492,7 +492,7 @@ class Rotation: @staticmethod def qu2ro(qu): - """Quaternion to Rodriques-Frank vector.""" + """Quaternion to Rodrigues-Frank vector.""" if iszero(qu[0]): ro = [qu[1], qu[2], qu[3], np.inf] else: @@ -567,7 +567,7 @@ class Rotation: @staticmethod def om2ro(om): - """Rotation matrix to Rodriques-Frank vector.""" + """Rotation matrix to Rodrigues-Frank vector.""" return Rotation.eu2ro(Rotation.om2eu(om)) @staticmethod @@ -628,7 +628,7 @@ class Rotation: @staticmethod def eu2ro(eu): - """Bunge-Euler angles to Rodriques-Frank vector.""" + """Bunge-Euler angles to Rodrigues-Frank vector.""" ro = Rotation.eu2ax(eu) # convert to axis angle pair representation if ro[3] >= np.pi: # Differs from original implementation. check convention 5 ro[3] = np.inf @@ -682,7 +682,7 @@ class Rotation: @staticmethod def ax2ro(ax): - """Axis angle pair to Rodriques-Frank vector.""" + """Axis angle pair to Rodrigues-Frank vector.""" if iszero(ax[3]): ro = [ 0.0, 0.0, P, 0.0 ] else: @@ -708,7 +708,7 @@ class Rotation: #---------- Rodrigues-Frank vector ---------- @staticmethod def ro2qu(ro): - """Rodriques-Frank vector to quaternion.""" + """Rodrigues-Frank vector to quaternion.""" return Rotation.ax2qu(Rotation.ro2ax(ro)) @staticmethod @@ -718,12 +718,12 @@ class Rotation: @staticmethod def ro2eu(ro): - """Rodriques-Frank vector to Bunge-Euler angles.""" + """Rodrigues-Frank vector to Bunge-Euler angles.""" return Rotation.om2eu(Rotation.ro2om(ro)) @staticmethod def ro2ax(ro): - """Rodriques-Frank vector to axis angle pair.""" + """Rodrigues-Frank vector to axis angle pair.""" ta = ro[3] if iszero(ta): @@ -738,7 +738,7 @@ class Rotation: @staticmethod def ro2ho(ro): - """Rodriques-Frank vector to homochoric vector.""" + """Rodrigues-Frank vector to homochoric vector.""" if iszero(np.sum(ro[0:3]**2.0)): ho = [ 0.0, 0.0, 0.0 ] else: @@ -748,7 +748,7 @@ class Rotation: @staticmethod def ro2cu(ro): - """Rodriques-Frank vector to cubochoric vector.""" + """Rodrigues-Frank vector to cubochoric vector.""" return Rotation.ho2cu(Rotation.ro2ho(ro)) @@ -796,13 +796,13 @@ class Rotation: @staticmethod def ho2ro(ho): - """Axis angle pair to Rodriques-Frank vector.""" + """Axis angle pair to Rodrigues-Frank vector.""" return Rotation.ax2ro(Rotation.ho2ax(ho)) @staticmethod def ho2cu(ho): """Homochoric vector to cubochoric vector.""" - return Lambert.BallToCube(ho) + return ball_to_cube(ho) #---------- Cubochoric ---------- @@ -828,10 +828,10 @@ class Rotation: @staticmethod def cu2ro(cu): - """Cubochoric vector to Rodriques-Frank vector.""" + """Cubochoric vector to Rodrigues-Frank vector.""" return Rotation.ho2ro(Rotation.cu2ho(cu)) @staticmethod def cu2ho(cu): """Cubochoric vector to homochoric vector.""" - return Lambert.CubeToBall(cu) + return cube_to_ball(cu) diff --git a/python/damask/table.py b/python/damask/_table.py similarity index 88% rename from python/damask/table.py rename to python/damask/_table.py index b704bdc24..9cb09fb3b 100644 --- a/python/damask/table.py +++ b/python/damask/_table.py @@ -5,39 +5,39 @@ import numpy as np from . import version -class Table(): +class Table: """Store spreadsheet-like data.""" - + def __init__(self,data,shapes,comments=None): """ New spreadsheet. - + Parameters ---------- data : numpy.ndarray or pandas.DataFrame Data. Column labels from a pandas.DataFrame will be replaced. shapes : dict with str:tuple pairs - Shapes of the columns. Example 'F':(3,3) for a deformation gradient. + Shapes of the columns. Example 'F':(3,3) for a deformation gradient. comments : iterable of str, optional Additional, human-readable information. - + """ self.comments = [] if comments is None else [c for c in comments] self.data = pd.DataFrame(data=data) self.shapes = shapes - self.__label_condensed() + self._label_condensed() - def __label_flat(self): + def _label_flat(self): """Label data individually, e.g. v v v ==> 1_v 2_v 3_v.""" labels = [] for label,shape in self.shapes.items(): size = int(np.prod(shape)) labels += ['{}{}'.format('' if size == 1 else '{}_'.format(i+1),label) for i in range(size)] self.data.columns = labels - - - def __label_condensed(self): + + + def _label_condensed(self): """Label data condensed, e.g. 1_v 2_v 3_v ==> v v v.""" labels = [] for label,shape in self.shapes.items(): @@ -45,19 +45,19 @@ class Table(): self.data.columns = labels - def __add_comment(self,label,shape,info): + def _add_comment(self,label,shape,info): if info is not None: - self.comments.append('{}{}: {}'.format(label, - ' '+str(shape) if np.prod(shape,dtype=int) > 1 else '', - info)) + c = '{}{}: {}'.format(label,' '+str(shape) if np.prod(shape,dtype=int) > 1 else '',info) + self.comments.append(c) + - @staticmethod def from_ASCII(fname): """ Create table from ASCII file. - The first line needs to indicate the number of subsequent header lines as 'n header'. + The first line can indicate the number of subsequent header lines as 'n header', + alternatively first line is the header and comments are marked by '#' ('new style'). Vector data column labels are indicated by '1_v, 2_v, ..., n_v'. Tensor data column labels are indicated by '3x3:1_T, 3x3:2_T, ..., 3x3:9_T'. @@ -88,7 +88,7 @@ class Table(): comments.append(line.lstrip('#').strip()) line = f.readline().strip() labels = line.split() - + shapes = {} for label in labels: tensor_column = re.search(r'[0-9,x]*?:[0-9]*?_',label) @@ -101,7 +101,7 @@ class Table(): shapes[label.split('_',1)[1]] = (int(label.split('_',1)[0]),) else: shapes[label] = (1,) - + data = pd.read_csv(f,names=list(range(len(labels))),sep=r'\s+') return Table(data,shapes,comments) @@ -133,7 +133,7 @@ class Table(): except TypeError: f = fname f.seek(0) - + content = f.readlines() comments = ['table.py:from_ang v {}'.format(version)] @@ -142,7 +142,7 @@ class Table(): comments.append(line.strip()) else: break - + data = np.loadtxt(content) for c in range(data.shape[1]-10): shapes['n/a_{}'.format(c+1)] = (1,) @@ -167,8 +167,8 @@ class Table(): """ if re.match(r'[0-9]*?_',label): idx,key = label.split('_',1) - data = self.data[key].to_numpy()[:,int(idx)-1].reshape((-1,1)) - else: + data = self.data[key].to_numpy()[:,int(idx)-1].reshape(-1,1) + else: data = self.data[label].to_numpy().reshape((-1,)+self.shapes[label]) return data.astype(type(data.flatten()[0])) @@ -188,13 +188,13 @@ class Table(): Human-readable information about the new data. """ - self.__add_comment(label,data.shape[1:],info) + self._add_comment(label,data.shape[1:],info) if re.match(r'[0-9]*?_',label): idx,key = label.split('_',1) iloc = self.data.columns.get_loc(key).tolist().index(True) + int(idx) -1 self.data.iloc[:,iloc] = data - else: + else: self.data[label] = data.reshape(self.data[label].shape) @@ -212,7 +212,7 @@ class Table(): Human-readable information about the modified data. """ - self.__add_comment(label,data.shape[1:],info) + self._add_comment(label,data.shape[1:],info) self.shapes[label] = data.shape[1:] if len(data.shape) > 1 else (1,) size = np.prod(data.shape[1:],dtype=int) @@ -251,12 +251,8 @@ class Table(): """ self.data.rename(columns={label_old:label_new},inplace=True) - - self.comments.append('{} => {}{}'.format(label_old, - label_new, - '' if info is None else ': {}'.format(info), - )) - + c = '{} => {}{}'.format(label_old,label_new,'' if info is None else ': {}'.format(info)) + self.comments.append(c) self.shapes = {(label if label != label_old else label_new):self.shapes[label] for label in self.shapes} @@ -272,9 +268,9 @@ class Table(): Set sort order. """ - self.__label_flat() + self._label_flat() self.data.sort_values(labels,axis=0,inplace=True,ascending=ascending) - self.__label_condensed() + self._label_condensed() self.comments.append('sorted by [{}]'.format(', '.join(labels))) @@ -287,7 +283,7 @@ class Table(): Parameters ---------- other : Table - Table to append + Table to append. """ if self.shapes != other.shapes or not self.data.columns.equals(other.data.columns): @@ -305,7 +301,7 @@ class Table(): Parameters ---------- other : Table - Table to join + Table to join. """ if set(self.shapes) & set(other.shapes) or self.data.shape[0] != other.data.shape[0]: @@ -316,14 +312,16 @@ class Table(): self.shapes[key] = other.shapes[key] - def to_ASCII(self,fname,new=False): + def to_ASCII(self,fname,new_style=False): """ Store as plain text file. Parameters ---------- fname : file, str, or pathlib.Path - Filename or file for reading. + Filename or file for writing. + new_style : Boolean, optional + Write table in new style, indicating header lines by comment sign ('#') only. """ seen = set() @@ -338,7 +336,7 @@ class Table(): labels += ['{}:{}_{}'.format('x'.join([str(d) for d in self.shapes[l]]),i+1,l) \ for i in range(np.prod(self.shapes[l]))] - if new: + if new_style: header = ['# {}'.format(comment) for comment in self.comments] else: header = ['{} header'.format(len(self.comments)+1)] \ diff --git a/python/damask/test.py b/python/damask/_test.py similarity index 93% rename from python/damask/test.py rename to python/damask/_test.py index b1729548d..a46eedac8 100644 --- a/python/damask/test.py +++ b/python/damask/_test.py @@ -1,11 +1,16 @@ -import os,sys,shutil -import logging,logging.config -import damask -import numpy as np +import os +import sys +import shutil +import logging +import logging.config from collections.abc import Iterable from optparse import OptionParser -class Test(): +import numpy as np + +import damask + +class Test: """ General class for testing. @@ -13,7 +18,7 @@ class Test(): """ variants = [] - + def __init__(self, **kwargs): """New test.""" defaults = {'description': '', @@ -25,7 +30,7 @@ class Test(): } for arg in defaults.keys(): setattr(self,arg,kwargs.get(arg) if kwargs.get(arg) else defaults[arg]) - + fh = logging.FileHandler('test.log') # create file handler which logs even debug messages fh.setLevel(logging.DEBUG) fh.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s: \n%(message)s')) @@ -73,7 +78,7 @@ class Test(): select = self.select, ) - + def variantName(self,variant): """Generate name of (numerical) variant.""" return str(variant) @@ -99,7 +104,7 @@ class Test(): self.run(variant) self.postprocess(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 @@ -109,7 +114,7 @@ class Test(): logging.critical('exception during variant execution: "{}"'.format(str(e))) return variant+1 # return culprit return 0 - + def feasible(self): """Check whether test is possible or not (e.g. no license available).""" return True @@ -127,7 +132,7 @@ class Test(): except FileExistsError: logging.critical('creation of directory "{}" failed.'.format(self.dirCurrent())) return False - + def prepareAll(self): """Do all necessary preparations for the whole test.""" return True @@ -282,12 +287,10 @@ class Test(): import numpy as np logging.info('\n '.join(['comparing',File1,File2])) - table1 = damask.ASCIItable(name=File1,readonly=True) - table1.head_read() - len1=len(table1.info)+2 - table2 = damask.ASCIItable(name=File2,readonly=True) - table2.head_read() - len2=len(table2.info)+2 + table = damask.Table.from_ASCII(File1) + len1=len(table.comments)+2 + table = damask.Table.from_ASCII(File2) + len2=len(table.comments)+2 refArray = np.nan_to_num(np.genfromtxt(File1,missing_values='n/a',skip_header = len1,autostrip=True)) curArray = np.nan_to_num(np.genfromtxt(File2,missing_values='n/a',skip_header = len2,autostrip=True)) @@ -445,15 +448,15 @@ class Test(): if not (isinstance(files, Iterable) and not isinstance(files, str)): # check whether list of files is requested files = [str(files)] - tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files] + tables = [damask.Table.from_ASCII(filename) for filename in files] for table in tables: - table.head_read() + table._label_flat() columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files columns = columns[:len(files)] # truncate to same length as files for i,column in enumerate(columns): - if column is None: columns[i] = tables[i].labels(raw = True) # if no column is given, read all + if column is None: columns[i] = list(tables[i].data.columns) # if no column is given, read all logging.info('comparing ASCIItables statistically') for i in range(len(columns)): @@ -467,9 +470,8 @@ class Test(): data = [] for table,labels in zip(tables,columns): - table.data_readArray(labels) - data.append(table.data) - table.close() + table._label_condensed() + data.append(np.hstack(list(table.get(label) for label in labels))) for i in range(1,len(data)): @@ -497,15 +499,13 @@ class Test(): if len(files) < 2: return True # single table is always close to itself... - tables = [damask.ASCIItable(name = filename,readonly = True) for filename in files] - for table in tables: - table.head_read() + tables = [damask.Table.from_ASCII(filename) for filename in files] columns += [columns[0]]*(len(files)-len(columns)) # extend to same length as files columns = columns[:len(files)] # truncate to same length as files for i,column in enumerate(columns): - if column is None: columns[i] = tables[i].labels(raw = False) # if no column is given, use all + if column is None: columns[i] = list(tables[i].shapes.keys()) # if no column is given, use all logging.info('comparing ASCIItables') for i in range(len(columns)): @@ -515,22 +515,20 @@ class Test(): ) logging.info(files[i]+': '+','.join(columns[i])) - dimensions = tables[0].label_dimension(columns[0]) # width of each requested column + dimensions = [np.prod(tables[0].shapes[c]) for c in columns[0]] # width of each requested column maximum = np.zeros_like(columns[0],dtype=float) # one magnitude per column entry data = [] # list of feature table extracted from each file (ASCII table) for i,(table,labels) in enumerate(zip(tables,columns)): - if np.any(dimensions != table.label_dimension(labels)): # check data object consistency + if np.any(dimensions != [np.prod(table.shapes[c]) for c in labels]): # check data object consistency logging.critical('Table {} differs in data layout.'.format(files[i])) return False - table.data_readArray(labels) # read data, ... - data.append(table.data) # ... store, ... - table.close() # ... close + data.append(np.hstack(list(table.get(label) for label in labels)).astype(np.float)) # store for j,label in enumerate(labels): # iterate over object labels maximum[j] = np.maximum( maximum[j], - np.amax(np.linalg.norm(table.data[:,table.label_indexrange(label)], + np.amax(np.linalg.norm(table.get(label), axis=1)) ) # find maximum Euclidean norm across rows @@ -552,8 +550,6 @@ class Test(): 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)): diff --git a/python/damask/ktv.py b/python/damask/_vtk.py similarity index 72% rename from python/damask/ktv.py rename to python/damask/_vtk.py index 19b87efdf..92b4be064 100644 --- a/python/damask/ktv.py +++ b/python/damask/_vtk.py @@ -3,7 +3,8 @@ import os import pandas as pd import numpy as np import vtk -from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk +from vtk.util.numpy_support import numpy_to_vtk as np_to_vtk +from vtk.util.numpy_support import numpy_to_vtkIdTypeArray as np_to_vtkIdTypeArray from . import Table from . import Environment @@ -24,12 +25,13 @@ class VTK: Parameters ---------- geom : subclass of vtk.vtkDataSet - Description of geometry and topology. Valid types are vtk.vtkRectilinearGrid, - vtk.vtkUnstructuredGrid, or vtk.vtkPolyData. + Description of geometry and topology. Valid types are vtk.vtkRectilinearGrid, + vtk.vtkUnstructuredGrid, or vtk.vtkPolyData. """ self.geom = geom + @staticmethod def from_rectilinearGrid(grid,size,origin=np.zeros(3)): """ @@ -40,23 +42,18 @@ class VTK: Parameters ---------- grid : numpy.ndarray of shape (3) of np.dtype = int - Number of cells. + Number of cells. size : numpy.ndarray of shape (3) - Physical length. + Physical length. origin : numpy.ndarray of shape (3), optional - Spatial origin. + Spatial origin. """ - coordArray = [vtk.vtkDoubleArray(),vtk.vtkDoubleArray(),vtk.vtkDoubleArray()] - for dim in [0,1,2]: - coords = np.linspace(origin[dim],origin[dim]+size[dim],grid[dim]+1) - coordArray[dim].SetArray(np_to_vtk(coords),grid[dim]+1,1) - geom = vtk.vtkRectilinearGrid() geom.SetDimensions(*(grid+1)) - geom.SetXCoordinates(coordArray[0]) - geom.SetYCoordinates(coordArray[1]) - geom.SetZCoordinates(coordArray[2]) + geom.SetXCoordinates(np_to_vtk(np.linspace(origin[0],origin[0]+size[0],grid[0]+1),deep=True)) + geom.SetYCoordinates(np_to_vtk(np.linspace(origin[1],origin[1]+size[1],grid[1]+1),deep=True)) + geom.SetZCoordinates(np_to_vtk(np.linspace(origin[2],origin[2]+size[2],grid[2]+1),deep=True)) return VTK(geom) @@ -71,11 +68,11 @@ class VTK: Parameters ---------- nodes : numpy.ndarray of shape (:,3) - Spatial position of the nodes. + Spatial position of the nodes. connectivity : numpy.ndarray of np.dtype = int - Cell connectivity (0-based), first dimension determines #Cells, second dimension determines #Nodes/Cell. + Cell connectivity (0-based), first dimension determines #Cells, second dimension determines #Nodes/Cell. cell_type : str - Name of the vtk.vtkCell subclass. Tested for TRIANGLE, QUAD, and HEXAHEDRON. + Name of the vtk.vtkCell subclass. Tested for TRIANGLE, QUAD, and HEXAHEDRON. """ vtk_nodes = vtk.vtkPoints() @@ -84,7 +81,7 @@ class VTK: cells.SetNumberOfCells(connectivity.shape[0]) T = np.concatenate((np.ones((connectivity.shape[0],1),dtype=np.int64)*connectivity.shape[1], connectivity),axis=1).ravel() - cells.SetCells(connectivity.shape[0],np_to_vtk(T, deep=True, array_type=vtk.VTK_ID_TYPE)) + cells.SetCells(connectivity.shape[0],np_to_vtkIdTypeArray(T,deep=True)) geom = vtk.vtkUnstructuredGrid() geom.SetPoints(vtk_nodes) @@ -103,7 +100,7 @@ class VTK: Parameters ---------- points : numpy.ndarray of shape (:,3) - Spatial position of the points. + Spatial position of the points. """ vtk_points= vtk.vtkPoints() @@ -123,10 +120,10 @@ class VTK: Parameters ---------- fname : str - Filename for reading. Valid extensions are .vtk, .vtr, .vtu, and .vtp. + Filename for reading. Valid extensions are *.vtr, *.vtu, *.vtp, and *.vtk. dataset_type : str, optional - Name of the vtk.vtkDataSet subclass when opening an .vtk file. Valid types are vtkRectilinearGrid, - vtkUnstructuredGrid, and vtkPolyData. + Name of the vtk.vtkDataSet subclass when opening an *.vtk file. Valid types are vtkRectilinearGrid, + vtkUnstructuredGrid, and vtkPolyData. """ ext = os.path.splitext(fname)[1] @@ -134,11 +131,13 @@ class VTK: reader = vtk.vtkGenericDataObjectReader() reader.SetFileName(fname) reader.Update() - if 'rectilineargrid' in dataset_type.lower(): + if dataset_type is None: + raise TypeError('Dataset type for *.vtk file not given.') + elif dataset_type.lower().endswith('rectilineargrid'): geom = reader.GetRectilinearGridOutput() - elif 'unstructuredgrid' in dataset_type.lower(): + elif dataset_type.lower().endswith('unstructuredgrid'): geom = reader.GetUnstructuredGridOutput() - elif 'polydata' in dataset_type.lower(): + elif dataset_type.lower().endswith('polydata'): geom = reader.GetPolyDataOutput() else: raise TypeError('Unknown dataset type for vtk file {}'.format(dataset_type)) @@ -159,7 +158,6 @@ class VTK: return VTK(geom) - # ToDo: If extension is given, check for consistency. def write(self,fname): """ Write to file. @@ -167,7 +165,7 @@ class VTK: Parameters ---------- fname : str - Filename for writing. + Filename for writing. """ if (isinstance(self.geom,vtk.vtkRectilinearGrid)): @@ -177,8 +175,11 @@ class VTK: elif(isinstance(self.geom,vtk.vtkPolyData)): writer = vtk.vtkXMLPolyDataWriter() - writer.SetFileName('{}.{}'.format(os.path.splitext(fname)[0], - writer.GetDefaultFileExtension())) + default_ext = writer.GetDefaultFileExtension() + name, ext = os.path.splitext(fname) + if ext and ext != '.'+default_ext: + raise ValueError('Given extension {} is not .{}'.format(ext,default_ext)) + writer.SetFileName('{}.{}'.format(name,default_ext)) writer.SetCompressorTypeToZLib() writer.SetDataModeToBinary() writer.SetInputData(self.geom) @@ -195,15 +196,19 @@ class VTK: if isinstance(data,np.ndarray): d = np_to_vtk(num_array=data.reshape(data.shape[0],-1),deep=True) + if label is None: + raise ValueError('No label defined for numpy.ndarray') d.SetName(label) if data.shape[0] == N_cells: self.geom.GetCellData().AddArray(d) elif data.shape[0] == N_points: self.geom.GetPointData().AddArray(d) elif isinstance(data,pd.DataFrame): - pass + raise NotImplementedError('pd.DataFrame') elif isinstance(data,Table): - pass + raise NotImplementedError('damask.Table') + else: + raise TypeError def __repr__(self): diff --git a/python/damask/colormaps.py b/python/damask/colormaps.py deleted file mode 100644 index e84d3338b..000000000 --- a/python/damask/colormaps.py +++ /dev/null @@ -1,556 +0,0 @@ -import numpy as np - -class Color(): - """Color representation in and conversion between different color-spaces.""" - - __slots__ = [ - 'model', - 'color', - '__dict__', - ] - - - def __init__(self, - model = 'RGB', - color = np.zeros(3,'d')): - """ - Create a Color object. - - Parameters - ---------- - model : string - color model - color : numpy.ndarray - vector representing the color according to the selected model - - """ - self.__transforms__ = \ - {'HSV': {'index': 0, 'next': self._HSV2HSL}, - 'HSL': {'index': 1, 'next': self._HSL2RGB, 'prev': self._HSL2HSV}, - 'RGB': {'index': 2, 'next': self._RGB2XYZ, 'prev': self._RGB2HSL}, - 'XYZ': {'index': 3, 'next': self._XYZ2CIELAB, 'prev': self._XYZ2RGB}, - 'CIELAB': {'index': 4, 'next': self._CIELAB2MSH, 'prev': self._CIELAB2XYZ}, - 'MSH': {'index': 5, 'prev': self._MSH2CIELAB}, - } - - model = model.upper() - if model not in list(self.__transforms__.keys()): model = 'RGB' - if model == 'RGB' and max(color) > 1.0: # are we RGB255 ? - for i in range(3): - color[i] /= 255.0 # rescale to RGB - - if model == 'HSL': # are we HSL ? - if abs(color[0]) > 1.0: color[0] /= 360.0 # with angular hue? - while color[0] >= 1.0: color[0] -= 1.0 # rewind to proper range - while color[0] < 0.0: color[0] += 1.0 # rewind to proper range - - self.model = model - self.color = np.array(color,'d') - - - def __repr__(self): - """Color model and values.""" - return 'Model: %s Color: %s'%(self.model,str(self.color)) - - - def __str__(self): - """Color model and values.""" - return self.__repr__() - - - def convert_to(self,toModel = 'RGB'): - """ - Change the color model permanently. - - Parameters - ---------- - toModel : string - color model - - """ - toModel = toModel.upper() - if toModel not in list(self.__transforms__.keys()): return - - sourcePos = self.__transforms__[self.model]['index'] - targetPos = self.__transforms__[toModel]['index'] - - while sourcePos < targetPos: - self.__transforms__[self.model]['next']() - sourcePos += 1 - - while sourcePos > targetPos: - self.__transforms__[self.model]['prev']() - sourcePos -= 1 - return self - - - def express_as(self,asModel = 'RGB'): - """ - Return the color in a different model. - - Parameters - ---------- - asModel : string - color model - - """ - return self.__class__(self.model,self.color).convert_to(asModel) - - - - def _HSV2HSL(self): - """ - Convert H(ue) S(aturation) V(alue or brightness) to H(ue) S(aturation) L(uminance). - - All values are in the range [0,1] - http://codeitdown.com/hsl-hsb-hsv-color - """ - if self.model != 'HSV': return - - converted = Color('HSL',np.array([ - self.color[0], - 1. if self.color[2] == 0.0 or (self.color[1] == 0.0 and self.color[2] == 1.0) \ - else self.color[1]*self.color[2]/(1.-abs(self.color[2]*(2.-self.color[1])-1.)), - 0.5*self.color[2]*(2.-self.color[1]), - ])) - - self.model = converted.model - self.color = converted.color - - - def _HSL2HSV(self): - """ - Convert H(ue) S(aturation) L(uminance) to H(ue) S(aturation) V(alue or brightness). - - All values are in the range [0,1] - http://codeitdown.com/hsl-hsb-hsv-color - """ - if self.model != 'HSL': return - - h = self.color[0] - b = self.color[2]+0.5*(self.color[1]*(1.-abs(2*self.color[2]-1))) - s = 1.0 if b == 0.0 else 2.*(b-self.color[2])/b - - converted = Color('HSV',np.array([h,s,b])) - - self.model = converted.model - self.color = converted.color - - - def _HSL2RGB(self): - """ - Convert H(ue) S(aturation) L(uminance) to R(red) G(reen) B(lue). - - All values are in the range [0,1] - from http://en.wikipedia.org/wiki/HSL_and_HSV - """ - if self.model != 'HSL': return - - sextant = self.color[0]*6.0 - c = (1.0 - abs(2.0 * self.color[2] - 1.0))*self.color[1] - x = c*(1.0 - abs(sextant%2 - 1.0)) - m = self.color[2] - 0.5*c - - converted = Color('RGB',np.array([ - [c+m, x+m, m], - [x+m, c+m, m], - [m, c+m, x+m], - [m, x+m, c+m], - [x+m, m, c+m], - [c+m, m, x+m], - ][int(sextant)],'d')) - self.model = converted.model - self.color = converted.color - - - def _RGB2HSL(self): - """ - Convert R(ed) G(reen) B(lue) to H(ue) S(aturation) L(uminance). - - All values are in the range [0,1] - from http://130.113.54.154/~monger/hsl-rgb.html - """ - if self.model != 'RGB': return - - HSL = np.zeros(3,'d') - maxcolor = self.color.max() - mincolor = self.color.min() - HSL[2] = (maxcolor + mincolor)/2.0 - if(mincolor == maxcolor): - HSL[0] = 0.0 - HSL[1] = 0.0 - else: - if (HSL[2]<0.5): - HSL[1] = (maxcolor - mincolor)/(maxcolor + mincolor) - else: - HSL[1] = (maxcolor - mincolor)/(2.0 - maxcolor - mincolor) - if (maxcolor == self.color[0]): - HSL[0] = 0.0 + (self.color[1] - self.color[2])/(maxcolor - mincolor) - elif (maxcolor == self.color[1]): - HSL[0] = 2.0 + (self.color[2] - self.color[0])/(maxcolor - mincolor) - elif (maxcolor == self.color[2]): - HSL[0] = 4.0 + (self.color[0] - self.color[1])/(maxcolor - mincolor) - HSL[0] = HSL[0]*60.0 # scaling to 360 might be dangerous for small values - if (HSL[0] < 0.0): - HSL[0] = HSL[0] + 360.0 - for i in range(2): - HSL[i+1] = min(HSL[i+1],1.0) - HSL[i+1] = max(HSL[i+1],0.0) - - converted = Color('HSL', HSL) - self.model = converted.model - self.color = converted.color - - - - def _RGB2XYZ(self): - """ - Convert R(ed) G(reen) B(lue) to CIE XYZ. - - All values are in the range [0,1] - from http://www.cs.rit.edu/~ncs/color/t_convert.html - """ - if self.model != 'RGB': return - - XYZ = np.zeros(3,'d') - RGB_lin = np.zeros(3,'d') - convert = np.array([[0.412453,0.357580,0.180423], - [0.212671,0.715160,0.072169], - [0.019334,0.119193,0.950227]]) - - for i in range(3): - if (self.color[i] > 0.04045): RGB_lin[i] = ((self.color[i]+0.0555)/1.0555)**2.4 - else: RGB_lin[i] = self.color[i] /12.92 - XYZ = np.dot(convert,RGB_lin) - for i in range(3): - - XYZ[i] = max(XYZ[i],0.0) - - converted = Color('XYZ', XYZ) - self.model = converted.model - self.color = converted.color - - - - def _XYZ2RGB(self): - """ - Convert CIE XYZ to R(ed) G(reen) B(lue). - - All values are in the range [0,1] - from http://www.cs.rit.edu/~ncs/color/t_convert.html - """ - if self.model != 'XYZ': - return - - convert = np.array([[ 3.240479,-1.537150,-0.498535], - [-0.969256, 1.875992, 0.041556], - [ 0.055648,-0.204043, 1.057311]]) - RGB_lin = np.dot(convert,self.color) - RGB = np.zeros(3,'d') - - for i in range(3): - if (RGB_lin[i] > 0.0031308): RGB[i] = ((RGB_lin[i])**(1.0/2.4))*1.0555-0.0555 - else: RGB[i] = RGB_lin[i] *12.92 - for i in range(3): - RGB[i] = min(RGB[i],1.0) - RGB[i] = max(RGB[i],0.0) - - maxVal = max(RGB) # clipping colors according to the display gamut - if (maxVal > 1.0): RGB /= maxVal - - converted = Color('RGB', RGB) - self.model = converted.model - self.color = converted.color - - - - def _CIELAB2XYZ(self): - """ - Convert CIE Lab to CIE XYZ. - - All values are in the range [0,1] - from http://www.easyrgb.com/index.php?X=MATH&H=07#text7 - """ - if self.model != 'CIELAB': return - - ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 - XYZ = np.zeros(3,'d') - - XYZ[1] = (self.color[0] + 16.0 ) / 116.0 - XYZ[0] = XYZ[1] + self.color[1]/ 500.0 - XYZ[2] = XYZ[1] - self.color[2]/ 200.0 - - for i in range(len(XYZ)): - if (XYZ[i] > 6./29. ): XYZ[i] = XYZ[i]**3. - else: XYZ[i] = 108./841. * (XYZ[i] - 4./29.) - - converted = Color('XYZ', XYZ*ref_white) - self.model = converted.model - self.color = converted.color - - - def _XYZ2CIELAB(self): - """ - Convert CIE XYZ to CIE Lab. - - All values are in the range [0,1] - from http://en.wikipedia.org/wiki/Lab_color_space, - http://www.cs.rit.edu/~ncs/color/t_convert.html - """ - if self.model != 'XYZ': return - - ref_white = np.array([.95047, 1.00000, 1.08883],'d') # Observer = 2, Illuminant = D65 - XYZ = self.color/ref_white - - for i in range(len(XYZ)): - if (XYZ[i] > 216./24389 ): XYZ[i] = XYZ[i]**(1.0/3.0) - else: XYZ[i] = (841./108. * XYZ[i]) + 16.0/116.0 - - converted = Color('CIELAB', np.array([ 116.0 * XYZ[1] - 16.0, - 500.0 * (XYZ[0] - XYZ[1]), - 200.0 * (XYZ[1] - XYZ[2]) ])) - self.model = converted.model - self.color = converted.color - - - def _CIELAB2MSH(self): - """ - Convert CIE Lab to Msh colorspace. - - from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls - """ - if self.model != 'CIELAB': return - - Msh = np.zeros(3,'d') - Msh[0] = np.sqrt(np.dot(self.color,self.color)) - if (Msh[0] > 0.001): - Msh[1] = np.arccos(self.color[0]/Msh[0]) - if (self.color[1] != 0.0): - Msh[2] = np.arctan2(self.color[2],self.color[1]) - - converted = Color('MSH', Msh) - self.model = converted.model - self.color = converted.color - - - def _MSH2CIELAB(self): - """ - Convert Msh colorspace to CIE Lab. - - with s,h in radians - from http://www.cs.unm.edu/~kmorel/documents/ColorMaps/DivergingColorMapWorkshop.xls - """ - if self.model != 'MSH': return - - Lab = np.zeros(3,'d') - Lab[0] = self.color[0] * np.cos(self.color[1]) - Lab[1] = self.color[0] * np.sin(self.color[1]) * np.cos(self.color[2]) - Lab[2] = self.color[0] * np.sin(self.color[1]) * np.sin(self.color[2]) - - converted = Color('CIELAB', Lab) - self.model = converted.model - self.color = converted.color - - -class Colormap(): - """Perceptually uniform diverging or sequential colormap.""" - - __slots__ = [ - 'left', - 'right', - 'interpolate', - ] - __predefined__ = { - 'gray': {'left': Color('HSL',[0,1,1]), - 'right': Color('HSL',[0,0,0.15]), - 'interpolate': 'perceptualuniform'}, - 'grey': {'left': Color('HSL',[0,1,1]), - 'right': Color('HSL',[0,0,0.15]), - 'interpolate': 'perceptualuniform'}, - 'red': {'left': Color('HSL',[0,1,0.14]), - 'right': Color('HSL',[0,0.35,0.91]), - 'interpolate': 'perceptualuniform'}, - 'green': {'left': Color('HSL',[0.33333,1,0.14]), - 'right': Color('HSL',[0.33333,0.35,0.91]), - 'interpolate': 'perceptualuniform'}, - 'blue': {'left': Color('HSL',[0.66,1,0.14]), - 'right': Color('HSL',[0.66,0.35,0.91]), - 'interpolate': 'perceptualuniform'}, - 'seaweed': {'left': Color('HSL',[0.78,1.0,0.1]), - 'right': Color('HSL',[0.40000,0.1,0.9]), - 'interpolate': 'perceptualuniform'}, - 'bluebrown': {'left': Color('HSL',[0.65,0.53,0.49]), - 'right': Color('HSL',[0.11,0.75,0.38]), - 'interpolate': 'perceptualuniform'}, - 'redgreen': {'left': Color('HSL',[0.97,0.96,0.36]), - 'right': Color('HSL',[0.33333,1.0,0.14]), - 'interpolate': 'perceptualuniform'}, - 'bluered': {'left': Color('HSL',[0.65,0.53,0.49]), - 'right': Color('HSL',[0.97,0.96,0.36]), - 'interpolate': 'perceptualuniform'}, - 'blueredrainbow':{'left': Color('HSL',[2.0/3.0,1,0.5]), - 'right': Color('HSL',[0,1,0.5]), - 'interpolate': 'linear' }, - 'orientation': {'left': Color('RGB',[0.933334,0.878432,0.878431]), - 'right': Color('RGB',[0.250980,0.007843,0.000000]), - 'interpolate': 'perceptualuniform'}, - 'strain': {'left': Color('RGB',[0.941177,0.941177,0.870588]), - 'right': Color('RGB',[0.266667,0.266667,0.000000]), - 'interpolate': 'perceptualuniform'}, - 'stress': {'left': Color('RGB',[0.878432,0.874511,0.949019]), - 'right': Color('RGB',[0.000002,0.000000,0.286275]), - 'interpolate': 'perceptualuniform'}, - } - - -# ------------------------------------------------------------------ - def __init__(self, - left = Color('RGB',[1,1,1]), - right = Color('RGB',[0,0,0]), - interpolate = 'perceptualuniform', - predefined = None - ): - """ - Create a Colormap object. - - Parameters - ---------- - left : Color - left color (minimum value) - right : Color - right color (maximum value) - interpolate : str - interpolation scheme (either 'perceptualuniform' or 'linear') - predefined : bool - ignore other arguments and use predefined definition - - """ - if predefined is not None: - left = self.__predefined__[predefined.lower()]['left'] - right= self.__predefined__[predefined.lower()]['right'] - interpolate = self.__predefined__[predefined.lower()]['interpolate'] - - if left.__class__.__name__ != 'Color': - left = Color() - if right.__class__.__name__ != 'Color': - right = Color() - - self.left = left - self.right = right - self.interpolate = interpolate - - -# ------------------------------------------------------------------ - def __repr__(self): - """Left and right value of colormap.""" - return 'Left: %s Right: %s'%(self.left,self.right) - - -# ------------------------------------------------------------------ - def invert(self): - """Switch left/minimum with right/maximum.""" - (self.left, self.right) = (self.right, self.left) - return self - - -# ------------------------------------------------------------------ - def show_predefined(self): - """Show the labels of the predefined colormaps.""" - print('\n'.join(self.__predefined__.keys())) - -# ------------------------------------------------------------------ - def color(self,fraction = 0.5): - - def interpolate_Msh(lo, hi, frac): - - def rad_diff(a,b): - return abs(a[2]-b[2]) -# if saturation of one of the two colors is too less than the other, hue of the less - def adjust_hue(Msh_sat, Msh_unsat): - if Msh_sat[0] >= Msh_unsat[0]: - return Msh_sat[2] - else: - hSpin = Msh_sat[1]/np.sin(Msh_sat[1])*np.sqrt(Msh_unsat[0]**2.0-Msh_sat[0]**2)/Msh_sat[0] - if Msh_sat[2] < - np.pi/3.0: hSpin *= -1.0 - return Msh_sat[2] + hSpin - - Msh1 = np.array(lo[:]) - Msh2 = np.array(hi[:]) - - if (Msh1[1] > 0.05 and Msh2[1] > 0.05 and rad_diff(Msh1,Msh2) > np.pi/3.0): - M_mid = max(Msh1[0],Msh2[0],88.0) - if frac < 0.5: - Msh2 = np.array([M_mid,0.0,0.0],'d') - frac *= 2.0 - else: - Msh1 = np.array([M_mid,0.0,0.0],'d') - frac = 2.0*frac - 1.0 - if Msh1[1] < 0.05 and Msh2[1] > 0.05: Msh1[2] = adjust_hue(Msh2,Msh1) - elif Msh1[1] > 0.05 and Msh2[1] < 0.05: Msh2[2] = adjust_hue(Msh1,Msh2) - Msh = (1.0 - frac) * Msh1 + frac * Msh2 - - return Color('MSH',Msh) - - def interpolate_linear(lo, hi, frac): - """Linear interpolation between lo and hi color at given fraction; output in model of lo color.""" - interpolation = (1.0 - frac) * np.array(lo.color[:]) \ - + frac * np.array(hi.express_as(lo.model).color[:]) - - return Color(lo.model,interpolation) - - if self.interpolate == 'perceptualuniform': - return interpolate_Msh(self.left.express_as('MSH').color, - self.right.express_as('MSH').color,fraction) - elif self.interpolate == 'linear': - return interpolate_linear(self.left, - self.right,fraction) - else: - raise NameError('unknown color interpolation method') - -# ------------------------------------------------------------------ - def export(self,name = 'uniformPerceptualColorMap',\ - format = 'paraview',\ - steps = 2,\ - crop = [-1.0,1.0], - model = 'RGB'): - """ - [RGB] colormap for use in paraview or gmsh, or as raw string, or array. - - Arguments: name, format, steps, crop. - Format is one of (paraview, gmsh, raw, list). - Crop selects a (sub)range in [-1.0,1.0]. - Generates sequential map if one limiting color is either white or black, - diverging map otherwise. - """ - format = format.lower() # consistent comparison basis - frac = 0.5*(np.array(crop) + 1.0) # rescale crop range to fractions - colors = [self.color(float(i)/(steps-1)*(frac[1]-frac[0])+frac[0]).express_as(model).color for i in range(steps)] - if format == 'paraview': - colormap = ['[\n {{\n "ColorSpace": "RGB", "Name": "{}", "DefaultMap": true,\n "RGBPoints" : ['.format(name)] \ - + [' {:4d},{:8.6f},{:8.6f},{:8.6f},'.format(i,color[0],color[1],color[2],) \ - for i,color in enumerate(colors[:-1])] \ - + [' {:4d},{:8.6f},{:8.6f},{:8.6f} '.format(len(colors),colors[-1][0],colors[-1][1],colors[-1][2],)] \ - + [' ]\n }\n]'] - - elif format == 'gmsh': - colormap = ['View.ColorTable = {'] \ - + [',\n'.join(['{%s}'%(','.join([str(x*255.0) for x in color])) for color in colors])] \ - + ['}'] - - elif format == 'gom': - colormap = ['1 1 ' + str(name) - + ' 9 ' + str(name) - + ' 0 1 0 3 0 0 -1 9 \\ 0 0 0 255 255 255 0 0 255 ' - + '30 NO_UNIT 1 1 64 64 64 255 1 0 0 0 0 0 0 3 0 ' + str(len(colors)) - + ' '.join([' 0 %s 255 1'%(' '.join([str(int(x*255.0)) for x in color])) for color in reversed(colors)])] - - elif format == 'raw': - colormap = ['\t'.join(map(str,color)) for color in colors] - - elif format == 'list': - colormap = colors - - else: - raise NameError('unknown color export format') - - return '\n'.join(colormap) + '\n' if type(colormap[0]) is str else colormap diff --git a/python/damask/config/__init__.py b/python/damask/config/__init__.py index f3635d2a9..f5c57a879 100644 --- a/python/damask/config/__init__.py +++ b/python/damask/config/__init__.py @@ -1,5 +1,3 @@ -# -*- coding: UTF-8 no BOM -*- - -"""Aggregator for configuration file handling""" +"""Aggregator for configuration file handling.""" from .material import Material # noqa diff --git a/python/damask/config/material.py b/python/damask/config/material.py index 408338313..a30db1242 100644 --- a/python/damask/config/material.py +++ b/python/damask/config/material.py @@ -1,11 +1,10 @@ -# -*- coding: UTF-8 no BOM -*- - import re import os class Section(): def __init__(self,data = {'__order__':[]},part = ''): + """New material.config section.""" classes = { 'homogenization':Homogenization, 'microstructure':Microstructure, @@ -35,26 +34,31 @@ class Section(): class Homogenization(Section): def __init__(self,data = {'__order__':[]}): + """New material.config section.""" Section.__init__(self,data) class Crystallite(Section): def __init__(self,data = {'__order__':[]}): + """New material.config section.""" Section.__init__(self,data) class Phase(Section): def __init__(self,data = {'__order__':[]}): + """New material.config section.""" Section.__init__(self,data) class Microstructure(Section): def __init__(self,data = {'__order__':[]}): + """New material.config section.""" Section.__init__(self,data) class Texture(Section): def __init__(self,data = {'__order__':[]}): + """New material.config section.""" Section.__init__(self,data) def add_component(self,theType,properties): @@ -79,10 +83,10 @@ class Texture(Section): class Material(): - """Reads, manipulates and writes material.config files""" + """Read, manipulate, and write material.config files.""" def __init__(self,verbose=True): - """Generates ordered list of parts""" + """Generates ordered list of parts.""" self.parts = [ 'homogenization', 'crystallite', @@ -100,7 +104,7 @@ class Material(): self.verbose = verbose def __repr__(self): - """Returns current data structure in material.config format""" + """Returns current data structure in material.config format.""" me = [] for part in self.parts: if self.verbose: print('processing <{}>'.format(part)) @@ -158,9 +162,9 @@ class Material(): def read(self,filename=None): - """Reads material.config file""" + """Read material.config file.""" def recursiveRead(filename): - """Takes care of include statements like '{}'""" + """Takes care of include statements like '{}'.""" result = [] re_include = re.compile(r'^{(.+)}$') with open(filename) as f: lines = f.readlines() @@ -176,7 +180,7 @@ class Material(): self.parse(part=p, content=c) def write(self,filename='material.config', overwrite=False): - """Writes to material.config""" + """Write to material.config.""" i = 0 outname = filename while os.path.exists(outname) and not overwrite: @@ -189,7 +193,7 @@ class Material(): return outname def add_section(self, part=None, section=None, initialData=None, merge=False): - """adding/updating""" + """Add Update.""" part = part.lower() section = section.lower() if part not in self.parts: raise Exception('invalid part {}'.format(part)) diff --git a/python/damask/grid_filters.py b/python/damask/grid_filters.py index 1375b4408..c454e3d00 100644 --- a/python/damask/grid_filters.py +++ b/python/damask/grid_filters.py @@ -98,17 +98,12 @@ def cell_coord0(grid,size,origin=np.zeros(3)): 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]. + physical origin of the periodic field. Defaults to [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) + start = origin + size/grid*.5 + end = origin + size - size/grid*.5 + return np.mgrid[start[0]:end[0]:grid[0]*1j,start[1]:end[1]:grid[1]*1j,start[2]:end[2]:grid[2]*1j].T def cell_displacement_fluct(size,F): @@ -180,7 +175,7 @@ def cell_coord(size,F,origin=np.zeros(3)): F : numpy.ndarray deformation gradient field. origin : numpy.ndarray, optional - physical origin of the periodic field. Default is [0.0,0.0,0.0]. + physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. """ return cell_coord0(F.shape[:3][::-1],size,origin) + cell_displacement(size,F) @@ -251,15 +246,12 @@ def node_coord0(grid,size,origin=np.zeros(3)): 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]. + physical origin of the periodic field. Defaults to [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) + return np.mgrid[origin[0]:size[0]+origin[0]:(grid[0]+1)*1j, + origin[1]:size[1]+origin[1]:(grid[1]+1)*1j, + origin[2]:size[2]+origin[2]:(grid[2]+1)*1j].T def node_displacement_fluct(size,F): @@ -319,7 +311,7 @@ def node_coord(size,F,origin=np.zeros(3)): F : numpy.ndarray deformation gradient field. origin : numpy.ndarray, optional - physical origin of the periodic field. Default is [0.0,0.0,0.0]. + physical origin of the periodic field. Defaults to [0.0,0.0,0.0]. """ return node_coord0(F.shape[:3][::-1],size,origin) + node_displacement(size,F) @@ -399,5 +391,5 @@ def regrid(size,F,new_grid): 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) + tree = spatial.cKDTree(c.reshape(-1,3),boxsize=outer) return tree.query(cell_coord0(new_grid,outer))[1].flatten() diff --git a/python/damask/mechanics.py b/python/damask/mechanics.py index 29c405b7d..674ff9c5a 100644 --- a/python/damask/mechanics.py +++ b/python/damask/mechanics.py @@ -8,10 +8,10 @@ def Cauchy(P,F): Parameters ---------- - F : numpy.array of shape (:,3,3) or (3,3) - Deformation gradient. - P : numpy.array of shape (:,3,3) or (3,3) - 1. Piola-Kirchhoff stress. + F : numpy.ndarray of shape (:,3,3) or (3,3) + Deformation gradient. + P : numpy.ndarray of shape (:,3,3) or (3,3) + First Piola-Kirchhoff stress. """ if np.shape(F) == np.shape(P) == (3,3): @@ -27,8 +27,8 @@ def deviatoric_part(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the deviatoric part is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the deviatoric part is computed. """ return T - np.eye(3)*spherical_part(T) if np.shape(T) == (3,3) else \ @@ -44,8 +44,8 @@ def eigenvalues(T_sym): Parameters ---------- - T_sym : numpy.array of shape (:,3,3) or (3,3) - Symmetric tensor of which the eigenvalues are computed. + T_sym : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric tensor of which the eigenvalues are computed. """ return np.linalg.eigvalsh(symmetric(T_sym)) @@ -59,10 +59,10 @@ def eigenvectors(T_sym,RHS=False): Parameters ---------- - T_sym : numpy.array of shape (:,3,3) or (3,3) - Symmetric tensor of which the eigenvectors are computed. + T_sym : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric tensor of which the eigenvectors are computed. RHS: bool, optional - Enforce right-handed coordinate system. Default is False. + Enforce right-handed coordinate system. Default is False. """ (u,v) = np.linalg.eigh(symmetric(T_sym)) @@ -81,11 +81,11 @@ def left_stretch(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the left stretch is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the left stretch is computed. """ - return __polar_decomposition(T,'V')[0] + return _polar_decomposition(T,'V')[0] def maximum_shear(T_sym): @@ -94,8 +94,8 @@ def maximum_shear(T_sym): Parameters ---------- - T_sym : numpy.array of shape (:,3,3) or (3,3) - Symmetric tensor of which the maximum shear is computed. + T_sym : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric tensor of which the maximum shear is computed. """ w = eigenvalues(T_sym) @@ -109,11 +109,11 @@ def Mises_strain(epsilon): Parameters ---------- - epsilon : numpy.array of shape (:,3,3) or (3,3) - Symmetric strain tensor of which the von Mises equivalent is computed. + epsilon : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric strain tensor of which the von Mises equivalent is computed. """ - return __Mises(epsilon,2.0/3.0) + return _Mises(epsilon,2.0/3.0) def Mises_stress(sigma): @@ -122,11 +122,11 @@ def Mises_stress(sigma): Parameters ---------- - sigma : numpy.array of shape (:,3,3) or (3,3) - Symmetric stress tensor of which the von Mises equivalent is computed. + sigma : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric stress tensor of which the von Mises equivalent is computed. """ - return __Mises(sigma,3.0/2.0) + return _Mises(sigma,3.0/2.0) def PK2(P,F): @@ -135,10 +135,10 @@ def PK2(P,F): Parameters ---------- - P : numpy.array of shape (:,3,3) or (3,3) - 1. Piola-Kirchhoff stress. - F : numpy.array of shape (:,3,3) or (3,3) - Deformation gradient. + P : numpy.ndarray of shape (:,3,3) or (3,3) + First Piola-Kirchhoff stress. + F : numpy.ndarray of shape (:,3,3) or (3,3) + Deformation gradient. """ if np.shape(F) == np.shape(P) == (3,3): @@ -154,11 +154,11 @@ def right_stretch(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the right stretch is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the right stretch is computed. """ - return __polar_decomposition(T,'U')[0] + return _polar_decomposition(T,'U')[0] def rotational_part(T): @@ -167,11 +167,11 @@ def rotational_part(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the rotational part is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the rotational part is computed. """ - return __polar_decomposition(T,'R')[0] + return _polar_decomposition(T,'R')[0] def spherical_part(T,tensor=False): @@ -180,10 +180,10 @@ def spherical_part(T,tensor=False): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the hydrostatic part is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the hydrostatic part is computed. tensor : bool, optional - Map spherical part onto identity tensor. Default is false + Map spherical part onto identity tensor. Default is false """ if T.shape == (3,3): @@ -206,15 +206,15 @@ def strain_tensor(F,t,m): Parameters ---------- - F : numpy.array of shape (:,3,3) or (3,3) - Deformation gradient. + F : numpy.ndarray of shape (:,3,3) or (3,3) + Deformation gradient. t : {‘V’, ‘U’} - Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + Type of the polar decomposition, ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. m : float - Order of the strain. + Order of the strain. """ - F_ = F.reshape((1,3,3)) if F.shape == (3,3) else F + F_ = F.reshape(1,3,3) if F.shape == (3,3) else F if t == 'V': B = np.matmul(F_,transpose(F_)) w,n = np.linalg.eigh(B) @@ -231,7 +231,7 @@ def strain_tensor(F,t,m): else: eps = np.matmul(n,np.einsum('ij,ikj->ijk',0.5*np.log(w),n)) - return eps.reshape((3,3)) if np.shape(F) == (3,3) else \ + return eps.reshape(3,3) if np.shape(F) == (3,3) else \ eps @@ -241,8 +241,8 @@ def symmetric(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the symmetrized values are computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the symmetrized values are computed. """ return (T+transpose(T))*0.5 @@ -254,25 +254,25 @@ def transpose(T): Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the transpose is computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the transpose is computed. """ return T.T if np.shape(T) == (3,3) else \ np.transpose(T,(0,2,1)) -def __polar_decomposition(T,requested): +def _polar_decomposition(T,requested): """ Singular value decomposition. Parameters ---------- - T : numpy.array of shape (:,3,3) or (3,3) - Tensor of which the singular values are computed. + T : numpy.ndarray of shape (:,3,3) or (3,3) + Tensor of which the singular values are computed. requested : iterable of str - Requested outputs: ‘R’ for the rotation tensor, - ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. + Requested outputs: ‘R’ for the rotation tensor, + ‘V’ for left stretch tensor and ‘U’ for right stretch tensor. """ u, s, vh = np.linalg.svd(T) @@ -290,16 +290,16 @@ def __polar_decomposition(T,requested): return tuple(output) -def __Mises(T_sym,s): +def _Mises(T_sym,s): """ Base equation for Mises equivalent of a stres or strain tensor. Parameters ---------- - T_sym : numpy.array of shape (:,3,3) or (3,3) - Symmetric tensor of which the von Mises equivalent is computed. + T_sym : numpy.ndarray of shape (:,3,3) or (3,3) + Symmetric tensor of which the von Mises equivalent is computed. s : float - Scaling factor (2/3 for strain, 3/2 for stress). + Scaling factor (2/3 for strain, 3/2 for stress). """ d = deviatoric_part(T_sym) diff --git a/python/damask/solver/__init__.py b/python/damask/solver/__init__.py index a1939eb55..298adb1f7 100644 --- a/python/damask/solver/__init__.py +++ b/python/damask/solver/__init__.py @@ -1,4 +1,3 @@ """Tools to control the various solvers.""" -from .solver import Solver # noqa -from .marc import Marc # noqa +from ._marc import Marc # noqa diff --git a/python/damask/solver/marc.py b/python/damask/solver/_marc.py similarity index 88% rename from python/damask/solver/marc.py rename to python/damask/solver/_marc.py index f7dda9c37..22e9842f5 100644 --- a/python/damask/solver/marc.py +++ b/python/damask/solver/_marc.py @@ -3,16 +3,15 @@ import subprocess import shlex import string -from .solver import Solver -import damask +from .._environment import Environment -class Marc(Solver): +class Marc: """Wrapper to run DAMASK with MSCMarc.""" - def __init__(self,version=damask.Environment().options['MARC_VERSION']): + def __init__(self,version=Environment().options['MARC_VERSION']): """ Create a Marc solver object. - + Parameters ---------- version : float @@ -29,7 +28,7 @@ class Marc(Solver): #-------------------------- def libraryPath(self): - path_MSC = damask.Environment().options['MSC_ROOT'] + path_MSC = Environment().options['MSC_ROOT'] path_lib = '{}/mentat{}/shlib/linux64'.format(path_MSC,self.version) return path_lib if os.path.exists(path_lib) else '' @@ -38,7 +37,7 @@ class Marc(Solver): #-------------------------- def toolsPath(self): - path_MSC = damask.Environment().options['MSC_ROOT'] + path_MSC = Environment().options['MSC_ROOT'] path_tools = '{}/marc{}/tools'.format(path_MSC,self.version) return path_tools if os.path.exists(path_tools) else '' @@ -54,15 +53,15 @@ class Marc(Solver): ): - damaskEnv = damask.Environment() - + damaskEnv = Environment() + user = os.path.join(damaskEnv.relPath('src'),'DAMASK_marc{}.{}'.format(self.version,'f90' if compile else 'marc')) if not os.path.isfile(user): raise FileNotFoundError("DAMASK4Marc ({}) '{}' not found".format(('source' if compile else 'binary'),user)) # Define options [see Marc Installation and Operation Guide, pp 23] script = 'run_damask_{}mp'.format(optimization) - + cmd = os.path.join(self.toolsPath(),script) + \ ' -jid ' + model + '_' + job + \ ' -nprocd 1 -autorst 0 -ci n -cr n -dcoup 0 -b no -v no' @@ -76,7 +75,7 @@ class Marc(Solver): process = subprocess.Popen(shlex.split(cmd),stdout = log,stderr = subprocess.STDOUT) log.close() process.wait() - + #-------------------------- def exit_number_from_outFile(self,outFile=None): exitnumber = -1 diff --git a/python/damask/solver/solver.py b/python/damask/solver/solver.py deleted file mode 100644 index c1ca7ff69..000000000 --- a/python/damask/solver/solver.py +++ /dev/null @@ -1,6 +0,0 @@ -class Solver(): - """ - General class for solver specific functionality. - - Sub-classed by the individual solvers. - """ diff --git a/python/damask/util.py b/python/damask/util.py index 4f5e3ec98..273da8c1e 100644 --- a/python/damask/util.py +++ b/python/damask/util.py @@ -47,9 +47,9 @@ def srepr(arg,glue = '\n'): Parameters ---------- arg : iterable - Items to join. + Items to join. glue : str, optional - Defaults to \n. + Defaults to \n. """ if (not hasattr(arg, "strip") and @@ -66,12 +66,12 @@ def croak(what, newline = True): Parameters ---------- what : str or iterable - Content to be displayed + Content to be displayed. newline : bool, optional - Separate items of what by newline. Defaults to True. + Separate items of what by newline. Defaults to True. """ - if not what: + if what is not None: sys.stderr.write(srepr(what,glue = '\n') + ('\n' if newline else '')) sys.stderr.flush() @@ -117,13 +117,13 @@ def execute(cmd, Parameters ---------- cmd : str - Command to be executed. + Command to be executed. streanIn :, optional - Input (via pipe) for executed process. + Input (via pipe) for executed process. wd : str, optional - Working directory of process. Defaults to ./ . - env : - Environment + Working directory of process. Defaults to ./ . + env : dict, optional + Environment for execution. """ initialPath = os.getcwd() @@ -140,7 +140,7 @@ def execute(cmd, error = error.decode('utf-8').replace('\x08','') os.chdir(initialPath) if process.returncode != 0: - raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) + raise RuntimeError('{} failed with returncode {}'.format(cmd,process.returncode)) return out,error @@ -158,11 +158,11 @@ class extendableOption(Option): ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) def take_action(self, action, dest, opt, value, values, parser): - if action == "extend": - lvalue = value.split(",") - values.ensure_value(dest, []).extend(lvalue) - else: - Option.take_action(self, action, dest, opt, value, values, parser) + if action == "extend": + lvalue = value.split(",") + values.ensure_value(dest, []).extend(lvalue) + else: + Option.take_action(self, action, dest, opt, value, values, parser) class _ProgressBar: @@ -179,11 +179,11 @@ class _ProgressBar: Parameters ---------- total : int - Total # of iterations. + Total # of iterations. prefix : str - Prefix string. + Prefix string. bar_length : int - Character length of bar. + Character length of bar. """ self.total = total @@ -224,13 +224,13 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50): Parameters ---------- iterable : iterable/function with yield statement - Iterable (or function with yield statement) to be decorated. + Iterable (or function with yield statement) to be decorated. N_iter : int - Total # of iterations. Needed if number of iterations can not be obtained as len(iterable). + Total # of iterations. Needed if number of iterations can not be obtained as len(iterable). prefix : str, optional. - Prefix string. + Prefix string. bar_length : int, optional - Character length of bar. Defaults to 50. + Character length of bar. Defaults to 50. """ status = _ProgressBar(N_iter if N_iter else len(iterable),prefix,bar_length) @@ -238,7 +238,7 @@ def show_progress(iterable,N_iter=None,prefix='',bar_length=50): for i,item in enumerate(iterable): yield item status.update(i) - + def scale_to_coprime(v): """Scale vector to co-prime (relatively prime) integers.""" @@ -258,7 +258,7 @@ def scale_to_coprime(v): return m//reduce(np.gcd,m) -class return_message(): +class return_message: """Object with formatted return message.""" def __init__(self,message): @@ -268,7 +268,7 @@ class return_message(): Parameters ---------- message : str or list of str - message for output to screen + message for output to screen """ self.message = message diff --git a/python/tests/test_Geom.py b/python/tests/test_Geom.py index bc3a3e751..a6fd57cb6 100644 --- a/python/tests/test_Geom.py +++ b/python/tests/test_Geom.py @@ -18,7 +18,7 @@ def default(): x=np.concatenate((np.ones(40,dtype=int), np.arange(2,42), np.ones(40,dtype=int)*2, - np.arange(1,41))).reshape((8,5,4)) + np.arange(1,41))).reshape(8,5,4) return Geom(x,[8e-6,5e-6,4e-6]) @pytest.fixture diff --git a/python/tests/test_Result.py b/python/tests/test_Result.py index 33c1e2842..a90430096 100644 --- a/python/tests/test_Result.py +++ b/python/tests/test_Result.py @@ -27,7 +27,7 @@ class TestResult: def test_time_increments(self,default): shape = default.read_dataset(default.get_dataset_location('F'),0).shape default.set_by_time(0.0,20.0) - for i in default.iter_visible('increments'): + for i in default.iterate('increments'): assert shape == default.read_dataset(default.get_dataset_location('F'),0).shape @@ -61,7 +61,7 @@ class TestResult: default.add_determinant('P') loc = {'P': default.get_dataset_location('P'), 'det(P)':default.get_dataset_location('det(P)')} - in_memory = np.linalg.det(default.read_dataset(loc['P'],0)).reshape((-1,1)) + in_memory = np.linalg.det(default.read_dataset(loc['P'],0)).reshape(-1,1) in_file = default.read_dataset(loc['det(P)'],0) assert np.allclose(in_memory,in_file) diff --git a/python/tests/test_Table.py b/python/tests/test_Table.py index 369a99efb..cfcdd8813 100644 --- a/python/tests/test_Table.py +++ b/python/tests/test_Table.py @@ -49,7 +49,7 @@ class TestTable: def test_write_read_new_style(self,default,tmpdir): with open(tmpdir.join('new_style.txt'),'w') as f: - default.to_ASCII(f,new=True) + default.to_ASCII(f,new_style=True) with open(tmpdir.join('new_style.txt')) as f: new = Table.from_ASCII(f) assert all(default.data==new.data) and default.shapes == new.shapes @@ -173,4 +173,4 @@ class TestTable: ['test data']) t.add('s',np.array(['b','a'])) t.sort_by('s') - assert np.all(t.get('1_v') == np.array([2,0]).reshape((2,1))) + assert np.all(t.get('1_v') == np.array([2,0]).reshape(2,1)) diff --git a/python/tests/test_grid_filters.py b/python/tests/test_grid_filters.py index ed1336842..cdddca89e 100644 --- a/python/tests/test_grid_filters.py +++ b/python/tests/test_grid_filters.py @@ -31,7 +31,7 @@ class TestGridFilters: 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_gridSizeOrigin(coord0.reshape((-1,3)))'.format(mode)) + _grid,_size,_origin = eval('grid_filters.{}_coord0_gridSizeOrigin(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): diff --git a/src/.gitignore b/src/.gitignore index e9956554e..dea625122 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,4 +1 @@ -Makefile -cmake_install.cmake -quit__genmod.f90 *.marc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 75b39e377..53c7ffc70 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,13 +9,11 @@ file(GLOB damask-sources *.f90 *.c) # probably we should have a subfolder for MSC.Marc list(FILTER damask-sources EXCLUDE REGEX ".*CPFEM.f90") list(FILTER damask-sources EXCLUDE REGEX ".*DAMASK_marc.*.f90") -list(FILTER damask-sources EXCLUDE REGEX ".*mesh_marc.*.f90") list(FILTER damask-sources EXCLUDE REGEX ".*commercialFEM_fileList.*.f90") if (PROJECT_NAME STREQUAL "damask-grid") - list(FILTER damask-sources EXCLUDE REGEX ".*mesh_FEM.*.f90") file(GLOB grid-sources grid/*.f90) if(NOT CMAKE_BUILD_TYPE STREQUAL "SYNTAXONLY") @@ -30,7 +28,6 @@ if (PROJECT_NAME STREQUAL "damask-grid") elseif (PROJECT_NAME STREQUAL "damask-mesh") - list(FILTER damask-sources EXCLUDE REGEX ".*mesh_grid.*.f90") file(GLOB mesh-sources mesh/*.f90) add_executable(DAMASK_FEM ${damask-sources} ${mesh-sources}) diff --git a/src/CPFEM.f90 b/src/CPFEM.f90 index 11b0a557f..c590a86b5 100644 --- a/src/CPFEM.f90 +++ b/src/CPFEM.f90 @@ -10,7 +10,7 @@ module CPFEM use FEsolving use math use rotations - use mesh + use discretization_marc use material use config use crystallite @@ -85,7 +85,7 @@ subroutine CPFEM_initAll(el,ip) call rotations_init call HDF5_utilities_init call results_init - call mesh_init(ip, el) + call discretization_marc_init(ip, el) call lattice_init call material_init call constitutive_init @@ -126,208 +126,201 @@ end subroutine CPFEM_init !-------------------------------------------------------------------------------------------------- subroutine CPFEM_general(mode, parallelExecution, ffn, ffn1, temperature_inp, dt, elFE, ip, cauchyStress, jacobian) - integer(pInt), intent(in) :: elFE, & !< FE element number - ip !< integration point number - real(pReal), intent(in) :: dt !< time increment - real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0 - ffn1 !< deformation gradient for t=t1 - integer(pInt), intent(in) :: mode !< computation mode 1: regular computation plus aging of results - real(pReal), intent(in) :: temperature_inp !< temperature - logical, intent(in) :: parallelExecution !< flag indicating parallel computation of requested IPs - real(pReal), dimension(6), intent(out) :: cauchyStress !< stress as 6 vector - real(pReal), dimension(6,6), intent(out) :: jacobian !< jacobian as 66 tensor (Consistent tangent dcs/dE) - - real(pReal) J_inverse, & ! inverse of Jacobian - rnd - real(pReal), dimension (3,3) :: Kirchhoff, & ! Piola-Kirchhoff stress in Matrix notation - cauchyStress33 ! stress vector in Matrix notation - real(pReal), dimension (3,3,3,3) :: H_sym, & - H, & - jacobian3333 ! jacobian in Matrix notation - - integer(pInt) elCP, & ! crystal plasticity element number - i, j, k, l, m, n, ph, homog, mySource - logical updateJaco ! flag indicating if Jacobian has to be updated - - real(pReal), parameter :: ODD_STRESS = 1e15_pReal, & !< return value for stress in case of ping pong dummy cycle - ODD_JACOBIAN = 1e50_pReal !< return value for jacobian in case of ping pong dummy cycle - - elCP = mesh_FEM2DAMASK_elem(elFE) - - if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt & - .and. elCP == debug_e .and. ip == debug_i) then - write(6,'(/,a)') '#############################################' - write(6,'(a1,a22,1x,i8,a13)') '#','element', elCP, '#' - write(6,'(a1,a22,1x,i8,a13)') '#','ip', ip, '#' - write(6,'(a1,a22,1x,f15.7,a6)') '#','theTime', theTime, '#' - write(6,'(a1,a22,1x,f15.7,a6)') '#','theDelta', theDelta, '#' - write(6,'(a1,a22,1x,i8,a13)') '#','theInc', theInc, '#' - write(6,'(a1,a22,1x,i8,a13)') '#','cycleCounter', cycleCounter, '#' - write(6,'(a1,a22,1x,i8,a13)') '#','computationMode',mode, '#' - if (terminallyIll) & - write(6,'(a,/)') '# --- terminallyIll --- #' - write(6,'(a,/)') '#############################################'; flush (6) - endif - - if (iand(mode, CPFEM_BACKUPJACOBIAN) /= 0_pInt) & - CPFEM_dcsde_knownGood = CPFEM_dcsde - if (iand(mode, CPFEM_RESTOREJACOBIAN) /= 0_pInt) & - CPFEM_dcsde = CPFEM_dcsde_knownGood - - !*** age results - if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) call CPFEM_forward - - - !*** collection of FEM input with returning of randomize odd stress and jacobian - !* If no parallel execution is required, there is no need to collect FEM input - - if (.not. parallelExecution) then - chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP))) - case (THERMAL_conduction_ID) chosenThermal1 - temperature(material_homogenizationAt(elCP))%p(thermalMapping(material_homogenizationAt(elCP))%p(ip,elCP)) = & - temperature_inp - end select chosenThermal1 - materialpoint_F0(1:3,1:3,ip,elCP) = ffn - materialpoint_F(1:3,1:3,ip,elCP) = ffn1 - - elseif (iand(mode, CPFEM_COLLECT) /= 0_pInt) then - call random_number(rnd) - if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal - CPFEM_cs(1:6,ip,elCP) = rnd * ODD_STRESS - CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) - chosenThermal2: select case (thermal_type(material_homogenizationAt(elCP))) - case (THERMAL_conduction_ID) chosenThermal2 - temperature(material_homogenizationAt(elCP))%p(thermalMapping(material_homogenizationAt(elCP))%p(ip,elCP)) = & - temperature_inp - end select chosenThermal2 - materialpoint_F0(1:3,1:3,ip,elCP) = ffn - materialpoint_F(1:3,1:3,ip,elCP) = ffn1 - CPFEM_calc_done = .false. - endif ! collection - - - - !*** calculation of stress and jacobian - - if (iand(mode, CPFEM_CALCRESULTS) /= 0_pInt) then - - !*** deformation gradient outdated or any actual deformation gradient differs more than relevantStrain from the stored one - validCalculation: if (terminallyIll & - .or. outdatedFFN1 & - .or. any(abs(ffn1 - materialpoint_F(1:3,1:3,ip,elCP)) > defgradTolerance)) then - if (any(abs(ffn1 - materialpoint_F(1:3,1:3,ip,elCP)) > defgradTolerance)) then - if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then - write(6,'(a,1x,i8,1x,i2)') '<< CPFEM >> OUTDATED at elFE ip',elFE,ip - write(6,'(a,/,3(12x,3(f10.6,1x),/))') '<< CPFEM >> FFN1 old:',& - transpose(materialpoint_F(1:3,1:3,ip,elCP)) - write(6,'(a,/,3(12x,3(f10.6,1x),/))') '<< CPFEM >> FFN1 now:',transpose(ffn1) - endif - outdatedFFN1 = .true. - endif - call random_number(rnd) - if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal - CPFEM_cs(1:6,ip,elCP) = ODD_STRESS * rnd - CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) - - !*** deformation gradient is not outdated - - else validCalculation - updateJaco = mod(cycleCounter,iJacoStiffness) == 0 - !* no parallel computation, so we use just one single elFE and ip for computation - - if (.not. parallelExecution) then - FEsolving_execElem = elCP - FEsolving_execIP = ip - if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & - write(6,'(a,i8,1x,i2)') '<< CPFEM >> calculation for elFE ip ',elFE,ip - call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent - - !* parallel computation and calulation not yet done - - elseif (.not. CPFEM_calc_done) then - if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & - write(6,'(a,i8,a,i8)') '<< CPFEM >> calculation for elements ',FEsolving_execElem(1),& - ' to ',FEsolving_execElem(2) - call materialpoint_stressAndItsTangent(updateJaco, dt) ! calculate stress and its tangent (parallel execution inside) - CPFEM_calc_done = .true. - endif - - !* map stress and stiffness (or return odd values if terminally ill) - terminalIllness: if ( terminallyIll ) then - - call random_number(rnd) - if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal - CPFEM_cs(1:6,ip,elCP) = ODD_STRESS * rnd - CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) - - else terminalIllness - - - ! translate from P to CS - Kirchhoff = matmul(materialpoint_P(1:3,1:3,ip,elCP), transpose(materialpoint_F(1:3,1:3,ip,elCP))) - J_inverse = 1.0_pReal / math_det33(materialpoint_F(1:3,1:3,ip,elCP)) - CPFEM_cs(1:6,ip,elCP) = math_sym33to6(J_inverse * Kirchhoff,weighted=.false.) - - ! translate from dP/dF to dCS/dE - H = 0.0_pReal - do i=1,3; do j=1,3; do k=1,3; do l=1,3; do m=1,3; do n=1,3 - H(i,j,k,l) = H(i,j,k,l) & - + materialpoint_F(j,m,ip,elCP) * materialpoint_F(l,n,ip,elCP) & - * materialpoint_dPdF(i,m,k,n,ip,elCP) & - - math_delta(j,l) * materialpoint_F(i,m,ip,elCP) * materialpoint_P(k,m,ip,elCP) & - + 0.5_pReal * ( Kirchhoff(j,l)*math_delta(i,k) + Kirchhoff(i,k)*math_delta(j,l) & - + Kirchhoff(j,k)*math_delta(i,l) + Kirchhoff(i,l)*math_delta(j,k)) - enddo; enddo; enddo; enddo; enddo; enddo - - forall(i=1:3, j=1:3,k=1:3,l=1:3) & - H_sym(i,j,k,l) = 0.25_pReal * (H(i,j,k,l) + H(j,i,k,l) + H(i,j,l,k) + H(j,i,l,k)) - - CPFEM_dcsde(1:6,1:6,ip,elCP) = math_sym3333to66(J_inverse * H_sym,weighted=.false.) - - endif terminalIllness - endif validCalculation - - !* report stress and stiffness - if ((iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & - .and. ((debug_e == elCP .and. debug_i == ip) & - .or. .not. iand(debug_level(debug_CPFEM), debug_levelSelective) /= 0_pInt)) then - write(6,'(a,i8,1x,i2,/,12x,6(f10.3,1x)/)') & - '<< CPFEM >> stress/MPa at elFE ip ', elFE, ip, CPFEM_cs(1:6,ip,elCP)*1.0e-6_pReal - write(6,'(a,i8,1x,i2,/,6(12x,6(f10.3,1x)/))') & - '<< CPFEM >> Jacobian/GPa at elFE ip ', elFE, ip, transpose(CPFEM_dcsdE(1:6,1:6,ip,elCP))*1.0e-9_pReal - flush(6) - endif - - endif - - !*** warn if stiffness close to zero - if (all(abs(CPFEM_dcsdE(1:6,1:6,ip,elCP)) < 1e-10_pReal)) call IO_warning(601,elCP,ip) - - !*** copy to output if using commercial FEM solver - cauchyStress = CPFEM_cs (1:6, ip,elCP) - jacobian = CPFEM_dcsdE(1:6,1:6,ip,elCP) - - - !*** remember extreme values of stress ... - cauchyStress33 = math_6toSym33(CPFEM_cs(1:6,ip,elCP),weighted=.false.) - if (maxval(cauchyStress33) > debug_stressMax) then - debug_stressMaxLocation = [elCP, ip] - debug_stressMax = maxval(cauchyStress33) - endif - if (minval(cauchyStress33) < debug_stressMin) then - debug_stressMinLocation = [elCP, ip] - debug_stressMin = minval(cauchyStress33) - endif - !*** ... and Jacobian - jacobian3333 = math_66toSym3333(CPFEM_dcsdE(1:6,1:6,ip,elCP),weighted=.false.) - if (maxval(jacobian3333) > debug_jacobianMax) then - debug_jacobianMaxLocation = [elCP, ip] - debug_jacobianMax = maxval(jacobian3333) - endif - if (minval(jacobian3333) < debug_jacobianMin) then - debug_jacobianMinLocation = [elCP, ip] - debug_jacobianMin = minval(jacobian3333) - endif + integer(pInt), intent(in) :: elFE, & !< FE element number + ip !< integration point number + real(pReal), intent(in) :: dt !< time increment + real(pReal), dimension (3,3), intent(in) :: ffn, & !< deformation gradient for t=t0 + ffn1 !< deformation gradient for t=t1 + integer(pInt), intent(in) :: mode !< computation mode 1: regular computation plus aging of results + real(pReal), intent(in) :: temperature_inp !< temperature + logical, intent(in) :: parallelExecution !< flag indicating parallel computation of requested IPs + real(pReal), dimension(6), intent(out) :: cauchyStress !< stress as 6 vector + real(pReal), dimension(6,6), intent(out) :: jacobian !< jacobian as 66 tensor (Consistent tangent dcs/dE) + + real(pReal) J_inverse, & ! inverse of Jacobian + rnd + real(pReal), dimension (3,3) :: Kirchhoff, & ! Piola-Kirchhoff stress + cauchyStress33 ! stress vector + real(pReal), dimension (3,3,3,3) :: H_sym, & + H, & + jacobian3333 ! jacobian in Matrix notation + + integer(pInt) elCP, & ! crystal plasticity element number + i, j, k, l, m, n, ph, homog, mySource + logical updateJaco ! flag indicating if Jacobian has to be updated + + real(pReal), parameter :: ODD_STRESS = 1e15_pReal, & !< return value for stress in case of ping pong dummy cycle + ODD_JACOBIAN = 1e50_pReal !< return value for jacobian in case of ping pong dummy cycle + + elCP = mesh_FEM2DAMASK_elem(elFE) + + if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt & + .and. elCP == debug_e .and. ip == debug_i) then + write(6,'(/,a)') '#############################################' + write(6,'(a1,a22,1x,i8,a13)') '#','element', elCP, '#' + write(6,'(a1,a22,1x,i8,a13)') '#','ip', ip, '#' + write(6,'(a1,a22,1x,f15.7,a6)') '#','theTime', theTime, '#' + write(6,'(a1,a22,1x,f15.7,a6)') '#','theDelta', theDelta, '#' + write(6,'(a1,a22,1x,i8,a13)') '#','theInc', theInc, '#' + write(6,'(a1,a22,1x,i8,a13)') '#','cycleCounter', cycleCounter, '#' + write(6,'(a1,a22,1x,i8,a13)') '#','computationMode',mode, '#' + if (terminallyIll) & + write(6,'(a,/)') '# --- terminallyIll --- #' + write(6,'(a,/)') '#############################################'; flush (6) + endif + + if (iand(mode, CPFEM_BACKUPJACOBIAN) /= 0_pInt) & + CPFEM_dcsde_knownGood = CPFEM_dcsde + if (iand(mode, CPFEM_RESTOREJACOBIAN) /= 0_pInt) & + CPFEM_dcsde = CPFEM_dcsde_knownGood + + !*** age results + if (iand(mode, CPFEM_AGERESULTS) /= 0_pInt) call CPFEM_forward + + + !*** collection of FEM input with returning of randomize odd stress and jacobian + !* If no parallel execution is required, there is no need to collect FEM input + if (.not. parallelExecution) then + chosenThermal1: select case (thermal_type(material_homogenizationAt(elCP))) + case (THERMAL_conduction_ID) chosenThermal1 + temperature(material_homogenizationAt(elCP))%p(thermalMapping(material_homogenizationAt(elCP))%p(ip,elCP)) = & + temperature_inp + end select chosenThermal1 + materialpoint_F0(1:3,1:3,ip,elCP) = ffn + materialpoint_F(1:3,1:3,ip,elCP) = ffn1 + + elseif (iand(mode, CPFEM_COLLECT) /= 0_pInt) then + call random_number(rnd) + if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal + CPFEM_cs(1:6,ip,elCP) = rnd * ODD_STRESS + CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) + chosenThermal2: select case (thermal_type(material_homogenizationAt(elCP))) + case (THERMAL_conduction_ID) chosenThermal2 + temperature(material_homogenizationAt(elCP))%p(thermalMapping(material_homogenizationAt(elCP))%p(ip,elCP)) = & + temperature_inp + end select chosenThermal2 + materialpoint_F0(1:3,1:3,ip,elCP) = ffn + materialpoint_F(1:3,1:3,ip,elCP) = ffn1 + CPFEM_calc_done = .false. + endif + + + !*** calculation of stress and jacobian + if (iand(mode, CPFEM_CALCRESULTS) /= 0_pInt) then + + !*** deformation gradient outdated or any actual deformation gradient differs more than relevantStrain from the stored one + validCalculation: if (terminallyIll & + .or. outdatedFFN1 & + .or. any(abs(ffn1 - materialpoint_F(1:3,1:3,ip,elCP)) > defgradTolerance)) then + if (any(abs(ffn1 - materialpoint_F(1:3,1:3,ip,elCP)) > defgradTolerance)) then + if (iand(debug_level(debug_CPFEM), debug_levelBasic) /= 0_pInt) then + write(6,'(a,1x,i8,1x,i2)') '<< CPFEM >> OUTDATED at elFE ip',elFE,ip + write(6,'(a,/,3(12x,3(f10.6,1x),/))') '<< CPFEM >> FFN1 old:',& + transpose(materialpoint_F(1:3,1:3,ip,elCP)) + write(6,'(a,/,3(12x,3(f10.6,1x),/))') '<< CPFEM >> FFN1 now:',transpose(ffn1) + endif + outdatedFFN1 = .true. + endif + call random_number(rnd) + if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal + CPFEM_cs(1:6,ip,elCP) = ODD_STRESS * rnd + CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) + + !*** deformation gradient is not outdated + else validCalculation + updateJaco = mod(cycleCounter,iJacoStiffness) == 0 + !* no parallel computation, so we use just one single elFE and ip for computation + if (.not. parallelExecution) then + FEsolving_execElem = elCP + FEsolving_execIP = ip + if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & + write(6,'(a,i8,1x,i2)') '<< CPFEM >> calculation for elFE ip ',elFE,ip + call materialpoint_stressAndItsTangent(updateJaco, dt) + + !* parallel computation and calulation not yet done + elseif (.not. CPFEM_calc_done) then + if (iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & + write(6,'(a,i8,a,i8)') '<< CPFEM >> calculation for elements ',FEsolving_execElem(1),& + ' to ',FEsolving_execElem(2) + call materialpoint_stressAndItsTangent(updateJaco, dt) + CPFEM_calc_done = .true. + endif + + !* map stress and stiffness (or return odd values if terminally ill) + terminalIllness: if (terminallyIll) then + + call random_number(rnd) + if (rnd < 0.5_pReal) rnd = rnd - 1.0_pReal + CPFEM_cs(1:6,ip,elCP) = ODD_STRESS * rnd + CPFEM_dcsde(1:6,1:6,ip,elCP) = ODD_JACOBIAN * math_identity2nd(6) + + else terminalIllness + + ! translate from P to CS + Kirchhoff = matmul(materialpoint_P(1:3,1:3,ip,elCP), transpose(materialpoint_F(1:3,1:3,ip,elCP))) + J_inverse = 1.0_pReal / math_det33(materialpoint_F(1:3,1:3,ip,elCP)) + CPFEM_cs(1:6,ip,elCP) = math_sym33to6(J_inverse * Kirchhoff,weighted=.false.) + + ! translate from dP/dF to dCS/dE + H = 0.0_pReal + do i=1,3; do j=1,3; do k=1,3; do l=1,3; do m=1,3; do n=1,3 + H(i,j,k,l) = H(i,j,k,l) & + + materialpoint_F(j,m,ip,elCP) * materialpoint_F(l,n,ip,elCP) & + * materialpoint_dPdF(i,m,k,n,ip,elCP) & + - math_delta(j,l) * materialpoint_F(i,m,ip,elCP) * materialpoint_P(k,m,ip,elCP) & + + 0.5_pReal * ( Kirchhoff(j,l)*math_delta(i,k) + Kirchhoff(i,k)*math_delta(j,l) & + + Kirchhoff(j,k)*math_delta(i,l) + Kirchhoff(i,l)*math_delta(j,k)) + enddo; enddo; enddo; enddo; enddo; enddo + + forall(i=1:3, j=1:3,k=1:3,l=1:3) & + H_sym(i,j,k,l) = 0.25_pReal * (H(i,j,k,l) + H(j,i,k,l) + H(i,j,l,k) + H(j,i,l,k)) + + CPFEM_dcsde(1:6,1:6,ip,elCP) = math_sym3333to66(J_inverse * H_sym,weighted=.false.) + + endif terminalIllness + endif validCalculation + + !* report stress and stiffness + if ((iand(debug_level(debug_CPFEM), debug_levelExtensive) /= 0_pInt) & + .and. ((debug_e == elCP .and. debug_i == ip) & + .or. .not. iand(debug_level(debug_CPFEM), debug_levelSelective) /= 0_pInt)) then + write(6,'(a,i8,1x,i2,/,12x,6(f10.3,1x)/)') & + '<< CPFEM >> stress/MPa at elFE ip ', elFE, ip, CPFEM_cs(1:6,ip,elCP)*1.0e-6_pReal + write(6,'(a,i8,1x,i2,/,6(12x,6(f10.3,1x)/))') & + '<< CPFEM >> Jacobian/GPa at elFE ip ', elFE, ip, transpose(CPFEM_dcsdE(1:6,1:6,ip,elCP))*1.0e-9_pReal + flush(6) + endif + + endif + + !*** warn if stiffness close to zero + if (all(abs(CPFEM_dcsdE(1:6,1:6,ip,elCP)) < 1e-10_pReal)) call IO_warning(601,elCP,ip) + + !*** copy to output if using commercial FEM solver + cauchyStress = CPFEM_cs (1:6, ip,elCP) + jacobian = CPFEM_dcsdE(1:6,1:6,ip,elCP) + + + !*** remember extreme values of stress ... + cauchyStress33 = math_6toSym33(CPFEM_cs(1:6,ip,elCP),weighted=.false.) + if (maxval(cauchyStress33) > debug_stressMax) then + debug_stressMaxLocation = [elCP, ip] + debug_stressMax = maxval(cauchyStress33) + endif + if (minval(cauchyStress33) < debug_stressMin) then + debug_stressMinLocation = [elCP, ip] + debug_stressMin = minval(cauchyStress33) + endif + !*** ... and Jacobian + jacobian3333 = math_66toSym3333(CPFEM_dcsdE(1:6,1:6,ip,elCP),weighted=.false.) + if (maxval(jacobian3333) > debug_jacobianMax) then + debug_jacobianMaxLocation = [elCP, ip] + debug_jacobianMax = maxval(jacobian3333) + endif + if (minval(jacobian3333) < debug_jacobianMin) then + debug_jacobianMinLocation = [elCP, ip] + debug_jacobianMin = minval(jacobian3333) + endif end subroutine CPFEM_general diff --git a/src/CPFEM2.f90 b/src/CPFEM2.f90 index 882fe8ae3..357bcce9f 100644 --- a/src/CPFEM2.f90 +++ b/src/CPFEM2.f90 @@ -21,11 +21,11 @@ module CPFEM2 use homogenization use constitutive use crystallite -#ifdef FEM - use FEM_Zoo - use mesh -#else - use mesh_grid +#if defined(FEM) + use FEM_quadrature + use discretization_mesh +#elif defined(Grid) + use discretization_grid #endif implicit none @@ -43,7 +43,7 @@ subroutine CPFEM_initAll call prec_init call IO_init #ifdef FEM - call FEM_Zoo_init + call FEM_quadrature_init #endif call numerics_init call debug_init @@ -53,7 +53,11 @@ subroutine CPFEM_initAll call lattice_init call HDF5_utilities_init call results_init - call mesh_init +#if defined(FEM) + call discretization_mesh_init +#elif defined(Grid) + call discretization_grid_init +#endif call material_init call constitutive_init call crystallite_init @@ -68,7 +72,7 @@ end subroutine CPFEM_initAll !-------------------------------------------------------------------------------------------------- subroutine CPFEM_init - write(6,'(/,a)') ' <<<+- CPFEM init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- CPFEM init -+>>>'; flush(6) if (interface_restartInc > 0) call crystallite_restartRead diff --git a/src/DAMASK_marc.f90 b/src/DAMASK_marc.f90 index a3718c59d..fe01301c9 100644 --- a/src/DAMASK_marc.f90 +++ b/src/DAMASK_marc.f90 @@ -178,7 +178,7 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, & use numerics use FEsolving use debug - use mesh + use discretization_marc use CPFEM implicit none @@ -233,8 +233,8 @@ subroutine hypela2(d,g,e,de,s,t,dt,ngens,m,nn,kcus,matus,ndi,nshear,disp, & ! Marc common blocks are in fixed format so they have to be reformated to free format (f90) ! Beware of changes in newer Marc versions -#include QUOTE(PASTE(./MarcInclude/concom,Marc4DAMASK)) ! concom is needed for inc, lovl -#include QUOTE(PASTE(./MarcInclude/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment) +#include QUOTE(PASTE(./marc/include/concom,Marc4DAMASK)) ! concom is needed for inc, lovl +#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment) logical :: cutBack real(pReal), dimension(6) :: stress @@ -378,7 +378,7 @@ end subroutine hypela2 subroutine flux(f,ts,n,time) use prec use thermal_conduction - use mesh + use discretization_marc implicit none real(pReal), dimension(6), intent(in) :: & @@ -408,7 +408,7 @@ subroutine uedinc(inc,incsub) implicit none integer, intent(in) :: inc, incsub integer, save :: inc_written -#include QUOTE(PASTE(./MarcInclude/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment) +#include QUOTE(PASTE(./marc/include/creeps,Marc4DAMASK)) ! creeps is needed for timinc (time increment) if (inc > inc_written) then call CPFEM_results(inc,cptim) diff --git a/src/HDF5_utilities.f90 b/src/HDF5_utilities.f90 index aa75d9c87..66705cc3f 100644 --- a/src/HDF5_utilities.f90 +++ b/src/HDF5_utilities.f90 @@ -30,7 +30,7 @@ module HDF5_utilities module procedure HDF5_read_real5 module procedure HDF5_read_real6 module procedure HDF5_read_real7 - + module procedure HDF5_read_int1 module procedure HDF5_read_int2 module procedure HDF5_read_int3 @@ -38,7 +38,7 @@ module HDF5_utilities module procedure HDF5_read_int5 module procedure HDF5_read_int6 module procedure HDF5_read_int7 - + end interface HDF5_read !-------------------------------------------------------------------------------------------------- @@ -53,7 +53,7 @@ module HDF5_utilities module procedure HDF5_write_real5 module procedure HDF5_write_real6 module procedure HDF5_write_real7 - + module procedure HDF5_write_int1 module procedure HDF5_write_int2 module procedure HDF5_write_int3 @@ -61,11 +61,11 @@ module HDF5_utilities module procedure HDF5_write_int5 module procedure HDF5_write_int6 module procedure HDF5_write_int7 - + module procedure HDF5_write_rotation - + end interface HDF5_write - + !-------------------------------------------------------------------------------------------------- !> @brief attached attributes of type char, integer or real to a file/dataset/group !-------------------------------------------------------------------------------------------------- @@ -76,7 +76,7 @@ module HDF5_utilities module procedure HDF5_addAttribute_int_array module procedure HDF5_addAttribute_real_array end interface HDF5_addAttribute - + contains @@ -116,17 +116,17 @@ integer(HID_T) function HDF5_openFile(fileName,mode,parallel) character(len=*), intent(in) :: fileName character, intent(in), optional :: mode logical, intent(in), optional :: parallel - + character :: m integer(HID_T) :: plist_id integer :: hdferr - + if (present(mode)) then m = mode else m = 'r' endif - + call h5pcreate_f(H5P_FILE_ACCESS_F, plist_id, hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_openFile: h5pcreate_f') @@ -149,7 +149,7 @@ integer(HID_T) function HDF5_openFile(fileName,mode,parallel) else call IO_error(1,ext_msg='HDF5_openFile: h5fopen_f unknown access mode: '//trim(m)) endif - + call h5pclose_f(plist_id, hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_openFile: h5pclose_f') @@ -162,9 +162,9 @@ end function HDF5_openFile subroutine HDF5_closeFile(fileHandle) integer(HID_T), intent(in) :: fileHandle - + integer :: hdferr - + call h5fclose_f(fileHandle,hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_closeFile: h5fclose_f') @@ -178,7 +178,7 @@ integer(HID_T) function HDF5_addGroup(fileHandle,groupName) integer(HID_T), intent(in) :: fileHandle character(len=*), intent(in) :: groupName - + integer :: hdferr integer(HID_T) :: aplist_id @@ -193,7 +193,7 @@ integer(HID_T) function HDF5_addGroup(fileHandle,groupName) call h5pset_all_coll_metadata_ops_f(aplist_id, .true., hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_addGroup: h5pset_all_coll_metadata_ops_f ('//trim(groupName)//')') #endif - + !------------------------------------------------------------------------------------------------- ! Create group call h5gcreate_f(fileHandle, trim(groupName), HDF5_addGroup, hdferr, OBJECT_NAMELEN_DEFAULT_F,gapl_id = aplist_id) @@ -211,13 +211,13 @@ integer(HID_T) function HDF5_openGroup(fileHandle,groupName) integer(HID_T), intent(in) :: fileHandle character(len=*), intent(in) :: groupName - - + + integer :: hdferr integer(HID_T) :: aplist_id logical :: is_collective - - + + !------------------------------------------------------------------------------------------------- ! creating a property list for data access properties call h5pcreate_f(H5P_GROUP_ACCESS_F, aplist_id, hdferr) @@ -229,7 +229,7 @@ integer(HID_T) function HDF5_openGroup(fileHandle,groupName) call h5pget_all_coll_metadata_ops_f(aplist_id, is_collective, hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_openGroup: h5pset_all_coll_metadata_ops_f ('//trim(groupName)//')') #endif - + !------------------------------------------------------------------------------------------------- ! opening the group call h5gopen_f(fileHandle, trim(groupName), HDF5_openGroup, hdferr, gapl_id = aplist_id) @@ -247,7 +247,7 @@ subroutine HDF5_closeGroup(group_id) integer(HID_T), intent(in) :: group_id integer :: hdferr - + call h5gclose_f(group_id, hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_closeGroup: h5gclose_f (el is ID)', el = int(group_id)) @@ -261,19 +261,19 @@ logical function HDF5_objectExists(loc_id,path) integer(HID_T), intent(in) :: loc_id character(len=*), intent(in), optional :: path - + integer :: hdferr character(len=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + call h5lexists_f(loc_id, p, HDF5_objectExists, hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_objectExists: h5oexists_by_name_f') - + if(HDF5_objectExists) then call h5oexists_by_name_f(loc_id, p, HDF5_objectExists, hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_objectExists: h5oexists_by_name_f') @@ -290,18 +290,18 @@ subroutine HDF5_addAttribute_str(loc_id,attrLabel,attrValue,path) integer(HID_T), intent(in) :: loc_id 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=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + call h5screate_f(H5S_SCALAR_F,space_id,hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_addAttribute_str: h5screate_f') call h5tcopy_f(H5T_NATIVE_CHARACTER, type_id, hdferr) @@ -337,18 +337,18 @@ subroutine HDF5_addAttribute_int(loc_id,attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel integer, intent(in) :: attrValue character(len=*), intent(in), optional :: path - + integer :: hdferr integer(HID_T) :: attr_id, space_id logical :: attrExists character(len=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + call h5screate_f(H5S_SCALAR_F,space_id,hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_addAttribute_int: h5screate_f') call h5aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) @@ -378,18 +378,18 @@ subroutine HDF5_addAttribute_real(loc_id,attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel real(pReal), intent(in) :: attrValue character(len=*), intent(in), optional :: path - + integer :: hdferr integer(HID_T) :: attr_id, space_id logical :: attrExists character(len=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + call h5screate_f(H5S_SCALAR_F,space_id,hdferr) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_addAttribute_real: h5screate_f') call h5aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) @@ -419,21 +419,21 @@ subroutine HDF5_addAttribute_int_array(loc_id,attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel integer, intent(in), dimension(:) :: attrValue character(len=*), intent(in), optional :: path - + integer :: hdferr integer(HID_T) :: attr_id, space_id integer(HSIZE_T),dimension(1) :: array_size logical :: attrExists character(len=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + array_size = size(attrValue,kind=HSIZE_T) - + call h5screate_simple_f(1, array_size, space_id, hdferr, array_size) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_addAttribute_int_array: h5screate_f') call h5aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) @@ -463,21 +463,21 @@ subroutine HDF5_addAttribute_real_array(loc_id,attrLabel,attrValue,path) character(len=*), intent(in) :: attrLabel real(pReal), intent(in), dimension(:) :: attrValue character(len=*), intent(in), optional :: path - + integer :: hdferr integer(HID_T) :: attr_id, space_id integer(HSIZE_T),dimension(1) :: array_size logical :: attrExists character(len=pStringLen) :: p - + if (present(path)) then p = trim(path) else p = '.' endif - + array_size = size(attrValue,kind=HSIZE_T) - + call h5screate_simple_f(1, array_size, space_id, hdferr, array_size) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_addAttribute_int_array: h5screate_f') call h5aexists_by_name_f(loc_id,trim(p),attrLabel,attrExists,hdferr) @@ -507,7 +507,7 @@ subroutine HDF5_setLink(loc_id,target_name,link_name) integer(HID_T), intent(in) :: loc_id integer :: hdferr logical :: linkExists - + call h5lexists_f(loc_id, link_name,linkExists, hdferr) if (hdferr < 0) call IO_error(1,ext_msg = 'HDF5_setLink: h5lexists_soft_f ('//trim(link_name)//')') if (linkExists) then @@ -525,11 +525,11 @@ end subroutine HDF5_setLink !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real1(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:) :: dataset + real(pReal), intent(out), dimension(:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & ! ToDo: Fortran 2018 size(shape(A)) = rank(A) myStart, & @@ -551,13 +551,13 @@ subroutine HDF5_read_real1(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real1: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) - + end subroutine HDF5_read_real1 !-------------------------------------------------------------------------------------------------- @@ -565,11 +565,11 @@ end subroutine HDF5_read_real1 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real2(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:) :: dataset + real(pReal), intent(out), dimension(:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -591,11 +591,11 @@ subroutine HDF5_read_real2(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real2: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_real2 @@ -605,11 +605,11 @@ end subroutine HDF5_read_real2 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real3(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:) :: dataset + real(pReal), intent(out), dimension(:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -631,7 +631,7 @@ subroutine HDF5_read_real3(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real3: h5dread_f') @@ -645,10 +645,10 @@ end subroutine HDF5_read_real3 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real4(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:) :: dataset + real(pReal), intent(out), dimension(:,:,:,:) :: dataset !< read data integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & @@ -671,11 +671,11 @@ subroutine HDF5_read_real4(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real4: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_real4 @@ -685,11 +685,11 @@ end subroutine HDF5_read_real4 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real5(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset + real(pReal), intent(out), dimension(:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -711,11 +711,11 @@ subroutine HDF5_read_real5(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real5: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_real5 @@ -725,11 +725,11 @@ end subroutine HDF5_read_real5 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real6(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset + real(pReal), intent(out), dimension(:,:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -765,10 +765,10 @@ end subroutine HDF5_read_real6 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_real7(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset + real(pReal), intent(out), dimension(:,:,:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & @@ -791,11 +791,11 @@ subroutine HDF5_read_real7(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_DOUBLE,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_real7: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_real7 @@ -806,11 +806,12 @@ end subroutine HDF5_read_real7 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int1(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:) :: dataset + integer, intent(out), dimension(:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -838,7 +839,7 @@ subroutine HDF5_read_int1(loc_id,dataset,datasetName,parallel) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int1: h5dread_f') call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) - + end subroutine HDF5_read_int1 !-------------------------------------------------------------------------------------------------- @@ -846,10 +847,10 @@ end subroutine HDF5_read_int1 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int2(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:) :: dataset + integer, intent(out), dimension(:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & @@ -872,11 +873,11 @@ subroutine HDF5_read_int2(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int2: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int2 @@ -886,10 +887,10 @@ end subroutine HDF5_read_int2 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int3(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:) :: dataset + integer, intent(out), dimension(:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & @@ -912,11 +913,11 @@ subroutine HDF5_read_int3(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int3: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int3 @@ -926,11 +927,11 @@ end subroutine HDF5_read_int3 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int4(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:) :: dataset + integer, intent(out), dimension(:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -952,11 +953,11 @@ subroutine HDF5_read_int4(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int4: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int4 @@ -966,11 +967,11 @@ end subroutine HDF5_read_int4 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int5(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:) :: dataset + integer, intent(out), dimension(:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -996,7 +997,7 @@ subroutine HDF5_read_int5(loc_id,dataset,datasetName,parallel) call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int5: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int5 @@ -1006,10 +1007,10 @@ end subroutine HDF5_read_int5 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int6(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset + integer, intent(out), dimension(:,:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & @@ -1032,11 +1033,11 @@ subroutine HDF5_read_int6(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int6: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int6 @@ -1046,11 +1047,11 @@ end subroutine HDF5_read_int6 !-------------------------------------------------------------------------------------------------- subroutine HDF5_read_int7(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset + integer, intent(out), dimension(:,:,:,:,:,:,:) :: dataset !< data read from file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel - + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes + integer(HID_T) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id integer(HSIZE_T), dimension(size(shape(dataset))) :: & myStart, & @@ -1072,11 +1073,11 @@ subroutine HDF5_read_int7(loc_id,dataset,datasetName,parallel) call initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id, & myStart, totalShape, loc_id,myShape,datasetName,.false.) endif - + call h5dread_f(dset_id, H5T_NATIVE_INTEGER,dataset,totalShape, hdferr,& file_space_id = filespace_id, xfer_prp = plist_id, mem_space_id = memspace_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_read_int7: h5dread_f') - + call finalize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_id) end subroutine HDF5_read_int7 @@ -1087,10 +1088,10 @@ end subroutine HDF5_read_int7 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real1(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:) :: dataset + real(pReal), intent(inout), dimension(:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1128,10 +1129,10 @@ end subroutine HDF5_write_real1 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real2(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:) :: dataset + real(pReal), intent(inout), dimension(:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1169,10 +1170,10 @@ end subroutine HDF5_write_real2 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real3(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:) :: dataset + real(pReal), intent(inout), dimension(:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1210,10 +1211,10 @@ end subroutine HDF5_write_real3 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:) :: dataset + real(pReal), intent(inout), dimension(:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1227,7 +1228,7 @@ subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel) ! determine shape of dataset myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - + if (present(parallel)) then call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) @@ -1235,13 +1236,13 @@ subroutine HDF5_write_real4(loc_id,dataset,datasetName,parallel) call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) endif - + if (product(totalShape) /= 0) then call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_real4: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_real4 @@ -1252,10 +1253,10 @@ end subroutine HDF5_write_real4 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset + real(pReal), intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1269,7 +1270,7 @@ subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel) ! determine shape of dataset myShape = int(shape(dataset),HSIZE_T) if (any(myShape(1:size(myShape)-1) == 0)) return !< empty dataset (last dimension can be empty) - + if (present(parallel)) then call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,parallel) @@ -1277,13 +1278,13 @@ subroutine HDF5_write_real5(loc_id,dataset,datasetName,parallel) call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, loc_id,myShape,datasetName,H5T_NATIVE_DOUBLE,.false.) endif - + if (product(totalShape) /= 0) then call h5dwrite_f(dset_id, H5T_NATIVE_DOUBLE,dataset,int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_real5: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_real5 @@ -1293,10 +1294,10 @@ end subroutine HDF5_write_real5 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset + real(pReal), intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1324,7 +1325,7 @@ subroutine HDF5_write_real6(loc_id,dataset,datasetName,parallel) file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_real6: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_real6 @@ -1334,10 +1335,10 @@ end subroutine HDF5_write_real6 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel) - real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset + real(pReal), intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1365,7 +1366,7 @@ subroutine HDF5_write_real7(loc_id,dataset,datasetName,parallel) file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_real7: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_real7 @@ -1376,10 +1377,10 @@ end subroutine HDF5_write_real7 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:) :: dataset + integer, intent(inout), dimension(:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1407,7 +1408,7 @@ subroutine HDF5_write_int1(loc_id,dataset,datasetName,parallel) file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_int1: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_int1 @@ -1417,10 +1418,10 @@ end subroutine HDF5_write_int1 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int2(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:) :: dataset + integer, intent(inout), dimension(:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1458,10 +1459,10 @@ end subroutine HDF5_write_int2 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:) :: dataset + integer, intent(inout), dimension(:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1489,7 +1490,7 @@ subroutine HDF5_write_int3(loc_id,dataset,datasetName,parallel) file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) if (hdferr < 0) call IO_error(1,ext_msg='HDF5_write_int3: h5dwrite_f') endif - + call finalize_write(plist_id, dset_id, filespace_id, memspace_id) end subroutine HDF5_write_int3 @@ -1499,10 +1500,10 @@ end subroutine HDF5_write_int3 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int4(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:) :: dataset + integer, intent(inout), dimension(:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1540,10 +1541,10 @@ end subroutine HDF5_write_int4 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int5(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:) :: dataset + integer, intent(inout), dimension(:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1581,10 +1582,10 @@ end subroutine HDF5_write_int5 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int6(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset + integer, intent(inout), dimension(:,:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1622,10 +1623,10 @@ end subroutine HDF5_write_int6 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_int7(loc_id,dataset,datasetName,parallel) - integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset + integer, intent(inout), dimension(:,:,:,:,:,:,:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file - logical, intent(in), optional :: parallel + logical, intent(in), optional :: parallel !< dataset is distributed over multiple processes integer :: hdferr @@ -1666,7 +1667,7 @@ end subroutine HDF5_write_int7 !-------------------------------------------------------------------------------------------------- subroutine HDF5_write_rotation(loc_id,dataset,datasetName,parallel) - type(rotation), intent(in), dimension(:) :: dataset + type(rotation), intent(in), dimension(:) :: dataset !< data written to file integer(HID_T), intent(in) :: loc_id !< file or group handle character(len=*), intent(in) :: datasetName !< name of the dataset in the file logical, intent(in), optional :: parallel @@ -1688,17 +1689,17 @@ subroutine HDF5_write_rotation(loc_id,dataset,datasetName,parallel) !--------------------------------------------------------------------------------------------------- ! determine shape of dataset myShape = int(shape(dataset),HSIZE_T) - + !--------------------------------------------------------------------------------------------------- ! compound type: name of each quaternion component call h5tget_size_f(H5T_NATIVE_DOUBLE, type_size_real, hdferr) - + call h5tcreate_f(H5T_COMPOUND_F, type_size_real*4_SIZE_T, dtype_id, hdferr) call h5tinsert_f(dtype_id, "w", type_size_real*0_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) call h5tinsert_f(dtype_id, "x", type_size_real*1_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) call h5tinsert_f(dtype_id, "y", type_size_real*2_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) call h5tinsert_f(dtype_id, "z", type_size_real*3_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) - + if (present(parallel)) then call initialize_write(dset_id, filespace_id, memspace_id, plist_id, & myStart, totalShape, loc_id,myShape,datasetName,dtype_id,parallel) @@ -1708,7 +1709,7 @@ subroutine HDF5_write_rotation(loc_id,dataset,datasetName,parallel) endif call h5pset_preserve_f(plist_id, .TRUE., hdferr) - + if (product(totalShape) /= 0) then call h5tcreate_f(H5T_COMPOUND_F, type_size_real, x_id, hdferr) call h5tinsert_f(x_id, "x", 0_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) @@ -1718,7 +1719,7 @@ subroutine HDF5_write_rotation(loc_id,dataset,datasetName,parallel) call h5tinsert_f(y_id, "y", 0_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) call h5tcreate_f(H5T_COMPOUND_F, type_size_real, z_id, hdferr) call h5tinsert_f(z_id, "z", 0_SIZE_T, H5T_NATIVE_DOUBLE, hdferr) - + call h5dwrite_f(dset_id, w_id,dataset_asArray(1,:),int(totalShape,HSIZE_T), hdferr,& file_space_id = filespace_id, mem_space_id = memspace_id, xfer_prp = plist_id) call h5dwrite_f(dset_id, x_id,dataset_asArray(2,:),int(totalShape,HSIZE_T), hdferr,& @@ -1746,17 +1747,17 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_ character(len=*), intent(in) :: datasetName !< name of the dataset in the file logical, intent(in) :: parallel integer(HSIZE_T), intent(in), dimension(:) :: & - localShape + localShape integer(HSIZE_T), intent(out), dimension(size(localShape,1)):: & myStart, & globalShape !< shape of the dataset (all processes) integer(HID_T), intent(out) :: dset_id, filespace_id, memspace_id, plist_id, aplist_id - + integer, dimension(worldsize) :: & readSize !< contribution of all processes integer :: ierr integer :: hdferr - + !------------------------------------------------------------------------------------------------- ! creating a property list for transfer properties (is collective for MPI) call h5pcreate_f(H5P_DATASET_XFER_F, plist_id, hdferr) @@ -1784,7 +1785,7 @@ subroutine initialize_read(dset_id, filespace_id, memspace_id, plist_id, aplist_ !-------------------------------------------------------------------------------------------------- ! creating a property list for IO and set it to collective - call h5pcreate_f(H5P_DATASET_ACCESS_F, aplist_id, hdferr) + call h5pcreate_f(H5P_DATASET_ACCESS_F, aplist_id, hdferr) if (hdferr < 0) call IO_error(1,ext_msg='initialize_read: h5pcreate_f') #ifdef PETSc call h5pset_all_coll_metadata_ops_f(aplist_id, .true., hdferr) @@ -1840,12 +1841,12 @@ subroutine initialize_write(dset_id, filespace_id, memspace_id, plist_id, & logical, intent(in) :: parallel integer(HID_T), intent(in) :: datatype integer(HSIZE_T), intent(in), dimension(:) :: & - myShape + myShape integer(HSIZE_T), intent(out), dimension(size(myShape,1)):: & myStart, & totalShape !< shape of the dataset (all processes) integer(HID_T), intent(out) :: dset_id, filespace_id, memspace_id, plist_id - + integer, dimension(worldsize) :: & writeSize !< contribution of all processes integer :: ierr diff --git a/src/IO.f90 b/src/IO.f90 index 6ab87715c..6e467cb89 100644 --- a/src/IO.f90 +++ b/src/IO.f90 @@ -7,14 +7,15 @@ !-------------------------------------------------------------------------------------------------- module IO use prec - use DAMASK_interface - + implicit none private character(len=*), parameter, public :: & - IO_EOF = '#EOF#' !< end of file string + IO_EOF = '#EOF#', & !< end of file string + IO_WHITESPACE = achar(44)//achar(32)//achar(9)//achar(10)//achar(13) !< whitespace characters character, parameter, public :: & - IO_EOL = new_line(' ') !< end of line str + IO_EOL = new_line('DAMASK'), & !< end of line character + IO_COMMENT = '#' character(len=*), parameter, private :: & IO_DIVIDER = '───────────────────'//& '───────────────────'//& @@ -23,7 +24,7 @@ module IO public :: & IO_init, & IO_read_ASCII, & - IO_open_jobFile_binary, & + IO_open_binary, & IO_isBlank, & IO_getTag, & IO_stringPos, & @@ -41,10 +42,11 @@ contains !> @brief does nothing. !-------------------------------------------------------------------------------------------------- subroutine IO_init - + write(6,'(/,a)') ' <<<+- IO init -+>>>'; flush(6) + call unitTest - + end subroutine IO_init @@ -66,7 +68,7 @@ function IO_read_ASCII(fileName) result(fileContent) l, & myStat logical :: warned - + !-------------------------------------------------------------------------------------------------- ! read data as stream inquire(file = fileName, size=fileLength) @@ -114,24 +116,6 @@ function IO_read_ASCII(fileName) result(fileContent) end function IO_read_ASCII -!-------------------------------------------------------------------------------------------------- -!> @brief opens an existing file for reading or a new file for writing. Name is the job name -!> @details replaces an existing file when writing -!-------------------------------------------------------------------------------------------------- -integer function IO_open_jobFile_binary(extension,mode) - - character(len=*), intent(in) :: extension - character, intent(in), optional :: mode - - if (present(mode)) then - IO_open_jobFile_binary = IO_open_binary(trim(getSolverJobName())//'.'//trim(extension),mode) - else - IO_open_jobFile_binary = IO_open_binary(trim(getSolverJobName())//'.'//trim(extension)) - endif - -end function IO_open_jobFile_binary - - !-------------------------------------------------------------------------------------------------- !> @brief opens an existing file for reading or a new file for writing. !> @details replaces an existing file when writing @@ -140,9 +124,9 @@ integer function IO_open_binary(fileName,mode) character(len=*), intent(in) :: fileName character, intent(in), optional :: mode - + character :: m - integer :: ierr + integer :: ierr if (present(mode)) then m = mode @@ -172,14 +156,10 @@ logical pure function IO_isBlank(string) character(len=*), intent(in) :: string !< string to check for content - character(len=*), parameter :: blankChar = achar(32)//achar(9)//achar(10)//achar(13) ! whitespaces - character(len=*), parameter :: comment = achar(35) ! comment id '#' + integer :: posNonBlank - integer :: posNonBlank, posComment - - posNonBlank = verify(string,blankChar) - posComment = scan(string,comment) - IO_isBlank = posNonBlank == 0 .or. posNonBlank == posComment + posNonBlank = verify(string,IO_WHITESPACE) + IO_isBlank = posNonBlank == 0 .or. posNonBlank == scan(string,IO_COMMENT) end function IO_isBlank @@ -193,19 +173,15 @@ pure function IO_getTag(string,openChar,closeChar) character, intent(in) :: openChar, & !< indicates beginning of tag closeChar !< indicates end of tag character(len=:), allocatable :: IO_getTag - - character(len=*), parameter :: SEP=achar(32)//achar(9)//achar(10)//achar(13) ! whitespaces + integer :: left,right - - if (openChar /= closeChar) then - left = scan(string,openChar) - right = scan(string,closeChar) - else - left = scan(string,openChar) - right = left + merge(scan(string(left+1:),openChar),0,len(string) > left) - endif - - foundTag: if (left == verify(string,SEP) .and. right > left) then + + left = scan(string,openChar) + right = merge(scan(string,closeChar), & + left + merge(scan(string(left+1:),openChar),0,len(string) > left), & + openChar /= closeChar) + + foundTag: if (left == verify(string,IO_WHITESPACE) .and. right > left) then IO_getTag = string(left+1:right-1) else foundTag IO_getTag = '' @@ -215,8 +191,8 @@ end function IO_getTag !-------------------------------------------------------------------------------------------------- -!> @brief locates all space-separated chunks in given string and returns array containing number -!! them and the left/right position to be used by IO_xxxVal +!> @brief locates all whitespace-separated chunks in given string and returns array containing +!! number them and the left/right position to be used by IO_xxxVal !! Array size is dynamically adjusted to number of chunks found in string !! IMPORTANT: first element contains number of chunks! !-------------------------------------------------------------------------------------------------- @@ -224,17 +200,16 @@ pure function IO_stringPos(string) character(len=*), intent(in) :: string !< string in which chunk positions are searched for integer, dimension(:), allocatable :: IO_stringPos - - character(len=*), parameter :: SEP=achar(44)//achar(32)//achar(9)//achar(10)//achar(13) ! comma and whitespaces + integer :: left, right - + allocate(IO_stringPos(1), source=0) right = 0 - - do while (verify(string(right+1:),SEP)>0) - left = right + verify(string(right+1:),SEP) - right = left + scan(string(left:),SEP) - 2 - if ( string(left:left) == '#' ) exit + + do while (verify(string(right+1:),IO_WHITESPACE)>0) + left = right + verify(string(right+1:),IO_WHITESPACE) + right = left + scan(string(left:),IO_WHITESPACE) - 2 + if ( string(left:left) == IO_COMMENT) exit IO_stringPos = [IO_stringPos,left,right] IO_stringPos(1) = IO_stringPos(1)+1 endOfString: if (right < left) then @@ -518,7 +493,7 @@ subroutine IO_error(error_ID,el,ip,g,instance,ext_msg) msg = 'unknown error number...' end select - + !$OMP CRITICAL (write2out) write(0,'(/,a)') ' ┌'//IO_DIVIDER//'┐' write(0,'(a,24x,a,40x,a)') ' │','error', '│' @@ -557,10 +532,10 @@ subroutine IO_warning(warning_ID,el,ip,g,ext_msg) integer, intent(in) :: warning_ID integer, optional, intent(in) :: el,ip,g character(len=*), optional, intent(in) :: ext_msg - + character(len=pStringLen) :: msg character(len=pStringLen) :: formatString - + select case (warning_ID) case (1) msg = 'unknown key' @@ -603,7 +578,7 @@ subroutine IO_warning(warning_ID,el,ip,g,ext_msg) case default msg = 'unknown warning number' end select - + !$OMP CRITICAL (write2out) write(6,'(/,a)') ' ┌'//IO_DIVIDER//'┐' write(6,'(a,24x,a,38x,a)') ' │','warning', '│' @@ -638,12 +613,12 @@ end subroutine IO_warning !> @brief returns verified integer value in given string !-------------------------------------------------------------------------------------------------- integer function verifyIntValue(string) - + character(len=*), intent(in) :: string !< string for conversion to int value integer :: readStatus character(len=*), parameter :: VALIDCHARS = '0123456789+- ' - + valid: if (verify(string,VALIDCHARS) == 0) then read(string,*,iostat=readStatus) verifyIntValue if (readStatus /= 0) call IO_error(111,ext_msg=string) @@ -651,7 +626,7 @@ integer function verifyIntValue(string) verifyIntValue = 0 call IO_error(111,ext_msg=string) endif valid - + end function verifyIntValue @@ -659,12 +634,12 @@ end function verifyIntValue !> @brief returns verified float value in given string !-------------------------------------------------------------------------------------------------- real(pReal) function verifyFloatValue(string) - + character(len=*), intent(in) :: string !< string for conversion to float value - + integer :: readStatus character(len=*), parameter :: VALIDCHARS = '0123456789eE.+- ' - + valid: if (verify(string,VALIDCHARS) == 0) then read(string,*,iostat=readStatus) verifyFloatValue if (readStatus /= 0) call IO_error(112,ext_msg=string) @@ -672,12 +647,12 @@ real(pReal) function verifyFloatValue(string) verifyFloatValue = 0.0_pReal call IO_error(112,ext_msg=string) endif valid - + end function verifyFloatValue !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of IO functions +!> @brief check correctness of some IO functions !-------------------------------------------------------------------------------------------------- subroutine unitTest @@ -704,6 +679,10 @@ subroutine unitTest chunkPos = IO_stringPos(str) if(3112019 /= IO_intValue(str,chunkPos,2)) call IO_error(0,ext_msg='IO_intValue') + if(.not. IO_isBlank(' ')) call IO_error(0,ext_msg='IO_isBlank/1') + if(.not. IO_isBlank(' #isBlank')) call IO_error(0,ext_msg='IO_isBlank/2') + if( IO_isBlank(' i#s')) call IO_error(0,ext_msg='IO_isBlank/3') + end subroutine unitTest end module IO diff --git a/src/commercialFEM_fileList.f90 b/src/commercialFEM_fileList.f90 index f3b681052..ab26ee9d5 100644 --- a/src/commercialFEM_fileList.f90 +++ b/src/commercialFEM_fileList.f90 @@ -20,7 +20,7 @@ #include "geometry_plastic_nonlocal.f90" #include "discretization.f90" #ifdef Marc4DAMASK -#include "mesh_marc.f90" +#include "marc/discretization_marc.f90" #endif #include "material.f90" #include "lattice.f90" diff --git a/src/config.f90 b/src/config.f90 index 58b0d69a1..187c4880f 100644 --- a/src/config.f90 +++ b/src/config.f90 @@ -132,7 +132,7 @@ contains !-------------------------------------------------------------------------------------------------- recursive function read_materialConfig(fileName,cnt) result(fileContent) - character(len=*), intent(in) :: fileName + character(len=*), intent(in) :: fileName !< name of the material configuration file integer, intent(in), optional :: cnt !< recursion counter character(len=pStringLen), dimension(:), allocatable :: fileContent !< file content, separated per lines character(len=pStringLen), dimension(:), allocatable :: includedContent diff --git a/src/constitutive.f90 b/src/constitutive.f90 index 2c6831fc2..94e590ab3 100644 --- a/src/constitutive.f90 +++ b/src/constitutive.f90 @@ -126,8 +126,8 @@ module constitutive of end subroutine plastic_disloUCLA_LpAndItsTangent - module subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & - Mp, Temperature, volume, ip, el) + module subroutine plastic_nonlocal_LpAndItsTangent(Lp,dLp_dMp, & + Mp,Temperature,instance,of,ip,el) real(pReal), dimension(3,3), intent(out) :: & Lp !< plastic velocity gradient real(pReal), dimension(3,3,3,3), intent(out) :: & @@ -136,9 +136,10 @@ module constitutive real(pReal), dimension(3,3), intent(in) :: & Mp !< Mandel stress real(pReal), intent(in) :: & - Temperature, & - volume - integer, intent(in) :: & + Temperature + integer, intent(in) :: & + instance, & + of, & ip, & !< current integration point el !< current element number end subroutine plastic_nonlocal_LpAndItsTangent @@ -202,19 +203,21 @@ module constitutive of end subroutine plastic_disloUCLA_dotState - module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature, & - timestep,ip,el) - integer, intent(in) :: & - ip, & !< current integration point - el !< current element number - real(pReal), intent(in) :: & - Temperature, & !< temperature - timestep !< substepped crystallite time increment + module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & + instance,of,ip,el) real(pReal), dimension(3,3), intent(in) ::& Mp !< MandelStress real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & F, & !< deformation gradient Fp !< plastic deformation gradient + real(pReal), intent(in) :: & + Temperature, & !< temperature + timestep !< substepped crystallite time increment + integer, intent(in) :: & + instance, & + of, & + ip, & !< current integration point + el !< current element number end subroutine plastic_nonlocal_dotState @@ -232,13 +235,15 @@ module constitutive of end subroutine plastic_disloUCLA_dependentState - module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) - integer, intent(in) :: & - ip, & - el + module subroutine plastic_nonlocal_dependentState(F, Fp, instance, of, ip, el) real(pReal), dimension(3,3), intent(in) :: & F, & Fp + integer, intent(in) :: & + instance, & + of, & + ip, & + el end subroutine plastic_nonlocal_dependentState @@ -250,12 +255,14 @@ module constitutive of end subroutine plastic_kinehardening_deltaState - module subroutine plastic_nonlocal_deltaState(Mp,ip,el) - integer, intent(in) :: & - ip, & - el + module subroutine plastic_nonlocal_deltaState(Mp,instance,of,ip,el) real(pReal), dimension(3,3), intent(in) :: & Mp + integer, intent(in) :: & + instance, & + of, & + ip, & + el end subroutine plastic_nonlocal_deltaState @@ -268,8 +275,9 @@ module constitutive el !< element end function plastic_dislotwin_homogenizedC - module subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) + module subroutine plastic_nonlocal_updateCompatibility(orientation,instance,i,e) integer, intent(in) :: & + instance, & i, & e type(rotation), dimension(1,discretization_nIP,discretization_nElem), intent(in) :: & @@ -364,9 +372,7 @@ subroutine constitutive_init write(6,'(/,a)') ' <<<+- constitutive init -+>>>'; flush(6) - constitutive_plasticity_maxSizeDotState = 0 constitutive_source_maxSizeDotState = 0 - PhaseLoop2:do ph = 1,material_Nphase !-------------------------------------------------------------------------------------------------- ! partition and inititalize state @@ -377,12 +383,11 @@ subroutine constitutive_init sourceState(ph)%p(s)%state = sourceState(ph)%p(s)%partionedState0 end forall !-------------------------------------------------------------------------------------------------- -! determine max size of state and output - constitutive_plasticity_maxSizeDotState = max(constitutive_plasticity_maxSizeDotState, & - plasticState(ph)%sizeDotState) - constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & - maxval(sourceState(ph)%p(:)%sizeDotState)) +! determine max size of source state + constitutive_source_maxSizeDotState = max(constitutive_source_maxSizeDotState, & + maxval(sourceState(ph)%p%sizeDotState)) enddo PhaseLoop2 + constitutive_plasticity_maxSizeDotState = maxval(plasticState%sizeDotState) end subroutine constitutive_init @@ -426,20 +431,18 @@ subroutine constitutive_dependentState(F, Fp, ipc, ip, el) tme, & !< thermal member position instance, of - ho = material_homogenizationAt(el) + ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) + of = material_phasememberAt(ipc,ip,el) + instance = phase_plasticityInstance(material_phaseAt(ipc,el)) plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el))) case (PLASTICITY_DISLOTWIN_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_dislotwin_dependentState(temperature(ho)%p(tme),instance,of) case (PLASTICITY_DISLOUCLA_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_disloUCLA_dependentState(instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_dependentState (F,Fp,ip,el) + call plastic_nonlocal_dependentState (F,Fp,instance,of,ip,el) end select plasticityType end subroutine constitutive_dependentState @@ -477,7 +480,9 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, & ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) - Mp = matmul(matmul(transpose(Fi),Fi),S) + Mp = matmul(matmul(transpose(Fi),Fi),S) + of = material_phasememberAt(ipc,ip,el) + instance = phase_plasticityInstance(material_phaseAt(ipc,el)) plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el))) @@ -486,33 +491,22 @@ subroutine constitutive_LpAndItsTangents(Lp, dLp_dS, dLp_dFi, & dLp_dMp = 0.0_pReal case (PLASTICITY_ISOTROPIC_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - call plastic_isotropic_LpAndItsTangent (Lp,dLp_dMp,Mp,instance,of) + call plastic_isotropic_LpAndItsTangent (Lp,dLp_dMp,Mp,instance,of) case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - call plastic_phenopowerlaw_LpAndItsTangent (Lp,dLp_dMp,Mp,instance,of) + call plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of) case (PLASTICITY_KINEHARDENING_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - call plastic_kinehardening_LpAndItsTangent (Lp,dLp_dMp, Mp,instance,of) + call plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, & - temperature(ho)%p(tme),geometry_plastic_nonlocal_IPvolume0(ip,el),ip,el) + call plastic_nonlocal_LpAndItsTangent (Lp,dLp_dMp,Mp, temperature(ho)%p(tme),instance,of,ip,el) case (PLASTICITY_DISLOTWIN_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - call plastic_dislotwin_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of) + call plastic_dislotwin_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of) case (PLASTICITY_DISLOUCLA_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - call plastic_disloucla_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of) + call plastic_disloucla_LpAndItsTangent (Lp,dLp_dMp,Mp,temperature(ho)%p(tme),instance,of) end select plasticityType @@ -724,7 +718,7 @@ subroutine constitutive_collectDotState(S, FArray, Fi, FpArray, subdt, ipc, ip, real(pReal), intent(in) :: & subdt !< timestep real(pReal), intent(in), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem) :: & - FArray, & !< elastic deformation gradient + FArray, & !< elastic deformation gradient FpArray !< plastic deformation gradient real(pReal), intent(in), dimension(3,3) :: & Fi !< intermediate deformation gradient @@ -740,39 +734,31 @@ subroutine constitutive_collectDotState(S, FArray, Fi, FpArray, subdt, ipc, ip, ho = material_homogenizationAt(el) tme = thermalMapping(ho)%p(ip,el) + of = material_phasememberAt(ipc,ip,el) + instance = phase_plasticityInstance(material_phaseAt(ipc,el)) - Mp = matmul(matmul(transpose(Fi),Fi),S) + Mp = matmul(matmul(transpose(Fi),Fi),S) plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el))) case (PLASTICITY_ISOTROPIC_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_isotropic_dotState (Mp,instance,of) case (PLASTICITY_PHENOPOWERLAW_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_phenopowerlaw_dotState(Mp,instance,of) case (PLASTICITY_KINEHARDENING_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_kinehardening_dotState(Mp,instance,of) case (PLASTICITY_DISLOTWIN_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_dislotwin_dotState (Mp,temperature(ho)%p(tme),instance,of) case (PLASTICITY_DISLOUCLA_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_disloucla_dotState (Mp,temperature(ho)%p(tme),instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_dotState (Mp,FArray,FpArray,temperature(ho)%p(tme), & - subdt,ip,el) + call plastic_nonlocal_dotState (Mp,FArray,FpArray,temperature(ho)%p(tme),subdt, & + instance,of,ip,el) end select plasticityType SourceLoop: do i = 1, phase_Nsources(material_phaseAt(ipc,el)) @@ -783,13 +769,12 @@ subroutine constitutive_collectDotState(S, FArray, Fi, FpArray, subdt, ipc, ip, call source_damage_anisoBrittle_dotState (S, ipc, ip, el) !< correct stress? case (SOURCE_damage_isoDuctile_ID) sourceType - call source_damage_isoDuctile_dotState ( ipc, ip, el) + call source_damage_isoDuctile_dotState ( ipc, ip, el) case (SOURCE_damage_anisoDuctile_ID) sourceType - call source_damage_anisoDuctile_dotState ( ipc, ip, el) + call source_damage_anisoDuctile_dotState ( ipc, ip, el) case (SOURCE_thermal_externalheat_ID) sourceType - of = material_phasememberAt(ipc,ip,el) call source_thermal_externalheat_dotState(material_phaseAt(ipc,el),of) end select sourceType @@ -820,16 +805,16 @@ subroutine constitutive_collectDeltaState(S, Fe, Fi, ipc, ip, el) instance, of Mp = matmul(matmul(transpose(Fi),Fi),S) + of = material_phasememberAt(ipc,ip,el) + instance = phase_plasticityInstance(material_phaseAt(ipc,el)) plasticityType: select case (phase_plasticity(material_phaseAt(ipc,el))) case (PLASTICITY_KINEHARDENING_ID) plasticityType - of = material_phasememberAt(ipc,ip,el) - instance = phase_plasticityInstance(material_phaseAt(ipc,el)) call plastic_kinehardening_deltaState(Mp,instance,of) case (PLASTICITY_NONLOCAL_ID) plasticityType - call plastic_nonlocal_deltaState(Mp,ip,el) + call plastic_nonlocal_deltaState(Mp,instance,of,ip,el) end select plasticityType diff --git a/src/constitutive_plastic_disloUCLA.f90 b/src/constitutive_plastic_disloUCLA.f90 index 00a1b8e21..6be86f266 100644 --- a/src/constitutive_plastic_disloUCLA.f90 +++ b/src/constitutive_plastic_disloUCLA.f90 @@ -12,16 +12,12 @@ submodule(constitutive) plastic_disloUCLA type :: tParameters real(pReal) :: & - aTol_rho, & - D, & !< grain size - mu, & - D_0, & !< prefactor for self-diffusion coefficient - Q_cl !< activation energy for dislocation climb + D = 1.0_pReal, & !< grain size + mu = 1.0_pReal, & !< equivalent shear modulus + D_0 = 1.0_pReal, & !< prefactor for self-diffusion coefficient + Q_cl = 1.0_pReal !< activation energy for dislocation climb real(pReal), allocatable, dimension(:) :: & - rho_mob_0, & !< initial dislocation density - rho_dip_0, & !< initial dipole density b_sl, & !< magnitude of burgers vector [m] - nonSchmidCoeff, & D_a, & i_sl, & !< Adj. parameter for distance between 2 forest dislocations atomicVolume, & @@ -37,15 +33,13 @@ submodule(constitutive) plastic_disloUCLA omega !< attempt frequency for kink pair nucleation real(pReal), allocatable, dimension(:,:) :: & h_sl_sl, & !< slip resistance from slip activity - forestProjectionEdge + forestProjection real(pReal), allocatable, dimension(:,:,:) :: & - Schmid, & + P_sl, & nonSchmid_pos, & nonSchmid_neg integer :: & sum_N_sl !< total number of active slip system - integer, allocatable, dimension(:) :: & - N_sl !< number of active slip systems for each family character(len=pStringLen), allocatable, dimension(:) :: & output logical :: & @@ -88,11 +82,16 @@ module subroutine plastic_disloUCLA_init NipcMyPhase, & sizeState, sizeDotState, & startIndex, endIndex - + integer, dimension(:), allocatable :: & + N_sl + real(pReal),dimension(:), allocatable :: & + rho_mob_0, & !< initial dislocation density + rho_dip_0, & !< initial dipole density + a !< non-Schmid coefficients character(len=pStringLen) :: & extmsg = '' - write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_DISLOUCLA_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Cereceda et al., International Journal of Plasticity 78:242–256, 2016' write(6,'(a)') ' https://dx.doi.org/10.1016/j.ijplas.2015.09.002' @@ -106,7 +105,6 @@ module subroutine plastic_disloUCLA_init allocate(dotState(Ninstance)) allocate(dependentState(Ninstance)) - do p = 1, size(phase_plasticity) if (phase_plasticity(p) /= PLASTICITY_DISLOUCLA_ID) cycle associate(prm => param(phase_plasticityInstance(p)), & @@ -115,109 +113,96 @@ module subroutine plastic_disloUCLA_init dst => dependentState(phase_plasticityInstance(p)), & config => config_phase(p)) -!-------------------------------------------------------------------------------------------------- -! optional parameters that need to be defined + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + + ! This data is read in already in lattice prm%mu = lattice_mu(p) - prm%aTol_rho = config%getFloat('atol_rho') - - ! sanity checks - if (prm%aTol_rho <= 0.0_pReal) extmsg = trim(extmsg)//' atol_rho' - !-------------------------------------------------------------------------------------------------- ! slip related parameters - prm%N_sl = config%getInts('nslip',defaultVal=emptyIntArray) - prm%sum_N_sl = sum(prm%N_sl) + N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%sum_N_sl = sum(abs(N_sl)) slipActive: if (prm%sum_N_sl > 0) then - prm%Schmid = lattice_SchmidMatrix_slip(prm%N_sl,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) if(trim(config%getString('lattice_structure')) == 'bcc') then - prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& - defaultVal = emptyRealArray) - prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%N_sl,prm%nonSchmidCoeff,+1) - prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%N_sl,prm%nonSchmidCoeff,-1) + a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray) + prm%nonSchmid_pos = lattice_nonSchmidMatrix(N_sl,a,+1) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(N_sl,a,-1) else - allocate(prm%nonSchmidCoeff(0)) - prm%nonSchmid_pos = prm%Schmid - prm%nonSchmid_neg = prm%Schmid + prm%nonSchmid_pos = prm%P_sl + prm%nonSchmid_neg = prm%P_sl endif - prm%h_sl_sl = lattice_interaction_SlipBySlip(prm%N_sl, & - config%getFloats('interaction_slipslip'), & - config%getString('lattice_structure')) - prm%forestProjectionEdge = lattice_forestProjection_edge(prm%N_sl,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%forestProjectionEdge = transpose(prm%forestProjectionEdge) + prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), & + config%getString('lattice_structure')) + prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%forestProjection = transpose(prm%forestProjection) - prm%rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(prm%N_sl)) - prm%rho_dip_0 = config%getFloats('rhoedgedip0', requiredSize=size(prm%N_sl)) - prm%v0 = config%getFloats('v0', requiredSize=size(prm%N_sl)) - prm%b_sl = config%getFloats('slipburgers', requiredSize=size(prm%N_sl)) - prm%delta_F = config%getFloats('qedge', requiredSize=size(prm%N_sl)) + rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl)) + rho_dip_0 = config%getFloats('rhoedgedip0', requiredSize=size(N_sl)) + prm%v0 = config%getFloats('v0', requiredSize=size(N_sl)) + prm%b_sl = config%getFloats('slipburgers', requiredSize=size(N_sl)) + prm%delta_F = config%getFloats('qedge', requiredSize=size(N_sl)) - prm%i_sl = config%getFloats('clambdaslip', requiredSize=size(prm%N_sl)) - prm%tau_0 = config%getFloats('tau_peierls', requiredSize=size(prm%N_sl)) - prm%p = config%getFloats('p_slip', requiredSize=size(prm%N_sl), & - defaultVal=[(1.0_pReal,i=1,size(prm%N_sl))]) - prm%q = config%getFloats('q_slip', requiredSize=size(prm%N_sl), & - defaultVal=[(1.0_pReal,i=1,size(prm%N_sl))]) - prm%kink_height = config%getFloats('kink_height', requiredSize=size(prm%N_sl)) - prm%w = config%getFloats('kink_width', requiredSize=size(prm%N_sl)) - prm%omega = config%getFloats('omega', requiredSize=size(prm%N_sl)) - prm%B = config%getFloats('friction_coeff', requiredSize=size(prm%N_sl)) + prm%i_sl = config%getFloats('clambdaslip', requiredSize=size(N_sl)) + prm%tau_0 = config%getFloats('tau_peierls', requiredSize=size(N_sl)) + prm%p = config%getFloats('p_slip', requiredSize=size(N_sl), & + defaultVal=[(1.0_pReal,i=1,size(N_sl))]) + prm%q = config%getFloats('q_slip', requiredSize=size(N_sl), & + defaultVal=[(1.0_pReal,i=1,size(N_sl))]) + prm%kink_height = config%getFloats('kink_height', requiredSize=size(N_sl)) + prm%w = config%getFloats('kink_width', requiredSize=size(N_sl)) + prm%omega = config%getFloats('omega', requiredSize=size(N_sl)) + prm%B = config%getFloats('friction_coeff', requiredSize=size(N_sl)) - prm%D = config%getFloat('grainsize') - prm%D_0 = config%getFloat('d0') - prm%Q_cl = config%getFloat('qsd') - prm%atomicVolume = config%getFloat('catomicvolume') * prm%b_sl**3.0_pReal - prm%D_a = config%getFloat('cedgedipmindistance') * prm%b_sl - prm%dipoleformation = config%getFloat('dipoleformationfactor') > 0.0_pReal !should be on by default, ToDo: change to /key/-type key + prm%D = config%getFloat('grainsize') + prm%D_0 = config%getFloat('d0') + prm%Q_cl = config%getFloat('qsd') + prm%atomicVolume = config%getFloat('catomicvolume') * prm%b_sl**3.0_pReal + prm%D_a = config%getFloat('cedgedipmindistance') * prm%b_sl + prm%dipoleformation = config%getFloat('dipoleformationfactor') > 0.0_pReal !should be on by default, ToDo: change to /key/-type key ! expand: family => system - prm%rho_mob_0 = math_expand(prm%rho_mob_0, prm%N_sl) - prm%rho_dip_0 = math_expand(prm%rho_dip_0, prm%N_sl) - prm%q = math_expand(prm%q, prm%N_sl) - prm%p = math_expand(prm%p, prm%N_sl) - prm%delta_F = math_expand(prm%delta_F, prm%N_sl) - prm%b_sl = math_expand(prm%b_sl, prm%N_sl) - prm%kink_height = math_expand(prm%kink_height, prm%N_sl) - prm%w = math_expand(prm%w, prm%N_sl) - prm%omega = math_expand(prm%omega, prm%N_sl) - prm%tau_0 = math_expand(prm%tau_0, prm%N_sl) - prm%v0 = math_expand(prm%v0, prm%N_sl) - prm%B = math_expand(prm%B, prm%N_sl) - prm%i_sl = math_expand(prm%i_sl, prm%N_sl) - prm%atomicVolume = math_expand(prm%atomicVolume, prm%N_sl) - prm%D_a = math_expand(prm%D_a, prm%N_sl) - + rho_mob_0 = math_expand(rho_mob_0, N_sl) + rho_dip_0 = math_expand(rho_dip_0, N_sl) + prm%q = math_expand(prm%q, N_sl) + prm%p = math_expand(prm%p, N_sl) + prm%delta_F = math_expand(prm%delta_F, N_sl) + prm%b_sl = math_expand(prm%b_sl, N_sl) + prm%kink_height = math_expand(prm%kink_height, N_sl) + prm%w = math_expand(prm%w, N_sl) + prm%omega = math_expand(prm%omega, N_sl) + prm%tau_0 = math_expand(prm%tau_0, N_sl) + prm%v0 = math_expand(prm%v0, N_sl) + prm%B = math_expand(prm%B, N_sl) + prm%i_sl = math_expand(prm%i_sl, N_sl) + prm%atomicVolume = math_expand(prm%atomicVolume, N_sl) + prm%D_a = math_expand(prm%D_a, N_sl) ! sanity checks - if ( prm%D_0 <= 0.0_pReal) extmsg = trim(extmsg)//' D_0' - if ( prm%Q_cl <= 0.0_pReal) extmsg = trim(extmsg)//' Q_cl' - if (any(prm%rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedge0' - if (any(prm%rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedgedip0' - if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0' - if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' slipb_sl' - if (any(prm%delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' qedge' - if (any(prm%tau_0 < 0.0_pReal)) extmsg = trim(extmsg)//' tau_0' - if (any(prm%D_a <= 0.0_pReal)) extmsg = trim(extmsg)//' cedgedipmindistance or slipb_sl' - if (any(prm%atomicVolume <= 0.0_pReal)) extmsg = trim(extmsg)//' catomicvolume or slipb_sl' + if ( prm%D_0 <= 0.0_pReal) extmsg = trim(extmsg)//' D_0' + if ( prm%Q_cl <= 0.0_pReal) extmsg = trim(extmsg)//' Q_cl' + if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedge0' + if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoedgedip0' + if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0' + if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl' + if (any(prm%delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' qedge' + if (any(prm%tau_0 < 0.0_pReal)) extmsg = trim(extmsg)//' tau_0' + if (any(prm%D_a <= 0.0_pReal)) extmsg = trim(extmsg)//' cedgedipmindistance or b_sl' + if (any(prm%atomicVolume <= 0.0_pReal)) extmsg = trim(extmsg)//' catomicvolume or b_sl' else slipActive - allocate(prm%rho_mob_0(0)) - allocate(prm%rho_dip_0(0)) + rho_mob_0= emptyRealArray; rho_dip_0 = emptyRealArray + allocate(prm%b_sl,prm%D_a,prm%i_sl,prm%atomicVolume,prm%tau_0, & + prm%delta_F,prm%v0,prm%p,prm%q,prm%B,prm%kink_height,prm%w,prm%omega, & + source = emptyRealArray) + allocate(prm%forestProjection(0,0)) + allocate(prm%h_sl_sl (0,0)) endif slipActive -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOUCLA_label//')') - -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - !-------------------------------------------------------------------------------------------------- ! allocate state arrays NipcMyPhase = count(material_phaseAt == p) * discretization_nIP @@ -227,26 +212,27 @@ module subroutine plastic_disloUCLA_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- -! locally defined state aliases and initialization of state0 and aTolState +! state aliases and initialization startIndex = 1 endIndex = prm%sum_N_sl - stt%rho_mob=>plasticState(p)%state(startIndex:endIndex,:) - stt%rho_mob= spread(prm%rho_mob_0,2,NipcMyPhase) - dot%rho_mob=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho + stt%rho_mob => plasticState(p)%state(startIndex:endIndex,:) + stt%rho_mob = spread(rho_mob_0,2,NipcMyPhase) + dot%rho_mob => plasticState(p)%dotState(startIndex:endIndex,:) + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) + if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl - stt%rho_dip=>plasticState(p)%state(startIndex:endIndex,:) - stt%rho_dip= spread(prm%rho_dip_0,2,NipcMyPhase) - dot%rho_dip=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho + stt%rho_dip => plasticState(p)%state(startIndex:endIndex,:) + stt%rho_dip = spread(rho_dip_0,2,NipcMyPhase) + dot%rho_dip => plasticState(p)%dotState(startIndex:endIndex,:) + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl - stt%gamma_sl=>plasticState(p)%state(startIndex:endIndex,:) - dot%gamma_sl=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = 1.0e6_pReal ! Don't use for convergence check + stt%gamma_sl => plasticState(p)%state(startIndex:endIndex,:) + dot%gamma_sl => plasticState(p)%dotState(startIndex:endIndex,:) + plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal ! global alias plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) @@ -257,6 +243,10 @@ module subroutine plastic_disloUCLA_init end associate +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOUCLA_LABEL//')') + enddo end subroutine plastic_disloUCLA_init @@ -266,7 +256,7 @@ end subroutine plastic_disloUCLA_init !> @brief Calculate plastic velocity gradient and its tangent. !-------------------------------------------------------------------------------------------------- pure module subroutine plastic_disloUCLA_LpAndItsTangent(Lp,dLp_dMp, & - Mp,T,instance,of) + Mp,T,instance,of) real(pReal), dimension(3,3), intent(out) :: & Lp !< plastic velocity gradient real(pReal), dimension(3,3,3,3), intent(out) :: & @@ -293,11 +283,11 @@ pure module subroutine plastic_disloUCLA_LpAndItsTangent(Lp,dLp_dMp, & call kinetics(Mp,T,instance,of,dot_gamma_pos,dot_gamma_neg,ddot_gamma_dtau_pos,ddot_gamma_dtau_neg) do i = 1, prm%sum_N_sl - Lp = Lp + (dot_gamma_pos(i)+dot_gamma_neg(i))*prm%Schmid(1:3,1:3,i) + Lp = Lp + (dot_gamma_pos(i)+dot_gamma_neg(i))*prm%P_sl(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & - + ddot_gamma_dtau_pos(i) * prm%Schmid(k,l,i) * prm%nonSchmid_pos(m,n,i) & - + ddot_gamma_dtau_neg(i) * prm%Schmid(k,l,i) * prm%nonSchmid_neg(m,n,i) + + ddot_gamma_dtau_pos(i) * prm%P_sl(k,l,i) * prm%nonSchmid_pos(m,n,i) & + + ddot_gamma_dtau_neg(i) * prm%P_sl(k,l,i) * prm%nonSchmid_neg(m,n,i) enddo end associate @@ -311,9 +301,9 @@ end subroutine plastic_disloUCLA_LpAndItsTangent module subroutine plastic_disloUCLA_dotState(Mp,T,instance,of) real(pReal), dimension(3,3), intent(in) :: & - Mp !< Mandel stress + Mp !< Mandel stress real(pReal), intent(in) :: & - T !< temperature + T !< temperature integer, intent(in) :: & instance, & of @@ -343,14 +333,14 @@ module subroutine plastic_disloUCLA_dotState(Mp,T,instance,of) dot_rho_dip_climb = 0.0_pReal else where dip_distance = math_clip(3.0_pReal*prm%mu*prm%b_sl/(16.0_pReal*PI*abs(tau_pos)), & - prm%D_a, & ! lower limit - dst%Lambda_sl(:,of)) ! upper limit + prm%D_a, & ! lower limit + dst%Lambda_sl(:,of)) ! upper limit dot_rho_dip_formation = merge(2.0_pReal*dip_distance* stt%rho_mob(:,of)*abs(dot%gamma_sl(:,of))/prm%b_sl, & ! ToDo: ignore region of spontaneous annihilation 0.0_pReal, & prm%dipoleformation) v_cl = (3.0_pReal*prm%mu*VacancyDiffusion*prm%atomicVolume/(2.0_pReal*pi*kB*T)) & * (1.0_pReal/(dip_distance+prm%D_a)) - dot_rho_dip_climb = (4.0_pReal*v_cl*stt%rho_dip(:,of))/(dip_distance-prm%D_a) ! ToDo: Discuss with Franz: Stress dependency? + dot_rho_dip_climb = (4.0_pReal*v_cl*stt%rho_dip(:,of))/(dip_distance-prm%D_a) ! ToDo: Discuss with Franz: Stress dependency? end where dot%rho_mob(:,of) = abs(dot%gamma_sl(:,of))/(prm%b_sl*dst%Lambda_sl(:,of)) & ! multiplication @@ -379,8 +369,7 @@ module subroutine plastic_disloUCLA_dependentState(instance,of) associate(prm => param(instance), stt => state(instance),dst => dependentState(instance)) - dislocationSpacing = sqrt(matmul(prm%forestProjectionEdge, & - stt%rho_mob(:,of)+stt%rho_dip(:,of))) + dislocationSpacing = sqrt(matmul(prm%forestProjection,stt%rho_mob(:,of)+stt%rho_dip(:,of))) dst%threshold_stress(:,of) = prm%mu*prm%b_sl & * sqrt(matmul(prm%h_sl_sl,stt%rho_mob(:,of)+stt%rho_dip(:,of))) @@ -411,7 +400,7 @@ module subroutine plastic_disloUCLA_results(instance,group) if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip,'rho_dip',& 'dislocation dipole density''1/m²') case('shear_rate_slip') ! should be gamma - if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& ! this is not dot!! + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_sl,'dot_gamma_sl',& ! this is not dot!! 'plastic shear','1') case('mfp_slip') !ToDo: should be Lambda if(prm%sum_N_sl>0) call results_writeDataset(group,dst%Lambda_sl,'Lambda_sl',& @@ -464,8 +453,8 @@ pure subroutine kinetics(Mp,T,instance,of, & associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do j = 1, prm%sum_N_sl - tau_pos(j) = math_mul33xx33(Mp,prm%nonSchmid_pos(1:3,1:3,j)) - tau_neg(j) = math_mul33xx33(Mp,prm%nonSchmid_neg(1:3,1:3,j)) + tau_pos(j) = math_tensordot(Mp,prm%nonSchmid_pos(1:3,1:3,j)) + tau_neg(j) = math_tensordot(Mp,prm%nonSchmid_neg(1:3,1:3,j)) enddo diff --git a/src/constitutive_plastic_dislotwin.f90 b/src/constitutive_plastic_dislotwin.f90 index 116abb1cb..d36e08846 100644 --- a/src/constitutive_plastic_dislotwin.f90 +++ b/src/constitutive_plastic_dislotwin.f90 @@ -14,36 +14,31 @@ submodule(constitutive) plastic_dislotwin type :: tParameters real(pReal) :: & - mu, & - nu, & - D0, & !< prefactor for self-diffusion coefficient - Qsd, & !< activation energy for dislocation climb - omega, & !< frequency factor for dislocation climb - D, & !< grain size - p_sb, & !< p-exponent in shear band velocity - q_sb, & !< q-exponent in shear band velocity - CEdgeDipMinDistance, & !< - i_tw, & !< - tau_0, & !< strength due to elements in solid solution - L_tw, & !< Length of twin nuclei in Burgers vectors - L_tr, & !< Length of trans nuclei in Burgers vectors - xc_twin, & !< critical distance for formation of twin nucleus - xc_trans, & !< critical distance for formation of trans nucleus - V_cs, & !< cross slip volume - sbResistance, & !< value for shearband resistance (might become an internal state variable at some point) - sbVelocity, & !< value for shearband velocity_0 - sbQedge, & !< activation energy for shear bands - SFE_0K, & !< stacking fault energy at zero K - dSFE_dT, & !< temperature dependance of stacking fault energy - aTol_rho, & !< absolute tolerance for integration of dislocation density - aTol_f_tw, & !< absolute tolerance for integration of twin volume fraction - aTol_f_tr, & !< absolute tolerance for integration of trans volume fraction - gamma_fcc_hex, & !< Free energy difference between austensite and martensite - i_tr, & !< - h !< Stack height of hex nucleus + mu = 1.0_pReal, & !< equivalent shear modulus + nu = 1.0_pReal, & !< equivalent shear Poisson's ratio + D0 = 1.0_pReal, & !< prefactor for self-diffusion coefficient + Qsd = 1.0_pReal, & !< activation energy for dislocation climb + omega = 1.0_pReal, & !< frequency factor for dislocation climb + D = 1.0_pReal, & !< grain size + p_sb = 1.0_pReal, & !< p-exponent in shear band velocity + q_sb = 1.0_pReal, & !< q-exponent in shear band velocity + CEdgeDipMinDistance = 1.0_pReal, & !< + i_tw = 1.0_pReal, & !< + tau_0 = 1.0_pReal, & !< strength due to elements in solid solution + L_tw = 1.0_pReal, & !< Length of twin nuclei in Burgers vectors + L_tr = 1.0_pReal, & !< Length of trans nuclei in Burgers vectors + xc_twin = 1.0_pReal, & !< critical distance for formation of twin nucleus + xc_trans = 1.0_pReal, & !< critical distance for formation of trans nucleus + V_cs = 1.0_pReal, & !< cross slip volume + sbResistance = 1.0_pReal, & !< value for shearband resistance + sbVelocity = 1.0_pReal, & !< value for shearband velocity_0 + E_sb = 1.0_pReal, & !< activation energy for shear bands + SFE_0K = 1.0_pReal, & !< stacking fault energy at zero K + dSFE_dT = 1.0_pReal, & !< temperature dependence of stacking fault energy + gamma_fcc_hex = 1.0_pReal, & !< Free energy difference between austensite and martensite + i_tr = 1.0_pReal, & !< + h = 1.0_pReal !< Stack height of hex nucleus real(pReal), allocatable, dimension(:) :: & - rho_mob_0, & !< initial unipolar dislocation density per slip system - rho_dip_0, & !< initial dipole dislocation density per slip system b_sl, & !< absolute length of burgers vector [m] for each slip system b_tw, & !< absolute length of burgers vector [m] for each twin system b_tr, & !< absolute length of burgers vector [m] for each transformation system @@ -53,7 +48,6 @@ submodule(constitutive) plastic_dislotwin dot_N_0_tr, & !< trans nucleation rate [1/m³s] for each trans system t_tw, & !< twin thickness [m] for each twin system CLambdaSlip, & !< Adj. parameter for distance between 2 forest dislocations for each slip system - atomicVolume, & t_tr, & !< martensite lamellar thickness [m] for each trans system and instance p, & !< p-exponent in glide velocity q, & !< q-exponent in glide velocity @@ -71,19 +65,15 @@ submodule(constitutive) plastic_dislotwin forestProjection, & C66 real(pReal), allocatable, dimension(:,:,:) :: & - P_tr, & P_sl, & P_tw, & + P_tr, & C66_tw, & C66_tr integer :: & sum_N_sl, & !< total number of active slip system sum_N_tw, & !< total number of active twin system sum_N_tr !< total number of active transformation system - integer, allocatable, dimension(:) :: & - N_sl, & !< number of active slip systems for each family - N_tw, & !< number of active twin systems for each family - N_tr !< number of active transformation systems for each family integer, allocatable, dimension(:,:) :: & fcc_twinNucleationSlipPair ! ToDo: Better name? Is also use for trans character(len=pStringLen), allocatable, dimension(:) :: & @@ -140,11 +130,15 @@ module subroutine plastic_dislotwin_init NipcMyPhase, & sizeState, sizeDotState, & startIndex, endIndex - + integer, dimension(:), allocatable :: & + N_sl, N_tw, N_tr + real(pReal), allocatable, dimension(:) :: & + rho_mob_0, & !< initial unipolar dislocation density per slip system + rho_dip_0 !< initial dipole dislocation density per slip system character(len=pStringLen) :: & extmsg = '' - write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_DISLOTWIN_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Ma and Roters, Acta Materialia 52(12):3603–3612, 2004' write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2004.04.012' @@ -173,83 +167,76 @@ module subroutine plastic_dislotwin_init dst => dependentState(phase_plasticityInstance(p)), & config => config_phase(p)) - prm%aTol_rho = config%getFloat('atol_rho', defaultVal=0.0_pReal) - prm%aTol_f_tw = config%getFloat('atol_twinfrac', defaultVal=0.0_pReal) - prm%aTol_f_tr = config%getFloat('atol_transfrac', defaultVal=0.0_pReal) + prm%output = config%getStrings('(output)', defaultVal=emptyStringArray) ! This data is read in already in lattice - prm%mu = lattice_mu(p) - prm%nu = lattice_nu(p) + prm%mu = lattice_mu(p) + prm%nu = lattice_nu(p) prm%C66 = lattice_C66(1:6,1:6,p) !-------------------------------------------------------------------------------------------------- ! slip related parameters - prm%N_sl = config%getInts('nslip',defaultVal=emptyIntArray) - prm%sum_N_sl = sum(prm%N_sl) + N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%sum_N_sl = sum(abs(N_sl)) slipActive: if (prm%sum_N_sl > 0) then - prm%P_sl = lattice_SchmidMatrix_slip(prm%N_sl,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%h_sl_sl = lattice_interaction_SlipBySlip(prm%N_sl, & - config%getFloats('interaction_slipslip'), & + prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%h_sl_sl = lattice_interaction_SlipBySlip(N_sl,config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) - prm%forestProjection = lattice_forestProjection_edge(prm%N_sl,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%forestProjection = transpose(prm%forestProjection) + prm%forestProjection = lattice_forestProjection_edge(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%forestProjection = transpose(prm%forestProjection) - prm%n0_sl = lattice_slip_normal(prm%N_sl,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) + prm%n0_sl = lattice_slip_normal(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) prm%fccTwinTransNucleation = merge(.true., .false., lattice_structure(p) == lattice_FCC_ID) & - .and. (prm%N_sl(1) == 12) - if(prm%fccTwinTransNucleation) & - prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR + .and. (N_sl(1) == 12) + if(prm%fccTwinTransNucleation) prm%fcc_twinNucleationSlipPair = lattice_FCC_TWINNUCLEATIONSLIPPAIR - prm%rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(prm%N_sl)) - prm%rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(prm%N_sl)) - prm%v0 = config%getFloats('v0', requiredSize=size(prm%N_sl)) - prm%b_sl = config%getFloats('slipburgers',requiredSize=size(prm%N_sl)) - prm%Delta_F = config%getFloats('qedge', requiredSize=size(prm%N_sl)) - prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(prm%N_sl)) - prm%p = config%getFloats('p_slip', requiredSize=size(prm%N_sl)) - prm%q = config%getFloats('q_slip', requiredSize=size(prm%N_sl)) - prm%B = config%getFloats('b', requiredSize=size(prm%N_sl), & - defaultVal=[(0.0_pReal, i=1,size(prm%N_sl))]) + rho_mob_0 = config%getFloats('rhoedge0', requiredSize=size(N_sl)) + rho_dip_0 = config%getFloats('rhoedgedip0',requiredSize=size(N_sl)) + prm%v0 = config%getFloats('v0', requiredSize=size(N_sl)) + prm%b_sl = config%getFloats('slipburgers',requiredSize=size(N_sl)) + prm%Delta_F = config%getFloats('qedge', requiredSize=size(N_sl)) + prm%CLambdaSlip = config%getFloats('clambdaslip',requiredSize=size(N_sl)) + prm%p = config%getFloats('p_slip', requiredSize=size(N_sl)) + prm%q = config%getFloats('q_slip', requiredSize=size(N_sl)) + prm%B = config%getFloats('b', requiredSize=size(N_sl), & + defaultVal=[(0.0_pReal, i=1,size(N_sl))]) prm%tau_0 = config%getFloat('solidsolutionstrength') prm%CEdgeDipMinDistance = config%getFloat('cedgedipmindistance') prm%D0 = config%getFloat('d0') prm%Qsd = config%getFloat('qsd') - prm%atomicVolume = config%getFloat('catomicvolume') * prm%b_sl**3.0_pReal prm%ExtendedDislocations = config%keyExists('/extend_dislocations/') if (prm%ExtendedDislocations) then - prm%SFE_0K = config%getFloat('sfe_0k') - prm%dSFE_dT = config%getFloat('dsfe_dt') + prm%SFE_0K = config%getFloat('sfe_0k') + prm%dSFE_dT = config%getFloat('dsfe_dt') endif - ! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex) - !@details: Refer: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 - prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) & - * merge(12.0_pReal, & - 8.0_pReal, & - lattice_structure(p) == lattice_FCC_ID .or. lattice_structure(p) == lattice_HEX_ID) + prm%dipoleformation = .not. config%keyExists('/nodipoleformation/') + ! multiplication factor according to crystal structure (nearest neighbors bcc vs fcc/hex) + ! details: Argon & Moffat, Acta Metallurgica, Vol. 29, pg 293 to 299, 1981 + prm%omega = config%getFloat('omega', defaultVal = 1000.0_pReal) & + * merge(12.0_pReal,8.0_pReal,any(lattice_structure(p) == [lattice_FCC_ID,lattice_HEX_ID])) ! expand: family => system - prm%rho_mob_0 = math_expand(prm%rho_mob_0, prm%N_sl) - prm%rho_dip_0 = math_expand(prm%rho_dip_0, prm%N_sl) - prm%v0 = math_expand(prm%v0, prm%N_sl) - prm%b_sl = math_expand(prm%b_sl, prm%N_sl) - prm%Delta_F = math_expand(prm%Delta_F, prm%N_sl) - prm%CLambdaSlip = math_expand(prm%CLambdaSlip, prm%N_sl) - prm%p = math_expand(prm%p, prm%N_sl) - prm%q = math_expand(prm%q, prm%N_sl) - prm%B = math_expand(prm%B, prm%N_sl) - prm%atomicVolume = math_expand(prm%atomicVolume,prm%N_sl) + rho_mob_0 = math_expand(rho_mob_0, N_sl) + rho_dip_0 = math_expand(rho_dip_0, N_sl) + prm%v0 = math_expand(prm%v0, N_sl) + prm%b_sl = math_expand(prm%b_sl, N_sl) + prm%Delta_F = math_expand(prm%Delta_F, N_sl) + prm%CLambdaSlip = math_expand(prm%CLambdaSlip, N_sl) + prm%p = math_expand(prm%p, N_sl) + prm%q = math_expand(prm%q, N_sl) + prm%B = math_expand(prm%B, N_sl) ! sanity checks if ( prm%D0 <= 0.0_pReal) extmsg = trim(extmsg)//' D0' if ( prm%Qsd <= 0.0_pReal) extmsg = trim(extmsg)//' Qsd' - if (any(prm%rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0' - if (any(prm%rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0' + if (any(rho_mob_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_mob_0' + if (any(rho_dip_0 < 0.0_pReal)) extmsg = trim(extmsg)//' rho_dip_0' if (any(prm%v0 < 0.0_pReal)) extmsg = trim(extmsg)//' v0' if (any(prm%b_sl <= 0.0_pReal)) extmsg = trim(extmsg)//' b_sl' if (any(prm%Delta_F <= 0.0_pReal)) extmsg = trim(extmsg)//' Delta_F' @@ -257,158 +244,152 @@ module subroutine plastic_dislotwin_init if (any(prm%B < 0.0_pReal)) extmsg = trim(extmsg)//' B' if (any(prm%p<=0.0_pReal .or. prm%p>1.0_pReal)) extmsg = trim(extmsg)//' p' if (any(prm%q< 1.0_pReal .or. prm%q>2.0_pReal)) extmsg = trim(extmsg)//' q' - else slipActive - allocate(prm%b_sl(0)) + rho_mob_0 = emptyRealArray; rho_dip_0 = emptyRealArray + allocate(prm%b_sl,prm%Delta_F,prm%v0,prm%CLambdaSlip,prm%p,prm%q,prm%B,source=emptyRealArray) + allocate(prm%forestProjection(0,0),prm%h_sl_sl(0,0)) endif slipActive !-------------------------------------------------------------------------------------------------- ! twin related parameters - prm%N_tw = config%getInts('ntwin', defaultVal=emptyIntArray) - prm%sum_N_tw = sum(prm%N_tw) - if (prm%sum_N_tw > 0) then - prm%P_tw = lattice_SchmidMatrix_twin(prm%N_tw,config%getString('lattice_structure'),& + N_tw = config%getInts('ntwin', defaultVal=emptyIntArray) + prm%sum_N_tw = sum(abs(N_tw)) + twinActive: if (prm%sum_N_tw > 0) then + prm%P_tw = lattice_SchmidMatrix_twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%h_tw_tw = lattice_interaction_TwinByTwin(prm%N_tw,& + prm%h_tw_tw = lattice_interaction_TwinByTwin(N_tw,& config%getFloats('interaction_twintwin'), & config%getString('lattice_structure')) - prm%b_tw = config%getFloats('twinburgers', requiredSize=size(prm%N_tw)) - prm%t_tw = config%getFloats('twinsize', requiredSize=size(prm%N_tw)) - prm%r = config%getFloats('r_twin', requiredSize=size(prm%N_tw)) + prm%b_tw = config%getFloats('twinburgers', requiredSize=size(N_tw)) + prm%t_tw = config%getFloats('twinsize', requiredSize=size(N_tw)) + prm%r = config%getFloats('r_twin', requiredSize=size(N_tw)) prm%xc_twin = config%getFloat('xc_twin') prm%L_tw = config%getFloat('l0_twin') prm%i_tw = config%getFloat('cmfptwin') - prm%gamma_char= lattice_characteristicShear_Twin(prm%N_tw,config%getString('lattice_structure'),& + prm%gamma_char= lattice_characteristicShear_Twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%C66_tw = lattice_C66_twin(prm%N_tw,prm%C66,config%getString('lattice_structure'),& + prm%C66_tw = lattice_C66_twin(N_tw,prm%C66,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) if (.not. prm%fccTwinTransNucleation) then prm%dot_N_0_tw = config%getFloats('ndot0_twin') - prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,prm%N_tw) + prm%dot_N_0_tw = math_expand(prm%dot_N_0_tw,N_tw) endif ! expand: family => system - prm%b_tw = math_expand(prm%b_tw,prm%N_tw) - prm%t_tw = math_expand(prm%t_tw,prm%N_tw) - prm%r = math_expand(prm%r,prm%N_tw) + prm%b_tw = math_expand(prm%b_tw,N_tw) + prm%t_tw = math_expand(prm%t_tw,N_tw) + prm%r = math_expand(prm%r,N_tw) - else - allocate(prm%gamma_char(0)) - allocate(prm%t_tw (0)) - allocate(prm%b_tw (0)) - allocate(prm%r (0)) - allocate(prm%h_tw_tw (0,0)) - endif + ! sanity checks + if ( prm%xc_twin < 0.0_pReal) extmsg = trim(extmsg)//' xc_twin' + if ( prm%L_tw < 0.0_pReal) extmsg = trim(extmsg)//' L_tw' + if ( prm%i_tw < 0.0_pReal) extmsg = trim(extmsg)//' i_tw' + if (any(prm%b_tw < 0.0_pReal)) extmsg = trim(extmsg)//' b_tw' + if (any(prm%t_tw < 0.0_pReal)) extmsg = trim(extmsg)//' t_tw' + if (any(prm%r < 0.0_pReal)) extmsg = trim(extmsg)//' r' + if (.not. prm%fccTwinTransNucleation) then + if (any(prm%dot_N_0_tw < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tw' + endif + else twinActive + allocate(prm%gamma_char,prm%b_tw,prm%dot_N_0_tw,prm%t_tw,prm%r,source=emptyRealArray) + allocate(prm%h_tw_tw(0,0)) + endif twinActive !-------------------------------------------------------------------------------------------------- ! transformation related parameters - prm%N_tr = config%getInts('ntrans', defaultVal=emptyIntArray) - prm%sum_N_tr = sum(prm%N_tr) - if (prm%sum_N_tr > 0) then + N_tr = config%getInts('ntrans', defaultVal=emptyIntArray) + prm%sum_N_tr = sum(abs(N_tr)) + transActive: if (prm%sum_N_tr > 0) then prm%b_tr = config%getFloats('transburgers') - prm%b_tr = math_expand(prm%b_tr,prm%N_tr) + prm%b_tr = math_expand(prm%b_tr,N_tr) prm%h = config%getFloat('transstackheight', defaultVal=0.0_pReal) ! ToDo: How to handle that??? - prm%i_tr = config%getFloat('cmfptrans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? + prm%i_tr = config%getFloat('cmfptrans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%gamma_fcc_hex = config%getFloat('deltag') - prm%xc_trans = config%getFloat('xc_trans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? + prm%xc_trans = config%getFloat('xc_trans', defaultVal=0.0_pReal) ! ToDo: How to handle that??? prm%L_tr = config%getFloat('l0_trans') - prm%h_tr_tr = lattice_interaction_TransByTrans(prm%N_tr,& - config%getFloats('interaction_transtrans'), & - config%getString('lattice_structure')) + prm%h_tr_tr = lattice_interaction_TransByTrans(N_tr,config%getFloats('interaction_transtrans'), & + config%getString('lattice_structure')) - prm%C66_tr = lattice_C66_trans(prm%N_tr,prm%C66, & - config%getString('trans_lattice_structure'), & - 0.0_pReal, & - config%getFloat('a_bcc', defaultVal=0.0_pReal), & - config%getFloat('a_fcc', defaultVal=0.0_pReal)) + prm%C66_tr = lattice_C66_trans(N_tr,prm%C66,config%getString('trans_lattice_structure'), & + 0.0_pReal, & + config%getFloat('a_bcc', defaultVal=0.0_pReal), & + config%getFloat('a_fcc', defaultVal=0.0_pReal)) - prm%P_tr = lattice_SchmidMatrix_trans(prm%N_tr, & - config%getString('trans_lattice_structure'), & - 0.0_pReal, & - config%getFloat('a_bcc', defaultVal=0.0_pReal), & - config%getFloat('a_fcc', defaultVal=0.0_pReal)) + prm%P_tr = lattice_SchmidMatrix_trans(N_tr,config%getString('trans_lattice_structure'), & + 0.0_pReal, & + config%getFloat('a_bcc', defaultVal=0.0_pReal), & + config%getFloat('a_fcc', defaultVal=0.0_pReal)) if (lattice_structure(p) /= lattice_FCC_ID) then - prm%dot_N_0_tr = config%getFloats('ndot0_trans') - prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,prm%N_tr) + prm%dot_N_0_tr = config%getFloats('ndot0_trans') + prm%dot_N_0_tr = math_expand(prm%dot_N_0_tr,N_tr) endif prm%t_tr = config%getFloats('lamellarsize') - prm%t_tr = math_expand(prm%t_tr,prm%N_tr) + prm%t_tr = math_expand(prm%t_tr,N_tr) prm%s = config%getFloats('s_trans',defaultVal=[0.0_pReal]) - prm%s = math_expand(prm%s,prm%N_tr) - else - allocate(prm%t_tr (0)) - allocate(prm%b_tr (0)) - allocate(prm%s (0)) + prm%s = math_expand(prm%s,N_tr) + + ! sanity checks + if ( prm%xc_trans < 0.0_pReal) extmsg = trim(extmsg)//' xc_trans' + if ( prm%L_tr < 0.0_pReal) extmsg = trim(extmsg)//' L_tr' + if ( prm%i_tr < 0.0_pReal) extmsg = trim(extmsg)//' i_tr' + if (any(prm%t_tr < 0.0_pReal)) extmsg = trim(extmsg)//' t_tr' + if (any(prm%s < 0.0_pReal)) extmsg = trim(extmsg)//' s' + if (lattice_structure(p) /= lattice_FCC_ID) then + if (any(prm%dot_N_0_tr < 0.0_pReal)) extmsg = trim(extmsg)//' dot_N_0_tr' + endif + else transActive + allocate(prm%s,prm%b_tr,prm%t_tr,prm%dot_N_0_tr,source=emptyRealArray) allocate(prm%h_tr_tr(0,0)) - endif - - if (sum(prm%N_tw) > 0 .or. prm%sum_N_tr > 0) then - prm%SFE_0K = config%getFloat('sfe_0k') - prm%dSFE_dT = config%getFloat('dsfe_dt') - prm%V_cs = config%getFloat('vcrossslip') - endif - - if (prm%sum_N_sl > 0 .and. prm%sum_N_tw > 0) then - prm%h_sl_tw = lattice_interaction_SlipByTwin(prm%N_sl,prm%N_tw,& - config%getFloats('interaction_sliptwin'), & - config%getString('lattice_structure')) - if (prm%fccTwinTransNucleation .and. prm%sum_N_tw > 12) write(6,*) 'mist' ! ToDo: implement better test. The model will fail also if N_tw is [6,6] - endif - - if (prm%sum_N_sl > 0 .and. prm%sum_N_tr > 0) then - prm%h_sl_tr = lattice_interaction_SlipByTrans(prm%N_sl,prm%N_tr,& - config%getFloats('interaction_sliptrans'), & - config%getString('lattice_structure')) - if (prm%fccTwinTransNucleation .and. prm%sum_N_tr > 12) write(6,*) 'mist' ! ToDo: implement better test. The model will fail also if N_tr is [6,6] - endif + endif transActive !-------------------------------------------------------------------------------------------------- ! shearband related parameters prm%sbVelocity = config%getFloat('shearbandvelocity',defaultVal=0.0_pReal) if (prm%sbVelocity > 0.0_pReal) then prm%sbResistance = config%getFloat('shearbandresistance') - prm%sbQedge = config%getFloat('qedgepersbsystem') + prm%E_sb = config%getFloat('qedgepersbsystem') prm%p_sb = config%getFloat('p_shearband') prm%q_sb = config%getFloat('q_shearband') ! sanity checks if (prm%sbResistance < 0.0_pReal) extmsg = trim(extmsg)//' shearbandresistance' - if (prm%sbQedge < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem' + if (prm%E_sb < 0.0_pReal) extmsg = trim(extmsg)//' qedgepersbsystem' if (prm%p_sb <= 0.0_pReal) extmsg = trim(extmsg)//' p_shearband' if (prm%q_sb <= 0.0_pReal) extmsg = trim(extmsg)//' q_shearband' endif - prm%D = config%getFloat('grainsize') +!-------------------------------------------------------------------------------------------------- +! parameters required for several mechanisms and their interactions + if(prm%sum_N_sl + prm%sum_N_tw + prm%sum_N_tw > 0) & + prm%D = config%getFloat('grainsize') - if (config%keyExists('dipoleformationfactor')) call IO_error(1,ext_msg='use /nodipoleformation/') - prm%dipoleformation = .not. config%keyExists('/nodipoleformation/') + twinOrSlipActive: if (prm%sum_N_tw + prm%sum_N_tr > 0) then + prm%SFE_0K = config%getFloat('sfe_0k') + prm%dSFE_dT = config%getFloat('dsfe_dt') + prm%V_cs = config%getFloat('vcrossslip') + endif twinOrSlipActive + slipAndTwinActive: if (prm%sum_N_sl * prm%sum_N_tw > 0) then + prm%h_sl_tw = lattice_interaction_SlipByTwin(N_sl,N_tw,& + config%getFloats('interaction_sliptwin'), & + config%getString('lattice_structure')) + if (prm%fccTwinTransNucleation .and. size(N_tw) /= 1) extmsg = trim(extmsg)//' interaction_sliptwin' + endif slipAndTwinActive - !if (Ndot0PerTwinFamily(f,p) < 0.0_pReal) & - ! call IO_error(211,el=p,ext_msg='dot_N_0_tw ('//PLASTICITY_DISLOTWIN_label//')') - - if (any(prm%atomicVolume <= 0.0_pReal)) & - call IO_error(211,el=p,ext_msg='cAtomicVolume ('//PLASTICITY_DISLOTWIN_label//')') - if (prm%sum_N_tw > 0) then - if (prm%aTol_rho <= 0.0_pReal) & - call IO_error(211,el=p,ext_msg='aTol_rho ('//PLASTICITY_DISLOTWIN_label//')') - if (prm%aTol_f_tw <= 0.0_pReal) & - call IO_error(211,el=p,ext_msg='aTol_f_tw ('//PLASTICITY_DISLOTWIN_label//')') - endif - if (prm%sum_N_tr > 0) then - if (prm%aTol_f_tr <= 0.0_pReal) & - call IO_error(211,el=p,ext_msg='aTol_f_tr ('//PLASTICITY_DISLOTWIN_label//')') - endif - - prm%output = config%getStrings('(output)', defaultVal=emptyStringArray) + slipAndTransActive: if (prm%sum_N_sl * prm%sum_N_tr > 0) then + prm%h_sl_tr = lattice_interaction_SlipByTrans(N_sl,N_tr,& + config%getFloats('interaction_sliptrans'), & + config%getString('lattice_structure')) + if (prm%fccTwinTransNucleation .and. size(N_tr) /= 1) extmsg = trim(extmsg)//' interaction_sliptrans' + endif slipAndTransActive !-------------------------------------------------------------------------------------------------- ! allocate state arrays @@ -421,26 +402,27 @@ module subroutine plastic_dislotwin_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- -! locally defined state aliases and initialization of state0 and aTolState +! locally defined state aliases and initialization of state0 and atol startIndex = 1 endIndex = prm%sum_N_sl stt%rho_mob=>plasticState(p)%state(startIndex:endIndex,:) - stt%rho_mob= spread(prm%rho_mob_0,2,NipcMyPhase) + stt%rho_mob= spread(rho_mob_0,2,NipcMyPhase) dot%rho_mob=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) + if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_rho' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%rho_dip=>plasticState(p)%state(startIndex:endIndex,:) - stt%rho_dip= spread(prm%rho_dip_0,2,NipcMyPhase) + stt%rho_dip= spread(rho_dip_0,2,NipcMyPhase) dot%rho_dip=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_rho + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_rho',defaultVal=1.0_pReal) startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_sl stt%gamma_sl=>plasticState(p)%state(startIndex:endIndex,:) dot%gamma_sl=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = 1.0e6_pReal !ToDo: better make optional parameter + plasticState(p)%atol(startIndex:endIndex) = 1.0e-2_pReal ! global alias plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) @@ -448,13 +430,15 @@ module subroutine plastic_dislotwin_init endIndex = endIndex + prm%sum_N_tw stt%f_tw=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tw=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_f_tw + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_twin',defaultVal=1.0e-7_pReal) + if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_twin' startIndex = endIndex + 1 endIndex = endIndex + prm%sum_N_tr stt%f_tr=>plasticState(p)%state(startIndex:endIndex,:) dot%f_tr=>plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTol_f_tr + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('f_trans',defaultVal=1.0e-6_pReal) + if (any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' f_trans' allocate(dst%Lambda_sl (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) allocate(dst%tau_pass (prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) @@ -469,11 +453,14 @@ module subroutine plastic_dislotwin_init allocate(dst%tau_r_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) allocate(dst%V_tr (prm%sum_N_tr,NipcMyPhase),source=0.0_pReal) - - plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally + plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally end associate +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_DISLOTWIN_LABEL//')') + enddo end subroutine plastic_dislotwin_init @@ -544,7 +531,6 @@ module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of) real(pReal):: dot_gamma_sb real(pReal), dimension(3,3) :: eigVectors, P_sb real(pReal), dimension(3) :: eigValues - logical :: error real(pReal), dimension(3,6), parameter :: & sb_sComposition = & reshape(real([& @@ -588,13 +574,13 @@ module subroutine plastic_dislotwin_LpAndItsTangent(Lp,dLp_dMp,Mp,T,instance,of) shearBandingContribution: if(dNeq0(prm%sbVelocity)) then - BoltzmannRatio = prm%sbQedge/(kB*T) - call math_eigenValuesVectorsSym(Mp,eigValues,eigVectors,error) + BoltzmannRatio = prm%E_sb/(kB*T) + call math_eigh33(Mp,eigValues,eigVectors) ! is Mp symmetric by design? do i = 1,6 P_sb = 0.5_pReal * math_outer(matmul(eigVectors,sb_sComposition(1:3,i)),& matmul(eigVectors,sb_mComposition(1:3,i))) - tau = math_mul33xx33(Mp,P_sb) + tau = math_tensordot(Mp,P_sb) significantShearBandStress: if (abs(tau) > tol_math_check) then StressRatio_p = (abs(tau)/prm%sbResistance)**prm%p_sb @@ -650,7 +636,6 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of) integer :: i real(pReal) :: & f_unrotated, & - VacancyDiffusion, & rho_dip_distance, & v_cl, & !< climb velocity Gamma, & !< stacking fault energy @@ -673,7 +658,6 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of) f_unrotated = 1.0_pReal & - sum(stt%f_tw(1:prm%sum_N_tw,of)) & - sum(stt%f_tr(1:prm%sum_N_tr,of)) - VacancyDiffusion = prm%D0*exp(-prm%Qsd/(kB*T)) call kinetics_slip(Mp,T,instance,of,dot_gamma_sl) dot%gamma_sl(:,of) = abs(dot_gamma_sl) @@ -681,7 +665,7 @@ module subroutine plastic_dislotwin_dotState(Mp,T,instance,of) rho_dip_distance_min = prm%CEdgeDipMinDistance*prm%b_sl slipState: do i = 1, prm%sum_N_sl - tau = math_mul33xx33(Mp,prm%P_sl(1:3,1:3,i)) + tau = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) significantSlipStress: if (dEq0(tau)) then dot_rho_dip_formation(i) = 0.0_pReal @@ -774,9 +758,9 @@ module subroutine plastic_dislotwin_dependentState(T,instance,of) Gamma = prm%SFE_0K + prm%dSFE_dT * T !* rescaled volume fraction for topology - f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,of)/prm%t_tw ! this is per system ... - f_over_t_tr = sumf_trans/prm%t_tr ! but this not - ! ToDo ...Physically correct, but naming could be adjusted + f_over_t_tw = stt%f_tw(1:prm%sum_N_tw,of)/prm%t_tw ! this is per system ... + f_over_t_tr = sumf_trans/prm%t_tr ! but this not + ! ToDo ...Physically correct, but naming could be adjusted inv_lambda_sl_sl = sqrt(matmul(prm%forestProjection, & stt%rho_mob(:,of)+stt%rho_dip(:,of)))/prm%CLambdaSlip @@ -791,7 +775,7 @@ module subroutine plastic_dislotwin_dependentState(T,instance,of) inv_lambda_tr_tr = matmul(prm%h_tr_tr,f_over_t_tr)/(1.0_pReal-sumf_trans) - if ((prm%sum_N_tw > 0) .or. (prm%sum_N_tr > 0)) then ! ToDo: better logic needed here + if ((prm%sum_N_tw > 0) .or. (prm%sum_N_tr > 0)) then ! ToDo: better logic needed here dst%Lambda_sl(:,of) = prm%D & / (1.0_pReal+prm%D*(inv_lambda_sl_sl + inv_lambda_sl_tw + inv_lambda_sl_tr)) else @@ -818,10 +802,10 @@ module subroutine plastic_dislotwin_dependentState(T,instance,of) dst%V_tr(:,of) = (PI/4.0_pReal)*prm%t_tr*dst%Lambda_tr(:,of)**2.0_pReal - x0 = prm%mu*prm%b_tw**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip and is the same for twin and trans + x0 = prm%mu*prm%b_tw**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip and is the same for twin and trans dst%tau_r_tw(:,of) = prm%mu*prm%b_tw/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_twin)+cos(pi/3.0_pReal)/x0) - x0 = prm%mu*prm%b_tr**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip + x0 = prm%mu*prm%b_tr**2.0_pReal/(Gamma*8.0_pReal*PI)*(2.0_pReal+prm%nu)/(1.0_pReal-prm%nu) ! ToDo: In the paper, this is the burgers vector for slip dst%tau_r_tr(:,of) = prm%mu*prm%b_tr/(2.0_pReal*PI)*(1.0_pReal/(x0+prm%xc_trans)+cos(pi/3.0_pReal)/x0) end associate @@ -922,7 +906,7 @@ pure subroutine kinetics_slip(Mp,T,instance,of, & associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_sl - tau(i) = math_mul33xx33(Mp,prm%P_sl(1:3,1:3,i)) + tau(i) = math_tensordot(Mp,prm%P_sl(1:3,1:3,i)) enddo tau_eff = abs(tau)-dst%tau_pass(:,of) @@ -993,7 +977,7 @@ pure subroutine kinetics_twin(Mp,T,dot_gamma_sl,instance,of,& associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tw - tau(i) = math_mul33xx33(Mp,prm%P_tw(1:3,1:3,i)) + tau(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) @@ -1061,7 +1045,7 @@ pure subroutine kinetics_trans(Mp,T,dot_gamma_sl,instance,of,& associate(prm => param(instance), stt => state(instance), dst => dependentState(instance)) do i = 1, prm%sum_N_tr - tau(i) = math_mul33xx33(Mp,prm%P_tr(1:3,1:3,i)) + tau(i) = math_tensordot(Mp,prm%P_tr(1:3,1:3,i)) isFCC: if (prm%fccTwinTransNucleation) then s1=prm%fcc_twinNucleationSlipPair(1,i) s2=prm%fcc_twinNucleationSlipPair(2,i) diff --git a/src/constitutive_plastic_isotropic.f90 b/src/constitutive_plastic_isotropic.f90 index beed2112a..94fc9817d 100644 --- a/src/constitutive_plastic_isotropic.f90 +++ b/src/constitutive_plastic_isotropic.f90 @@ -12,7 +12,6 @@ submodule(constitutive) plastic_isotropic type :: tParameters real(pReal) :: & M, & !< Taylor factor - xi_0, & !< initial critical stress dot_gamma_0, & !< reference strain rate n, & !< stress exponent h0, & @@ -22,9 +21,7 @@ submodule(constitutive) plastic_isotropic c_1, & c_4, & c_3, & - c_2, & - aTol_xi, & - aTol_gamma + c_2 integer :: & of_debug = 0 logical :: & @@ -59,11 +56,12 @@ module subroutine plastic_isotropic_init p, & NipcMyPhase, & sizeState, sizeDotState - + real(pReal) :: & + xi_0 !< initial critical stress character(len=pStringLen) :: & extmsg = '' - write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_ISOTROPIC_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Maiti and Eisenlohr, Scripta Materialia 145:37–40, 2018' write(6,'(a)') ' https://doi.org/10.1016/j.scriptamat.2017.09.047' @@ -83,48 +81,35 @@ module subroutine plastic_isotropic_init stt => state(phase_plasticityInstance(p)), & config => config_phase(p)) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + #ifdef DEBUG if (p==material_phaseAt(debug_g,debug_e)) & prm%of_debug = material_phasememberAt(debug_g,debug_i,debug_e) #endif - prm%xi_0 = config%getFloat('tau0') - prm%xi_inf = config%getFloat('tausat') - prm%dot_gamma_0 = config%getFloat('gdot0') - prm%n = config%getFloat('n') - prm%h0 = config%getFloat('h0') - prm%M = config%getFloat('m') - prm%h_ln = config%getFloat('h0_slopelnrate', defaultVal=0.0_pReal) - prm%c_1 = config%getFloat('tausat_sinhfita',defaultVal=0.0_pReal) - prm%c_4 = config%getFloat('tausat_sinhfitb',defaultVal=0.0_pReal) - prm%c_3 = config%getFloat('tausat_sinhfitc',defaultVal=0.0_pReal) - prm%c_2 = config%getFloat('tausat_sinhfitd',defaultVal=0.0_pReal) - prm%a = config%getFloat('a') - prm%aTol_xi = config%getFloat('atol_flowstress',defaultVal=1.0_pReal) - prm%aTol_gamma = config%getFloat('atol_shear', defaultVal=1.0e-6_pReal) + xi_0 = config%getFloat('tau0') + prm%xi_inf = config%getFloat('tausat') + prm%dot_gamma_0 = config%getFloat('gdot0') + prm%n = config%getFloat('n') + prm%h0 = config%getFloat('h0') + prm%M = config%getFloat('m') + prm%h_ln = config%getFloat('h0_slopelnrate', defaultVal=0.0_pReal) + prm%c_1 = config%getFloat('tausat_sinhfita',defaultVal=0.0_pReal) + prm%c_4 = config%getFloat('tausat_sinhfitb',defaultVal=0.0_pReal) + prm%c_3 = config%getFloat('tausat_sinhfitc',defaultVal=0.0_pReal) + prm%c_2 = config%getFloat('tausat_sinhfitd',defaultVal=0.0_pReal) + prm%a = config%getFloat('a') - prm%dilatation = config%keyExists('/dilatation/') + prm%dilatation = config%keyExists('/dilatation/') !-------------------------------------------------------------------------------------------------- ! sanity checks - extmsg = '' - if (prm%aTol_gamma <= 0.0_pReal) extmsg = trim(extmsg)//' aTol_gamma' - if (prm%xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0' - if (prm%dot_gamma_0 <= 0.0_pReal) extmsg = trim(extmsg)//' dot_gamma_0' - if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n' - if (prm%a <= 0.0_pReal) extmsg = trim(extmsg)//' a' - if (prm%M <= 0.0_pReal) extmsg = trim(extmsg)//' m' - if (prm%aTol_xi <= 0.0_pReal) extmsg = trim(extmsg)//' atol_xi' - if (prm%aTol_gamma <= 0.0_pReal) extmsg = trim(extmsg)//' atol_shear' - -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_ISOTROPIC_label//')') - -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + if (xi_0 < 0.0_pReal) extmsg = trim(extmsg)//' xi_0' + if (prm%dot_gamma_0 <= 0.0_pReal) extmsg = trim(extmsg)//' dot_gamma_0' + if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n' + if (prm%a <= 0.0_pReal) extmsg = trim(extmsg)//' a' + if (prm%M <= 0.0_pReal) extmsg = trim(extmsg)//' M' !-------------------------------------------------------------------------------------------------- ! allocate state arrays @@ -135,15 +120,17 @@ module subroutine plastic_isotropic_init call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- -! locally defined state aliases and initialization of state0 and aTolState +! state aliases and initialization stt%xi => plasticState(p)%state (1,:) - stt%xi = prm%xi_0 + stt%xi = xi_0 dot%xi => plasticState(p)%dotState(1,:) - plasticState(p)%aTolState(1) = prm%aTol_xi + plasticState(p)%atol(1) = config%getFloat('atol_xi',defaultVal=1.0_pReal) + if (plasticState(p)%atol(1) < 0.0_pReal) extmsg = trim(extmsg)//' atol_xi' stt%gamma => plasticState(p)%state (2,:) dot%gamma => plasticState(p)%dotState(2,:) - plasticState(p)%aTolState(2) = prm%aTol_gamma + plasticState(p)%atol(2) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal) + if (plasticState(p)%atol(2) < 0.0_pReal) extmsg = trim(extmsg)//' atol_gamma' ! global alias plasticState(p)%slipRate => plasticState(p)%dotState(2:2,:) @@ -151,6 +138,10 @@ module subroutine plastic_isotropic_init end associate +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_ISOTROPIC_LABEL//')') + enddo end subroutine plastic_isotropic_init @@ -184,7 +175,7 @@ module subroutine plastic_isotropic_LpAndItsTangent(Lp,dLp_dMp,Mp,instance,of) associate(prm => param(instance), stt => state(instance)) Mp_dev = math_deviatoric33(Mp) - squarenorm_Mp_dev = math_mul33xx33(Mp_dev,Mp_dev) + squarenorm_Mp_dev = math_tensordot(Mp_dev,Mp_dev) norm_Mp_dev = sqrt(squarenorm_Mp_dev) if (norm_Mp_dev > 0.0_pReal) then @@ -222,14 +213,14 @@ end subroutine plastic_isotropic_LpAndItsTangent !-------------------------------------------------------------------------------------------------- module subroutine plastic_isotropic_LiAndItsTangent(Li,dLi_dMi,Mi,instance,of) - real(pReal), dimension(3,3), intent(out) :: & + real(pReal), dimension(3,3), intent(out) :: & Li !< inleastic velocity gradient real(pReal), dimension(3,3,3,3), intent(out) :: & dLi_dMi !< derivative of Li with respect to Mandel stress - real(pReal), dimension(3,3), intent(in) :: & + real(pReal), dimension(3,3), intent(in) :: & Mi !< Mandel stress - integer, intent(in) :: & + integer, intent(in) :: & instance, & of @@ -288,9 +279,9 @@ module subroutine plastic_isotropic_dotState(Mp,instance,of) associate(prm => param(instance), stt => state(instance), dot => dotState(instance)) if (prm%dilatation) then - norm_Mp = sqrt(math_mul33xx33(Mp,Mp)) + norm_Mp = sqrt(math_tensordot(Mp,Mp)) else - norm_Mp = sqrt(math_mul33xx33(math_deviatoric33(Mp),math_deviatoric33(Mp))) + norm_Mp = sqrt(math_tensordot(math_deviatoric33(Mp),math_deviatoric33(Mp))) endif dot_gamma = prm%dot_gamma_0 * (sqrt(1.5_pReal) * norm_Mp /(prm%M*stt%xi(of))) **prm%n diff --git a/src/constitutive_plastic_kinehardening.f90 b/src/constitutive_plastic_kinehardening.f90 index 65751989c..5843f5b5e 100644 --- a/src/constitutive_plastic_kinehardening.f90 +++ b/src/constitutive_plastic_kinehardening.f90 @@ -9,30 +9,26 @@ submodule(constitutive) plastic_kinehardening type :: tParameters real(pReal) :: & - gdot0, & !< reference shear strain rate for slip - n, & !< stress exponent for slip - aTolResistance, & - aTolShear + gdot0 = 1.0_pReal, & !< reference shear strain rate for slip + n = 1.0_pReal !< stress exponent for slip real(pReal), allocatable, dimension(:) :: & - crss0, & !< initial critical shear stress for slip theta0, & !< initial hardening rate of forward stress for each slip theta1, & !< asymptotic hardening rate of forward stress for each slip theta0_b, & !< initial hardening rate of back stress for each slip theta1_b, & !< asymptotic hardening rate of back stress for each slip tau1, & - tau1_b, & - nonSchmidCoeff + tau1_b real(pReal), allocatable, dimension(:,:) :: & interaction_slipslip !< slip resistance from slip activity real(pReal), allocatable, dimension(:,:,:) :: & - Schmid, & + P, & nonSchmid_pos, & nonSchmid_neg integer :: & - totalNslip, & !< total number of active slip system + sum_N_sl, & !< total number of active slip system of_debug = 0 - integer, allocatable, dimension(:) :: & - Nslip !< number of active slip systems for each family + logical :: & + nonSchmidActive = .false. character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -70,11 +66,15 @@ module subroutine plastic_kinehardening_init NipcMyPhase, & sizeState, sizeDeltaState, sizeDotState, & startIndex, endIndex - + integer, dimension(:), allocatable :: & + N_sl + real(pReal), dimension(:), allocatable :: & + xi_0, & !< initial resistance against plastic flow + a !< non-Schmid coefficients character(len=pStringLen) :: & extmsg = '' - write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_KINEHARDENING_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_plasticity == PLASTICITY_KINEHARDENING_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & @@ -93,130 +93,117 @@ module subroutine plastic_kinehardening_init stt => state(phase_plasticityInstance(p)),& config => config_phase(p)) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + #ifdef DEBUG if (p==material_phaseAt(debug_g,debug_e)) then prm%of_debug = material_phasememberAt(debug_g,debug_i,debug_e) endif #endif -!-------------------------------------------------------------------------------------------------- -! optional parameters that need to be defined - prm%aTolResistance = config%getFloat('atol_resistance',defaultVal=1.0_pReal) - prm%aTolShear = config%getFloat('atol_shear', defaultVal=1.0e-6_pReal) - - ! sanity checks - if (prm%aTolResistance <= 0.0_pReal) extmsg = trim(extmsg)//' aTolresistance' - if (prm%aTolShear <= 0.0_pReal) extmsg = trim(extmsg)//' aTolShear' - !-------------------------------------------------------------------------------------------------- ! slip related parameters - prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray) - prm%totalNslip = sum(prm%Nslip) - slipActive: if (prm%totalNslip > 0) then - prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) + N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%sum_N_sl = sum(abs(N_sl)) + slipActive: if (prm%sum_N_sl > 0) then + prm%P = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) if(trim(config%getString('lattice_structure')) == 'bcc') then - prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& - defaultVal = emptyRealArray) - prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1) - prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1) + a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray) + if(size(a) > 0) prm%nonSchmidActive = .true. + prm%nonSchmid_pos = lattice_nonSchmidMatrix(N_sl,a,+1) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(N_sl,a,-1) else - prm%nonSchmid_pos = prm%Schmid - prm%nonSchmid_neg = prm%Schmid + prm%nonSchmid_pos = prm%P + prm%nonSchmid_neg = prm%P endif - prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(prm%Nslip, & + prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(N_sl, & config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) - prm%crss0 = config%getFloats('crss0', requiredSize=size(prm%Nslip)) - prm%tau1 = config%getFloats('tau1', requiredSize=size(prm%Nslip)) - prm%tau1_b = config%getFloats('tau1_b', requiredSize=size(prm%Nslip)) - prm%theta0 = config%getFloats('theta0', requiredSize=size(prm%Nslip)) - prm%theta1 = config%getFloats('theta1', requiredSize=size(prm%Nslip)) - prm%theta0_b = config%getFloats('theta0_b', requiredSize=size(prm%Nslip)) - prm%theta1_b = config%getFloats('theta1_b', requiredSize=size(prm%Nslip)) + xi_0 = config%getFloats('crss0', requiredSize=size(N_sl)) + prm%tau1 = config%getFloats('tau1', requiredSize=size(N_sl)) + prm%tau1_b = config%getFloats('tau1_b', requiredSize=size(N_sl)) + prm%theta0 = config%getFloats('theta0', requiredSize=size(N_sl)) + prm%theta1 = config%getFloats('theta1', requiredSize=size(N_sl)) + prm%theta0_b = config%getFloats('theta0_b', requiredSize=size(N_sl)) + prm%theta1_b = config%getFloats('theta1_b', requiredSize=size(N_sl)) prm%gdot0 = config%getFloat('gdot0') prm%n = config%getFloat('n_slip') ! expand: family => system - prm%crss0 = math_expand(prm%crss0, prm%Nslip) - prm%tau1 = math_expand(prm%tau1, prm%Nslip) - prm%tau1_b = math_expand(prm%tau1_b, prm%Nslip) - prm%theta0 = math_expand(prm%theta0, prm%Nslip) - prm%theta1 = math_expand(prm%theta1, prm%Nslip) - prm%theta0_b = math_expand(prm%theta0_b,prm%Nslip) - prm%theta1_b = math_expand(prm%theta1_b,prm%Nslip) - - + xi_0 = math_expand(xi_0, N_sl) + prm%tau1 = math_expand(prm%tau1, N_sl) + prm%tau1_b = math_expand(prm%tau1_b, N_sl) + prm%theta0 = math_expand(prm%theta0, N_sl) + prm%theta1 = math_expand(prm%theta1, N_sl) + prm%theta0_b = math_expand(prm%theta0_b,N_sl) + prm%theta1_b = math_expand(prm%theta1_b,N_sl) !-------------------------------------------------------------------------------------------------- ! sanity checks if ( prm%gdot0 <= 0.0_pReal) extmsg = trim(extmsg)//' gdot0' if ( prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' n_slip' - if (any(prm%crss0 <= 0.0_pReal)) extmsg = trim(extmsg)//' crss0' + if (any(xi_0 <= 0.0_pReal)) extmsg = trim(extmsg)//' crss0' if (any(prm%tau1 <= 0.0_pReal)) extmsg = trim(extmsg)//' tau1' if (any(prm%tau1_b <= 0.0_pReal)) extmsg = trim(extmsg)//' tau1_b' !ToDo: Any sensible checks for theta? - + else slipActive + xi_0 = emptyRealArray + allocate(prm%tau1,prm%tau1_b,prm%theta0,prm%theta1,prm%theta0_b,prm%theta1_b,source=emptyRealArray) + allocate(prm%interaction_SlipSlip(0,0)) endif slipActive -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_KINEHARDENING_label//')') - -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - !-------------------------------------------------------------------------------------------------- ! allocate state arrays NipcMyPhase = count(material_phaseAt == p) * discretization_nIP - sizeDotState = size(['crss ','crss_back', 'accshear ']) * prm%totalNslip - sizeDeltaState = size(['sense ', 'chi0 ', 'gamma0' ]) * prm%totalNslip + sizeDotState = size(['crss ','crss_back', 'accshear ']) * prm%sum_N_sl + sizeDeltaState = size(['sense ', 'chi0 ', 'gamma0' ]) * prm%sum_N_sl sizeState = sizeDotState + sizeDeltaState call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState) !-------------------------------------------------------------------------------------------------- -! locally defined state aliases and initialization of state0 and aTolState +! state aliases and initialization startIndex = 1 - endIndex = prm%totalNslip + endIndex = prm%sum_N_sl stt%crss => plasticState(p)%state (startIndex:endIndex,:) - stt%crss = spread(prm%crss0, 2, NipcMyPhase) + stt%crss = spread(xi_0, 2, NipcMyPhase) dot%crss => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_xi' startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%crss_back => plasticState(p)%state (startIndex:endIndex,:) dot%crss_back => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal) startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%accshear => plasticState(p)%state (startIndex:endIndex,:) dot%accshear => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolShear + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_gamma' ! global alias - plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) + plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) o = plasticState(p)%offsetDeltaState startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%sense => plasticState(p)%state (startIndex :endIndex ,:) dlt%sense => plasticState(p)%deltaState(startIndex-o:endIndex-o,:) startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%chi0 => plasticState(p)%state (startIndex :endIndex ,:) dlt%chi0 => plasticState(p)%deltaState(startIndex-o:endIndex-o,:) startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%gamma0 => plasticState(p)%state (startIndex :endIndex ,:) dlt%gamma0 => plasticState(p)%deltaState(startIndex-o:endIndex-o,:) @@ -224,8 +211,13 @@ module subroutine plastic_kinehardening_init end associate +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_KINEHARDENING_LABEL//')') + enddo + end subroutine plastic_kinehardening_init @@ -247,7 +239,7 @@ pure module subroutine plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,insta integer :: & i,k,l,m,n - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & gdot_pos,gdot_neg, & dgdot_dtau_pos,dgdot_dtau_neg @@ -258,12 +250,12 @@ pure module subroutine plastic_kinehardening_LpAndItsTangent(Lp,dLp_dMp,Mp,insta call kinetics(Mp,instance,of,gdot_pos,gdot_neg,dgdot_dtau_pos,dgdot_dtau_neg) - do i = 1, prm%totalNslip - Lp = Lp + (gdot_pos(i)+gdot_neg(i))*prm%Schmid(1:3,1:3,i) + do i = 1, prm%sum_N_sl + Lp = Lp + (gdot_pos(i)+gdot_neg(i))*prm%P(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & - + dgdot_dtau_pos(i) * prm%Schmid(k,l,i) * prm%nonSchmid_pos(m,n,i) & - + dgdot_dtau_neg(i) * prm%Schmid(k,l,i) * prm%nonSchmid_neg(m,n,i) + + dgdot_dtau_pos(i) * prm%P(k,l,i) * prm%nonSchmid_pos(m,n,i) & + + dgdot_dtau_neg(i) * prm%P(k,l,i) * prm%nonSchmid_neg(m,n,i) enddo end associate @@ -284,7 +276,7 @@ module subroutine plastic_kinehardening_dotState(Mp,instance,of) real(pReal) :: & sumGamma - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & gdot_pos,gdot_neg @@ -324,7 +316,7 @@ module subroutine plastic_kinehardening_deltaState(Mp,instance,of) instance, & of - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & gdot_pos,gdot_neg, & sense @@ -375,23 +367,23 @@ module subroutine plastic_kinehardening_results(instance,group) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) case('resistance') - if(prm%totalNslip>0) call results_writeDataset(group,stt%crss,'xi_sl', & - 'resistance against plastic slip','Pa') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%crss,'xi_sl', & + 'resistance against plastic slip','Pa') case('backstress') ! ToDo: should be 'tau_back' - if(prm%totalNslip>0) call results_writeDataset(group,stt%crss_back,'tau_back', & - 'back stress against plastic slip','Pa') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%crss_back,'tau_back', & + 'back stress against plastic slip','Pa') case ('sense') - if(prm%totalNslip>0) call results_writeDataset(group,stt%sense,'sense_of_shear', & - 'tbd','1') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%sense,'sense_of_shear', & + 'tbd','1') case ('chi0') - if(prm%totalNslip>0) call results_writeDataset(group,stt%chi0,'chi0', & - 'tbd','Pa') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%chi0,'chi0', & + 'tbd','Pa') case ('gamma0') - if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma0,'gamma0', & - 'tbd','1') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma0,'gamma0', & + 'tbd','1') case ('accumulatedshear') - if(prm%totalNslip>0) call results_writeDataset(group,stt%accshear,'gamma_sl', & - 'plastic shear','1') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%accshear,'gamma_sl', & + 'plastic shear','1') end select enddo outputsLoop end associate @@ -415,31 +407,28 @@ pure subroutine kinetics(Mp,instance,of, & instance, & of - real(pReal), intent(out), dimension(param(instance)%totalNslip) :: & + real(pReal), intent(out), dimension(param(instance)%sum_N_sl) :: & gdot_pos, & gdot_neg - real(pReal), intent(out), optional, dimension(param(instance)%totalNslip) :: & + real(pReal), intent(out), optional, dimension(param(instance)%sum_N_sl) :: & dgdot_dtau_pos, & dgdot_dtau_neg - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & tau_pos, & tau_neg integer :: i - logical :: nonSchmidActive associate(prm => param(instance), stt => state(instance)) - nonSchmidActive = size(prm%nonSchmidCoeff) > 0 - - do i = 1, prm%totalNslip - tau_pos(i) = math_mul33xx33(Mp,prm%nonSchmid_pos(1:3,1:3,i)) - stt%crss_back(i,of) - tau_neg(i) = merge(math_mul33xx33(Mp,prm%nonSchmid_neg(1:3,1:3,i)) - stt%crss_back(i,of), & - 0.0_pReal, nonSchmidActive) + do i = 1, prm%sum_N_sl + tau_pos(i) = math_tensordot(Mp,prm%nonSchmid_pos(1:3,1:3,i)) - stt%crss_back(i,of) + tau_neg(i) = merge(math_tensordot(Mp,prm%nonSchmid_neg(1:3,1:3,i)) - stt%crss_back(i,of), & + 0.0_pReal, prm%nonSchmidActive) enddo where(dNeq0(tau_pos)) - gdot_pos = prm%gdot0 * merge(0.5_pReal,1.0_pReal, nonSchmidActive) & ! 1/2 if non-Schmid active + gdot_pos = prm%gdot0 * merge(0.5_pReal,1.0_pReal, prm%nonSchmidActive) & ! 1/2 if non-Schmid active * sign(abs(tau_pos/stt%crss(:,of))**prm%n, tau_pos) else where gdot_pos = 0.0_pReal diff --git a/src/constitutive_plastic_none.f90 b/src/constitutive_plastic_none.f90 index 4840c9c09..7ff1c76f7 100644 --- a/src/constitutive_plastic_none.f90 +++ b/src/constitutive_plastic_none.f90 @@ -19,7 +19,7 @@ module subroutine plastic_none_init p, & NipcMyPhase - write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_NONE_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_NONE_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_plasticity == PLASTICITY_NONE_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & diff --git a/src/constitutive_plastic_nonlocal.f90 b/src/constitutive_plastic_nonlocal.f90 index 47db19385..58218ac00 100644 --- a/src/constitutive_plastic_nonlocal.f90 +++ b/src/constitutive_plastic_nonlocal.f90 @@ -13,7 +13,7 @@ submodule(constitutive) plastic_nonlocal IPareaNormal => geometry_plastic_nonlocal_IPareaNormal0 real(pReal), parameter :: & - KB = 1.38e-23_pReal !< Physical parameter, Boltzmann constant in J/Kelvin + kB = 1.38e-23_pReal !< Boltzmann constant in J/Kelvin ! storage order of dislocation types integer, dimension(8), parameter :: & @@ -34,27 +34,38 @@ submodule(constitutive) plastic_nonlocal mob_scr_pos = 3, & !< mobile screw positive mob_scr_neg = 4 !< mobile screw positive - ! BEGIN DEPRECATES + ! BEGIN DEPRECATED integer, dimension(:,:,:), allocatable :: & iRhoU, & !< state indices for unblocked density - iRhoB, & !< state indices for blocked density - iRhoD, & !< state indices for dipole density iV, & !< state indices for dislcation velocities iD !< state indices for stable dipole height - integer, dimension(:), allocatable :: & - totalNslip !< total number of active slip systems for each instance !END DEPRECATED real(pReal), dimension(:,:,:,:,:,:), allocatable :: & compatibility !< slip system compatibility between me and my neighbors + type :: tInitialParameters !< container type for internal constitutive parameters + real(pReal) :: & + rhoSglScatter, & !< standard deviation of scatter in initial dislocation density + rhoSglRandom, & + rhoSglRandomBinning + real(pReal), dimension(:), allocatable :: & + rhoSglEdgePos0, & !< initial edge_pos dislocation density + rhoSglEdgeNeg0, & !< initial edge_neg dislocation density + rhoSglScrewPos0, & !< initial screw_pos dislocation density + rhoSglScrewNeg0, & !< initial screw_neg dislocation density + rhoDipEdge0, & !< initial edge dipole dislocation density + rhoDipScrew0 !< initial screw dipole dislocation density + integer, dimension(:) ,allocatable :: & + N_sl + end type tInitialParameters + type :: tParameters !< container type for internal constitutive parameters real(pReal) :: & atomicVolume, & !< atomic volume Dsd0, & !< prefactor for self-diffusion coefficient selfDiffusionEnergy, & !< activation enthalpy for diffusion - aTolRho, & !< absolute tolerance for dislocation density in state integration - aTolShear, & !< absolute tolerance for accumulated shear in state integration + atol_rho, & !< absolute tolerance for dislocation density in state integration significantRho, & !< density considered significant significantN, & !< number of dislocations considered significant doublekinkwidth, & !< width of a doubkle kink in multiples of the burgers vector length b @@ -65,31 +76,22 @@ submodule(constitutive) plastic_nonlocal q, & !< parameter for kinetic law (Kocks,Argon,Ashby) viscosity, & !< viscosity for dislocation glide in Pa s fattack, & !< attack frequency in Hz - rhoSglScatter, & !< standard deviation of scatter in initial dislocation density surfaceTransmissivity, & !< transmissivity at free surface grainboundaryTransmissivity, & !< transmissivity at grain boundary (identified by different texture) CFLfactor, & !< safety factor for CFL flux condition fEdgeMultiplication, & !< factor that determines how much edge dislocations contribute to multiplication (0...1) - rhoSglRandom, & - rhoSglRandomBinning, & linetensionEffect, & edgeJogFactor, & mu, & nu - real(pReal), dimension(:), allocatable :: & + real(pReal), dimension(:), allocatable :: & minDipoleHeight_edge, & !< minimum stable edge dipole height minDipoleHeight_screw, & !< minimum stable screw dipole height peierlsstress_edge, & peierlsstress_screw, & - rhoSglEdgePos0, & !< initial edge_pos dislocation density - rhoSglEdgeNeg0, & !< initial edge_neg dislocation density - rhoSglScrewPos0, & !< initial screw_pos dislocation density - rhoSglScrewNeg0, & !< initial screw_neg dislocation density - rhoDipEdge0, & !< initial edge dipole dislocation density - rhoDipScrew0,& !< initial screw dipole dislocation density lambda0, & !< mean free path prefactor for each burgers !< absolute length of burgers vector [m] - real(pReal), dimension(:,:), allocatable :: & + real(pReal), dimension(:,:), allocatable :: & slip_normal, & slip_direction, & slip_transverse, & @@ -98,23 +100,19 @@ submodule(constitutive) plastic_nonlocal interactionSlipSlip ,& !< coefficients for slip-slip interaction forestProjection_Edge, & !< matrix of forest projections of edge dislocations forestProjection_Screw !< matrix of forest projections of screw dislocations - real(pReal), dimension(:), allocatable :: & - nonSchmidCoeff real(pReal), dimension(:,:,:), allocatable :: & Schmid, & !< Schmid contribution nonSchmid_pos, & nonSchmid_neg !< combined projection of Schmid and non-Schmid contributions to the resolved shear stress (only for screws) integer :: & - totalNslip - integer, dimension(:) ,allocatable :: & - Nslip,& + sum_N_sl + integer, dimension(:), allocatable :: & colinearSystem !< colinear system to the active slip system (only valid for fcc!) - character(len=pStringLen), allocatable, dimension(:) :: & + character(len=pStringLen), dimension(:), allocatable :: & output logical :: & - shortRangeStressCorrection, & !< flag indicating the use of the short range stress correction by a excess density gradient term - probabilisticMultiplication - + shortRangeStressCorrection, & !< use of short range stress correction by excess density gradient term + nonSchmidActive = .false. end type tParameters type :: tNonlocalMicrostructure @@ -132,12 +130,12 @@ submodule(constitutive) plastic_nonlocal rho_sgl_mob_edg_neg, & rho_sgl_mob_scr_pos, & rho_sgl_mob_scr_neg, & - rhoSglImmobile, & ! iRhoB + rhoSglImmobile, & rho_sgl_imm_edg_pos, & rho_sgl_imm_edg_neg, & rho_sgl_imm_scr_pos, & rho_sgl_imm_scr_neg, & - rhoDip, & ! iRhoD + rhoDip, & rho_dip_edg, & rho_dip_scr, & rho_forest, & @@ -168,21 +166,20 @@ contains module subroutine plastic_nonlocal_init integer :: & - sizeState, sizeDotState,sizeDependentState, sizeDeltaState, & - maxNinstances, & + Ninstance, & p, & - l, & + NipcMyPhase, & + sizeState, sizeDotState, sizeDependentState, sizeDeltaState, & s1, s2, & - s, & - t, & - c - + s, t, l + real(pReal), dimension(:), allocatable :: & + a character(len=pStringLen) :: & - extmsg = '', & - structure - integer :: NofMyPhase + extmsg = '' + type(tInitialParameters) :: & + ini - write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- constitutive_'//PLASTICITY_NONLOCAL_LABEL//' init -+>>>'; flush(6) write(6,'(/,a)') ' Reuber et al., Acta Materialia 71:333–348, 2014' write(6,'(a)') ' https://doi.org/10.1016/j.actamat.2014.03.012' @@ -190,18 +187,16 @@ module subroutine plastic_nonlocal_init write(6,'(/,a)') ' Kords, Dissertation RWTH Aachen, 2014' write(6,'(a)') ' http://publications.rwth-aachen.de/record/229993' - maxNinstances = count(phase_plasticity == PLASTICITY_NONLOCAL_ID) + Ninstance = count(phase_plasticity == PLASTICITY_NONLOCAL_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & - write(6,'(a16,1x,i5,/)') '# instances:',maxNinstances - - allocate(param(maxNinstances)) - allocate(state(maxNinstances)) - allocate(state0(maxNinstances)) - allocate(dotState(maxNinstances)) - allocate(deltaState(maxNinstances)) - allocate(microstructure(maxNinstances)) - allocate(totalNslip(maxNinstances), source=0) + write(6,'(a16,1x,i5,/)') '# instances:',Ninstance + allocate(param(Ninstance)) + allocate(state(Ninstance)) + allocate(state0(Ninstance)) + allocate(dotState(Ninstance)) + allocate(deltaState(Ninstance)) + allocate(microstructure(Ninstance)) do p=1, size(config_phase) if (phase_plasticity(p) /= PLASTICITY_NONLOCAL_ID) cycle @@ -214,84 +209,82 @@ module subroutine plastic_nonlocal_init dst => microstructure(phase_plasticityInstance(p)), & config => config_phase(p)) - prm%aTolRho = config%getFloat('atol_rho', defaultVal=0.0_pReal) - prm%aTolShear = config%getFloat('atol_shear', defaultVal=0.0_pReal) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - structure = config%getString('lattice_structure') + prm%atol_rho = config%getFloat('atol_rho',defaultVal=1.0e4_pReal) ! This data is read in already in lattice prm%mu = lattice_mu(p) prm%nu = lattice_nu(p) - - prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray) - prm%totalNslip = sum(prm%Nslip) - slipActive: if (prm%totalNslip > 0) then - prm%Schmid = lattice_SchmidMatrix_slip(prm%Nslip,config%getString('lattice_structure'),& + ini%N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%sum_N_sl = sum(abs(ini%N_sl)) + slipActive: if (prm%sum_N_sl > 0) then + prm%Schmid = lattice_SchmidMatrix_slip(ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) if(trim(config%getString('lattice_structure')) == 'bcc') then - prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& - defaultVal = emptyRealArray) - prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1) - prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1) + a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray) + if(size(a) > 0) prm%nonSchmidActive = .true. + prm%nonSchmid_pos = lattice_nonSchmidMatrix(ini%N_sl,a,+1) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(ini%N_sl,a,-1) else prm%nonSchmid_pos = prm%Schmid prm%nonSchmid_neg = prm%Schmid endif - prm%interactionSlipSlip = lattice_interaction_SlipBySlip(prm%Nslip, & + prm%interactionSlipSlip = lattice_interaction_SlipBySlip(ini%N_sl, & config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) - prm%forestProjection_edge = lattice_forestProjection_edge (prm%Nslip,config%getString('lattice_structure'),& + prm%forestProjection_edge = lattice_forestProjection_edge (ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%forestProjection_screw = lattice_forestProjection_screw(prm%Nslip,config%getString('lattice_structure'),& + prm%forestProjection_screw = lattice_forestProjection_screw(ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%slip_direction = lattice_slip_direction (prm%Nslip,config%getString('lattice_structure'),& + prm%slip_direction = lattice_slip_direction (ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%slip_transverse = lattice_slip_transverse(prm%Nslip,config%getString('lattice_structure'),& + prm%slip_transverse = lattice_slip_transverse(ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%slip_normal = lattice_slip_normal (prm%Nslip,config%getString('lattice_structure'),& + prm%slip_normal = lattice_slip_normal (ini%N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) ! collinear systems (only for octahedral slip systems in fcc) - allocate(prm%colinearSystem(prm%totalNslip), source = -1) - do s1 = 1, prm%totalNslip - do s2 = 1, prm%totalNslip + allocate(prm%colinearSystem(prm%sum_N_sl), source = -1) + do s1 = 1, prm%sum_N_sl + do s2 = 1, prm%sum_N_sl if (all(dEq0 (math_cross(prm%slip_direction(1:3,s1),prm%slip_direction(1:3,s2)))) .and. & any(dNeq0(math_cross(prm%slip_normal (1:3,s1),prm%slip_normal (1:3,s2))))) & prm%colinearSystem(s1) = s2 enddo enddo - prm%rhoSglEdgePos0 = config%getFloats('rhosgledgepos0', requiredSize=size(prm%Nslip)) - prm%rhoSglEdgeNeg0 = config%getFloats('rhosgledgeneg0', requiredSize=size(prm%Nslip)) - prm%rhoSglScrewPos0 = config%getFloats('rhosglscrewpos0', requiredSize=size(prm%Nslip)) - prm%rhoSglScrewNeg0 = config%getFloats('rhosglscrewneg0', requiredSize=size(prm%Nslip)) - prm%rhoDipEdge0 = config%getFloats('rhodipedge0', requiredSize=size(prm%Nslip)) - prm%rhoDipScrew0 = config%getFloats('rhodipscrew0', requiredSize=size(prm%Nslip)) + ini%rhoSglEdgePos0 = config%getFloats('rhosgledgepos0', requiredSize=size(ini%N_sl)) + ini%rhoSglEdgeNeg0 = config%getFloats('rhosgledgeneg0', requiredSize=size(ini%N_sl)) + ini%rhoSglScrewPos0 = config%getFloats('rhosglscrewpos0', requiredSize=size(ini%N_sl)) + ini%rhoSglScrewNeg0 = config%getFloats('rhosglscrewneg0', requiredSize=size(ini%N_sl)) + ini%rhoDipEdge0 = config%getFloats('rhodipedge0', requiredSize=size(ini%N_sl)) + ini%rhoDipScrew0 = config%getFloats('rhodipscrew0', requiredSize=size(ini%N_sl)) - prm%lambda0 = config%getFloats('lambda0', requiredSize=size(prm%Nslip)) - prm%burgers = config%getFloats('burgers', requiredSize=size(prm%Nslip)) + prm%lambda0 = config%getFloats('lambda0', requiredSize=size(ini%N_sl)) + prm%burgers = config%getFloats('burgers', requiredSize=size(ini%N_sl)) - prm%lambda0 = math_expand(prm%lambda0,prm%Nslip) - prm%burgers = math_expand(prm%burgers,prm%Nslip) + prm%lambda0 = math_expand(prm%lambda0,ini%N_sl) + prm%burgers = math_expand(prm%burgers,ini%N_sl) - prm%minDipoleHeight_edge = config%getFloats('minimumdipoleheightedge', requiredSize=size(prm%Nslip)) - prm%minDipoleHeight_screw = config%getFloats('minimumdipoleheightscrew', requiredSize=size(prm%Nslip)) - prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge,prm%Nslip) - prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,prm%Nslip) - allocate(prm%minDipoleHeight(prm%totalNslip,2)) + prm%minDipoleHeight_edge = config%getFloats('minimumdipoleheightedge', requiredSize=size(ini%N_sl)) + prm%minDipoleHeight_screw = config%getFloats('minimumdipoleheightscrew', requiredSize=size(ini%N_sl)) + prm%minDipoleHeight_edge = math_expand(prm%minDipoleHeight_edge, ini%N_sl) + prm%minDipoleHeight_screw = math_expand(prm%minDipoleHeight_screw,ini%N_sl) + allocate(prm%minDipoleHeight(prm%sum_N_sl,2)) prm%minDipoleHeight(:,1) = prm%minDipoleHeight_edge prm%minDipoleHeight(:,2) = prm%minDipoleHeight_screw - prm%peierlsstress_edge = config%getFloats('peierlsstressedge', requiredSize=size(prm%Nslip)) - prm%peierlsstress_screw = config%getFloats('peierlsstressscrew', requiredSize=size(prm%Nslip)) - prm%peierlsstress_edge = math_expand(prm%peierlsstress_edge,prm%Nslip) - prm%peierlsstress_screw = math_expand(prm%peierlsstress_screw,prm%Nslip) - allocate(prm%peierlsstress(prm%totalNslip,2)) + prm%peierlsstress_edge = config%getFloats('peierlsstressedge', requiredSize=size(ini%N_sl)) + prm%peierlsstress_screw = config%getFloats('peierlsstressscrew', requiredSize=size(ini%N_sl)) + prm%peierlsstress_edge = math_expand(prm%peierlsstress_edge, ini%N_sl) + prm%peierlsstress_screw = math_expand(prm%peierlsstress_screw,ini%N_sl) + allocate(prm%peierlsstress(prm%sum_N_sl,2)) prm%peierlsstress(:,1) = prm%peierlsstress_edge prm%peierlsstress(:,2) = prm%peierlsstress_screw @@ -315,10 +308,10 @@ module subroutine plastic_nonlocal_init prm%fattack = config%getFloat('attackfrequency') ! ToDo: discuss logic - prm%rhoSglScatter = config%getFloat('rhosglscatter') - prm%rhoSglRandom = config%getFloat('rhosglrandom',0.0_pReal) + ini%rhoSglScatter = config%getFloat('rhosglscatter') + ini%rhoSglRandom = config%getFloat('rhosglrandom',0.0_pReal) if (config%keyExists('/rhosglrandom/')) & - prm%rhoSglRandomBinning = config%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? + ini%rhoSglRandomBinning = config%getFloat('rhosglrandombinning',0.0_pReal) !ToDo: useful default? ! if (rhoSglRandom(instance) < 0.0_pReal) & ! if (rhoSglRandomBinning(instance) <= 0.0_pReal) & @@ -332,12 +325,12 @@ module subroutine plastic_nonlocal_init if (any(prm%burgers < 0.0_pReal)) extmsg = trim(extmsg)//' burgers' if (any(prm%lambda0 <= 0.0_pReal)) extmsg = trim(extmsg)//' lambda0' - if (any(prm%rhoSglEdgePos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgePos0' - if (any(prm%rhoSglEdgeNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgeNeg0' - if (any(prm%rhoSglScrewPos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewPos0' - if (any(prm%rhoSglScrewNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewNeg0' - if (any(prm%rhoDipEdge0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipEdge0' - if (any(prm%rhoDipScrew0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipScrew0' + if (any(ini%rhoSglEdgePos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgePos0' + if (any(ini%rhoSglEdgeNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglEdgeNeg0' + if (any(ini%rhoSglScrewPos0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewPos0' + if (any(ini%rhoSglScrewNeg0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoSglScrewNeg0' + if (any(ini%rhoDipEdge0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipEdge0' + if (any(ini%rhoDipScrew0 < 0.0_pReal)) extmsg = trim(extmsg)//' rhoDipScrew0' if (any(prm%peierlsstress < 0.0_pReal)) extmsg = trim(extmsg)//' peierlsstress' if (any(prm%minDipoleHeight < 0.0_pReal)) extmsg = trim(extmsg)//' minDipoleHeight' @@ -347,12 +340,11 @@ module subroutine plastic_nonlocal_init if (prm%fattack <= 0.0_pReal) extmsg = trim(extmsg)//' fattack' if (prm%doublekinkwidth <= 0.0_pReal) extmsg = trim(extmsg)//' doublekinkwidth' if (prm%Dsd0 < 0.0_pReal) extmsg = trim(extmsg)//' Dsd0' - if (prm%atomicVolume <= 0.0_pReal) extmsg = trim(extmsg)//' atomicVolume' ! ToDo: in disloUCLA/dislotwin, the atomic volume is given as a factor + if (prm%atomicVolume <= 0.0_pReal) extmsg = trim(extmsg)//' atomicVolume' ! ToDo: in disloUCLA, the atomic volume is given as a factor if (prm%significantN < 0.0_pReal) extmsg = trim(extmsg)//' significantN' if (prm%significantrho < 0.0_pReal) extmsg = trim(extmsg)//' significantrho' - if (prm%atolshear <= 0.0_pReal) extmsg = trim(extmsg)//' atolshear' - if (prm%atolrho <= 0.0_pReal) extmsg = trim(extmsg)//' atolrho' + if (prm%atol_rho < 0.0_pReal) extmsg = trim(extmsg)//' atol_rho' if (prm%CFLfactor < 0.0_pReal) extmsg = trim(extmsg)//' CFLfactor' if (prm%p <= 0.0_pReal .or. prm%p > 1.0_pReal) extmsg = trim(extmsg)//' p' @@ -372,258 +364,156 @@ module subroutine plastic_nonlocal_init extmsg = trim(extmsg)//' surfaceTransmissivity' if (prm%fEdgeMultiplication < 0.0_pReal .or. prm%fEdgeMultiplication > 1.0_pReal) & - extmsg = trim(extmsg)//' fEdgeMultiplication' + extmsg = trim(extmsg)//' fEdgeMultiplication' endif slipActive - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - !-------------------------------------------------------------------------------------------------- ! allocate state arrays - NofMyPhase = count(material_phaseAt==p) * discretization_nIP - sizeDotState = size([ 'rhoSglEdgePosMobile ','rhoSglEdgeNegMobile ', & - 'rhoSglScrewPosMobile ','rhoSglScrewNegMobile ', & - 'rhoSglEdgePosImmobile ','rhoSglEdgeNegImmobile ', & - 'rhoSglScrewPosImmobile','rhoSglScrewNegImmobile', & - 'rhoDipEdge ','rhoDipScrew ', & - 'gamma ' ]) * prm%totalNslip !< "basic" microstructural state variables that are independent from other state variables - sizeDependentState = size([ 'rhoForest ']) * prm%totalNslip !< microstructural state variables that depend on other state variables + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP + sizeDotState = size([ 'rhoSglEdgePosMobile ','rhoSglEdgeNegMobile ', & + 'rhoSglScrewPosMobile ','rhoSglScrewNegMobile ', & + 'rhoSglEdgePosImmobile ','rhoSglEdgeNegImmobile ', & + 'rhoSglScrewPosImmobile','rhoSglScrewNegImmobile', & + 'rhoDipEdge ','rhoDipScrew ', & + 'gamma ' ]) * prm%sum_N_sl !< "basic" microstructural state variables that are independent from other state variables + sizeDependentState = size([ 'rhoForest ']) * prm%sum_N_sl !< microstructural state variables that depend on other state variables sizeState = sizeDotState + sizeDependentState & + size([ 'velocityEdgePos ','velocityEdgeNeg ', & 'velocityScrewPos ','velocityScrewNeg ', & - 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]) * prm%totalNslip !< other dependent state variables that are not updated by microstructure + 'maxDipoleHeightEdge ','maxDipoleHeightScrew' ]) * prm%sum_N_sl !< other dependent state variables that are not updated by microstructure sizeDeltaState = sizeDotState - call material_allocatePlasticState(p,NofMyPhase,sizeState,sizeDotState,sizeDeltaState) + call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,sizeDeltaState) plasticState(p)%nonlocal = .true. plasticState(p)%offsetDeltaState = 0 ! ToDo: state structure does not follow convention - totalNslip(phase_plasticityInstance(p)) = prm%totalNslip + st0%rho => plasticState(p)%state0 (0*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + stt%rho => plasticState(p)%state (0*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + dot%rho => plasticState(p)%dotState (0*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + del%rho => plasticState(p)%deltaState (0*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + plasticState(p)%atol(1:10*prm%sum_N_sl) = prm%atol_rho - st0%rho => plasticState(p)%state0 (0*prm%totalNslip+1:10*prm%totalNslip,:) - stt%rho => plasticState(p)%state (0*prm%totalNslip+1:10*prm%totalNslip,:) - dot%rho => plasticState(p)%dotState (0*prm%totalNslip+1:10*prm%totalNslip,:) - del%rho => plasticState(p)%deltaState (0*prm%totalNslip+1:10*prm%totalNslip,:) - plasticState(p)%aTolState(1:10*prm%totalNslip) = prm%aTolRho + stt%rhoSgl => plasticState(p)%state (0*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + dot%rhoSgl => plasticState(p)%dotState (0*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + del%rhoSgl => plasticState(p)%deltaState (0*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) - stt%rhoSgl => plasticState(p)%state (0*prm%totalNslip+1: 8*prm%totalNslip,:) - dot%rhoSgl => plasticState(p)%dotState (0*prm%totalNslip+1: 8*prm%totalNslip,:) - del%rhoSgl => plasticState(p)%deltaState (0*prm%totalNslip+1: 8*prm%totalNslip,:) + stt%rhoSglMobile => plasticState(p)%state (0*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) + dot%rhoSglMobile => plasticState(p)%dotState (0*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) + del%rhoSglMobile => plasticState(p)%deltaState (0*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) - stt%rhoSglMobile => plasticState(p)%state (0*prm%totalNslip+1: 4*prm%totalNslip,:) - dot%rhoSglMobile => plasticState(p)%dotState (0*prm%totalNslip+1: 4*prm%totalNslip,:) - del%rhoSglMobile => plasticState(p)%deltaState (0*prm%totalNslip+1: 4*prm%totalNslip,:) + stt%rho_sgl_mob_edg_pos => plasticState(p)%state (0*prm%sum_N_sl+1: 1*prm%sum_N_sl,:) + dot%rho_sgl_mob_edg_pos => plasticState(p)%dotState (0*prm%sum_N_sl+1: 1*prm%sum_N_sl,:) + del%rho_sgl_mob_edg_pos => plasticState(p)%deltaState (0*prm%sum_N_sl+1: 1*prm%sum_N_sl,:) - stt%rho_sgl_mob_edg_pos => plasticState(p)%state (0*prm%totalNslip+1: 1*prm%totalNslip,:) - dot%rho_sgl_mob_edg_pos => plasticState(p)%dotState (0*prm%totalNslip+1: 1*prm%totalNslip,:) - del%rho_sgl_mob_edg_pos => plasticState(p)%deltaState (0*prm%totalNslip+1: 1*prm%totalNslip,:) + stt%rho_sgl_mob_edg_neg => plasticState(p)%state (1*prm%sum_N_sl+1: 2*prm%sum_N_sl,:) + dot%rho_sgl_mob_edg_neg => plasticState(p)%dotState (1*prm%sum_N_sl+1: 2*prm%sum_N_sl,:) + del%rho_sgl_mob_edg_neg => plasticState(p)%deltaState (1*prm%sum_N_sl+1: 2*prm%sum_N_sl,:) - stt%rho_sgl_mob_edg_neg => plasticState(p)%state (1*prm%totalNslip+1: 2*prm%totalNslip,:) - dot%rho_sgl_mob_edg_neg => plasticState(p)%dotState (1*prm%totalNslip+1: 2*prm%totalNslip,:) - del%rho_sgl_mob_edg_neg => plasticState(p)%deltaState (1*prm%totalNslip+1: 2*prm%totalNslip,:) + stt%rho_sgl_mob_scr_pos => plasticState(p)%state (2*prm%sum_N_sl+1: 3*prm%sum_N_sl,:) + dot%rho_sgl_mob_scr_pos => plasticState(p)%dotState (2*prm%sum_N_sl+1: 3*prm%sum_N_sl,:) + del%rho_sgl_mob_scr_pos => plasticState(p)%deltaState (2*prm%sum_N_sl+1: 3*prm%sum_N_sl,:) - stt%rho_sgl_mob_scr_pos => plasticState(p)%state (2*prm%totalNslip+1: 3*prm%totalNslip,:) - dot%rho_sgl_mob_scr_pos => plasticState(p)%dotState (2*prm%totalNslip+1: 3*prm%totalNslip,:) - del%rho_sgl_mob_scr_pos => plasticState(p)%deltaState (2*prm%totalNslip+1: 3*prm%totalNslip,:) + stt%rho_sgl_mob_scr_neg => plasticState(p)%state (3*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) + dot%rho_sgl_mob_scr_neg => plasticState(p)%dotState (3*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) + del%rho_sgl_mob_scr_neg => plasticState(p)%deltaState (3*prm%sum_N_sl+1: 4*prm%sum_N_sl,:) - stt%rho_sgl_mob_scr_neg => plasticState(p)%state (3*prm%totalNslip+1: 4*prm%totalNslip,:) - dot%rho_sgl_mob_scr_neg => plasticState(p)%dotState (3*prm%totalNslip+1: 4*prm%totalNslip,:) - del%rho_sgl_mob_scr_neg => plasticState(p)%deltaState (3*prm%totalNslip+1: 4*prm%totalNslip,:) + stt%rhoSglImmobile => plasticState(p)%state (4*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + dot%rhoSglImmobile => plasticState(p)%dotState (4*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + del%rhoSglImmobile => plasticState(p)%deltaState (4*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) - stt%rhoSglImmobile => plasticState(p)%state (4*prm%totalNslip+1: 8*prm%totalNslip,:) - dot%rhoSglImmobile => plasticState(p)%dotState (4*prm%totalNslip+1: 8*prm%totalNslip,:) - del%rhoSglImmobile => plasticState(p)%deltaState (4*prm%totalNslip+1: 8*prm%totalNslip,:) + stt%rho_sgl_imm_edg_pos => plasticState(p)%state (4*prm%sum_N_sl+1: 5*prm%sum_N_sl,:) + dot%rho_sgl_imm_edg_pos => plasticState(p)%dotState (4*prm%sum_N_sl+1: 5*prm%sum_N_sl,:) + del%rho_sgl_imm_edg_pos => plasticState(p)%deltaState (4*prm%sum_N_sl+1: 5*prm%sum_N_sl,:) - stt%rho_sgl_imm_edg_pos => plasticState(p)%state (4*prm%totalNslip+1: 5*prm%totalNslip,:) - dot%rho_sgl_imm_edg_pos => plasticState(p)%dotState (4*prm%totalNslip+1: 5*prm%totalNslip,:) - del%rho_sgl_imm_edg_pos => plasticState(p)%deltaState (4*prm%totalNslip+1: 5*prm%totalNslip,:) + stt%rho_sgl_imm_edg_neg => plasticState(p)%state (5*prm%sum_N_sl+1: 6*prm%sum_N_sl,:) + dot%rho_sgl_imm_edg_neg => plasticState(p)%dotState (5*prm%sum_N_sl+1: 6*prm%sum_N_sl,:) + del%rho_sgl_imm_edg_neg => plasticState(p)%deltaState (5*prm%sum_N_sl+1: 6*prm%sum_N_sl,:) - stt%rho_sgl_imm_edg_neg => plasticState(p)%state (5*prm%totalNslip+1: 6*prm%totalNslip,:) - dot%rho_sgl_imm_edg_neg => plasticState(p)%dotState (5*prm%totalNslip+1: 6*prm%totalNslip,:) - del%rho_sgl_imm_edg_neg => plasticState(p)%deltaState (5*prm%totalNslip+1: 6*prm%totalNslip,:) + stt%rho_sgl_imm_scr_pos => plasticState(p)%state (6*prm%sum_N_sl+1: 7*prm%sum_N_sl,:) + dot%rho_sgl_imm_scr_pos => plasticState(p)%dotState (6*prm%sum_N_sl+1: 7*prm%sum_N_sl,:) + del%rho_sgl_imm_scr_pos => plasticState(p)%deltaState (6*prm%sum_N_sl+1: 7*prm%sum_N_sl,:) - stt%rho_sgl_imm_scr_pos => plasticState(p)%state (6*prm%totalNslip+1: 7*prm%totalNslip,:) - dot%rho_sgl_imm_scr_pos => plasticState(p)%dotState (6*prm%totalNslip+1: 7*prm%totalNslip,:) - del%rho_sgl_imm_scr_pos => plasticState(p)%deltaState (6*prm%totalNslip+1: 7*prm%totalNslip,:) + stt%rho_sgl_imm_scr_neg => plasticState(p)%state (7*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + dot%rho_sgl_imm_scr_neg => plasticState(p)%dotState (7*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) + del%rho_sgl_imm_scr_neg => plasticState(p)%deltaState (7*prm%sum_N_sl+1: 8*prm%sum_N_sl,:) - stt%rho_sgl_imm_scr_neg => plasticState(p)%state (7*prm%totalNslip+1: 8*prm%totalNslip,:) - dot%rho_sgl_imm_scr_neg => plasticState(p)%dotState (7*prm%totalNslip+1: 8*prm%totalNslip,:) - del%rho_sgl_imm_scr_neg => plasticState(p)%deltaState (7*prm%totalNslip+1: 8*prm%totalNslip,:) + stt%rhoDip => plasticState(p)%state (8*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + dot%rhoDip => plasticState(p)%dotState (8*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + del%rhoDip => plasticState(p)%deltaState (8*prm%sum_N_sl+1:10*prm%sum_N_sl,:) - stt%rhoDip => plasticState(p)%state (8*prm%totalNslip+1:10*prm%totalNslip,:) - dot%rhoDip => plasticState(p)%dotState (8*prm%totalNslip+1:10*prm%totalNslip,:) - del%rhoDip => plasticState(p)%deltaState (8*prm%totalNslip+1:10*prm%totalNslip,:) + stt%rho_dip_edg => plasticState(p)%state (8*prm%sum_N_sl+1: 9*prm%sum_N_sl,:) + dot%rho_dip_edg => plasticState(p)%dotState (8*prm%sum_N_sl+1: 9*prm%sum_N_sl,:) + del%rho_dip_edg => plasticState(p)%deltaState (8*prm%sum_N_sl+1: 9*prm%sum_N_sl,:) - stt%rho_dip_edg => plasticState(p)%state (8*prm%totalNslip+1: 9*prm%totalNslip,:) - dot%rho_dip_edg => plasticState(p)%dotState (8*prm%totalNslip+1: 9*prm%totalNslip,:) - del%rho_dip_edg => plasticState(p)%deltaState (8*prm%totalNslip+1: 9*prm%totalNslip,:) + stt%rho_dip_scr => plasticState(p)%state (9*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + dot%rho_dip_scr => plasticState(p)%dotState (9*prm%sum_N_sl+1:10*prm%sum_N_sl,:) + del%rho_dip_scr => plasticState(p)%deltaState (9*prm%sum_N_sl+1:10*prm%sum_N_sl,:) - stt%rho_dip_scr => plasticState(p)%state (9*prm%totalNslip+1:10*prm%totalNslip,:) - dot%rho_dip_scr => plasticState(p)%dotState (9*prm%totalNslip+1:10*prm%totalNslip,:) - del%rho_dip_scr => plasticState(p)%deltaState (9*prm%totalNslip+1:10*prm%totalNslip,:) + stt%gamma => plasticState(p)%state (10*prm%sum_N_sl + 1:11*prm%sum_N_sl,1:NipcMyPhase) + dot%gamma => plasticState(p)%dotState (10*prm%sum_N_sl + 1:11*prm%sum_N_sl,1:NipcMyPhase) + del%gamma => plasticState(p)%deltaState (10*prm%sum_N_sl + 1:11*prm%sum_N_sl,1:NipcMyPhase) + plasticState(p)%atol(10*prm%sum_N_sl+1:11*prm%sum_N_sl ) = config%getFloat('atol_gamma', defaultVal = 1.0e-2_pReal) + if(any(plasticState(p)%atol(10*prm%sum_N_sl+1:11*prm%sum_N_sl) < 0.0_pReal)) & + extmsg = trim(extmsg)//' atol_gamma' + plasticState(p)%slipRate => plasticState(p)%dotState (10*prm%sum_N_sl + 1:11*prm%sum_N_sl,1:NipcMyPhase) - stt%gamma => plasticState(p)%state (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - dot%gamma => plasticState(p)%dotState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - del%gamma => plasticState(p)%deltaState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) - plasticState(p)%aTolState(10*prm%totalNslip + 1:11*prm%totalNslip ) = prm%aTolShear - plasticState(p)%slipRate => plasticState(p)%dotState (10*prm%totalNslip + 1:11*prm%totalNslip ,1:NofMyPhase) + stt%rho_forest => plasticState(p)%state (11*prm%sum_N_sl + 1:12*prm%sum_N_sl,1:NipcMyPhase) + stt%v => plasticState(p)%state (12*prm%sum_N_sl + 1:16*prm%sum_N_sl,1:NipcMyPhase) + stt%v_edg_pos => plasticState(p)%state (12*prm%sum_N_sl + 1:13*prm%sum_N_sl,1:NipcMyPhase) + stt%v_edg_neg => plasticState(p)%state (13*prm%sum_N_sl + 1:14*prm%sum_N_sl,1:NipcMyPhase) + stt%v_scr_pos => plasticState(p)%state (14*prm%sum_N_sl + 1:15*prm%sum_N_sl,1:NipcMyPhase) + stt%v_scr_neg => plasticState(p)%state (15*prm%sum_N_sl + 1:16*prm%sum_N_sl,1:NipcMyPhase) - stt%rho_forest => plasticState(p)%state (11*prm%totalNslip + 1:12*prm%totalNslip ,1:NofMyPhase) - stt%v => plasticState(p)%state (12*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase) - stt%v_edg_pos => plasticState(p)%state (12*prm%totalNslip + 1:13*prm%totalNslip ,1:NofMyPhase) - stt%v_edg_neg => plasticState(p)%state (13*prm%totalNslip + 1:14*prm%totalNslip ,1:NofMyPhase) - stt%v_scr_pos => plasticState(p)%state (14*prm%totalNslip + 1:15*prm%totalNslip ,1:NofMyPhase) - stt%v_scr_neg => plasticState(p)%state (15*prm%totalNslip + 1:16*prm%totalNslip ,1:NofMyPhase) - - allocate(dst%tau_pass(prm%totalNslip,NofMyPhase),source=0.0_pReal) - allocate(dst%tau_back(prm%totalNslip,NofMyPhase),source=0.0_pReal) + allocate(dst%tau_pass(prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) + allocate(dst%tau_back(prm%sum_N_sl,NipcMyPhase),source=0.0_pReal) end associate - if (NofMyPhase > 0) call stateInit(p,NofMyPhase) + if (NipcMyPhase > 0) call stateInit(ini,p,NipcMyPhase) plasticState(p)%state0 = plasticState(p)%state +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_NONLOCAL_LABEL//')') + enddo - allocate(compatibility(2,maxval(totalNslip),maxval(totalNslip),nIPneighbors,& + allocate(compatibility(2,maxval(param%sum_N_sl),maxval(param%sum_N_sl),nIPneighbors,& discretization_nIP,discretization_nElem), source=0.0_pReal) ! BEGIN DEPRECATED---------------------------------------------------------------------------------- - allocate(iRhoU(maxval(totalNslip),4,maxNinstances), source=0) - allocate(iRhoB(maxval(totalNslip),4,maxNinstances), source=0) - allocate(iRhoD(maxval(totalNslip),2,maxNinstances), source=0) - allocate(iV(maxval(totalNslip),4,maxNinstances), source=0) - allocate(iD(maxval(totalNslip),2,maxNinstances), source=0) + allocate(iRhoU(maxval(param%sum_N_sl),4,Ninstance), source=0) + allocate(iV(maxval(param%sum_N_sl),4,Ninstance), source=0) + allocate(iD(maxval(param%sum_N_sl),2,Ninstance), source=0) initializeInstances: do p = 1, size(phase_plasticity) - NofMyPhase = count(material_phaseAt==p) * discretization_nIP + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP myPhase2: if (phase_plasticity(p) == PLASTICITY_NONLOCAL_ID) then - - !*** determine indices to state array - l = 0 do t = 1,4 - do s = 1,param(phase_plasticityInstance(p))%totalNslip + do s = 1,param(phase_plasticityInstance(p))%sum_N_sl l = l + 1 iRhoU(s,t,phase_plasticityInstance(p)) = l enddo enddo + l = l + (4+2+1+1)*param(phase_plasticityInstance(p))%sum_N_sl ! immobile(4), dipole(2), shear, forest do t = 1,4 - do s = 1,param(phase_plasticityInstance(p))%totalNslip - l = l + 1 - iRhoB(s,t,phase_plasticityInstance(p)) = l - enddo - enddo - do c = 1,2 - do s = 1,param(phase_plasticityInstance(p))%totalNslip - l = l + 1 - iRhoD(s,c,phase_plasticityInstance(p)) = l - enddo - enddo - - l = l + param(phase_plasticityInstance(p))%totalNslip ! shear(rates) - l = l + param(phase_plasticityInstance(p))%totalNslip ! rho_forest - - do t = 1,4 - do s = 1,param(phase_plasticityInstance(p))%totalNslip + do s = 1,param(phase_plasticityInstance(p))%sum_N_sl l = l + 1 iV(s,t,phase_plasticityInstance(p)) = l enddo enddo - do c = 1,2 - do s = 1,param(phase_plasticityInstance(p))%totalNslip + do t = 1,2 + do s = 1,param(phase_plasticityInstance(p))%sum_N_sl l = l + 1 - iD(s,c,phase_plasticityInstance(p)) = l + iD(s,t,phase_plasticityInstance(p)) = l enddo enddo - if (iD(param(phase_plasticityInstance(p))%totalNslip,2,phase_plasticityInstance(p)) /= plasticState(p)%sizeState) & - call IO_error(0, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_label//')') - - + if (iD(param(phase_plasticityInstance(p))%sum_N_sl,2,phase_plasticityInstance(p)) /= plasticState(p)%sizeState) & + call IO_error(0, ext_msg = 'state indices not properly set ('//PLASTICITY_NONLOCAL_LABEL//')') endif myPhase2 - enddo initializeInstances -! END DEPRECATED------------------------------------------------------------------------------------ - - - contains - !-------------------------------------------------------------------------------------------------- - !> @brief populates the initial dislocation density - !-------------------------------------------------------------------------------------------------- - subroutine stateInit(phase,NofMyPhase) - - integer,intent(in) ::& - phase, & - NofMyPhase - integer :: & - e, & - i, & - f, & - from, & - upto, & - s, & - instance, & - phasemember - real(pReal), dimension(2) :: & - noise, & - rnd - real(pReal) :: & - meanDensity, & - totalVolume, & - densityBinning, & - minimumIpVolume - real(pReal), dimension(NofMyPhase) :: & - volume - - - instance = phase_plasticityInstance(phase) - associate(prm => param(instance), stt => state(instance)) - - ! randomly distribute dislocation segments on random slip system and of random type in the volume - if (prm%rhoSglRandom > 0.0_pReal) then - - ! get the total volume of the instance - do e = 1,discretization_nElem - do i = 1,discretization_nIP - if (material_phaseAt(1,e) == phase) volume(material_phasememberAt(1,i,e)) = IPvolume(i,e) - enddo - enddo - totalVolume = sum(volume) - minimumIPVolume = minval(volume) - densityBinning = prm%rhoSglRandomBinning / minimumIpVolume ** (2.0_pReal / 3.0_pReal) - - ! subsequently fill random ips with dislocation segments until we reach the desired overall density - meanDensity = 0.0_pReal - do while(meanDensity < prm%rhoSglRandom) - call random_number(rnd) - phasemember = nint(rnd(1)*real(NofMyPhase,pReal) + 0.5_pReal) - s = nint(rnd(2)*real(prm%totalNslip,pReal)*4.0_pReal + 0.5_pReal) - meanDensity = meanDensity + densityBinning * volume(phasemember) / totalVolume - stt%rhoSglMobile(s,phasemember) = densityBinning - enddo - ! homogeneous distribution of density with some noise - else - do e = 1, NofMyPhase - do f = 1,size(prm%Nslip,1) - from = 1 + sum(prm%Nslip(1:f-1)) - upto = sum(prm%Nslip(1:f)) - do s = from,upto - noise = [math_sampleGaussVar(0.0_pReal, prm%rhoSglScatter), & - math_sampleGaussVar(0.0_pReal, prm%rhoSglScatter)] - stt%rho_sgl_mob_edg_pos(s,e) = prm%rhoSglEdgePos0(f) + noise(1) - stt%rho_sgl_mob_edg_neg(s,e) = prm%rhoSglEdgeNeg0(f) + noise(1) - stt%rho_sgl_mob_scr_pos(s,e) = prm%rhoSglScrewPos0(f) + noise(2) - stt%rho_sgl_mob_scr_neg(s,e) = prm%rhoSglScrewNeg0(f) + noise(2) - enddo - stt%rho_dip_edg(from:upto,e) = prm%rhoDipEdge0(f) - stt%rho_dip_scr(from:upto,e) = prm%rhoDipScrew0(f) - enddo - enddo - endif - - end associate - - end subroutine stateInit end subroutine plastic_nonlocal_init @@ -631,23 +521,21 @@ end subroutine plastic_nonlocal_init !-------------------------------------------------------------------------------------------------- !> @brief calculates quantities characterizing the microstructure !-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) +module subroutine plastic_nonlocal_dependentState(F, Fp, instance, of, ip, el) - integer, intent(in) :: & - ip, & - el real(pReal), dimension(3,3), intent(in) :: & F, & Fp + integer, intent(in) :: & + instance, & + of, & + ip, & + el integer :: & - ph, & !< phase - of, & !< offset no, & !< neighbor offset - ns, & neighbor_el, & ! element number of neighboring material point neighbor_ip, & ! integration point of neighboring material point - instance, & ! my instance of this plasticity neighbor_instance, & ! instance of this plasticity of neighboring material point c, & ! index of dilsocation character (edge, screw) s, & ! slip system index @@ -655,7 +543,6 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) n real(pReal) :: & FVsize, & - correction, & nRealNeighbors ! number of really existing neighbors integer, dimension(2) :: & neighbors @@ -673,36 +560,28 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) invConnections real(pReal), dimension(3,nIPneighbors) :: & connection_latticeConf - real(pReal), dimension(2,totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & + real(pReal), dimension(2,param(instance)%sum_N_sl) :: & rhoExcess - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & rho_edg_delta, & rho_scr_delta - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),10) :: & + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & rho, & rho0, & rho_neighbor0 - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))), & - totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & + real(pReal), dimension(param(instance)%sum_N_sl,param(instance)%sum_N_sl) :: & myInteractionMatrix ! corrected slip interaction matrix - - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),nIPneighbors) :: & + real(pReal), dimension(param(instance)%sum_N_sl,nIPneighbors) :: & rho_edg_delta_neighbor, & rho_scr_delta_neighbor - real(pReal), dimension(2,maxval(totalNslip),nIPneighbors) :: & + real(pReal), dimension(2,maxval(param%sum_N_sl),nIPneighbors) :: & neighbor_rhoExcess, & ! excess density at neighboring material point neighbor_rhoTotal ! total density at neighboring material point - real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),2) :: & + real(pReal), dimension(3,param(instance)%sum_N_sl,2) :: & m ! direction of dislocation motion - ph = material_phaseAt(1,el) - of = material_phasememberAt(1,ip,el) - instance = phase_plasticityInstance(ph) - associate(prm => param(instance),dst => microstructure(instance), stt => state(instance)) - ns = prm%totalNslip - rho = getRho(instance,of,ip,el) stt%rho_forest(:,of) = matmul(prm%forestProjection_Edge, sum(abs(rho(:,edg)),2)) & @@ -711,22 +590,18 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) ! coefficients are corrected for the line tension effect ! (see Kubin,Devincre,Hoc; 2008; Modeling dislocation storage rates and mean free paths in face-centered cubic crystals) - if (lattice_structure(ph) == LATTICE_bcc_ID .or. lattice_structure(ph) == LATTICE_fcc_ID) then - do s = 1,ns - correction = ( 1.0_pReal - prm%linetensionEffect & - + prm%linetensionEffect & - * log(0.35_pReal * prm%burgers(s) * sqrt(max(stt%rho_forest(s,of),prm%significantRho))) & - / log(0.35_pReal * prm%burgers(s) * 1e6_pReal)) ** 2.0_pReal - myInteractionMatrix(1:ns,s) = correction * prm%interactionSlipSlip(1:ns,s) - enddo + if (any(lattice_structure(material_phaseAt(1,el)) == [LATTICE_bcc_ID,LATTICE_fcc_ID])) then + myInteractionMatrix = prm%interactionSlipSlip & + * spread(( 1.0_pReal - prm%linetensionEffect & + + prm%linetensionEffect & + * log(0.35_pReal * prm%burgers * sqrt(max(stt%rho_forest(:,of),prm%significantRho))) & + / log(0.35_pReal * prm%burgers * 1e6_pReal))** 2.0_pReal,2,prm%sum_N_sl) else myInteractionMatrix = prm%interactionSlipSlip endif - forall (s = 1:ns) & - dst%tau_pass(s,of) = prm%mu * prm%burgers(s) & - * sqrt(dot_product(sum(abs(rho),2), myInteractionMatrix(1:ns,s))) - + dst%tau_pass(:,of) = prm%mu * prm%burgers & + * sqrt(matmul(myInteractionMatrix,sum(abs(rho),2))) !*** calculate the dislocation stress of the neighboring excess dislocation densities !*** zero for material points of local plasticity @@ -736,15 +611,15 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) !################################################################################################# rho0 = getRho0(instance,of,ip,el) - if (.not. phase_localPlasticity(ph) .and. prm%shortRangeStressCorrection) then + if (.not. phase_localPlasticity(material_phaseAt(1,el)) .and. prm%shortRangeStressCorrection) then invFp = math_inv33(Fp) invFe = matmul(Fp,math_inv33(F)) rho_edg_delta = rho0(:,mob_edg_pos) - rho0(:,mob_edg_neg) rho_scr_delta = rho0(:,mob_scr_pos) - rho0(:,mob_scr_neg) - rhoExcess(1,1:ns) = rho_edg_delta - rhoExcess(2,1:ns) = rho_scr_delta + rhoExcess(1,:) = rho_edg_delta + rhoExcess(2,:) = rho_scr_delta FVsize = IPvolume(ip,el) ** (1.0_pReal/3.0_pReal) @@ -772,8 +647,8 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) connection_latticeConf(1:3,n) = matmul(invFe, discretization_IPcoords(1:3,neighbor_el+neighbor_ip-1) & - discretization_IPcoords(1:3,el+neighbor_ip-1)) normal_latticeConf = matmul(transpose(invFp), IPareaNormal(1:3,n,ip,el)) - if (math_inner(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) & ! neighboring connection points in opposite direction to face normal: must be periodic image - connection_latticeConf(1:3,n) = normal_latticeConf * IPvolume(ip,el)/IParea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell + if (math_inner(normal_latticeConf,connection_latticeConf(1:3,n)) < 0.0_pReal) & ! neighboring connection points in opposite direction to face normal: must be periodic image + connection_latticeConf(1:3,n) = normal_latticeConf * IPvolume(ip,el)/IParea(n,ip,el) ! instead take the surface normal scaled with the diameter of the cell else ! local neighbor or different lattice structure or different constitution instance -> use central values instead connection_latticeConf(1:3,n) = 0.0_pReal @@ -794,10 +669,10 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) !* loop through the slip systems and calculate the dislocation gradient by !* 1. interpolation of the excess density in the neighorhood !* 2. interpolation of the dead dislocation density in the central volume - m(1:3,1:ns,1) = prm%slip_direction - m(1:3,1:ns,2) = -prm%slip_transverse + m(1:3,:,1) = prm%slip_direction + m(1:3,:,2) = -prm%slip_transverse - do s = 1,ns + do s = 1,prm%sum_N_sl ! gradient from interpolation of neighboring excess density ... do c = 1,2 @@ -824,14 +699,12 @@ module subroutine plastic_nonlocal_dependentState(F, Fp, ip, el) rhoTotal(2) = (sum(abs(rho(s,scr))) + sum(neighbor_rhoTotal(2,s,:))) / (1.0_pReal + nRealNeighbors) rhoExcessGradient_over_rho = 0.0_pReal - where(rhoTotal > 0.0_pReal) & - rhoExcessGradient_over_rho = rhoExcessGradient / rhoTotal + where(rhoTotal > 0.0_pReal) rhoExcessGradient_over_rho = rhoExcessGradient / rhoTotal ! ... gives the local stress correction when multiplied with a factor - dst%tau_back(s,of) = - prm%mu * prm%burgers(s) / (2.0_pReal * pi) & - * (rhoExcessGradient_over_rho(1) / (1.0_pReal - prm%nu) & - + rhoExcessGradient_over_rho(2)) - + dst%tau_back(s,of) = - prm%mu * prm%burgers(s) / (2.0_pReal * PI) & + * ( rhoExcessGradient_over_rho(1) / (1.0_pReal - prm%nu) & + + rhoExcessGradient_over_rho(2)) enddo endif @@ -852,21 +725,904 @@ end subroutine plastic_nonlocal_dependentState !-------------------------------------------------------------------------------------------------- -!> @brief calculates kinetics +!> @brief calculates plastic velocity gradient and its tangent !-------------------------------------------------------------------------------------------------- -subroutine plastic_nonlocal_kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, & - tauThreshold, c, Temperature, instance, of) +module subroutine plastic_nonlocal_LpAndItsTangent(Lp,dLp_dMp, & + Mp,Temperature,instance,of,ip,el) + real(pReal), dimension(3,3), intent(out) :: & + Lp !< plastic velocity gradient + real(pReal), dimension(3,3,3,3), intent(out) :: & + dLp_dMp integer, intent(in) :: & - c, & !< dislocation character (1:edge, 2:screw) - instance, of + instance, & + of, & + ip, & !< current integration point + el !< current element number real(pReal), intent(in) :: & Temperature !< temperature - real(pReal), dimension(param(instance)%totalNslip), intent(in) :: & + + real(pReal), dimension(3,3), intent(in) :: & + Mp + !< derivative of Lp with respect to Mp + integer :: & + ns, & !< short notation for the total number of active slip systems + i, & + j, & + k, & + l, & + t, & !< dislocation type + s !< index of my current slip system + real(pReal), dimension(param(instance)%sum_N_sl,8) :: & + rhoSgl !< single dislocation densities (including blocked) + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & + rho + real(pReal), dimension(param(instance)%sum_N_sl,4) :: & + v, & !< velocity + tauNS, & !< resolved shear stress including non Schmid and backstress terms + dv_dtau, & !< velocity derivative with respect to the shear stress + dv_dtauNS !< velocity derivative with respect to the shear stress + real(pReal), dimension(param(instance)%sum_N_sl) :: & + tau, & !< resolved shear stress including backstress terms + gdotTotal !< shear rate + + associate(prm => param(instance),dst=>microstructure(instance),stt=>state(instance)) + ns = prm%sum_N_sl + + !*** shortcut to state variables + rho = getRho(instance,of,ip,el) + rhoSgl = rho(:,sgl) + + do s = 1,ns + tau(s) = math_tensordot(Mp, prm%Schmid(1:3,1:3,s)) + tauNS(s,1) = tau(s) + tauNS(s,2) = tau(s) + if (tau(s) > 0.0_pReal) then + tauNS(s,3) = math_tensordot(Mp, +prm%nonSchmid_pos(1:3,1:3,s)) + tauNS(s,4) = math_tensordot(Mp, -prm%nonSchmid_neg(1:3,1:3,s)) + else + tauNS(s,3) = math_tensordot(Mp, +prm%nonSchmid_neg(1:3,1:3,s)) + tauNS(s,4) = math_tensordot(Mp, -prm%nonSchmid_pos(1:3,1:3,s)) + endif + enddo + tauNS = tauNS + spread(dst%tau_back(:,of),2,4) + tau = tau + dst%tau_back(:,of) + + ! edges + call kinetics(v(:,1), dv_dtau(:,1), dv_dtauNS(:,1), & + tau, tauNS(:,1), dst%tau_pass(:,of),1,Temperature, instance) + v(:,2) = v(:,1) + dv_dtau(:,2) = dv_dtau(:,1) + dv_dtauNS(:,2) = dv_dtauNS(:,1) + + !screws + if (prm%nonSchmidActive) then + v(:,3:4) = spread(v(:,1),2,2) + dv_dtau(:,3:4) = spread(dv_dtau(:,1),2,2) + dv_dtauNS(:,3:4) = spread(dv_dtauNS(:,1),2,2) + else + do t = 3,4 + call kinetics(v(:,t), dv_dtau(:,t), dv_dtauNS(:,t), & + tau, tauNS(:,t), dst%tau_pass(:,of),2,Temperature, instance) + enddo + endif + + stt%v(:,of) = pack(v,.true.) + + !*** Bauschinger effect + forall (s = 1:ns, t = 5:8, rhoSgl(s,t) * v(s,t-4) < 0.0_pReal) & + rhoSgl(s,t-4) = rhoSgl(s,t-4) + abs(rhoSgl(s,t)) + + gdotTotal = sum(rhoSgl(:,1:4) * v, 2) * prm%burgers + + Lp = 0.0_pReal + dLp_dMp = 0.0_pReal + do s = 1,ns + Lp = Lp + gdotTotal(s) * prm%Schmid(1:3,1:3,s) + forall (i=1:3,j=1:3,k=1:3,l=1:3) & + dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & + + prm%Schmid(i,j,s) * prm%Schmid(k,l,s) & + * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * prm%burgers(s) & + + prm%Schmid(i,j,s) & + * ( prm%nonSchmid_pos(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & + - prm%nonSchmid_neg(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4)) * prm%burgers(s) + enddo + + end associate + +end subroutine plastic_nonlocal_LpAndItsTangent + + +!-------------------------------------------------------------------------------------------------- +!> @brief (instantaneous) incremental change of microstructure +!-------------------------------------------------------------------------------------------------- +module subroutine plastic_nonlocal_deltaState(Mp,instance,of,ip,el) + + real(pReal), dimension(3,3), intent(in) :: & + Mp !< MandelStress + integer, intent(in) :: & + instance, & ! current instance of this plasticity + of, & !< offset + ip, & + el + + integer :: & + ph, & !< phase + ns, & ! short notation for the total number of active slip systems + c, & ! character of dislocation + t, & ! type of dislocation + s ! index of my current slip system + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & + deltaRhoRemobilization, & ! density increment by remobilization + deltaRhoDipole2SingleStress ! density increment by dipole dissociation (by stress change) + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & + rho ! current dislocation densities + real(pReal), dimension(param(instance)%sum_N_sl,4) :: & + v ! dislocation glide velocity + real(pReal), dimension(param(instance)%sum_N_sl) :: & + tau ! current resolved shear stress + real(pReal), dimension(param(instance)%sum_N_sl,2) :: & + rhoDip, & ! current dipole dislocation densities (screw and edge dipoles) + dUpper, & ! current maximum stable dipole distance for edges and screws + dUpperOld, & ! old maximum stable dipole distance for edges and screws + deltaDUpper ! change in maximum stable dipole distance for edges and screws + + ph = material_phaseAt(1,el) + + associate(prm => param(instance),dst => microstructure(instance),del => deltaState(instance)) + ns = prm%sum_N_sl + + !*** shortcut to state variables + forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) + forall (s = 1:ns, c = 1:2) dUpperOld(s,c) = plasticState(ph)%state(iD(s,c,instance),of) + + rho = getRho(instance,of,ip,el) + rhoDip = rho(:,dip) + + !**************************************************************************** + !*** dislocation remobilization (bauschinger effect) + where(rho(:,imm) * v < 0.0_pReal) + deltaRhoRemobilization(:,mob) = abs(rho(:,imm)) + deltaRhoRemobilization(:,imm) = - rho(:,imm) + rho(:,mob) = rho(:,mob) + abs(rho(:,imm)) + rho(:,imm) = 0.0_pReal + elsewhere + deltaRhoRemobilization(:,mob) = 0.0_pReal + deltaRhoRemobilization(:,imm) = 0.0_pReal + endwhere + deltaRhoRemobilization(:,dip) = 0.0_pReal + + !**************************************************************************** + !*** calculate dipole formation and dissociation by stress change + + !*** calculate limits for stable dipole height + do s = 1,prm%sum_N_sl + tau(s) = math_tensordot(Mp, prm%Schmid(1:3,1:3,s)) +dst%tau_back(s,of) + if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal + enddo + + dUpper(:,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) + dUpper(:,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) + + where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & + dUpper(:,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(:,1)) + where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & + dUpper(:,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(:,2)) + + dUpper = max(dUpper,prm%minDipoleHeight) + deltaDUpper = dUpper - dUpperOld + + + !*** dissociation by stress increase + deltaRhoDipole2SingleStress = 0.0_pReal + forall (c=1:2, s=1:ns, deltaDUpper(s,c) < 0.0_pReal .and. & + dNeq0(dUpperOld(s,c) - prm%minDipoleHeight(s,c))) & + deltaRhoDipole2SingleStress(s,8+c) = rhoDip(s,c) * deltaDUpper(s,c) & + / (dUpperOld(s,c) - prm%minDipoleHeight(s,c)) + + forall (t=1:4) deltaRhoDipole2SingleStress(:,t) = -0.5_pReal * deltaRhoDipole2SingleStress(:,(t-1)/2+9) + forall (s = 1:ns, c = 1:2) plasticState(ph)%state(iD(s,c,instance),of) = dUpper(s,c) + + plasticState(ph)%deltaState(:,of) = 0.0_pReal + del%rho(:,of) = reshape(deltaRhoRemobilization + deltaRhoDipole2SingleStress, [10*ns]) + +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & + .and. ((debug_e == el .and. debug_i == ip)& + .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then + write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation remobilization', deltaRhoRemobilization(:,1:8) + write(6,'(a,/,10(12x,12(e12.5,1x),/),/)') '<< CONST >> dipole dissociation by stress increase', deltaRhoDipole2SingleStress + endif +#endif + + end associate + +end subroutine plastic_nonlocal_deltaState + + +!--------------------------------------------------------------------------------------------------- +!> @brief calculates the rate of change of microstructure +!--------------------------------------------------------------------------------------------------- +module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature,timestep, & + instance,of,ip,el) + + real(pReal), dimension(3,3), intent(in) :: & + Mp !< MandelStress + real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & + F, & !< elastic deformation gradient + Fp !< plastic deformation gradient + real(pReal), intent(in) :: & + Temperature, & !< temperature + timestep !< substepped crystallite time increment + integer, intent(in) :: & + instance, & + of, & + ip, & !< current integration point + el !< current element number + + integer :: & + ph, & + neighbor_instance, & !< instance of my neighbor's plasticity + ns, & !< short notation for the total number of active slip systems + c, & !< character of dislocation + n, & !< index of my current neighbor + neighbor_el, & !< element number of my neighbor + neighbor_ip, & !< integration point of my neighbor + neighbor_n, & !< neighbor index pointing to me when looking from my neighbor + opposite_neighbor, & !< index of my opposite neighbor + opposite_ip, & !< ip of my opposite neighbor + opposite_el, & !< element index of my opposite neighbor + opposite_n, & !< neighbor index pointing to me when looking from my opposite neighbor + t, & !< type of dislocation + no,& !< neighbor offset shortcut + np,& !< neighbor phase shortcut + topp, & !< type of dislocation with opposite sign to t + s !< index of my current slip system + real(pReal), dimension(param(instance)%sum_N_sl,10) :: & + rho, & + rho0, & !< dislocation density at beginning of time step + rhoDot, & !< density evolution + rhoDotMultiplication, & !< density evolution by multiplication + rhoDotFlux, & !< density evolution by flux + rhoDotSingle2DipoleGlide, & !< density evolution by dipole formation (by glide) + rhoDotAthermalAnnihilation, & !< density evolution by athermal annihilation + rhoDotThermalAnnihilation !< density evolution by thermal annihilation + real(pReal), dimension(param(instance)%sum_N_sl,8) :: & + rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) + neighbor_rhoSgl0, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) + my_rhoSgl0 !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) + real(pReal), dimension(param(instance)%sum_N_sl,4) :: & + v, & !< current dislocation glide velocity + v0, & + neighbor_v0, & !< dislocation glide velocity of enighboring ip + gdot !< shear rates + real(pReal), dimension(param(instance)%sum_N_sl) :: & + tau, & !< current resolved shear stress + vClimb !< climb velocity of edge dipoles + real(pReal), dimension(param(instance)%sum_N_sl,2) :: & + rhoDip, & !< current dipole dislocation densities (screw and edge dipoles) + dLower, & !< minimum stable dipole distance for edges and screws + dUpper !< current maximum stable dipole distance for edges and screws + real(pReal), dimension(3,param(instance)%sum_N_sl,4) :: & + m !< direction of dislocation motion + real(pReal), dimension(3,3) :: & + my_F, & !< my total deformation gradient + neighbor_F, & !< total deformation gradient of my neighbor + my_Fe, & !< my elastic deformation gradient + neighbor_Fe, & !< elastic deformation gradient of my neighbor + Favg !< average total deformation gradient of me and my neighbor + real(pReal), dimension(3) :: & + normal_neighbor2me, & !< interface normal pointing from my neighbor to me in neighbor's lattice configuration + normal_neighbor2me_defConf, & !< interface normal pointing from my neighbor to me in shared deformed configuration + normal_me2neighbor, & !< interface normal pointing from me to my neighbor in my lattice configuration + normal_me2neighbor_defConf !< interface normal pointing from me to my neighbor in shared deformed configuration + real(pReal) :: & + area, & !< area of the current interface + transmissivity, & !< overall transmissivity of dislocation flux to neighboring material point + lineLength, & !< dislocation line length leaving the current interface + selfDiffusion !< self diffusion + + ph = material_phaseAt(1,el) + if (timestep <= 0.0_pReal) then + plasticState(ph)%dotState = 0.0_pReal + return + endif + + associate(prm => param(instance), & + dst => microstructure(instance), & + dot => dotState(instance), & + stt => state(instance)) + ns = prm%sum_N_sl + + tau = 0.0_pReal + gdot = 0.0_pReal + + rho = getRho(instance,of,ip,el) + rhoSgl = rho(:,sgl) + rhoDip = rho(:,dip) + rho0 = getRho0(instance,of,ip,el) + my_rhoSgl0 = rho0(:,sgl) + + forall (s = 1:ns, t = 1:4) v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) + gdot = rhoSgl(:,1:4) * v * spread(prm%burgers,2,4) + +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0 & + .and. ((debug_e == el .and. debug_i == ip)& + .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> rho / 1/m^2', rhoSgl, rhoDip + write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> gdot / 1/s',gdot + endif +#endif + + !**************************************************************************** + !*** limits for stable dipole height + do s = 1,ns + tau(s) = math_tensordot(Mp, prm%Schmid(1:3,1:3,s)) + dst%tau_back(s,of) + if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal + enddo + + dLower = prm%minDipoleHeight + dUpper(:,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) + dUpper(:,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) + + where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & + dUpper(:,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(:,1)) + where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & + dUpper(:,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(:,2)) + + dUpper = max(dUpper,dLower) + + !**************************************************************************** + !*** dislocation multiplication + rhoDotMultiplication = 0.0_pReal + isBCC: if (lattice_structure(ph) == LATTICE_bcc_ID) then + forall (s = 1:ns, sum(abs(v(s,1:4))) > 0.0_pReal) + rhoDotMultiplication(s,1:2) = sum(abs(gdot(s,3:4))) / prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication + * sqrt(stt%rho_forest(s,of)) / prm%lambda0(s) ! & ! mean free path + ! * 2.0_pReal * sum(abs(v(s,3:4))) / sum(abs(v(s,1:4))) ! ratio of screw to overall velocity determines edge generation + rhoDotMultiplication(s,3:4) = sum(abs(gdot(s,3:4))) /prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication + * sqrt(stt%rho_forest(s,of)) / prm%lambda0(s) ! & ! mean free path + ! * 2.0_pReal * sum(abs(v(s,1:2))) / sum(abs(v(s,1:4))) ! ratio of edge to overall velocity determines screw generation + endforall + + else isBCC + rhoDotMultiplication(:,1:4) = spread( & + (sum(abs(gdot(:,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(:,3:4)),2)) & + * sqrt(stt%rho_forest(:,of)) / prm%lambda0 / prm%burgers, 2, 4) + endif isBCC + + forall (s = 1:ns, t = 1:4) v0(s,t) = plasticState(ph)%state0(iV(s,t,instance),of) + + !**************************************************************************** + !*** calculate dislocation fluxes (only for nonlocal plasticity) + rhoDotFlux = 0.0_pReal + if (.not. phase_localPlasticity(material_phaseAt(1,el))) then + + !*** check CFL (Courant-Friedrichs-Lewy) condition for flux + if (any( abs(gdot) > 0.0_pReal & ! any active slip system ... + .and. prm%CFLfactor * abs(v0) * timestep & + > IPvolume(ip,el) / maxval(IParea(:,ip,el)))) then ! ...with velocity above critical value (we use the reference volume and area for simplicity here) +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then + write(6,'(a,i5,a,i2)') '<< CONST >> CFL condition not fullfilled at el ',el,' ip ',ip + write(6,'(a,e10.3,a,e10.3)') '<< CONST >> velocity is at ', & + maxval(abs(v0), abs(gdot) > 0.0_pReal & + .and. prm%CFLfactor * abs(v0) * timestep & + > IPvolume(ip,el) / maxval(IParea(:,ip,el))), & + ' at a timestep of ',timestep + write(6,'(a)') '<< CONST >> enforcing cutback !!!' + endif +#endif + plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! -> return NaN and, hence, enforce cutback + return + endif + + + !*** be aware of the definition of slip_transverse = slip_direction x slip_normal !!! + !*** opposite sign to our t vector in the (s,t,n) triplet !!! + + m(1:3,:,1) = prm%slip_direction + m(1:3,:,2) = -prm%slip_direction + m(1:3,:,3) = -prm%slip_transverse + m(1:3,:,4) = prm%slip_transverse + + my_F = F(1:3,1:3,1,ip,el) + my_Fe = matmul(my_F, math_inv33(Fp(1:3,1:3,1,ip,el))) + + neighbors: do n = 1,nIPneighbors + + neighbor_el = IPneighborhood(1,n,ip,el) + neighbor_ip = IPneighborhood(2,n,ip,el) + neighbor_n = IPneighborhood(3,n,ip,el) + np = material_phaseAt(1,neighbor_el) + no = material_phasememberAt(1,neighbor_ip,neighbor_el) + + opposite_neighbor = n + mod(n,2) - mod(n+1,2) + opposite_el = IPneighborhood(1,opposite_neighbor,ip,el) + opposite_ip = IPneighborhood(2,opposite_neighbor,ip,el) + opposite_n = IPneighborhood(3,opposite_neighbor,ip,el) + + if (neighbor_n > 0) then ! if neighbor exists, average deformation gradient + neighbor_instance = phase_plasticityInstance(material_phaseAt(1,neighbor_el)) + neighbor_F = F(1:3,1:3,1,neighbor_ip,neighbor_el) + neighbor_Fe = matmul(neighbor_F, math_inv33(Fp(1:3,1:3,1,neighbor_ip,neighbor_el))) + Favg = 0.5_pReal * (my_F + neighbor_F) + else ! if no neighbor, take my value as average + Favg = my_F + endif + + neighbor_v0 = 0.0_pReal ! needed for check of sign change in flux density below + + !* FLUX FROM MY NEIGHBOR TO ME + !* This is only considered, if I have a neighbor of nonlocal plasticity + !* (also nonlocal constitutive law with local properties) that is at least a little bit + !* compatible. + !* If it's not at all compatible, no flux is arriving, because everything is dammed in front of + !* my neighbor's interface. + !* The entering flux from my neighbor will be distributed on my slip systems according to the + !* compatibility + if (neighbor_n > 0) then + if (phase_plasticity(material_phaseAt(1,neighbor_el)) == PLASTICITY_NONLOCAL_ID .and. & + any(compatibility(:,:,:,n,ip,el) > 0.0_pReal)) then + + forall (s = 1:ns, t = 1:4) + neighbor_v0(s,t) = plasticState(np)%state0(iV (s,t,neighbor_instance),no) + neighbor_rhoSgl0(s,t) = max(plasticState(np)%state0(iRhoU(s,t,neighbor_instance),no),0.0_pReal) + endforall + + where (neighbor_rhoSgl0 * IPvolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & + .or. neighbor_rhoSgl0 < prm%significantRho) & + neighbor_rhoSgl0 = 0.0_pReal + normal_neighbor2me_defConf = math_det33(Favg) * matmul(math_inv33(transpose(Favg)), & + IPareaNormal(1:3,neighbor_n,neighbor_ip,neighbor_el)) ! normal of the interface in (average) deformed configuration (pointing neighbor => me) + normal_neighbor2me = matmul(transpose(neighbor_Fe), normal_neighbor2me_defConf) & + / math_det33(neighbor_Fe) ! interface normal in the lattice configuration of my neighbor + area = IParea(neighbor_n,neighbor_ip,neighbor_el) * norm2(normal_neighbor2me) + normal_neighbor2me = normal_neighbor2me / norm2(normal_neighbor2me) ! normalize the surface normal to unit length + do s = 1,ns + do t = 1,4 + c = (t + 1) / 2 + topp = t + mod(t,2) - mod(t+1,2) + if (neighbor_v0(s,t) * math_inner(m(1:3,s,t), normal_neighbor2me) > 0.0_pReal & ! flux from my neighbor to me == entering flux for me + .and. v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal ) then ! ... only if no sign change in flux density + lineLength = neighbor_rhoSgl0(s,t) * neighbor_v0(s,t) & + * math_inner(m(1:3,s,t), normal_neighbor2me) * area ! positive line length that wants to enter through this interface + where (compatibility(c,:,s,n,ip,el) > 0.0_pReal) & + rhoDotFlux(:,t) = rhoDotFlux(1:ns,t) & + + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to equally signed mobile dislocation type + where (compatibility(c,:,s,n,ip,el) < 0.0_pReal) & + rhoDotFlux(:,topp) = rhoDotFlux(:,topp) & + + lineLength/IPvolume(ip,el)*compatibility(c,:,s,n,ip,el)**2.0_pReal ! transferring to opposite signed mobile dislocation type + + endif + enddo + enddo + endif; endif + + + !* FLUX FROM ME TO MY NEIGHBOR + !* This is not considered, if my opposite neighbor has a different constitutive law than nonlocal (still considered for nonlocal law with local properties). + !* Then, we assume, that the opposite(!) neighbor sends an equal amount of dislocations to me. + !* So the net flux in the direction of my neighbor is equal to zero: + !* leaving flux to neighbor == entering flux from opposite neighbor + !* In case of reduced transmissivity, part of the leaving flux is stored as dead dislocation density. + !* That means for an interface of zero transmissivity the leaving flux is fully converted to dead dislocations. + if (opposite_n > 0) then + if (phase_plasticity(material_phaseAt(1,opposite_el)) == PLASTICITY_NONLOCAL_ID) then + + normal_me2neighbor_defConf = math_det33(Favg) & + * matmul(math_inv33(transpose(Favg)),IPareaNormal(1:3,n,ip,el)) ! normal of the interface in (average) deformed configuration (pointing me => neighbor) + normal_me2neighbor = matmul(transpose(my_Fe), normal_me2neighbor_defConf) & + / math_det33(my_Fe) ! interface normal in my lattice configuration + area = IParea(n,ip,el) * norm2(normal_me2neighbor) + normal_me2neighbor = normal_me2neighbor / norm2(normal_me2neighbor) ! normalize the surface normal to unit length + do s = 1,ns + do t = 1,4 + c = (t + 1) / 2 + if (v0(s,t) * math_inner(m(1:3,s,t), normal_me2neighbor) > 0.0_pReal ) then ! flux from me to my neighbor == leaving flux for me (might also be a pure flux from my mobile density to dead density if interface not at all transmissive) + if (v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal) then ! no sign change in flux density + transmissivity = sum(compatibility(c,:,s,n,ip,el)**2.0_pReal) ! overall transmissivity from this slip system to my neighbor + else ! sign change in flux density means sign change in stress which does not allow for dislocations to arive at the neighbor + transmissivity = 0.0_pReal + endif + lineLength = my_rhoSgl0(s,t) * v0(s,t) & + * math_inner(m(1:3,s,t), normal_me2neighbor) * area ! positive line length of mobiles that wants to leave through this interface + rhoDotFlux(s,t) = rhoDotFlux(s,t) - lineLength / IPvolume(ip,el) ! subtract dislocation flux from current type + rhoDotFlux(s,t+4) = rhoDotFlux(s,t+4) & + + lineLength / IPvolume(ip,el) * (1.0_pReal - transmissivity) & + * sign(1.0_pReal, v0(s,t)) ! dislocation flux that is not able to leave through interface (because of low transmissivity) will remain as immobile single density at the material point + endif + enddo + enddo + endif; endif + + enddo neighbors + endif + + + + !**************************************************************************** + !*** calculate dipole formation and annihilation + + !*** formation by glide + do c = 1,2 + rhoDotSingle2DipoleGlide(:,2*c-1) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile + + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile + + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) ! positive mobile --> negative immobile + + rhoDotSingle2DipoleGlide(:,2*c) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * ( rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) & ! negative mobile --> positive mobile + + rhoSgl(:,2*c) * abs(gdot(:,2*c-1)) & ! positive mobile --> negative mobile + + abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c))) ! negative mobile --> positive immobile + + rhoDotSingle2DipoleGlide(:,2*c+3) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * rhoSgl(:,2*c+3) * abs(gdot(:,2*c)) ! negative mobile --> positive immobile + + rhoDotSingle2DipoleGlide(:,2*c+4) = -2.0_pReal * dUpper(:,c) / prm%burgers & + * rhoSgl(:,2*c+4) * abs(gdot(:,2*c-1)) ! positive mobile --> negative immobile + + rhoDotSingle2DipoleGlide(:,c+8) = abs(rhoDotSingle2DipoleGlide(:,2*c+3)) & + + abs(rhoDotSingle2DipoleGlide(:,2*c+4)) & + - rhoDotSingle2DipoleGlide(:,2*c-1) & + - rhoDotSingle2DipoleGlide(:,2*c) + enddo + + + !*** athermal annihilation + rhoDotAthermalAnnihilation = 0.0_pReal + forall (c=1:2) & + rhoDotAthermalAnnihilation(:,c+8) = -2.0_pReal * dLower(:,c) / prm%burgers & + * ( 2.0_pReal * (rhoSgl(:,2*c-1) * abs(gdot(:,2*c)) + rhoSgl(:,2*c) * abs(gdot(:,2*c-1))) & ! was single hitting single + + 2.0_pReal * (abs(rhoSgl(:,2*c+3)) * abs(gdot(:,2*c)) + abs(rhoSgl(:,2*c+4)) * abs(gdot(:,2*c-1))) & ! was single hitting immobile single or was immobile single hit by single + + rhoDip(:,c) * (abs(gdot(:,2*c-1)) + abs(gdot(:,2*c)))) ! single knocks dipole constituent + + ! annihilated screw dipoles leave edge jogs behind on the colinear system + if (lattice_structure(ph) == LATTICE_fcc_ID) & + forall (s = 1:ns, prm%colinearSystem(s) > 0) & + rhoDotAthermalAnnihilation(prm%colinearSystem(s),1:2) = - rhoDotAthermalAnnihilation(s,10) & + * 0.25_pReal * sqrt(stt%rho_forest(s,of)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor + + + !*** thermally activated annihilation of edge dipoles by climb + rhoDotThermalAnnihilation = 0.0_pReal + selfDiffusion = prm%Dsd0 * exp(-prm%selfDiffusionEnergy / (kB * Temperature)) + vClimb = prm%atomicVolume * selfDiffusion * prm%mu & + / ( kB * Temperature * PI * (1.0_pReal-prm%nu) * (dUpper(:,1) + dLower(:,1))) + forall (s = 1:ns, dUpper(s,1) > dLower(s,1)) & + rhoDotThermalAnnihilation(s,9) = max(- 4.0_pReal * rhoDip(s,1) * vClimb(s) / (dUpper(s,1) - dLower(s,1)), & + - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & + - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have + + rhoDot = rhoDotFlux & + + rhoDotMultiplication & + + rhoDotSingle2DipoleGlide & + + rhoDotAthermalAnnihilation & + + rhoDotThermalAnnihilation + +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & + .and. ((debug_e == el .and. debug_i == ip)& + .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then + write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & + rhoDotMultiplication(:,1:4) * timestep + write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation flux', & + rhoDotFlux(:,1:8) * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> dipole formation by glide', & + rhoDotSingle2DipoleGlide * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> athermal dipole annihilation', & + rhoDotAthermalAnnihilation * timestep + write(6,'(a,/,2(12x,12(e12.5,1x),/))') '<< CONST >> thermally activated dipole annihilation', & + rhoDotThermalAnnihilation(:,9:10) * timestep + write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> total density change', & + rhoDot * timestep + write(6,'(a,/,10(12x,12(f12.5,1x),/))') '<< CONST >> relative density change', & + rhoDot(:,1:8) * timestep / (abs(stt%rho(:,sgl))+1.0e-10), & + rhoDot(:,9:10) * timestep / (stt%rho(:,dip)+1.0e-10) + write(6,*) + endif +#endif + + + if ( any(rho(:,mob) + rhoDot(:,1:4) * timestep < -prm%atol_rho) & + .or. any(rho(:,dip) + rhoDot(:,9:10) * timestep < -prm%atol_rho)) then +#ifdef DEBUG + if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then + write(6,'(a,i5,a,i2)') '<< CONST >> evolution rate leads to negative density at el ',el,' ip ',ip + write(6,'(a)') '<< CONST >> enforcing cutback !!!' + endif +#endif + plasticState(ph)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) + else + dot%rho(:,of) = pack(rhoDot,.true.) + dot%gamma(:,of) = sum(gdot,2) + endif + + end associate + +end subroutine plastic_nonlocal_dotState + + +!-------------------------------------------------------------------------------------------------- +!> @brief Compatibility update +!> @detail Compatibility is defined as normalized product of signed cosine of the angle between the slip +! plane normals and signed cosine of the angle between the slip directions. Only the largest values +! that sum up to a total of 1 are considered, all others are set to zero. +!-------------------------------------------------------------------------------------------------- +module subroutine plastic_nonlocal_updateCompatibility(orientation,instance,i,e) + + type(rotation), dimension(1,discretization_nIP,discretization_nElem), intent(in) :: & + orientation ! crystal orientation + integer, intent(in) :: & + instance, & + i, & + e + + integer :: & + n, & ! neighbor index + neighbor_e, & ! element index of my neighbor + neighbor_i, & ! integration point index of my neighbor + ph, & + neighbor_phase, & + ns, & ! number of active slip systems + s1, & ! slip system index (me) + s2 ! slip system index (my neighbor) + real(pReal), dimension(2,param(instance)%sum_N_sl,param(instance)%sum_N_sl,nIPneighbors) :: & + my_compatibility ! my_compatibility for current element and ip + real(pReal) :: & + my_compatibilitySum, & + thresholdValue, & + nThresholdValues + logical, dimension(param(instance)%sum_N_sl) :: & + belowThreshold + type(rotation) :: mis + + ph = material_phaseAt(1,e) + + associate(prm => param(instance)) + ns = prm%sum_N_sl + + !*** start out fully compatible + my_compatibility = 0.0_pReal + forall(s1 = 1:ns) my_compatibility(:,s1,s1,:) = 1.0_pReal + + neighbors: do n = 1,nIPneighbors + neighbor_e = IPneighborhood(1,n,i,e) + neighbor_i = IPneighborhood(2,n,i,e) + + neighbor_phase = material_phaseAt(1,neighbor_e) + + if (neighbor_e <= 0 .or. neighbor_i <= 0) then + !* FREE SURFACE + !* Set surface transmissivity to the value specified in the material.config + forall(s1 = 1:ns) my_compatibility(:,s1,s1,n) = sqrt(prm%surfaceTransmissivity) + elseif (neighbor_phase /= ph) then + !* PHASE BOUNDARY + !* If we encounter a different nonlocal phase at the neighbor, + !* we consider this to be a real "physical" phase boundary, so completely incompatible. + !* If one of the two phases has a local plasticity law, + !* we do not consider this to be a phase boundary, so completely compatible. + if (.not. phase_localPlasticity(neighbor_phase) .and. .not. phase_localPlasticity(ph)) & + forall(s1 = 1:ns) my_compatibility(:,s1,s1,n) = 0.0_pReal + elseif (prm%grainboundaryTransmissivity >= 0.0_pReal) then + !* GRAIN BOUNDARY ! + !* fixed transmissivity for adjacent ips with different texture (only if explicitly given in material.config) + if (material_texture(1,i,e) /= material_texture(1,neighbor_i,neighbor_e) .and. & + (.not. phase_localPlasticity(neighbor_phase))) & + forall(s1 = 1:ns) my_compatibility(:,s1,s1,n) = sqrt(prm%grainboundaryTransmissivity) + else + !* GRAIN BOUNDARY ? + !* Compatibility defined by relative orientation of slip systems: + !* The my_compatibility value is defined as the product of the slip normal projection and the slip direction projection. + !* Its sign is always positive for screws, for edges it has the same sign as the slip normal projection. + !* Since the sum for each slip system can easily exceed one (which would result in a transmissivity larger than one), + !* only values above or equal to a certain threshold value are considered. This threshold value is chosen, such that + !* the number of compatible slip systems is minimized with the sum of the original compatibility values exceeding one. + !* Finally the smallest compatibility value is decreased until the sum is exactly equal to one. + !* All values below the threshold are set to zero. + mis = orientation(1,i,e)%misorientation(orientation(1,neighbor_i,neighbor_e)) + mySlipSystems: do s1 = 1,ns + neighborSlipSystems: do s2 = 1,ns + my_compatibility(1,s2,s1,n) = math_inner(prm%slip_normal(1:3,s1), & + mis%rotate(prm%slip_normal(1:3,s2))) & + * abs(math_inner(prm%slip_direction(1:3,s1), & + mis%rotate(prm%slip_direction(1:3,s2)))) + my_compatibility(2,s2,s1,n) = abs(math_inner(prm%slip_normal(1:3,s1), & + mis%rotate(prm%slip_normal(1:3,s2)))) & + * abs(math_inner(prm%slip_direction(1:3,s1), & + mis%rotate(prm%slip_direction(1:3,s2)))) + enddo neighborSlipSystems + + my_compatibilitySum = 0.0_pReal + belowThreshold = .true. + do while (my_compatibilitySum < 1.0_pReal .and. any(belowThreshold)) + thresholdValue = maxval(my_compatibility(2,:,s1,n), belowThreshold) ! screws always positive + nThresholdValues = real(count(my_compatibility(2,:,s1,n) >= thresholdValue),pReal) + where (my_compatibility(2,:,s1,n) >= thresholdValue) belowThreshold = .false. + if (my_compatibilitySum + thresholdValue * nThresholdValues > 1.0_pReal) & + where (abs(my_compatibility(:,:,s1,n)) >= thresholdValue) & + my_compatibility(:,:,s1,n) = sign((1.0_pReal - my_compatibilitySum)/nThresholdValues,& + my_compatibility(:,:,s1,n)) + my_compatibilitySum = my_compatibilitySum + nThresholdValues * thresholdValue + enddo + + where(belowThreshold) my_compatibility(1,:,s1,n) = 0.0_pReal + where(belowThreshold) my_compatibility(2,:,s1,n) = 0.0_pReal + + enddo mySlipSystems + endif + + enddo neighbors + + compatibility(:,:,:,:,i,e) = my_compatibility + + end associate + +end subroutine plastic_nonlocal_updateCompatibility + + +!-------------------------------------------------------------------------------------------------- +!> @brief writes results to HDF5 output file +!-------------------------------------------------------------------------------------------------- +module subroutine plastic_nonlocal_results(instance,group) + + integer, intent(in) :: instance + character(len=*),intent(in) :: group + + integer :: o + + associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance)) + outputsLoop: do o = 1,size(prm%output) + select case(trim(prm%output(o))) + case('rho_sgl_mob_edg_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_pos, 'rho_sgl_mob_edg_pos', & + 'positive mobile edge density','1/m²') + case('rho_sgl_imm_edg_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_pos, 'rho_sgl_imm_edg_pos',& + 'positive immobile edge density','1/m²') + case('rho_sgl_mob_edg_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_neg, 'rho_sgl_mob_edg_neg',& + 'negative mobile edge density','1/m²') + case('rho_sgl_imm_edg_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_neg, 'rho_sgl_imm_edg_neg',& + 'negative immobile edge density','1/m²') + case('rho_dip_edg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip_edg, 'rho_dip_edg',& + 'edge dipole density','1/m²') + case('rho_sgl_mob_scr_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_pos, 'rho_sgl_mob_scr_pos',& + 'positive mobile screw density','1/m²') + case('rho_sgl_imm_scr_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_pos, 'rho_sgl_imm_scr_pos',& + 'positive immobile screw density','1/m²') + case('rho_sgl_mob_scr_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_neg, 'rho_sgl_mob_scr_neg',& + 'negative mobile screw density','1/m²') + case('rho_sgl_imm_scr_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_neg, 'rho_sgl_imm_scr_neg',& + 'negative immobile screw density','1/m²') + case('rho_dip_scr') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_dip_scr, 'rho_dip_scr',& + 'screw dipole density','1/m²') + case('rho_forest') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%rho_forest, 'rho_forest',& + 'forest density','1/m²') + case('v_edg_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%v_edg_pos, 'v_edg_pos',& + 'positive edge velocity','m/s') + case('v_edg_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%v_edg_neg, 'v_edg_neg',& + 'negative edge velocity','m/s') + case('v_scr_pos') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%v_scr_pos, 'v_scr_pos',& + 'positive srew velocity','m/s') + case('v_scr_neg') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%v_scr_neg, 'v_scr_neg',& + 'negative screw velocity','m/s') + case('gamma') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma,'gamma',& + 'plastic shear','1') + case('tau_pass') + if(prm%sum_N_sl>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',& + 'passing stress for slip','Pa') + end select + enddo outputsLoop + end associate + +end subroutine plastic_nonlocal_results + + +!-------------------------------------------------------------------------------------------------- +!> @brief populates the initial dislocation density +!-------------------------------------------------------------------------------------------------- +subroutine stateInit(ini,phase,NipcMyPhase) + + type(tInitialParameters) :: & + ini + integer,intent(in) :: & + phase, & + NipcMyPhase + integer :: & + e, & + i, & + f, & + from, & + upto, & + s, & + instance, & + phasemember + real(pReal), dimension(2) :: & + noise, & + rnd + real(pReal) :: & + meanDensity, & + totalVolume, & + densityBinning, & + minimumIpVolume + real(pReal), dimension(NipcMyPhase) :: & + volume + + instance = phase_plasticityInstance(phase) + associate(stt => state(instance)) + + if (ini%rhoSglRandom > 0.0_pReal) then ! randomly distribute dislocation segments on random slip system and of random type in the volume + do e = 1,discretization_nElem + do i = 1,discretization_nIP + if (material_phaseAt(1,e) == phase) volume(material_phasememberAt(1,i,e)) = IPvolume(i,e) + enddo + enddo + totalVolume = sum(volume) + minimumIPVolume = minval(volume) + densityBinning = ini%rhoSglRandomBinning / minimumIpVolume ** (2.0_pReal / 3.0_pReal) + + ! fill random material points with dislocation segments until the desired overall density is reached + meanDensity = 0.0_pReal + do while(meanDensity < ini%rhoSglRandom) + call random_number(rnd) + phasemember = nint(rnd(1)*real(NipcMyPhase,pReal) + 0.5_pReal) + s = nint(rnd(2)*real(sum(ini%N_sl),pReal)*4.0_pReal + 0.5_pReal) + meanDensity = meanDensity + densityBinning * volume(phasemember) / totalVolume + stt%rhoSglMobile(s,phasemember) = densityBinning + enddo + else ! homogeneous distribution with noise + do e = 1, NipcMyPhase + do f = 1,size(ini%N_sl,1) + from = 1 + sum(ini%N_sl(1:f-1)) + upto = sum(ini%N_sl(1:f)) + do s = from,upto + noise = [math_sampleGaussVar(0.0_pReal, ini%rhoSglScatter), & + math_sampleGaussVar(0.0_pReal, ini%rhoSglScatter)] + stt%rho_sgl_mob_edg_pos(s,e) = ini%rhoSglEdgePos0(f) + noise(1) + stt%rho_sgl_mob_edg_neg(s,e) = ini%rhoSglEdgeNeg0(f) + noise(1) + stt%rho_sgl_mob_scr_pos(s,e) = ini%rhoSglScrewPos0(f) + noise(2) + stt%rho_sgl_mob_scr_neg(s,e) = ini%rhoSglScrewNeg0(f) + noise(2) + enddo + stt%rho_dip_edg(from:upto,e) = ini%rhoDipEdge0(f) + stt%rho_dip_scr(from:upto,e) = ini%rhoDipScrew0(f) + enddo + enddo + endif + + end associate + +end subroutine stateInit + + +!-------------------------------------------------------------------------------------------------- +!> @brief calculates kinetics +!-------------------------------------------------------------------------------------------------- +subroutine kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, tauThreshold, c, Temperature, instance) + + integer, intent(in) :: & + c, & !< dislocation character (1:edge, 2:screw) + instance + real(pReal), intent(in) :: & + Temperature !< temperature + real(pReal), dimension(param(instance)%sum_N_sl), intent(in) :: & tau, & !< resolved external shear stress (without non Schmid effects) tauNS, & !< resolved external shear stress (including non Schmid effects) tauThreshold !< threshold shear stress - - real(pReal), dimension(param(instance)%totalNslip), intent(out) :: & + real(pReal), dimension(param(instance)%sum_N_sl), intent(out) :: & v, & !< velocity dv_dtau, & !< velocity derivative with respect to resolved shear stress (without non Schmid contributions) dv_dtauNS !< velocity derivative with respect to resolved shear stress (including non Schmid contributions) @@ -898,933 +1654,72 @@ subroutine plastic_nonlocal_kinetics(v, dv_dtau, dv_dtauNS, tau, tauNS, & mobility !< dislocation mobility associate(prm => param(instance)) - ns = prm%totalNslip + ns = prm%sum_N_sl v = 0.0_pReal dv_dtau = 0.0_pReal dv_dtauNS = 0.0_pReal - - if (Temperature > 0.0_pReal) then - do s = 1,ns - if (abs(tau(s)) > tauThreshold(s)) then - - !* Peierls contribution - !* Effective stress includes non Schmid constributions - !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity - - tauEff = max(0.0_pReal, abs(tauNS(s)) - tauThreshold(s)) ! ensure that the effective stress is positive - meanfreepath_P = prm%burgers(s) - jumpWidth_P = prm%burgers(s) - activationLength_P = prm%doublekinkwidth *prm%burgers(s) - activationVolume_P = activationLength_P * jumpWidth_P * prm%burgers(s) - criticalStress_P = prm%peierlsStress(s,c) - activationEnergy_P = criticalStress_P * activationVolume_P - tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one - tPeierls = 1.0_pReal / prm%fattack & - * exp(activationEnergy_P / (KB * Temperature) & - * (1.0_pReal - tauRel_P**prm%p)**prm%q) - if (tauEff < criticalStress_P) then - dtPeierls_dtau = tPeierls * prm%p * prm%q * activationVolume_P / (KB * Temperature) & - * (1.0_pReal - tauRel_P**prm%p)**(prm%q-1.0_pReal) & - * tauRel_P**(prm%p-1.0_pReal) - else - dtPeierls_dtau = 0.0_pReal - endif - - - !* Contribution from solid solution strengthening - !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity - - tauEff = abs(tau(s)) - tauThreshold(s) - meanfreepath_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) - jumpWidth_S = prm%solidSolutionSize * prm%burgers(s) - activationLength_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) - activationVolume_S = activationLength_S * jumpWidth_S * prm%burgers(s) - activationEnergy_S = prm%solidSolutionEnergy - criticalStress_S = activationEnergy_S / activationVolume_S - tauRel_S = min(1.0_pReal, tauEff / criticalStress_S) ! ensure that the activation probability cannot become greater than one - tSolidSolution = 1.0_pReal / prm%fattack & - * exp(activationEnergy_S / (KB * Temperature) & - * (1.0_pReal - tauRel_S**prm%p)**prm%q) - if (tauEff < criticalStress_S) then - dtSolidSolution_dtau = tSolidSolution * prm%p * prm%q & - * activationVolume_S / (KB * Temperature) & - * (1.0_pReal - tauRel_S**prm%p)**(prm%q-1.0_pReal) & - * tauRel_S**(prm%p-1.0_pReal) - else - dtSolidSolution_dtau = 0.0_pReal - endif - - - !* viscous glide velocity - - tauEff = abs(tau(s)) - tauThreshold(s) - mobility = prm%burgers(s) / prm%viscosity - vViscous = mobility * tauEff - - - !* Mean velocity results from waiting time at peierls barriers and solid solution obstacles with respective meanfreepath of - !* free flight at glide velocity in between. - !* adopt sign from resolved stress - - v(s) = sign(1.0_pReal,tau(s)) & - / (tPeierls / meanfreepath_P + tSolidSolution / meanfreepath_S + 1.0_pReal / vViscous) - dv_dtau(s) = v(s) * v(s) * (dtSolidSolution_dtau / meanfreepath_S & - + mobility / (vViscous * vViscous)) - dv_dtauNS(s) = v(s) * v(s) * dtPeierls_dtau / meanfreepath_P - endif - enddo - endif - - -#ifdef DEBUGTODO - write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tauThreshold / MPa', tauThreshold * 1e-6_pReal - write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tau / MPa', tau * 1e-6_pReal - write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> tauNS / MPa', tauNS * 1e-6_pReal - write(6,'(a,/,12x,12(f12.5,1x))') '<< CONST >> v / mm/s', v * 1e3 - write(6,'(a,/,12x,12(e12.5,1x))') '<< CONST >> dv_dtau', dv_dtau - write(6,'(a,/,12x,12(e12.5,1x))') '<< CONST >> dv_dtauNS', dv_dtauNS -#endif - - end associate - -end subroutine plastic_nonlocal_kinetics - - -!-------------------------------------------------------------------------------------------------- -!> @brief calculates plastic velocity gradient and its tangent -!-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_LpAndItsTangent(Lp, dLp_dMp, & - Mp, Temperature, volume, ip, el) - - integer, intent(in) :: & - ip, & !< current integration point - el !< current element number - real(pReal), intent(in) :: & - Temperature, & !< temperature - volume !< volume of the materialpoint - real(pReal), dimension(3,3), intent(in) :: & - Mp - real(pReal), dimension(3,3), intent(out) :: & - Lp !< plastic velocity gradient - real(pReal), dimension(3,3,3,3), intent(out) :: & - dLp_dMp !< derivative of Lp with respect to Tstar (9x9 matrix) - - - integer :: & - instance, & !< current instance of this plasticity - ns, & !< short notation for the total number of active slip systems - i, & - j, & - k, & - l, & - ph, & !phase number - of, & !offset - t, & !< dislocation type - s !< index of my current slip system - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),8) :: & - rhoSgl !< single dislocation densities (including blocked) - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),10) :: & - rho - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),4) :: & - v, & !< velocity - tauNS, & !< resolved shear stress including non Schmid and backstress terms - dv_dtau, & !< velocity derivative with respect to the shear stress - dv_dtauNS !< velocity derivative with respect to the shear stress - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & - tau, & !< resolved shear stress including backstress terms - gdotTotal !< shear rate - - !*** shortcut for mapping - ph = material_phaseAt(1,el) - of = material_phasememberAt(1,ip,el) - - instance = phase_plasticityInstance(ph) - associate(prm => param(instance),dst=>microstructure(instance),stt=>state(instance)) - ns = prm%totalNslip - - !*** shortcut to state variables - rho = getRho(instance,of,ip,el) - rhoSgl = rho(:,sgl) - - - !*** get resolved shear stress - !*** for screws possible non-schmid contributions are also taken into account do s = 1,ns - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) - tauNS(s,1) = tau(s) - tauNS(s,2) = tau(s) - if (tau(s) > 0.0_pReal) then - tauNS(s,3) = math_mul33xx33(Mp, +prm%nonSchmid_pos(1:3,1:3,s)) - tauNS(s,4) = math_mul33xx33(Mp, -prm%nonSchmid_neg(1:3,1:3,s)) - else - tauNS(s,3) = math_mul33xx33(Mp, +prm%nonSchmid_neg(1:3,1:3,s)) - tauNS(s,4) = math_mul33xx33(Mp, -prm%nonSchmid_pos(1:3,1:3,s)) + if (abs(tau(s)) > tauThreshold(s)) then + + !* Peierls contribution + !* Effective stress includes non Schmid constributions + !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity + tauEff = max(0.0_pReal, abs(tauNS(s)) - tauThreshold(s)) ! ensure that the effective stress is positive + meanfreepath_P = prm%burgers(s) + jumpWidth_P = prm%burgers(s) + activationLength_P = prm%doublekinkwidth *prm%burgers(s) + activationVolume_P = activationLength_P * jumpWidth_P * prm%burgers(s) + criticalStress_P = prm%peierlsStress(s,c) + activationEnergy_P = criticalStress_P * activationVolume_P + tauRel_P = min(1.0_pReal, tauEff / criticalStress_P) ! ensure that the activation probability cannot become greater than one + tPeierls = 1.0_pReal / prm%fattack & + * exp(activationEnergy_P / (kB * Temperature) & + * (1.0_pReal - tauRel_P**prm%p)**prm%q) + if (tauEff < criticalStress_P) then + dtPeierls_dtau = tPeierls * prm%p * prm%q * activationVolume_P / (kB * Temperature) & + * (1.0_pReal - tauRel_P**prm%p)**(prm%q-1.0_pReal) * tauRel_P**(prm%p-1.0_pReal) + else + dtPeierls_dtau = 0.0_pReal + endif + + !* Contribution from solid solution strengthening + !* The derivative only gives absolute values; the correct sign is taken care of in the formula for the derivative of the velocity + tauEff = abs(tau(s)) - tauThreshold(s) + meanfreepath_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) + jumpWidth_S = prm%solidSolutionSize * prm%burgers(s) + activationLength_S = prm%burgers(s) / sqrt(prm%solidSolutionConcentration) + activationVolume_S = activationLength_S * jumpWidth_S * prm%burgers(s) + activationEnergy_S = prm%solidSolutionEnergy + criticalStress_S = activationEnergy_S / activationVolume_S + tauRel_S = min(1.0_pReal, tauEff / criticalStress_S) ! ensure that the activation probability cannot become greater than one + tSolidSolution = 1.0_pReal / prm%fattack & + * exp(activationEnergy_S / (kB * Temperature)* (1.0_pReal - tauRel_S**prm%p)**prm%q) + if (tauEff < criticalStress_S) then + dtSolidSolution_dtau = tSolidSolution * prm%p * prm%q * activationVolume_S / (kB * Temperature) & + * (1.0_pReal - tauRel_S**prm%p)**(prm%q-1.0_pReal)* tauRel_S**(prm%p-1.0_pReal) + else + dtSolidSolution_dtau = 0.0_pReal + endif + + !* viscous glide velocity + tauEff = abs(tau(s)) - tauThreshold(s) + mobility = prm%burgers(s) / prm%viscosity + vViscous = mobility * tauEff + + !* Mean velocity results from waiting time at peierls barriers and solid solution obstacles with respective meanfreepath of + !* free flight at glide velocity in between. + !* adopt sign from resolved stress + v(s) = sign(1.0_pReal,tau(s)) & + / (tPeierls / meanfreepath_P + tSolidSolution / meanfreepath_S + 1.0_pReal / vViscous) + dv_dtau(s) = v(s)**2.0_pReal * (dtSolidSolution_dtau / meanfreepath_S + mobility /vViscous**2.0_pReal) + dv_dtauNS(s) = v(s)**2.0_pReal * dtPeierls_dtau / meanfreepath_P endif enddo - forall (t = 1:4) & - tauNS(1:ns,t) = tauNS(1:ns,t) + dst%tau_back(:,of) - tau = tau + dst%tau_back(:,of) - - - !*** get dislocation velocity and its tangent and store the velocity in the state array - - ! edges - call plastic_nonlocal_kinetics(v(1:ns,1), dv_dtau(1:ns,1), dv_dtauNS(1:ns,1), & - tau(1:ns), tauNS(1:ns,1), dst%tau_pass(1:ns,of), & - 1, Temperature, instance, of) - v(1:ns,2) = v(1:ns,1) - dv_dtau(1:ns,2) = dv_dtau(1:ns,1) - dv_dtauNS(1:ns,2) = dv_dtauNS(1:ns,1) - - !screws - if (size(prm%nonSchmidCoeff) == 0) then - forall(t = 3:4) - v(1:ns,t) = v(1:ns,1) - dv_dtau(1:ns,t) = dv_dtau(1:ns,1) - dv_dtauNS(1:ns,t) = dv_dtauNS(1:ns,1) - endforall - else - do t = 3,4 - call plastic_nonlocal_kinetics(v(1:ns,t), dv_dtau(1:ns,t), dv_dtauNS(1:ns,t), & - tau(1:ns), tauNS(1:ns,t), dst%tau_pass(1:ns,of), & - 2 , Temperature, instance, of) - enddo - endif - - stt%v(:,of) = pack(v,.true.) - - !*** Bauschinger effect - forall (s = 1:ns, t = 5:8, rhoSgl(s,t) * v(s,t-4) < 0.0_pReal) & - rhoSgl(s,t-4) = rhoSgl(s,t-4) + abs(rhoSgl(s,t)) - - - gdotTotal = sum(rhoSgl(1:ns,1:4) * v, 2) * prm%burgers(1:ns) - - Lp = 0.0_pReal - dLp_dMp = 0.0_pReal - - do s = 1,ns - Lp = Lp + gdotTotal(s) * prm%Schmid(1:3,1:3,s) - forall (i=1:3,j=1:3,k=1:3,l=1:3) & - dLp_dMp(i,j,k,l) = dLp_dMp(i,j,k,l) & - + prm%Schmid(i,j,s) * prm%Schmid(k,l,s) & - * sum(rhoSgl(s,1:4) * dv_dtau(s,1:4)) * prm%burgers(s) & - + prm%Schmid(i,j,s) & - * ( prm%nonSchmid_pos(k,l,s) * rhoSgl(s,3) * dv_dtauNS(s,3) & - - prm%nonSchmid_neg(k,l,s) * rhoSgl(s,4) * dv_dtauNS(s,4)) * prm%burgers(s) - enddo - end associate -end subroutine plastic_nonlocal_LpAndItsTangent - - -!-------------------------------------------------------------------------------------------------- -!> @brief (instantaneous) incremental change of microstructure -!-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_deltaState(Mp,ip,el) - - integer, intent(in) :: & - ip, & - el - real(pReal), dimension(3,3), intent(in) :: & - Mp !< MandelStress - - integer :: & - ph, & !< phase - of, & !< offset - instance, & ! current instance of this plasticity - ns, & ! short notation for the total number of active slip systems - c, & ! character of dislocation - t, & ! type of dislocation - s ! index of my current slip system - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),10) :: & - deltaRhoRemobilization, & ! density increment by remobilization - deltaRhoDipole2SingleStress ! density increment by dipole dissociation (by stress change) - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),10) :: & - rho ! current dislocation densities - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),4) :: & - v ! dislocation glide velocity - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & - tau ! current resolved shear stress - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),2) :: & - rhoDip, & ! current dipole dislocation densities (screw and edge dipoles) - dUpper, & ! current maximum stable dipole distance for edges and screws - dUpperOld, & ! old maximum stable dipole distance for edges and screws - deltaDUpper ! change in maximum stable dipole distance for edges and screws - - ph = material_phaseAt(1,el) - of = material_phasememberAt(1,ip,el) - instance = phase_plasticityInstance(ph) - - associate(prm => param(instance),dst => microstructure(instance),del => deltaState(instance)) - ns = totalNslip(instance) - - !*** shortcut to state variables - forall (s = 1:ns, t = 1:4) & - v(s,t) = plasticState(ph)%state(iV(s,t,instance),of) - forall (s = 1:ns, c = 1:2) & - dUpperOld(s,c) = plasticState(ph)%state(iD(s,c,instance),of) - - rho = getRho(instance,of,ip,el) - rhoDip = rho(:,dip) - - !**************************************************************************** - !*** dislocation remobilization (bauschinger effect) - where(rho(:,imm) * v < 0.0_pReal) - deltaRhoRemobilization(:,mob) = abs(rho(:,imm)) - deltaRhoRemobilization(:,imm) = - rho(:,imm) - rho(:,mob) = rho(:,mob) + abs(rho(:,imm)) - rho(:,imm) = 0.0_pReal - elsewhere - deltaRhoRemobilization(:,mob) = 0.0_pReal - deltaRhoRemobilization(:,imm) = 0.0_pReal - endwhere - deltaRhoRemobilization(:,dip) = 0.0_pReal - - !**************************************************************************** - !*** calculate dipole formation and dissociation by stress change - - !*** calculate limits for stable dipole height - do s = 1,prm%totalNslip - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) +dst%tau_back(s,of) - if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal - enddo - - dUpper(1:ns,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) - dUpper(1:ns,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) - - where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & - dUpper(1:ns,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(1:ns,1)) - - where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & - dUpper(1:ns,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(1:ns,2)) - - dUpper = max(dUpper,prm%minDipoleHeight) - deltaDUpper = dUpper - dUpperOld - - - !*** dissociation by stress increase - deltaRhoDipole2SingleStress = 0.0_pReal - forall (c=1:2, s=1:ns, deltaDUpper(s,c) < 0.0_pReal .and. & - dNeq0(dUpperOld(s,c) - prm%minDipoleHeight(s,c))) & - deltaRhoDipole2SingleStress(s,8+c) = rhoDip(s,c) * deltaDUpper(s,c) & - / (dUpperOld(s,c) - prm%minDipoleHeight(s,c)) - - forall (t=1:4) & - deltaRhoDipole2SingleStress(1:ns,t) = -0.5_pReal & - * deltaRhoDipole2SingleStress(1:ns,(t-1)/2+9) - - forall (s = 1:ns, c = 1:2) & - plasticState(ph)%state(iD(s,c,instance),of) = dUpper(s,c) - - plasticState(ph)%deltaState(:,of) = 0.0_pReal - del%rho(:,of) = reshape(deltaRhoRemobilization + deltaRhoDipole2SingleStress, [10*ns]) - -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation remobilization', deltaRhoRemobilization(1:ns,1:8) - write(6,'(a,/,10(12x,12(e12.5,1x),/),/)') '<< CONST >> dipole dissociation by stress increase', deltaRhoDipole2SingleStress - endif -#endif - - end associate - -end subroutine plastic_nonlocal_deltaState - - -!--------------------------------------------------------------------------------------------------- -!> @brief calculates the rate of change of microstructure -!--------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_dotState(Mp, F, Fp, Temperature, & - timestep,ip,el) - - integer, intent(in) :: & - ip, & !< current integration point - el !< current element number - real(pReal), intent(in) :: & - Temperature, & !< temperature - timestep !< substepped crystallite time increment - real(pReal), dimension(3,3), intent(in) ::& - Mp !< MandelStress - real(pReal), dimension(3,3,homogenization_maxNgrains,discretization_nIP,discretization_nElem), intent(in) :: & - F, & !< elastic deformation gradient - Fp !< plastic deformation gradient - - integer :: & - ph, & - instance, & !< current instance of this plasticity - neighbor_instance, & !< instance of my neighbor's plasticity - ns, & !< short notation for the total number of active slip systems - c, & !< character of dislocation - n, & !< index of my current neighbor - neighbor_el, & !< element number of my neighbor - neighbor_ip, & !< integration point of my neighbor - neighbor_n, & !< neighbor index pointing to me when looking from my neighbor - opposite_neighbor, & !< index of my opposite neighbor - opposite_ip, & !< ip of my opposite neighbor - opposite_el, & !< element index of my opposite neighbor - opposite_n, & !< neighbor index pointing to me when looking from my opposite neighbor - t, & !< type of dislocation - o,& !< offset shortcut - no,& !< neighbor offset shortcut - p,& !< phase shortcut - np,& !< neighbor phase shortcut - topp, & !< type of dislocation with opposite sign to t - s !< index of my current slip system - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),10) :: & - rho, & - rho0, & !< dislocation density at beginning of time step - rhoDot, & !< density evolution - rhoDotMultiplication, & !< density evolution by multiplication - rhoDotFlux, & !< density evolution by flux - rhoDotSingle2DipoleGlide, & !< density evolution by dipole formation (by glide) - rhoDotAthermalAnnihilation, & !< density evolution by athermal annihilation - rhoDotThermalAnnihilation !< density evolution by thermal annihilation - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),8) :: & - rhoSgl, & !< current single dislocation densities (positive/negative screw and edge without dipoles) - neighbor_rhoSgl0, & !< current single dislocation densities of neighboring ip (positive/negative screw and edge without dipoles) - my_rhoSgl0 !< single dislocation densities of central ip (positive/negative screw and edge without dipoles) - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),4) :: & - v, & !< current dislocation glide velocity - v0, & - neighbor_v0, & !< dislocation glide velocity of enighboring ip - gdot !< shear rates - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el)))) :: & - tau, & !< current resolved shear stress - vClimb !< climb velocity of edge dipoles - - real(pReal), dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),2) :: & - rhoDip, & !< current dipole dislocation densities (screw and edge dipoles) - dLower, & !< minimum stable dipole distance for edges and screws - dUpper !< current maximum stable dipole distance for edges and screws - real(pReal), dimension(3,totalNslip(phase_plasticityInstance(material_phaseAt(1,el))),4) :: & - m !< direction of dislocation motion - real(pReal), dimension(3,3) :: & - my_F, & !< my total deformation gradient - neighbor_F, & !< total deformation gradient of my neighbor - my_Fe, & !< my elastic deformation gradient - neighbor_Fe, & !< elastic deformation gradient of my neighbor - Favg !< average total deformation gradient of me and my neighbor - real(pReal), dimension(3) :: & - normal_neighbor2me, & !< interface normal pointing from my neighbor to me in neighbor's lattice configuration - normal_neighbor2me_defConf, & !< interface normal pointing from my neighbor to me in shared deformed configuration - normal_me2neighbor, & !< interface normal pointing from me to my neighbor in my lattice configuration - normal_me2neighbor_defConf !< interface normal pointing from me to my neighbor in shared deformed configuration - real(pReal) :: & - area, & !< area of the current interface - transmissivity, & !< overall transmissivity of dislocation flux to neighboring material point - lineLength, & !< dislocation line length leaving the current interface - selfDiffusion !< self diffusion - - logical :: & - considerEnteringFlux, & - considerLeavingFlux - - p = material_phaseAt(1,el) - o = material_phasememberAt(1,ip,el) - - if (timestep <= 0.0_pReal) then - plasticState(p)%dotState = 0.0_pReal - return - endif - - ph = material_phaseAt(1,el) - instance = phase_plasticityInstance(ph) - associate(prm => param(instance), & - dst => microstructure(instance), & - dot => dotState(instance), & - stt => state(instance)) - ns = totalNslip(instance) - - tau = 0.0_pReal - gdot = 0.0_pReal - - rho = getRho(instance,o,ip,el) - rhoSgl = rho(:,sgl) - rhoDip = rho(:,dip) - rho0 = getRho0(instance,o,ip,el) - my_rhoSgl0 = rho0(:,sgl) - - forall (s = 1:ns, t = 1:4) - v(s,t) = plasticState(p)%state(iV (s,t,instance),o) - endforall - - - !**************************************************************************** - !*** Calculate shear rate - - forall (t = 1:4) & - gdot(1:ns,t) = rhoSgl(1:ns,t) * prm%burgers(1:ns) * v(1:ns,t) - -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> rho / 1/m^2', rhoSgl, rhoDip - write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> gdot / 1/s',gdot - endif -#endif - - - - !**************************************************************************** - !*** calculate limits for stable dipole height - - do s = 1,ns ! loop over slip systems - tau(s) = math_mul33xx33(Mp, prm%Schmid(1:3,1:3,s)) + dst%tau_back(s,o) - if (abs(tau(s)) < 1.0e-15_pReal) tau(s) = 1.0e-15_pReal - enddo - - dLower = prm%minDipoleHeight - dUpper(1:ns,1) = prm%mu * prm%burgers/(8.0_pReal * PI * (1.0_pReal - prm%nu) * abs(tau)) - dUpper(1:ns,2) = prm%mu * prm%burgers/(4.0_pReal * PI * abs(tau)) - - where(dNeq0(sqrt(sum(abs(rho(:,edg)),2)))) & - dUpper(1:ns,1) = min(1.0_pReal/sqrt(sum(abs(rho(:,edg)),2)),dUpper(1:ns,1)) - - where(dNeq0(sqrt(sum(abs(rho(:,scr)),2)))) & - dUpper(1:ns,2) = min(1.0_pReal/sqrt(sum(abs(rho(:,scr)),2)),dUpper(1:ns,2)) - - dUpper = max(dUpper,dLower) - - !**************************************************************************** - !*** calculate dislocation multiplication - rhoDotMultiplication = 0.0_pReal - isBCC: if (lattice_structure(ph) == LATTICE_bcc_ID) then - forall (s = 1:ns, sum(abs(v(s,1:4))) > 0.0_pReal) - rhoDotMultiplication(s,1:2) = sum(abs(gdot(s,3:4))) / prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication - * sqrt(stt%rho_forest(s,o)) / prm%lambda0(s) ! & ! mean free path - ! * 2.0_pReal * sum(abs(v(s,3:4))) / sum(abs(v(s,1:4))) ! ratio of screw to overall velocity determines edge generation - rhoDotMultiplication(s,3:4) = sum(abs(gdot(s,3:4))) /prm%burgers(s) & ! assuming double-cross-slip of screws to be decisive for multiplication - * sqrt(stt%rho_forest(s,o)) / prm%lambda0(s) ! & ! mean free path - ! * 2.0_pReal * sum(abs(v(s,1:2))) / sum(abs(v(s,1:4))) ! ratio of edge to overall velocity determines screw generation - endforall - - else isBCC - rhoDotMultiplication(1:ns,1:4) = spread( & - (sum(abs(gdot(1:ns,1:2)),2) * prm%fEdgeMultiplication + sum(abs(gdot(1:ns,3:4)),2)) & - * sqrt(stt%rho_forest(:,o)) / prm%lambda0 / prm%burgers(1:ns), 2, 4) - endif isBCC - - forall (s = 1:ns, t = 1:4) - v0(s,t) = plasticState(p)%state0(iV(s,t,instance),o) - endforall - - !**************************************************************************** - !*** calculate dislocation fluxes (only for nonlocal plasticity) - rhoDotFlux = 0.0_pReal - if (.not. phase_localPlasticity(material_phaseAt(1,el))) then - - !*** check CFL (Courant-Friedrichs-Lewy) condition for flux - if (any( abs(gdot) > 0.0_pReal & ! any active slip system ... - .and. prm%CFLfactor * abs(v0) * timestep & - > IPvolume(ip,el) / maxval(IParea(:,ip,el)))) then ! ...with velocity above critical value (we use the reference volume and area for simplicity here) -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then - write(6,'(a,i5,a,i2)') '<< CONST >> CFL condition not fullfilled at el ',el,' ip ',ip - write(6,'(a,e10.3,a,e10.3)') '<< CONST >> velocity is at ', & - maxval(abs(v0), abs(gdot) > 0.0_pReal & - .and. prm%CFLfactor * abs(v0) * timestep & - > IPvolume(ip,el) / maxval(IParea(:,ip,el))), & - ' at a timestep of ',timestep - write(6,'(a)') '<< CONST >> enforcing cutback !!!' - endif -#endif - plasticState(p)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) ! -> return NaN and, hence, enforce cutback - return - endif - - - !*** be aware of the definition of slip_transverse = slip_direction x slip_normal !!! - !*** opposite sign to our p vector in the (s,p,n) triplet !!! - - m(1:3,1:ns,1) = prm%slip_direction - m(1:3,1:ns,2) = -prm%slip_direction - m(1:3,1:ns,3) = -prm%slip_transverse - m(1:3,1:ns,4) = prm%slip_transverse - - my_F = F(1:3,1:3,1,ip,el) - my_Fe = matmul(my_F, math_inv33(Fp(1:3,1:3,1,ip,el))) - - neighbors: do n = 1,nIPneighbors - - neighbor_el = IPneighborhood(1,n,ip,el) - neighbor_ip = IPneighborhood(2,n,ip,el) - neighbor_n = IPneighborhood(3,n,ip,el) - np = material_phaseAt(1,neighbor_el) - no = material_phasememberAt(1,neighbor_ip,neighbor_el) - - opposite_neighbor = n + mod(n,2) - mod(n+1,2) - opposite_el = IPneighborhood(1,opposite_neighbor,ip,el) - opposite_ip = IPneighborhood(2,opposite_neighbor,ip,el) - opposite_n = IPneighborhood(3,opposite_neighbor,ip,el) - - if (neighbor_n > 0) then ! if neighbor exists, average deformation gradient - neighbor_instance = phase_plasticityInstance(material_phaseAt(1,neighbor_el)) - neighbor_F = F(1:3,1:3,1,neighbor_ip,neighbor_el) - neighbor_Fe = matmul(neighbor_F, math_inv33(Fp(1:3,1:3,1,neighbor_ip,neighbor_el))) - Favg = 0.5_pReal * (my_F + neighbor_F) - else ! if no neighbor, take my value as average - Favg = my_F - endif - - - !* FLUX FROM MY NEIGHBOR TO ME - !* This is only considered, if I have a neighbor of nonlocal plasticity - !* (also nonlocal constitutive law with local properties) that is at least a little bit - !* compatible. - !* If it's not at all compatible, no flux is arriving, because everything is dammed in front of - !* my neighbor's interface. - !* The entering flux from my neighbor will be distributed on my slip systems according to the - !* compatibility - - considerEnteringFlux = .false. - neighbor_v0 = 0.0_pReal ! needed for check of sign change in flux density below - if (neighbor_n > 0) then - if (phase_plasticity(material_phaseAt(1,neighbor_el)) == PLASTICITY_NONLOCAL_ID & - .and. any(compatibility(:,:,:,n,ip,el) > 0.0_pReal)) & - considerEnteringFlux = .true. - endif - - enteringFlux: if (considerEnteringFlux) then - forall (s = 1:ns, t = 1:4) - neighbor_v0(s,t) = plasticState(np)%state0(iV (s,t,neighbor_instance),no) - neighbor_rhoSgl0(s,t) = max(plasticState(np)%state0(iRhoU(s,t,neighbor_instance),no), & - 0.0_pReal) - endforall - - where (neighbor_rhoSgl0 * IPvolume(neighbor_ip,neighbor_el) ** 0.667_pReal < prm%significantN & - .or. neighbor_rhoSgl0 < prm%significantRho) & - neighbor_rhoSgl0 = 0.0_pReal - normal_neighbor2me_defConf = math_det33(Favg) * matmul(math_inv33(transpose(Favg)), & - IPareaNormal(1:3,neighbor_n,neighbor_ip,neighbor_el)) ! calculate the normal of the interface in (average) deformed configuration (now pointing from my neighbor to me!!!) - normal_neighbor2me = matmul(transpose(neighbor_Fe), normal_neighbor2me_defConf) & - / math_det33(neighbor_Fe) ! interface normal in the lattice configuration of my neighbor - area = IParea(neighbor_n,neighbor_ip,neighbor_el) * norm2(normal_neighbor2me) - normal_neighbor2me = normal_neighbor2me / norm2(normal_neighbor2me) ! normalize the surface normal to unit length - do s = 1,ns - do t = 1,4 - c = (t + 1) / 2 - topp = t + mod(t,2) - mod(t+1,2) - if (neighbor_v0(s,t) * math_inner(m(1:3,s,t), normal_neighbor2me) > 0.0_pReal & ! flux from my neighbor to me == entering flux for me - .and. v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal ) then ! ... only if no sign change in flux density - lineLength = neighbor_rhoSgl0(s,t) * neighbor_v0(s,t) & - * math_inner(m(1:3,s,t), normal_neighbor2me) * area ! positive line length that wants to enter through this interface - where (compatibility(c,1:ns,s,n,ip,el) > 0.0_pReal) & ! positive compatibility... - rhoDotFlux(1:ns,t) = rhoDotFlux(1:ns,t) & - + lineLength / IPvolume(ip,el) & ! ... transferring to equally signed mobile dislocation type - * compatibility(c,1:ns,s,n,ip,el) ** 2.0_pReal - where (compatibility(c,1:ns,s,n,ip,el) < 0.0_pReal) & ! ..negative compatibility... - rhoDotFlux(1:ns,topp) = rhoDotFlux(1:ns,topp) & - + lineLength / IPvolume(ip,el) & ! ... transferring to opposite signed mobile dislocation type - * compatibility(c,1:ns,s,n,ip,el) ** 2.0_pReal - endif - enddo - enddo - endif enteringFlux - - - !* FLUX FROM ME TO MY NEIGHBOR - !* This is not considered, if my opposite neighbor has a different constitutive law than nonlocal (still considered for nonlocal law with local properties). - !* Then, we assume, that the opposite(!) neighbor sends an equal amount of dislocations to me. - !* So the net flux in the direction of my neighbor is equal to zero: - !* leaving flux to neighbor == entering flux from opposite neighbor - !* In case of reduced transmissivity, part of the leaving flux is stored as dead dislocation density. - !* That means for an interface of zero transmissivity the leaving flux is fully converted to dead dislocations. - - considerLeavingFlux = .true. - if (opposite_n > 0) then - if (phase_plasticity(material_phaseAt(1,opposite_el)) /= PLASTICITY_NONLOCAL_ID) & - considerLeavingFlux = .false. - endif - - leavingFlux: if (considerLeavingFlux) then - normal_me2neighbor_defConf = math_det33(Favg) & - * matmul(math_inv33(transpose(Favg)), & - IPareaNormal(1:3,n,ip,el)) ! calculate the normal of the interface in (average) deformed configuration (pointing from me to my neighbor!!!) - normal_me2neighbor = matmul(transpose(my_Fe), normal_me2neighbor_defConf) & - / math_det33(my_Fe) ! interface normal in my lattice configuration - area = IParea(n,ip,el) * norm2(normal_me2neighbor) - normal_me2neighbor = normal_me2neighbor / norm2(normal_me2neighbor) ! normalize the surface normal to unit length - do s = 1,ns - do t = 1,4 - c = (t + 1) / 2 - if (v0(s,t) * math_inner(m(1:3,s,t), normal_me2neighbor) > 0.0_pReal ) then ! flux from me to my neighbor == leaving flux for me (might also be a pure flux from my mobile density to dead density if interface not at all transmissive) - if (v0(s,t) * neighbor_v0(s,t) >= 0.0_pReal) then ! no sign change in flux density - transmissivity = sum(compatibility(c,1:ns,s,n,ip,el)**2.0_pReal) ! overall transmissivity from this slip system to my neighbor - else ! sign change in flux density means sign change in stress which does not allow for dislocations to arive at the neighbor - transmissivity = 0.0_pReal - endif - lineLength = my_rhoSgl0(s,t) * v0(s,t) & - * math_inner(m(1:3,s,t), normal_me2neighbor) * area ! positive line length of mobiles that wants to leave through this interface - rhoDotFlux(s,t) = rhoDotFlux(s,t) - lineLength / IPvolume(ip,el) ! subtract dislocation flux from current type - rhoDotFlux(s,t+4) = rhoDotFlux(s,t+4) & - + lineLength / IPvolume(ip,el) * (1.0_pReal - transmissivity) & - * sign(1.0_pReal, v0(s,t)) ! dislocation flux that is not able to leave through interface (because of low transmissivity) will remain as immobile single density at the material point - endif - enddo - enddo - endif leavingFlux - - enddo neighbors - endif - - - - !**************************************************************************** - !*** calculate dipole formation and annihilation - - !*** formation by glide - - do c = 1,2 - rhoDotSingle2DipoleGlide(1:ns,2*c-1) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & - * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) & ! negative mobile --> positive mobile - + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1)) & ! positive mobile --> negative mobile - + abs(rhoSgl(1:ns,2*c+4)) * abs(gdot(1:ns,2*c-1))) ! positive mobile --> negative immobile - - rhoDotSingle2DipoleGlide(1:ns,2*c) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & - * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) & ! negative mobile --> positive mobile - + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1)) & ! positive mobile --> negative mobile - + abs(rhoSgl(1:ns,2*c+3)) * abs(gdot(1:ns,2*c))) ! negative mobile --> positive immobile - - rhoDotSingle2DipoleGlide(1:ns,2*c+3) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns) & - * rhoSgl(1:ns,2*c+3) * abs(gdot(1:ns,2*c)) ! negative mobile --> positive immobile - - rhoDotSingle2DipoleGlide(1:ns,2*c+4) = -2.0_pReal * dUpper(1:ns,c) / prm%burgers(1:ns)& - * rhoSgl(1:ns,2*c+4) * abs(gdot(1:ns,2*c-1)) ! positive mobile --> negative immobile - - rhoDotSingle2DipoleGlide(1:ns,c+8) = - rhoDotSingle2DipoleGlide(1:ns,2*c-1) & - - rhoDotSingle2DipoleGlide(1:ns,2*c) & - + abs(rhoDotSingle2DipoleGlide(1:ns,2*c+3)) & - + abs(rhoDotSingle2DipoleGlide(1:ns,2*c+4)) - enddo - - - !*** athermal annihilation - - rhoDotAthermalAnnihilation = 0.0_pReal - - forall (c=1:2) & - rhoDotAthermalAnnihilation(1:ns,c+8) = -2.0_pReal * dLower(1:ns,c) / prm%burgers(1:ns) & - * ( 2.0_pReal * (rhoSgl(1:ns,2*c-1) * abs(gdot(1:ns,2*c)) + rhoSgl(1:ns,2*c) * abs(gdot(1:ns,2*c-1))) & ! was single hitting single - + 2.0_pReal * (abs(rhoSgl(1:ns,2*c+3)) * abs(gdot(1:ns,2*c)) + abs(rhoSgl(1:ns,2*c+4)) * abs(gdot(1:ns,2*c-1))) & ! was single hitting immobile single or was immobile single hit by single - + rhoDip(1:ns,c) * (abs(gdot(1:ns,2*c-1)) + abs(gdot(1:ns,2*c)))) ! single knocks dipole constituent - ! annihilated screw dipoles leave edge jogs behind on the colinear system - - if (lattice_structure(ph) == LATTICE_fcc_ID) & - forall (s = 1:ns, prm%colinearSystem(s) > 0) & - rhoDotAthermalAnnihilation(prm%colinearSystem(s),1:2) = - rhoDotAthermalAnnihilation(s,10) & - * 0.25_pReal * sqrt(stt%rho_forest(s,o)) * (dUpper(s,2) + dLower(s,2)) * prm%edgeJogFactor - - - - !*** thermally activated annihilation of edge dipoles by climb - - rhoDotThermalAnnihilation = 0.0_pReal - selfDiffusion = prm%Dsd0 * exp(-prm%selfDiffusionEnergy / (KB * Temperature)) - vClimb = prm%atomicVolume * selfDiffusion / ( KB * Temperature ) & - * prm%mu / ( 2.0_pReal * PI * (1.0_pReal-prm%nu) ) & - * 2.0_pReal / ( dUpper(1:ns,1) + dLower(1:ns,1) ) - forall (s = 1:ns, dUpper(s,1) > dLower(s,1)) & - rhoDotThermalAnnihilation(s,9) = max(- 4.0_pReal * rhoDip(s,1) * vClimb(s) / (dUpper(s,1) - dLower(s,1)), & - - rhoDip(s,1) / timestep - rhoDotAthermalAnnihilation(s,9) & - - rhoDotSingle2DipoleGlide(s,9)) ! make sure that we do not annihilate more dipoles than we have - - rhoDot = rhoDotFlux & - + rhoDotMultiplication & - + rhoDotSingle2DipoleGlide & - + rhoDotAthermalAnnihilation & - + rhoDotThermalAnnihilation - -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0 & - .and. ((debug_e == el .and. debug_i == ip)& - .or. .not. iand(debug_level(debug_constitutive),debug_levelSelective) /= 0 )) then - write(6,'(a,/,4(12x,12(e12.5,1x),/))') '<< CONST >> dislocation multiplication', & - rhoDotMultiplication(1:ns,1:4) * timestep - write(6,'(a,/,8(12x,12(e12.5,1x),/))') '<< CONST >> dislocation flux', & - rhoDotFlux(1:ns,1:8) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> dipole formation by glide', & - rhoDotSingle2DipoleGlide * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> athermal dipole annihilation', & - rhoDotAthermalAnnihilation * timestep - write(6,'(a,/,2(12x,12(e12.5,1x),/))') '<< CONST >> thermally activated dipole annihilation', & - rhoDotThermalAnnihilation(1:ns,9:10) * timestep - write(6,'(a,/,10(12x,12(e12.5,1x),/))') '<< CONST >> total density change', & - rhoDot * timestep - write(6,'(a,/,10(12x,12(f12.5,1x),/))') '<< CONST >> relative density change', & - rhoDot(1:ns,1:8) * timestep / (abs(stt%rho(:,sgl))+1.0e-10), & - rhoDot(1:ns,9:10) * timestep / (stt%rho(:,dip)+1.0e-10) - write(6,*) - endif -#endif - - - if ( any(rho(:,mob) + rhoDot(1:ns,1:4) * timestep < -prm%aTolRho) & - .or. any(rho(:,dip) + rhoDot(1:ns,9:10) * timestep < -prm%aTolRho)) then -#ifdef DEBUG - if (iand(debug_level(debug_constitutive),debug_levelExtensive) /= 0) then - write(6,'(a,i5,a,i2)') '<< CONST >> evolution rate leads to negative density at el ',el,' ip ',ip - write(6,'(a)') '<< CONST >> enforcing cutback !!!' - endif -#endif - plasticState(p)%dotState = IEEE_value(1.0_pReal,IEEE_quiet_NaN) - else - dot%rho(:,o) = pack(rhoDot,.true.) - forall (s = 1:ns) & - dot%gamma(s,o) = sum(gdot(s,1:4)) - endif - - end associate - -end subroutine plastic_nonlocal_dotState - -!-------------------------------------------------------------------------------------------------- -!> @brief Compatibility update -!> @detail Compatibility is defined as normalized product of signed cosine of the angle between the slip -! plane normals and signed cosine of the angle between the slip directions. Only the largest values -! that sum up to a total of 1 are considered, all others are set to zero. -!-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_updateCompatibility(orientation,i,e) - - integer, intent(in) :: & - i, & - e - type(rotation), dimension(1,discretization_nIP,discretization_nElem), intent(in) :: & - orientation ! crystal orientation - - integer :: & - Nneighbors, & ! number of neighbors - n, & ! neighbor index - neighbor_e, & ! element index of my neighbor - neighbor_i, & ! integration point index of my neighbor - ph, & - neighbor_phase, & - textureID, & - neighbor_textureID, & - instance, & ! instance of plasticity - ns, & ! number of active slip systems - s1, & ! slip system index (me) - s2 ! slip system index (my neighbor) - real(pReal), dimension(2,totalNslip(phase_plasticityInstance(material_phaseAt(1,e))),& - totalNslip(phase_plasticityInstance(material_phaseAt(1,e))),& - nIPneighbors) :: & - my_compatibility ! my_compatibility for current element and ip - real(pReal) :: & - my_compatibilitySum, & - thresholdValue, & - nThresholdValues - logical, dimension(totalNslip(phase_plasticityInstance(material_phaseAt(1,e)))) :: & - belowThreshold - type(rotation) :: mis - - Nneighbors = nIPneighbors - ph = material_phaseAt(1,e) - textureID = material_texture(1,i,e) - instance = phase_plasticityInstance(ph) - ns = totalNslip(instance) - associate(prm => param(instance)) - - !*** start out fully compatible - my_compatibility = 0.0_pReal - - forall(s1 = 1:ns) my_compatibility(1:2,s1,s1,1:Nneighbors) = 1.0_pReal - - !*** Loop thrugh neighbors and check whether there is any compatibility. - - neighbors: do n = 1,Nneighbors - neighbor_e = IPneighborhood(1,n,i,e) - neighbor_i = IPneighborhood(2,n,i,e) - - - !* FREE SURFACE - !* Set surface transmissivity to the value specified in the material.config - - if (neighbor_e <= 0 .or. neighbor_i <= 0) then - forall(s1 = 1:ns) my_compatibility(1:2,s1,s1,n) = sqrt(prm%surfaceTransmissivity) - cycle - endif - - - !* PHASE BOUNDARY - !* If we encounter a different nonlocal phase at the neighbor, - !* we consider this to be a real "physical" phase boundary, so completely incompatible. - !* If one of the two phases has a local plasticity law, - !* we do not consider this to be a phase boundary, so completely compatible. - neighbor_phase = material_phaseAt(1,neighbor_e) - if (neighbor_phase /= ph) then - if (.not. phase_localPlasticity(neighbor_phase) .and. .not. phase_localPlasticity(ph))& - forall(s1 = 1:ns) my_compatibility(1:2,s1,s1,n) = 0.0_pReal - cycle - endif - - - !* GRAIN BOUNDARY ! - !* fixed transmissivity for adjacent ips with different texture (only if explicitly given in material.config) - if (prm%grainboundaryTransmissivity >= 0.0_pReal) then - neighbor_textureID = material_texture(1,neighbor_i,neighbor_e) - if (neighbor_textureID /= textureID) then - if (.not. phase_localPlasticity(neighbor_phase)) then - forall(s1 = 1:ns) & - my_compatibility(1:2,s1,s1,n) = sqrt(prm%grainboundaryTransmissivity) - endif - cycle - endif - - - !* GRAIN BOUNDARY ? - !* Compatibility defined by relative orientation of slip systems: - !* The my_compatibility value is defined as the product of the slip normal projection and the slip direction projection. - !* Its sign is always positive for screws, for edges it has the same sign as the slip normal projection. - !* Since the sum for each slip system can easily exceed one (which would result in a transmissivity larger than one), - !* only values above or equal to a certain threshold value are considered. This threshold value is chosen, such that - !* the number of compatible slip systems is minimized with the sum of the original compatibility values exceeding one. - !* Finally the smallest compatibility value is decreased until the sum is exactly equal to one. - !* All values below the threshold are set to zero. - else - mis = orientation(1,i,e)%misorientation(orientation(1,neighbor_i,neighbor_e)) - mySlipSystems: do s1 = 1,ns - neighborSlipSystems: do s2 = 1,ns - my_compatibility(1,s2,s1,n) = math_inner(prm%slip_normal(1:3,s1), & - mis%rotate(prm%slip_normal(1:3,s2))) & - * abs(math_inner(prm%slip_direction(1:3,s1), & - mis%rotate(prm%slip_direction(1:3,s2)))) - my_compatibility(2,s2,s1,n) = abs(math_inner(prm%slip_normal(1:3,s1), & - mis%rotate(prm%slip_normal(1:3,s2)))) & - * abs(math_inner(prm%slip_direction(1:3,s1), & - mis%rotate(prm%slip_direction(1:3,s2)))) - enddo neighborSlipSystems - - my_compatibilitySum = 0.0_pReal - belowThreshold = .true. - do while (my_compatibilitySum < 1.0_pReal .and. any(belowThreshold(1:ns))) - thresholdValue = maxval(my_compatibility(2,1:ns,s1,n), belowThreshold(1:ns)) ! screws always positive - nThresholdValues = real(count(my_compatibility(2,1:ns,s1,n) >= thresholdValue),pReal) - where (my_compatibility(2,1:ns,s1,n) >= thresholdValue) & - belowThreshold(1:ns) = .false. - if (my_compatibilitySum + thresholdValue * nThresholdValues > 1.0_pReal) & - where (abs(my_compatibility(1:2,1:ns,s1,n)) >= thresholdValue) & ! MD: rather check below threshold? - my_compatibility(1:2,1:ns,s1,n) = sign((1.0_pReal - my_compatibilitySum) & - / nThresholdValues, my_compatibility(1:2,1:ns,s1,n)) - my_compatibilitySum = my_compatibilitySum + nThresholdValues * thresholdValue - enddo - where (belowThreshold(1:ns)) my_compatibility(1,1:ns,s1,n) = 0.0_pReal - where (belowThreshold(1:ns)) my_compatibility(2,1:ns,s1,n) = 0.0_pReal - enddo mySlipSystems - endif - - enddo neighbors - - compatibility(1:2,1:ns,1:ns,1:Nneighbors,i,e) = my_compatibility - - end associate - -end subroutine plastic_nonlocal_updateCompatibility +end subroutine kinetics !-------------------------------------------------------------------------------------------------- @@ -1834,11 +1729,11 @@ end subroutine plastic_nonlocal_updateCompatibility function getRho(instance,of,ip,el) integer, intent(in) :: instance, of,ip,el - real(pReal), dimension(param(instance)%totalNslip,10) :: getRho + real(pReal), dimension(param(instance)%sum_N_sl,10) :: getRho associate(prm => param(instance)) - getRho = reshape(state(instance)%rho(:,of),[prm%totalNslip,10]) + getRho = reshape(state(instance)%rho(:,of),[prm%sum_N_sl,10]) ! ensure positive densities (not for imm, they have a sign) getRho(:,mob) = max(getRho(:,mob),0.0_pReal) @@ -1859,11 +1754,11 @@ end function getRho function getRho0(instance,of,ip,el) integer, intent(in) :: instance, of,ip,el - real(pReal), dimension(param(instance)%totalNslip,10) :: getRho0 + real(pReal), dimension(param(instance)%sum_N_sl,10) :: getRho0 associate(prm => param(instance)) - getRho0 = reshape(state0(instance)%rho(:,of),[prm%totalNslip,10]) + getRho0 = reshape(state0(instance)%rho(:,of),[prm%sum_N_sl,10]) ! ensure positive densities (not for imm, they have a sign) getRho0(:,mob) = max(getRho0(:,mob),0.0_pReal) @@ -1876,75 +1771,4 @@ function getRho0(instance,of,ip,el) end function getRho0 - -!-------------------------------------------------------------------------------------------------- -!> @brief writes results to HDF5 output file -!-------------------------------------------------------------------------------------------------- -module subroutine plastic_nonlocal_results(instance,group) - - integer, intent(in) :: instance - character(len=*),intent(in) :: group - - integer :: o - - associate(prm => param(instance),dst => microstructure(instance),stt=>state(instance)) - outputsLoop: do o = 1,size(prm%output) - select case(trim(prm%output(o))) - case('rho_sgl_mob_edg_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_pos, 'rho_sgl_mob_edg_pos', & - 'positive mobile edge density','1/m²') - case('rho_sgl_imm_edg_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_pos, 'rho_sgl_imm_edg_pos',& - 'positive immobile edge density','1/m²') - case('rho_sgl_mob_edg_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_edg_neg, 'rho_sgl_mob_edg_neg',& - 'negative mobile edge density','1/m²') - case('rho_sgl_imm_edg_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_edg_neg, 'rho_sgl_imm_edg_neg',& - 'negative immobile edge density','1/m²') - case('rho_dip_edg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_dip_edg, 'rho_dip_edg',& - 'edge dipole density','1/m²') - case('rho_sgl_mob_scr_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_pos, 'rho_sgl_mob_scr_pos',& - 'positive mobile screw density','1/m²') - case('rho_sgl_imm_scr_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_pos, 'rho_sgl_imm_scr_pos',& - 'positive immobile screw density','1/m²') - case('rho_sgl_mob_scr_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_mob_scr_neg, 'rho_sgl_mob_scr_neg',& - 'negative mobile screw density','1/m²') - case('rho_sgl_imm_scr_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_sgl_imm_scr_neg, 'rho_sgl_imm_scr_neg',& - 'negative immobile screw density','1/m²') - case('rho_dip_scr') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_dip_scr, 'rho_dip_scr',& - 'screw dipole density','1/m²') - case('rho_forest') - if(prm%totalNslip>0) call results_writeDataset(group,stt%rho_forest, 'rho_forest',& - 'forest density','1/m²') - case('v_edg_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%v_edg_pos, 'v_edg_pos',& - 'positive edge velocity','m/s') - case('v_edg_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%v_edg_neg, 'v_edg_neg',& - 'negative edge velocity','m/s') - case('v_scr_pos') - if(prm%totalNslip>0) call results_writeDataset(group,stt%v_scr_pos, 'v_scr_pos',& - 'positive srew velocity','m/s') - case('v_scr_neg') - if(prm%totalNslip>0) call results_writeDataset(group,stt%v_scr_neg, 'v_scr_neg',& - 'negative screw velocity','m/s') - case('gamma') - if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma,'gamma',& - 'plastic shear','1') - case('tau_pass') - if(prm%totalNslip>0) call results_writeDataset(group,dst%tau_pass,'tau_pass',& - 'passing stress for slip','Pa') - end select - enddo outputsLoop - end associate - -end subroutine plastic_nonlocal_results - end submodule plastic_nonlocal diff --git a/src/constitutive_plastic_phenopowerlaw.f90 b/src/constitutive_plastic_phenopowerlaw.f90 index 6dfa3fb16..a980d6106 100644 --- a/src/constitutive_plastic_phenopowerlaw.f90 +++ b/src/constitutive_plastic_phenopowerlaw.f90 @@ -8,27 +8,21 @@ submodule(constitutive) plastic_phenopowerlaw type :: tParameters real(pReal) :: & - gdot0_slip, & !< reference shear strain rate for slip - gdot0_twin, & !< reference shear strain rate for twin - n_slip, & !< stress exponent for slip - n_twin, & !< stress exponent for twin - spr, & !< push-up factor for slip saturation due to twinning - c_1, & - c_2, & - c_3, & - c_4, & - h0_SlipSlip, & !< reference hardening slip - slip - h0_TwinSlip, & !< reference hardening twin - slip - h0_TwinTwin, & !< reference hardening twin - twin - a_slip, & - aTolResistance, & !< absolute tolerance for integration of xi - aTolShear, & !< absolute tolerance for integration of gamma - aTolTwinfrac !< absolute tolerance for integration of f + gdot0_slip = 1.0_pReal, & !< reference shear strain rate for slip + gdot0_twin = 1.0_pReal, & !< reference shear strain rate for twin + n_slip = 1.0_pReal, & !< stress exponent for slip + n_twin = 1.0_pReal, & !< stress exponent for twin + spr = 1.0_pReal, & !< push-up factor for slip saturation due to twinning + c_1 = 1.0_pReal, & + c_2 = 1.0_pReal, & + c_3 = 1.0_pReal, & + c_4 = 1.0_pReal, & + h0_SlipSlip = 1.0_pReal, & !< reference hardening slip - slip + h0_TwinSlip = 1.0_pReal, & !< reference hardening twin - slip + h0_TwinTwin = 1.0_pReal, & !< reference hardening twin - twin + a_slip = 1.0_pReal real(pReal), allocatable, dimension(:) :: & - xi_slip_0, & !< initial critical shear stress for slip - xi_twin_0, & !< initial critical shear stress for twin xi_slip_sat, & !< maximum critical shear stress for slip - nonSchmidCoeff, & H_int, & !< per family hardening activity (optional) gamma_twin_char !< characteristic shear for twins real(pReal), allocatable, dimension(:,:) :: & @@ -37,16 +31,15 @@ submodule(constitutive) plastic_phenopowerlaw interaction_TwinSlip, & !< twin resistance from slip activity interaction_TwinTwin !< twin resistance from twin activity real(pReal), allocatable, dimension(:,:,:) :: & - Schmid_slip, & - Schmid_twin, & + P_sl, & + P_tw, & nonSchmid_pos, & nonSchmid_neg integer :: & - totalNslip, & !< total number of active slip system - totalNtwin !< total number of active twin systems - integer, allocatable, dimension(:) :: & - Nslip, & !< number of active slip systems for each family - Ntwin !< number of active twin systems for each family + sum_N_sl, & !< total number of active slip system + sum_N_tw !< total number of active twin systems + logical :: & + nonSchmidActive = .false. character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -81,11 +74,16 @@ module subroutine plastic_phenopowerlaw_init NipcMyPhase, & sizeState, sizeDotState, & startIndex, endIndex - + integer, dimension(:), allocatable :: & + N_sl, N_tw + real(pReal), dimension(:), allocatable :: & + xi_slip_0, & !< initial critical shear stress for slip + xi_twin_0, & !< initial critical shear stress for twin + a !< non-Schmid coefficients character(len=pStringLen) :: & extmsg = '' - write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_PHENOPOWERLAW_label//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- plastic_'//PLASTICITY_PHENOPOWERLAW_LABEL//' init -+>>>'; flush(6) Ninstance = count(phase_plasticity == PLASTICITY_PHENOPOWERLAW_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & @@ -102,48 +100,31 @@ module subroutine plastic_phenopowerlaw_init stt => state(phase_plasticityInstance(p)), & config => config_phase(p)) -!-------------------------------------------------------------------------------------------------- -! optional parameters that need to be defined - prm%c_1 = config%getFloat('twin_c',defaultVal=0.0_pReal) - prm%c_2 = config%getFloat('twin_b',defaultVal=1.0_pReal) - prm%c_3 = config%getFloat('twin_e',defaultVal=0.0_pReal) - prm%c_4 = config%getFloat('twin_d',defaultVal=0.0_pReal) - - prm%aTolResistance = config%getFloat('atol_resistance',defaultVal=1.0_pReal) - prm%aTolShear = config%getFloat('atol_shear', defaultVal=1.0e-6_pReal) - prm%aTolTwinfrac = config%getFloat('atol_twinfrac', defaultVal=1.0e-6_pReal) - - ! sanity checks - if (prm%aTolResistance <= 0.0_pReal) extmsg = trim(extmsg)//' aTolresistance' - if (prm%aTolShear <= 0.0_pReal) extmsg = trim(extmsg)//' aTolShear' - if (prm%aTolTwinfrac <= 0.0_pReal) extmsg = trim(extmsg)//' atoltwinfrac' - !-------------------------------------------------------------------------------------------------- ! slip related parameters - prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray) - prm%totalNslip = sum(prm%Nslip) - slipActive: if (prm%totalNslip > 0) then - prm%Schmid_slip = lattice_SchmidMatrix_slip(prm%Nslip,config%getString('lattice_structure'),& - config%getFloat('c/a',defaultVal=0.0_pReal)) + N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%sum_N_sl = sum(abs(N_sl)) + slipActive: if (prm%sum_N_sl > 0) then + prm%P_sl = lattice_SchmidMatrix_slip(N_sl,config%getString('lattice_structure'),& + config%getFloat('c/a',defaultVal=0.0_pReal)) if(trim(config%getString('lattice_structure')) == 'bcc') then - prm%nonSchmidCoeff = config%getFloats('nonschmid_coefficients',& - defaultVal = emptyRealArray) - prm%nonSchmid_pos = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,+1) - prm%nonSchmid_neg = lattice_nonSchmidMatrix(prm%Nslip,prm%nonSchmidCoeff,-1) + a = config%getFloats('nonschmid_coefficients',defaultVal = emptyRealArray) + if(size(a) > 0) prm%nonSchmidActive = .true. + prm%nonSchmid_pos = lattice_nonSchmidMatrix(N_sl,a,+1) + prm%nonSchmid_neg = lattice_nonSchmidMatrix(N_sl,a,-1) else - allocate(prm%nonSchmidCoeff(0)) - prm%nonSchmid_pos = prm%Schmid_slip - prm%nonSchmid_neg = prm%Schmid_slip + prm%nonSchmid_pos = prm%P_sl + prm%nonSchmid_neg = prm%P_sl endif - prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(prm%Nslip, & + prm%interaction_SlipSlip = lattice_interaction_SlipBySlip(N_sl, & config%getFloats('interaction_slipslip'), & config%getString('lattice_structure')) - prm%xi_slip_0 = config%getFloats('tau0_slip', requiredSize=size(prm%Nslip)) - prm%xi_slip_sat = config%getFloats('tausat_slip', requiredSize=size(prm%Nslip)) - prm%H_int = config%getFloats('h_int', requiredSize=size(prm%Nslip), & - defaultVal=[(0.0_pReal,i=1,size(prm%Nslip))]) + xi_slip_0 = config%getFloats('tau0_slip', requiredSize=size(N_sl)) + prm%xi_slip_sat = config%getFloats('tausat_slip', requiredSize=size(N_sl)) + prm%H_int = config%getFloats('h_int', requiredSize=size(N_sl), & + defaultVal=[(0.0_pReal,i=1,size(N_sl))]) prm%gdot0_slip = config%getFloat('gdot0_slip') prm%n_slip = config%getFloat('n_slip') @@ -151,74 +132,76 @@ module subroutine plastic_phenopowerlaw_init prm%h0_SlipSlip = config%getFloat('h0_slipslip') ! expand: family => system - prm%xi_slip_0 = math_expand(prm%xi_slip_0, prm%Nslip) - prm%xi_slip_sat = math_expand(prm%xi_slip_sat,prm%Nslip) - prm%H_int = math_expand(prm%H_int, prm%Nslip) + xi_slip_0 = math_expand(xi_slip_0, N_sl) + prm%xi_slip_sat = math_expand(prm%xi_slip_sat,N_sl) + prm%H_int = math_expand(prm%H_int, N_sl) ! sanity checks if ( prm%gdot0_slip <= 0.0_pReal) extmsg = trim(extmsg)//' gdot0_slip' if ( prm%a_slip <= 0.0_pReal) extmsg = trim(extmsg)//' a_slip' if ( prm%n_slip <= 0.0_pReal) extmsg = trim(extmsg)//' n_slip' - if (any(prm%xi_slip_0 <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_slip_0' + if (any(xi_slip_0 <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_slip_0' if (any(prm%xi_slip_sat <= 0.0_pReal)) extmsg = trim(extmsg)//' xi_slip_sat' + else slipActive + xi_slip_0 = emptyRealArray + allocate(prm%xi_slip_sat,prm%H_int,source=emptyRealArray) allocate(prm%interaction_SlipSlip(0,0)) - allocate(prm%xi_slip_0(0)) endif slipActive !-------------------------------------------------------------------------------------------------- ! twin related parameters - prm%Ntwin = config%getInts('ntwin', defaultVal=emptyIntArray) - prm%totalNtwin = sum(prm%Ntwin) - twinActive: if (prm%totalNtwin > 0) then - prm%Schmid_twin = lattice_SchmidMatrix_twin(prm%Ntwin,config%getString('lattice_structure'),& + N_tw = config%getInts('ntwin', defaultVal=emptyIntArray) + prm%sum_N_tw = sum(abs(N_tw)) + twinActive: if (prm%sum_N_tw > 0) then + prm%P_tw = lattice_SchmidMatrix_twin(N_tw,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - prm%interaction_TwinTwin = lattice_interaction_TwinByTwin(prm%Ntwin,& + prm%interaction_TwinTwin = lattice_interaction_TwinByTwin(N_tw,& config%getFloats('interaction_twintwin'), & config%getString('lattice_structure')) - prm%gamma_twin_char = lattice_characteristicShear_twin(prm%Ntwin,config%getString('lattice_structure'),& - config%getFloat('c/a')) + prm%gamma_twin_char = lattice_characteristicShear_twin(N_tw,config%getString('lattice_structure'),& + config%getFloat('c/a')) - prm%xi_twin_0 = config%getFloats('tau0_twin',requiredSize=size(prm%Ntwin)) + xi_twin_0 = config%getFloats('tau0_twin',requiredSize=size(N_tw)) - prm%gdot0_twin = config%getFloat('gdot0_twin') - prm%n_twin = config%getFloat('n_twin') - prm%spr = config%getFloat('s_pr') - prm%h0_TwinTwin = config%getFloat('h0_twintwin') + prm%c_1 = config%getFloat('twin_c',defaultVal=0.0_pReal) + prm%c_2 = config%getFloat('twin_b',defaultVal=1.0_pReal) + prm%c_3 = config%getFloat('twin_e',defaultVal=0.0_pReal) + prm%c_4 = config%getFloat('twin_d',defaultVal=0.0_pReal) + prm%gdot0_twin = config%getFloat('gdot0_twin') + prm%n_twin = config%getFloat('n_twin') + prm%spr = config%getFloat('s_pr') + prm%h0_TwinTwin = config%getFloat('h0_twintwin') ! expand: family => system - prm%xi_twin_0 = math_expand(prm%xi_twin_0, prm%Ntwin) + xi_twin_0 = math_expand(xi_twin_0,N_tw) ! sanity checks if (prm%gdot0_twin <= 0.0_pReal) extmsg = trim(extmsg)//' gdot0_twin' if (prm%n_twin <= 0.0_pReal) extmsg = trim(extmsg)//' n_twin' + else twinActive + xi_twin_0 = emptyRealArray + allocate(prm%gamma_twin_char,source=emptyRealArray) allocate(prm%interaction_TwinTwin(0,0)) - allocate(prm%xi_twin_0(0)) - allocate(prm%gamma_twin_char(0)) endif twinActive !-------------------------------------------------------------------------------------------------- ! slip-twin related parameters - slipAndTwinActive: if (prm%totalNslip > 0 .and. prm%totalNtwin > 0) then + slipAndTwinActive: if (prm%sum_N_sl > 0 .and. prm%sum_N_tw > 0) then prm%h0_TwinSlip = config%getFloat('h0_twinslip') - prm%interaction_SlipTwin = lattice_interaction_SlipByTwin(prm%Nslip,prm%Ntwin,& + prm%interaction_SlipTwin = lattice_interaction_SlipByTwin(N_sl,N_tw,& config%getFloats('interaction_sliptwin'), & config%getString('lattice_structure')) - prm%interaction_TwinSlip = lattice_interaction_TwinBySlip(prm%Ntwin,prm%Nslip,& + prm%interaction_TwinSlip = lattice_interaction_TwinBySlip(N_tw,N_sl,& config%getFloats('interaction_twinslip'), & config%getString('lattice_structure')) else slipAndTwinActive - allocate(prm%interaction_SlipTwin(prm%TotalNslip,prm%TotalNtwin)) ! at least one dimension is 0 - allocate(prm%interaction_TwinSlip(prm%TotalNtwin,prm%TotalNslip)) ! at least one dimension is 0 + allocate(prm%interaction_SlipTwin(prm%sum_N_sl,prm%sum_N_tw)) ! at least one dimension is 0 + allocate(prm%interaction_TwinSlip(prm%sum_N_tw,prm%sum_N_sl)) ! at least one dimension is 0 prm%h0_TwinSlip = 0.0_pReal endif slipAndTwinActive -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_PHENOPOWERLAW_label//')') - !-------------------------------------------------------------------------------------------------- ! output pararameters prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) @@ -226,46 +209,54 @@ module subroutine plastic_phenopowerlaw_init !-------------------------------------------------------------------------------------------------- ! allocate state arrays NipcMyPhase = count(material_phaseAt == p) * discretization_nIP - sizeDotState = size(['tau_slip ','gamma_slip']) * prm%totalNslip & - + size(['tau_twin ','gamma_twin']) * prm%totalNtwin + sizeDotState = size(['xi_sl ','gamma_sl']) * prm%sum_N_sl & + + size(['xi_tw ','gamma_tw']) * prm%sum_N_tw sizeState = sizeDotState call material_allocatePlasticState(p,NipcMyPhase,sizeState,sizeDotState,0) !-------------------------------------------------------------------------------------------------- -! locally defined state aliases and initialization of state0 and aTolState +! state aliases and initialization startIndex = 1 - endIndex = prm%totalNslip + endIndex = prm%sum_N_sl stt%xi_slip => plasticState(p)%state (startIndex:endIndex,:) - stt%xi_slip = spread(prm%xi_slip_0, 2, NipcMyPhase) + stt%xi_slip = spread(xi_slip_0, 2, NipcMyPhase) dot%xi_slip => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_xi' startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNtwin + endIndex = endIndex + prm%sum_N_tw stt%xi_twin => plasticState(p)%state (startIndex:endIndex,:) - stt%xi_twin = spread(prm%xi_twin_0, 2, NipcMyPhase) + stt%xi_twin = spread(xi_twin_0, 2, NipcMyPhase) dot%xi_twin => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolResistance + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_xi',defaultVal=1.0_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_xi' startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNslip + endIndex = endIndex + prm%sum_N_sl stt%gamma_slip => plasticState(p)%state (startIndex:endIndex,:) dot%gamma_slip => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolShear + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_gamma' ! global alias - plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) + plasticState(p)%slipRate => plasticState(p)%dotState(startIndex:endIndex,:) startIndex = endIndex + 1 - endIndex = endIndex + prm%totalNtwin + endIndex = endIndex + prm%sum_N_tw stt%gamma_twin => plasticState(p)%state (startIndex:endIndex,:) dot%gamma_twin => plasticState(p)%dotState(startIndex:endIndex,:) - plasticState(p)%aTolState(startIndex:endIndex) = prm%aTolShear + plasticState(p)%atol(startIndex:endIndex) = config%getFloat('atol_gamma',defaultVal=1.0e-6_pReal) + if(any(plasticState(p)%atol(startIndex:endIndex) < 0.0_pReal)) extmsg = trim(extmsg)//' atol_gamma' plasticState(p)%state0 = plasticState(p)%state ! ToDo: this could be done centrally end associate +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//PLASTICITY_PHENOPOWERLAW_LABEL//')') + enddo end subroutine plastic_phenopowerlaw_init @@ -291,10 +282,10 @@ pure module subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,insta integer :: & i,k,l,m,n - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & gdot_slip_pos,gdot_slip_neg, & dgdot_dtauslip_pos,dgdot_dtauslip_neg - real(pReal), dimension(param(instance)%totalNtwin) :: & + real(pReal), dimension(param(instance)%sum_N_tw) :: & gdot_twin,dgdot_dtautwin Lp = 0.0_pReal @@ -303,20 +294,20 @@ pure module subroutine plastic_phenopowerlaw_LpAndItsTangent(Lp,dLp_dMp,Mp,insta associate(prm => param(instance)) call kinetics_slip(Mp,instance,of,gdot_slip_pos,gdot_slip_neg,dgdot_dtauslip_pos,dgdot_dtauslip_neg) - slipSystems: do i = 1, prm%totalNslip - Lp = Lp + (gdot_slip_pos(i)+gdot_slip_neg(i))*prm%Schmid_slip(1:3,1:3,i) + slipSystems: do i = 1, prm%sum_N_sl + Lp = Lp + (gdot_slip_pos(i)+gdot_slip_neg(i))*prm%P_sl(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & - + dgdot_dtauslip_pos(i) * prm%Schmid_slip(k,l,i) * prm%nonSchmid_pos(m,n,i) & - + dgdot_dtauslip_neg(i) * prm%Schmid_slip(k,l,i) * prm%nonSchmid_neg(m,n,i) + + dgdot_dtauslip_pos(i) * prm%P_sl(k,l,i) * prm%nonSchmid_pos(m,n,i) & + + dgdot_dtauslip_neg(i) * prm%P_sl(k,l,i) * prm%nonSchmid_neg(m,n,i) enddo slipSystems call kinetics_twin(Mp,instance,of,gdot_twin,dgdot_dtautwin) - twinSystems: do i = 1, prm%totalNtwin - Lp = Lp + gdot_twin(i)*prm%Schmid_twin(1:3,1:3,i) + twinSystems: do i = 1, prm%sum_N_tw + Lp = Lp + gdot_twin(i)*prm%P_tw(1:3,1:3,i) forall (k=1:3,l=1:3,m=1:3,n=1:3) & dLp_dMp(k,l,m,n) = dLp_dMp(k,l,m,n) & - + dgdot_dtautwin(i)*prm%Schmid_twin(k,l,i)*prm%Schmid_twin(m,n,i) + + dgdot_dtautwin(i)*prm%P_tw(k,l,i)*prm%P_tw(m,n,i) enddo twinSystems end associate @@ -339,7 +330,7 @@ module subroutine plastic_phenopowerlaw_dotState(Mp,instance,of) c_SlipSlip,c_TwinSlip,c_TwinTwin, & xi_slip_sat_offset,& sumGamma,sumF - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & left_SlipSlip,right_SlipSlip, & gdot_slip_pos,gdot_slip_neg @@ -395,18 +386,18 @@ module subroutine plastic_phenopowerlaw_results(instance,group) select case(trim(prm%output(o))) case('resistance_slip') - if(prm%totalNslip>0) call results_writeDataset(group,stt%xi_slip, 'xi_sl', & - 'resistance against plastic slip','Pa') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%xi_slip, 'xi_sl', & + 'resistance against plastic slip','Pa') case('accumulatedshear_slip') - if(prm%totalNslip>0) call results_writeDataset(group,stt%gamma_slip,'gamma_sl', & - 'plastic shear','1') + if(prm%sum_N_sl>0) call results_writeDataset(group,stt%gamma_slip,'gamma_sl', & + 'plastic shear','1') case('resistance_twin') - if(prm%totalNtwin>0) call results_writeDataset(group,stt%xi_twin, 'xi_tw', & - 'resistance against twinning','Pa') + if(prm%sum_N_tw>0) call results_writeDataset(group,stt%xi_twin, 'xi_tw', & + 'resistance against twinning','Pa') case('accumulatedshear_twin') - if(prm%totalNtwin>0) call results_writeDataset(group,stt%gamma_twin,'gamma_tw', & - 'twinning shear','1') + if(prm%sum_N_tw>0) call results_writeDataset(group,stt%gamma_twin,'gamma_tw', & + 'twinning shear','1') end select enddo outputsLoop @@ -431,31 +422,28 @@ pure subroutine kinetics_slip(Mp,instance,of, & instance, & of - real(pReal), intent(out), dimension(param(instance)%totalNslip) :: & + real(pReal), intent(out), dimension(param(instance)%sum_N_sl) :: & gdot_slip_pos, & gdot_slip_neg - real(pReal), intent(out), optional, dimension(param(instance)%totalNslip) :: & + real(pReal), intent(out), optional, dimension(param(instance)%sum_N_sl) :: & dgdot_dtau_slip_pos, & dgdot_dtau_slip_neg - real(pReal), dimension(param(instance)%totalNslip) :: & + real(pReal), dimension(param(instance)%sum_N_sl) :: & tau_slip_pos, & tau_slip_neg integer :: i - logical :: nonSchmidActive associate(prm => param(instance), stt => state(instance)) - nonSchmidActive = size(prm%nonSchmidCoeff) > 0 - - do i = 1, prm%totalNslip - tau_slip_pos(i) = math_mul33xx33(Mp,prm%nonSchmid_pos(1:3,1:3,i)) - tau_slip_neg(i) = merge(math_mul33xx33(Mp,prm%nonSchmid_neg(1:3,1:3,i)), & - 0.0_pReal, nonSchmidActive) + do i = 1, prm%sum_N_sl + tau_slip_pos(i) = math_tensordot(Mp,prm%nonSchmid_pos(1:3,1:3,i)) + tau_slip_neg(i) = merge(math_tensordot(Mp,prm%nonSchmid_neg(1:3,1:3,i)), & + 0.0_pReal, prm%nonSchmidActive) enddo where(dNeq0(tau_slip_pos)) - gdot_slip_pos = prm%gdot0_slip * merge(0.5_pReal,1.0_pReal, nonSchmidActive) & ! 1/2 if non-Schmid active + gdot_slip_pos = prm%gdot0_slip * merge(0.5_pReal,1.0_pReal, prm%nonSchmidActive) & ! 1/2 if non-Schmid active * sign(abs(tau_slip_pos/stt%xi_slip(:,of))**prm%n_slip, tau_slip_pos) else where gdot_slip_pos = 0.0_pReal @@ -503,19 +491,19 @@ pure subroutine kinetics_twin(Mp,instance,of,& instance, & of - real(pReal), dimension(param(instance)%totalNtwin), intent(out) :: & + real(pReal), dimension(param(instance)%sum_N_tw), intent(out) :: & gdot_twin - real(pReal), dimension(param(instance)%totalNtwin), intent(out), optional :: & + real(pReal), dimension(param(instance)%sum_N_tw), intent(out), optional :: & dgdot_dtau_twin - real(pReal), dimension(param(instance)%totalNtwin) :: & + real(pReal), dimension(param(instance)%sum_N_tw) :: & tau_twin integer :: i associate(prm => param(instance), stt => state(instance)) - do i = 1, prm%totalNtwin - tau_twin(i) = math_mul33xx33(Mp,prm%Schmid_twin(1:3,1:3,i)) + do i = 1, prm%sum_N_tw + tau_twin(i) = math_tensordot(Mp,prm%P_tw(1:3,1:3,i)) enddo where(tau_twin > 0.0_pReal) diff --git a/src/crystallite.f90 b/src/crystallite.f90 index d1f073a91..9f7ea0be8 100644 --- a/src/crystallite.f90 +++ b/src/crystallite.f90 @@ -91,9 +91,9 @@ module crystallite subStepSizeLp, & !< size of first substep when cutback in Lp calculation subStepSizeLi, & !< size of first substep when cutback in Li calculation stepIncreaseCryst, & !< increase of next substep size when previous substep converged - rTol_crystalliteState, & !< relative tolerance in state loop - rTol_crystalliteStress, & !< relative tolerance in stress loop - aTol_crystalliteStress !< absolute tolerance in stress loop + rtol_crystalliteState, & !< relative tolerance in state loop + rtol_crystalliteStress, & !< relative tolerance in stress loop + atol_crystalliteStress !< absolute tolerance in stress loop end type tNumerics type(tNumerics) :: num ! numerics parameters. Better name? @@ -171,9 +171,9 @@ subroutine crystallite_init num%subStepSizeLp = config_numerics%getFloat('substepsizelp', defaultVal=0.5_pReal) num%subStepSizeLi = config_numerics%getFloat('substepsizeli', defaultVal=0.5_pReal) - num%rTol_crystalliteState = config_numerics%getFloat('rtol_crystallitestate', defaultVal=1.0e-6_pReal) - num%rTol_crystalliteStress = config_numerics%getFloat('rtol_crystallitestress',defaultVal=1.0e-6_pReal) - num%aTol_crystalliteStress = config_numerics%getFloat('atol_crystallitestress',defaultVal=1.0e-8_pReal) + num%rtol_crystalliteState = config_numerics%getFloat('rtol_crystallitestate', defaultVal=1.0e-6_pReal) + num%rtol_crystalliteStress = config_numerics%getFloat('rtol_crystallitestress',defaultVal=1.0e-6_pReal) + num%atol_crystalliteStress = config_numerics%getFloat('atol_crystallitestress',defaultVal=1.0e-8_pReal) num%iJacoLpresiduum = config_numerics%getInt ('ijacolpresiduum', defaultVal=1) @@ -187,9 +187,9 @@ subroutine crystallite_init if(num%subStepSizeLp <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeLp') if(num%subStepSizeLi <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeLi') - if(num%rTol_crystalliteState <= 0.0_pReal) call IO_error(301,ext_msg='rTol_crystalliteState') - if(num%rTol_crystalliteStress <= 0.0_pReal) call IO_error(301,ext_msg='rTol_crystalliteStress') - if(num%aTol_crystalliteStress <= 0.0_pReal) call IO_error(301,ext_msg='aTol_crystalliteStress') + if(num%rtol_crystalliteState <= 0.0_pReal) call IO_error(301,ext_msg='rtol_crystalliteState') + if(num%rtol_crystalliteStress <= 0.0_pReal) call IO_error(301,ext_msg='rtol_crystalliteStress') + if(num%atol_crystalliteStress <= 0.0_pReal) call IO_error(301,ext_msg='atol_crystalliteStress') if(num%iJacoLpresiduum < 1) call IO_error(301,ext_msg='iJacoLpresiduum') @@ -606,7 +606,7 @@ subroutine crystallite_orientations do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1),FEsolving_execIP(2) do c = 1,homogenization_Ngrains(material_homogenizationAt(e)) - call crystallite_orientation(c,i,e)%fromMatrix(transpose(math_rotationalPart33(crystallite_Fe(1:3,1:3,c,i,e)))) + call crystallite_orientation(c,i,e)%fromMatrix(transpose(math_rotationalPart(crystallite_Fe(1:3,1:3,c,i,e)))) enddo; enddo; enddo !$OMP END PARALLEL DO @@ -614,8 +614,9 @@ subroutine crystallite_orientations !$OMP PARALLEL DO do e = FEsolving_execElem(1),FEsolving_execElem(2) do i = FEsolving_execIP(1),FEsolving_execIP(2) - if (plasticState(material_phaseAt(1,e))%nonLocal) & ! if nonlocal model - call plastic_nonlocal_updateCompatibility(crystallite_orientation,i,e) + if (plasticState(material_phaseAt(1,e))%nonLocal) & + call plastic_nonlocal_updateCompatibility(crystallite_orientation, & + phase_plasticityInstance(material_phaseAt(i,e)),i,e) enddo; enddo !$OMP END PARALLEL DO endif nonlocalPresent @@ -651,7 +652,7 @@ subroutine crystallite_results integer :: p,o real(pReal), allocatable, dimension(:,:,:) :: selected_tensors type(rotation), allocatable, dimension(:) :: selected_rotations - character(len=pStringLen) :: group,lattice_label + character(len=pStringLen) :: group,structureLabel do p=1,size(config_name_phase) group = trim('current/constituent')//'/'//trim(config_name_phase(p))//'/generic' @@ -687,29 +688,29 @@ subroutine crystallite_results case('p') selected_tensors = select_tensors(crystallite_P,p) call results_writeDataset(group,selected_tensors,'P',& - '1st Piola-Kirchoff stress','Pa') + 'First Piola-Kirchoff stress','Pa') case('s') selected_tensors = select_tensors(crystallite_S,p) call results_writeDataset(group,selected_tensors,'S',& - '2nd Piola-Kirchoff stress','Pa') + 'Second Piola-Kirchoff stress','Pa') case('orientation') select case(lattice_structure(p)) - case(LATTICE_iso_ID) - lattice_label = 'iso' - case(LATTICE_fcc_ID) - lattice_label = 'fcc' - case(LATTICE_bcc_ID) - lattice_label = 'bcc' - case(LATTICE_bct_ID) - lattice_label = 'bct' - case(LATTICE_hex_ID) - lattice_label = 'hex' - case(LATTICE_ort_ID) - lattice_label = 'ort' + case(lattice_ISO_ID) + structureLabel = 'iso' + case(lattice_FCC_ID) + structureLabel = 'fcc' + case(lattice_BCC_ID) + structureLabel = 'bcc' + case(lattice_BCT_ID) + structureLabel = 'bct' + case(lattice_HEX_ID) + structureLabel = 'hex' + case(lattice_ORT_ID) + structureLabel = 'ort' end select selected_rotations = select_rotations(crystallite_orientation,p) call results_writeDataset(group,selected_rotations,'orientation',& - 'crystal orientation as quaternion',lattice_label) + 'crystal orientation as quaternion',structureLabel) end select enddo enddo @@ -824,8 +825,8 @@ logical function integrateStress(ipc,ip,el,timeFraction) real(pReal) steplengthLp, & steplengthLi, & dt, & ! time increment - aTolLp, & - aTolLi, & + atol_Lp, & + atol_Li, & devNull integer NiterationStressLp, & ! number of stress integrations NiterationStressLi, & ! number of inner stress integrations @@ -891,13 +892,13 @@ logical function integrateStress(ipc,ip,el,timeFraction) S, Fi_new, ipc, ip, el) !* update current residuum and check for convergence of loop - aTolLp = max(num%rTol_crystalliteStress * max(norm2(Lpguess),norm2(Lp_constitutive)), & ! absolute tolerance from largest acceptable relative error - num%aTol_crystalliteStress) ! minimum lower cutoff + atol_Lp = max(num%rtol_crystalliteStress * max(norm2(Lpguess),norm2(Lp_constitutive)), & ! absolute tolerance from largest acceptable relative error + num%atol_crystalliteStress) ! minimum lower cutoff residuumLp = Lpguess - Lp_constitutive if (any(IEEE_is_NaN(residuumLp))) then return ! error - elseif (norm2(residuumLp) < aTolLp) then ! converged if below absolute tolerance + elseif (norm2(residuumLp) < atol_Lp) then ! converged if below absolute tolerance exit LpLoop elseif (NiterationStressLp == 1 .or. norm2(residuumLp) < norm2(residuumLp_old)) then ! not converged, but improved norm of residuum (always proceed in first iteration)... residuumLp_old = residuumLp ! ...remember old values and... @@ -934,12 +935,12 @@ logical function integrateStress(ipc,ip,el,timeFraction) S, Fi_new, ipc, ip, el) !* update current residuum and check for convergence of loop - aTolLi = max(num%rTol_crystalliteStress * max(norm2(Liguess),norm2(Li_constitutive)), & ! absolute tolerance from largest acceptable relative error - num%aTol_crystalliteStress) ! minimum lower cutoff + atol_Li = max(num%rtol_crystalliteStress * max(norm2(Liguess),norm2(Li_constitutive)), & ! absolute tolerance from largest acceptable relative error + num%atol_crystalliteStress) ! minimum lower cutoff residuumLi = Liguess - Li_constitutive if (any(IEEE_is_NaN(residuumLi))) then return ! error - elseif (norm2(residuumLi) < aTolLi) then ! converged if below absolute tolerance + elseif (norm2(residuumLi) < atol_Li) then ! converged if below absolute tolerance exit LiLoop elseif (NiterationStressLi == 1 .or. norm2(residuumLi) < norm2(residuumLi_old)) then ! not converged, but improved norm of residuum (always proceed in first iteration)... residuumLi_old = residuumLi ! ...remember old values and... @@ -1089,7 +1090,7 @@ subroutine integrateStateFPI crystallite_converged(g,i,e) = converged(residuum_plastic(1:sizeDotState), & plasticState(p)%state(1:sizeDotState,c), & - plasticState(p)%aTolState(1:sizeDotState)) + plasticState(p)%atol(1:sizeDotState)) do s = 1, phase_Nsources(p) @@ -1113,7 +1114,7 @@ subroutine integrateStateFPI crystallite_converged(g,i,e) = & crystallite_converged(g,i,e) .and. converged(residuum_source(1:sizeDotState), & sourceState(p)%p(s)%state(1:sizeDotState,c), & - sourceState(p)%p(s)%aTolState(1:sizeDotState)) + sourceState(p)%p(s)%atol(1:sizeDotState)) enddo endif enddo; enddo; enddo @@ -1269,7 +1270,7 @@ subroutine integrateStateAdaptiveEuler crystallite_converged(g,i,e) = converged(residuum_plastic(1:sizeDotState,g,i,e), & plasticState(p)%state(1:sizeDotState,c), & - plasticState(p)%aTolState(1:sizeDotState)) + plasticState(p)%atol(1:sizeDotState)) do s = 1, phase_Nsources(p) sizeDotState = sourceState(p)%p(s)%sizeDotState @@ -1280,7 +1281,7 @@ subroutine integrateStateAdaptiveEuler crystallite_converged(g,i,e) = & crystallite_converged(g,i,e) .and. converged(residuum_source(1:sizeDotState,s,g,i,e), & sourceState(p)%p(s)%state(1:sizeDotState,c), & - sourceState(p)%p(s)%aTolState(1:sizeDotState)) + sourceState(p)%p(s)%atol(1:sizeDotState)) enddo endif @@ -1497,7 +1498,7 @@ subroutine integrateStateRKCK45 crystallite_todo(g,i,e) = converged(residuum_plastic(1:sizeDotState,g,i,e), & plasticState(p)%state(1:sizeDotState,cc), & - plasticState(p)%aTolState(1:sizeDotState)) + plasticState(p)%atol(1:sizeDotState)) do s = 1, phase_Nsources(p) sizeDotState = sourceState(p)%p(s)%sizeDotState @@ -1505,7 +1506,7 @@ subroutine integrateStateRKCK45 crystallite_todo(g,i,e) = & crystallite_todo(g,i,e) .and. converged(residuum_source(1:sizeDotState,s,g,i,e), & sourceState(p)%p(s)%state(1:sizeDotState,cc), & - sourceState(p)%p(s)%aTolState(1:sizeDotState)) + sourceState(p)%p(s)%atol(1:sizeDotState)) enddo endif enddo; enddo; enddo @@ -1522,7 +1523,7 @@ end subroutine integrateStateRKCK45 !-------------------------------------------------------------------------------------------------- !> @brief sets convergence flag for nonlocal calculations -!> @detail one non-converged nonlocal sets all other nonlocals to non-converged to trigger cut back +!> @details one non-converged nonlocal sets all other nonlocals to non-converged to trigger cut back !-------------------------------------------------------------------------------------------------- subroutine nonlocalConvergenceCheck @@ -1558,16 +1559,16 @@ end subroutine setConvergenceFlag !-------------------------------------------------------------------------------------------------- !> @brief determines whether a point is converged !-------------------------------------------------------------------------------------------------- - logical pure function converged(residuum,state,aTol) + logical pure function converged(residuum,state,atol) real(pReal), intent(in), dimension(:) ::& - residuum, state, aTol + residuum, state, atol real(pReal) :: & rTol rTol = num%rTol_crystalliteState - converged = all(abs(residuum) <= max(aTol, rTol*abs(state))) + converged = all(abs(residuum) <= max(atol, rtol*abs(state))) end function converged diff --git a/src/discretization.f90 b/src/discretization.f90 index 21cd2b616..e9a987912 100644 --- a/src/discretization.f90 +++ b/src/discretization.f90 @@ -25,7 +25,7 @@ module discretization discretization_NodeCoords integer :: & - discretization_sharedNodesBeginn + discretization_sharedNodesBegin public :: & discretization_init, & @@ -40,7 +40,7 @@ contains !-------------------------------------------------------------------------------------------------- subroutine discretization_init(homogenizationAt,microstructureAt,& IPcoords0,NodeCoords0,& - sharedNodesBeginn) + sharedNodesBegin) integer, dimension(:), intent(in) :: & homogenizationAt, & @@ -49,7 +49,7 @@ subroutine discretization_init(homogenizationAt,microstructureAt,& IPcoords0, & NodeCoords0 integer, optional, intent(in) :: & - sharedNodesBeginn + sharedNodesBegin write(6,'(/,a)') ' <<<+- discretization init -+>>>'; flush(6) @@ -65,10 +65,10 @@ subroutine discretization_init(homogenizationAt,microstructureAt,& discretization_NodeCoords0 = NodeCoords0 discretization_NodeCoords = NodeCoords0 - if(present(sharedNodesBeginn)) then - discretization_sharedNodesBeginn = sharedNodesBeginn + if(present(sharedNodesBegin)) then + discretization_sharedNodesBegin = sharedNodesBegin else - discretization_sharedNodesBeginn = size(discretization_NodeCoords0,2) + discretization_sharedNodesBegin = size(discretization_NodeCoords0,2) endif end subroutine discretization_init @@ -83,8 +83,8 @@ subroutine discretization_results call results_closeGroup(results_addGroup('current/geometry')) - u = discretization_NodeCoords (1:3,:discretization_sharedNodesBeginn) & - - discretization_NodeCoords0(1:3,:discretization_sharedNodesBeginn) + u = discretization_NodeCoords (1:3,:discretization_sharedNodesBegin) & + - discretization_NodeCoords0(1:3,:discretization_sharedNodesBegin) call results_writeDataset('current/geometry',u,'u_n','displacements of the nodes','m') u = discretization_IPcoords & diff --git a/src/mesh_grid.f90 b/src/grid/discretization_grid.f90 similarity index 98% rename from src/mesh_grid.f90 rename to src/grid/discretization_grid.f90 index 0366f2213..8413fc5e8 100644 --- a/src/mesh_grid.f90 +++ b/src/grid/discretization_grid.f90 @@ -4,7 +4,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Parse geometry file to set up discretization and geometry for nonlocal model !-------------------------------------------------------------------------------------------------- -module mesh_grid +module discretization_grid #include use PETScsys @@ -34,7 +34,7 @@ module mesh_grid size3offset !< (local) size offset in 3rd direction public :: & - mesh_init + discretization_grid_init contains @@ -42,7 +42,7 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief reads the geometry file to obtain information on discretization !-------------------------------------------------------------------------------------------------- -subroutine mesh_init +subroutine discretization_grid_init include 'fftw3-mpi.f03' real(pReal), dimension(3) :: & @@ -59,7 +59,7 @@ subroutine mesh_init integer(C_INTPTR_T) :: & devNull, z, z_offset - write(6,'(/,a)') ' <<<+- mesh_grid init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- discretization_grid init -+>>>'; flush(6) call readGeom(grid,geomSize,origin,microstructureAt,homogenizationAt) @@ -120,7 +120,7 @@ subroutine mesh_init if (debug_e < 1 .or. debug_e > product(myGrid)) call IO_error(602,ext_msg='element') ! selected element does not exist if (debug_i /= 1) call IO_error(602,ext_msg='IP') ! selected IP does not exist -end subroutine mesh_init +end subroutine discretization_grid_init !-------------------------------------------------------------------------------------------------- @@ -434,4 +434,4 @@ pure function IPneighborhood(grid) end function IPneighborhood -end module mesh_grid +end module discretization_grid diff --git a/src/grid/grid_damage_spectral.f90 b/src/grid/grid_damage_spectral.f90 index 8460ea8be..eda60d070 100644 --- a/src/grid/grid_damage_spectral.f90 +++ b/src/grid/grid_damage_spectral.f90 @@ -12,7 +12,7 @@ module grid_damage_spectral use prec use spectral_utilities - use mesh_grid + use discretization_grid use damage_nonlocal use numerics diff --git a/src/grid/grid_mech_FEM.f90 b/src/grid/grid_mech_FEM.f90 index 57a27ebe8..9cdf2f5b5 100644 --- a/src/grid/grid_mech_FEM.f90 +++ b/src/grid/grid_mech_FEM.f90 @@ -19,7 +19,7 @@ module grid_mech_FEM use numerics use homogenization use discretization - use mesh_grid + use discretization_grid use debug implicit none diff --git a/src/grid/grid_mech_spectral_basic.f90 b/src/grid/grid_mech_spectral_basic.f90 index 25ac9cb63..e04dd49f3 100644 --- a/src/grid/grid_mech_spectral_basic.f90 +++ b/src/grid/grid_mech_spectral_basic.f90 @@ -19,7 +19,7 @@ module grid_mech_spectral_basic use config use numerics use homogenization - use mesh_grid + use discretization_grid use debug implicit none diff --git a/src/grid/grid_mech_spectral_polarisation.f90 b/src/grid/grid_mech_spectral_polarisation.f90 index ab880e2a6..80ed2e485 100644 --- a/src/grid/grid_mech_spectral_polarisation.f90 +++ b/src/grid/grid_mech_spectral_polarisation.f90 @@ -20,7 +20,7 @@ module grid_mech_spectral_polarisation use config use numerics use homogenization - use mesh_grid + use discretization_grid use debug implicit none diff --git a/src/grid/grid_thermal_spectral.f90 b/src/grid/grid_thermal_spectral.f90 index 1fe6aeab0..1c8314369 100644 --- a/src/grid/grid_thermal_spectral.f90 +++ b/src/grid/grid_thermal_spectral.f90 @@ -12,7 +12,7 @@ module grid_thermal_spectral use prec use spectral_utilities - use mesh_grid + use discretization_grid use thermal_conduction use numerics use material diff --git a/src/grid/spectral_utilities.f90 b/src/grid/spectral_utilities.f90 index 87e906727..55375ee32 100644 --- a/src/grid/spectral_utilities.f90 +++ b/src/grid/spectral_utilities.f90 @@ -9,10 +9,11 @@ module spectral_utilities use PETScSys use prec + use DAMASK_interface use math use rotations use IO - use mesh_grid + use discretization_grid use numerics use debug use config @@ -26,12 +27,11 @@ module spectral_utilities !-------------------------------------------------------------------------------------------------- ! field labels information - enum, bind(c) - enumerator :: & - FIELD_UNDEFINED_ID, & - FIELD_MECH_ID, & - FIELD_THERMAL_ID, & - FIELD_DAMAGE_ID + enum, bind(c); enumerator :: & + FIELD_UNDEFINED_ID, & + FIELD_MECH_ID, & + FIELD_THERMAL_ID, & + FIELD_DAMAGE_ID end enum !-------------------------------------------------------------------------------------------------- @@ -125,11 +125,10 @@ module spectral_utilities type(tNumerics) :: num ! numerics parameters. Better name? - enum, bind(c) - enumerator :: & - DERIVATIVE_CONTINUOUS_ID, & - DERIVATIVE_CENTRAL_DIFF_ID, & - DERIVATIVE_FWBW_DIFF_ID + enum, bind(c); enumerator :: & + DERIVATIVE_CONTINUOUS_ID, & + DERIVATIVE_CENTRAL_DIFF_ID, & + DERIVATIVE_FWBW_DIFF_ID end enum integer(kind(DERIVATIVE_CONTINUOUS_ID)) :: & @@ -430,7 +429,7 @@ end subroutine utilities_updateGamma !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTtensorForward - tensorField_real(1:3,1:3,grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) + tensorField_real(1:3,1:3,grid(1)+1:grid1Red*2,:,:) = 0.0_pReal call fftw_mpi_execute_dft_r2c(planTensorForth,tensorField_real,tensorField_fourier) end subroutine utilities_FFTtensorForward @@ -454,7 +453,7 @@ end subroutine utilities_FFTtensorBackward !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTscalarForward - scalarField_real(grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) + scalarField_real(grid(1)+1:grid1Red*2,:,:) = 0.0_pReal call fftw_mpi_execute_dft_r2c(planScalarForth,scalarField_real,scalarField_fourier) end subroutine utilities_FFTscalarForward @@ -479,7 +478,7 @@ end subroutine utilities_FFTscalarBackward !-------------------------------------------------------------------------------------------------- subroutine utilities_FFTvectorForward - vectorField_real(1:3,grid(1)+1:grid1Red*2,:,:) = cmplx(0.0,0.0,pReal) + vectorField_real(1:3,grid(1)+1:grid1Red*2,:,:) = 0.0_pReal call fftw_mpi_execute_dft_r2c(planVectorForth,vectorField_real,vectorField_fourier) end subroutine utilities_FFTvectorForward @@ -1030,7 +1029,7 @@ subroutine utilities_updateCoords(F) do k = 1, grid3; do j = 1, grid(2); do i = 1, grid1Red if(any([i,j,k+grid3Offset] /= 1)) then vectorField_fourier(1:3,i,j,k) = matmul(tensorField_fourier(1:3,1:3,i,j,k),xi2nd(1:3,i,j,k)) & - / sum(conjg(-xi2nd(1:3,i,j,k))*xi2nd(1:3,i,j,k)) * wgt + / sum(conjg(-xi2nd(1:3,i,j,k))*xi2nd(1:3,i,j,k)) * cmplx(wgt,0.0,pReal) else vectorField_fourier(1:3,i,j,k) = cmplx(0.0,0.0,pReal) endif @@ -1082,7 +1081,7 @@ subroutine utilities_updateCoords(F) ! calculate cell center displacements do k = 1,grid3; do j = 1,grid(2); do i = 1,grid(1) IPcoords(1:3,i,j,k) = vectorField_real(1:3,i,j,k) & - + matmul(Favg,step*real([i,j,k+grid3Offset]-0.5_pReal,pReal)) + + matmul(Favg,step*(real([i,j,k+grid3Offset],pReal)-0.5_pReal)) enddo; enddo; enddo call discretization_setNodeCoords(reshape(NodeCoords,[3,(grid(1)+1)*(grid(2)+1)*(grid3+1)])) @@ -1101,7 +1100,7 @@ subroutine utilities_saveReferenceStiffness if (worldrank == 0) then write(6,'(a)') ' writing reference stiffness data required for restart to file'; flush(6) - fileUnit = IO_open_jobFile_binary('C_ref','w') + fileUnit = IO_open_binary(trim(getSolverJobName())//'.C_ref','w') write(fileUnit) C_ref close(fileUnit) endif diff --git a/src/homogenization.f90 b/src/homogenization.f90 index 9d935866c..b657dfe3e 100644 --- a/src/homogenization.f90 +++ b/src/homogenization.f90 @@ -23,7 +23,7 @@ module homogenization use damage_local use damage_nonlocal use results - + implicit none private @@ -48,24 +48,35 @@ module homogenization materialpoint_converged logical, dimension(:,:,:), allocatable :: & materialpoint_doneAndHappy - + + type :: tNumerics + integer :: & + nMPstate !< materialpoint state loop limit + real(pReal) :: & + subStepMinHomog, & !< minimum (relative) size of sub-step allowed during cutback in homogenization + subStepSizeHomog, & !< size of first substep when cutback in homogenization + stepIncreaseHomog !< increase of next substep size when previous substep converged in homogenization + end type tNumerics + + type(tNumerics) :: num + interface module subroutine mech_none_init end subroutine mech_none_init - + module subroutine mech_isostrain_init end subroutine mech_isostrain_init - + module subroutine mech_RGC_init end subroutine mech_RGC_init - - + + module subroutine mech_isostrain_partitionDeformation(F,avgF) real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point end subroutine mech_isostrain_partitionDeformation - + module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) real(pReal), dimension (:,:,:), intent(out) :: F !< partitioned deformation gradient real(pReal), dimension (3,3), intent(in) :: avgF !< average deformation gradient at material point @@ -73,30 +84,30 @@ module homogenization instance, & of end subroutine mech_RGC_partitionDeformation - - + + module subroutine mech_isostrain_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point - + real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses - integer, intent(in) :: instance + integer, intent(in) :: instance end subroutine mech_isostrain_averageStressAndItsTangent - + module subroutine mech_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) real(pReal), dimension (3,3), intent(out) :: avgP !< average stress at material point real(pReal), dimension (3,3,3,3), intent(out) :: dAvgPdAvgF !< average stiffness at material point - + real(pReal), dimension (:,:,:), intent(in) :: P !< partitioned stresses real(pReal), dimension (:,:,:,:,:), intent(in) :: dPdF !< partitioned stiffnesses - integer, intent(in) :: instance + integer, intent(in) :: instance end subroutine mech_RGC_averageStressAndItsTangent - - + + module function mech_RGC_updateState(P,F,F0,avgF,dt,dPdF,ip,el) logical, dimension(2) :: mech_RGC_updateState - real(pReal), dimension(:,:,:), intent(in) :: & + real(pReal), dimension(:,:,:), intent(in) :: & P,& !< partitioned stresses F,& !< partitioned deformation gradients F0 !< partitioned initial deformation gradients @@ -113,7 +124,7 @@ module homogenization integer, intent(in) :: instance !< homogenization instance character(len=*), intent(in) :: group !< group name in HDF5 file end subroutine mech_RGC_results - + end interface public :: & @@ -179,6 +190,15 @@ subroutine homogenization_init if (debug_g < 1 .or. debug_g > homogenization_Ngrains(material_homogenizationAt(debug_e))) & call IO_error(602,ext_msg='constituent', el=debug_e, g=debug_g) + num%nMPstate = config_numerics%getInt( 'nmpstate', defaultVal=10) + num%subStepMinHomog = config_numerics%getFloat('substepminhomog', defaultVal=1.0e-3_pReal) + num%subStepSizeHomog = config_numerics%getFloat('substepsizehomog', defaultVal=0.25_pReal) + num%stepIncreaseHomog = config_numerics%getFloat('stepincreasehomog', defaultVal=1.5_pReal) + if (num%nMPstate < 1) call IO_error(301,ext_msg='nMPstate') + if (num%subStepMinHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepMinHomog') + if (num%subStepSizeHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeHomog') + if (num%stepIncreaseHomog <= 0.0_pReal) call IO_error(301,ext_msg='stepIncreaseHomog') + end subroutine homogenization_init @@ -235,10 +255,10 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) materialpoint_subF0(1:3,1:3,i,e) = materialpoint_F0(1:3,1:3,i,e) materialpoint_subFrac(i,e) = 0.0_pReal - materialpoint_subStep(i,e) = 1.0_pReal/subStepSizeHomog ! <> + materialpoint_subStep(i,e) = 1.0_pReal/num%subStepSizeHomog ! <> materialpoint_converged(i,e) = .false. ! pretend failed step of twice the required size materialpoint_requested(i,e) = .true. ! everybody requires calculation - + if (homogState(material_homogenizationAt(e))%sizeState > 0) & homogState(material_homogenizationAt(e))%subState0(:,material_homogenizationMemberAt(i,e)) = & homogState(material_homogenizationAt(e))%State0( :,material_homogenizationMemberAt(i,e)) ! ...internal homogenization state @@ -246,17 +266,17 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) if (thermalState(material_homogenizationAt(e))%sizeState > 0) & thermalState(material_homogenizationAt(e))%subState0(:,material_homogenizationMemberAt(i,e)) = & thermalState(material_homogenizationAt(e))%State0( :,material_homogenizationMemberAt(i,e)) ! ...internal thermal state - + if (damageState(material_homogenizationAt(e))%sizeState > 0) & damageState(material_homogenizationAt(e))%subState0(:,material_homogenizationMemberAt(i,e)) = & damageState(material_homogenizationAt(e))%State0( :,material_homogenizationMemberAt(i,e)) ! ...internal damage state enddo enddo - + NiterationHomog = 0 cutBackLooping: do while (.not. terminallyIll .and. & - any(materialpoint_subStep(:,FEsolving_execELem(1):FEsolving_execElem(2)) > subStepMinHomog)) + any(materialpoint_subStep(:,FEsolving_execELem(1):FEsolving_execElem(2)) > num%subStepMinHomog)) !$OMP PARALLEL DO PRIVATE(myNgrains) elementLooping1: do e = FEsolving_execElem(1),FEsolving_execElem(2) @@ -278,9 +298,9 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) ! calculate new subStep and new subFrac materialpoint_subFrac(i,e) = materialpoint_subFrac(i,e) + materialpoint_subStep(i,e) materialpoint_subStep(i,e) = min(1.0_pReal-materialpoint_subFrac(i,e), & - stepIncreaseHomog*materialpoint_subStep(i,e)) ! introduce flexibility for step increase/acceleration + num%stepIncreaseHomog*materialpoint_subStep(i,e)) ! introduce flexibility for step increase/acceleration - steppingNeeded: if (materialpoint_subStep(i,e) > subStepMinHomog) then + steppingNeeded: if (materialpoint_subStep(i,e) > num%subStepMinHomog) then ! wind forward grain starting point of... crystallite_partionedF0 (1:3,1:3,1:myNgrains,i,e) = & @@ -319,14 +339,14 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) if(damageState(material_homogenizationAt(e))%sizeState > 0) & damageState(material_homogenizationAt(e))%subState0(:,material_homogenizationMemberAt(i,e)) = & damageState(material_homogenizationAt(e))%State (:,material_homogenizationMemberAt(i,e)) - + materialpoint_subF0(1:3,1:3,i,e) = materialpoint_subF(1:3,1:3,i,e) endif steppingNeeded else converged if ( (myNgrains == 1 .and. materialpoint_subStep(i,e) <= 1.0 ) .or. & ! single grain already tried internal subStepping in crystallite - subStepSizeHomog * materialpoint_subStep(i,e) <= subStepMinHomog ) then ! would require too small subStep + num%subStepSizeHomog * materialpoint_subStep(i,e) <= num%subStepMinHomog ) then ! would require too small subStep ! cutback makes no sense !$OMP FLUSH(terminallyIll) if (.not. terminallyIll) then ! so first signals terminally ill... @@ -336,7 +356,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) endif terminallyIll = .true. ! ...and kills all others else ! cutback makes sense - materialpoint_subStep(i,e) = subStepSizeHomog * materialpoint_subStep(i,e) ! crystallite had severe trouble, so do a significant cutback + materialpoint_subStep(i,e) = num%subStepSizeHomog * materialpoint_subStep(i,e) ! crystallite had severe trouble, so do a significant cutback #ifdef DEBUG if (iand(debug_level(debug_homogenization), debug_levelExtensive) /= 0 & @@ -382,7 +402,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) endif endif converged - if (materialpoint_subStep(i,e) > subStepMinHomog) then + if (materialpoint_subStep(i,e) > num%subStepMinHomog) then materialpoint_requested(i,e) = .true. materialpoint_subF(1:3,1:3,i,e) = materialpoint_subF0(1:3,1:3,i,e) & + materialpoint_subStep(i,e) * (materialpoint_F(1:3,1:3,i,e) & @@ -400,7 +420,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) any( materialpoint_requested(:,FEsolving_execELem(1):FEsolving_execElem(2)) & .and. .not. materialpoint_doneAndHappy(1,:,FEsolving_execELem(1):FEsolving_execElem(2)) & ) .and. & - NiterationMPstate < nMPstate) + NiterationMPstate < num%nMPstate) NiterationMPstate = NiterationMPstate + 1 !-------------------------------------------------------------------------------------------------- @@ -427,7 +447,7 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) ! crystallite integration ! based on crystallite_partionedF0,.._partionedF ! incrementing by crystallite_dt - + materialpoint_converged = crystallite_stress() !ToDo: MD not sure if that is the best logic !-------------------------------------------------------------------------------------------------- @@ -447,15 +467,15 @@ subroutine materialpoint_stressAndItsTangent(updateJaco,dt) enddo IpLooping3 enddo elementLooping3 !$OMP END PARALLEL DO - + enddo convergenceLooping - + NiterationHomog = NiterationHomog + 1 - + enddo cutBackLooping - + if(updateJaco) call crystallite_stressTangent - + if (.not. terminallyIll ) then call crystallite_orientations() ! calculate crystal orientations !$OMP PARALLEL DO @@ -589,25 +609,25 @@ end subroutine averageStressAndItsTangent subroutine homogenization_results use material, only: & material_homogenization_type => homogenization_type - + integer :: p character(len=pStringLen) :: group_base,group - + !real(pReal), dimension(:,:,:), allocatable :: temp - + do p=1,size(config_name_homogenization) 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') + ! 'deformation gradient','1') !temp = reshape(materialpoint_P,[3,3,discretization_nIP*discretization_nElem]) !call results_writeDataset(group,temp,'P',& - ! '1st Piola-Kirchoff stress','Pa') - + ! '1st Piola-Kirchoff stress','Pa') + group = trim(group_base)//'/mech' call results_closeGroup(results_addGroup(group)) select case(material_homogenization_type(p)) @@ -623,7 +643,7 @@ subroutine homogenization_results 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)) @@ -632,7 +652,7 @@ subroutine homogenization_results case(THERMAL_CONDUCTION_ID) call thermal_conduction_results(p,group) end select - + enddo end subroutine homogenization_results diff --git a/src/homogenization_mech_RGC.f90 b/src/homogenization_mech_RGC.f90 index 2152211b7..e10a0fef9 100644 --- a/src/homogenization_mech_RGC.f90 +++ b/src/homogenization_mech_RGC.f90 @@ -23,7 +23,7 @@ submodule(homogenization) homogenization_mech_RGC character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters - + type :: tRGCstate real(pReal), pointer, dimension(:) :: & work, & @@ -31,7 +31,7 @@ submodule(homogenization) homogenization_mech_RGC real(pReal), pointer, dimension(:,:) :: & relaxationVector end type tRGCstate - + type :: tRGCdependentState real(pReal), allocatable, dimension(:) :: & volumeDiscrepancy, & @@ -42,7 +42,24 @@ submodule(homogenization) homogenization_mech_RGC real(pReal), allocatable, dimension(:,:,:) :: & orientation end type tRGCdependentState - + + type :: tNumerics_RGC + real(pReal) :: & + atol, & !< absolute tolerance of RGC residuum + rtol, & !< relative tolerance of RGC residuum + absMax, & !< absolute maximum of RGC residuum + relMax, & !< relative maximum of RGC residuum + pPert, & !< perturbation for computing RGC penalty tangent + xSmoo, & !< RGC penalty smoothing parameter (hyperbolic tangent) + viscPower, & !< power (sensitivity rate) of numerical viscosity in RGC scheme, Default 1.0e0: Newton viscosity (linear model) + viscModus, & !< stress modulus of RGC numerical viscosity, Default 0.0e0: No viscosity is applied + refRelaxRate, & !< reference relaxation rate in RGC viscosity + maxdRelax, & !< threshold of maximum relaxation vector increment (if exceed this then cutback) + maxVolDiscr, & !< threshold of maximum volume discrepancy allowed + volDiscrMod, & !< stiffness of RGC volume discrepancy (zero = without volume discrepancy constraint) + volDiscrPow !< powerlaw penalty for volume discrepancy + end type tNumerics_RGC + type(tparameters), dimension(:), allocatable :: & param type(tRGCstate), dimension(:), allocatable :: & @@ -50,6 +67,8 @@ submodule(homogenization) homogenization_mech_RGC state0 type(tRGCdependentState), dimension(:), allocatable :: & dependentState + type(tNumerics_RGC) :: & + num ! numerics parameters. Better name? contains @@ -63,26 +82,52 @@ module subroutine mech_RGC_init h, & NofMyHomog, & sizeState, nIntFaceTot - - + write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_RGC_label//' init -+>>>'; flush(6) - + write(6,'(/,a)') ' Tjahjanto et al., International Journal of Material Forming 2(1):939–942, 2009' write(6,'(a)') ' https://doi.org/10.1007/s12289-009-0619-1' - + write(6,'(/,a)') ' Tjahjanto et al., Modelling and Simulation in Materials Science and Engineering 18:015006, 2010' write(6,'(a)') ' https://doi.org/10.1088/0965-0393/18/1/015006' - + Ninstance = count(homogenization_type == HOMOGENIZATION_RGC_ID) if (iand(debug_level(debug_HOMOGENIZATION),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance - + allocate(param(Ninstance)) allocate(state(Ninstance)) allocate(state0(Ninstance)) allocate(dependentState(Ninstance)) - - + + num%atol = config_numerics%getFloat('atol_rgc', defaultVal=1.0e+4_pReal) + num%rtol = config_numerics%getFloat('rtol_rgc', defaultVal=1.0e-3_pReal) + num%absMax = config_numerics%getFloat('amax_rgc', defaultVal=1.0e+10_pReal) + num%relMax = config_numerics%getFloat('rmax_rgc', defaultVal=1.0e+2_pReal) + num%pPert = config_numerics%getFloat('perturbpenalty_rgc', defaultVal=1.0e-7_pReal) + num%xSmoo = config_numerics%getFloat('relvantmismatch_rgc', defaultVal=1.0e-5_pReal) + num%viscPower = config_numerics%getFloat('viscositypower_rgc', defaultVal=1.0e+0_pReal) + num%viscModus = config_numerics%getFloat('viscositymodulus_rgc', defaultVal=0.0e+0_pReal) + num%refRelaxRate = config_numerics%getFloat('refrelaxationrate_rgc',defaultVal=1.0e-3_pReal) + num%maxdRelax = config_numerics%getFloat('maxrelaxationrate_rgc',defaultVal=1.0e+0_pReal) + num%maxVolDiscr = config_numerics%getFloat('maxvoldiscrepancy_rgc',defaultVal=1.0e-5_pReal) + num%volDiscrMod = config_numerics%getFloat('voldiscrepancymod_rgc',defaultVal=1.0e+12_pReal) + num%volDiscrPow = config_numerics%getFloat('dicrepancypower_rgc', defaultVal=5.0_pReal) + + if (num%atol <= 0.0_pReal) call IO_error(301,ext_msg='absTol_RGC') + if (num%rtol <= 0.0_pReal) call IO_error(301,ext_msg='relTol_RGC') + if (num%absMax <= 0.0_pReal) call IO_error(301,ext_msg='absMax_RGC') + if (num%relMax <= 0.0_pReal) call IO_error(301,ext_msg='relMax_RGC') + if (num%pPert <= 0.0_pReal) call IO_error(301,ext_msg='pPert_RGC') + if (num%xSmoo <= 0.0_pReal) call IO_error(301,ext_msg='xSmoo_RGC') + if (num%viscPower < 0.0_pReal) call IO_error(301,ext_msg='viscPower_RGC') + if (num%viscModus < 0.0_pReal) call IO_error(301,ext_msg='viscModus_RGC') + if (num%refRelaxRate <= 0.0_pReal) call IO_error(301,ext_msg='refRelaxRate_RGC') + if (num%maxdRelax <= 0.0_pReal) call IO_error(301,ext_msg='maxdRelax_RGC') + if (num%maxVolDiscr <= 0.0_pReal) call IO_error(301,ext_msg='maxVolDiscr_RGC') + if (num%volDiscrMod < 0.0_pReal) call IO_error(301,ext_msg='volDiscrMod_RGC') + if (num%volDiscrPow <= 0.0_pReal) call IO_error(301,ext_msg='volDiscrPw_RGC') + do h = 1, size(homogenization_type) if (homogenization_type(h) /= HOMOGENIZATION_RGC_ID) cycle associate(prm => param(homogenization_typeInstance(h)), & @@ -90,24 +135,24 @@ module subroutine mech_RGC_init st0 => state0(homogenization_typeInstance(h)), & dst => dependentState(homogenization_typeInstance(h)), & config => config_homogenization(h)) - + #ifdef DEBUG if (h==material_homogenizationAt(debug_e)) then prm%of_debug = material_homogenizationMemberAt(debug_i,debug_e) endif #endif + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + prm%Nconstituents = config%getInts('clustersize',requiredSize=3) if (homogenization_Ngrains(h) /= product(prm%Nconstituents)) & call IO_error(211,ext_msg='clustersize ('//HOMOGENIZATION_RGC_label//')') - + prm%xiAlpha = config%getFloat('scalingparameter') prm%ciAlpha = config%getFloat('overproportionality') - + prm%dAlpha = config%getFloats('grainsize', requiredSize=3) prm%angles = config%getFloats('clusterorientation',requiredSize=3) - - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) NofMyHomog = count(material_homogenizationAt == h) nIntFaceTot = 3*( (prm%Nconstituents(1)-1)*prm%Nconstituents(2)*prm%Nconstituents(3) & @@ -115,17 +160,17 @@ module subroutine mech_RGC_init + prm%Nconstituents(1)*prm%Nconstituents(2)*(prm%Nconstituents(3)-1)) sizeState = nIntFaceTot & + size(['avg constitutive work ','average penalty energy']) - + homogState(h)%sizeState = sizeState allocate(homogState(h)%state0 (sizeState,NofMyHomog), source=0.0_pReal) allocate(homogState(h)%subState0(sizeState,NofMyHomog), source=0.0_pReal) allocate(homogState(h)%state (sizeState,NofMyHomog), source=0.0_pReal) - + stt%relaxationVector => homogState(h)%state(1:nIntFaceTot,:) st0%relaxationVector => homogState(h)%state0(1:nIntFaceTot,:) stt%work => homogState(h)%state(nIntFaceTot+1,:) stt%penaltyEnergy => homogState(h)%state(nIntFaceTot+2,:) - + allocate(dst%volumeDiscrepancy( NofMyHomog)) allocate(dst%relaxationRate_avg( NofMyHomog)) allocate(dst%relaxationRate_max( NofMyHomog)) @@ -135,11 +180,11 @@ module subroutine mech_RGC_init ! assigning cluster orientations dependentState(homogenization_typeInstance(h))%orientation = spread(eu2om(prm%angles*inRad),3,NofMyHomog) !dst%orientation = spread(eu2om(prm%angles*inRad),3,NofMyHomog) ifort version 18.0.1 crashes (for whatever reason) - + end associate - - enddo - + + enddo + end subroutine mech_RGC_init @@ -149,19 +194,19 @@ end subroutine mech_RGC_init module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) real(pReal), dimension (:,:,:), intent(out) :: F !< partioned F per grain - + real(pReal), dimension (3,3), intent(in) :: avgF !< averaged F integer, intent(in) :: & instance, & of - + real(pReal), dimension(3) :: aVect,nVect integer, dimension(4) :: intFace integer, dimension(3) :: iGrain3 integer :: iGrain,iFace,i,j - + associate(prm => param(instance)) - + !-------------------------------------------------------------------------------------------------- ! compute the deformation gradient of individual grains due to relaxations F = 0.0_pReal @@ -187,14 +232,14 @@ module subroutine mech_RGC_partitionDeformation(F,avgF,instance,of) endif #endif enddo - + end associate end subroutine mech_RGC_partitionDeformation !-------------------------------------------------------------------------------------------------- -!> @brief update the internal state of the homogenization scheme and tell whether "done" and +!> @brief update the internal state of the homogenization scheme and tell whether "done" and ! "happy" with result !-------------------------------------------------------------------------------------------------- module procedure mech_RGC_updateState @@ -213,17 +258,17 @@ module procedure mech_RGC_updateState integer, dimension(3) :: stresLoc integer, dimension(2) :: residLoc #endif - + zeroTimeStep: if(dEq0(dt)) then mech_RGC_updateState = .true. ! pretend everything is fine and return - return + return endif zeroTimeStep instance = homogenization_typeInstance(material_homogenizationAt(el)) of = material_homogenizationMemberAt(ip,el) - + associate(stt => state(instance), st0 => state0(instance), dst => dependentState(instance), prm => param(instance)) - + !-------------------------------------------------------------------------------------------------- ! get the dimension of the cluster (grains and interfaces) nGDim = prm%Nconstituents @@ -238,7 +283,7 @@ module procedure mech_RGC_updateState allocate(tract(nIntFaceTot,3), source=0.0_pReal) relax = stt%relaxationVector(:,of) drelax = stt%relaxationVector(:,of) - st0%relaxationVector(:,of) - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0) then write(6,'(1x,a30)')'Obtained state: ' @@ -254,7 +299,7 @@ module procedure mech_RGC_updateState call stressPenalty(R,NN,avgF,F,ip,el,instance,of) !-------------------------------------------------------------------------------------------------- -! calculating volume discrepancy and stress penalty related to overall volume discrepancy +! calculating volume discrepancy and stress penalty related to overall volume discrepancy call volumePenalty(D,dst%volumeDiscrepancy(of),avgF,F,nGrain,instance,of) #ifdef DEBUG @@ -284,7 +329,7 @@ module procedure mech_RGC_updateState iGrN = grain3to1(iGr3N,param(instance)%Nconstituents) ! translate the local grain ID into global coordinate system (1-dimensional index) intFaceN = getInterface(2*faceID(1),iGr3N) normN = interfaceNormal(intFaceN,instance,of) - + !-------------------------------------------------------------------------------------------------- ! identify the right/up/front grain (+|P) iGr3P = iGr3N @@ -296,7 +341,7 @@ module procedure mech_RGC_updateState !-------------------------------------------------------------------------------------------------- ! compute the residual of traction at the interface (in local system, 4-dimensional index) do i = 1,3 - tract(iNum,i) = sign(viscModus_RGC*(abs(drelax(i+3*(iNum-1)))/(refRelaxRate_RGC*dt))**viscPower_RGC, & + tract(iNum,i) = sign(num%viscModus*(abs(drelax(i+3*(iNum-1)))/(num%refRelaxRate*dt))**num%viscPower, & drelax(i+3*(iNum-1))) ! contribution from the relaxation viscosity do j = 1,3 tract(iNum,i) = tract(iNum,i) + (P(i,j,iGrP) + R(i,j,iGrP) + D(i,j,iGrP))*normP(j) & ! contribution from material stress P, mismatch penalty R, and volume penalty D projected into the interface @@ -304,7 +349,7 @@ module procedure mech_RGC_updateState resid(i+3*(iNum-1)) = tract(iNum,i) ! translate the local residual into global 1-dimensional residual array enddo enddo - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0) then write(6,'(1x,a30,1x,i3)')'Traction at interface: ',iNum @@ -332,12 +377,12 @@ module procedure mech_RGC_updateState flush(6) endif #endif - + mech_RGC_updateState = .false. - + !-------------------------------------------------------------------------------------------------- ! If convergence reached => done and happy - if (residMax < relTol_RGC*stresMax .or. residMax < absTol_RGC) then + if (residMax < num%rtol*stresMax .or. residMax < num%atol) then mech_RGC_updateState = .true. #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0 .and. prm%of_debug == of) & @@ -358,7 +403,7 @@ module procedure mech_RGC_updateState dst%mismatch(1:3,of) = sum(NN,2)/real(nGrain,pReal) dst%relaxationRate_avg(of) = sum(abs(drelax))/dt/real(3*nIntFaceTot,pReal) dst%relaxationRate_max(of) = maxval(abs(drelax))/dt - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0 .and. prm%of_debug == of) then write(6,'(1x,a30,1x,e15.8)') 'Constitutive work: ',stt%work(of) @@ -372,31 +417,31 @@ module procedure mech_RGC_updateState flush(6) endif #endif - + return !-------------------------------------------------------------------------------------------------- ! if residual blows-up => done but unhappy - elseif (residMax > relMax_RGC*stresMax .or. residMax > absMax_RGC) then ! try to restart when residual blows up exceeding maximum bound + elseif (residMax > num%relMax*stresMax .or. residMax > num%absMax) then ! try to restart when residual blows up exceeding maximum bound mech_RGC_updateState = [.true.,.false.] ! with direct cut-back - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0 .and. prm%of_debug == of) & write(6,'(1x,a,/)') '... broken'; flush(6) #endif return - + else ! proceed with computing the Jacobian and state update #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0 .and. prm%of_debug == of) & write(6,'(1x,a,/)') '... not yet done'; flush(6) #endif - + endif !--------------------------------------------------------------------------------------------------- -! construct the global Jacobian matrix for updating the global relaxation vector array when +! construct the global Jacobian matrix for updating the global relaxation vector array when ! convergence is not yet reached ... !-------------------------------------------------------------------------------------------------- @@ -404,7 +449,7 @@ module procedure mech_RGC_updateState allocate(smatrix(3*nIntFaceTot,3*nIntFaceTot), source=0.0_pReal) do iNum = 1,nIntFaceTot faceID = interface1to4(iNum,param(instance)%Nconstituents) ! assembling of local dPdF into global Jacobian matrix - + !-------------------------------------------------------------------------------------------------- ! identify the left/bottom/back grain (-|N) iGr3N = faceID(2:4) ! identifying the grain ID in local coordinate sytem @@ -424,7 +469,7 @@ module procedure mech_RGC_updateState ! to obtain the Jacobian matrix contribution of dPdF endif enddo - + !-------------------------------------------------------------------------------------------------- ! identify the right/up/front grain (+|P) iGr3P = iGr3N @@ -444,7 +489,7 @@ module procedure mech_RGC_updateState endif enddo enddo - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0) then write(6,'(1x,a30)')'Jacobian matrix of stress' @@ -455,9 +500,9 @@ module procedure mech_RGC_updateState flush(6) endif #endif - + !-------------------------------------------------------------------------------------------------- -! ... of the stress penalty tangent (mismatch penalty and volume penalty, computed using numerical +! ... of the stress penalty tangent (mismatch penalty and volume penalty, computed using numerical ! perturbation method) "pmatrix" allocate(pmatrix(3*nIntFaceTot,3*nIntFaceTot), source=0.0_pReal) allocate(p_relax(3*nIntFaceTot), source=0.0_pReal) @@ -465,7 +510,7 @@ module procedure mech_RGC_updateState do ipert = 1,3*nIntFaceTot p_relax = relax - p_relax(ipert) = relax(ipert) + pPert_RGC ! perturb the relaxation vector + p_relax(ipert) = relax(ipert) + num%pPert ! perturb the relaxation vector stt%relaxationVector(:,of) = p_relax call grainDeformation(pF,avgF,instance,of) ! rain deformation from perturbed state call stressPenalty(pR,DevNull, avgF,pF,ip,el,instance,of) ! stress penalty due to interface mismatch from perturbed state @@ -483,7 +528,7 @@ module procedure mech_RGC_updateState iGrN = grain3to1(iGr3N,param(instance)%Nconstituents) ! translate the local grain ID into global coordinate system (1-dimensional index) intFaceN = getInterface(2*faceID(1),iGr3N) ! identify the interface ID of the grain normN = interfaceNormal(intFaceN,instance,of) - + !-------------------------------------------------------------------------------------------------- ! identify the right/up/front grain (+|P) iGr3P = iGr3N @@ -491,9 +536,9 @@ module procedure mech_RGC_updateState iGrP = grain3to1(iGr3P,param(instance)%Nconstituents) ! translate the local grain ID into global coordinate system (1-dimensional index) intFaceP = getInterface(2*faceID(1)-1,iGr3P) ! identify the interface ID of the grain normP = interfaceNormal(intFaceP,instance,of) - + !-------------------------------------------------------------------------------------------------- -! compute the residual stress (contribution of mismatch and volume penalties) from perturbed state +! compute the residual stress (contribution of mismatch and volume penalties) from perturbed state ! at all interfaces do i = 1,3; do j = 1,3 p_resid(i+3*(iNum-1)) = p_resid(i+3*(iNum-1)) + (pR(i,j,iGrP) - R(i,j,iGrP))*normP(j) & @@ -502,9 +547,9 @@ module procedure mech_RGC_updateState + (pD(i,j,iGrN) - D(i,j,iGrN))*normN(j) enddo; enddo enddo - pmatrix(:,ipert) = p_resid/pPert_RGC + pmatrix(:,ipert) = p_resid/num%pPert enddo - + #ifdef DEBUG if (iand(debug_level(debug_homogenization), debug_levelExtensive) /= 0) then write(6,'(1x,a30)')'Jacobian matrix of penalty' @@ -515,15 +560,15 @@ module procedure mech_RGC_updateState flush(6) endif #endif - + !-------------------------------------------------------------------------------------------------- ! ... of the numerical viscosity traction "rmatrix" allocate(rmatrix(3*nIntFaceTot,3*nIntFaceTot),source=0.0_pReal) do i=1,3*nIntFaceTot - rmatrix(i,i) = viscModus_RGC*viscPower_RGC/(refRelaxRate_RGC*dt)* & ! tangent due to numerical viscosity traction appears - (abs(drelax(i))/(refRelaxRate_RGC*dt))**(viscPower_RGC - 1.0_pReal) ! only in the main diagonal term + rmatrix(i,i) = num%viscModus*num%viscPower/(num%refRelaxRate*dt)* & ! tangent due to numerical viscosity traction appears + (abs(drelax(i))/(num%refRelaxRate*dt))**(num%viscPower - 1.0_pReal) ! only in the main diagonal term enddo - + #ifdef DEBUG if (iand(debug_level(debug_homogenization), debug_levelExtensive) /= 0) then write(6,'(1x,a30)')'Jacobian matrix of penalty' @@ -554,7 +599,7 @@ module procedure mech_RGC_updateState ! computing the update of the state variable (relaxation vectors) using the Jacobian matrix allocate(jnverse(3*nIntFaceTot,3*nIntFaceTot),source=0.0_pReal) call math_invert(jnverse,error,jmatrix) - + #ifdef DEBUG if (iand(debug_level(debug_homogenization), debug_levelExtensive) /= 0) then write(6,'(1x,a30)')'Jacobian inverse' @@ -573,7 +618,7 @@ module procedure mech_RGC_updateState drelax(i) = drelax(i) - jnverse(i,j)*resid(j) ! Calculate the correction for the state variable enddo; enddo stt%relaxationVector(:,of) = relax + drelax ! Updateing the state variable for the next iteration - if (any(abs(drelax) > maxdRelax_RGC)) then ! Forcing cutback when the incremental change of relaxation vector becomes too large + if (any(abs(drelax) > num%maxdRelax)) then ! Forcing cutback when the incremental change of relaxation vector becomes too large mech_RGC_updateState = [.true.,.false.] !$OMP CRITICAL (write2out) write(6,'(1x,a,1x,i3,1x,a,1x,i3,1x,a)')'RGC_updateState: ip',ip,'| el',el,'enforces cutback' @@ -603,11 +648,11 @@ module procedure mech_RGC_updateState real(pReal), dimension (:,:,:), intent(out) :: rPen !< stress-like penalty real(pReal), dimension (:,:), intent(out) :: nMis !< total amount of mismatch - + real(pReal), dimension (:,:,:), intent(in) :: fDef !< deformation gradients real(pReal), dimension (3,3), intent(in) :: avgF !< initial effective stretch tensor integer, intent(in) :: ip,el,instance,of - + integer, dimension (4) :: intFace integer, dimension (3) :: iGrain3,iGNghb3,nGDim real(pReal), dimension (3,3) :: gDef,nDef @@ -623,13 +668,13 @@ module procedure mech_RGC_updateState nGDim = param(instance)%Nconstituents rPen = 0.0_pReal nMis = 0.0_pReal - + !---------------------------------------------------------------------------------------------- - ! get the correction factor the modulus of penalty stress representing the evolution of area of + ! get the correction factor the modulus of penalty stress representing the evolution of area of ! the interfaces due to deformations surfCorr = surfaceCorrection(avgF,instance,of) - + associate(prm => param(instance)) #ifdef DEBUG @@ -640,15 +685,15 @@ module procedure mech_RGC_updateState write(6,*) surfCorr endif #endif - + !----------------------------------------------------------------------------------------------- - ! computing the mismatch and penalty stress tensor of all grains + ! computing the mismatch and penalty stress tensor of all grains grainLoop: do iGrain = 1,product(prm%Nconstituents) Gmoduli = equivalentModuli(iGrain,ip,el) muGrain = Gmoduli(1) ! collecting the equivalent shear modulus of grain bgGrain = Gmoduli(2) ! and the lengthh of Burgers vector iGrain3 = grain1to3(iGrain,prm%Nconstituents) ! get the grain ID in local 3-dimensional index (x,y,z)-position - + interfaceLoop: do iFace = 1,6 intFace = getInterface(iFace,iGrain3) ! get the 4-dimensional index of the interface in local numbering system of the grain nVect = interfaceNormal(intFace,instance,of) @@ -662,7 +707,7 @@ module procedure mech_RGC_updateState muGNghb = Gmoduli(1) bgGNghb = Gmoduli(2) gDef = 0.5_pReal*(fDef(1:3,1:3,iGNghb) - fDef(1:3,1:3,iGrain)) ! difference/jump in deformation gradeint across the neighbor - + !------------------------------------------------------------------------------------------- ! compute the mismatch tensor of all interfaces nDefNorm = 0.0_pReal @@ -690,7 +735,7 @@ module procedure mech_RGC_updateState *surfCorr(abs(intFace(1)))/prm%dAlpha(abs(intFace(1))) & *cosh(prm%ciAlpha*nDefNorm) & *0.5_pReal*nVect(l)*nDef(i,k)/nDefNorm*math_LeviCivita(k,l,j) & - *tanh(nDefNorm/xSmoo_RGC) + *tanh(nDefNorm/num%xSmoo) enddo; enddo;enddo; enddo enddo interfaceLoop #ifdef DEBUG @@ -699,32 +744,32 @@ module procedure mech_RGC_updateState write(6,*) transpose(rPen(1:3,1:3,iGrain)) endif #endif - + enddo grainLoop - + end associate - + end subroutine stressPenalty - - + + !------------------------------------------------------------------------------------------------ - !> @brief calculate stress-like penalty due to volume discrepancy + !> @brief calculate stress-like penalty due to volume discrepancy !------------------------------------------------------------------------------------------------ subroutine volumePenalty(vPen,vDiscrep,fAvg,fDef,nGrain,instance,of) - + real(pReal), dimension (:,:,:), intent(out) :: vPen ! stress-like penalty due to volume real(pReal), intent(out) :: vDiscrep ! total volume discrepancy - + real(pReal), dimension (:,:,:), intent(in) :: fDef ! deformation gradients real(pReal), dimension (3,3), intent(in) :: fAvg ! overall deformation gradient integer, intent(in) :: & Ngrain, & instance, & of - + real(pReal), dimension(size(vPen,3)) :: gVol integer :: i - + !---------------------------------------------------------------------------------------------- ! compute the volumes of grains and of cluster vDiscrep = math_det33(fAvg) ! compute the volume of the cluster @@ -733,15 +778,15 @@ module procedure mech_RGC_updateState vDiscrep = vDiscrep - gVol(i)/real(nGrain,pReal) ! calculate the difference/dicrepancy between ! the volume of the cluster and the the total volume of grains enddo - + !---------------------------------------------------------------------------------------------- ! calculate the stress and penalty due to volume discrepancy vPen = 0.0_pReal do i = 1,nGrain - vPen(:,:,i) = -1.0_pReal/real(nGrain,pReal)*volDiscrMod_RGC*volDiscrPow_RGC/maxVolDiscr_RGC* & - sign((abs(vDiscrep)/maxVolDiscr_RGC)**(volDiscrPow_RGC - 1.0),vDiscrep)* & + vPen(:,:,i) = -1.0_pReal/real(nGrain,pReal)*num%volDiscrMod*num%volDiscrPow/num%maxVolDiscr* & + sign((abs(vDiscrep)/num%maxVolDiscr)**(num%volDiscrPow - 1.0),vDiscrep)* & gVol(i)*transpose(math_inv33(fDef(:,:,i))) - + #ifdef DEBUG if (iand(debug_level(debug_homogenization),debug_levelExtensive) /= 0 & .and. param(instance)%of_debug == of) then @@ -755,11 +800,11 @@ module procedure mech_RGC_updateState !-------------------------------------------------------------------------------------------------- - !> @brief compute the correction factor accouted for surface evolution (area change) due to + !> @brief compute the correction factor accouted for surface evolution (area change) due to ! deformation !-------------------------------------------------------------------------------------------------- function surfaceCorrection(avgF,instance,of) - + real(pReal), dimension(3) :: surfaceCorrection real(pReal), dimension(3,3), intent(in) :: avgF !< average F @@ -771,9 +816,9 @@ module procedure mech_RGC_updateState real(pReal) :: detF integer :: i,j,iBase logical :: error - + call math_invert33(invC,detF,error,matmul(transpose(avgF),avgF)) - + surfaceCorrection = 0.0_pReal do iBase = 1,3 nVect = interfaceNormal([iBase,1,1,1],instance,of) @@ -782,7 +827,7 @@ module procedure mech_RGC_updateState enddo; enddo surfaceCorrection(iBase) = sqrt(surfaceCorrection(iBase))*detF ! get the surface correction factor (area contraction/enlargement) enddo - + end function surfaceCorrection @@ -790,9 +835,9 @@ module procedure mech_RGC_updateState !> @brief compute the equivalent shear and bulk moduli from the elasticity tensor !-------------------------------------------------------------------------------------------------- function equivalentModuli(grainID,ip,el) - + real(pReal), dimension(2) :: equivalentModuli - + integer, intent(in) :: & grainID,& ip, & !< integration point number @@ -802,9 +847,9 @@ module procedure mech_RGC_updateState cEquiv_11, & cEquiv_12, & cEquiv_44 - + elasTens = constitutive_homogenizedC(grainID,ip,el) - + !---------------------------------------------------------------------------------------------- ! compute the equivalent shear modulus after Turterltaub and Suiker, JMPS (2005) cEquiv_11 = (elasTens(1,1) + elasTens(2,2) + elasTens(3,3))/3.0_pReal @@ -812,37 +857,37 @@ module procedure mech_RGC_updateState elasTens(1,3) + elasTens(2,1) + elasTens(3,2))/6.0_pReal cEquiv_44 = (elasTens(4,4) + elasTens(5,5) + elasTens(6,6))/3.0_pReal equivalentModuli(1) = 0.2_pReal*(cEquiv_11 - cEquiv_12) + 0.6_pReal*cEquiv_44 - + !---------------------------------------------------------------------------------------------- ! obtain the length of Burgers vector (could be model dependend) equivalentModuli(2) = 2.5e-10_pReal - + end function equivalentModuli - - + + !-------------------------------------------------------------------------------------------------- - !> @brief calculating the grain deformation gradient (the same with + !> @brief calculating the grain deformation gradient (the same with ! homogenization_RGC_partitionDeformation, but used only for perturbation scheme) !-------------------------------------------------------------------------------------------------- subroutine grainDeformation(F, avgF, instance, of) - + real(pReal), dimension(:,:,:), intent(out) :: F !< partioned F per grain - + real(pReal), dimension(:,:), intent(in) :: avgF !< averaged F integer, intent(in) :: & instance, & of - + real(pReal), dimension(3) :: aVect,nVect integer, dimension(4) :: intFace integer, dimension(3) :: iGrain3 integer :: iGrain,iFace,i,j - + !------------------------------------------------------------------------------------------------- ! compute the deformation gradient of individual grains due to relaxations - + associate(prm => param(instance)) - + F = 0.0_pReal do iGrain = 1,product(prm%Nconstituents) iGrain3 = grain1to3(iGrain,prm%Nconstituents) @@ -855,16 +900,16 @@ module procedure mech_RGC_updateState enddo F(1:3,1:3,iGrain) = F(1:3,1:3,iGrain) + avgF ! relaxed deformation gradient enddo - + end associate - + end subroutine grainDeformation - + end procedure mech_RGC_updateState !-------------------------------------------------------------------------------------------------- -!> @brief derive average stress and stiffness from constituent quantities +!> @brief derive average stress and stiffness from constituent quantities !-------------------------------------------------------------------------------------------------- module subroutine mech_RGC_averageStressAndItsTangent(avgP,dAvgPdAvgF,P,dPdF,instance) @@ -888,9 +933,9 @@ module subroutine mech_RGC_results(instance,group) integer, intent(in) :: instance character(len=*), intent(in) :: group - + integer :: o - + associate(stt => state(instance), dst => dependentState(instance), prm => param(instance)) outputsLoop: do o = 1,size(prm%output) select case(trim(prm%output(o))) @@ -915,7 +960,7 @@ module subroutine mech_RGC_results(instance,group) end select enddo outputsLoop end associate - + end subroutine mech_RGC_results @@ -928,7 +973,7 @@ pure function relaxationVector(intFace,instance,of) integer, intent(in) :: instance,of integer, dimension(4), intent(in) :: intFace !< set of interface ID in 4D array (normal and position) - + integer :: iNum !-------------------------------------------------------------------------------------------------- @@ -945,10 +990,10 @@ end function relaxationVector !-------------------------------------------------------------------------------------------------- -!> @brief identify the normal of an interface +!> @brief identify the normal of an interface !-------------------------------------------------------------------------------------------------- pure function interfaceNormal(intFace,instance,of) - + real(pReal), dimension(3) :: interfaceNormal integer, dimension(4), intent(in) :: intFace !< interface ID in 4D array (normal and position) @@ -980,10 +1025,10 @@ pure function getInterface(iFace,iGrain3) integer, intent(in) :: iFace !< face index (1..6) mapped like (-e1,-e2,-e3,+e1,+e2,+e3) or iDir = (-1,-2,-3,1,2,3) integer :: iDir !< direction of interface normal - + iDir = (int(real(iFace-1,pReal)/2.0_pReal)+1)*(-1)**iFace getInterface(1) = iDir - + !-------------------------------------------------------------------------------------------------- ! identify the interface position by the direction of its normal getInterface(2:4) = iGrain3 @@ -996,7 +1041,7 @@ end function getInterface !> @brief map grain ID from in 1D (global array) to in 3D (local position) !-------------------------------------------------------------------------------------------------- pure function grain1to3(grain1,nGDim) - + integer, dimension(3) :: grain1to3 integer, intent(in) :: grain1 !< grain ID in 1D array @@ -1016,7 +1061,7 @@ integer pure function grain3to1(grain3,nGDim) integer, dimension(3), intent(in) :: grain3 !< grain ID in 3D array (pos.x,pos.y,pos.z) integer, dimension(3), intent(in) :: nGDim - + grain3to1 = grain3(1) & + nGDim(1)*(grain3(2)-1) & + nGDim(1)*nGDim(2)*(grain3(3)-1) @@ -1028,11 +1073,11 @@ end function grain3to1 !> @brief maps interface ID from 4D (normal and local position) into 1D (global array) !-------------------------------------------------------------------------------------------------- integer pure function interface4to1(iFace4D, nGDim) - + integer, dimension(4), intent(in) :: iFace4D !< interface ID in 4D array (n.dir,pos.x,pos.y,pos.z) integer, dimension(3), intent(in) :: nGDim - + select case(abs(iFace4D(1))) case(1) @@ -1064,7 +1109,7 @@ integer pure function interface4to1(iFace4D, nGDim) case default interface4to1 = -1 - + end select end function interface4to1 @@ -1074,7 +1119,7 @@ end function interface4to1 !> @brief maps interface ID from 1D (global array) into 4D (normal and local position) !-------------------------------------------------------------------------------------------------- pure function interface1to4(iFace1D, nGDim) - + integer, dimension(4) :: interface1to4 integer, intent(in) :: iFace1D !< interface ID in 1D array diff --git a/src/homogenization_mech_isostrain.f90 b/src/homogenization_mech_isostrain.f90 index 9345d1eda..9b81ab666 100644 --- a/src/homogenization_mech_isostrain.f90 +++ b/src/homogenization_mech_isostrain.f90 @@ -6,10 +6,9 @@ !-------------------------------------------------------------------------------------------------- submodule(homogenization) homogenization_mech_isostrain - enum, bind(c) - enumerator :: & - parallel_ID, & - average_ID + enum, bind(c); enumerator :: & + parallel_ID, & + average_ID end enum type :: tParameters !< container type for internal constitutive parameters @@ -36,7 +35,7 @@ module subroutine mech_isostrain_init character(len=pStringLen) :: & tag = '' - write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_ISOSTRAIN_label//' init -+>>>' + write(6,'(/,a)') ' <<<+- homogenization_'//HOMOGENIZATION_ISOSTRAIN_LABEL//' init -+>>>' Ninstance = count(homogenization_type == HOMOGENIZATION_ISOSTRAIN_ID) if (iand(debug_level(debug_HOMOGENIZATION),debug_levelBasic) /= 0) & @@ -58,7 +57,7 @@ module subroutine mech_isostrain_init case ('avg') prm%mapping = average_ID case default - call IO_error(211,ext_msg=trim(tag)//' ('//HOMOGENIZATION_isostrain_label//')') + call IO_error(211,ext_msg=trim(tag)//' ('//HOMOGENIZATION_ISOSTRAIN_LABEL//')') end select NofMyHomog = count(material_homogenizationAt == h) diff --git a/src/kinematics_cleavage_opening.f90 b/src/kinematics_cleavage_opening.f90 index a5f5dfae2..3366a7b1e 100644 --- a/src/kinematics_cleavage_opening.f90 +++ b/src/kinematics_cleavage_opening.f90 @@ -20,9 +20,7 @@ module kinematics_cleavage_opening type :: tParameters !< container type for internal constitutive parameters integer :: & - totalNcleavage - integer, dimension(:), allocatable :: & - Ncleavage !< active number of cleavage systems per family + sum_N_cl real(pReal) :: & sdot0, & n @@ -48,11 +46,12 @@ contains subroutine kinematics_cleavage_opening_init integer :: Ninstance,p + integer, dimension(:), allocatable :: N_cl !< active number of cleavage systems per family character(len=pStringLen) :: extmsg = '' - write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_cleavage_opening_LABEL//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_CLEAVAGE_OPENING_LABEL//' init -+>>>'; flush(6) - Ninstance = count(phase_kinematics == KINEMATICS_cleavage_opening_ID) + Ninstance = count(phase_kinematics == KINEMATICS_CLEAVAGE_OPENING_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance @@ -60,25 +59,25 @@ subroutine kinematics_cleavage_opening_init allocate(param(Ninstance)) do p = 1, size(config_phase) - kinematics_cleavage_opening_instance(p) = count(phase_kinematics(:,1:p) == kinematics_cleavage_opening_ID) - if (all(phase_kinematics(:,p) /= KINEMATICS_cleavage_opening_ID)) cycle + kinematics_cleavage_opening_instance(p) = count(phase_kinematics(:,1:p) == KINEMATICS_CLEAVAGE_OPENING_ID) + if (all(phase_kinematics(:,p) /= KINEMATICS_CLEAVAGE_OPENING_ID)) cycle associate(prm => param(kinematics_cleavage_opening_instance(p)), & config => config_phase(p)) - prm%Ncleavage = config%getInts('ncleavage') - prm%totalNcleavage = sum(prm%Ncleavage) + N_cl = config%getInts('ncleavage') + prm%sum_N_cl = sum(abs(N_cl)) prm%n = config%getFloat('anisobrittle_ratesensitivity') prm%sdot0 = config%getFloat('anisobrittle_sdot0') - prm%critLoad = config%getFloats('anisobrittle_criticalload',requiredSize=size(prm%Ncleavage)) + prm%critLoad = config%getFloats('anisobrittle_criticalload',requiredSize=size(N_cl)) - prm%cleavage_systems = lattice_SchmidMatrix_cleavage(prm%Ncleavage,config%getString('lattice_structure'),& + prm%cleavage_systems = lattice_SchmidMatrix_cleavage(N_cl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) ! expand: family => system - prm%critLoad = math_expand(prm%critLoad, prm%Ncleavage) + prm%critLoad = math_expand(prm%critLoad,N_cl) ! sanity checks if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' anisobrittle_n' @@ -87,7 +86,7 @@ subroutine kinematics_cleavage_opening_init !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range - if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ANISOBRITTLE_LABEL//')') + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//KINEMATICS_CLEAVAGE_OPENING_LABEL//')') end associate enddo @@ -124,10 +123,10 @@ subroutine kinematics_cleavage_opening_LiAndItsTangent(Ld, dLd_dTstar, S, ipc, i Ld = 0.0_pReal dLd_dTstar = 0.0_pReal associate(prm => param(kinematics_cleavage_opening_instance(material_phaseAt(ipc,el)))) - do i = 1,prm%totalNcleavage + do i = 1,prm%sum_N_cl traction_crit = prm%critLoad(i)* damage(homog)%p(damageOffset)**2.0_pReal - traction_d = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,1,i)) + traction_d = math_tensordot(S,prm%cleavage_systems(1:3,1:3,1,i)) if (abs(traction_d) > traction_crit + tol_math_check) then udotd = sign(1.0_pReal,traction_d)* prm%sdot0 * ((abs(traction_d) - traction_crit)/traction_crit)**prm%n Ld = Ld + udotd*prm%cleavage_systems(1:3,1:3,1,i) @@ -137,7 +136,7 @@ subroutine kinematics_cleavage_opening_LiAndItsTangent(Ld, dLd_dTstar, S, ipc, i + dudotd_dt*prm%cleavage_systems(k,l,1,i) * prm%cleavage_systems(m,n,1,i) endif - traction_t = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,2,i)) + traction_t = math_tensordot(S,prm%cleavage_systems(1:3,1:3,2,i)) if (abs(traction_t) > traction_crit + tol_math_check) then udott = sign(1.0_pReal,traction_t)* prm%sdot0 * ((abs(traction_t) - traction_crit)/traction_crit)**prm%n Ld = Ld + udott*prm%cleavage_systems(1:3,1:3,2,i) @@ -147,7 +146,7 @@ subroutine kinematics_cleavage_opening_LiAndItsTangent(Ld, dLd_dTstar, S, ipc, i + dudott_dt*prm%cleavage_systems(k,l,2,i) * prm%cleavage_systems(m,n,2,i) endif - traction_n = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,3,i)) + traction_n = math_tensordot(S,prm%cleavage_systems(1:3,1:3,3,i)) if (abs(traction_n) > traction_crit + tol_math_check) then udotn = sign(1.0_pReal,traction_n)* prm%sdot0 * ((abs(traction_n) - traction_crit)/traction_crit)**prm%n Ld = Ld + udotn*prm%cleavage_systems(1:3,1:3,3,i) diff --git a/src/kinematics_slipplane_opening.f90 b/src/kinematics_slipplane_opening.f90 index ab9035918..833fa8759 100644 --- a/src/kinematics_slipplane_opening.f90 +++ b/src/kinematics_slipplane_opening.f90 @@ -20,9 +20,7 @@ module kinematics_slipplane_opening type :: tParameters !< container type for internal constitutive parameters integer :: & - totalNslip - integer, dimension(:), allocatable :: & - Nslip !< active number of slip systems per family + sum_N_sl real(pReal) :: & sdot0, & n @@ -51,11 +49,12 @@ subroutine kinematics_slipplane_opening_init integer :: Ninstance,p,i character(len=pStringLen) :: extmsg = '' + integer, dimension(:), allocatable :: N_sl real(pReal), dimension(:,:), allocatable :: d,n,t - write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_slipplane_opening_LABEL//' init -+>>>'; flush(6) + write(6,'(/,a)') ' <<<+- kinematics_'//KINEMATICS_SLIPPLANE_OPENING_LABEL//' init -+>>>'; flush(6) - Ninstance = count(phase_kinematics == KINEMATICS_slipplane_opening_ID) + Ninstance = count(phase_kinematics == KINEMATICS_SLIPPLANE_OPENING_ID) if (iand(debug_level(debug_constitutive),debug_levelBasic) /= 0) & write(6,'(a16,1x,i5,/)') '# instances:',Ninstance @@ -63,21 +62,21 @@ subroutine kinematics_slipplane_opening_init allocate(param(Ninstance)) do p = 1, size(config_phase) - kinematics_slipplane_opening_instance(p) = count(phase_kinematics(:,1:p) == kinematics_slipplane_opening_ID) - if (all(phase_kinematics(:,p) /= KINEMATICS_slipplane_opening_ID)) cycle + kinematics_slipplane_opening_instance(p) = count(phase_kinematics(:,1:p) == KINEMATICS_SLIPPLANE_OPENING_ID) + if (all(phase_kinematics(:,p) /= KINEMATICS_SLIPPLANE_OPENING_ID)) cycle associate(prm => param(kinematics_slipplane_opening_instance(p)), & config => config_phase(p)) prm%sdot0 = config%getFloat('anisoductile_sdot0') prm%n = config%getFloat('anisoductile_ratesensitivity') - prm%Nslip = config%getInts('nslip') - prm%totalNslip = sum(prm%Nslip) + N_sl = config%getInts('nslip') + prm%sum_N_sl = sum(abs(N_sl)) - d = lattice_slip_direction (prm%Nslip,config%getString('lattice_structure'),& + d = lattice_slip_direction (N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - t = lattice_slip_transverse(prm%Nslip,config%getString('lattice_structure'),& + t = lattice_slip_transverse(N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) - n = lattice_slip_normal (prm%Nslip,config%getString('lattice_structure'),& + n = lattice_slip_normal (N_sl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) allocate(prm%P_d(3,3,size(d,2)),prm%P_t(3,3,size(t,2)),prm%P_n(3,3,size(n,2))) @@ -87,10 +86,10 @@ subroutine kinematics_slipplane_opening_init prm%P_n(1:3,1:3,i) = math_outer(n(1:3,i), n(1:3,i)) enddo - prm%critLoad = config%getFloats('anisoductile_criticalload',requiredSize=size(prm%Nslip)) + prm%critLoad = config%getFloats('anisoductile_criticalload',requiredSize=size(N_sl)) ! expand: family => system - prm%critLoad = math_expand(prm%critLoad, prm%Nslip) + prm%critLoad = math_expand(prm%critLoad,N_sl) ! sanity checks if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' anisoDuctile_n' @@ -99,7 +98,7 @@ subroutine kinematics_slipplane_opening_init !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range - if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ANISODUCTILE_LABEL//')') + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//KINEMATICS_SLIPPLANE_OPENING_LABEL//')') end associate enddo @@ -139,7 +138,7 @@ subroutine kinematics_slipplane_opening_LiAndItsTangent(Ld, dLd_dTstar, S, ipc, associate(prm => param(instance)) Ld = 0.0_pReal dLd_dTstar = 0.0_pReal - do i = 1, prm%totalNslip + do i = 1, prm%sum_N_sl traction_d = math_tensordot(S,prm%P_d(1:3,1:3,i)) traction_t = math_tensordot(S,prm%P_t(1:3,1:3,i)) diff --git a/src/lattice.f90 b/src/lattice.f90 index 3f5ceddb7..31a73d7d6 100644 --- a/src/lattice.f90 +++ b/src/lattice.f90 @@ -381,14 +381,14 @@ module lattice ],pReal),shape(ORT_SYSTEMCLEAVAGE)) - enum, bind(c) - enumerator :: lattice_UNDEFINED_ID, & - lattice_ISO_ID, & - lattice_FCC_ID, & - lattice_BCC_ID, & - lattice_BCT_ID, & - lattice_HEX_ID, & - lattice_ORT_ID + enum, bind(c); enumerator :: & + lattice_UNDEFINED_ID, & + lattice_ISO_ID, & + lattice_FCC_ID, & + lattice_BCC_ID, & + lattice_BCT_ID, & + lattice_HEX_ID, & + lattice_ORT_ID end enum ! SHOULD NOT BE PART OF LATTICE BEGIN @@ -502,15 +502,10 @@ subroutine lattice_init lattice_C66(1:6,1:6,p) = applyLatticeSymmetryC66(lattice_C66(1:6,1:6,p),structure) - ! (C11iso-C12iso)/2 with C11iso=(3*C11+2*C12+4*C44)/5 and C12iso=(C11+4*C12-2*C44)/5 - lattice_mu(p) = 0.2_pReal *(lattice_C66(1,1,p) -lattice_C66(1,2,p) +3.0_pReal*lattice_C66(4,4,p)) - - ! C12iso/(C11iso+C12iso) with C11iso=(3*C11+2*C12+4*C44)/5 and C12iso=(C11+4*C12-2*C44)/5 - lattice_nu(p) = ( lattice_C66(1,1,p) +4.0_pReal*lattice_C66(1,2,p) -2.0_pReal*lattice_C66(4,4,p)) & - / (4.0_pReal*lattice_C66(1,1,p) +6.0_pReal*lattice_C66(1,2,p) +2.0_pReal*lattice_C66(4,4,p)) + lattice_mu(p) = equivalent_mu(lattice_C66(1:6,1:6,p),'voigt') + lattice_nu(p) = equivalent_nu(lattice_C66(1:6,1:6,p),'voigt') lattice_C66(1:6,1:6,p) = math_sym3333to66(math_Voigt66to3333(lattice_C66(1:6,1:6,p))) ! Literature data is in Voigt notation - do i = 1, 6 if (abs(lattice_C66(i,i,p)) @brief Populates reduced interaction matrix +!> @brief Populate reduced interaction matrix !-------------------------------------------------------------------------------------------------- function buildInteraction(reacting_used,acting_used,reacting_max,acting_max,values,matrix) @@ -1979,7 +1976,7 @@ end function buildInteraction !-------------------------------------------------------------------------------------------------- -!> @brief build a local coordinate system on slip, twin, trans, cleavage systems +!> @brief Build a local coordinate system on slip, twin, trans, cleavage systems !> @details Order: Direction, plane (normal), and common perpendicular !-------------------------------------------------------------------------------------------------- function buildCoordinateSystem(active,potential,system,structure,cOverA) @@ -1994,7 +1991,7 @@ function buildCoordinateSystem(active,potential,system,structure,cOverA) real(pReal), intent(in) :: & cOverA real(pReal), dimension(3,3,sum(active)) :: & - buildCoordinateSystem + buildCoordinateSystem real(pReal), dimension(3) :: & direction, normal @@ -2207,7 +2204,7 @@ function getlabels(active,potential,system) result(labels) i = 1 label(i:i) = '[' direction: do j = 1, size(system,1)/2 - write(label(i+1:i+2),"(I2.1)") int(system(j,p)) + write(label(i+1:i+2),'(I2.1)') int(system(j,p)) label(i+3:i+3) = ' ' i = i + 3 enddo direction @@ -2216,7 +2213,7 @@ function getlabels(active,potential,system) result(labels) i = i +1 label(i:i) = '(' normal: do j = size(system,1)/2+1, size(system,1) - write(label(i+1:i+2),"(I2.1)") int(system(j,p)) + write(label(i+1:i+2),'(I2.1)') int(system(j,p)) label(i+3:i+3) = ' ' i = i + 3 enddo normal @@ -2230,4 +2227,100 @@ function getlabels(active,potential,system) result(labels) end function getlabels +!-------------------------------------------------------------------------------------------------- +!> @brief Equivalent Poisson's ratio (ν) +!> @details https://doi.org/10.1143/JPSJ.20.635 +!-------------------------------------------------------------------------------------------------- +function equivalent_nu(C,assumption) result(nu) + + real(pReal), dimension(6,6), intent(in) :: C !< Stiffness tensor (Voigt notation) + character(len=*), intent(in) :: assumption !< Assumption ('Voigt' = isostrain, 'Reuss' = isostress) + + real(pReal) :: K, mu, nu + logical :: error + real(pReal), dimension(6,6) :: S + + if (IO_lc(assumption) == 'voigt') then + K = (C(1,1)+C(2,2)+C(3,3) +2.0_pReal*(C(1,2)+C(2,3)+C(1,3))) & + / 9.0_pReal + elseif(IO_lc(assumption) == 'reuss') then + call math_invert(S,error,C) + if(error) call IO_error(0) + K = 1.0_pReal & + / (S(1,1)+S(2,2)+S(3,3) +2.0_pReal*(S(1,2)+S(2,3)+S(1,3))) + else + call IO_error(0) + K = 0.0_pReal + endif + + mu = equivalent_mu(C,assumption) + nu = (1.5_pReal*K -mu)/(3.0_pReal*K+mu) + +end function equivalent_nu + + +!-------------------------------------------------------------------------------------------------- +!> @brief Equivalent shear modulus (μ) +!> @details https://doi.org/10.1143/JPSJ.20.635 +!-------------------------------------------------------------------------------------------------- +function equivalent_mu(C,assumption) result(mu) + + real(pReal), dimension(6,6), intent(in) :: C !< Stiffness tensor (Voigt notation) + character(len=*), intent(in) :: assumption !< Assumption ('Voigt' = isostrain, 'Reuss' = isostress) + + real(pReal) :: mu + logical :: error + real(pReal), dimension(6,6) :: S + + if (IO_lc(assumption) == 'voigt') then + mu = (1.0_pReal*(C(1,1)+C(2,2)+C(3,3)) -1.0_pReal*(C(1,2)+C(2,3)+C(1,3)) +3.0_pReal*(C(4,4)+C(5,5)+C(6,6))) & + / 15.0_pReal + elseif(IO_lc(assumption) == 'reuss') then + call math_invert(S,error,C) + if(error) call IO_error(0) + mu = 15.0_pReal & + / (4.0_pReal*(S(1,1)+S(2,2)+S(3,3)) -4.0_pReal*(S(1,2)+S(2,3)+S(1,3)) +3.0_pReal*(S(4,4)+S(5,5)+S(6,6))) + else + call IO_error(0) + mu = 0.0_pReal + endif + +end function equivalent_mu + + +!-------------------------------------------------------------------------------------------------- +!> @brief check correctness of some lattice functions +!-------------------------------------------------------------------------------------------------- +subroutine unitTest + + real(pReal), dimension(:,:,:), allocatable :: CoSy + real(pReal), dimension(:,:), allocatable :: system + + real(pReal), dimension(6,6) :: C + real(pReal), dimension(2) :: r + real(pReal) :: lambda + + call random_number(r) + + system = reshape([1.0_pReal+r(1),0.0_pReal,0.0_pReal, 0.0_pReal,1.0_pReal+r(2),0.0_pReal],[6,1]) + CoSy = buildCoordinateSystem([1],[1],system,'fcc',0.0_pReal) + + if(any(dNeq(CoSy(1:3,1:3,1),math_I3))) & + call IO_error(0) + + call random_number(C) + C(1,1) = C(1,1) + 1.0_pReal + C = applyLatticeSymmetryC66(C,'iso') + if(dNeq(C(6,6),equivalent_mu(C,'voigt'),1.0e-12_pReal)) & + call IO_error(0,ext_msg='equivalent_mu/voigt') + if(dNeq(C(6,6),equivalent_mu(C,'voigt'),1.0e-12_pReal)) & + call IO_error(0,ext_msg='equivalent_mu/reuss') + lambda = C(1,2) + if(dNeq(lambda*0.5_pReal/(lambda+equivalent_mu(C,'voigt')),equivalent_nu(C,'voigt'),1.0e-12_pReal)) & + call IO_error(0,ext_msg='equivalent_nu/voigt') + if(dNeq(lambda*0.5_pReal/(lambda+equivalent_mu(C,'reuss')),equivalent_nu(C,'reuss'),1.0e-12_pReal)) & + call IO_error(0,ext_msg='equivalent_nu/reuss') + +end subroutine unitTest + end module lattice diff --git a/src/mesh_marc.f90 b/src/marc/discretization_marc.f90 similarity index 99% rename from src/mesh_marc.f90 rename to src/marc/discretization_marc.f90 index 42185e9d6..0221ad693 100644 --- a/src/mesh_marc.f90 +++ b/src/marc/discretization_marc.f90 @@ -5,7 +5,7 @@ !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @brief Sets up the mesh for the solver MSC.Marc !-------------------------------------------------------------------------------------------------- -module mesh +module discretization_marc use IO use prec use math @@ -37,7 +37,7 @@ module mesh mesh_FEM2DAMASK_node !< DAMASK node ID for Marc node ID public :: & - mesh_init + discretization_marc_init contains @@ -45,7 +45,7 @@ contains !> @brief initializes the mesh by calling all necessary private routines the mesh module !! Order and routines strongly depend on type of solver !-------------------------------------------------------------------------------------------------- -subroutine mesh_init(ip,el) +subroutine discretization_marc_init(ip,el) integer, intent(in) :: el, ip @@ -114,7 +114,7 @@ subroutine mesh_init(ip,el) call geometry_plastic_nonlocal_setIPareaNormal(unscaledNormals/spread(norm2(unscaledNormals,1),1,3)) call geometry_plastic_nonlocal_results -end subroutine mesh_init +end subroutine discretization_marc_init !-------------------------------------------------------------------------------------------------- @@ -1118,4 +1118,4 @@ logical function containsRange(str,chunkPos) end function containsRange -end module mesh +end module discretization_marc diff --git a/src/MarcInclude/concom2018 b/src/marc/include/concom2018 similarity index 100% rename from src/MarcInclude/concom2018 rename to src/marc/include/concom2018 diff --git a/src/MarcInclude/concom2018.1 b/src/marc/include/concom2018.1 similarity index 100% rename from src/MarcInclude/concom2018.1 rename to src/marc/include/concom2018.1 diff --git a/src/MarcInclude/concom2019 b/src/marc/include/concom2019 similarity index 100% rename from src/MarcInclude/concom2019 rename to src/marc/include/concom2019 diff --git a/src/MarcInclude/creeps2018 b/src/marc/include/creeps2018 similarity index 100% rename from src/MarcInclude/creeps2018 rename to src/marc/include/creeps2018 diff --git a/src/MarcInclude/creeps2018.1 b/src/marc/include/creeps2018.1 similarity index 100% rename from src/MarcInclude/creeps2018.1 rename to src/marc/include/creeps2018.1 diff --git a/src/MarcInclude/creeps2019 b/src/marc/include/creeps2019 similarity index 100% rename from src/MarcInclude/creeps2019 rename to src/marc/include/creeps2019 diff --git a/src/material.f90 b/src/material.f90 index 9c5009484..14a16a2ed 100644 --- a/src/material.f90 +++ b/src/material.f90 @@ -17,7 +17,7 @@ module material implicit none private - + character(len=*), parameter, public :: & ELASTICITY_hooke_label = 'hooke', & PLASTICITY_none_label = 'none', & @@ -46,45 +46,43 @@ module material HOMOGENIZATION_none_label = 'none', & HOMOGENIZATION_isostrain_label = 'isostrain', & HOMOGENIZATION_rgc_label = 'rgc' - - - - enum, bind(c) - enumerator :: ELASTICITY_undefined_ID, & - ELASTICITY_hooke_ID, & - PLASTICITY_undefined_ID, & - PLASTICITY_none_ID, & - PLASTICITY_isotropic_ID, & - PLASTICITY_phenopowerlaw_ID, & - PLASTICITY_kinehardening_ID, & - PLASTICITY_dislotwin_ID, & - PLASTICITY_disloucla_ID, & - PLASTICITY_nonlocal_ID, & - SOURCE_undefined_ID, & - SOURCE_thermal_dissipation_ID, & - SOURCE_thermal_externalheat_ID, & - SOURCE_damage_isoBrittle_ID, & - SOURCE_damage_isoDuctile_ID, & - SOURCE_damage_anisoBrittle_ID, & - SOURCE_damage_anisoDuctile_ID, & - KINEMATICS_undefined_ID, & - KINEMATICS_cleavage_opening_ID, & - KINEMATICS_slipplane_opening_ID, & - KINEMATICS_thermal_expansion_ID, & - STIFFNESS_DEGRADATION_undefined_ID, & - STIFFNESS_DEGRADATION_damage_ID, & - THERMAL_isothermal_ID, & - THERMAL_adiabatic_ID, & - THERMAL_conduction_ID, & - DAMAGE_none_ID, & - DAMAGE_local_ID, & - DAMAGE_nonlocal_ID, & - HOMOGENIZATION_undefined_ID, & - HOMOGENIZATION_none_ID, & - HOMOGENIZATION_isostrain_ID, & - HOMOGENIZATION_rgc_ID + + enum, bind(c); enumerator :: & + ELASTICITY_UNDEFINED_ID ,& + ELASTICITY_HOOKE_ID ,& + PLASTICITY_UNDEFINED_ID ,& + PLASTICITY_NONE_ID, & + PLASTICITY_ISOTROPIC_ID, & + PLASTICITY_PHENOPOWERLAW_ID, & + PLASTICITY_KINEHARDENING_ID, & + PLASTICITY_DISLOTWIN_ID, & + PLASTICITY_DISLOUCLA_ID, & + PLASTICITY_NONLOCAL_ID, & + SOURCE_UNDEFINED_ID ,& + SOURCE_THERMAL_DISSIPATION_ID, & + SOURCE_THERMAL_EXTERNALHEAT_ID, & + SOURCE_DAMAGE_ISOBRITTLE_ID, & + SOURCE_DAMAGE_ISODUCTILE_ID, & + SOURCE_DAMAGE_ANISOBRITTLE_ID, & + SOURCE_DAMAGE_ANISODUCTILE_ID, & + KINEMATICS_UNDEFINED_ID ,& + KINEMATICS_CLEAVAGE_OPENING_ID, & + KINEMATICS_SLIPPLANE_OPENING_ID, & + KINEMATICS_THERMAL_EXPANSION_ID, & + STIFFNESS_DEGRADATION_UNDEFINED_ID, & + STIFFNESS_DEGRADATION_DAMAGE_ID, & + THERMAL_ISOTHERMAL_ID, & + THERMAL_ADIABATIC_ID, & + THERMAL_CONDUCTION_ID, & + DAMAGE_NONE_ID, & + DAMAGE_LOCAL_ID, & + DAMAGE_NONLOCAL_ID, & + HOMOGENIZATION_UNDEFINED_ID, & + HOMOGENIZATION_NONE_ID, & + HOMOGENIZATION_ISOSTRAIN_ID, & + HOMOGENIZATION_RGC_ID end enum - + integer(kind(ELASTICITY_undefined_ID)), dimension(:), allocatable, public, protected :: & phase_elasticity !< elasticity of each phase integer(kind(PLASTICITY_undefined_ID)), dimension(:), allocatable, public, protected :: & @@ -95,19 +93,19 @@ module material damage_type !< nonlocal damage model integer(kind(HOMOGENIZATION_undefined_ID)), dimension(:), allocatable, public, protected :: & homogenization_type !< type of each homogenization - + integer, public, protected :: & material_Nphase, & !< number of phases material_Nhomogenization !< number of homogenizations - + integer(kind(SOURCE_undefined_ID)), dimension(:,:), allocatable, public, protected :: & phase_source, & !< active sources mechanisms of each phase phase_kinematics, & !< active kinematic mechanisms of each phase phase_stiffnessDegradation !< active stiffness degradation mechanisms of each phase - + integer, public, protected :: & homogenization_maxNgrains !< max number of grains in any USED homogenization - + integer, dimension(:), allocatable, public, protected :: & phase_Nsources, & !< number of source mechanisms active in each phase phase_Nkinematics, & !< number of kinematic mechanisms active in each phase @@ -118,12 +116,11 @@ module material homogenization_typeInstance, & !< instance of particular type of each homogenization thermal_typeInstance, & !< instance of particular type of each thermal transport damage_typeInstance !< instance of particular type of each nonlocal damage - + real(pReal), dimension(:), allocatable, public, protected :: & thermal_initialT, & !< initial temperature per each homogenization damage_initialPhi !< initial damage per each homogenization -! NEW MAPPINGS integer, dimension(:), allocatable, public, protected :: & ! (elem) material_homogenizationAt !< homogenization ID of each element (copy of discretization_homogenizationAt) integer, dimension(:,:), allocatable, public, target :: & ! (ip,elem) ToDo: ugly target for mapping hack @@ -132,7 +129,6 @@ module material material_phaseAt !< phase ID of each element integer, dimension(:,:,:), allocatable, public, protected :: & ! (constituent,elem) material_phaseMemberAt !< position of the element within its phase instance -! END NEW MAPPINGS type(tPlasticState), allocatable, dimension(:), public :: & plasticState @@ -142,26 +138,26 @@ module material homogState, & thermalState, & damageState - + integer, dimension(:,:,:), allocatable, public, protected :: & material_texture !< texture (index) of each grain,IP,element. Only used by plastic_nonlocal - + type(Rotation), dimension(:,:,:), allocatable, public, protected :: & material_orientation0 !< initial orientation of each grain,IP,element - + logical, dimension(:), allocatable, public, protected :: & phase_localPlasticity !< flags phases with local constitutive law - + integer, dimension(:), allocatable, private :: & microstructure_Nconstituents !< number of constituents in each microstructure - + integer, dimension(:,:), allocatable, private :: & microstructure_phase, & !< phase IDs of each microstructure microstructure_texture !< texture IDs of each microstructure - + type(Rotation), dimension(:), allocatable, private :: & texture_orientation !< Euler angles in material.config (possibly rotated for alignment) - + ! BEGIN DEPRECATED integer, dimension(:,:), allocatable, private, target :: mappingHomogenizationConst !< mapping from material points to offset in constant state/field @@ -170,42 +166,42 @@ module material type(tHomogMapping), allocatable, dimension(:), public :: & thermalMapping, & !< mapping for thermal state/fields damageMapping !< mapping for damage state/fields - + type(group_float), allocatable, dimension(:), public :: & temperature, & !< temperature field damage, & !< damage field temperatureRate !< temperature change rate field - + public :: & material_init, & material_allocatePlasticState, & material_allocateSourceState, & - ELASTICITY_hooke_ID ,& - PLASTICITY_none_ID, & - PLASTICITY_isotropic_ID, & - PLASTICITY_phenopowerlaw_ID, & - PLASTICITY_kinehardening_ID, & - PLASTICITY_dislotwin_ID, & - PLASTICITY_disloucla_ID, & - PLASTICITY_nonlocal_ID, & - SOURCE_thermal_dissipation_ID, & - SOURCE_thermal_externalheat_ID, & - SOURCE_damage_isoBrittle_ID, & - SOURCE_damage_isoDuctile_ID, & - SOURCE_damage_anisoBrittle_ID, & - SOURCE_damage_anisoDuctile_ID, & - KINEMATICS_cleavage_opening_ID, & - KINEMATICS_slipplane_opening_ID, & - KINEMATICS_thermal_expansion_ID, & - STIFFNESS_DEGRADATION_damage_ID, & - THERMAL_isothermal_ID, & - THERMAL_adiabatic_ID, & - THERMAL_conduction_ID, & - DAMAGE_none_ID, & - DAMAGE_local_ID, & - DAMAGE_nonlocal_ID, & - HOMOGENIZATION_none_ID, & - HOMOGENIZATION_isostrain_ID, & + ELASTICITY_HOOKE_ID ,& + PLASTICITY_NONE_ID, & + PLASTICITY_ISOTROPIC_ID, & + PLASTICITY_PHENOPOWERLAW_ID, & + PLASTICITY_KINEHARDENING_ID, & + PLASTICITY_DISLOTWIN_ID, & + PLASTICITY_DISLOUCLA_ID, & + PLASTICITY_NONLOCAL_ID, & + SOURCE_THERMAL_DISSIPATION_ID, & + SOURCE_THERMAL_EXTERNALHEAT_ID, & + SOURCE_DAMAGE_ISOBRITTLE_ID, & + SOURCE_DAMAGE_ISODUCTILE_ID, & + SOURCE_DAMAGE_ANISOBRITTLE_ID, & + SOURCE_DAMAGE_ANISODUCTILE_ID, & + KINEMATICS_CLEAVAGE_OPENING_ID, & + KINEMATICS_SLIPPLANE_OPENING_ID, & + KINEMATICS_THERMAL_EXPANSION_ID, & + STIFFNESS_DEGRADATION_DAMAGE_ID, & + THERMAL_ISOTHERMAL_ID, & + THERMAL_ADIABATIC_ID, & + THERMAL_CONDUCTION_ID, & + DAMAGE_NONE_ID, & + DAMAGE_LOCAL_ID, & + DAMAGE_NONLOCAL_ID, & + HOMOGENIZATION_NONE_ID, & + HOMOGENIZATION_ISOSTRAIN_ID, & HOMOGENIZATION_RGC_ID contains @@ -219,43 +215,43 @@ subroutine material_init integer, dimension(:), allocatable :: & CounterPhase, & CounterHomogenization - + myDebug = debug_level(debug_material) - + write(6,'(/,a)') ' <<<+- material init -+>>>'; flush(6) - + call material_parsePhase() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Phase parsed'; flush(6) - + call material_parseMicrostructure() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Microstructure parsed'; flush(6) - + call material_parseHomogenization() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Homogenization parsed'; flush(6) - + call material_parseTexture() if (iand(myDebug,debug_levelBasic) /= 0) write(6,'(a)') ' Texture parsed'; flush(6) - + material_Nphase = size(config_phase) material_Nhomogenization = size(config_homogenization) - - + + allocate(plasticState(material_Nphase)) allocate(sourceState (material_Nphase)) do myPhase = 1,material_Nphase allocate(sourceState(myPhase)%p(phase_Nsources(myPhase))) enddo - + allocate(homogState (material_Nhomogenization)) allocate(thermalState (material_Nhomogenization)) allocate(damageState (material_Nhomogenization)) - + allocate(thermalMapping (material_Nhomogenization)) allocate(damageMapping (material_Nhomogenization)) - + allocate(temperature (material_Nhomogenization)) allocate(damage (material_Nhomogenization)) - + allocate(temperatureRate (material_Nhomogenization)) do m = 1,size(config_microstructure) @@ -269,7 +265,7 @@ subroutine material_init call IO_error(151,m) enddo if(homogenization_maxNgrains > size(microstructure_phase,1)) call IO_error(148) - + debugOut: if (iand(myDebug,debug_levelExtensive) /= 0) then write(6,'(/,a,/)') ' MATERIAL configuration' write(6,'(a32,1x,a16,1x,a6)') 'homogenization ','type ','grains' @@ -289,9 +285,6 @@ subroutine material_init enddo endif debugOut -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -! new mappings - allocate(material_phaseAt(homogenization_maxNgrains,discretization_nElem), source=0) allocate(material_texture(homogenization_maxNgrains,discretization_nIP,discretization_nElem),source=0) !this is only needed by plasticity nonlocal allocate(material_orientation0(homogenization_maxNgrains,discretization_nIP,discretization_nElem)) @@ -314,15 +307,15 @@ subroutine material_init enddo enddo enddo - + deallocate(microstructure_phase) deallocate(microstructure_texture) deallocate(texture_orientation) - - + + allocate(material_homogenizationAt,source=discretization_homogenizationAt) allocate(material_homogenizationMemberAt(discretization_nIP,discretization_nElem),source=0) - + allocate(CounterHomogenization(size(config_homogenization)),source=0) do e = 1, discretization_nElem do i = 1, discretization_nIP @@ -331,9 +324,9 @@ subroutine material_init material_homogenizationMemberAt(i,e) = CounterHomogenization(material_homogenizationAt(e)) enddo enddo - + allocate(material_phaseMemberAt(homogenization_maxNgrains,discretization_nIP,discretization_nElem),source=0) - + allocate(CounterPhase(size(config_phase)),source=0) do e = 1, discretization_nElem do i = 1, discretization_nIP @@ -344,7 +337,7 @@ subroutine material_init enddo enddo enddo - + call config_deallocate('material.config/microstructure') call config_deallocate('material.config/texture') @@ -379,7 +372,7 @@ subroutine material_parseHomogenization character(len=pStringLen) :: tag logical, dimension(:), allocatable :: homogenization_active - + allocate(homogenization_type(size(config_homogenization)), source=HOMOGENIZATION_undefined_ID) allocate(thermal_type(size(config_homogenization)), source=THERMAL_isothermal_ID) allocate(damage_type (size(config_homogenization)), source=DAMAGE_none_ID) @@ -390,13 +383,13 @@ subroutine material_parseHomogenization allocate(homogenization_active(size(config_homogenization)), source=.false.) !!!!!!!!!!!!!!! allocate(thermal_initialT(size(config_homogenization)), source=300.0_pReal) allocate(damage_initialPhi(size(config_homogenization)), source=1.0_pReal) - + forall (h = 1:size(config_homogenization)) & homogenization_active(h) = any(discretization_homogenizationAt == h) - - + + do h=1, size(config_homogenization) - + tag = config_homogenization(h)%getString('mech') select case (trim(tag)) case(HOMOGENIZATION_NONE_label) @@ -411,12 +404,12 @@ subroutine material_parseHomogenization case default call IO_error(500,ext_msg=trim(tag)) end select - + homogenization_typeInstance(h) = count(homogenization_type==homogenization_type(h)) - + if (config_homogenization(h)%keyExists('thermal')) then thermal_initialT(h) = config_homogenization(h)%getFloat('t0',defaultVal=300.0_pReal) - + tag = config_homogenization(h)%getString('thermal') select case (trim(tag)) case(THERMAL_isothermal_label) @@ -428,12 +421,12 @@ subroutine material_parseHomogenization case default call IO_error(500,ext_msg=trim(tag)) end select - + endif - + if (config_homogenization(h)%keyExists('damage')) then damage_initialPhi(h) = config_homogenization(h)%getFloat('initialdamage',defaultVal=1.0_pReal) - + tag = config_homogenization(h)%getString('damage') select case (trim(tag)) case(DAMAGE_NONE_label) @@ -445,17 +438,17 @@ subroutine material_parseHomogenization case default call IO_error(500,ext_msg=trim(tag)) end select - + endif - + enddo - + do h=1, size(config_homogenization) homogenization_typeInstance(h) = count(homogenization_type(1:h) == homogenization_type(h)) thermal_typeInstance(h) = count(thermal_type (1:h) == thermal_type (h)) damage_typeInstance(h) = count(damage_type (1:h) == damage_type (h)) enddo - + homogenization_maxNgrains = maxval(homogenization_Ngrains,homogenization_active) end subroutine material_parseHomogenization @@ -476,30 +469,30 @@ subroutine material_parseMicrostructure microstructure_fraction !< vol fraction of each constituent in microstructure integer :: & maxNconstituents !< max number of constituents in any phase - + allocate(microstructure_Nconstituents(size(config_microstructure)), source=0) - + if(any(discretization_microstructureAt > size(config_microstructure))) & call IO_error(155,ext_msg='More microstructures in geometry than sections in material.config') - + do m=1, size(config_microstructure) microstructure_Nconstituents(m) = config_microstructure(m)%countKeys('(constituent)') enddo - + maxNconstituents = maxval(microstructure_Nconstituents) allocate(microstructure_phase (maxNconstituents,size(config_microstructure)),source=0) allocate(microstructure_texture (maxNconstituents,size(config_microstructure)),source=0) allocate(microstructure_fraction(maxNconstituents,size(config_microstructure)),source=0.0_pReal) - + allocate(strings(1)) ! Intel 16.0 Bug do m=1, size(config_microstructure) strings = config_microstructure(m)%getStrings('(constituent)',raw=.true.) do c = 1, size(strings) chunkPos = IO_stringPos(strings(c)) - + do i = 1,5,2 tag = IO_stringValue(strings(c),chunkPos,i) - + select case (tag) case('phase') microstructure_phase(c,m) = IO_intValue(strings(c),chunkPos,i+1) @@ -508,13 +501,13 @@ subroutine material_parseMicrostructure case('fraction') microstructure_fraction(c,m) = IO_floatValue(strings(c),chunkPos,i+1) end select - + enddo enddo if (dNeq(sum(microstructure_fraction(:,m)),1.0_pReal)) call IO_error(153,ext_msg=config_name_microstructure(m)) enddo - + end subroutine material_parseMicrostructure @@ -524,29 +517,29 @@ end subroutine material_parseMicrostructure subroutine material_parsePhase integer :: sourceCtr, kinematicsCtr, stiffDegradationCtr, p - character(len=pStringLen), dimension(:), allocatable :: str - - + character(len=pStringLen), dimension(:), allocatable :: str + + allocate(phase_elasticity(size(config_phase)),source=ELASTICITY_undefined_ID) allocate(phase_plasticity(size(config_phase)),source=PLASTICITY_undefined_ID) allocate(phase_Nsources(size(config_phase)), source=0) allocate(phase_Nkinematics(size(config_phase)), source=0) allocate(phase_NstiffnessDegradations(size(config_phase)),source=0) allocate(phase_localPlasticity(size(config_phase)), source=.false.) - + do p=1, size(config_phase) phase_Nsources(p) = config_phase(p)%countKeys('(source)') phase_Nkinematics(p) = config_phase(p)%countKeys('(kinematics)') phase_NstiffnessDegradations(p) = config_phase(p)%countKeys('(stiffness_degradation)') phase_localPlasticity(p) = .not. config_phase(p)%KeyExists('/nonlocal/') - + select case (config_phase(p)%getString('elasticity')) case (ELASTICITY_HOOKE_label) phase_elasticity(p) = ELASTICITY_HOOKE_ID case default call IO_error(200,ext_msg=trim(config_phase(p)%getString('elasticity'))) end select - + select case (config_phase(p)%getString('plasticity')) case (PLASTICITY_NONE_label) phase_plasticity(p) = PLASTICITY_NONE_ID @@ -565,9 +558,9 @@ subroutine material_parsePhase case default call IO_error(201,ext_msg=trim(config_phase(p)%getString('plasticity'))) end select - + enddo - + allocate(phase_source(maxval(phase_Nsources),size(config_phase)), source=SOURCE_undefined_ID) allocate(phase_kinematics(maxval(phase_Nkinematics),size(config_phase)), source=KINEMATICS_undefined_ID) allocate(phase_stiffnessDegradation(maxval(phase_NstiffnessDegradations),size(config_phase)), & @@ -628,10 +621,10 @@ subroutine material_parsePhase end select enddo enddo - + allocate(phase_plasticityInstance(size(config_phase)),source=0) allocate(phase_elasticityInstance(size(config_phase)),source=0) - + do p=1, size(config_phase) phase_elasticityInstance(p) = count(phase_elasticity(1:p) == phase_elasticity(p)) phase_plasticityInstance(p) = count(phase_plasticity(1:p) == phase_plasticity(p)) @@ -646,7 +639,7 @@ end subroutine material_parsePhase subroutine material_parseTexture integer :: j,t - character(len=pStringLen), dimension(:), allocatable :: strings ! Values for given key in material config + 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 @@ -662,7 +655,7 @@ subroutine material_parseTexture allocate(texture_orientation(size(config_texture))) do t=1, size(config_texture) - + strings = config_texture(t)%getStrings('(gauss)',raw= .true.) chunkPos = IO_stringPos(strings(1)) do j = 1,5,2 @@ -700,21 +693,21 @@ subroutine material_parseTexture call transformation_%fromMatrix(transformation) texture_orientation(t) = texture_orientation(t) * transformation_ endif - - enddo - + + enddo + end subroutine material_parseTexture !-------------------------------------------------------------------------------------------------- !> @brief allocates the plastic state of a phase !-------------------------------------------------------------------------------------------------- -subroutine material_allocatePlasticState(phase,NofMyPhase,& +subroutine material_allocatePlasticState(phase,NipcMyPhase,& sizeState,sizeDotState,sizeDeltaState) integer, intent(in) :: & phase, & - NofMyPhase, & + NipcMyPhase, & sizeState, & sizeDotState, & sizeDeltaState @@ -724,23 +717,23 @@ subroutine material_allocatePlasticState(phase,NofMyPhase,& plasticState(phase)%sizeDeltaState = sizeDeltaState plasticState(phase)%offsetDeltaState = sizeState-sizeDeltaState ! deltaState occupies latter part of state by definition - allocate(plasticState(phase)%aTolState (sizeState), source=0.0_pReal) - allocate(plasticState(phase)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(plasticState(phase)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(plasticState(phase)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(plasticState(phase)%state (sizeState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%atol (sizeState), source=0.0_pReal) + allocate(plasticState(phase)%state0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%partionedState0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%subState0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%state (sizeState,NipcMyPhase), source=0.0_pReal) - allocate(plasticState(phase)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%dotState (sizeDotState,NipcMyPhase),source=0.0_pReal) if (numerics_integrator == 1) then - allocate(plasticState(phase)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(plasticState(phase)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%previousDotState (sizeDotState,NipcMyPhase),source=0.0_pReal) + allocate(plasticState(phase)%previousDotState2 (sizeDotState,NipcMyPhase),source=0.0_pReal) endif if (numerics_integrator == 4) & - allocate(plasticState(phase)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%RK4dotState (sizeDotState,NipcMyPhase),source=0.0_pReal) if (numerics_integrator == 5) & - allocate(plasticState(phase)%RKCK45dotState (6,sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%RKCK45dotState (6,sizeDotState,NipcMyPhase),source=0.0_pReal) - allocate(plasticState(phase)%deltaState (sizeDeltaState,NofMyPhase), source=0.0_pReal) + allocate(plasticState(phase)%deltaState (sizeDeltaState,NipcMyPhase),source=0.0_pReal) end subroutine material_allocatePlasticState @@ -748,37 +741,37 @@ end subroutine material_allocatePlasticState !-------------------------------------------------------------------------------------------------- !> @brief allocates the source state of a phase !-------------------------------------------------------------------------------------------------- -subroutine material_allocateSourceState(phase,of,NofMyPhase,& +subroutine material_allocateSourceState(phase,of,NipcMyPhase,& sizeState,sizeDotState,sizeDeltaState) integer, intent(in) :: & phase, & of, & - NofMyPhase, & + NipcMyPhase, & sizeState, sizeDotState,sizeDeltaState - + sourceState(phase)%p(of)%sizeState = sizeState sourceState(phase)%p(of)%sizeDotState = sizeDotState sourceState(phase)%p(of)%sizeDeltaState = sizeDeltaState sourceState(phase)%p(of)%offsetDeltaState = sizeState-sizeDeltaState ! deltaState occupies latter part of state by definition - - allocate(sourceState(phase)%p(of)%aTolState (sizeState), source=0.0_pReal) - allocate(sourceState(phase)%p(of)%state0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(sourceState(phase)%p(of)%partionedState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(sourceState(phase)%p(of)%subState0 (sizeState,NofMyPhase), source=0.0_pReal) - allocate(sourceState(phase)%p(of)%state (sizeState,NofMyPhase), source=0.0_pReal) - - allocate(sourceState(phase)%p(of)%dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(of)%atol (sizeState), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%state0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%partionedState0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%subState0 (sizeState,NipcMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%state (sizeState,NipcMyPhase), source=0.0_pReal) + + allocate(sourceState(phase)%p(of)%dotState (sizeDotState,NipcMyPhase),source=0.0_pReal) if (numerics_integrator == 1) then - allocate(sourceState(phase)%p(of)%previousDotState (sizeDotState,NofMyPhase), source=0.0_pReal) - allocate(sourceState(phase)%p(of)%previousDotState2 (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%previousDotState (sizeDotState,NipcMyPhase),source=0.0_pReal) + allocate(sourceState(phase)%p(of)%previousDotState2 (sizeDotState,NipcMyPhase),source=0.0_pReal) endif if (numerics_integrator == 4) & - allocate(sourceState(phase)%p(of)%RK4dotState (sizeDotState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%RK4dotState (sizeDotState,NipcMyPhase),source=0.0_pReal) if (numerics_integrator == 5) & - allocate(sourceState(phase)%p(of)%RKCK45dotState (6,sizeDotState,NofMyPhase), source=0.0_pReal) - - allocate(sourceState(phase)%p(of)%deltaState (sizeDeltaState,NofMyPhase), source=0.0_pReal) + allocate(sourceState(phase)%p(of)%RKCK45dotState (6,sizeDotState,NipcMyPhase),source=0.0_pReal) + + allocate(sourceState(phase)%p(of)%deltaState (sizeDeltaState,NipcMyPhase),source=0.0_pReal) end subroutine material_allocateSourceState diff --git a/src/math.f90 b/src/math.f90 index 5d02812da..a296dce31 100644 --- a/src/math.f90 +++ b/src/math.f90 @@ -73,10 +73,10 @@ module math 3,3 & ],[2,9]) !< arrangement in Plain notation + interface math_eye + module procedure math_identity2nd + end interface math_eye - interface math_mul33xx33 - module procedure math_tensordot - end interface math_mul33xx33 !--------------------------------------------------------------------------------------------------- private :: & @@ -89,7 +89,6 @@ contains !-------------------------------------------------------------------------------------------------- subroutine math_init - integer :: i real(pReal), dimension(4) :: randTest integer :: randSize integer, dimension(:), allocatable :: randInit @@ -106,11 +105,8 @@ subroutine math_init randInit(2:randSize) = randInit(1) endif - call random_seed(put=randInit) - - do i = 1, 4 - call random_number(randTest(i)) - enddo + call random_seed(put = randInit) + call random_number(randTest) write(6,'(a,i2)') ' size of random seed: ', randSize write(6,'(a,i0)') ' value of random seed: ', randInit(1) @@ -427,7 +423,7 @@ end function math_exp33 !-------------------------------------------------------------------------------------------------- -!> @brief Cramer inversion of 33 matrix (function) +!> @brief Cramer inversion of 3x3 matrix (function) !> @details Direct Cramer inversion of matrix A. Returns all zeroes if not possible, i.e. ! if determinant is close to zero !-------------------------------------------------------------------------------------------------- @@ -446,7 +442,7 @@ end function math_inv33 !-------------------------------------------------------------------------------------------------- -!> @brief Cramer inversion of 33 matrix (subroutine) +!> @brief Cramer inversion of 3x3 matrix (subroutine) !> @details Direct Cramer inversion of matrix A. Also returns determinant ! Returns an error if not possible, i.e. if determinant is close to zero !-------------------------------------------------------------------------------------------------- @@ -483,7 +479,7 @@ end subroutine math_invert33 !-------------------------------------------------------------------------------------------------- -!> @brief Inversion of symmetriced 3x3x3x3 tensor. +!> @brief Inversion of symmetriced 3x3x3x3 matrix !-------------------------------------------------------------------------------------------------- function math_invSym3333(A) @@ -540,7 +536,7 @@ end subroutine math_invert !-------------------------------------------------------------------------------------------------- -!> @brief symmetrize a 33 matrix +!> @brief symmetrize a 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_symmetric33(m) @@ -553,7 +549,7 @@ end function math_symmetric33 !-------------------------------------------------------------------------------------------------- -!> @brief symmetrize a 66 matrix +!> @brief symmetrize a 6x6 matrix !-------------------------------------------------------------------------------------------------- pure function math_symmetric66(m) @@ -566,7 +562,7 @@ end function math_symmetric66 !-------------------------------------------------------------------------------------------------- -!> @brief skew part of a 33 matrix +!> @brief skew part of a 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_skew33(m) @@ -579,7 +575,7 @@ end function math_skew33 !-------------------------------------------------------------------------------------------------- -!> @brief hydrostatic part of a 33 matrix +!> @brief hydrostatic part of a 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_spherical33(m) @@ -592,7 +588,7 @@ end function math_spherical33 !-------------------------------------------------------------------------------------------------- -!> @brief deviatoric part of a 33 matrix +!> @brief deviatoric part of a 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_deviatoric33(m) @@ -605,7 +601,7 @@ end function math_deviatoric33 !-------------------------------------------------------------------------------------------------- -!> @brief trace of a 33 matrix +!> @brief trace of a 3x3 matrix !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_trace33(m) @@ -617,7 +613,7 @@ end function math_trace33 !-------------------------------------------------------------------------------------------------- -!> @brief determinant of a 33 matrix +!> @brief determinant of a 3x3 matrix !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_det33(m) @@ -631,7 +627,7 @@ end function math_det33 !-------------------------------------------------------------------------------------------------- -!> @brief determinant of a symmetric 33 matrix +!> @brief determinant of a symmetric 3x3 matrix !-------------------------------------------------------------------------------------------------- real(pReal) pure function math_detSym33(m) @@ -644,7 +640,7 @@ end function math_detSym33 !-------------------------------------------------------------------------------------------------- -!> @brief convert 33 matrix into vector 9 +!> @brief convert 3x3 matrix into vector 9 !-------------------------------------------------------------------------------------------------- pure function math_33to9(m33) @@ -661,7 +657,7 @@ end function math_33to9 !-------------------------------------------------------------------------------------------------- -!> @brief convert 9 vector into 33 matrix +!> @brief convert 9 vector into 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_9to33(v9) @@ -678,7 +674,7 @@ end function math_9to33 !-------------------------------------------------------------------------------------------------- -!> @brief convert symmetric 33 matrix into 6 vector +!> @brief convert symmetric 3x3 matrix into 6 vector !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only changes order according to Nye @@ -686,8 +682,8 @@ end function math_9to33 pure function math_sym33to6(m33,weighted) real(pReal), dimension(6) :: math_sym33to6 - real(pReal), dimension(3,3), intent(in) :: m33 !< symmetric matrix (no internal check) - logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) + real(pReal), dimension(3,3), intent(in) :: m33 !< symmetric 3x3 matrix (no internal check) + logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) real(pReal), dimension(6) :: w integer :: i @@ -706,7 +702,7 @@ end function math_sym33to6 !-------------------------------------------------------------------------------------------------- -!> @brief convert 6 vector into symmetric 33 matrix +!> @brief convert 6 vector into symmetric 3x3 matrix !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. ! Unweighted conversion only changes order according to Nye @@ -714,8 +710,8 @@ end function math_sym33to6 pure function math_6toSym33(v6,weighted) real(pReal), dimension(3,3) :: math_6toSym33 - real(pReal), dimension(6), intent(in) :: v6 - logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) + real(pReal), dimension(6), intent(in) :: v6 !< 6 vector + logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) real(pReal), dimension(6) :: w integer :: i @@ -735,7 +731,7 @@ end function math_6toSym33 !-------------------------------------------------------------------------------------------------- -!> @brief convert 3333 matrix into 99 matrix +!> @brief convert 3x3x3x3 matrix into 9x9 matrix !-------------------------------------------------------------------------------------------------- pure function math_3333to99(m3333) @@ -752,7 +748,7 @@ end function math_3333to99 !-------------------------------------------------------------------------------------------------- -!> @brief convert 99 matrix into 3333 matrix +!> @brief convert 9x9 matrix into 3x3x3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_99to3333(m99) @@ -769,16 +765,16 @@ end function math_99to3333 !-------------------------------------------------------------------------------------------------- -!> @brief convert symmetric 3333 matrix into 66 matrix +!> @brief convert symmetric 3x3x3x3 matrix into 6x6 matrix !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. -! Unweighted conversion only changes order according to Nye +! Unweighted conversion only rearranges order according to Nye !-------------------------------------------------------------------------------------------------- pure function math_sym3333to66(m3333,weighted) real(pReal), dimension(6,6) :: math_sym3333to66 - real(pReal), dimension(3,3,3,3), intent(in) :: m3333 !< symmetric matrix (no internal check) - logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) + real(pReal), dimension(3,3,3,3), intent(in) :: m3333 !< symmetric 3x3x3x3 matrix (no internal check) + logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) real(pReal), dimension(6) :: w integer :: i,j @@ -797,16 +793,16 @@ end function math_sym3333to66 !-------------------------------------------------------------------------------------------------- -!> @brief convert 66 matrix into symmetric 3333 matrix +!> @brief convert 66 matrix into symmetric 3x3x3x3 matrix !> @details Weighted conversion (default) rearranges according to Nye and weights shear ! components according to Mandel. Advisable for matrix operations. -! Unweighted conversion only changes order according to Nye +! Unweighted conversion only rearranges order according to Nye !-------------------------------------------------------------------------------------------------- pure function math_66toSym3333(m66,weighted) real(pReal), dimension(3,3,3,3) :: math_66toSym3333 - real(pReal), dimension(6,6), intent(in) :: m66 - logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) + real(pReal), dimension(6,6), intent(in) :: m66 !< 6x6 matrix + logical, optional, intent(in) :: weighted !< weight according to Mandel (.true. by default) real(pReal), dimension(6) :: w integer :: i,j @@ -828,12 +824,12 @@ end function math_66toSym3333 !-------------------------------------------------------------------------------------------------- -!> @brief convert 66 Voigt matrix into symmetric 3333 matrix +!> @brief convert 66 Voigt matrix into symmetric 3x3x3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_Voigt66to3333(m66) real(pReal), dimension(3,3,3,3) :: math_Voigt66to3333 - real(pReal), dimension(6,6), intent(in) :: m66 + real(pReal), dimension(6,6), intent(in) :: m66 !< 6x6 matrix integer :: i,j do i=1,6; do j=1, 6 @@ -851,9 +847,10 @@ end function math_Voigt66to3333 !-------------------------------------------------------------------------------------------------- real(pReal) function math_sampleGaussVar(meanvalue, stddev, width) - real(pReal), intent(in) :: meanvalue, & ! meanvalue of gauss distribution - stddev ! standard deviation of gauss distribution - real(pReal), intent(in), optional :: width ! width of considered values as multiples of standard deviation + real(pReal), intent(in) :: meanvalue, & !< meanvalue of gauss distribution + stddev !< standard deviation of gauss distribution + real(pReal), intent(in), optional :: width !< width of considered values as multiples of standard deviation + real(pReal), dimension(2) :: rnd ! random numbers real(pReal) :: scatter, & ! normalized scatter around meanvalue width_ @@ -880,266 +877,172 @@ end function math_sampleGaussVar !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric matrix m +!> @brief eigenvalues and eigenvectors of symmetric matrix ! ToDo: has wrong oder of arguments !-------------------------------------------------------------------------------------------------- -subroutine math_eigenValuesVectorsSym(m,values,vectors,error) +subroutine math_eigh(m,w,v,error) + + real(pReal), dimension(:,:), intent(in) :: m !< quadratic matrix to compute eigenvectors and values of + real(pReal), dimension(size(m,1)), intent(out) :: w !< eigenvalues + real(pReal), dimension(size(m,1),size(m,1)), intent(out) :: v !< eigenvectors - real(pReal), dimension(:,:), intent(in) :: m - real(pReal), dimension(size(m,1)), intent(out) :: values - real(pReal), dimension(size(m,1),size(m,1)), intent(out) :: vectors logical, intent(out) :: error integer :: ierr real(pReal), dimension((64+2)*size(m,1)) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f external :: & dsyev - vectors = m ! copy matrix to input (doubles as output) array - call dsyev('V','U',size(m,1),vectors,size(m,1),values,work,size(work,1),ierr) + v = m ! copy matrix to input (doubles as output) array + call dsyev('V','U',size(m,1),v,size(m,1),w,work,size(work,1),ierr) error = (ierr /= 0) -end subroutine math_eigenValuesVectorsSym +end subroutine math_eigh !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues and eigenvectors of symmetric 33 matrix m using an analytical expression +!> @brief eigenvalues and eigenvectors of symmetric 3x3 matrix using an analytical expression !> and the general LAPACK powered version for arbritrary sized matrices as fallback !> @author Joachim Kopp, Max-Planck-Institut für Kernphysik, Heidelberg (Copyright (C) 2006) !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @details See http://arxiv.org/abs/physics/0610206 (DSYEVH3) ! ToDo: has wrong oder of arguments !-------------------------------------------------------------------------------------------------- -subroutine math_eigenValuesVectorsSym33(m,values,vectors) +subroutine math_eigh33(m,w,v) + + real(pReal), dimension(3,3),intent(in) :: m !< 3x3 matrix to compute eigenvectors and values of + real(pReal), dimension(3), intent(out) :: w !< eigenvalues + real(pReal), dimension(3,3),intent(out) :: v !< eigenvectors - real(pReal), dimension(3,3),intent(in) :: m - real(pReal), dimension(3), intent(out) :: values - real(pReal), dimension(3,3),intent(out) :: vectors real(pReal) :: T, U, norm, threshold logical :: error - values = math_eigenvaluesSym33(m) + w = math_eigvalsh33(m) - vectors(1:3,2) = [ m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2), & - m(1, 3) * m(1, 2) - m(2, 3) * m(1, 1), & - m(1, 2)**2] + v(1:3,2) = [ m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2), & + m(1, 3) * m(1, 2) - m(2, 3) * m(1, 1), & + m(1, 2)**2] - T = maxval(abs(values)) + T = maxval(abs(w)) U = max(T, T**2) threshold = sqrt(5.68e-14_pReal * U**2) - ! Calculate first eigenvector by the formula v[0] = (m - lambda[0]).e1 x (m - lambda[0]).e2 - vectors(1:3,1) = [ vectors(1,2) + m(1, 3) * values(1), & - vectors(2,2) + m(2, 3) * values(1), & - (m(1,1) - values(1)) * (m(2,2) - values(1)) - vectors(3,2)] - norm = norm2(vectors(1:3, 1)) - + v(1:3,1) = [ v(1,2) + m(1, 3) * w(1), & + v(2,2) + m(2, 3) * w(1), & + (m(1,1) - w(1)) * (m(2,2) - w(1)) - v(3,2)] + norm = norm2(v(1:3, 1)) fallback1: if(norm < threshold) then - call math_eigenValuesVectorsSym(m,values,vectors,error) - return + call math_eigh(m,w,v,error) + else fallback1 + v(1:3,1) = v(1:3, 1) / norm + v(1:3,2) = [ v(1,2) + m(1, 3) * w(2), & + v(2,2) + m(2, 3) * w(2), & + (m(1,1) - w(2)) * (m(2,2) - w(2)) - v(3,2)] + norm = norm2(v(1:3, 2)) + fallback2: if(norm < threshold) then + call math_eigh(m,w,v,error) + else fallback2 + v(1:3,2) = v(1:3, 2) / norm + v(1:3,3) = math_cross(v(1:3,1),v(1:3,2)) + endif fallback2 endif fallback1 - vectors(1:3,1) = vectors(1:3, 1) / norm +end subroutine math_eigh33 - ! Calculate second eigenvector by the formula v[1] = (m - lambda[1]).e1 x (m - lambda[1]).e2 - vectors(1:3,2) = [ vectors(1,2) + m(1, 3) * values(2), & - vectors(2,2) + m(2, 3) * values(2), & - (m(1,1) - values(2)) * (m(2,2) - values(2)) - vectors(3,2)] - norm = norm2(vectors(1:3, 2)) - fallback2: if(norm < threshold) then - call math_eigenValuesVectorsSym(m,values,vectors,error) - return - endif fallback2 - vectors(1:3,2) = vectors(1:3, 2) / norm - - ! Calculate third eigenvector according to v[2] = v[0] x v[1] - vectors(1:3,3) = math_cross(vectors(1:3,1),vectors(1:3,2)) - -end subroutine math_eigenValuesVectorsSym33 !-------------------------------------------------------------------------------------------------- -!> @brief eigenvector basis of symmetric matrix m +!> @brief rotational part from polar decomposition of 3x3 tensor !-------------------------------------------------------------------------------------------------- -function math_eigenvectorBasisSym(m) - - real(pReal), dimension(:,:), intent(in) :: m - real(pReal), dimension(size(m,1)) :: values - real(pReal), dimension(size(m,1),size(m,1)) :: vectors - real(pReal), dimension(size(m,1),size(m,1)) :: math_eigenvectorBasisSym - logical :: error - integer :: i - - math_eigenvectorBasisSym = 0.0_pReal - call math_eigenValuesVectorsSym(m,values,vectors,error) - if(error) return - - do i=1, size(m,1) - math_eigenvectorBasisSym = math_eigenvectorBasisSym & - + sqrt(values(i)) * math_outer(vectors(:,i),vectors(:,i)) - enddo - -end function math_eigenvectorBasisSym - - -!-------------------------------------------------------------------------------------------------- -!> @brief eigenvector basis of symmetric 33 matrix m -!-------------------------------------------------------------------------------------------------- -pure function math_eigenvectorBasisSym33(m) - - real(pReal), dimension(3,3) :: math_eigenvectorBasisSym33 - real(pReal), dimension(3) :: invariants, values - real(pReal), dimension(3,3), intent(in) :: m - real(pReal) :: P, Q, rho, phi - real(pReal), parameter :: TOL=1.e-14_pReal - real(pReal), dimension(3,3,3) :: N, EB - - invariants = math_invariantsSym33(m) - EB = 0.0_pReal - - P = invariants(2)-invariants(1)**2.0_pReal/3.0_pReal - Q = -2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+product(invariants(1:2))/3.0_pReal-invariants(3) - - threeSimilarEigenvalues: if(all(abs([P,Q]) < TOL)) then - values = invariants(1)/3.0_pReal - ! this is not really correct, but at least the basis is correct - EB(1,1,1)=1.0_pReal - EB(2,2,2)=1.0_pReal - EB(3,3,3)=1.0_pReal - else threeSimilarEigenvalues - rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal - phi=acos(math_clip(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) - values = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & - [cos(phi/3.0_pReal), & - cos((phi+2.0_pReal*PI)/3.0_pReal), & - cos((phi+4.0_pReal*PI)/3.0_pReal) & - ] + invariants(1)/3.0_pReal - N(1:3,1:3,1) = m-values(1)*math_I3 - N(1:3,1:3,2) = m-values(2)*math_I3 - N(1:3,1:3,3) = m-values(3)*math_I3 - twoSimilarEigenvalues: if(abs(values(1)-values(2)) < TOL) then - EB(1:3,1:3,3)=matmul(N(1:3,1:3,1),N(1:3,1:3,2))/ & - ((values(3)-values(1))*(values(3)-values(2))) - EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,3) - elseif(abs(values(2)-values(3)) < TOL) then twoSimilarEigenvalues - EB(1:3,1:3,1)=matmul(N(1:3,1:3,2),N(1:3,1:3,3))/ & - ((values(1)-values(2))*(values(1)-values(3))) - EB(1:3,1:3,2)=math_I3-EB(1:3,1:3,1) - elseif(abs(values(3)-values(1)) < TOL) then twoSimilarEigenvalues - EB(1:3,1:3,2)=matmul(N(1:3,1:3,1),N(1:3,1:3,3))/ & - ((values(2)-values(1))*(values(2)-values(3))) - EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,2) - else twoSimilarEigenvalues - EB(1:3,1:3,1)=matmul(N(1:3,1:3,2),N(1:3,1:3,3))/ & - ((values(1)-values(2))*(values(1)-values(3))) - EB(1:3,1:3,2)=matmul(N(1:3,1:3,1),N(1:3,1:3,3))/ & - ((values(2)-values(1))*(values(2)-values(3))) - EB(1:3,1:3,3)=matmul(N(1:3,1:3,1),N(1:3,1:3,2))/ & - ((values(3)-values(1))*(values(3)-values(2))) - endif twoSimilarEigenvalues - endif threeSimilarEigenvalues - - math_eigenvectorBasisSym33 = sqrt(values(1)) * EB(1:3,1:3,1) & - + sqrt(values(2)) * EB(1:3,1:3,2) & - + sqrt(values(3)) * EB(1:3,1:3,3) - -end function math_eigenvectorBasisSym33 - - -!-------------------------------------------------------------------------------------------------- -!> @brief logarithm eigenvector basis of symmetric 33 matrix m -!-------------------------------------------------------------------------------------------------- -pure function math_eigenvectorBasisSym33_log(m) - - real(pReal), dimension(3,3) :: math_eigenvectorBasisSym33_log - real(pReal), dimension(3) :: invariants, values - real(pReal), dimension(3,3), intent(in) :: m - real(pReal) :: P, Q, rho, phi - real(pReal), parameter :: TOL=1.e-14_pReal - real(pReal), dimension(3,3,3) :: N, EB - - invariants = math_invariantsSym33(m) - EB = 0.0_pReal - - P = invariants(2)-invariants(1)**2.0_pReal/3.0_pReal - Q = -2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+product(invariants(1:2))/3.0_pReal-invariants(3) - - threeSimilarEigenvalues: if(all(abs([P,Q]) < TOL)) then - values = invariants(1)/3.0_pReal - ! this is not really correct, but at least the basis is correct - EB(1,1,1)=1.0_pReal - EB(2,2,2)=1.0_pReal - EB(3,3,3)=1.0_pReal - else threeSimilarEigenvalues - rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal - phi=acos(math_clip(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) - values = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & - [cos(phi/3.0_pReal), & - cos((phi+2.0_pReal*PI)/3.0_pReal), & - cos((phi+4.0_pReal*PI)/3.0_pReal) & - ] + invariants(1)/3.0_pReal - N(1:3,1:3,1) = m-values(1)*math_I3 - N(1:3,1:3,2) = m-values(2)*math_I3 - N(1:3,1:3,3) = m-values(3)*math_I3 - twoSimilarEigenvalues: if(abs(values(1)-values(2)) < TOL) then - EB(1:3,1:3,3)=matmul(N(1:3,1:3,1),N(1:3,1:3,2))/ & - ((values(3)-values(1))*(values(3)-values(2))) - EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,3) - elseif(abs(values(2)-values(3)) < TOL) then twoSimilarEigenvalues - EB(1:3,1:3,1)=matmul(N(1:3,1:3,2),N(1:3,1:3,3))/ & - ((values(1)-values(2))*(values(1)-values(3))) - EB(1:3,1:3,2)=math_I3-EB(1:3,1:3,1) - elseif(abs(values(3)-values(1)) < TOL) then twoSimilarEigenvalues - EB(1:3,1:3,2)=matmul(N(1:3,1:3,1),N(1:3,1:3,3))/ & - ((values(2)-values(1))*(values(2)-values(3))) - EB(1:3,1:3,1)=math_I3-EB(1:3,1:3,2) - else twoSimilarEigenvalues - EB(1:3,1:3,1)=matmul(N(1:3,1:3,2),N(1:3,1:3,3))/ & - ((values(1)-values(2))*(values(1)-values(3))) - EB(1:3,1:3,2)=matmul(N(1:3,1:3,1),N(1:3,1:3,3))/ & - ((values(2)-values(1))*(values(2)-values(3))) - EB(1:3,1:3,3)=matmul(N(1:3,1:3,1),N(1:3,1:3,2))/ & - ((values(3)-values(1))*(values(3)-values(2))) - endif twoSimilarEigenvalues - endif threeSimilarEigenvalues - - math_eigenvectorBasisSym33_log = log(sqrt(values(1))) * EB(1:3,1:3,1) & - + log(sqrt(values(2))) * EB(1:3,1:3,2) & - + log(sqrt(values(3))) * EB(1:3,1:3,3) - -end function math_eigenvectorBasisSym33_log - - -!-------------------------------------------------------------------------------------------------- -!> @brief rotational part from polar decomposition of 33 tensor m -!-------------------------------------------------------------------------------------------------- -function math_rotationalPart33(m) +function math_rotationalPart(m) real(pReal), intent(in), dimension(3,3) :: m - real(pReal), dimension(3,3) :: math_rotationalPart33 + real(pReal), dimension(3,3) :: math_rotationalPart real(pReal), dimension(3,3) :: U , Uinv - U = math_eigenvectorBasisSym33(matmul(transpose(m),m)) + U = eigenvectorBasis(matmul(transpose(m),m)) Uinv = math_inv33(U) inversionFailed: if (all(dEq0(Uinv))) then - math_rotationalPart33 = math_I3 + math_rotationalPart = math_I3 call IO_warning(650) else inversionFailed - math_rotationalPart33 = matmul(m,Uinv) + math_rotationalPart = matmul(m,Uinv) endif inversionFailed -end function math_rotationalPart33 +contains + !-------------------------------------------------------------------------------------------------- + !> @brief eigenvector basis of positive-definite 3x3 matrix + !-------------------------------------------------------------------------------------------------- + pure function eigenvectorBasis(m) + + real(pReal), dimension(3,3) :: eigenvectorBasis + real(pReal), dimension(3,3), intent(in) :: m !< positive-definite matrix of which the basis is computed + + real(pReal), dimension(3) :: I, v + real(pReal) :: P, Q, rho, phi + real(pReal), parameter :: TOL=1.e-14_pReal + real(pReal), dimension(3,3,3) :: N, EB + + I = math_invariantsSym33(m) + + P = I(2)-I(1)**2.0_pReal/3.0_pReal + Q = -2.0_pReal/27.0_pReal*I(1)**3.0_pReal+product(I(1:2))/3.0_pReal-I(3) + + threeSimilarEigVals: if(all(abs([P,Q]) < TOL)) then + v = I(1)/3.0_pReal + ! this is not really correct, but at least the basis is correct + EB = 0.0_pReal + EB(1,1,1)=1.0_pReal + EB(2,2,2)=1.0_pReal + EB(3,3,3)=1.0_pReal + else threeSimilarEigVals + rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal + phi=acos(math_clip(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) + v = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* [cos((phi )/3.0_pReal), & + cos((phi+2.0_pReal*PI)/3.0_pReal), & + cos((phi+4.0_pReal*PI)/3.0_pReal) & + ] + I(1)/3.0_pReal + N(1:3,1:3,1) = m-v(1)*math_I3 + N(1:3,1:3,2) = m-v(2)*math_I3 + N(1:3,1:3,3) = m-v(3)*math_I3 + twoSimilarEigVals: if(abs(v(1)-v(2)) < TOL) then + EB(1:3,1:3,3) = matmul(N(1:3,1:3,1),N(1:3,1:3,2))/((v(3)-v(1))*(v(3)-v(2))) + EB(1:3,1:3,1) = math_I3-EB(1:3,1:3,3) + EB(1:3,1:3,2) = 0.0_pReal + elseif (abs(v(2)-v(3)) < TOL) then twoSimilarEigVals + EB(1:3,1:3,1) = matmul(N(1:3,1:3,2),N(1:3,1:3,3))/((v(1)-v(2))*(v(1)-v(3))) + EB(1:3,1:3,2) = math_I3-EB(1:3,1:3,1) + EB(1:3,1:3,3) = 0.0_pReal + elseif (abs(v(3)-v(1)) < TOL) then twoSimilarEigVals + EB(1:3,1:3,2) = matmul(N(1:3,1:3,3),N(1:3,1:3,1))/((v(2)-v(3))*(v(2)-v(1))) + EB(1:3,1:3,3) = math_I3-EB(1:3,1:3,2) + EB(1:3,1:3,1) = 0.0_pReal + else twoSimilarEigVals + EB(1:3,1:3,1) = matmul(N(1:3,1:3,2),N(1:3,1:3,3))/((v(1)-v(2))*(v(1)-v(3))) + EB(1:3,1:3,2) = matmul(N(1:3,1:3,3),N(1:3,1:3,1))/((v(2)-v(3))*(v(2)-v(1))) + EB(1:3,1:3,3) = matmul(N(1:3,1:3,1),N(1:3,1:3,2))/((v(3)-v(1))*(v(3)-v(2))) + endif twoSimilarEigVals + endif threeSimilarEigVals + + eigenvectorBasis = sqrt(v(1)) * EB(1:3,1:3,1) & + + sqrt(v(2)) * EB(1:3,1:3,2) & + + sqrt(v(3)) * EB(1:3,1:3,3) + + end function eigenvectorBasis + +end function math_rotationalPart !-------------------------------------------------------------------------------------------------- -!> @brief Eigenvalues of symmetric matrix m +!> @brief Eigenvalues of symmetric matrix ! will return NaN on error !-------------------------------------------------------------------------------------------------- -function math_eigenvaluesSym(m) +function math_eigvalsh(m) + + real(pReal), dimension(:,:), intent(in) :: m !< symmetric matrix to compute eigenvalues of + real(pReal), dimension(size(m,1)) :: math_eigvalsh - real(pReal), dimension(:,:), intent(in) :: m - real(pReal), dimension(size(m,1)) :: math_eigenvaluesSym real(pReal), dimension(size(m,1),size(m,1)) :: m_ integer :: ierr real(pReal), dimension((64+2)*size(m,1)) :: work ! block size of 64 taken from http://www.netlib.org/lapack/double/dsyev.f @@ -1147,48 +1050,51 @@ function math_eigenvaluesSym(m) dsyev m_= m ! copy matrix to input (will be destroyed) - call dsyev('N','U',size(m,1),m_,size(m,1),math_eigenvaluesSym,work,size(work,1),ierr) - if (ierr /= 0) math_eigenvaluesSym = IEEE_value(1.0_pReal,IEEE_quiet_NaN) + call dsyev('N','U',size(m,1),m_,size(m,1),math_eigvalsh,work,size(work,1),ierr) + if (ierr /= 0) math_eigvalsh = IEEE_value(1.0_pReal,IEEE_quiet_NaN) -end function math_eigenvaluesSym +end function math_eigvalsh !-------------------------------------------------------------------------------------------------- -!> @brief eigenvalues of symmetric 33 matrix m using an analytical expression +!> @brief eigenvalues of symmetric 3x3 matrix using an analytical expression !> @author Martin Diehl, Max-Planck-Institut für Eisenforschung GmbH !> @details similar to http://arxiv.org/abs/physics/0610206 (DSYEVC3) !> but apparently more stable solution and has general LAPACK powered version for arbritrary sized !> matrices as fallback !-------------------------------------------------------------------------------------------------- -function math_eigenvaluesSym33(m) +function math_eigvalsh33(m) - real(pReal), intent(in), dimension(3,3) :: m - real(pReal), dimension(3) :: math_eigenvaluesSym33,invariants + real(pReal), intent(in), dimension(3,3) :: m !< 3x3 symmetric matrix to compute eigenvalues of + real(pReal), dimension(3) :: math_eigvalsh33,I real(pReal) :: P, Q, rho, phi real(pReal), parameter :: TOL=1.e-14_pReal - invariants = math_invariantsSym33(m) ! invariants are coefficients in characteristic polynomial apart for the sign of c0 and c2 in http://arxiv.org/abs/physics/0610206 + I = math_invariantsSym33(m) ! invariants are coefficients in characteristic polynomial apart for the sign of c0 and c2 in http://arxiv.org/abs/physics/0610206 - P = invariants(2)-invariants(1)**2.0_pReal/3.0_pReal ! different from http://arxiv.org/abs/physics/0610206 (this formulation was in DAMASK) - Q = -2.0_pReal/27.0_pReal*invariants(1)**3.0_pReal+product(invariants(1:2))/3.0_pReal-invariants(3)! different from http://arxiv.org/abs/physics/0610206 (this formulation was in DAMASK) + P = I(2)-I(1)**2.0_pReal/3.0_pReal ! different from http://arxiv.org/abs/physics/0610206 (this formulation was in DAMASK) + Q = product(I(1:2))/3.0_pReal & + - 2.0_pReal/27.0_pReal*I(1)**3.0_pReal & + - I(3) ! different from http://arxiv.org/abs/physics/0610206 (this formulation was in DAMASK) if(all(abs([P,Q]) < TOL)) then - math_eigenvaluesSym33 = math_eigenvaluesSym(m) + math_eigvalsh33 = math_eigvalsh(m) else rho=sqrt(-3.0_pReal*P**3.0_pReal)/9.0_pReal phi=acos(math_clip(-Q/rho*0.5_pReal,-1.0_pReal,1.0_pReal)) - math_eigenvaluesSym33 = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & - [cos(phi/3.0_pReal), & - cos((phi+2.0_pReal*PI)/3.0_pReal), & - cos((phi+4.0_pReal*PI)/3.0_pReal) & - ] + invariants(1)/3.0_pReal + math_eigvalsh33 = 2.0_pReal*rho**(1.0_pReal/3.0_pReal)* & + [cos(phi/3.0_pReal), & + cos((phi+2.0_pReal*PI)/3.0_pReal), & + cos((phi+4.0_pReal*PI)/3.0_pReal) & + ] & + + I(1)/3.0_pReal endif -end function math_eigenvaluesSym33 +end function math_eigvalsh33 !-------------------------------------------------------------------------------------------------- -!> @brief invariants of symmetrix 33 matrix m +!> @brief invariants of symmetrix 3x3 matrix !-------------------------------------------------------------------------------------------------- pure function math_invariantsSym33(m) @@ -1298,7 +1204,7 @@ end function math_clip !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of (some) math functions +!> @brief check correctness of some math functions !-------------------------------------------------------------------------------------------------- subroutine unitTest @@ -1344,7 +1250,6 @@ subroutine unitTest if(any(dNeq(math_exp33(math_I3,0),math_I3))) & call IO_error(0,ext_msg='math_exp33(math_I3,1)') - if(any(dNeq(math_exp33(math_I3,256),exp(1.0_pReal)*math_I3))) & call IO_error(0,ext_msg='math_exp33(math_I3,256)') @@ -1400,9 +1305,13 @@ subroutine unitTest if(any(dNeq0(matmul(t33,t33_2) - math_identity2nd(3),tol=1.0e-9_pReal)) .or. e) & call IO_error(0,ext_msg='math_invert t33') - t33_2 = transpose(math_rotationalPart33(t33)) - if(any(dNeq0(matmul(t33_2,math_rotationalPart33(t33)) - MATH_I3,tol=5.0e-4_pReal))) & - call IO_error(0,ext_msg='math_rotationalPart33') + do while(math_det33(t33)<1.0e-2_pReal) ! O(det(F)) = 1 + call random_number(t33) + enddo + t33_2 = math_rotationalPart(transpose(t33)) + t33 = math_rotationalPart(t33) + if(any(dNeq0(matmul(t33_2,t33) - math_I3,tol=1.0e-10_pReal))) & + call IO_error(0,ext_msg='math_rotationalPart') call random_number(r) d = int(r*5.0_pReal) + 1 diff --git a/src/mesh/DAMASK_FEM.f90 b/src/mesh/DAMASK_mesh.f90 similarity index 99% rename from src/mesh/DAMASK_FEM.f90 rename to src/mesh/DAMASK_mesh.f90 index d6c7d9375..3c9613d73 100644 --- a/src/mesh/DAMASK_FEM.f90 +++ b/src/mesh/DAMASK_mesh.f90 @@ -16,9 +16,9 @@ program DAMASK_FEM use CPFEM2 use FEsolving use numerics - use mesh + use discretization_mesh use FEM_Utilities - use FEM_mech + use mesh_mech_FEM implicit none diff --git a/src/mesh/FEM_zoo.f90 b/src/mesh/FEM_quadrature.f90 similarity index 58% rename from src/mesh/FEM_zoo.f90 rename to src/mesh/FEM_quadrature.f90 index 1326039fc..65b0bc6fe 100644 --- a/src/mesh/FEM_zoo.f90 +++ b/src/mesh/FEM_quadrature.f90 @@ -2,12 +2,12 @@ !> @author Pratheek Shanthraj, Max-Planck-Institut für Eisenforschung GmbH !> @brief Interpolation data used by the FEM solver !-------------------------------------------------------------------------------------------------- -module FEM_Zoo +module FEM_quadrature use prec - + implicit none private - + integer, parameter :: & maxOrder = 5 !< current max interpolation set at cubic (intended to be arbitrary) real(pReal), dimension(2,3), parameter :: & @@ -21,13 +21,13 @@ module FEM_Zoo -1.0_pReal, -1.0_pReal, 1.0_pReal], shape=[3,4]) integer, dimension(2:3,maxOrder), public, protected :: & - FEM_Zoo_nQuadrature !< number of quadrature points for a given spatial dimension(2-3) and interpolation order(1-maxOrder) + FEM_nQuadrature !< number of quadrature points for a given spatial dimension(2-3) and interpolation order(1-maxOrder) type(group_float), dimension(2:3,maxOrder), public, protected :: & - FEM_Zoo_QuadratureWeights, & !< quadrature weights for each quadrature rule - FEM_Zoo_QuadraturePoints !< quadrature point coordinates (in simplical system) for each quadrature rule - + FEM_quadrature_weights, & !< quadrature weights for each quadrature rule + FEM_quadrature_points !< quadrature point coordinates (in simplical system) for each quadrature rule + public :: & - FEM_Zoo_init + FEM_quadrature_init contains @@ -35,195 +35,195 @@ contains !-------------------------------------------------------------------------------------------------- !> @brief initializes FEM interpolation data !-------------------------------------------------------------------------------------------------- -subroutine FEM_Zoo_init - - write(6,'(/,a)') ' <<<+- FEM_Zoo init -+>>>'; flush(6) +subroutine FEM_quadrature_init + + write(6,'(/,a)') ' <<<+- FEM_quadrature init -+>>>'; flush(6) !-------------------------------------------------------------------------------------------------- ! 2D linear - FEM_Zoo_nQuadrature(2,1) = 1 + FEM_nQuadrature(2,1) = 1 - allocate(FEM_Zoo_QuadratureWeights(2,1)%p(1)) - FEM_Zoo_QuadratureWeights(2,1)%p(1) = 1.0_pReal + allocate(FEM_quadrature_weights(2,1)%p(1)) + FEM_quadrature_weights(2,1)%p(1) = 1.0_pReal + + allocate(FEM_quadrature_points (2,1)%p(2)) + FEM_quadrature_points (2,1)%p(1:2) = permutationStar3([1.0_pReal/3.0_pReal]) - allocate(FEM_Zoo_QuadraturePoints (2,1)%p(2)) - FEM_Zoo_QuadraturePoints (2,1)%p(1:2) = FEM_Zoo_permutationStar3([1.0_pReal/3.0_pReal]) - !-------------------------------------------------------------------------------------------------- ! 2D quadratic - FEM_Zoo_nQuadrature(2,2) = 3 - - allocate(FEM_Zoo_QuadratureWeights(2,2)%p(3)) - FEM_Zoo_QuadratureWeights(2,2)%p(1:3) = 1.0_pReal/3.0_pReal + FEM_nQuadrature(2,2) = 3 + + allocate(FEM_quadrature_weights(2,2)%p(3)) + FEM_quadrature_weights(2,2)%p(1:3) = 1.0_pReal/3.0_pReal + + allocate(FEM_quadrature_points (2,2)%p(6)) + FEM_quadrature_points (2,2)%p(1:6) = permutationStar21([1.0_pReal/6.0_pReal]) - allocate(FEM_Zoo_QuadraturePoints (2,2)%p(6)) - FEM_Zoo_QuadraturePoints (2,2)%p(1:6) = FEM_Zoo_permutationStar21([1.0_pReal/6.0_pReal]) - !-------------------------------------------------------------------------------------------------- ! 2D cubic - FEM_Zoo_nQuadrature(2,3) = 6 - - allocate(FEM_Zoo_QuadratureWeights(2,3)%p(6)) - FEM_Zoo_QuadratureWeights(2,3)%p(1:3) = 0.22338158967801146570_pReal - FEM_Zoo_QuadratureWeights(2,3)%p(4:6) = 0.10995174365532186764_pReal + FEM_nQuadrature(2,3) = 6 - allocate(FEM_Zoo_QuadraturePoints (2,3)%p(12)) - FEM_Zoo_QuadraturePoints (2,3)%p(1:6) = FEM_Zoo_permutationStar21([0.44594849091596488632_pReal]) - FEM_Zoo_QuadraturePoints (2,3)%p(7:12)= FEM_Zoo_permutationStar21([0.091576213509770743460_pReal]) + allocate(FEM_quadrature_weights(2,3)%p(6)) + FEM_quadrature_weights(2,3)%p(1:3) = 0.22338158967801146570_pReal + FEM_quadrature_weights(2,3)%p(4:6) = 0.10995174365532186764_pReal + + allocate(FEM_quadrature_points (2,3)%p(12)) + FEM_quadrature_points (2,3)%p(1:6) = permutationStar21([0.44594849091596488632_pReal]) + FEM_quadrature_points (2,3)%p(7:12)= permutationStar21([0.091576213509770743460_pReal]) !-------------------------------------------------------------------------------------------------- ! 2D quartic - FEM_Zoo_nQuadrature(2,4) = 12 + FEM_nQuadrature(2,4) = 12 - allocate(FEM_Zoo_QuadratureWeights(2,4)%p(12)) - FEM_Zoo_QuadratureWeights(2,4)%p(1:3) = 0.11678627572638_pReal - FEM_Zoo_QuadratureWeights(2,4)%p(4:6) = 0.05084490637021_pReal - FEM_Zoo_QuadratureWeights(2,4)%p(7:12) = 0.08285107561837_pReal + allocate(FEM_quadrature_weights(2,4)%p(12)) + FEM_quadrature_weights(2,4)%p(1:3) = 0.11678627572638_pReal + FEM_quadrature_weights(2,4)%p(4:6) = 0.05084490637021_pReal + FEM_quadrature_weights(2,4)%p(7:12) = 0.08285107561837_pReal - allocate(FEM_Zoo_QuadraturePoints (2,4)%p(24)) - FEM_Zoo_QuadraturePoints (2,4)%p(1:6) = FEM_Zoo_permutationStar21([0.24928674517091_pReal]) - FEM_Zoo_QuadraturePoints (2,4)%p(7:12) = FEM_Zoo_permutationStar21([0.06308901449150_pReal]) - FEM_Zoo_QuadraturePoints (2,4)%p(13:24)= FEM_Zoo_permutationStar111([0.31035245103378_pReal, 0.63650249912140_pReal]) + allocate(FEM_quadrature_points (2,4)%p(24)) + FEM_quadrature_points (2,4)%p(1:6) = permutationStar21([0.24928674517091_pReal]) + FEM_quadrature_points (2,4)%p(7:12) = permutationStar21([0.06308901449150_pReal]) + FEM_quadrature_points (2,4)%p(13:24)= permutationStar111([0.31035245103378_pReal, 0.63650249912140_pReal]) !-------------------------------------------------------------------------------------------------- ! 2D quintic - FEM_Zoo_nQuadrature(2,5) = 16 + FEM_nQuadrature(2,5) = 16 - allocate(FEM_Zoo_QuadratureWeights(2,5)%p(16)) - FEM_Zoo_QuadratureWeights(2,5)%p(1 ) = 0.14431560767779_pReal - FEM_Zoo_QuadratureWeights(2,5)%p(2:4) = 0.09509163426728_pReal - FEM_Zoo_QuadratureWeights(2,5)%p(5:7) = 0.10321737053472_pReal - FEM_Zoo_QuadratureWeights(2,5)%p(8:10) = 0.03245849762320_pReal - FEM_Zoo_QuadratureWeights(2,5)%p(11:16)= 0.02723031417443_pReal + allocate(FEM_quadrature_weights(2,5)%p(16)) + FEM_quadrature_weights(2,5)%p(1 ) = 0.14431560767779_pReal + FEM_quadrature_weights(2,5)%p(2:4) = 0.09509163426728_pReal + FEM_quadrature_weights(2,5)%p(5:7) = 0.10321737053472_pReal + FEM_quadrature_weights(2,5)%p(8:10) = 0.03245849762320_pReal + FEM_quadrature_weights(2,5)%p(11:16)= 0.02723031417443_pReal - allocate(FEM_Zoo_QuadraturePoints (2,5)%p(32)) - FEM_Zoo_QuadraturePoints (2,5)%p(1:2) = FEM_Zoo_permutationStar3([0.33333333333333_pReal]) - FEM_Zoo_QuadraturePoints (2,5)%p(3:8) = FEM_Zoo_permutationStar21([0.45929258829272_pReal]) - FEM_Zoo_QuadraturePoints (2,5)%p(9:14) = FEM_Zoo_permutationStar21([0.17056930775176_pReal]) - FEM_Zoo_QuadraturePoints (2,5)%p(15:20)= FEM_Zoo_permutationStar21([0.05054722831703_pReal]) - FEM_Zoo_QuadraturePoints (2,5)%p(21:32)=FEM_Zoo_permutationStar111([0.26311282963464_pReal, 0.72849239295540_pReal]) + allocate(FEM_quadrature_points (2,5)%p(32)) + FEM_quadrature_points (2,5)%p(1:2) = permutationStar3([0.33333333333333_pReal]) + FEM_quadrature_points (2,5)%p(3:8) = permutationStar21([0.45929258829272_pReal]) + FEM_quadrature_points (2,5)%p(9:14) = permutationStar21([0.17056930775176_pReal]) + FEM_quadrature_points (2,5)%p(15:20)= permutationStar21([0.05054722831703_pReal]) + FEM_quadrature_points (2,5)%p(21:32)= permutationStar111([0.26311282963464_pReal, 0.72849239295540_pReal]) !-------------------------------------------------------------------------------------------------- ! 3D linear - FEM_Zoo_nQuadrature(3,1) = 1 + FEM_nQuadrature(3,1) = 1 - allocate(FEM_Zoo_QuadratureWeights(3,1)%p(1)) - FEM_Zoo_QuadratureWeights(3,1)%p(1) = 1.0_pReal + allocate(FEM_quadrature_weights(3,1)%p(1)) + FEM_quadrature_weights(3,1)%p(1) = 1.0_pReal + + allocate(FEM_quadrature_points (3,1)%p(3)) + FEM_quadrature_points (3,1)%p(1:3)= permutationStar4([0.25_pReal]) - allocate(FEM_Zoo_QuadraturePoints (3,1)%p(3)) - FEM_Zoo_QuadraturePoints (3,1)%p(1:3)= FEM_Zoo_permutationStar4([0.25_pReal]) - !-------------------------------------------------------------------------------------------------- ! 3D quadratic - FEM_Zoo_nQuadrature(3,2) = 4 + FEM_nQuadrature(3,2) = 4 - allocate(FEM_Zoo_QuadratureWeights(3,2)%p(4)) - FEM_Zoo_QuadratureWeights(3,2)%p(1:4) = 0.25_pReal + allocate(FEM_quadrature_weights(3,2)%p(4)) + FEM_quadrature_weights(3,2)%p(1:4) = 0.25_pReal + + allocate(FEM_quadrature_points (3,2)%p(12)) + FEM_quadrature_points (3,2)%p(1:12)= permutationStar31([0.13819660112501051518_pReal]) - allocate(FEM_Zoo_QuadraturePoints (3,2)%p(12)) - FEM_Zoo_QuadraturePoints (3,2)%p(1:12)= FEM_Zoo_permutationStar31([0.13819660112501051518_pReal]) - !-------------------------------------------------------------------------------------------------- ! 3D cubic - FEM_Zoo_nQuadrature(3,3) = 14 + FEM_nQuadrature(3,3) = 14 - allocate(FEM_Zoo_QuadratureWeights(3,3)%p(14)) - FEM_Zoo_QuadratureWeights(3,3)%p(5:8) = 0.11268792571801585080_pReal - FEM_Zoo_QuadratureWeights(3,3)%p(1:4) = 0.073493043116361949544_pReal - FEM_Zoo_QuadratureWeights(3,3)%p(9:14) = 0.042546020777081466438_pReal + allocate(FEM_quadrature_weights(3,3)%p(14)) + FEM_quadrature_weights(3,3)%p(5:8) = 0.11268792571801585080_pReal + FEM_quadrature_weights(3,3)%p(1:4) = 0.073493043116361949544_pReal + FEM_quadrature_weights(3,3)%p(9:14) = 0.042546020777081466438_pReal - allocate(FEM_Zoo_QuadraturePoints (3,3)%p(42)) - FEM_Zoo_QuadraturePoints (3,3)%p(1:12) = FEM_Zoo_permutationStar31([0.092735250310891226402_pReal]) - FEM_Zoo_QuadraturePoints (3,3)%p(13:24)= FEM_Zoo_permutationStar31([0.31088591926330060980_pReal]) - FEM_Zoo_QuadraturePoints (3,3)%p(25:42)= FEM_Zoo_permutationStar22([0.045503704125649649492_pReal]) + allocate(FEM_quadrature_points (3,3)%p(42)) + FEM_quadrature_points (3,3)%p(1:12) = permutationStar31([0.092735250310891226402_pReal]) + FEM_quadrature_points (3,3)%p(13:24)= permutationStar31([0.31088591926330060980_pReal]) + FEM_quadrature_points (3,3)%p(25:42)= permutationStar22([0.045503704125649649492_pReal]) !-------------------------------------------------------------------------------------------------- ! 3D quartic - FEM_Zoo_nQuadrature(3,4) = 35 + FEM_nQuadrature(3,4) = 35 - allocate(FEM_Zoo_QuadratureWeights(3,4)%p(35)) - FEM_Zoo_QuadratureWeights(3,4)%p(1:4) = 0.0021900463965388_pReal - FEM_Zoo_QuadratureWeights(3,4)%p(5:16) = 0.0143395670177665_pReal - FEM_Zoo_QuadratureWeights(3,4)%p(17:22) = 0.0250305395686746_pReal - FEM_Zoo_QuadratureWeights(3,4)%p(23:34) = 0.0479839333057554_pReal - FEM_Zoo_QuadratureWeights(3,4)%p(35) = 0.0931745731195340_pReal + allocate(FEM_quadrature_weights(3,4)%p(35)) + FEM_quadrature_weights(3,4)%p(1:4) = 0.0021900463965388_pReal + FEM_quadrature_weights(3,4)%p(5:16) = 0.0143395670177665_pReal + FEM_quadrature_weights(3,4)%p(17:22) = 0.0250305395686746_pReal + FEM_quadrature_weights(3,4)%p(23:34) = 0.0479839333057554_pReal + FEM_quadrature_weights(3,4)%p(35) = 0.0931745731195340_pReal - allocate(FEM_Zoo_QuadraturePoints (3,4)%p(105)) - FEM_Zoo_QuadraturePoints (3,4)%p(1:12) = FEM_Zoo_permutationStar31([0.0267367755543735_pReal]) - FEM_Zoo_QuadraturePoints (3,4)%p(13:48) = FEM_Zoo_permutationStar211([0.0391022406356488_pReal, 0.7477598884818090_pReal]) - FEM_Zoo_QuadraturePoints (3,4)%p(49:66) = FEM_Zoo_permutationStar22([0.4547545999844830_pReal]) - FEM_Zoo_QuadraturePoints (3,4)%p(67:102) = FEM_Zoo_permutationStar211([0.2232010379623150_pReal, 0.0504792790607720_pReal]) - FEM_Zoo_QuadraturePoints (3,4)%p(103:105)= FEM_Zoo_permutationStar4([0.25_pReal]) + allocate(FEM_quadrature_points (3,4)%p(105)) + FEM_quadrature_points (3,4)%p(1:12) = permutationStar31([0.0267367755543735_pReal]) + FEM_quadrature_points (3,4)%p(13:48) = permutationStar211([0.0391022406356488_pReal, 0.7477598884818090_pReal]) + FEM_quadrature_points (3,4)%p(49:66) = permutationStar22([0.4547545999844830_pReal]) + FEM_quadrature_points (3,4)%p(67:102) = permutationStar211([0.2232010379623150_pReal, 0.0504792790607720_pReal]) + FEM_quadrature_points (3,4)%p(103:105)= permutationStar4([0.25_pReal]) !-------------------------------------------------------------------------------------------------- ! 3D quintic - FEM_Zoo_nQuadrature(3,5) = 56 + FEM_nQuadrature(3,5) = 56 - allocate(FEM_Zoo_QuadratureWeights(3,5)%p(56)) - FEM_Zoo_QuadratureWeights(3,5)%p(1:4) = 0.0010373112336140_pReal - FEM_Zoo_QuadratureWeights(3,5)%p(5:16) = 0.0096016645399480_pReal - FEM_Zoo_QuadratureWeights(3,5)%p(17:28) = 0.0164493976798232_pReal - FEM_Zoo_QuadratureWeights(3,5)%p(29:40) = 0.0153747766513310_pReal - FEM_Zoo_QuadratureWeights(3,5)%p(41:52) = 0.0293520118375230_pReal - FEM_Zoo_QuadratureWeights(3,5)%p(53:56) = 0.0366291366405108_pReal + allocate(FEM_quadrature_weights(3,5)%p(56)) + FEM_quadrature_weights(3,5)%p(1:4) = 0.0010373112336140_pReal + FEM_quadrature_weights(3,5)%p(5:16) = 0.0096016645399480_pReal + FEM_quadrature_weights(3,5)%p(17:28) = 0.0164493976798232_pReal + FEM_quadrature_weights(3,5)%p(29:40) = 0.0153747766513310_pReal + FEM_quadrature_weights(3,5)%p(41:52) = 0.0293520118375230_pReal + FEM_quadrature_weights(3,5)%p(53:56) = 0.0366291366405108_pReal - allocate(FEM_Zoo_QuadraturePoints (3,5)%p(168)) - FEM_Zoo_QuadraturePoints (3,5)%p(1:12) = FEM_Zoo_permutationStar31([0.0149520651530592_pReal]) - FEM_Zoo_QuadraturePoints (3,5)%p(13:48) = FEM_Zoo_permutationStar211([0.0340960211962615_pReal, 0.1518319491659370_pReal]) - FEM_Zoo_QuadraturePoints (3,5)%p(49:84) = FEM_Zoo_permutationStar211([0.0462051504150017_pReal, 0.3549340560639790_pReal]) - FEM_Zoo_QuadraturePoints (3,5)%p(85:120) = FEM_Zoo_permutationStar211([0.2281904610687610_pReal, 0.0055147549744775_pReal]) - FEM_Zoo_QuadraturePoints (3,5)%p(121:156)= FEM_Zoo_permutationStar211([0.3523052600879940_pReal, 0.0992057202494530_pReal]) - FEM_Zoo_QuadraturePoints (3,5)%p(157:168)= FEM_Zoo_permutationStar31([0.1344783347929940_pReal]) + allocate(FEM_quadrature_points (3,5)%p(168)) + FEM_quadrature_points (3,5)%p(1:12) = permutationStar31([0.0149520651530592_pReal]) + FEM_quadrature_points (3,5)%p(13:48) = permutationStar211([0.0340960211962615_pReal, 0.1518319491659370_pReal]) + FEM_quadrature_points (3,5)%p(49:84) = permutationStar211([0.0462051504150017_pReal, 0.3549340560639790_pReal]) + FEM_quadrature_points (3,5)%p(85:120) = permutationStar211([0.2281904610687610_pReal, 0.0055147549744775_pReal]) + FEM_quadrature_points (3,5)%p(121:156)= permutationStar211([0.3523052600879940_pReal, 0.0992057202494530_pReal]) + FEM_quadrature_points (3,5)%p(157:168)= permutationStar31([0.1344783347929940_pReal]) -end subroutine FEM_Zoo_init +end subroutine FEM_quadrature_init !-------------------------------------------------------------------------------------------------- -!> @brief star 3 permutation of input +!> @brief star 3 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar3(point) result(qPt) +pure function permutationStar3(point) result(qPt) real(pReal), dimension(2) :: qPt real(pReal), dimension(1), intent(in) :: point real(pReal), dimension(3,1) :: temp - + temp(:,1) = [point(1), point(1), point(1)] - + qPt = reshape(matmul(triangle, temp),[2]) - -end function FEM_Zoo_permutationStar3 + +end function permutationStar3 !-------------------------------------------------------------------------------------------------- -!> @brief star 21 permutation of input +!> @brief star 21 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar21(point) result(qPt) +pure function permutationStar21(point) result(qPt) real(pReal), dimension(6) :: qPt real(pReal), dimension(1), intent(in) :: point real(pReal), dimension(3,3) :: temp - + temp(:,1) = [point(1), point(1), 1.0_pReal - 2.0_pReal*point(1)] temp(:,2) = [point(1), 1.0_pReal - 2.0_pReal*point(1), point(1)] temp(:,3) = [1.0_pReal - 2.0_pReal*point(1), point(1), point(1)] - + qPt = reshape(matmul(triangle, temp),[6]) - -end function FEM_Zoo_permutationStar21 + +end function permutationStar21 !-------------------------------------------------------------------------------------------------- -!> @brief star 111 permutation of input +!> @brief star 111 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar111(point) result(qPt) +pure function permutationStar111(point) result(qPt) real(pReal), dimension(12) :: qPt real(pReal), dimension(2), intent(in) :: point real(pReal), dimension(3,6) :: temp - + temp(:,1) = [point(1), point(2), 1.0_pReal - point(1) - point(2)] temp(:,2) = [point(1), 1.0_pReal - point(1) - point(2), point(2)] temp(:,4) = [point(2), 1.0_pReal - point(1) - point(2), point(1)] @@ -231,57 +231,57 @@ pure function FEM_Zoo_permutationStar111(point) result(qPt) temp(:,6) = [1.0_pReal - point(1) - point(2), point(1), point(2)] qPt = reshape(matmul(triangle, temp),[12]) - -end function FEM_Zoo_permutationStar111 + +end function permutationStar111 !-------------------------------------------------------------------------------------------------- -!> @brief star 4 permutation of input +!> @brief star 4 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar4(point) result(qPt) +pure function permutationStar4(point) result(qPt) real(pReal), dimension(3) :: qPt real(pReal), dimension(1), intent(in) :: point real(pReal), dimension(4,1) :: temp - + temp(:,1) = [point(1), point(1), point(1), point(1)] - + qPt = reshape(matmul(tetrahedron, temp),[3]) - -end function FEM_Zoo_permutationStar4 + +end function permutationStar4 !-------------------------------------------------------------------------------------------------- -!> @brief star 31 permutation of input +!> @brief star 31 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar31(point) result(qPt) +pure function permutationStar31(point) result(qPt) real(pReal), dimension(12) :: qPt real(pReal), dimension(1), intent(in) :: point real(pReal), dimension(4,4) :: temp - + temp(:,1) = [point(1), point(1), point(1), 1.0_pReal - 3.0_pReal*point(1)] temp(:,2) = [point(1), point(1), 1.0_pReal - 3.0_pReal*point(1), point(1)] temp(:,3) = [point(1), 1.0_pReal - 3.0_pReal*point(1), point(1), point(1)] temp(:,4) = [1.0_pReal - 3.0_pReal*point(1), point(1), point(1), point(1)] - + qPt = reshape(matmul(tetrahedron, temp),[12]) - -end function FEM_Zoo_permutationStar31 + +end function permutationStar31 !-------------------------------------------------------------------------------------------------- -!> @brief star 22 permutation of input +!> @brief star 22 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar22(point) result(qPt) +pure function permutationStar22(point) result(qPt) real(pReal), dimension(18) :: qPt real(pReal), dimension(1), intent(in) :: point real(pReal), dimension(4,6) :: temp - + temp(:,1) = [point(1), point(1), 0.5_pReal - point(1), 0.5_pReal - point(1)] temp(:,2) = [point(1), 0.5_pReal - point(1), point(1), 0.5_pReal - point(1)] temp(:,3) = [0.5_pReal - point(1), point(1), point(1), 0.5_pReal - point(1)] @@ -290,20 +290,20 @@ pure function FEM_Zoo_permutationStar22(point) result(qPt) temp(:,6) = [point(1), 0.5_pReal - point(1), 0.5_pReal - point(1), point(1)] qPt = reshape(matmul(tetrahedron, temp),[18]) - -end function FEM_Zoo_permutationStar22 + +end function permutationStar22 !-------------------------------------------------------------------------------------------------- -!> @brief star 211 permutation of input +!> @brief star 211 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar211(point) result(qPt) +pure function permutationStar211(point) result(qPt) real(pReal), dimension(36) :: qPt real(pReal), dimension(2), intent(in) :: point real(pReal), dimension(4,12) :: temp - + temp(:,1 ) = [point(1), point(1), point(2), 1.0_pReal - 2.0_pReal*point(1) - point(2)] temp(:,2 ) = [point(1), point(1), 1.0_pReal - 2.0_pReal*point(1) - point(2), point(2)] temp(:,3 ) = [point(1), point(2), point(1), 1.0_pReal - 2.0_pReal*point(1) - point(2)] @@ -316,22 +316,22 @@ pure function FEM_Zoo_permutationStar211(point) result(qPt) temp(:,10) = [1.0_pReal - 2.0_pReal*point(1) - point(2), point(1), point(1), point(2)] temp(:,11) = [1.0_pReal - 2.0_pReal*point(1) - point(2), point(1), point(2), point(1)] temp(:,12) = [1.0_pReal - 2.0_pReal*point(1) - point(2), point(2), point(1), point(1)] - + qPt = reshape(matmul(tetrahedron, temp),[36]) - -end function FEM_Zoo_permutationStar211 + +end function permutationStar211 !-------------------------------------------------------------------------------------------------- -!> @brief star 1111 permutation of input +!> @brief star 1111 permutation of input !-------------------------------------------------------------------------------------------------- -pure function FEM_Zoo_permutationStar1111(point) result(qPt) +pure function permutationStar1111(point) result(qPt) real(pReal), dimension(72) :: qPt real(pReal), dimension(3), intent(in) :: point real(pReal), dimension(4,24) :: temp - + temp(:,1 ) = [point(1), point(2), point(3), 1.0_pReal - point(1) - point(2)- point(3)] temp(:,2 ) = [point(1), point(2), 1.0_pReal - point(1) - point(2)- point(3), point(3)] temp(:,3 ) = [point(1), point(3), point(2), 1.0_pReal - point(1) - point(2)- point(3)] @@ -356,9 +356,9 @@ pure function FEM_Zoo_permutationStar1111(point) result(qPt) temp(:,22) = [1.0_pReal - point(1) - point(2)- point(3), point(2), point(3), point(1)] temp(:,23) = [1.0_pReal - point(1) - point(2)- point(3), point(3), point(1), point(2)] temp(:,24) = [1.0_pReal - point(1) - point(2)- point(3), point(3), point(2), point(1)] - - qPt = reshape(matmul(tetrahedron, temp),[72]) - -end function FEM_Zoo_permutationStar1111 -end module FEM_Zoo + qPt = reshape(matmul(tetrahedron, temp),[72]) + +end function permutationStar1111 + +end module FEM_quadrature diff --git a/src/mesh/FEM_utilities.f90 b/src/mesh/FEM_utilities.f90 index d21450b29..512d741bf 100644 --- a/src/mesh/FEM_utilities.f90 +++ b/src/mesh/FEM_utilities.f90 @@ -17,7 +17,7 @@ module FEM_utilities use numerics use debug use math - use mesh + use discretization_mesh implicit none private @@ -37,15 +37,15 @@ module FEM_utilities character(len=*), parameter, public :: & FIELD_MECH_label = 'mechanical' - enum, bind(c) - enumerator :: FIELD_UNDEFINED_ID, & - FIELD_MECH_ID + enum, bind(c); enumerator :: & + FIELD_UNDEFINED_ID, & + FIELD_MECH_ID end enum - enum, bind(c) - enumerator :: COMPONENT_UNDEFINED_ID, & - COMPONENT_MECH_X_ID, & - COMPONENT_MECH_Y_ID, & - COMPONENT_MECH_Z_ID + enum, bind(c); enumerator :: & + COMPONENT_UNDEFINED_ID, & + COMPONENT_MECH_X_ID, & + COMPONENT_MECH_Y_ID, & + COMPONENT_MECH_Z_ID end enum !-------------------------------------------------------------------------------------------------- @@ -117,7 +117,13 @@ subroutine utilities_init CHKERRQ(ierr) if(debugPETSc) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(PETSCDEBUG),ierr) CHKERRQ(ierr) - call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(petsc_defaultOptions),ierr) + call PetscOptionsInsertString(PETSC_NULL_OPTIONS,'-mech_snes_type newtonls & + &-mech_snes_linesearch_type cp -mech_snes_ksp_ew & + &-mech_snes_ksp_ew_rtol0 0.01 -mech_snes_ksp_ew_rtolmax 0.01 & + &-mech_ksp_type fgmres -mech_ksp_max_it 25 & + &-mech_pc_type ml -mech_mg_levels_ksp_type chebyshev & + &-mech_mg_levels_pc_type sor -mech_pc_ml_nullspace user',ierr) + CHKERRQ(ierr) call PetscOptionsInsertString(PETSC_NULL_OPTIONS,trim(petsc_options),ierr) CHKERRQ(ierr) write(petsc_optionsOrder,'(a,i0)') '-mechFE_petscspace_degree ', structOrder @@ -129,6 +135,7 @@ subroutine utilities_init end subroutine utilities_init + !-------------------------------------------------------------------------------------------------- !> @brief calculates constitutive response !-------------------------------------------------------------------------------------------------- diff --git a/src/mesh_FEM.f90 b/src/mesh/discretization_mesh.f90 similarity index 96% rename from src/mesh_FEM.f90 rename to src/mesh/discretization_mesh.f90 index 9b278e45b..072f3b4ec 100644 --- a/src/mesh_FEM.f90 +++ b/src/mesh/discretization_mesh.f90 @@ -4,7 +4,7 @@ !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @author Franz Roters, Max-Planck-Institut für Eisenforschung GmbH !-------------------------------------------------------------------------------------------------- -module mesh +module discretization_mesh #include #include #include @@ -18,7 +18,7 @@ module mesh use discretization use numerics use FEsolving - use FEM_Zoo + use FEM_quadrature use prec implicit none @@ -52,7 +52,7 @@ module mesh mesh_boundaries public :: & - mesh_init, & + discretization_mesh_init, & mesh_FEM_build_ipVolumes, & mesh_FEM_build_ipCoordinates @@ -63,7 +63,7 @@ contains !> @brief initializes the mesh by calling all necessary private routines the mesh module !! Order and routines strongly depend on type of solver !-------------------------------------------------------------------------------------------------- -subroutine mesh_init +subroutine discretization_mesh_init integer, dimension(1), parameter:: FE_geomtype = [1] !< geometry type of particular element type integer, dimension(1) :: FE_Nips !< number of IPs in a specific type of element @@ -152,11 +152,11 @@ subroutine mesh_init call DMGetStratumSize(geomMesh,'depth',0,mesh_Nnodes,ierr) CHKERRQ(ierr) - FE_Nips(FE_geomtype(1)) = FEM_Zoo_nQuadrature(dimPlex,integrationOrder) + FE_Nips(FE_geomtype(1)) = FEM_nQuadrature(dimPlex,integrationOrder) mesh_maxNips = FE_Nips(1) write(6,*) 'mesh_maxNips',mesh_maxNips - call mesh_FEM_build_ipCoordinates(dimPlex,FEM_Zoo_QuadraturePoints(dimPlex,integrationOrder)%p) + call mesh_FEM_build_ipCoordinates(dimPlex,FEM_quadrature_points(dimPlex,integrationOrder)%p) call mesh_FEM_build_ipVolumes(dimPlex) allocate (mesh_element (4,mesh_NcpElems)); mesh_element = 0 @@ -182,7 +182,7 @@ subroutine mesh_init reshape(mesh_ipCoordinates,[3,mesh_maxNips*mesh_NcpElems]), & mesh_node0) -end subroutine mesh_init +end subroutine discretization_mesh_init !-------------------------------------------------------------------------------------------------- @@ -248,4 +248,4 @@ subroutine mesh_FEM_build_ipCoordinates(dimPlex,qPoints) end subroutine mesh_FEM_build_ipCoordinates -end module mesh +end module discretization_mesh diff --git a/src/mesh/FEM_mech.f90 b/src/mesh/mesh_mech_FEM.f90 similarity index 99% rename from src/mesh/FEM_mech.f90 rename to src/mesh/mesh_mech_FEM.f90 index 3af19e1f6..8206f4174 100644 --- a/src/mesh/FEM_mech.f90 +++ b/src/mesh/mesh_mech_FEM.f90 @@ -4,7 +4,7 @@ !> @author Philip Eisenlohr, Max-Planck-Institut für Eisenforschung GmbH !> @brief FEM PETSc solver !-------------------------------------------------------------------------------------------------- -module FEM_mech +module mesh_mech_FEM #include #include #include @@ -16,11 +16,11 @@ module FEM_mech use prec use FEM_utilities - use mesh + use discretization_mesh use IO use DAMASK_interface use numerics - use FEM_Zoo + use FEM_quadrature use FEsolving use homogenization use math @@ -105,10 +105,10 @@ subroutine FEM_mech_init(fieldBC) !-------------------------------------------------------------------------------------------------- ! Setup FEM mech discretization - qPoints = FEM_Zoo_QuadraturePoints(dimPlex,integrationOrder)%p - qWeights = FEM_Zoo_QuadratureWeights(dimPlex,integrationOrder)%p - nQuadrature = FEM_Zoo_nQuadrature(dimPlex,integrationOrder) - qPointsP => qPoints + qPoints = FEM_quadrature_points( dimPlex,integrationOrder)%p + qWeights = FEM_quadrature_weights(dimPlex,integrationOrder)%p + nQuadrature = FEM_nQuadrature( dimPlex,integrationOrder) + qPointsP => qPoints qWeightsP => qWeights call PetscQuadratureCreate(PETSC_COMM_SELF,mechQuad,ierr); CHKERRQ(ierr) CHKERRQ(ierr) @@ -670,4 +670,4 @@ subroutine FEM_mech_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dumm end subroutine FEM_mech_converged -end module FEM_mech +end module mesh_mech_FEM diff --git a/src/numerics.f90 b/src/numerics.f90 index 61297ff6f..a29601322 100644 --- a/src/numerics.f90 +++ b/src/numerics.f90 @@ -17,36 +17,19 @@ module numerics private integer, protected, public :: & - iJacoStiffness = 1, & !< frequency of stiffness update - nMPstate = 10, & !< materialpoint state loop limit - randomSeed = 0, & !< fixed seeding for pseudo-random number generator, Default 0: use random seed - worldrank = 0, & !< MPI worldrank (/=0 for MPI simulations only) - worldsize = 1, & !< MPI worldsize (/=1 for MPI simulations only) - numerics_integrator = 1 !< method used for state integration Default 1: fix-point iteration + iJacoStiffness = 1, & !< frequency of stiffness update + randomSeed = 0, & !< fixed seeding for pseudo-random number generator, Default 0: use random seed + worldrank = 0, & !< MPI worldrank (/=0 for MPI simulations only) + worldsize = 1, & !< MPI worldsize (/=1 for MPI simulations only) + numerics_integrator = 1 !< method used for state integration Default 1: fix-point iteration integer(4), protected, public :: & DAMASK_NumThreadsInt = 0 !< value stored in environment variable DAMASK_NUM_THREADS, set to zero if no OpenMP directive real(pReal), protected, public :: & defgradTolerance = 1.0e-7_pReal, & !< deviation of deformation gradient that is still allowed (used by CPFEM to determine outdated ffn1) - subStepMinHomog = 1.0e-3_pReal, & !< minimum (relative) size of sub-step allowed during cutback in homogenization - subStepSizeHomog = 0.25_pReal, & !< size of first substep when cutback in homogenization - stepIncreaseHomog = 1.5_pReal, & !< increase of next substep size when previous substep converged in homogenization numerics_unitlength = 1.0_pReal, & !< determines the physical length of one computational length unit - absTol_RGC = 1.0e+4_pReal, & !< absolute tolerance of RGC residuum - relTol_RGC = 1.0e-3_pReal, & !< relative tolerance of RGC residuum - absMax_RGC = 1.0e+10_pReal, & !< absolute maximum of RGC residuum - relMax_RGC = 1.0e+2_pReal, & !< relative maximum of RGC residuum - pPert_RGC = 1.0e-7_pReal, & !< perturbation for computing RGC penalty tangent - xSmoo_RGC = 1.0e-5_pReal, & !< RGC penalty smoothing parameter (hyperbolic tangent) - viscPower_RGC = 1.0e+0_pReal, & !< power (sensitivity rate) of numerical viscosity in RGC scheme, Default 1.0e0: Newton viscosity (linear model) - viscModus_RGC = 0.0e+0_pReal, & !< stress modulus of RGC numerical viscosity, Default 0.0e0: No viscosity is applied - refRelaxRate_RGC = 1.0e-3_pReal, & !< reference relaxation rate in RGC viscosity - maxdRelax_RGC = 1.0e+0_pReal, & !< threshold of maximum relaxation vector increment (if exceed this then cutback) - maxVolDiscr_RGC = 1.0e-5_pReal, & !< threshold of maximum volume discrepancy allowed - volDiscrMod_RGC = 1.0e+12_pReal, & !< stiffness of RGC volume discrepancy (zero = without volume discrepancy constraint) - volDiscrPow_RGC = 5.0_pReal, & !< powerlaw penalty for volume discrepancy charLength = 1.0_pReal, & !< characteristic length scale for gradient problems - residualStiffness = 1.0e-6_pReal !< non-zero residual damage - logical, protected, public :: & + residualStiffness = 1.0e-6_pReal !< non-zero residual damage + logical, protected, public :: & usePingPong = .true. !-------------------------------------------------------------------------------------------------- @@ -74,9 +57,8 @@ module numerics err_curl_tolRel = 5.0e-4_pReal, & !< relative tolerance for compatibility err_stress_tolAbs = 1.0e3_pReal, & !< absolute tolerance for fullfillment of stress BC err_stress_tolRel = 0.01_pReal, & !< relative tolerance for fullfillment of stress BC - rotation_tol = 1.0e-12_pReal, & !< tolerance of rotation specified in loadcase, Default 1.0e-12: first guess - polarAlpha = 1.0_pReal, & !< polarization scheme parameter 0.0 < alpha < 2.0. alpha = 1.0 ==> AL scheme, alpha = 2.0 ==> accelerated scheme - polarBeta = 1.0_pReal !< polarization scheme parameter 0.0 < beta < 2.0. beta = 1.0 ==> AL scheme, beta = 2.0 ==> accelerated scheme + polarAlpha = 1.0_pReal, & !< polarization scheme parameter 0.0 < alpha < 2.0. alpha = 1.0 ==> AL scheme, alpha = 2.0 ==> accelerated scheme + polarBeta = 1.0_pReal !< polarization scheme parameter 0.0 < beta < 2.0. beta = 1.0 ==> AL scheme, beta = 2.0 ==> accelerated scheme character(len=pStringLen), protected, public :: & petsc_options = '' #endif @@ -87,26 +69,14 @@ module numerics integer, protected, public :: & integrationOrder = 2, & !< order of quadrature rule required structOrder = 2 !< order of displacement shape functions - logical, protected, public :: & - BBarStabilisation = .false. - character(len=*), parameter, public :: & - petsc_defaultOptions = '-mech_snes_type newtonls & - &-mech_snes_linesearch_type cp & - &-mech_snes_ksp_ew & - &-mech_snes_ksp_ew_rtol0 0.01 & - &-mech_snes_ksp_ew_rtolmax 0.01 & - &-mech_ksp_type fgmres & - &-mech_ksp_max_it 25 & - &-mech_pc_type ml & - &-mech_mg_levels_ksp_type chebyshev & - &-mech_mg_levels_pc_type sor & - &-mech_pc_ml_nullspace user' + logical, protected, public :: & + BBarStabilisation = .false. character(len=pStringLen), protected, public :: & petsc_options = '' #endif public :: numerics_init - + contains @@ -130,7 +100,7 @@ subroutine numerics_init call MPI_Comm_size(PETSC_COMM_WORLD,worldsize,ierr);CHKERRQ(ierr) #endif write(6,'(/,a)') ' <<<+- numerics init -+>>>' - + !$ call GET_ENVIRONMENT_VARIABLE(NAME='DAMASK_NUM_THREADS',VALUE=DAMASK_NumThreadsString,STATUS=gotDAMASK_NUM_THREADS) ! get environment variable DAMASK_NUM_THREADS... !$ if(gotDAMASK_NUM_THREADS /= 0) then ! could not get number of threads, set it to 1 !$ call IO_warning(35,ext_msg='BEGIN:'//DAMASK_NumThreadsString//':END') @@ -140,15 +110,15 @@ subroutine numerics_init !$ if (DAMASK_NumThreadsInt < 1_4) DAMASK_NumThreadsInt = 1_4 ! in case of string conversion fails, set it to one !$ endif !$ call omp_set_num_threads(DAMASK_NumThreadsInt) ! set number of threads for parallel execution - + inquire(file='numerics.config', exist=fexist) - + fileExists: if (fexist) then write(6,'(a,/)') ' using values from config file' flush(6) - fileContent = IO_read_ASCII('numerics.config') + fileContent = IO_read_ASCII('numerics.config') do j=1, size(fileContent) - + !-------------------------------------------------------------------------------------------------- ! read variables from config file and overwrite default parameters if keyword is present line = fileContent(j) @@ -164,14 +134,6 @@ subroutine numerics_init defgradTolerance = IO_floatValue(line,chunkPos,2) case ('ijacostiffness') iJacoStiffness = IO_intValue(line,chunkPos,2) - case ('nmpstate') - nMPstate = IO_intValue(line,chunkPos,2) - case ('substepminhomog') - subStepMinHomog = IO_floatValue(line,chunkPos,2) - case ('substepsizehomog') - subStepSizeHomog = IO_floatValue(line,chunkPos,2) - case ('stepincreasehomog') - stepIncreaseHomog = IO_floatValue(line,chunkPos,2) case ('integrator') numerics_integrator = IO_intValue(line,chunkPos,2) case ('usepingpong') @@ -179,35 +141,6 @@ subroutine numerics_init case ('unitlength') numerics_unitlength = IO_floatValue(line,chunkPos,2) -!-------------------------------------------------------------------------------------------------- -! RGC parameters - case ('atol_rgc') - absTol_RGC = IO_floatValue(line,chunkPos,2) - case ('rtol_rgc') - relTol_RGC = IO_floatValue(line,chunkPos,2) - case ('amax_rgc') - absMax_RGC = IO_floatValue(line,chunkPos,2) - case ('rmax_rgc') - relMax_RGC = IO_floatValue(line,chunkPos,2) - case ('perturbpenalty_rgc') - pPert_RGC = IO_floatValue(line,chunkPos,2) - case ('relevantmismatch_rgc') - xSmoo_RGC = IO_floatValue(line,chunkPos,2) - case ('viscositypower_rgc') - viscPower_RGC = IO_floatValue(line,chunkPos,2) - case ('viscositymodulus_rgc') - viscModus_RGC = IO_floatValue(line,chunkPos,2) - case ('refrelaxationrate_rgc') - refRelaxRate_RGC = IO_floatValue(line,chunkPos,2) - case ('maxrelaxation_rgc') - maxdRelax_RGC = IO_floatValue(line,chunkPos,2) - case ('maxvoldiscrepancy_rgc') - maxVolDiscr_RGC = IO_floatValue(line,chunkPos,2) - case ('voldiscrepancymod_rgc') - volDiscrMod_RGC = IO_floatValue(line,chunkPos,2) - case ('discrepancypower_rgc') - volDiscrPow_RGC = IO_floatValue(line,chunkPos,2) - !-------------------------------------------------------------------------------------------------- ! random seeding parameter case ('random_seed','fixed_seed') @@ -280,8 +213,6 @@ subroutine numerics_init #endif end select enddo - - else fileExists write(6,'(a,/)') ' using standard values' flush(6) @@ -296,26 +227,6 @@ subroutine numerics_init write(6,'(a24,1x,L8)') ' use ping pong scheme: ',usepingpong write(6,'(a24,1x,es8.1,/)')' unitlength: ',numerics_unitlength - write(6,'(a24,1x,es8.1)') ' subStepMinHomog: ',subStepMinHomog - write(6,'(a24,1x,es8.1)') ' subStepSizeHomog: ',subStepSizeHomog - write(6,'(a24,1x,es8.1)') ' stepIncreaseHomog: ',stepIncreaseHomog - write(6,'(a24,1x,i8,/)') ' nMPstate: ',nMPstate - -!-------------------------------------------------------------------------------------------------- -! RGC parameters - write(6,'(a24,1x,es8.1)') ' aTol_RGC: ',absTol_RGC - write(6,'(a24,1x,es8.1)') ' rTol_RGC: ',relTol_RGC - write(6,'(a24,1x,es8.1)') ' aMax_RGC: ',absMax_RGC - write(6,'(a24,1x,es8.1)') ' rMax_RGC: ',relMax_RGC - write(6,'(a24,1x,es8.1)') ' perturbPenalty_RGC: ',pPert_RGC - write(6,'(a24,1x,es8.1)') ' relevantMismatch_RGC: ',xSmoo_RGC - write(6,'(a24,1x,es8.1)') ' viscosityrate_RGC: ',viscPower_RGC - write(6,'(a24,1x,es8.1)') ' viscositymodulus_RGC: ',viscModus_RGC - write(6,'(a24,1x,es8.1)') ' maxrelaxation_RGC: ',maxdRelax_RGC - write(6,'(a24,1x,es8.1)') ' maxVolDiscrepancy_RGC: ',maxVolDiscr_RGC - write(6,'(a24,1x,es8.1)') ' volDiscrepancyMod_RGC: ',volDiscrMod_RGC - write(6,'(a24,1x,es8.1,/)') ' discrepancyPower_RGC: ',volDiscrPow_RGC - !-------------------------------------------------------------------------------------------------- ! Random seeding parameter write(6,'(a16,1x,i16,/)') ' random_seed: ',randomSeed @@ -363,35 +274,17 @@ subroutine numerics_init #ifdef FEM write(6,'(a24,1x,i8)') ' integrationOrder: ',integrationOrder write(6,'(a24,1x,i8)') ' structOrder: ',structOrder - write(6,'(a24,1x,a)') ' PETSc_options: ',trim(petsc_defaultOptions)//' '//trim(petsc_options) + write(6,'(a24,1x,a)') ' PETSc_options: ',trim(petsc_options) write(6,'(a24,1x,L8)') ' B-Bar stabilisation: ',BBarStabilisation #endif - !-------------------------------------------------------------------------------------------------- ! sanity checks if (defgradTolerance <= 0.0_pReal) call IO_error(301,ext_msg='defgradTolerance') if (iJacoStiffness < 1) call IO_error(301,ext_msg='iJacoStiffness') - if (nMPstate < 1) call IO_error(301,ext_msg='nMPstate') - if (subStepMinHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepMinHomog') - if (subStepSizeHomog <= 0.0_pReal) call IO_error(301,ext_msg='subStepSizeHomog') - if (stepIncreaseHomog <= 0.0_pReal) call IO_error(301,ext_msg='stepIncreaseHomog') if (numerics_integrator <= 0 .or. numerics_integrator >= 6) & call IO_error(301,ext_msg='integrator') if (numerics_unitlength <= 0.0_pReal) call IO_error(301,ext_msg='unitlength') - if (absTol_RGC <= 0.0_pReal) call IO_error(301,ext_msg='absTol_RGC') - if (relTol_RGC <= 0.0_pReal) call IO_error(301,ext_msg='relTol_RGC') - if (absMax_RGC <= 0.0_pReal) call IO_error(301,ext_msg='absMax_RGC') - if (relMax_RGC <= 0.0_pReal) call IO_error(301,ext_msg='relMax_RGC') - if (pPert_RGC <= 0.0_pReal) call IO_error(301,ext_msg='pPert_RGC') - if (xSmoo_RGC <= 0.0_pReal) call IO_error(301,ext_msg='xSmoo_RGC') - if (viscPower_RGC < 0.0_pReal) call IO_error(301,ext_msg='viscPower_RGC') - if (viscModus_RGC < 0.0_pReal) call IO_error(301,ext_msg='viscModus_RGC') - if (refRelaxRate_RGC <= 0.0_pReal) call IO_error(301,ext_msg='refRelaxRate_RGC') - if (maxdRelax_RGC <= 0.0_pReal) call IO_error(301,ext_msg='maxdRelax_RGC') - if (maxVolDiscr_RGC <= 0.0_pReal) call IO_error(301,ext_msg='maxVolDiscr_RGC') - if (volDiscrMod_RGC < 0.0_pReal) call IO_error(301,ext_msg='volDiscrMod_RGC') - if (volDiscrPow_RGC <= 0.0_pReal) call IO_error(301,ext_msg='volDiscrPw_RGC') if (residualStiffness < 0.0_pReal) call IO_error(301,ext_msg='residualStiffness') if (itmax <= 1) call IO_error(301,ext_msg='itmax') if (itmin > itmax .or. itmin < 1) call IO_error(301,ext_msg='itmin') diff --git a/src/prec.f90 b/src/prec.f90 index 8ced9813a..b3e2c2747 100644 --- a/src/prec.f90 +++ b/src/prec.f90 @@ -42,7 +42,7 @@ module prec 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 real(pReal), pointer, dimension(:), contiguous :: & - atolState + atol 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 state0, & state, & !< state @@ -241,7 +241,7 @@ end function cNeq !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of (some) prec functions +!> @brief check correctness of some prec functions !-------------------------------------------------------------------------------------------------- subroutine unitTest diff --git a/src/quaternions.f90 b/src/quaternions.f90 index 4e40ecc4e..8d62fe6aa 100644 --- a/src/quaternions.f90 +++ b/src/quaternions.f90 @@ -455,7 +455,7 @@ end function inverse !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of (some) quaternions functions +!> @brief check correctness of some quaternions functions !-------------------------------------------------------------------------------------------------- subroutine unitTest diff --git a/src/rotations.f90 b/src/rotations.f90 index c1fb1f2cf..7ce366f74 100644 --- a/src/rotations.f90 +++ b/src/rotations.f90 @@ -1222,7 +1222,7 @@ end function cu2ho !-------------------------------------------------------------------------------------------------- -!> @brief check correctness of (some) rotations functions +!> @brief check correctness of some rotations functions !-------------------------------------------------------------------------------------------------- subroutine unitTest diff --git a/src/source_damage_anisoBrittle.f90 b/src/source_damage_anisoBrittle.f90 index 91c90adc2..3978be959 100644 --- a/src/source_damage_anisoBrittle.f90 +++ b/src/source_damage_anisoBrittle.f90 @@ -24,18 +24,15 @@ module source_damage_anisoBrittle type :: tParameters !< container type for internal constitutive parameters real(pReal) :: & - aTol, & sdot_0, & - N + n real(pReal), dimension(:), allocatable :: & critDisp, & critLoad real(pReal), dimension(:,:,:,:), allocatable :: & cleavage_systems integer :: & - totalNcleavage - integer, dimension(:), allocatable :: & - Ncleavage + sum_N_cl character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -58,7 +55,8 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_damage_anisoBrittle_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p + integer, dimension(:), allocatable :: N_cl character(len=pStringLen) :: extmsg = '' write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISOBRITTLE_LABEL//' init -+>>>'; flush(6) @@ -84,44 +82,42 @@ subroutine source_damage_anisoBrittle_init associate(prm => param(source_damage_anisoBrittle_instance(p)), & config => config_phase(p)) - prm%Ncleavage = config%getInts('ncleavage',defaultVal=emptyIntArray) - prm%totalNcleavage = sum(prm%Ncleavage) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - prm%aTol = config%getFloat('anisobrittle_atol',defaultVal = 1.0e-3_pReal) - prm%N = config%getFloat('anisobrittle_ratesensitivity') + N_cl = config%getInts('ncleavage',defaultVal=emptyIntArray) + prm%sum_N_cl = sum(abs(N_cl)) + + prm%n = config%getFloat('anisobrittle_ratesensitivity') prm%sdot_0 = config%getFloat('anisobrittle_sdot0') - prm%critDisp = config%getFloats('anisobrittle_criticaldisplacement',requiredSize=size(prm%Ncleavage)) - prm%critLoad = config%getFloats('anisobrittle_criticalload', requiredSize=size(prm%Ncleavage)) + prm%critDisp = config%getFloats('anisobrittle_criticaldisplacement',requiredSize=size(N_cl)) + prm%critLoad = config%getFloats('anisobrittle_criticalload', requiredSize=size(N_cl)) - prm%cleavage_systems = lattice_SchmidMatrix_cleavage(prm%Ncleavage,config%getString('lattice_structure'),& + prm%cleavage_systems = lattice_SchmidMatrix_cleavage(N_cl,config%getString('lattice_structure'),& config%getFloat('c/a',defaultVal=0.0_pReal)) ! expand: family => system - prm%critDisp = math_expand(prm%critDisp, prm%Ncleavage) - prm%critLoad = math_expand(prm%critLoad, prm%Ncleavage) + prm%critDisp = math_expand(prm%critDisp,N_cl) + prm%critLoad = math_expand(prm%critLoad,N_cl) ! sanity checks - if (prm%aTol < 0.0_pReal) extmsg = trim(extmsg)//' anisobrittle_atol' - if (prm%N <= 0.0_pReal) extmsg = trim(extmsg)//' anisobrittle_n' + if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' anisobrittle_n' if (prm%sdot_0 <= 0.0_pReal) extmsg = trim(extmsg)//' anisobrittle_sdot0' if (any(prm%critLoad < 0.0_pReal)) extmsg = trim(extmsg)//' anisobrittle_critLoad' if (any(prm%critDisp < 0.0_pReal)) extmsg = trim(extmsg)//' anisobrittle_critDisp' + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,1,1,0) + sourceState(p)%p(sourceOffset)%atol = config%getFloat('anisobrittle_atol',defaultVal=1.0e-3_pReal) + if(any(sourceState(p)%p(sourceOffset)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' anisobrittle_atol' + + end associate + !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ANISOBRITTLE_LABEL//')') -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - - NofMyPhase = count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,1,1,0) - sourceState(p)%p(sourceOffset)%aTolState=prm%aTol - - end associate - enddo +enddo end subroutine source_damage_anisoBrittle_init @@ -156,21 +152,19 @@ subroutine source_damage_anisoBrittle_dotState(S, ipc, ip, el) associate(prm => param(source_damage_anisoBrittle_instance(phase))) sourceState(phase)%p(sourceOffset)%dotState(1,constituent) = 0.0_pReal - do i = 1, prm%totalNcleavage - - traction_d = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,1,i)) - traction_t = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,2,i)) - traction_n = math_mul33xx33(S,prm%cleavage_systems(1:3,1:3,3,i)) + do i = 1, prm%sum_N_cl + traction_d = math_tensordot(S,prm%cleavage_systems(1:3,1:3,1,i)) + traction_t = math_tensordot(S,prm%cleavage_systems(1:3,1:3,2,i)) + traction_n = math_tensordot(S,prm%cleavage_systems(1:3,1:3,3,i)) traction_crit = prm%critLoad(i)*damage(homog)%p(damageOffset)**2.0_pReal sourceState(phase)%p(sourceOffset)%dotState(1,constituent) & = sourceState(phase)%p(sourceOffset)%dotState(1,constituent) & + prm%sdot_0 / prm%critDisp(i) & - * ((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**prm%N + & - (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**prm%N + & - (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**prm%N) - + * ((max(0.0_pReal, abs(traction_d) - traction_crit)/traction_crit)**prm%n + & + (max(0.0_pReal, abs(traction_t) - traction_crit)/traction_crit)**prm%n + & + (max(0.0_pReal, abs(traction_n) - traction_crit)/traction_crit)**prm%n) enddo end associate diff --git a/src/source_damage_anisoDuctile.f90 b/src/source_damage_anisoDuctile.f90 index 4dd18dac0..2b818e2cf 100644 --- a/src/source_damage_anisoDuctile.f90 +++ b/src/source_damage_anisoDuctile.f90 @@ -23,14 +23,9 @@ module source_damage_anisoDuctile type, private :: tParameters !< container type for internal constitutive parameters real(pReal) :: & - aTol, & - N + n real(pReal), dimension(:), allocatable :: & critPlasticStrain - integer :: & - totalNslip - integer, dimension(:), allocatable :: & - Nslip character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -53,7 +48,8 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_damage_anisoDuctile_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p + integer, dimension(:), allocatable :: N_sl character(len=pStringLen) :: extmsg = '' write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ANISODUCTILE_LABEL//' init -+>>>'; flush(6) @@ -79,36 +75,31 @@ subroutine source_damage_anisoDuctile_init associate(prm => param(source_damage_anisoDuctile_instance(p)), & config => config_phase(p)) - prm%Nslip = config%getInts('nslip',defaultVal=emptyIntArray) - prm%totalNslip = sum(prm%Nslip) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - prm%aTol = config%getFloat('anisoductile_atol',defaultVal = 1.0e-3_pReal) - prm%N = config%getFloat('anisoductile_ratesensitivity') - - prm%critPlasticStrain = config%getFloats('anisoductile_criticalplasticstrain',requiredSize=size(prm%Nslip)) + N_sl = config%getInts('nslip',defaultVal=emptyIntArray) + prm%n = config%getFloat('anisoductile_ratesensitivity') + prm%critPlasticStrain = config%getFloats('anisoductile_criticalplasticstrain',requiredSize=size(N_sl)) ! expand: family => system - prm%critPlasticStrain = math_expand(prm%critPlasticStrain, prm%Nslip) + prm%critPlasticStrain = math_expand(prm%critPlasticStrain,N_sl) ! sanity checks - if (prm%aTol < 0.0_pReal) extmsg = trim(extmsg)//' anisoductile_atol' - if (prm%N <= 0.0_pReal) extmsg = trim(extmsg)//' anisoductile_ratesensitivity' + if (prm%n <= 0.0_pReal) extmsg = trim(extmsg)//' anisoductile_ratesensitivity' if (any(prm%critPlasticStrain < 0.0_pReal)) extmsg = trim(extmsg)//' anisoductile_criticalplasticstrain' + NipcMyPhase=count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,1,1,0) + sourceState(p)%p(sourceOffset)%atol = config%getFloat('anisoductile_atol',defaultVal=1.0e-3_pReal) + if(any(sourceState(p)%p(sourceOffset)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' anisoductile_atol' + + end associate + !-------------------------------------------------------------------------------------------------- ! exit if any parameter is out of range - if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ANISODUCTILE_LABEL//')') + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ANISODUCTILE_LABEL//')') -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - - NofMyPhase=count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,1,1,0) - sourceState(p)%p(sourceOffset)%aTolState=prm%aTol - - end associate - enddo +enddo end subroutine source_damage_anisoDuctile_init @@ -128,8 +119,7 @@ subroutine source_damage_anisoDuctile_dotState(ipc, ip, el) constituent, & sourceOffset, & damageOffset, & - homog, & - i + homog phase = material_phaseAt(ipc,el) constituent = material_phasememberAt(ipc,ip,el) @@ -138,11 +128,8 @@ subroutine source_damage_anisoDuctile_dotState(ipc, ip, el) damageOffset = damageMapping(homog)%p(ip,el) associate(prm => param(source_damage_anisoDuctile_instance(phase))) - do i = 1, prm%totalNslip - sourceState(phase)%p(sourceOffset)%dotState(1,constituent) & - = sourceState(phase)%p(sourceOffset)%dotState(1,constituent) & - + plasticState(phase)%slipRate(i,constituent)/(damage(homog)%p(damageOffset)**prm%N)/prm%critPlasticStrain(i) - enddo + sourceState(phase)%p(sourceOffset)%dotState(1,constituent) & + = sum(plasticState(phase)%slipRate(:,constituent)/(damage(homog)%p(damageOffset)**prm%n)/prm%critPlasticStrain) end associate end subroutine source_damage_anisoDuctile_dotState diff --git a/src/source_damage_isoBrittle.f90 b/src/source_damage_isoBrittle.f90 index 8856dc4e0..ed6d89a89 100644 --- a/src/source_damage_isoBrittle.f90 +++ b/src/source_damage_isoBrittle.f90 @@ -24,8 +24,7 @@ module source_damage_isoBrittle type, private :: tParameters !< container type for internal constitutive parameters real(pReal) :: & critStrainEnergy, & - N, & - aTol + N character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -48,7 +47,7 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_damage_isoBrittle_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p character(len=pStringLen) :: extmsg = '' write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ISOBRITTLE_LABEL//' init -+>>>'; flush(6) @@ -74,30 +73,27 @@ subroutine source_damage_isoBrittle_init associate(prm => param(source_damage_isoBrittle_instance(p)), & config => config_phase(p)) - prm%aTol = config%getFloat('isobrittle_atol',defaultVal = 1.0e-3_pReal) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + prm%N = config%getFloat('isobrittle_n') prm%critStrainEnergy = config%getFloat('isobrittle_criticalstrainenergy') ! sanity checks - if (prm%aTol < 0.0_pReal) extmsg = trim(extmsg)//' isobrittle_atol' if (prm%N <= 0.0_pReal) extmsg = trim(extmsg)//' isobrittle_n' if (prm%critStrainEnergy <= 0.0_pReal) extmsg = trim(extmsg)//' isobrittle_criticalstrainenergy' -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ISOBRITTLE_LABEL//')') - -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - - NofMyPhase = count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,1,1,1) - sourceState(p)%p(sourceOffset)%aTolState=prm%aTol + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,1,1,1) + sourceState(p)%p(sourceOffset)%atol = config%getFloat('isobrittle_atol',defaultVal=1.0e-3_pReal) + if(any(sourceState(p)%p(sourceOffset)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' isobrittle_atol' end associate - enddo + +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ISOBRITTLE_LABEL//')') + +enddo end subroutine source_damage_isoBrittle_init diff --git a/src/source_damage_isoDuctile.f90 b/src/source_damage_isoDuctile.f90 index 2f7389592..7024e595a 100644 --- a/src/source_damage_isoDuctile.f90 +++ b/src/source_damage_isoDuctile.f90 @@ -23,8 +23,7 @@ module source_damage_isoDuctile type, private :: tParameters !< container type for internal constitutive parameters real(pReal) :: & critPlasticStrain, & - N, & - aTol + N character(len=pStringLen), allocatable, dimension(:) :: & output end type tParameters @@ -47,7 +46,7 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_damage_isoDuctile_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p character(len=pStringLen) :: extmsg = '' write(6,'(/,a)') ' <<<+- source_'//SOURCE_DAMAGE_ISODUCTILE_LABEL//' init -+>>>'; flush(6) @@ -73,30 +72,27 @@ subroutine source_damage_isoDuctile_init associate(prm => param(source_damage_isoDuctile_instance(p)), & config => config_phase(p)) - prm%aTol = config%getFloat('isoductile_atol',defaultVal = 1.0e-3_pReal) + prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) + prm%N = config%getFloat('isoductile_ratesensitivity') prm%critPlasticStrain = config%getFloat('isoductile_criticalplasticstrain') ! sanity checks - if (prm%aTol < 0.0_pReal) extmsg = trim(extmsg)//' isoductile_atol' if (prm%N <= 0.0_pReal) extmsg = trim(extmsg)//' isoductile_ratesensitivity' if (prm%critPlasticStrain <= 0.0_pReal) extmsg = trim(extmsg)//' isoductile_criticalplasticstrain' -!-------------------------------------------------------------------------------------------------- -! exit if any parameter is out of range - if (extmsg /= '') & - call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ISODUCTILE_LABEL//')') - -!-------------------------------------------------------------------------------------------------- -! output pararameters - prm%output = config%getStrings('(output)',defaultVal=emptyStringArray) - - NofMyPhase=count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,1,1,0) - sourceState(p)%p(sourceOffset)%aTolState=prm%aTol + NipcMyPhase=count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,1,1,0) + sourceState(p)%p(sourceOffset)%atol = config%getFloat('isoductile_atol',defaultVal=1.0e-3_pReal) + if(any(sourceState(p)%p(sourceOffset)%atol < 0.0_pReal)) extmsg = trim(extmsg)//' isoductile_atol' end associate - enddo + +!-------------------------------------------------------------------------------------------------- +! exit if any parameter is out of range + if (extmsg /= '') call IO_error(211,ext_msg=trim(extmsg)//'('//SOURCE_DAMAGE_ISODUCTILE_LABEL//')') + +enddo end subroutine source_damage_isoDuctile_init diff --git a/src/source_thermal_dissipation.f90 b/src/source_thermal_dissipation.f90 index c03d66c24..521c79077 100644 --- a/src/source_thermal_dissipation.f90 +++ b/src/source_thermal_dissipation.f90 @@ -39,7 +39,7 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_thermal_dissipation_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_dissipation_label//' init -+>>>'; flush(6) @@ -66,8 +66,8 @@ subroutine source_thermal_dissipation_init prm%kappa = config%getFloat('dissipation_coldworkcoeff') - NofMyPhase = count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,0,0,0) + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,0,0,0) end associate enddo diff --git a/src/source_thermal_externalheat.f90 b/src/source_thermal_externalheat.f90 index 6cb8cdf6e..ade13bef2 100644 --- a/src/source_thermal_externalheat.f90 +++ b/src/source_thermal_externalheat.f90 @@ -43,7 +43,7 @@ contains !-------------------------------------------------------------------------------------------------- subroutine source_thermal_externalheat_init - integer :: Ninstance,sourceOffset,NofMyPhase,p + integer :: Ninstance,sourceOffset,NipcMyPhase,p write(6,'(/,a)') ' <<<+- source_'//SOURCE_thermal_externalheat_label//' init -+>>>'; flush(6) @@ -73,8 +73,8 @@ subroutine source_thermal_externalheat_init prm%heat_rate = config%getFloats('externalheat_rate',requiredSize = size(prm%time)) - NofMyPhase = count(material_phaseAt==p) * discretization_nIP - call material_allocateSourceState(p,sourceOffset,NofMyPhase,1,1,0) + NipcMyPhase = count(material_phaseAt==p) * discretization_nIP + call material_allocateSourceState(p,sourceOffset,NipcMyPhase,1,1,0) end associate enddo