


limit growth rate so that hC-vector remains valid
Syntax: growthRateMatrix = limitGrowthRate(growthRateMatrix, ...
positionMatrix, dec, distanceLimit, zerotol)
During growth, hC vectors must be prevented that are outside the valid
cone. The first reason is that disappeared facets must retain touching
the crystal shape. Simulation results would be invalid when such a
facet reappears. The second reason is that measures cannot be
calculated for invalid vectors. However, this could be prevented by
mapping of the hC-vectors for the task of measure calculation.
The input distanceLimit gives a maximal distance of a facet from its
limiting vertex before the growth rate of that facet is adopted. This
implies also that the growth rate is limited to zero growth at a size
that approximately corresponds to the distanceLimit. Hence,
disappearing crystals should be selected based on a pure-zero growth
rate if the growth rate was not pure-zero beforehand.
See also: obtainDec, mapToValidCone, solvePopulationBalance

0001 function growthRateMatrixNew = limitGrowthRate(growthRateMatrix, ... 0002 positionMatrix, partitionVector, dec, distanceLimit) 0003 % limit growth rate so that hC-vector remains valid 0004 % 0005 % Syntax: growthRateMatrix = limitGrowthRate(growthRateMatrix, ... 0006 % positionMatrix, dec, distanceLimit, zerotol) 0007 % 0008 % During growth, hC vectors must be prevented that are outside the valid 0009 % cone. The first reason is that disappeared facets must retain touching 0010 % the crystal shape. Simulation results would be invalid when such a 0011 % facet reappears. The second reason is that measures cannot be 0012 % calculated for invalid vectors. However, this could be prevented by 0013 % mapping of the hC-vectors for the task of measure calculation. 0014 % 0015 % The input distanceLimit gives a maximal distance of a facet from its 0016 % limiting vertex before the growth rate of that facet is adopted. This 0017 % implies also that the growth rate is limited to zero growth at a size 0018 % that approximately corresponds to the distanceLimit. Hence, 0019 % disappearing crystals should be selected based on a pure-zero growth 0020 % rate if the growth rate was not pure-zero beforehand. 0021 % 0022 % See also: obtainDec, mapToValidCone, solvePopulationBalance 0023 0024 % The distance from a facet validity boundary A{V,i}*hC equals the distance 0025 % between the facet and the limiting vertex. Thus, selecting a margin 0026 % value for the facet distances of the cone equals a margin distance of 0027 % the facets from the limiting vertices. 0028 0029 %% input handling 0030 if ~exist('distanceLimit', 'var') || isempty(distanceLimit) 0031 distanceLimit = 1e-6; 0032 end 0033 if isempty(growthRateMatrix) 0034 growthRateMatrixNew = growthRateMatrix; 0035 return 0036 end 0037 0038 if ~dec.isComplete 0039 %% INCOMPLETE: no fixing at all 0040 growthRateMatrixNew = growthRateMatrix; 0041 return 0042 0043 elseif dec.isProper 0044 %% PROPER: handled in mapToValidityCone 0045 growthRateMatrixNew = mapToValidityCone(positionMatrix, dec, distanceLimit, ... 0046 growthRateMatrix); 0047 0048 elseif ~dec.isProper && size(growthRateMatrix, 1) > size(positionMatrix, 1) 0049 %% IMPROPER: growth directly im embedding 0050 % use hE-vectors in proper embedding - we don't need to apply validity 0051 % mapping to he-Vectors since the he-vectors are used only to 0052 % determine which facets grow out additionally. 0053 heMatrix = dec.properData.mappingNewToProper * positionMatrix; 0054 % growth rates are already in proper embedding 0055 geMatrix = growthRateMatrix; 0056 % steps follow that are treated per partition: 0057 for thisPartIndex = unique(partitionVector) 0058 % filter affected vectors 0059 thisVectorFilter = partitionVector == thisPartIndex; 0060 if sum(thisVectorFilter) == 0,continue;end 0061 % apply validity mapping when growth violates the constraints given 0062 % by the unified partition 0063 constraintIndexVector = dec.unifiedPartition{thisPartIndex... 0064 }.projection.invalidConstraintIndexVector; 0065 for iCon = 1:length(constraintIndexVector) 0066 thisConIndex = constraintIndexVector(iCon); 0067 applyFilter = thisVectorFilter; 0068 applyFilter(thisVectorFilter) = ... 0069 dec.properData.confinementMappingData.A(thisConIndex,:)*... 0070 geMatrix(:, thisVectorFilter) > 0; 0071 if sum(applyFilter) == 0,continue;end 0072 geMatrix(:, applyFilter) = ... 0073 dec.properData.confinementMappingData.projectionData(... 0074 dec.unifiedPartition{thisPartIndex}.projection.invalidGroupIndexVector(iCon)... 0075 ).projectionList{... 0076 dec.unifiedPartition{thisPartIndex}.projection.projectionIndexVector(iCon)... 0077 } * geMatrix(:, applyFilter); 0078 end 0079 % otherwise, we ensure that the growth vector is consistent with 0080 % the subspace by approximation: 0081 geMatrix(:, thisVectorFilter) = ... 0082 dec.unifiedPartition{thisPartIndex}.projection.orthogonalOntoSubspace*... 0083 geMatrix(:, thisVectorFilter); 0084 0085 % we then apply "normal" growth rate mapping but apply a special 0086 % filter for the constraints to be considered 0087 geMatrix(:, thisVectorFilter) = ... 0088 mapToValidityCone(heMatrix(:, thisVectorFilter), ... 0089 dec.properData, distanceLimit, ... 0090 geMatrix(:, thisVectorFilter), ... 0091 dec.unifiedPartition{thisPartIndex}.projection.applyConstraintFilter); 0092 end 0093 0094 % transform to proper embedding according to known partition 0095 growthRateMatrixNew = mapFromProperEmbedding(geMatrix, dec, ... 0096 [], max(partitionVector,1)); 0097 0098 else 0099 error('elk:pbeSolver:wrongInput', ['Please check the dimensions of ' ... 0100 'the growth rate function output and the position matrix']); 0101 end 0102 end