From 043af529bf316c0f002d14c218f94a3451d25c6d Mon Sep 17 00:00:00 2001 From: Nicholas Ury Date: Fri, 6 Sep 2024 09:19:12 -0700 Subject: [PATCH] set homogenization functions by int ID --- kawin/diffusion/DiffusionParameters.py | 99 ++++++++++++++----- kawin/diffusion/__init__.py | 3 +- .../non_ideal/EffectiveDiffusion.py | 39 +++----- kawin/tests/test_diffusion.py | 21 ++-- kawin/tests/test_plotting.py | 2 +- kawin/tests/test_solver.py | 6 +- 6 files changed, 108 insertions(+), 62 deletions(-) diff --git a/kawin/diffusion/DiffusionParameters.py b/kawin/diffusion/DiffusionParameters.py index 8a2cbe7..8ef66c5 100644 --- a/kawin/diffusion/DiffusionParameters.py +++ b/kawin/diffusion/DiffusionParameters.py @@ -379,9 +379,17 @@ def buildProfile(self, x, z): build_functions[step_info[0]](i, x, z, *step_info[1], **step_info[2]) class TemperatureParameters: - def __init__(self): - self.Tparameters = None - self.Tfunction = None + def __init__(self, *args): + if len(args) == 2: + self.setTemperatureArray(*args) + elif len(args) == 1: + if callable(args[0]): + self.setTemperatureFunction(args[0]) + else: + self.setIsothermalTemperature(args[0]) + else: + self.Tparameters = None + self.Tfunction = None def setIsothermalTemperature(self, T): self.Tparameters = T @@ -399,28 +407,49 @@ def __call__(self, z, t): return self.Tfunction(z, t) class HomogenizationParameters: - def __init__(self): - self.setHomogenizationFunction('wiener upper') - self.labyrinthFactor: float = 1 - self.setPostProcessFunction(None) - self.eps = 0.05 + WIENER_UPPER = 0 + WIENER_LOWER = 1 + HASHIN_UPPER = 2 + HASHIN_LOWER = 3 + LABYRINTH = 4 + + NO_POST = 5 + PREDEFINED = 6 + MAJORITY = 7 + EXCLUDE = 8 + + def __init__(self, + homogenizationFunction = None, + labyrinthFactor = 1, + eps = 0.05, + postProcessFunction = None, + postProcessArgs = None): + if homogenizationFunction is None: + homogenizationFunction = self.WIENER_UPPER + self.setHomogenizationFunction(homogenizationFunction) + + self.labyrinthFactor: float = labyrinthFactor + + if postProcessFunction is None: + postProcessFunction = self.NO_POST + self.setPostProcessFunction(postProcessFunction, postProcessArgs) + self.eps = eps def setPostProcessFunction(self, functionName, functionArgs = None): ''' Returns post process function ''' self.postProcessParameters = [functionArgs] - if functionName is None: + if functionName == self.NO_POST: self.postProcessFunction = _postProcessDoNothing + elif functionName == self.PREDEFINED: + self.postProcessFunction = _postProcessPredefinedMatrixPhase + elif functionName == self.MAJORITY: + self.postProcessFunction = _postProcessMajorityPhase + elif functionName == self.EXCLUDE: + self.postProcessFunction = _postProcessExcludePhases else: - if functionName == 'predefined': - self.postProcessFunction = _postProcessPredefinedMatrixPhase - elif functionName == 'majority': - self.postProcessFunction = _postProcessMajorityPhase - elif functionName == 'exclude': - self.postProcessFunction = _postProcessExcludePhases - else: - raise "Error: post process function should be \'predefined\', \'majority\' or \'exclude\'" + raise Exception("Error: post process function should be \'predefined\', \'majority\' or \'exclude\'") def setHomogenizationFunction(self, function): ''' @@ -433,16 +462,42 @@ def setHomogenizationFunction(self, function): function : str Options - 'upper wiener', 'lower wiener', 'upper hashin-shtrikman', 'lower hashin-strikman', 'labyrinth' ''' - if 'upper' in function and 'wiener' in function: + if isinstance(function, str): + self._setHomogenizationFunctionByStr(function) + else: + self._setHomogenizationFunctionByID(function) + + def _setHomogenizationFunctionByStr(self, function): + keywords_map = { + self.WIENER_UPPER: ['wiener', 'upper'], + self.WIENER_LOWER: ['wiener', 'lower'], + self.HASHIN_UPPER: ['hashin', 'upper'], + self.HASHIN_LOWER: ['hashin', 'lower'], + self.LABYRINTH: ['lab'], + } + for func_id, keywords in keywords_map.items(): + if all([kw in function for kw in keywords]): + self._setHomogenizationFunctionByID(func_id) + + func_types = ['wiener upper', 'wiener lower', 'hashin upper', 'hashin lower', 'labyrinth'] + str_options = ', '.join(func_types) + raise Exception(f'Error: homogenization function by str should be {str_options}') + + def _setHomogenizationFunctionByID(self, function): + if function == self.WIENER_UPPER: self.homogenizationFunction = wienerUpper - elif 'lower' in function and 'wiener' in function: + elif function == self.WIENER_LOWER: self.homogenizationFunction = wienerLower - elif 'upper' in function and 'hashin' in function: + elif function == self.HASHIN_UPPER: self.homogenizationFunction = hashinShtrikmanUpper - elif 'lower' in function and 'hashin' in function: + elif function == self.HASHIN_LOWER: self.homogenizationFunction = hashinShtrikmanLower - elif 'lab' in function: + elif function == self.LABYRINTH: self.homogenizationFunction = labyrinth + else: + func_types = ['WIENER_UPPER', 'WIENER_LOWER', 'HASHIN_UPPER', 'HASHIN_LOWER', 'LABYRINTH'] + int_options = ', '.join([f'HomogenizationParameters.{t}' for t in func_types]) + raise Exception(f'Error: homogenization function by ID should be {int_options}') def setLabyrinthFactor(self, n): ''' diff --git a/kawin/diffusion/__init__.py b/kawin/diffusion/__init__.py index 0623f82..8d3260a 100644 --- a/kawin/diffusion/__init__.py +++ b/kawin/diffusion/__init__.py @@ -1,2 +1,3 @@ from .SinglePhase import SinglePhaseModel -from .Homogenization import HomogenizationModel \ No newline at end of file +from .Homogenization import HomogenizationModel +from .DiffusionParameters import DiffusionParameters, HashTable, CompositionProfile, BoundaryConditions, HomogenizationParameters, TemperatureParameters \ No newline at end of file diff --git a/kawin/precipitation/non_ideal/EffectiveDiffusion.py b/kawin/precipitation/non_ideal/EffectiveDiffusion.py index 0d8d6bc..0547166 100644 --- a/kawin/precipitation/non_ideal/EffectiveDiffusion.py +++ b/kawin/precipitation/non_ideal/EffectiveDiffusion.py @@ -83,31 +83,19 @@ def effectiveDiffusionDistanceApprox(self, supersaturation): ------- Effective diffusion distance (eps) to be used as (eps*R) in the growth rate equation ''' - #Interpolation constant a = 1.2 - - if hasattr(supersaturation, '__len__'): - diff = np.zeros(len(supersaturation)) - indices = (supersaturation >= 0) & (supersaturation < 1) - diff[supersaturation >= 1] = 0 - diff[supersaturation < 0] = 1 - - lam = (1 - supersaturation[indices]**a) * self.lambdaLow(supersaturation[indices]) + (supersaturation[indices]**a) * self.lambdaHigh(supersaturation[indices]) - diff[indices] = supersaturation[indices] / (2 * lam**2) - - return diff - - else: - if supersaturation < 0: - return 1 - - if supersaturation >= 1: - return 0 - - lam = (1 - supersaturation**a) * self.lambdaLow(supersaturation) + (supersaturation**a) * self.lambdaHigh(supersaturation) - return supersaturation / (2 * lam**2) + supersaturation = np.atleast_1d(supersaturation) + diff = np.zeros(len(supersaturation)) + indices = (supersaturation >= 0) & (supersaturation < 1) + diff[supersaturation >= 1] = 0 + diff[supersaturation < 0] = 1 + + lam = (1 - supersaturation[indices]**a) * self.lambdaLow(supersaturation[indices]) + (supersaturation[indices]**a) * self.lambdaHigh(supersaturation[indices]) + diff[indices] = supersaturation[indices] / (2 * lam**2) + + return np.squeeze(diff) def noDiffusionDistance(self, supersaturation): ''' @@ -122,7 +110,6 @@ def noDiffusionDistance(self, supersaturation): ------- 1 or array of 1s ''' - if hasattr(supersaturation, '__len__'): - return np.ones(len(supersaturation), dtype=np.float32) - else: - return 1 \ No newline at end of file + #TODO: this can be more efficient + supersaturation = np.atleast_1d(supersaturation) + return np.squeeze(np.ones(supersaturation.shape), dtype=np.float64) \ No newline at end of file diff --git a/kawin/tests/test_diffusion.py b/kawin/tests/test_diffusion.py index 5ed81fd..e9d8d5f 100644 --- a/kawin/tests/test_diffusion.py +++ b/kawin/tests/test_diffusion.py @@ -1,7 +1,7 @@ from numpy.testing import assert_allclose import numpy as np from kawin.diffusion import SinglePhaseModel, HomogenizationModel -from kawin.diffusion.DiffusionParameters import computeHomogenizationFunction, computeMobility, DiffusionParameters +from kawin.diffusion.DiffusionParameters import computeHomogenizationFunction, computeMobility, DiffusionParameters, HomogenizationParameters from kawin.thermo import GeneralThermodynamics from kawin.tests.datasets import * @@ -134,10 +134,13 @@ def test_homogenizationSinglePhaseMobility(): ternaryParameters.labyrinthFactor = 2 mob_data = computeMobility(NiCrAlTherm, x, T, ternaryParameters) - mob_funcs = ['wiener upper', 'wiener lower', 'hashin upper', 'lab'] + #mob_funcs = ['wiener upper', 'wiener lower', 'hashin upper', 'lab'] + mob_funcs = [HomogenizationParameters.WIENER_UPPER, HomogenizationParameters.WIENER_LOWER, + HomogenizationParameters.HASHIN_UPPER, HomogenizationParameters.HASHIN_LOWER, + HomogenizationParameters.LABYRINTH] for f in mob_funcs: ternaryParameters.hashTable.clearCache() - ternaryParameters.homogenizationParameters.setHomogenizationFunction(mob_funcs) + ternaryParameters.homogenizationParameters.setHomogenizationFunction(f) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x, T, ternaryParameters) assert(np.allclose(np.squeeze(mob), np.squeeze(mob_data.mobility[0]), atol=0, rtol=1e-3)) @@ -178,7 +181,7 @@ def test_homogenization_wiener_upper(): T = 1073 ternaryParameters = DiffusionParameters(['CR', 'AL']) - ternaryParameters.homogenizationParameters.setHomogenizationFunction('wiener upper') + ternaryParameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.WIENER_UPPER) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x1, T, ternaryParameters) assert_allclose(mob, [3.927302e-22, 2.323337e-23, 6.206029e-23], atol=0, rtol=1e-3) @@ -215,7 +218,7 @@ def test_homogenization_wiener_lower(): T = 1073 ternaryParameters = DiffusionParameters(['CR', 'AL']) - ternaryParameters.homogenizationParameters.setHomogenizationFunction('wiener lower') + ternaryParameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.WIENER_LOWER) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x1, T, ternaryParameters) assert_allclose(mob, [3.927302e-22, 2.323337e-23, 6.206029e-23], atol=0, rtol=1e-3) @@ -252,7 +255,7 @@ def test_homogenization_hashin_upper(): T = 1073 ternaryParameters = DiffusionParameters(['CR', 'AL']) - ternaryParameters.homogenizationParameters.setHomogenizationFunction('hashin upper') + ternaryParameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.HASHIN_UPPER) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x1, T, ternaryParameters) assert_allclose(mob, [3.927302e-22, 2.323337e-23, 6.206029e-23], atol=0, rtol=1e-3) @@ -289,7 +292,7 @@ def test_homogenization_hashin_lower(): T = 1073 ternaryParameters = DiffusionParameters(['CR', 'AL']) - ternaryParameters.homogenizationParameters.setHomogenizationFunction('hashin lower') + ternaryParameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.HASHIN_LOWER) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x1, T, ternaryParameters) assert_allclose(mob, [3.927302e-22, 2.323337e-23, 6.206029e-23], atol=0, rtol=1e-3) @@ -326,7 +329,7 @@ def test_homogenization_lab(): T = 1073 ternaryParameters = DiffusionParameters(['CR', 'AL']) - ternaryParameters.homogenizationParameters.setHomogenizationFunction('lab') + ternaryParameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.LABYRINTH) mob, _ = computeHomogenizationFunction(NiCrAlTherm, x1, T, ternaryParameters) assert_allclose(mob, [3.927302e-22, 2.323337e-23, 6.206029e-23], atol=0, rtol=1e-3) @@ -462,7 +465,7 @@ def test_homogenization_dxdt(): m.parameters.maxCompositionChange = 0.002 #m.setMobilityFunction('hashin lower') - m.parameters.homogenizationParameters.setHomogenizationFunction('hashin lower') + m.parameters.homogenizationParameters.setHomogenizationFunction(HomogenizationParameters.HASHIN_LOWER) m.setup() t, x = m.getCurrentX() diff --git a/kawin/tests/test_plotting.py b/kawin/tests/test_plotting.py index 229d66c..02537a0 100644 --- a/kawin/tests/test_plotting.py +++ b/kawin/tests/test_plotting.py @@ -73,7 +73,7 @@ def test_diffusion_plotting(): for m in models: #m[0].setTemperature(900) - m[0].parameters.temperature.set_isothermal_temperature(900) + m[0].parameters.temperature.setIsothermalTemperature(900) #For each plot, check that the number of lines correspond to number of elements or phases #For 'plot', number of lines should be elements (with or without reference) or a single element diff --git a/kawin/tests/test_solver.py b/kawin/tests/test_solver.py index 1ad7fde..b626cb5 100644 --- a/kawin/tests/test_solver.py +++ b/kawin/tests/test_solver.py @@ -104,12 +104,12 @@ def test_coupler_shape(): #Define Cr and Al composition, with step-wise change at z=0 #d_model.setCompositionLinear(0.077, 0.359, 'CR') #d_model.setCompositionLinear(0.054, 0.062, 'AL') - d_model.parameters.composition_profile.add_linear_composition_step('CR', 0.077, 0.359) - d_model.parameters.composition_profile.add_linear_composition_step('AL', 0.054, 0.062) + d_model.parameters.compositionProfile.addLinearCompositionStep('CR', 0.077, 0.359) + d_model.parameters.compositionProfile.addLinearCompositionStep('AL', 0.054, 0.062) d_model.setThermodynamics(NiAlCrTherm) #d_model.setTemperature(1200 + 273.15) - d_model.parameters.temperature.set_isothermal_temperature(1200+273.15) + d_model.parameters.temperature.setIsothermalTemperature(1200+273.15) coupled_model = Coupler([p_model, d_model]) coupled_model.setup()