diff --git a/composite_calculator/lib/calculators/UDFRC_rules_of_mixture_calculator.dart b/composite_calculator/lib/calculators/UDFRC_rules_of_mixture_calculator.dart new file mode 100644 index 0000000..c0daf91 --- /dev/null +++ b/composite_calculator/lib/calculators/UDFRC_rules_of_mixture_calculator.dart @@ -0,0 +1,230 @@ +import 'package:composite_calculator/utils/matrix_to_list_extension.dart'; +import 'package:linalg/matrix.dart'; + +import '../models/UDFRC_rules_of_mixture_input.dart'; +import '../models/UDFRC_rules_of_mixture_output.dart'; +import '../models/analysis_type.dart'; + +class UDFRCRulesOfMixtureCalculator { + static UDFRCRulesOfMixtureOutput calculate(UDFRCRulesOfMixtureInput input) { + double Vf = input.fiberVolumeFraction; + double ef1 = input.E1_fiber; + double ef2 = input.E2_fiber; + double ef3 = ef2; + double gf12 = input.G12_fiber; + double gf13 = gf12; + double gf23 = ef2 / (2 * (1 + input.nu23_fiber)); + double nuf12 = input.nu12_fiber; + double nuf13 = input.nu12_fiber; + double nuf23 = input.nu23_fiber; + + double Vm = 1 - Vf; + double Em = input.E_matrix; + double num = input.nu_matrix; + double Gm = Em / (2 * (1 + num)); + double em1 = Em; + double em2 = Em; + double em3 = Em; + double gm12 = Gm; + double gm13 = Gm; + double gm23 = Gm; + double num12 = num; + double num13 = num; + double num23 = num; + + Matrix Sf = Matrix([ + [1 / ef1, -nuf12 / ef1, -nuf13 / ef1, 0, 0, 0], + [-nuf12 / ef1, 1 / ef2, -nuf23 / ef2, 0, 0, 0], + [-nuf12 / ef1, -nuf23 / ef2, 1 / ef3, 0, 0, 0], + [0, 0, 0, 1 / gf23, 0, 0], + [0, 0, 0, 0, 1 / gf13, 0], + [0, 0, 0, 0, 0, 1 / gf12] + ]); + Matrix SHf_Temp = Matrix([ + [ef1, nuf12, nuf13, 0, 0, 0], + [ + -nuf12, + 1 / ef2 - nuf12 * nuf12 / ef1, + -nuf23 / ef2 - nuf13 * nuf13 / ef1, + 0, + 0, + 0 + ], + [ + -nuf23, + -nuf23 / ef2 - nuf12 * nuf12 / ef1, + 1 / ef3 - nuf13 * nuf13 / ef1, + 0, + 0, + 0 + ], + [0, 0, 0, 1 / gf23, 0, 0], + [0, 0, 0, 0, 1 / gf13, 0], + [0, 0, 0, 0, 0, 1 / gf12] + ]); + + Matrix Sm = Matrix([ + [1 / em1, -num12 / em1, -num13 / em1, 0, 0, 0], + [-num12 / em1, 1 / em2, -num23 / em2, 0, 0, 0], + [-num12 / em1, -num23 / em2, 1 / em3, 0, 0, 0], + [0, 0, 0, 1 / gm23, 0, 0], + [0, 0, 0, 0, 1 / gm13, 0], + [0, 0, 0, 0, 0, 1 / gm12] + ]); + Matrix SHm_Temp = Matrix([ + [em1, num12, num13, 0, 0, 0], + [ + -num12, + 1 / em2 - num12 * num12 / em1, + -num23 / em2 - num13 * num13 / em1, + 0, + 0, + 0 + ], + [ + -num23, + -num23 / em2 - num12 * num12 / em1, + 1 / em3 - num13 * num13 / em1, + 0, + 0, + 0 + ], + [0, 0, 0, 1 / gm23, 0, 0], + [0, 0, 0, 0, 1 / gm13, 0], + [0, 0, 0, 0, 0, 1 / gm12] + ]); + + Matrix Cf = Sf.inverse(); + Matrix Cm = Sm.inverse(); + + Matrix CVs = Cf * Vf + Cm * Vm; + Matrix SVs = CVs.inverse(); + + Matrix SRs = Sf * Vf + Sm * Vm; + Matrix CRs = SRs.inverse(); + + Matrix SHs_Temp = SHf_Temp * Vf + SHm_Temp * Vm; + + UDFRCRulesOfMixtureOutput output = UDFRCRulesOfMixtureOutput(); + + output.voigtRulesOfMixture.engineeringConstants['E1'] = 1 / SVs[0][0]; + output.voigtRulesOfMixture.engineeringConstants['E2'] = 1 / SVs[1][1]; + output.voigtRulesOfMixture.engineeringConstants['E3'] = 1 / SVs[2][2]; + output.voigtRulesOfMixture.engineeringConstants['G12'] = 1 / SVs[5][5]; + output.voigtRulesOfMixture.engineeringConstants['G13'] = 1 / SVs[4][4]; + output.voigtRulesOfMixture.engineeringConstants['G23'] = 1 / SVs[3][3]; + output.voigtRulesOfMixture.engineeringConstants['nu12'] = + -1 / SVs[0][0] * SVs[0][1]; + output.voigtRulesOfMixture.engineeringConstants['nu13'] = + -1 / SVs[0][0] * SVs[0][2]; + output.voigtRulesOfMixture.engineeringConstants['nu23'] = + -1 / SVs[1][1] * SVs[1][2]; + + output.reussRulesOfMixture.engineeringConstants['E1'] = 1 / SRs[0][0]; + output.reussRulesOfMixture.engineeringConstants['E2'] = 1 / SRs[1][1]; + output.reussRulesOfMixture.engineeringConstants['E3'] = 1 / SRs[2][2]; + output.reussRulesOfMixture.engineeringConstants['G12'] = 1 / SRs[5][5]; + output.reussRulesOfMixture.engineeringConstants['G13'] = 1 / SRs[4][4]; + output.reussRulesOfMixture.engineeringConstants['G23'] = 1 / SRs[3][3]; + output.reussRulesOfMixture.engineeringConstants['nu12'] = + -1 / SRs[0][0] * SRs[0][1]; + output.reussRulesOfMixture.engineeringConstants['nu13'] = + -1 / SRs[0][0] * SRs[0][2]; + output.reussRulesOfMixture.engineeringConstants['nu23'] = + -1 / SRs[1][1] * SRs[1][2]; + + double eh1 = SHs_Temp[0][0]; + + double nuh12 = SHs_Temp[0][1]; + double nuh13 = SHs_Temp[0][2]; + + double gh12 = 1 / SHs_Temp[5][5]; + double gh13 = 1 / SHs_Temp[4][4]; + double gh23 = 1 / SHs_Temp[3][3]; + + double eh2 = 1 / (SHs_Temp[1][1] + nuh12 * nuh12 / eh1); + double eh3 = 1 / (SHs_Temp[2][2] + nuh13 * nuh13 / eh1); + + double nuh23 = -eh2 * (SHs_Temp[1][2] + nuh12 * nuh12 / eh1); + + output.hybirdRulesOfMixture.engineeringConstants['E1'] = eh1; + output.hybirdRulesOfMixture.engineeringConstants['E2'] = eh2; + output.hybirdRulesOfMixture.engineeringConstants['E3'] = eh3; + output.hybirdRulesOfMixture.engineeringConstants['G12'] = gh12; + output.hybirdRulesOfMixture.engineeringConstants['G13'] = gh13; + output.hybirdRulesOfMixture.engineeringConstants['G23'] = gh23; + output.hybirdRulesOfMixture.engineeringConstants['nu12'] = nuh12; + output.hybirdRulesOfMixture.engineeringConstants['nu13'] = nuh13; + output.hybirdRulesOfMixture.engineeringConstants['nu23'] = nuh23; + + Matrix Shs = Matrix([ + [1 / eh1, -nuh12 / eh1, -nuh13 / eh1, 0, 0, 0], + [-nuh12 / eh1, 1 / eh2, -nuh23 / eh2, 0, 0, 0], + [-nuh12 / eh1, -nuh23 / eh2, 1 / eh3, 0, 0, 0], + [0, 0, 0, 1 / gh23, 0, 0], + [0, 0, 0, 0, 1 / gh13, 0], + [0, 0, 0, 0, 0, 1 / gh12] + ]); + + Matrix Chs = Shs.inverse(); + + output.voigtRulesOfMixture.stiffness = CVs.toListOfLists(); + output.voigtRulesOfMixture.compliance = SVs.toListOfLists(); + + output.reussRulesOfMixture.stiffness = CRs.toListOfLists(); + output.reussRulesOfMixture.compliance = SRs.toListOfLists(); + + output.hybirdRulesOfMixture.stiffness = Chs.toListOfLists(); + output.hybirdRulesOfMixture.compliance = Shs.toListOfLists(); + + if (input.analysisType == AnalysisType.thermalElastic) { + double alpha11_f = input.alpha11_fiber; + double alpha22_f = input.alpha22_fiber; + Matrix cteVector_f = Matrix([ + [alpha11_f], + [alpha22_f], + [alpha22_f], + [0], + [0], + [0] + ]); + + double alpha_m = input.alpha_matrix; + Matrix cteVector_m = Matrix([ + [alpha_m], + [alpha_m], + [alpha_m], + [0], + [0], + [0] + ]); + + Matrix alpha_V = + CVs.inverse() * (Cf * Vf * cteVector_f + Cm * Vm * cteVector_m); + Matrix alpha_R = (cteVector_f * Vf + cteVector_m * Vm); + output.voigtRulesOfMixture.engineeringConstants["alpha11"] = + alpha_V[0][0]; + output.voigtRulesOfMixture.engineeringConstants["alpha22"] = + alpha_V[1][0]; + output.voigtRulesOfMixture.engineeringConstants["alpha33"] = + alpha_V[2][0]; + + output.reussRulesOfMixture.engineeringConstants["alpha11"] = + alpha_R[0][0]; + output.reussRulesOfMixture.engineeringConstants["alpha22"] = + alpha_R[1][0]; + output.reussRulesOfMixture.engineeringConstants["alpha33"] = + alpha_R[2][0]; + + double alpha11_h = (Vf * ef1 * alpha11_f + Vm * em1 * alpha_m) / eh1; + output.hybirdRulesOfMixture.engineeringConstants["alpha11"] = alpha11_h; + double alpha22_h = (Vf * (alpha11_f * nuf12 + alpha22_f) + + Vm * alpha_m * (1 + num) - + alpha11_h * nuh12); + output.hybirdRulesOfMixture.engineeringConstants["alpha22"] = alpha22_h; + output.hybirdRulesOfMixture.engineeringConstants["alpha33"] = alpha22_h; + } + + return output; + } +} diff --git a/composite_calculator/lib/composite_calculator.dart b/composite_calculator/lib/composite_calculator.dart index 1da55ee..a1da23d 100644 --- a/composite_calculator/lib/composite_calculator.dart +++ b/composite_calculator/lib/composite_calculator.dart @@ -10,9 +10,12 @@ export 'models/laminate_3d_properties_input.dart'; export 'models/laminate_3d_properties_output.dart'; export 'models/laminar_stress_strain_input.dart'; export 'models/laminar_stress_strain_output.dart'; +export 'models/UDFRC_rules_of_mixture_input.dart'; +export 'models/UDFRC_rules_of_mixture_output.dart'; export 'calculators/lamina_engineering_constants_calculator.dart'; export 'calculators/lamina_stress_strain_calculator.dart'; export 'calculators/laminate_plate_properties_calculator.dart'; export 'calculators/laminate_3d_properties_calculator.dart'; -export 'calculators/laminar_stress_strain_calculator.dart'; \ No newline at end of file +export 'calculators/laminar_stress_strain_calculator.dart'; +export 'calculators/UDFRC_rules_of_mixture_calculator.dart'; diff --git a/composite_calculator/lib/models/UDFRC_rules_of_mixture_input.dart b/composite_calculator/lib/models/UDFRC_rules_of_mixture_input.dart new file mode 100644 index 0000000..cc3a31e --- /dev/null +++ b/composite_calculator/lib/models/UDFRC_rules_of_mixture_input.dart @@ -0,0 +1,84 @@ +import 'package:composite_calculator/models/analysis_type.dart'; + +class UDFRCRulesOfMixtureInput { + AnalysisType analysisType; + double E1_fiber; + double E2_fiber; + double G12_fiber; + double nu12_fiber; + double nu23_fiber; + double alpha11_fiber; + double alpha22_fiber; + double E_matrix; + double nu_matrix; + double alpha_matrix; + double fiberVolumeFraction; + + UDFRCRulesOfMixtureInput({ + this.analysisType = AnalysisType.elastic, + this.E1_fiber = 0, + this.E2_fiber = 0, + this.G12_fiber = 0, + this.nu12_fiber = 0, + this.nu23_fiber = 0, + this.alpha11_fiber = 0, + this.alpha22_fiber = 0, + this.E_matrix = 0, + this.nu_matrix = 0, + this.alpha_matrix = 0, + this.fiberVolumeFraction = 0, + }); + + // Factory method to create an instance with default values + factory UDFRCRulesOfMixtureInput.withDefaults() { + return UDFRCRulesOfMixtureInput( + E1_fiber: 150000, + E2_fiber: 10000, + G12_fiber: 5000, + nu12_fiber: 0.3, + nu23_fiber: 0.25, + E_matrix: 3500, + nu_matrix: 0.35, + fiberVolumeFraction: 0.3 + ); + } + + Map toJson() { + return { + 'analysis_type': analysisType.toJson(), + 'E1_fiber': E1_fiber, + 'E2_fiber': E2_fiber, + 'G12_fiber': G12_fiber, + 'nu12_fiber': nu12_fiber, + 'nu23_fiber': nu23_fiber, + 'alpha11_fiber': alpha11_fiber, + 'alpha22_fiber': alpha22_fiber, + 'E_matrix': E_matrix, + 'nu_matrix': nu_matrix, + 'alpha_matrix': alpha_matrix, + 'fiberVolumeFraction': fiberVolumeFraction, + }; + } + + // Factory method to create an instance from a JSON map + factory UDFRCRulesOfMixtureInput.fromJson(Map json) { + return UDFRCRulesOfMixtureInput( + analysisType: AnalysisType.values.firstWhere( + (e) => + e.toString() == + 'AnalysisType.' + (json['analysis_type'] ?? "elastic"), + orElse: () => AnalysisType.elastic, // Default value if not found + ), + E1_fiber: (json['E1_fiber'] ?? 0).toDouble(), + E2_fiber: (json['E2_fiber'] ?? 0).toDouble(), + G12_fiber: (json['G12_fiber'] ?? 0).toDouble(), + nu12_fiber: (json['nu12_fiber'] ?? 0).toDouble(), + alpha11_fiber: (json['alpha11_fiber'] ?? 0).toDouble(), + alpha22_fiber: (json['alpha22_fiber'] ?? 0).toDouble(), + E_matrix: (json['E_matrix'] ?? 0).toDouble(), + nu_matrix: (json['nu_matrix'] ?? 0).toDouble(), + alpha_matrix: (json['alpha_matrix'] ?? 0).toDouble(), + fiberVolumeFraction: (json['fiberVolumeFraction'] ?? 0).toDouble(), + ); + } +} diff --git a/composite_calculator/lib/models/UDFRC_rules_of_mixture_output.dart b/composite_calculator/lib/models/UDFRC_rules_of_mixture_output.dart new file mode 100644 index 0000000..830b90d --- /dev/null +++ b/composite_calculator/lib/models/UDFRC_rules_of_mixture_output.dart @@ -0,0 +1,46 @@ +class UDFRCRulesOfMixtureOutput { + ThreeDimensionalPropertiesOutput voigtRulesOfMixture; + ThreeDimensionalPropertiesOutput reussRulesOfMixture; + ThreeDimensionalPropertiesOutput hybirdRulesOfMixture; + + UDFRCRulesOfMixtureOutput({ + ThreeDimensionalPropertiesOutput? voigtRulesOfMixture, + ThreeDimensionalPropertiesOutput? reussRulesOfMixture, + ThreeDimensionalPropertiesOutput? hybridRulesOfMixture, + }) : voigtRulesOfMixture = + voigtRulesOfMixture ?? ThreeDimensionalPropertiesOutput(), + reussRulesOfMixture = + reussRulesOfMixture ?? ThreeDimensionalPropertiesOutput(), + hybirdRulesOfMixture = + hybridRulesOfMixture ?? ThreeDimensionalPropertiesOutput(); + + Map toJson() { + return { + 'voigtRulesOfMixture': voigtRulesOfMixture.toJson(), + 'reussRulesOfMixture': reussRulesOfMixture.toJson(), + 'hybridRulesOfMixture': hybirdRulesOfMixture.toJson() + }; + } +} + +class ThreeDimensionalPropertiesOutput { + List> stiffness; + List> compliance; + + Map engineeringConstants; + + ThreeDimensionalPropertiesOutput({ + this.stiffness = const [], + this.compliance = const [], + Map? + engineeringConstants, // Make it nullable and initialize later + }) : engineeringConstants = engineeringConstants ?? {}; + + Map toJson() { + return { + 'stiffness': stiffness, + 'compliance': compliance, + 'engineeringConstants': engineeringConstants + }; + } +} diff --git a/composite_calculator/test/UDFRC_rules_of_mixture_calculator_test.dart b/composite_calculator/test/UDFRC_rules_of_mixture_calculator_test.dart new file mode 100644 index 0000000..7b72f22 --- /dev/null +++ b/composite_calculator/test/UDFRC_rules_of_mixture_calculator_test.dart @@ -0,0 +1,142 @@ +import 'package:composite_calculator/calculators/laminate_3d_properties_calculator.dart'; +import 'package:composite_calculator/composite_calculator.dart'; +import 'package:composite_calculator/models/laminate_3d_properties_input.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('UDFRCRulesOfMixtureCalculator Tests', () { + test('Default input test case', () { + // Arrange: Create input data with default values + var input = UDFRCRulesOfMixtureInput.withDefaults(); + + // Act: Calculate the output using the calculator + var output = UDFRCRulesOfMixtureCalculator.calculate(input); + + // Assert: + List> expectedVoigtStiffness = [ + [ + 49663.80608250527, + 3336.796145739233, + 3336.7961457392335, + 0.0, + 0.0, + 0.0 + ], + [ + 3336.7961457392335, + 7164.619090635349, + 2949.8042758205343, + 0.0, + 0.0, + 0.0 + ], + [ + 3336.796145739233, + 2949.8042758205343, + 7164.619090635349, + 0.0, + 0.0, + 0.0 + ], + [0.0, 0.0, 0.0, 2107.4074074074074, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 2407.4074074074074, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 2407.4074074074074] + ]; + + List> expectedVoigtCompliance = [ + [ + 2.1069417741194078e-05, + -6.950900645997087e-06, + -6.950900645997087e-06, + 0.0, + 0.0, + 0.0 + ], + [ + -6.950900645997089e-06, + 0.00017035666447795232, + -6.690168350095812e-05, + 0.0, + 0.0, + 0.0 + ], + [ + -6.950900645997084e-06, + -6.690168350095812e-05, + 0.0001703566644779523, + 0.0, + 0.0, + 0.0 + ], + [0.0, 0.0, 0.0, 0.00047451669595782075, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.00041538461538461537, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.00041538461538461537] + ]; + + for (int i = 0; i < output.voigtRulesOfMixture.stiffness.length; i++) { + for (int j = 0; + j < output.voigtRulesOfMixture.stiffness[i].length; + j++) { + expect(output.voigtRulesOfMixture.stiffness[i][j], + closeTo(expectedVoigtStiffness[i][j], 1e-3)); + } + } + for (int i = 0; i < output.voigtRulesOfMixture.compliance.length; i++) { + for (int j = 0; + j < output.voigtRulesOfMixture.compliance[i].length; + j++) { + expect(output.voigtRulesOfMixture.compliance[i][j], + closeTo(expectedVoigtCompliance[i][j], 1e-3)); + } + } + + expect(output.voigtRulesOfMixture.engineeringConstants["E1"], + closeTo(47462.1563957527, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["E2"], + closeTo(5870.037447988545, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["E3"], + closeTo(5870.037447988546, 1e-3)); + + expect(output.voigtRulesOfMixture.engineeringConstants["G12"], + closeTo(2407.4074074074074, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["G13"], + closeTo(2407.4074074074074, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["G23"], + closeTo(2107.4074074074074, 1e-3)); + + expect(output.voigtRulesOfMixture.engineeringConstants["nu12"], + closeTo(0.32990473355165223, 1e-5)); + expect(output.voigtRulesOfMixture.engineeringConstants["nu13"], + closeTo(0.32990473355165223, 1e-5)); + expect(output.voigtRulesOfMixture.engineeringConstants["nu23"], + closeTo(0.392715387484101, 1e-5)); + }); + + test('Custom input test case', () { + // Arrange: Create custom input data + var input = UDFRCRulesOfMixtureInput( + analysisType: AnalysisType.thermalElastic, + E1_fiber: 150000, + E2_fiber: 10000, + G12_fiber: 5000, + nu12_fiber: 0.3, + nu23_fiber: 0.25, + alpha11_fiber: 0.1, + E_matrix: 3500, + nu_matrix: 0.35, + alpha_matrix: 0.02, + fiberVolumeFraction: 0.3); + + // Act: Calculate the output using the calculator + var output = UDFRCRulesOfMixtureCalculator.calculate(input); + + // Assert: + expect(output.voigtRulesOfMixture.engineeringConstants["alpha11"], + closeTo(9.5829e-2, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["alpha22"], + closeTo(-3.4089e-3, 1e-3)); + expect(output.voigtRulesOfMixture.engineeringConstants["alpha33"], + closeTo(-3.4089e-3, 1e-3)); + }); + }); +} diff --git a/data/lib/repositories/function_tools_repository_imp.dart b/data/lib/repositories/function_tools_repository_imp.dart index 3284005..a488608 100644 --- a/data/lib/repositories/function_tools_repository_imp.dart +++ b/data/lib/repositories/function_tools_repository_imp.dart @@ -132,8 +132,8 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { "E2", "G12", "nu12", - "nu23" - "layup_sequence", + "nu23", + "layup_sequence", "layer_thickness", ], "properties": { @@ -248,6 +248,69 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { "kappa12": {"type": "number", "default": 0} } }); + FunctionTool calculateUDFRCRulesOfMixtureTool = FunctionTool( + name: "calculate_UDFRC_rules_of_mixture", + description: + "Calculates the UDFRC (Unidirectional fibre-reinforced composites) properties by rules of mixture. $commonDescription", + parameters: { + "type": "object", + "required": [ + "E1_fiber", + "E2_fiber", + "G12_fiber", + "nu12_fiber", + "nu23_fiber", + "E_matrix", + "nu_matrix", + "fiberVolumeFraction" + ], + "properties": { + "E1_fiber": { + "type": "number", + "default": 150000, + "exclusiveMinimum": 0 + }, + "E2_fiber": { + "type": "number", + "default": 10000, + "exclusiveMinimum": 0 + }, + "G12_fiber": { + "type": "number", + "default": 5000, + "exclusiveMinimum": 0 + }, + "nu12_fiber": { + "type": "number", + "default": 0.3, + "maximum": 0.5, + "minimum": -1 + }, + "nu23_fiber": { + "type": "number", + "default": 0.25, + "maximum": 0.5, + "minimum": -1 + }, + "E_matrix": { + "type": "number", + "default": 3500, + "exclusiveMinimum": 0 + }, + "nu_matrix": { + "type": "number", + "default": 0.35, + "maximum": 0.5, + "minimum": -1 + }, + "fiberVolumeFraction": { + "type": "number", + "default": 0.3, + "maximum": 1, + "minimum": 0 + }, + } + }); return [ calculateLaminaEngineeringConstantsTool, calculateLaminaStrainTool, @@ -256,6 +319,7 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { calculateLaminate3DPropertiesTool, calculateLaminarStrainTool, calculateLaminarStressTool, + calculateUDFRCRulesOfMixtureTool ]; } } diff --git a/lib/presentation/chat/viewModels/chat_view_model.dart b/lib/presentation/chat/viewModels/chat_view_model.dart index 16dcc7d..168dc40 100644 --- a/lib/presentation/chat/viewModels/chat_view_model.dart +++ b/lib/presentation/chat/viewModels/chat_view_model.dart @@ -5,6 +5,7 @@ import 'package:composite_calculator/calculators/lamina_stress_strain_calculator import 'package:composite_calculator/calculators/laminar_stress_strain_calculator.dart'; import 'package:composite_calculator/calculators/laminate_3d_properties_calculator.dart'; import 'package:composite_calculator/calculators/laminate_plate_properties_calculator.dart'; +import 'package:composite_calculator/composite_calculator.dart'; import 'package:composite_calculator/models/lamina_engineering_constants_input.dart'; import 'package:composite_calculator/models/lamina_engineering_constants_output.dart'; @@ -53,8 +54,8 @@ class ChatViewModel extends ChangeNotifier { "Calculate laminate 3D properties", "Calculate laminar strain", "Calculate laminate stress", + "Calculates the UDFRC (Unidirectional fibre-reinforced composites) properties by rules of mixture", "What is the upper bound of Young's modulus for composites?", - // "How to use SwiftComp?", // "Give me some math equations.", ]; @@ -195,16 +196,22 @@ class ChatViewModel extends ChangeNotifier { outputString = output.toJson().toString(); } else if (functionName == "calculate_laminar_strain") { LaminarStressStrainInput input = - LaminarStressStrainInput.fromJson(argumentsJson); + LaminarStressStrainInput.fromJson(argumentsJson); LaminarStressStrainOutput output = - LaminarStressStrainCalculator.calculate(input); + LaminarStressStrainCalculator.calculate(input); outputString = output.toJson().toString(); } else if (functionName == "calculate_laminar_stress") { LaminarStressStrainInput input = - LaminarStressStrainInput.fromJson(argumentsJson); + LaminarStressStrainInput.fromJson(argumentsJson); input.tensorType = TensorType.strain; LaminarStressStrainOutput output = - LaminarStressStrainCalculator.calculate(input); + LaminarStressStrainCalculator.calculate(input); + outputString = output.toJson().toString(); + } else if (functionName == "calculate_UDFRC_rules_of_mixture") { + UDFRCRulesOfMixtureInput input = + UDFRCRulesOfMixtureInput.fromJson(argumentsJson); + UDFRCRulesOfMixtureOutput output = + UDFRCRulesOfMixtureCalculator.calculate(input); outputString = output.toJson().toString(); } _chatSessionUseCase.addMessageToSession(selectedSession!, diff --git a/lib/presentation/tools/page/UDFRC_rules_of_mixture_page.dart b/lib/presentation/tools/page/UDFRC_rules_of_mixture_page.dart index 4cee715..da9d1a5 100644 --- a/lib/presentation/tools/page/UDFRC_rules_of_mixture_page.dart +++ b/lib/presentation/tools/page/UDFRC_rules_of_mixture_page.dart @@ -1,8 +1,8 @@ import 'package:composite_calculator/composite_calculator.dart'; +import 'package:composite_calculator/models/UDFRC_rules_of_mixture_input.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:linalg/matrix.dart'; import 'package:swiftcomp/generated/l10n.dart'; import 'package:swiftcomp/presentation/tools/model/material_model.dart'; import 'package:swiftcomp/presentation/tools/model/volume_fraction_model.dart'; @@ -123,233 +123,28 @@ class _RulesOfMixturePageState extends State { return; } - double Vf = fiberVolumeFraction.value!; - // double Ef = fiberMaterial.e1!; - // double nuf = fiberMaterial.nu12!; - // double Gf = Ef / (2 * (1 + nuf)); - double ef1 = fiberMaterial.e1!; - double ef2 = fiberMaterial.e2!; - double ef3 = fiberMaterial.e2!; - double gf12 = fiberMaterial.g12!; - double gf13 = fiberMaterial.g12!; - double gf23 = fiberMaterial.e2! / (2 * (1 + fiberMaterial.nu23!)); - double nuf12 = fiberMaterial.nu12!; - double nuf13 = fiberMaterial.nu12!; - double nuf23 = fiberMaterial.nu23!; - - double Vm = 1 - Vf; - double Em = matrixMaterial.e!; - double num = matrixMaterial.nu!; - double Gm = Em / (2 * (1 + num)); - double em1 = Em; - double em2 = Em; - double em3 = Em; - double gm12 = Gm; - double gm13 = Gm; - double gm23 = Gm; - double num12 = num; - double num13 = num; - double num23 = num; - - Matrix Sf = Matrix([ - [1 / ef1, -nuf12 / ef1, -nuf13 / ef1, 0, 0, 0], - [-nuf12 / ef1, 1 / ef2, -nuf23 / ef2, 0, 0, 0], - [-nuf12 / ef1, -nuf23 / ef2, 1 / ef3, 0, 0, 0], - [0, 0, 0, 1 / gf23, 0, 0], - [0, 0, 0, 0, 1 / gf13, 0], - [0, 0, 0, 0, 0, 1 / gf12] - ]); - Matrix SHf_Temp = Matrix([ - [ef1, nuf12, nuf13, 0, 0, 0], - [ - -nuf12, - 1 / ef2 - nuf12 * nuf12 / ef1, - -nuf23 / ef2 - nuf13 * nuf13 / ef1, - 0, - 0, - 0 - ], - [ - -nuf23, - -nuf23 / ef2 - nuf12 * nuf12 / ef1, - 1 / ef3 - nuf13 * nuf13 / ef1, - 0, - 0, - 0 - ], - [0, 0, 0, 1 / gf23, 0, 0], - [0, 0, 0, 0, 1 / gf13, 0], - [0, 0, 0, 0, 0, 1 / gf12] - ]); - - Matrix Sm = Matrix([ - [1 / em1, -num12 / em1, -num13 / em1, 0, 0, 0], - [-num12 / em1, 1 / em2, -num23 / em2, 0, 0, 0], - [-num12 / em1, -num23 / em2, 1 / em3, 0, 0, 0], - [0, 0, 0, 1 / gm23, 0, 0], - [0, 0, 0, 0, 1 / gm13, 0], - [0, 0, 0, 0, 0, 1 / gm12] - ]); - Matrix SHm_Temp = Matrix([ - [em1, num12, num13, 0, 0, 0], - [ - -num12, - 1 / em2 - num12 * num12 / em1, - -num23 / em2 - num13 * num13 / em1, - 0, - 0, - 0 - ], - [ - -num23, - -num23 / em2 - num12 * num12 / em1, - 1 / em3 - num13 * num13 / em1, - 0, - 0, - 0 - ], - [0, 0, 0, 1 / gm23, 0, 0], - [0, 0, 0, 0, 1 / gm13, 0], - [0, 0, 0, 0, 0, 1 / gm12] - ]); - - Matrix Cf = Sf.inverse(); - Matrix Cm = Sm.inverse(); - - Matrix CVs = Cf * Vf + Cm * Vm; - Matrix SVs = CVs.inverse(); - - Matrix SRs = Sf * Vf + Sm * Vm; - Matrix CRs = SRs.inverse(); - - Matrix SHs_Temp = SHf_Temp * Vf + SHm_Temp * Vm; - - OrthotropicMaterial voigtEngineeringConstants = OrthotropicMaterial(); - voigtEngineeringConstants.e1 = 1 / SVs[0][0]; - voigtEngineeringConstants.e2 = 1 / SVs[1][1]; - voigtEngineeringConstants.e3 = 1 / SVs[2][2]; - voigtEngineeringConstants.g12 = 1 / SVs[5][5]; - voigtEngineeringConstants.g13 = 1 / SVs[4][4]; - voigtEngineeringConstants.g23 = 1 / SVs[3][3]; - voigtEngineeringConstants.nu12 = -1 / SVs[0][0] * SVs[0][1]; - voigtEngineeringConstants.nu13 = -1 / SVs[0][0] * SVs[0][2]; - voigtEngineeringConstants.nu23 = -1 / SVs[1][1] * SVs[1][2]; - - OrthotropicMaterial reussEngineeringConstants = OrthotropicMaterial(); - reussEngineeringConstants.e1 = 1 / SRs[0][0]; - reussEngineeringConstants.e2 = 1 / SRs[1][1]; - reussEngineeringConstants.e3 = 1 / SRs[2][2]; - reussEngineeringConstants.g12 = 1 / SRs[5][5]; - reussEngineeringConstants.g13 = 1 / SRs[4][4]; - reussEngineeringConstants.g23 = 1 / SRs[3][3]; - reussEngineeringConstants.nu12 = -1 / SRs[0][0] * SRs[0][1]; - reussEngineeringConstants.nu13 = -1 / SRs[0][0] * SRs[0][2]; - reussEngineeringConstants.nu23 = -1 / SRs[1][1] * SRs[1][2]; - - OrthotropicMaterial hybridEngineeringConstants = OrthotropicMaterial(); - hybridEngineeringConstants.e1 = SHs_Temp[0][0]; - - hybridEngineeringConstants.nu12 = SHs_Temp[0][1]; - hybridEngineeringConstants.nu13 = SHs_Temp[0][2]; - - hybridEngineeringConstants.g12 = 1 / SHs_Temp[5][5]; - hybridEngineeringConstants.g13 = 1 / SHs_Temp[4][4]; - hybridEngineeringConstants.g23 = 1 / SHs_Temp[3][3]; - - hybridEngineeringConstants.e2 = 1 / - (SHs_Temp[1][1] + - hybridEngineeringConstants.nu12! * - hybridEngineeringConstants.nu12! / - hybridEngineeringConstants.e1!); - - hybridEngineeringConstants.e3 = 1 / - (SHs_Temp[2][2] + - hybridEngineeringConstants.nu13! * - hybridEngineeringConstants.nu13! / - hybridEngineeringConstants.e1!); - - hybridEngineeringConstants.nu23 = -hybridEngineeringConstants.e2! * - (SHs_Temp[1][2] + - hybridEngineeringConstants.nu12! * - hybridEngineeringConstants.nu12! / - hybridEngineeringConstants.e1!); - - double eh1 = hybridEngineeringConstants.e1!; - double eh2 = hybridEngineeringConstants.e2!; - double eh3 = hybridEngineeringConstants.e3!; - double gh12 = hybridEngineeringConstants.g12!; - double gh13 = hybridEngineeringConstants.g13!; - double gh23 = hybridEngineeringConstants.g23!; - double nuh12 = hybridEngineeringConstants.nu12!; - double nuh13 = hybridEngineeringConstants.nu13!; - double nuh23 = hybridEngineeringConstants.nu23!; - - Matrix Shs = Matrix([ - [1 / eh1, -nuh12 / eh1, -nuh13 / eh1, 0, 0, 0], - [-nuh12 / eh1, 1 / eh2, -nuh23 / eh2, 0, 0, 0], - [-nuh12 / eh1, -nuh23 / eh2, 1 / eh3, 0, 0, 0], - [0, 0, 0, 1 / gh23, 0, 0], - [0, 0, 0, 0, 1 / gh13, 0], - [0, 0, 0, 0, 0, 1 / gh12] - ]); - - Matrix Chs = Shs.inverse(); - - if (analysisType == AnalysisType.thermalElastic) { - double alpha11_f = transverselyIsotropicCTE.alpha11!; - double alpha22_f = transverselyIsotropicCTE.alpha22!; - Matrix cteVector_f = Matrix([ - [alpha11_f], - [alpha22_f], - [alpha22_f], - [0], - [0], - [0] - ]); - - double alpha_m = isotropicCTE.alpha!; - Matrix cteVector_m = Matrix([ - [alpha_m], - [alpha_m], - [alpha_m], - [0], - [0], - [0] - ]); - - Matrix alpha_V = - CVs.inverse() * (Cf * Vf * cteVector_f + Cm * Vm * cteVector_m); - Matrix alpha_R = (cteVector_f * Vf + cteVector_m * Vm); - voigtEngineeringConstants.alpha11 = alpha_V[0][0]; - voigtEngineeringConstants.alpha22 = alpha_V[1][0]; - voigtEngineeringConstants.alpha33 = alpha_V[2][0]; - - reussEngineeringConstants.alpha11 = alpha_R[0][0]; - reussEngineeringConstants.alpha22 = alpha_R[1][0]; - reussEngineeringConstants.alpha33 = alpha_R[2][0]; - - double alpha11_h = (Vf * ef1 * alpha11_f + Vm * em1 * alpha_m) / eh1; - hybridEngineeringConstants.alpha11 = alpha11_h; - double alpha22_h = (Vf * (alpha11_f * nuf12 + alpha22_f) + - Vm * alpha_m * (1 + num) - - alpha11_h * nuh12); - hybridEngineeringConstants.alpha22 = alpha22_h; - hybridEngineeringConstants.alpha33 = alpha22_h; - } + UDFRCRulesOfMixtureInput input = UDFRCRulesOfMixtureInput( + analysisType: analysisType, + E1_fiber: fiberMaterial.e1 ?? 0, + E2_fiber: fiberMaterial.e2 ?? 0, + G12_fiber: fiberMaterial.g12 ?? 0, + nu12_fiber: fiberMaterial.nu12 ?? 0, + nu23_fiber: fiberMaterial.nu23 ?? 0, + alpha11_fiber: transverselyIsotropicCTE.alpha11 ?? 0, + alpha22_fiber: transverselyIsotropicCTE.alpha22 ?? 0, + E_matrix: matrixMaterial.e ?? 0, + nu_matrix: matrixMaterial.nu ?? 0, + alpha_matrix: isotropicCTE.alpha ?? 0, + fiberVolumeFraction: fiberVolumeFraction.value ?? 0, + ); + + UDFRCRulesOfMixtureOutput output = + UDFRCRulesOfMixtureCalculator.calculate(input); Navigator.push( context, MaterialPageRoute( - builder: (context) => RulesOfMixtureResultPage( - Cv: CVs, - Cr: CRs, - Ch: Chs, - Sv: SVs, - Sr: SRs, - Sh: Shs, - voigtConstants: voigtEngineeringConstants, - reussConstants: reussEngineeringConstants, - hybridConstants: hybridEngineeringConstants))); + builder: (context) => RulesOfMixtureResultPage(output: output))); } } } diff --git a/lib/presentation/tools/page/UDFRC_rules_of_mixture_result_page.dart b/lib/presentation/tools/page/UDFRC_rules_of_mixture_result_page.dart index 814fd63..b283867 100644 --- a/lib/presentation/tools/page/UDFRC_rules_of_mixture_result_page.dart +++ b/lib/presentation/tools/page/UDFRC_rules_of_mixture_result_page.dart @@ -1,8 +1,7 @@ -import 'package:composite_calculator/utils/matrix_to_list_extension.dart'; +import 'package:composite_calculator/composite_calculator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:linalg/matrix.dart'; import 'package:swiftcomp/generated/l10n.dart'; import 'package:swiftcomp/presentation/tools/model/material_model.dart'; import 'package:swiftcomp/presentation/tools/widget/orthotropic_properties_widget.dart'; @@ -10,31 +9,14 @@ import 'package:swiftcomp/presentation/tools/widget/result_6by6_matrix.dart'; import 'package:swiftcomp/presentation/more/tool_setting_page.dart'; class RulesOfMixtureResultPage extends StatefulWidget { - final Matrix Cv; - final Matrix Cr; - final Matrix Ch; - final Matrix Sv; - final Matrix Sr; - final Matrix Sh; - final OrthotropicMaterial voigtConstants; - final OrthotropicMaterial reussConstants; - final OrthotropicMaterial hybridConstants; + final UDFRCRulesOfMixtureOutput output; - const RulesOfMixtureResultPage( - {Key? key, - required this.Cv, - required this.Cr, - required this.Ch, - required this.Sv, - required this.Sr, - required this.Sh, - required this.voigtConstants, - required this.reussConstants, - required this.hybridConstants}) + const RulesOfMixtureResultPage({Key? key, required this.output}) : super(key: key); @override - _RulesOfMixtureResultPageState createState() => _RulesOfMixtureResultPageState(); + _RulesOfMixtureResultPageState createState() => + _RulesOfMixtureResultPageState(); } class _RulesOfMixtureResultPageState extends State { @@ -45,14 +27,17 @@ class _RulesOfMixtureResultPageState extends State { return Scaffold( appBar: AppBar( leading: IconButton( - icon: const Icon(Icons.arrow_back_ios_outlined, color: Colors.white), + icon: + const Icon(Icons.arrow_back_ios_outlined, color: Colors.white), onPressed: () => Navigator.of(context).pop(), ), actions: [ IconButton( onPressed: () { Navigator.push( - context, MaterialPageRoute(builder: (context) => const ToolSettingPage())); + context, + MaterialPageRoute( + builder: (context) => const ToolSettingPage())); }, icon: const Icon(Icons.settings_rounded), ), @@ -63,63 +48,88 @@ class _RulesOfMixtureResultPageState extends State { child: StaggeredGridView.countBuilder( padding: const EdgeInsets.fromLTRB(20, 20, 20, 100), crossAxisCount: 8, - itemCount: 12, - staggeredTileBuilder: (int index) => - StaggeredTile.fit(MediaQuery.of(context).size.width > 600 ? 4 : 8), + itemCount: resultList.length, + staggeredTileBuilder: (int index) => StaggeredTile.fit( + MediaQuery.of(context).size.width > 600 ? 4 : 8), mainAxisSpacing: 12, crossAxisSpacing: 12, itemBuilder: (BuildContext context, int index) { - return [ - Text( - "Voigt Rules of Mixture", - style: Theme.of(context).textTheme.titleMedium, - ), - Result6By6Matrix( - matrix: widget.Cv.toListOfLists(), - title: "Effective 3D Stiffness Matrix", - ), - Result6By6Matrix( - matrix: widget.Sv.toListOfLists(), - title: "Effective 3D Compliance Matrix", - ), - OrthotropicPropertiesWidget( - title: S.of(context).Engineering_Constants, - orthotropicMaterial: widget.voigtConstants, - ), - Text( - "Reuss Rules of Mixture", - style: Theme.of(context).textTheme.titleMedium, - ), - Result6By6Matrix( - matrix: widget.Cr.toListOfLists(), - title: "Effective 3D Stiffness Matrix", - ), - Result6By6Matrix( - matrix: widget.Sr.toListOfLists(), - title: "Effective 3D Compliance Matrix", - ), - OrthotropicPropertiesWidget( - title: S.of(context).Engineering_Constants, - orthotropicMaterial: widget.reussConstants, - ), - Text( - "Hybrid Rules of Mixture", - style: Theme.of(context).textTheme.titleMedium, - ), - Result6By6Matrix( - matrix: widget.Ch.toListOfLists(), - title: "Effective 3D Stiffness Matrix", - ), - Result6By6Matrix( - matrix: widget.Sh.toListOfLists(), - title: "Effective 3D Compliance Matrix", - ), - OrthotropicPropertiesWidget( - title: S.of(context).Engineering_Constants, - orthotropicMaterial: widget.hybridConstants, - ), - ][index]; + return resultList[index]; }), )); } + + List get resultList { + return [ + Text( + "Voigt Rules of Mixture", + style: Theme.of(context).textTheme.titleMedium, + ), + Result6By6Matrix( + matrix: widget.output.voigtRulesOfMixture.stiffness, + title: "Effective 3D Stiffness Matrix", + ), + Result6By6Matrix( + matrix: widget.output.voigtRulesOfMixture.compliance, + title: "Effective 3D Compliance Matrix", + ), + OrthotropicPropertiesWidget( + title: S.of(context).Engineering_Constants, + orthotropicMaterial: createOrthotropicMaterial( + widget.output.voigtRulesOfMixture.engineeringConstants), + ), + Text( + "Reuss Rules of Mixture", + style: Theme.of(context).textTheme.titleMedium, + ), + Result6By6Matrix( + matrix: widget.output.reussRulesOfMixture.stiffness, + title: "Effective 3D Stiffness Matrix", + ), + Result6By6Matrix( + matrix: widget.output.reussRulesOfMixture.compliance, + title: "Effective 3D Compliance Matrix", + ), + OrthotropicPropertiesWidget( + title: S.of(context).Engineering_Constants, + orthotropicMaterial: createOrthotropicMaterial( + widget.output.reussRulesOfMixture.engineeringConstants), + ), + Text( + "Hybrid Rules of Mixture", + style: Theme.of(context).textTheme.titleMedium, + ), + Result6By6Matrix( + matrix: widget.output.hybirdRulesOfMixture.stiffness, + title: "Effective 3D Stiffness Matrix", + ), + Result6By6Matrix( + matrix: widget.output.hybirdRulesOfMixture.compliance, + title: "Effective 3D Compliance Matrix", + ), + OrthotropicPropertiesWidget( + title: S.of(context).Engineering_Constants, + orthotropicMaterial: createOrthotropicMaterial( + widget.output.hybirdRulesOfMixture.engineeringConstants), + ), + ]; + } + + OrthotropicMaterial createOrthotropicMaterial( + Map materialMap) { + return OrthotropicMaterial( + e1: materialMap["E1"], + e2: materialMap["E2"], + e3: materialMap["E3"], + g12: materialMap["G12"], + g13: materialMap["G13"], + g23: materialMap["G23"], + nu12: materialMap["nu12"], + nu13: materialMap["nu13"], + nu23: materialMap["nu23"], + alpha11: materialMap["alpha11"], + alpha22: materialMap["alpha22"], + alpha12: materialMap["alpha33"], + ); + } } diff --git a/lib/presentation/tools/page/laminate_3d_properties_result_page.dart b/lib/presentation/tools/page/laminate_3d_properties_result_page.dart index e2a5828..4efb8ab 100644 --- a/lib/presentation/tools/page/laminate_3d_properties_result_page.dart +++ b/lib/presentation/tools/page/laminate_3d_properties_result_page.dart @@ -2,7 +2,6 @@ import 'package:composite_calculator/composite_calculator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:linalg/matrix.dart'; import 'package:swiftcomp/generated/l10n.dart'; import 'package:swiftcomp/presentation/tools/model/material_model.dart'; import 'package:swiftcomp/presentation/tools/widget/orthotropic_properties_widget.dart'; diff --git a/lib/presentation/tools/widget/result_3by3_matrix.dart b/lib/presentation/tools/widget/result_3by3_matrix.dart index 6a096c3..71127a7 100644 --- a/lib/presentation/tools/widget/result_3by3_matrix.dart +++ b/lib/presentation/tools/widget/result_3by3_matrix.dart @@ -1,7 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:linalg/matrix.dart'; import 'package:provider/provider.dart'; import 'package:swiftcomp/util/NumberPrecisionHelper.dart'; diff --git a/lib/presentation/tools/widget/result_6by6_matrix.dart b/lib/presentation/tools/widget/result_6by6_matrix.dart index 05caeee..bbe4302 100644 --- a/lib/presentation/tools/widget/result_6by6_matrix.dart +++ b/lib/presentation/tools/widget/result_6by6_matrix.dart @@ -2,7 +2,6 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; -import 'package:linalg/matrix.dart'; import 'package:provider/provider.dart'; import 'package:swiftcomp/util/NumberPrecisionHelper.dart';