diff --git a/zUtil_Crack/GtCrackAnalysis.m b/zUtil_Crack/GtCrackAnalysis.m new file mode 100644 index 0000000000000000000000000000000000000000..a6121c16b2a215b360ec3f0be222580a93793eea --- /dev/null +++ b/zUtil_Crack/GtCrackAnalysis.m @@ -0,0 +1,750 @@ +classdef GtCrackAnalysis < handle +% Complete procedure +% - create a new crack analysis: +% >> study = GtCrackAnalysis(); +% +% - load the mesh of the crack +% >> study.loadCrackMesh('crack_mesh.vtk'); +% +% - set the scale factor applied when segmenting the crack (compared to DCT +% voxel size) +% >> study.setScaleFactor(factor); +% +% - load the binary volume of the crack +% >> study.loadCrackVolume('crack_binary_volume.tif'); +% +% - load the grain IDs from the DCT volume +% >> study.loadGrainsVolume('dct.edf'); +% +% - match crack mesh faces with grains ID +% >> study.matchCrackFacesWithGrains(); +% +% - load the Rodigues Vectors of each grain +% >> study.loadRVectors('r_vectors.mat'); +% +% - set the crystal system of each phase +% >> study.setPhasesCrystalSystem({'cubic', 'hexagonal'}); + +% - play with the functions +% >> study.computeNormalSample(); +% >> study.computeNormalCrystal(); +% >> study.computeNormalCrystalSST(); +% >> study.computeSchmidFactors(); + +properties + name; % Name of the study + %N; % Number of cycles + + Nphases; % Number of phases + p_crystalSystem; % Crystal system of each phase + p_symm; % Symmetry operators of each phase + p_grainIDs; % List of grain IDs for each phase + p_faces; % List of grain IDs for each phase + p_slipSystemsFamilies;% List of slip system families of each phase + + binCrack; % Binary volume of the crack + binCrackVoxelSize; % Voxel size of crack binary volume (µm) + binBBox; % BoundingBox of the binary volume of the crack + + dctVol; % DCT volume containing the grain IDs + dctVoxelSize; % Voxel size of DCT volume + r_vectors; % Rodrigues vectors + scaleFactor; % Scale factor between DCT volume and crack volume + + mesh; % Mesh for figures + Nvertices; % Number of vertices + Nfaces; % Number of faces + f_grainID; % Grain ID of each face + f_GB % Faces indices corresponding to Grain Boundaries + + Ngrains; % Number of grains + grainIDs; % List of grain IDs + maxGrainID; % Maximal grain ID + g_phaseID; % Phase related to grain ID + g_orientation; % Orientation matrix g for each grain ID + g_schmidFactors; % Schmid factors for each grains + + norm_samp; % Normal vector for each face in sample CS + norm_cryst; % Normal vector for each face in crystal CS + %norm_cryst_sst; % Normal vector for each face in crystal SST + + facecol_phys; % Face orientation color in sample CS + facecol_cryst; % Face orientation color in crystal CS + facecol_cryst_sst; % Face orientation color in crystal SST + + grainIDColorMap; % Color map for grain ID/label + grainIPFColorMap; % Color map for grain inverse pole figure +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% PUBLIC METHODS +methods (Access = public) + function obj = GtCrackAnalysis() + % GTCRACKANALYSIS/GTCRACKANALYSIS Contructor + obj.name = ''; + + obj.Nphases = 0; + obj.p_crystalSystem = {}; + obj.p_symm = {}; + obj.p_grainIDs = {}; + obj.p_faces = {}; + obj.p_slipSystemsFamilies = {}; + + obj.binCrack = []; + obj.binCrackVoxelSize = 0; + obj.binBBox = []; + + obj.dctVol = []; + obj.dctVoxelSize = 0; + obj.r_vectors = []; + obj.scaleFactor = 0; + + obj.mesh = struct; + obj.Nvertices = 0; + obj.Nfaces = 0; + obj.f_grainID = []; + obj.f_GB = []; + + obj.Ngrains = 0; + obj.grainIDs = []; + obj.maxGrainID = 0; + obj.g_phaseID = []; + obj.g_orientation = {}; + obj.g_schmidFactors = []; + + obj.norm_samp = []; + obj.norm_cryst = []; + %obj.norm_cryst_sst = []; + + obj.facecol_phys = []; + obj.facecol_cryst = []; + obj.facecol_cryst_sst = []; + + obj.grainIDColorMap = []; + obj.grainIPFColorMap = []; + end + + function delete(obj) + % GTCRACKANALYSIS/DELETE Destructor + clear obj; + end + + function loadCrackMesh(obj, filename) + % GTCRACKANALYSIS/LOADCRACKMESH Load the mesh of the crack. + if ~exist('filename', 'var') || isempty(filename) + [f, p] = uigetfile('*', 'Select the file containing the mesh ' ... + of the crack'); + filename = fullfile(f, p); + end + [fpath, fname, fext] = fileparts(filename); + if strcmp(fext, '.vtk') + disp([' Loading crack mesh from ' filename ' ... ']); + obj.mesh = gtVTKMeshReader(filename); + obj.Nvertices = length(obj.mesh.vertices); + obj.Nfaces = length(obj.mesh.faces); + disp([' number of vertices : ' num2str(obj.Nvertices) ]); + disp([' number of faces : ' num2str(obj.Nfaces) ]); + disp(' '); + else + gtError(['Cannot load mesh from ' fext ' file!']); + end + end + + function setScaleFactor(obj, factor) + % GTCRACKANALYSIS/SETUPSCALEFACTOR Set the scale factor applied to the + % initial volume. + if obj.binCrackVoxelSize == 0 + obj.binCrackVoxelSize = inputwdefaultnumeric('Please enter ' ... + 'the voxel size of binary crack volume.', '0.7'); + end + if obj.dctVoxelSize == 0 + obj.dctVoxelSize = inputwdefaultnumeric('Please enter the ' ... + 'voxel size of the DCT volume.', '1.4'); + end + obj.scaleFactor = binCrackVoxelSize/dctVoxelSize; + %obj.scaleFactor = factor; + end + + function loadCrackVolume(obj, filename, voxelSize) + % GTCRACKANALYSIS/LOADCRACKVolume Load the binary volume of the crack. + if ~exist('voxelSize', 'var') || isempty(voxelSize) + voxelSize = 0.7; + disp(['Warning: crack volume voxel size not given, setting it ' ... + 'to default: ' num2str(voxelSize)]); + end + obj.binCrackVoxelSize = voxelSize; + + if ~exist('filename', 'var') || isempty(filename) + [f, p] = uigetfile('*', 'Select the file containing the binary ' ... + 'volume of the crack'); + filename = fullfile(f, p); + end + [fpath, fname, fext] = fileparts(filename); + disp([' Loading crack binary volume from ' filename ' ... ']); + switch fext + case '.edf' + bin = logical(edf_read(filename)); + case {'.tif', '.tiff'} + bin = logical(gtTIFVolReader(filename)); + case {'.raw', '.vol'} + bin = logical(gtHSTVolReader(filename)); + otherwise + gtError('Unsupported type of volume data!'); + end + obj.binCrack = bin; + disp([' size of crack binary volume: ' num2str(size(bin))]); + disp(' '); + + bboxFile = fullfile(fpath, [fname '.bbox']); + disp([' Loading crack binary volume from ' bboxFile ' ... ']); + if exist(bboxFile, 'file') + fid = fopen(bboxFile, 'r'); + obj.binBBox = fscanf(fid, '[%d, %d, %d] [%d, %d, %d]')'; + fclose(fid); + end + disp([' BoundingBox of crack volume: ' num2str(obj.binBBox)]); + disp(' '); + end + + function loadGrainsVolume(obj, volume, voxelSize) + % GTCRACKANALYSIS/LOADGRAINSVOLUME Load the grains volume containing the + % grains ID. + if ~exist('voxelSize', 'var') || isempty(voxelSize) + voxelSize = 1.4; + disp(['Warning: DCT volume voxel size not given, setting it to ' ... + 'default: ' num2str(voxelSize)]); + end + obj.dctVoxelSize = voxelSize; + + %if obj.scaleFactor == 0 + % obj.setScaleFactor(); + %end + if isnumeric(volume) && ndims(volume == 3) + dct = volume; + else + if ~exist('volume', 'var') || isempty(volume) + [f, p] = uigetfile('*', 'Select the file containing the ' ... + 'binary volume of the crack'); + volume = fullfile(f, p); + end + [fpath, fname, fext] = fileparts(volume); + disp([' Loading grains volume from ' volume ' ... ']); + switch fext + case '.edf' + dct = uint16(edf_read(volume)); + case '.tif' + dct = uint16(gtTIFVolReader(volume)); + case {'.raw', '.vol'} + dct = uint16(gtHSTVolReader(volume)); + otherwise + gtError('Unsupported type of volume data!'); + end + end + + if isempty(obj.Nphases) + disp(' Phases not set, please set it!'); + obj.setPhasesCrystalSystem(); + end + + obj.grainIDs = unique(dct)'; + obj.grainIDs = obj.grainIDs(obj.grainIDs>0); + obj.maxGrainID = max(obj.grainIDs); + obj.Ngrains = length(obj.grainIDs); + obj.dctVol = dct; + disp([' Grains volume size : ' num2str(size(obj.dctVol))]); + disp([' Number of grains : ' num2str(obj.Ngrains) ]); + disp([' Number of grain IDs : ' num2str(obj.maxGrainID) ]); + disp(' '); + + % The multi-phase material is not completely managed right now + obj.g_phaseID = ones(1, obj.maxGrainID); + end + + function setPhaseGrainID(obj) + % GTCRACKANALYSIS/SETPHASEGRAINID Set grain IDs of each phases + if isempty(obj.dctVol) + gtCrackAnalysis.loadGrainsVolume(); + end + if isempty(obj.Nphases) + disp(' Phases not set, please set it!'); + obj.setPhasesCrystalSystem(); + end + obj.p_grainIDs = cell(1, obj.Nphases); + for iphase=1:obj.Nphases + obj.p_grainIDs{iphase} = uint16(obj.grainIDs); + end + end + + function matchCrackFacesWithGrains(obj) + % GTCRACKANALYSIS/MATCHCRACKFACESWITHGRAINS Match the crack mesh faces + % with the grains. + if obj.Nvertices == 0 || obj.Nfaces == 0 + gtCrackAnalysis.loadCrackMesh(); + end + if isempty(obj.dctVol) + gtCrackAnalysis.loadGrainsVolume(); + end + + volSize = size(obj.dctVol); + obj.f_grainID = zeros(obj.Nfaces, 1, 'uint16'); + disp([' Grain volume size is: ' num2str(volSize)]); + + p1 = round(obj.mesh.vertices(obj.mesh.faces(:, 1), :) / obj.dctVoxelSize); + p2 = round(obj.mesh.vertices(obj.mesh.faces(:, 2), :) / obj.dctVoxelSize); + p3 = round(obj.mesh.vertices(obj.mesh.faces(:, 3), :) / obj.dctVoxelSize); + + minIndex = ones(obj.Nfaces, 3); + maxIndex = volSize(ones(1, obj.Nfaces), :); + ok = between(p1, minIndex, maxIndex) & ... + between(p2, minIndex, maxIndex) & ... + between(p3, minIndex, maxIndex); + + if any(~ok) + disp(['Problem with ' num2str(sum(~ok)) ' vertices:']); + end + + for iface=1:length(obj.mesh.faces) + if ok(iface) + igrain1 = obj.dctVol(p1(iface, 1), p1(iface, 2), p1(iface, 3)); + igrain2 = obj.dctVol(p2(iface, 1), p2(iface, 2), p2(iface, 3)); + igrain3 = obj.dctVol(p3(iface, 1), p3(iface, 2), p3(iface, 3)); + if igrain1 == igrain2 && igrain1 == igrain3 + obj.f_grainID(iface) = igrain1; + else + % GB labeled as maxGrainID+1 + obj.f_grainID(iface) = obj.maxGrainID + 1; + end + end + end + obj.f_GB = find(obj.f_grainID == obj.maxGrainID+1); + %obj.f_GB = obj.f_grainID == obj.maxGrainID+1; + disp(' '); + end + + function loadRVectors(obj, filename) + % GTCRACKANALYSIS/LOADRVECTORS Load the list of R vectors and compute + % orientation matrices. + if ~exist('filename', 'var') || isempty(filename) + if exist('r_vectors.mat', 'file') + filename = fullfile(pwd, 'r_vectors.mat'); + else + [f, p] = uigetfile('*.mat', 'Select the Matlab file ' ... + 'containing the R vectors'); + filename = fullfile(f, p); + end + end + [fpath, fname, fext] = fileparts(filename); + if isempty(fext) + filename = fullfile(fpath, fname, '.mat'); + end + tmp = load(filename, 'r_vectors'); + obj.r_vectors = tmp.r_vectors(:, 2:4); + + % Might be better to check that grain IDs match with array index... + %if length(obj.r_vectors) ~= obj.maxGrainID + %end + + % Compute orientation matrices g + obj.g_orientation = gtMathsRod2RotMat(obj.r_vectors); + end + + function setPhasesCrystalSystem(obj, crystal_systems) + % GTCRACKANALYSIS/SETPHASESCRYSTALSYSTEM Set the crystal system of each + % phase. + if ~exist('crystal_systems', 'var') || isempty(crystal_systems) + N = inputwdefaultnumeric('Number of phases', '1'); + crystal_systems = cell(1, N); + for iphase=1:N + crystal_systems{iphase} = inputwdefault([... + 'Crystal systems for phase ' num2str(iphase) ''], 'cubic'); + end + elseif ~iscell(crystal_systems) && ischar(crystal_systems) + crystal_systems = {crystal_systems}; + end + obj.Nphases = length(crystal_systems); + + for iphase=1:obj.Nphases + % Get crystal system + try + validatestring(crystal_systems{iphase}, {'cubic', ... + 'hexagonal', 'trigonal'}); + catch Mexc + throw(Mexc); + end + syst = crystal_systems{iphase}; + + % Get symmetry operators + tmp = gtCrystGetSymmetryOperators(syst); + if isfield(tmp, 'g3') + symm{iphase} = {tmp.g3}; + else + symm{iphase} = {tmp.g}; + end + + % Store phase crystal system and symmetry operators + obj.p_crystalSystem{iphase} = syst; + obj.p_symm{iphase} = symm{iphase}; + end + end + + function computeNormalSampleColor(obj) + % GTCRACKANALYSIS/COMPUTENORMALSAMPLE Compute the normal of all faces in + % the sample CS. + if obj.Nvertices == 0 || obj.Nfaces == 0 + gtCrackAnalysis.loadCrackMesh(); + end + %obj.norm_samp = zeros(obj.Nfaces, 3); + p1 = obj.mesh.vertices(obj.mesh.faces(:, 1), :); + p2 = obj.mesh.vertices(obj.mesh.faces(:, 2), :); + p3 = obj.mesh.vertices(obj.mesh.faces(:, 3), :); + %v1 = p1 - p2; + %v2 = p3 - p2; + %n = cross( v1 , v2 ); + %n = cross(p3 - p2, p1 - p2); + n = cross(p1 - p2, p3 - p2); + n_norm = sqrt(sum(n.^2, 2)); + obj.norm_samp = n./n_norm(:, [1 1 1]); + norm_zero = find(n_norm < 1.e-5); + obj.norm_samp(norm_zero, :) = repmat([1 0 0], size(norm_zero, 1) 1]); + + % Get the vector orientation color in sample + rgb = gtVectorOrientationColor(obj.norm_samp); + + % Label GBs in black + obj.facecol_phys = obj.colorGBFaces(rgb); + end + + function computeNormalCrystalColor(obj) + % GTCRACKANALYSIS/COMPUTENORMALCRYST Compute the normal of all faces in + % the crystal CS. + if isempty(obj.norm_samp) + obj.computeNormalSampleColor(); + end + if isempty(obj.r_vectors) + obj.loadRVectors(); + end + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + + obj.norm_cryst = zeros(obj.Nfaces, 3); + for iphase=1:obj.Nphases + for igrain=obj.p_grainIDs{iphase} + g_facesID = find(obj.f_grainID == igrain); + if g_facesID + g = obj.g_orientation{igrain}; + obj.norm_cryst(g_facesID, :) = ... + gtVectorLab2Cryst(obj.norm_samp(g_facesID, :), g); + end + end + end + + %%%%% TEST + % Turn all normals so that they lay in upper half of sphere + %lower_sphere = obj.norm_cryst(:,3) < 0; + %obj.norm_cryst(lower_sphere,:) = -obj.norm_cryst(lower_sphere,:); + %%%%% TEST + + % Get the vector orientation color in crystal + rgb = gtVectorOrientationColor(obj.norm_cryst); + + % Label GBs in black + obj.facecol_cryst = obj.colorGBFaces(rgb); + end + + function computeNormalCrystalSSTColor(obj) + % GTCRACKANALYSIS/COMPUTENORMALCRYSTSST Compute the normal of all faces + % in the crystal CS SST. + if isempty(obj.norm_cryst) + obj.computeNormalCrystalColor(); + end + + obj.facecol_cryst_sst = zeros(obj.Nfaces, 3); + for iphase=1:obj.Nphases + for igrain=obj.p_grainIDs{iphase} + g_facesID = find(obj.f_grainID == igrain); + if length(g_facesID) + obj.facecol_cryst_sst(g_facesID, :) = gtCrystVector2SST(... + obj.norm_cryst(g_facesID, :), ... + obj.p_crystalSystem{iphase}, obj.p_symm{iphase}, false); + %obj.norm_cryst(g_facesID, :), ... + %obj.p_crystalSystem{iphase}, obj.p_symm{iphase}); + end + end + end + end + + function computeSchmidFactors(obj, load) + % GTCRACKANALYSIS/COMPUTESCHMIDFACTORS Compute Schmid factors depending on + % the given load direction. + if isempty(obj.r_vectors) + obj.loadRVectors(); + end + if ~exist('load', 'var') || isempty(load) + load = [0 0 1]; + end + load = load / norm(load); + for iphase=1:obj.Nphases + grainIDs = obj.p_grainIDs{iphase}; + loadCryst = gtVectorLab2Cryst(load, {obj.g_orientation{grainIDs}}); + slipFamilies = obj.p_slipSystemsFamilies{iphase}; + slipSystems = gtGetSlipSystems(slipFamilies); + for ifam=1:length(slipFamilies) + syst = getfield(slipSystems, slipFamilies{ifam}); + schmid = zeros(1, length(syst)); + for igrain=1:obj.maxGrainID + for isyst=1:length(syst) + theta = dot(F, syst(isyst).n'); + kappa = dot(F, syst(isyst).l'); + schmid(isyst) = abs(theta * kappa); + end + end + setfield(obj.g_schmidFactors(iphase), slipFamilies{ifam}, schmid); + end + end + end + + function [hf, ha, hp] = drawCrackEdgesHeight(obj) + % GTCRACKANALYSIS/DRAWCRACKFACESHEIGHT + disp(' Drawing faces height map ...'); + disp(' '); + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + heightColor = squeeze(obj.mesh.vertices(:, 3)); + [hf, ha, hp] = obj.drawCrackEdgesColor(heightColor, 'Name', ... + 'Height of the crack vertices'); + end + + function [hf, ha, hp] = drawCrackGrainLabel(obj) + % GTCRACKANALYSIS/DRAWCRACKGRAINLABEL Draw the crack faces grain ID/label + disp(' Drawing grain label map ...'); + disp(' '); + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + if isempty(obj.grainIDColorMap) + obj.createGrainIDColorMap(); + end + [hf, ha, hp] = obj.drawCrackFacesColor(obj.f_grainID, false, ... + 'Name', 'Grain labels', 'Colormap', obj.grainIDColorMap); + end + + function [hf, ha, hp] = drawCrackGrainIPF(obj) + % GTCRACKANALYSIS/DRAWCRACKGRAINIPF Draw the crack faces grain inverse + % pole figure + disp(' Drawing grain inverse pole figure map ...'); + disp(' '); + if isempty(obj.grainIPFColorMap) + obj.createGrainIPFColorMap(); + end + [hf, ha] = obj.drawCrackFacesColor(obj.f_grainID, false, 'Name', ... + 'Grain inverse pole figure', 'Colormap', obj.grainIPFColorMap); + end + + function [hf, ha, hp] = drawCrackFacesHeight(obj) + % GTCRACKANALYSIS/DRAWCRACKFACESHEIGHT + disp(' Drawing faces height map ...'); + disp(' '); + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + f_height = squeeze(mean(reshape(obj.mesh.vertices(... + obj.mesh.faces(:, :), 3), [obj.Nfaces 3 1]), 2)); + Ncolor = 50; + colorGB = (1-1/Ncolor) * min(f_height) - max(f_height)/Ncolor; + heightColor = obj.colorGBFaces(f_height, colorGB); + cmap = [0 0 0 ; jet(Ncolor)]; + [hf, ha, hp] = obj.drawCrackFacesColor(heightColor, false, ... + 'ColorMap', cmap, ... + 'Name', 'Height of the crack faces'); + set(hp, 'CDataMapping', 'scaled'); + end + + function [hf, ha, hp] = drawCrackFacesOrientationSample(obj) + % GTCRACKANALYSIS/DRAWCRACKFACESORIENTATIONSAMPLE Draw the crack faces + % with the sample orientation color code. + disp(' Drawing faces orientation in sample CS ...'); + disp(' '); + if isempty(obj.facecol_phys) || isempty(obj.norm_samp) + obj.computeNormalSampleColor(); + end + [hf, ha, hp] = obj.drawCrackFacesColor(obj.facecol_phys, false, ... + 'Name', 'Orientation of the crack faces in the sample'); + end + + function [hf, ha, hp] = drawCrackFacesOrientationCrystal(obj) + % GTCRACKANALYSIS/DRAWCRACKFACESORIENTATIONCRYSTAL Draw the crack faces + % with the crystal orientation color code. + disp(' Drawing faces orientation in crystal CS ...'); + disp(' '); + if isempty(obj.facecol_cryst) || isempty(obj.norm_cryst) + obj.computeNormalCrystalColor(); + end + [hf, ha, hp] = obj.drawCrackFacesColor(obj.facecol_cryst, false, ... + 'Name', 'Orientation of the crack faces in the crystal'); + end + + function [hf, ha, hp] = drawCrackFacesOrientationCrystalSST(obj, sat) + % GTCRACKANALYSIS/DRAWCRACKFACESORIENTATIONCRYSTALSST Draw the crack + % faces with the crystal SST orientation color code. + if ~exist('sat', 'var') || isempty(sat) + saturation = true; + end + disp(' Drawing faces orientation in crystal SST ...'); + disp(' '); + if isempty(obj.facecol_cryst_sst) || isempty(obj.norm_cryst) || ... + isempty(obj.norm_cryst) + obj.computeNormalCrystalSSTColor(); + end + [hf, ha, hp] = obj.drawCrackFacesColor(obj.facecol_cryst_sst, sat, ... + 'Name', 'Orientation of the crack faces in the crystal SST'); + end + +end % end of public methods + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% PROTECTED METHODS +methods (Access = protected) + function x = colorGBFaces(obj, x, color) + % GTCRACKANALYSIS/COLORGBFACES Change the color of GB faces to black or + % white. + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + Ncomp = size(x, 2); + if ~exist('color', 'var') || isempty(color) + color = zeros(1, Ncomp); + elseif ~size(color) == [1 Ncomp] + gtError('GtCrackAnalysis:colorGBFaces', ... + 'Wrong RGB color vector size!'); + end + if Ncomp == 1 + x(obj.f_GB) = color(ones(1, size(obj.f_GB, 1))); + elseif Ncomp == 3 + x(obj.f_GB, :) = color(ones(1, size(obj.f_GB, 1)), :); + end + end + + function createGrainIDColorMap(obj) + % GTCRACKANALYSIS/CREATEGRAINIDCOLORMAP Creates a colormap for grain + % labels. + cmap = gtRandCmap(obj.maxGrainID); + cmap(1, :) = [ 1 1 1 ]; + obj.grainIDColorMap = [ cmap ; 0 0 0 ]; + end + + function createGrainIPFColorMap(obj, LD) + % GTCRACKANALYSIS/CREATEGRAINIPFCOLORMAP Creates a colormap for grain + % inverse pole figure for LD direction. + if isempty(obj.f_grainID) + obj.matchCrackFacesWithGrains(); + end + if isempty(obj.r_vectors) + obj.loadRVectors(); + end + if ~exist('LD', 'var') || isempty(LD) + LD = [ 0 0 1 ]; + end + + obj.setPhaseGrainID(); + map = zeros(obj.maxGrainID, 3); + for iphase=1:obj.Nphases + grainIDs = obj.p_grainIDs{iphase}; + LDc = gtVectorLab2Cryst(LD, {obj.g_orientation{grainIDs}}); + map(grainIDs, :) = gtCrystVector2SST(LDc, ... + obj.p_crystalSystem{iphase}, obj.p_symm{iphase}); + end + + obj.grainIPFColorMap = [ 1 1 1 ; map ; 0 0 0 ]; + end + + function [hf, ha, hp] = drawCrackEdgesColor(obj, edgeColor, varargin) + % GTCRACKANALYSIS/DRAWCRACKORIENTATION Draw the crack faces orientation + % with given color. + par.Color = 'w'; + par.ColorMap = []; + par.Name = []; + par = parse_pv_pairs(par, varargin); + + % Create figure + hf = figure(); + ha = axes(); + + % Create a patch from the crack mesh + hp = patch(obj.mesh); + set(hp, 'FaceVertexCData', edgeColor, ... + 'FaceColor', 'interp', ... + 'CDataMapping', 'scaled', ... + 'EdgeColor', 'interp'); + %'LineWidth', 5 ...) + + minColor = min(edgeColor); + maxColor = max(edgeColor); + + shading(ha, 'flat'); + axis equal; + axis vis3d; + set(ha, 'XTickLabel', '', 'YTickLabel', '', 'ZTickLabel', '', ... + 'Xcolor', 'w', 'Ycolor', 'w', 'Zcolor', 'w', ... + 'GridLineStyle', 'none', ... + 'CLim', [minColor maxColor]); + if exist('title', 'var') && ~isempty(title) + set(hf, 'Name', title); + end + + parFields = fieldnames(par); + for i=1:numel(parFields) + val = par.(parFields{i}); + if ~isempty(val) + set(hf, parFields{i}, val); + end + end + end + + function [hf, ha, hp] = drawCrackFacesColor(obj, faceColor, sat, varargin) + % GTCRACKANALYSIS/DRAWCRACKORIENTATION Draw the crack faces orientation + % with given color. + % Set and get figure parameters + par.Color = 'w'; + par.ColorMap = []; + par.Name = []; + par = parse_pv_pairs(par, varargin); + + if sat + ok = any(faceColor ~= 0, 2); + saturated = max(faceColor(ok, :), [], 2); + faceColor(ok, :) = faceColor(ok, :)./saturated(:, [1 1 1]); + end + + % Create figure + hf = figure(); + ha = axes(); + + % Create a patch from the crack mesh + hp = patch(obj.mesh); + set(hp, 'FaceVertexCData', faceColor); + + shading(ha, 'flat'); + axis equal; + axis vis3d; + set(ha, 'XTickLabel', '', 'YTickLabel', '', 'ZTickLabel', '', ... + 'Xcolor', 'w', 'Ycolor', 'w', 'Zcolor', 'w', ... + 'GridLineStyle', 'none'); + if exist('title', 'var') && ~isempty(title) + set(hf, 'Name', title); + end + + parFields = fieldnames(par); + for i=1:numel(parFields) + val = par.(parFields{i}); + if ~isempty(val) + set(hf, parFields{i}, val); + end + end + shg; + end + +end % end of protected methods + +end % end of class diff --git a/zUtil_Cryst/gtGetSlipSystems.m b/zUtil_Cryst/gtGetSlipSystems.m new file mode 100644 index 0000000000000000000000000000000000000000..e51aad2754c8acb29e8df60fa190407bad12d8d0 --- /dev/null +++ b/zUtil_Cryst/gtGetSlipSystems.m @@ -0,0 +1,107 @@ +function slipSystems = gtGetSlipSystems(slipFamilies) +% Based on Z-set slip systems definition + +slipSystems = struct; + +for ifam:1:length(slipFamilies) + switch slipFamilies{ifam} + case {'fcc', 'FCC', 'octahedral'} + + fcc(1).n = [ 1 1 1]; fcc(1).l = [-1 0 1]; % Bd / B4 + fcc(2).n = [ 1 1 1]; fcc(2).l = [ 0 -1 1]; % Ba / B2 + fcc(3).n = [ 1 1 1]; fcc(3).l = [-1 1 0]; % Bc / B5 + + fcc(4).n = [ 1 -1 1]; fcc(4).l = [-1 0 1]; % Db / D4 + fcc(5).n = [ 1 -1 1]; fcc(5).l = [ 0 1 1]; % Dc / D1 + fcc(6).n = [ 1 -1 1]; fcc(6).l = [ 1 1 0]; % Da / D6 + + fcc(7).n = [-1 1 1]; fcc(7).l = [ 0 -1 1]; % Ab / A2 + fcc(8).n = [-1 1 1]; fcc(8).l = [ 1 1 0]; % Ad / A6 + fcc(9).n = [-1 1 1]; fcc(9).l = [ 1 0 1]; % Ac / A3 + + fcc(10).n = [ 1 1 -1]; fcc(10).l = [-1 1 0]; % Cb / C5 + fcc(11).n = [ 1 1 -1]; fcc(11).l = [ 1 0 1]; % Ca / C3 + fcc(12).n = [ 1 1 -1]; fcc(12).l = [ 0 1 1]; % Cd / C1 + + slipSystems.fcc = fcc; + + case {'bcc', 'BCC'} + + bcc(1).n = [-1 0 1]; bcc(1).l = [ 1 1 1]; % Bd / B4 + bcc(2).n = [ 0 -1 1]; bcc(2).l = [ 1 1 1]; % Ba / B2 + bcc(3).n = [-1 1 0]; bcc(3).l = [ 1 1 1]; % Bc / B5 + + bcc(4).n = [-1 0 1]; bcc(4).l = [ 1 -1 1]; % Db / D4 + bcc(5).n = [ 0 1 1]; bcc(5).l = [ 1 -1 1]; % Dc / D1 + bcc(6).n = [ 1 1 0]; bcc(6).l = [ 1 -1 1]; % Da / D6 + + bcc(7).n = [ 0 -1 1]; bcc(7).l = [-1 1 1]; % Ab / A2 + bcc(8).n = [ 1 1 0]; bcc(8).l = [-1 1 1]; % Ad / A6 + bcc(9).n = [ 1 0 1]; bcc(9).l = [-1 1 1]; % Ac / A3 + + bcc(10).n = [-1 1 0]; bcc(10).l = [ 1 1 -1]; % Cb / C5 + bcc(11).n = [ 1 0 1]; bcc(11).l = [ 1 1 -1]; % Ca / C3 + bcc(12).n = [ 0 1 1]; bcc(12).l = [ 1 1 -1]; % Cd / C1 + + slipSystems.bcc = bcc; + + case {'bcc112', 'BCC112'} + + bcc112(1).n = [ 1 1 2]; bcc112(1).l = [ 1 1 -1]; + bcc112(2).n = [-1 1 2]; bcc112(2).l = [ 1 -1 1]; + bcc112(3).n = [ 1 -1 2]; bcc112(3).l = [ -1 1 1]; + + bcc112(4).n = [ 1 1 -2]; bcc112(4).l = [ 1 1 1]; + bcc112(5).n = [ 1 2 1]; bcc112(5).l = [ 1 -1 1]; + bcc112(6).n = [-1 2 1]; bcc112(6).l = [ 1 1 -1]; + + bcc112(7).n = [ 1 -2 1]; bcc112(7).l = [ 1 1 1]; + bcc112(8).n = [ 1 2 -1]; bcc112(8).l = [ -1 1 1]; + bcc112(9).n = [ 2 1 1]; bcc112(9).l = [ -1 1 1]; + + bcc112(10).n = [-2 1 1]; bcc112(10).l = [ 1 1 1]; + bcc112(11).n = [ 2 -1 1]; bcc112(11).l = [ 1 1 -1]; + bcc112(12).n = [ 2 1 -1]; bcc112(12).l = [ 1 -1 1]; + + slipSystems.bcc112 = bcc112; + + case {'bcc123', 'BCC123'} + + bcc123(1).n = [ 1 2 3]; bcc123(1).l = [ 1 1 -1]; + bcc123(2).n = [-1 2 3]; bcc123(2).l = [ 1 -1 1]; + bcc123(3).n = [ 1 -2 3]; bcc123(3).l = [-1 1 1]; + + bcc123(4).n = [ 1 2 -3]; bcc123(4).l = [ 1 1 1]; + bcc123(5).n = [ 3 1 2]; bcc123(5).l = [-1 1 1]; + bcc123(6).n = [-3 1 2]; bcc123(6).l = [ 1 1 1]; + + bcc123(7).n = [ 3 -1 2]; bcc123(7).l = [ 1 1 -1]; + bcc123(8).n = [ 3 1 -2]; bcc123(8).l = [ 1 -1 1]; + bcc123(9).n = [ 2 3 1]; bcc123(9).l = [ 1 -1 1]; + + bcc123(10).n = [-2 3 1]; bcc123(10).l = [ 1 1 -1]; + bcc123(11).n = [ 2 -3 1]; bcc123(11).l = [ 1 1 1]; + bcc123(12).n = [ 2 3 -1]; bcc123(12).l = [-1 1 1]; + + bcc123(13).n = [ 1 3 2]; bcc123(13).l = [ 1 -1 1]; + bcc123(14).n = [-1 3 2]; bcc123(14).l = [ 1 1 -1]; + bcc123(15).n = [ 1 -3 2]; bcc123(15).l = [ 1 1 1]; + + bcc123(16).n = [ 1 3 -2]; bcc123(16).l = [-1 1 1]; + bcc123(17).n = [ 2 1 3]; bcc123(17).l = [ 1 1 -1]; + bcc123(18).n = [-2 1 3]; bcc123(18).l = [ 1 -1 1]; + + bcc123(19).n = [ 2 -1 3]; bcc123(19).l = [-1 1 1]; + bcc123(20).n = [ 2 1 -3]; bcc123(20).l = [ 1 1 1]; + bcc123(21).n = [ 3 2 1]; bcc123(21).l = [-1 1 1]; + + bcc123(22).n = [-3 2 1]; bcc123(22).l = [ 1 1 1]; + bcc123(23).n = [ 3 -2 1]; bcc123(23).l = [ 1 1 -1]; + bcc123(24).n = [ 3 2 -1]; bcc123(24).l = [ 1 -1 1]; + + slipSystems.bcc123 = bcc123; + + otherwise + gtError('gtGetSlipSystems:wrong_input', ... + 'Unsupported slip systems family!'); +end