From 0f4c7e3f3d2df33ba5132f461195876825e1cab4 Mon Sep 17 00:00:00 2001 From: Banghua Zhao Date: Sun, 13 Oct 2024 16:54:52 +1300 Subject: [PATCH] Add laminate stress strain function tool (#16) --- .../laminar_stress_strain_calculator.dart | 156 ++++++++++++++++++ .../lib/composite_calculator.dart | 5 +- .../models/laminar_stress_strain_input.dart | 116 +++++++++++++ .../models/laminar_stress_strain_output.dart | 58 +++++++ ...aminar_stress_strain_calculator_tests.dart | 42 +++++ .../function_tools_repository_imp.dart | 116 +++++++++++-- .../chat/viewModels/chat_view_model.dart | 18 ++ .../tools/model/mechanical_tensor_model.dart | 18 +- ...laminate_plate_properties_result_page.dart | 2 - .../page/laminate_stress_strain_page.dart | 152 ++++++----------- .../laminate_stress_strain_result_page.dart | 144 ++++++++++------ 11 files changed, 657 insertions(+), 170 deletions(-) create mode 100644 composite_calculator/lib/calculators/laminar_stress_strain_calculator.dart create mode 100644 composite_calculator/lib/models/laminar_stress_strain_input.dart create mode 100644 composite_calculator/lib/models/laminar_stress_strain_output.dart create mode 100644 composite_calculator/test/laminar_stress_strain_calculator_tests.dart diff --git a/composite_calculator/lib/calculators/laminar_stress_strain_calculator.dart b/composite_calculator/lib/calculators/laminar_stress_strain_calculator.dart new file mode 100644 index 0000000..8eece34 --- /dev/null +++ b/composite_calculator/lib/calculators/laminar_stress_strain_calculator.dart @@ -0,0 +1,156 @@ +import 'dart:math'; + +import 'package:composite_calculator/models/tensor_type.dart'; +import 'package:linalg/matrix.dart'; + +import '../models/laminar_stress_strain_input.dart'; +import '../models/laminar_stress_strain_output.dart'; +import '../utils/layup_parser.dart'; + +class LaminarStressStrainCalculator { + static LaminarStressStrainOutput calculate(LaminarStressStrainInput input) { + Matrix A = Matrix.fill(3, 3); + Matrix B = Matrix.fill(3, 3); + Matrix D = Matrix.fill(3, 3); + double thickness = input.layerThickness; + List layups = LayupParser.parse(input.layupSequence) ?? []; + int nPly = layups.length; + double e1 = input.E1; + double e2 = input.E2; + double g12 = input.G12; + double nu12 = input.nu12; + + List bzi = []; + List Q = []; + for (int i = 1; i <= nPly; i++) { + double bz = (-(nPly + 1) * thickness) / 2 + i * thickness; + bzi.add(bz); + } + + for (int i = 0; i < nPly; i++) { + double layup = layups[i]; + + double angleRadian = layup * pi / 180; + double s = sin(angleRadian); + double c = cos(angleRadian); + + Matrix Sep = Matrix([ + [1 / e1, -nu12 / e1, 0], + [-nu12 / e1, 1 / e2, 0], + [0, 0, 1 / g12] + ]); + + Matrix Qep = Sep.inverse(); + + Matrix Rsigmae = Matrix([ + [c * c, s * s, -2 * s * c], + [s * s, c * c, 2 * s * c], + [s * c, -s * c, c * c - s * s] + ]); + + Matrix Qe = Rsigmae * Qep * Rsigmae.transpose(); + + Q.add(Qe); + + A += Qe * thickness; + B += Qe * thickness * bzi[i]; + D += Qe * (thickness * bzi[i] * bzi[i] + pow(thickness, 3) / 12); + } + + Matrix ABD = Matrix([ + [A[0][0], A[0][1], A[0][2], B[0][0], B[0][1], B[0][2]], + [A[1][0], A[1][1], A[1][2], B[1][0], B[1][1], B[1][2]], + [A[2][0], A[2][1], A[2][2], B[2][0], B[2][1], B[2][2]], + [B[0][0], B[0][1], B[0][2], D[0][0], D[0][1], D[0][2]], + [B[1][0], B[1][1], B[1][2], D[1][0], D[1][1], D[1][2]], + [B[2][0], B[2][1], B[2][2], D[2][0], D[2][1], D[2][2]] + ]); + + Matrix ABD_inverese = ABD.inverse(); + + LaminarStressStrainOutput output; + if (input.tensorType == TensorType.stress) { + Matrix stressVector = Matrix([ + [input.N11], + [input.N22], + [input.N12], + [input.M11], + [input.M22], + [input.M12], + ]); + Matrix strainVector = ABD_inverese * stressVector; + output = LaminarStressStrainOutput( + tensorType: TensorType.strain, + epsilon11: strainVector[0][0], + epsilon22: strainVector[1][0], + epsilon12: strainVector[2][0], + kappa11: strainVector[3][0], + kappa22: strainVector[4][0], + kappa12: strainVector[5][0]); + } else { + Matrix strainVector = Matrix([ + [input.epsilon11], + [input.epsilon22], + [input.epsilon12], + [input.kappa11], + [input.kappa22], + [input.kappa12] + ]); + Matrix stressVector = ABD * strainVector; + output = LaminarStressStrainOutput( + tensorType: TensorType.stress, + N11: stressVector[0][0], + N22: stressVector[1][0], + N12: stressVector[2][0], + M11: stressVector[3][0], + M22: stressVector[4][0], + M12: stressVector[5][0]); + } + + return output; + } + + static List getQMatrices(LaminarStressStrainInput input) { + double thickness = input.layerThickness; + List layups = LayupParser.parse(input.layupSequence) ?? []; + int nPly = layups.length; + double e1 = input.E1; + double e2 = input.E2; + double g12 = input.G12; + double nu12 = input.nu12; + + List bzi = []; + List Q = []; + for (int i = 1; i <= nPly; i++) { + double bz = (-(nPly + 1) * thickness) / 2 + i * thickness; + bzi.add(bz); + } + + for (int i = 0; i < nPly; i++) { + double layup = layups[i]; + + double angleRadian = layup * pi / 180; + double s = sin(angleRadian); + double c = cos(angleRadian); + + Matrix Sep = Matrix([ + [1 / e1, -nu12 / e1, 0], + [-nu12 / e1, 1 / e2, 0], + [0, 0, 1 / g12] + ]); + + Matrix Qep = Sep.inverse(); + + Matrix Rsigmae = Matrix([ + [c * c, s * s, -2 * s * c], + [s * s, c * c, 2 * s * c], + [s * c, -s * c, c * c - s * s] + ]); + + Matrix Qe = Rsigmae * Qep * Rsigmae.transpose(); + + Q.add(Qe); + } + return Q; + } +} diff --git a/composite_calculator/lib/composite_calculator.dart b/composite_calculator/lib/composite_calculator.dart index 4d2aa15..1da55ee 100644 --- a/composite_calculator/lib/composite_calculator.dart +++ b/composite_calculator/lib/composite_calculator.dart @@ -8,8 +8,11 @@ export 'models/laminate_plate_properties_input.dart'; export 'models/laminate_plate_properties_output.dart'; 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 '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'; \ No newline at end of file +export 'calculators/laminate_3d_properties_calculator.dart'; +export 'calculators/laminar_stress_strain_calculator.dart'; \ No newline at end of file diff --git a/composite_calculator/lib/models/laminar_stress_strain_input.dart b/composite_calculator/lib/models/laminar_stress_strain_input.dart new file mode 100644 index 0000000..c938ab8 --- /dev/null +++ b/composite_calculator/lib/models/laminar_stress_strain_input.dart @@ -0,0 +1,116 @@ +import 'package:composite_calculator/models/tensor_type.dart'; + +import 'analysis_type.dart'; + +class LaminarStressStrainInput { + double E1; + double E2; + double G12; + double nu12; + String layupSequence; + double layerThickness; + + TensorType tensorType; + + double N11; + double N22; + double N12; + double M11; + double M22; + double M12; + + double epsilon11; + double epsilon22; + double epsilon12; + double kappa11; + double kappa22; + double kappa12; + + LaminarStressStrainInput({ + this.E1 = 0, + this.E2 = 0, + this.G12 = 0, + this.nu12 = 0, + this.layupSequence = "", + this.layerThickness = 0, + this.tensorType = TensorType.stress, + this.N11 = 0, + this.N22 = 0, + this.N12 = 0, + this.M11 = 0, + this.M22 = 0, + this.M12 = 0, + this.epsilon11 = 0, + this.epsilon22 = 0, + this.epsilon12 = 0, + this.kappa11 = 0, + this.kappa22 = 0, + this.kappa12 = 0, + }); + + // Factory method to create an instance with default values + factory LaminarStressStrainInput.withDefaults() { + return LaminarStressStrainInput( + E1: 150000, + E2: 10000, + G12: 5000, + nu12: 0.3, + layupSequence: "[0/90/45/-45]s", + layerThickness: 0.125, + tensorType: TensorType.stress, + N11: 1, + ); + } + + Map toJson() { + return { + 'E1': E1, + 'E2': E2, + 'G12': G12, + 'nu12': nu12, + 'layup_sequence': layupSequence, + 'layer_thickness': layerThickness, + 'tensorType': tensorType, + 'N11': N11, + 'N22': N22, + 'N12': N12, + 'M11': M11, + 'M22': M22, + 'M12': M12, + 'epsilon11': epsilon11, + 'epsilon22': epsilon22, + 'epsilon12': epsilon12, + 'kappa11': kappa11, + 'kappa22': kappa22, + 'kappa12': kappa12, + }; + } + + // Factory method to create an instance from a JSON map + factory LaminarStressStrainInput.fromJson(Map json) { + return LaminarStressStrainInput( + E1: (json['E1'] ?? 0).toDouble(), + E2: (json['E2'] ?? 0).toDouble(), + G12: (json['G12'] ?? 0).toDouble(), + nu12: (json['nu12'] ?? 0).toDouble(), + layupSequence: (json['layup_sequence'] ?? "").toString(), + layerThickness: (json['layer_thickness'] ?? 0).toDouble(), + tensorType: TensorType.values.firstWhere( + (e) => e.toString() == 'TensorType.' + (json['tensorType'] ?? 'stress'), + orElse: () => TensorType.stress, // Default value if not found + ), + N11: (json['N11'] ?? 0).toDouble(), + N22: (json['N22'] ?? 0).toDouble(), + N12: (json['N12'] ?? 0).toDouble(), + M11: (json['M11'] ?? 0).toDouble(), + M22: (json['M22'] ?? 0).toDouble(), + M12: (json['M12'] ?? 0).toDouble(), + epsilon11: (json['epsilon11'] ?? 0).toDouble(), + epsilon22: (json['epsilon22'] ?? 0).toDouble(), + epsilon12: (json['epsilon12'] ?? 0).toDouble(), + kappa11: (json['kappa11'] ?? 0).toDouble(), + kappa22: (json['kappa22'] ?? 0).toDouble(), + kappa12: (json['kappa12'] ?? 0).toDouble(), + ); + } +} diff --git a/composite_calculator/lib/models/laminar_stress_strain_output.dart b/composite_calculator/lib/models/laminar_stress_strain_output.dart new file mode 100644 index 0000000..e5ed243 --- /dev/null +++ b/composite_calculator/lib/models/laminar_stress_strain_output.dart @@ -0,0 +1,58 @@ +import 'package:composite_calculator/models/tensor_type.dart'; + +class LaminarStressStrainOutput { + TensorType tensorType; + + double N11; + double N22; + double N12; + double M11; + double M22; + double M12; + double epsilon11; + double epsilon22; + double epsilon12; + double kappa11; + double kappa22; + double kappa12; + + LaminarStressStrainOutput({ + this.tensorType = TensorType.stress, + this.N11 = 0, + this.N22 = 0, + this.N12 = 0, + this.M11 = 0, + this.M22 = 0, + this.M12 = 0, + this.epsilon11 = 0, + this.epsilon22 = 0, + this.epsilon12 = 0, + this.kappa11 = 0, + this.kappa22 = 0, + this.kappa12 = 0, + }); + + Map toJson() { + Map result = {}; + if (tensorType == TensorType.stress) { + result.addAll({ + 'N11': N11, + 'N22': N22, + 'N12': N12, + 'M11': M11, + 'M22': M22, + 'M12': M12, + }); + } else { + result.addAll({ + 'epsilon11': epsilon11, + 'epsilon22': epsilon22, + 'epsilon12': epsilon12, + 'kappa11': kappa11, + 'kappa22': kappa22, + 'kappa12': kappa12, + }); + } + return result; + } +} diff --git a/composite_calculator/test/laminar_stress_strain_calculator_tests.dart b/composite_calculator/test/laminar_stress_strain_calculator_tests.dart new file mode 100644 index 0000000..d52bfa8 --- /dev/null +++ b/composite_calculator/test/laminar_stress_strain_calculator_tests.dart @@ -0,0 +1,42 @@ +import 'package:composite_calculator/calculators/laminar_stress_strain_calculator.dart'; +import 'package:composite_calculator/models/laminar_stress_strain_input.dart'; +import 'package:composite_calculator/models/tensor_type.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('LaminarStressStrainCalculator Tests', () { + test('Default input test case', () { + // Arrange: Create input data with default values + var input = LaminarStressStrainInput.withDefaults(); + + // Act: Calculate the output using the calculator + var output = LaminarStressStrainCalculator.calculate(input); + + expect(output.epsilon11, closeTo(0.000017421124109966436, 1e-3)); + expect(output.epsilon22, closeTo(-0.000005445220495508603, 1e-3)); + expect(output.epsilon12, closeTo(4.712693325579657e-22, 1e-3)); + expect(output.kappa11, closeTo(3.261347510124405e-22, 1e-3)); + expect(output.kappa22, closeTo(-1.6068855629179688e-21, 1e-3)); + expect(output.kappa12, closeTo(2.184974840156989e-22, 1e-3)); + + }); + + test('Default input test case with custom strain input', () { + // Arrange: Create input data with default values + var input = LaminarStressStrainInput.withDefaults(); + input.tensorType = TensorType.strain; + input.epsilon11 = 1e-5; + + // Act: Calculate the output using the calculator + var output = LaminarStressStrainCalculator.calculate(input); + + expect(output.N11, closeTo(0.6361670020120725, 1e-3)); + expect(output.N22, closeTo(0.19884305835010055, 1e-3)); + expect(output.N12, closeTo(2.2638717237759187e-19, 1e-3)); + expect(output.M11, closeTo(0, 1e-3)); + expect(output.M22, closeTo(0, 1e-3)); + expect(output.M12, closeTo(0, 1e-3)); + }); + + }); +} diff --git a/data/lib/repositories/function_tools_repository_imp.dart b/data/lib/repositories/function_tools_repository_imp.dart index a3eda74..3284005 100644 --- a/data/lib/repositories/function_tools_repository_imp.dart +++ b/data/lib/repositories/function_tools_repository_imp.dart @@ -29,8 +29,7 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { }); FunctionTool calculateLaminaStrainTool = FunctionTool( name: "calculate_lamina_strain", - description: - "Calculates the strains for a lamina. $commonDescription", + description: "Calculates the strains for a lamina. $commonDescription", parameters: { "type": "object", "required": [ @@ -61,8 +60,7 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { }); FunctionTool calculateLaminaStressTool = FunctionTool( name: "calculate_lamina_stress", - description: - "Calculates the stress for a lamina. $commonDescription", + description: "Calculates the stress for a lamina. $commonDescription", parameters: { "type": "object", "required": [ @@ -94,7 +92,7 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { FunctionTool calculateLaminatePlatePropertiesTool = FunctionTool( name: "calculate_laminate_plate_properties", description: - "Calculates the laminate plate properties. $commonDescription", + "Calculates the laminate plate properties. $commonDescription", parameters: { "type": "object", "required": [ @@ -116,13 +114,17 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { "minimum": -1 }, "layup_sequence": {"type": "string", "default": "[0/90/45/-45]s"}, - "layer_thickness": {"type": "number", "default": 0.125, "exclusiveMinimum": 0} + "layer_thickness": { + "type": "number", + "default": 0.125, + "exclusiveMinimum": 0 + } } }); FunctionTool calculateLaminate3DPropertiesTool = FunctionTool( name: "calculate_laminate_3d_properties", description: - "Calculates the laminate plate properties. $commonDescription", + "Calculates the laminate plate properties. $commonDescription", parameters: { "type": "object", "required": [ @@ -131,7 +133,7 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { "G12", "nu12", "nu23" - "layup_sequence", + "layup_sequence", "layer_thickness", ], "properties": { @@ -151,7 +153,99 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { "minimum": -1 }, "layup_sequence": {"type": "string", "default": "[0/90/45/-45]s"}, - "layer_thickness": {"type": "number", "default": 0.125, "exclusiveMinimum": 0} + "layer_thickness": { + "type": "number", + "default": 0.125, + "exclusiveMinimum": 0 + } + } + }); + FunctionTool calculateLaminarStrainTool = FunctionTool( + name: "calculate_laminar_strain", + description: + "Calculates the strains for a laminar/laminate. $commonDescription", + parameters: { + "type": "object", + "required": [ + "E1", + "E2", + "G12", + "nu12", + "layupSequence", + "layerThickness", + "N11", + "N22", + "N12", + "M11", + "M22", + "M12" + ], + "properties": { + "E1": {"type": "number", "default": 150000, "exclusiveMinimum": 0}, + "E2": {"type": "number", "default": 10000, "exclusiveMinimum": 0}, + "G12": {"type": "number", "default": 5000, "exclusiveMinimum": 0}, + "nu12": { + "type": "number", + "default": 0.3, + "maximum": 0.5, + "minimum": -1 + }, + "layup_sequence": {"type": "string", "default": "[0/90/45/-45]s"}, + "layer_thickness": { + "type": "number", + "default": 0.125, + "exclusiveMinimum": 0 + }, + "N11": {"type": "number", "default": 1}, + "N22": {"type": "number", "default": 0}, + "N12": {"type": "number", "default": 0}, + "M11": {"type": "number", "default": 0}, + "M22": {"type": "number", "default": 0}, + "M12": {"type": "number", "default": 0} + } + }); + FunctionTool calculateLaminarStressTool = FunctionTool( + name: "calculate_laminar_stress", + description: + "Calculates the stress for a laminar/laminate. $commonDescription", + parameters: { + "type": "object", + "required": [ + "E1", + "E2", + "G12", + "nu12", + "layupSequence", + "layerThickness", + "epsilon11", + "epsilon22", + "epsilon12", + "kappa11", + "kappa22", + "kappa12" + ], + "properties": { + "E1": {"type": "number", "default": 150000, "exclusiveMinimum": 0}, + "E2": {"type": "number", "default": 10000, "exclusiveMinimum": 0}, + "G12": {"type": "number", "default": 5000, "exclusiveMinimum": 0}, + "nu12": { + "type": "number", + "default": 0.3, + "maximum": 0.5, + "minimum": -1 + }, + "layup_sequence": {"type": "string", "default": "[0/90/45/-45]s"}, + "layer_thickness": { + "type": "number", + "default": 0.125, + "exclusiveMinimum": 0 + }, + "epsilon11": {"type": "number", "default": 1e-5}, + "epsilon22": {"type": "number", "default": 0}, + "epsilon12": {"type": "number", "default": 0}, + "kappa11": {"type": "number", "default": 0}, + "kappa22": {"type": "number", "default": 0}, + "kappa12": {"type": "number", "default": 0} } }); return [ @@ -159,7 +253,9 @@ class FunctionToolsRepositoryImp extends FunctionToolsRepository { calculateLaminaStrainTool, calculateLaminaStressTool, calculateLaminatePlatePropertiesTool, - calculateLaminate3DPropertiesTool + calculateLaminate3DPropertiesTool, + calculateLaminarStrainTool, + calculateLaminarStressTool, ]; } } diff --git a/lib/presentation/chat/viewModels/chat_view_model.dart b/lib/presentation/chat/viewModels/chat_view_model.dart index f3e9c01..16dcc7d 100644 --- a/lib/presentation/chat/viewModels/chat_view_model.dart +++ b/lib/presentation/chat/viewModels/chat_view_model.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:composite_calculator/calculators/lamina_engineering_constants_calculator.dart'; import 'package:composite_calculator/calculators/lamina_stress_strain_calculator.dart'; +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'; @@ -9,6 +10,8 @@ import 'package:composite_calculator/models/lamina_engineering_constants_input.d import 'package:composite_calculator/models/lamina_engineering_constants_output.dart'; import 'package:composite_calculator/models/lamina_stress_strain_input.dart'; import 'package:composite_calculator/models/lamina_stress_strain_output.dart'; +import 'package:composite_calculator/models/laminar_stress_strain_input.dart'; +import 'package:composite_calculator/models/laminar_stress_strain_output.dart'; import 'package:composite_calculator/models/laminate_3d_properties_input.dart'; import 'package:composite_calculator/models/laminate_3d_properties_output.dart'; import 'package:composite_calculator/models/laminate_plate_properties_input.dart'; @@ -48,6 +51,8 @@ class ChatViewModel extends ChangeNotifier { "Calculate lamina stress", "Calculate laminate plate properties", "Calculate laminate 3D properties", + "Calculate laminar strain", + "Calculate laminate stress", "What is the upper bound of Young's modulus for composites?", // "How to use SwiftComp?", // "Give me some math equations.", @@ -188,6 +193,19 @@ class ChatViewModel extends ChangeNotifier { Laminate3DPropertiesOutput output = Laminate3DPropertiesCalculator.calculate(input); outputString = output.toJson().toString(); + } else if (functionName == "calculate_laminar_strain") { + LaminarStressStrainInput input = + LaminarStressStrainInput.fromJson(argumentsJson); + LaminarStressStrainOutput output = + LaminarStressStrainCalculator.calculate(input); + outputString = output.toJson().toString(); + } else if (functionName == "calculate_laminar_stress") { + LaminarStressStrainInput input = + LaminarStressStrainInput.fromJson(argumentsJson); + input.tensorType = TensorType.strain; + LaminarStressStrainOutput output = + LaminarStressStrainCalculator.calculate(input); + outputString = output.toJson().toString(); } _chatSessionUseCase.addMessageToSession(selectedSession!, Message(role: "tool", content: outputString, tool_call_id: tool.id)); diff --git a/lib/presentation/tools/model/mechanical_tensor_model.dart b/lib/presentation/tools/model/mechanical_tensor_model.dart index 05bb6fe..9faeb11 100644 --- a/lib/presentation/tools/model/mechanical_tensor_model.dart +++ b/lib/presentation/tools/model/mechanical_tensor_model.dart @@ -40,7 +40,14 @@ class LaminateStress extends MechanicalTensor { double? M22; double? M12; - LaminateStress(); + LaminateStress({ + this.N11, + this.N22, + this.N12, + this.M11, + this.M22, + this.M12, + }); LaminateStress.from( this.N11, this.N22, this.N12, this.M11, this.M22, this.M12); @@ -69,7 +76,14 @@ class LaminateStrain extends MechanicalTensor { double? kappa22; double? kappa12; - LaminateStrain(); + LaminateStrain({ + this.epsilon11, + this.epsilon22, + this.epsilon12, + this.kappa11, + this.kappa22, + this.kappa12, + }); LaminateStrain.from(this.epsilon11, this.epsilon22, this.epsilon12, this.kappa11, this.kappa22, this.kappa12); diff --git a/lib/presentation/tools/page/laminate_plate_properties_result_page.dart b/lib/presentation/tools/page/laminate_plate_properties_result_page.dart index 62ffffc..a2b6602 100644 --- a/lib/presentation/tools/page/laminate_plate_properties_result_page.dart +++ b/lib/presentation/tools/page/laminate_plate_properties_result_page.dart @@ -4,10 +4,8 @@ import 'package:composite_calculator/composite_calculator.dart'; import 'package:composite_calculator/models/in-plane-properties.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/generated/l10n.dart'; -import 'package:swiftcomp/presentation/tools/model/in_plane_properties_model.dart'; import 'package:swiftcomp/presentation/tools/widget/result_3by3_matrix.dart'; import 'package:swiftcomp/presentation/more/tool_setting_page.dart'; import 'package:swiftcomp/util/NumberPrecisionHelper.dart'; diff --git a/lib/presentation/tools/page/laminate_stress_strain_page.dart b/lib/presentation/tools/page/laminate_stress_strain_page.dart index 029c509..b778e10 100644 --- a/lib/presentation/tools/page/laminate_stress_strain_page.dart +++ b/lib/presentation/tools/page/laminate_stress_strain_page.dart @@ -1,5 +1,8 @@ import 'dart:math'; +import 'package:composite_calculator/composite_calculator.dart'; +import 'package:composite_calculator/models/laminar_stress_strain_input.dart'; +import 'package:composite_calculator/models/tensor_type.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; @@ -22,7 +25,8 @@ class LaminateStressStrainPage extends StatefulWidget { const LaminateStressStrainPage({Key? key}) : super(key: key); @override - _LaminateStressStrainPageState createState() => _LaminateStressStrainPageState(); + _LaminateStressStrainPageState createState() => + _LaminateStressStrainPageState(); } class _LaminateStressStrainPageState extends State { @@ -37,10 +41,13 @@ class _LaminateStressStrainPageState 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(), ), - title: Text(S.of(context).Laminar_stressstrain), + title: Text(S + .of(context) + .Laminar_stressstrain), ), floatingActionButton: FloatingActionButton.extended( onPressed: () { @@ -49,7 +56,9 @@ class _LaminateStressStrainPageState extends State { }); _calculate(); }, - label: Text(S.of(context).Calculate), + label: Text(S + .of(context) + .Calculate), ), body: GestureDetector( behavior: HitTestBehavior.opaque, @@ -62,7 +71,10 @@ class _LaminateStressStrainPageState extends State { crossAxisCount: 8, itemCount: itemList.length, staggeredTileBuilder: (int index) => - StaggeredTile.fit(MediaQuery.of(context).size.width > 600 ? 4 : 8), + StaggeredTile.fit(MediaQuery + .of(context) + .size + .width > 600 ? 4 : 8), mainAxisSpacing: 12, crossAxisSpacing: 12, itemBuilder: (BuildContext context, int index) { @@ -106,116 +118,48 @@ class _LaminateStressStrainPageState extends State { !mechanicalTensor.isValid()) { return; } - Matrix A = Matrix.fill(3, 3); - Matrix B = Matrix.fill(3, 3); - Matrix D = Matrix.fill(3, 3); - double thickness = layerThickness.value!; - int nPly = layupSequence.layups!.length; - - List bzi = []; - List Q = []; - for (int i = 1; i <= nPly; i++) { - double bz = (-(nPly + 1) * thickness) / 2 + i * thickness; - bzi.add(bz); - } - - for (int i = 0; i < nPly; i++) { - double layup = layupSequence.layups![i]; - double e1 = transverselyIsotropicMaterial.e1!; - double e2 = transverselyIsotropicMaterial.e2!; - double g12 = transverselyIsotropicMaterial.g12!; - double nu12 = transverselyIsotropicMaterial.nu12!; - - double angleRadian = layup * pi / 180; - double s = sin(angleRadian); - double c = cos(angleRadian); - - Matrix Sep = Matrix([ - [1 / e1, -nu12 / e1, 0], - [-nu12 / e1, 1 / e2, 0], - [0, 0, 1 / g12] - ]); - - Matrix Qep = Sep.inverse(); - - Matrix Rsigmae = Matrix([ - [c * c, s * s, -2 * s * c], - [s * s, c * c, 2 * s * c], - [s * c, -s * c, c * c - s * s] - ]); - - Matrix Qe = Rsigmae * Qep * Rsigmae.transpose(); - - Q.add(Qe); - - A += Qe * thickness; - B += Qe * thickness * bzi[i]; - D += Qe * (thickness * bzi[i] * bzi[i] + pow(thickness, 3) / 12); - } - - Matrix ABD = Matrix([ - [A[0][0], A[0][1], A[0][2], B[0][0], B[0][1], B[0][2]], - [A[1][0], A[1][1], A[1][2], B[1][0], B[1][1], B[1][2]], - [A[2][0], A[2][1], A[2][2], B[2][0], B[2][1], B[2][2]], - [B[0][0], B[0][1], B[0][2], D[0][0], D[0][1], D[0][2]], - [B[1][0], B[1][1], B[1][2], D[1][0], D[1][1], D[1][2]], - [B[2][0], B[2][1], B[2][2], D[2][0], D[2][1], D[2][2]] - ]); - - Matrix ABD_inverese = ABD.inverse(); + LaminarStressStrainInput input = LaminarStressStrainInput( + E1: transverselyIsotropicMaterial.e1 ?? 0, + E2: transverselyIsotropicMaterial.e2 ?? 0, + G12: transverselyIsotropicMaterial.g12 ?? 0, + nu12: transverselyIsotropicMaterial.nu12 ?? 0, + layupSequence: layupSequence.stringValue, + layerThickness: layerThickness.value ?? 0, + ); MechanicalTensor resultTensor; if (mechanicalTensor is LaminateStress) { - double N11 = (mechanicalTensor as LaminateStress).N11!; - double N22 = (mechanicalTensor as LaminateStress).N22!; - double N12 = (mechanicalTensor as LaminateStress).N12!; - double M11 = (mechanicalTensor as LaminateStress).M11!; - double M22 = (mechanicalTensor as LaminateStress).M22!; - double M12 = (mechanicalTensor as LaminateStress).M12!; - Matrix stressVector = Matrix([ - [N11], - [N22], - [N12], - [M11], - [M22], - [M12], - ]); - Matrix strainVector = ABD_inverese * stressVector; - resultTensor = LaminateStrain.from(strainVector[0][0], strainVector[1][0], strainVector[2][0], - strainVector[3][0], strainVector[4][0], strainVector[5][0]); + input.tensorType = TensorType.stress; + input.N11 = (mechanicalTensor as LaminateStress).N11 ?? 0; + input.N22 = (mechanicalTensor as LaminateStress).N22 ?? 0; + input.N12 = (mechanicalTensor as LaminateStress).N12 ?? 0; + input.M11 = (mechanicalTensor as LaminateStress).M11 ?? 0; + input.M22 = (mechanicalTensor as LaminateStress).M22 ?? 0; + input.M12 = (mechanicalTensor as LaminateStress).M12 ?? 0; } else { - double epsilon11 = (mechanicalTensor as LaminateStrain).epsilon11!; - double epsilon22 = (mechanicalTensor as LaminateStrain).epsilon22!; - double epsilon12 = (mechanicalTensor as LaminateStrain).epsilon12!; - double kappa11 = (mechanicalTensor as LaminateStrain).kappa11!; - double kappa22 = (mechanicalTensor as LaminateStrain).kappa22!; - double kappa12 = (mechanicalTensor as LaminateStrain).kappa12!; - Matrix strainVector = Matrix([ - [epsilon11], - [epsilon22], - [epsilon12], - [kappa11], - [kappa22], - [kappa12] - ]); - Matrix stressVector = ABD * strainVector; - resultTensor = LaminateStress.from(stressVector[0][0], stressVector[1][0], stressVector[2][0], - stressVector[3][0], stressVector[4][0], stressVector[5][0]); + input.epsilon11 = (mechanicalTensor as LaminateStrain).epsilon11 ?? 0; + input.epsilon22 = (mechanicalTensor as LaminateStrain).epsilon22 ?? 0; + input.epsilon12 = (mechanicalTensor as LaminateStrain).epsilon12 ?? 0; + input.kappa11 = (mechanicalTensor as LaminateStrain).kappa11 ?? 0; + input.kappa22 = (mechanicalTensor as LaminateStrain).kappa22 ?? 0; + input.kappa12 = (mechanicalTensor as LaminateStrain).kappa12 ?? 0; } - // print(A); - // print(D); - // print(mechanicalTensor); - print(resultTensor); + List QMatrices = LaminarStressStrainCalculator.getQMatrices( + input); + LaminarStressStrainOutput output = LaminarStressStrainCalculator.calculate( + input); + Navigator.push( context, MaterialPageRoute( - builder: (context) => LaminateStressStrainResultPage( + builder: (context) => + LaminateStressStrainResultPage( inputTensor: mechanicalTensor, - resultTensor: resultTensor, - thickness: thickness, - Q: Q, + output: output, + thickness: input.layerThickness, + Q: QMatrices, ))); } } diff --git a/lib/presentation/tools/page/laminate_stress_strain_result_page.dart b/lib/presentation/tools/page/laminate_stress_strain_result_page.dart index f093599..debbfde 100644 --- a/lib/presentation/tools/page/laminate_stress_strain_result_page.dart +++ b/lib/presentation/tools/page/laminate_stress_strain_result_page.dart @@ -1,5 +1,7 @@ import 'dart:math'; +import 'package:composite_calculator/composite_calculator.dart'; +import 'package:composite_calculator/models/tensor_type.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -13,23 +15,25 @@ import 'package:swiftcomp/util/NumberPrecisionHelper.dart'; class LaminateStressStrainResultPage extends StatefulWidget { final MechanicalTensor inputTensor; - final MechanicalTensor resultTensor; + final LaminarStressStrainOutput output; final double thickness; final List Q; const LaminateStressStrainResultPage( {Key? key, required this.inputTensor, - required this.resultTensor, + required this.output, required this.thickness, required this.Q}) : super(key: key); @override - _LaminateStressStrainResultPageState createState() => _LaminateStressStrainResultPageState(); + _LaminateStressStrainResultPageState createState() => + _LaminateStressStrainResultPageState(); } -class _LaminateStressStrainResultPageState extends State { +class _LaminateStressStrainResultPageState + extends State { List epsilon11_datas = []; List epsilon22_datas = []; List epsilon12_datas = []; @@ -48,12 +52,12 @@ class _LaminateStressStrainResultPageState extends State 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), ), @@ -120,55 +127,84 @@ class _LaminateStressStrainResultPageState extends State - StaggeredTile.fit(MediaQuery.of(context).size.width > 600 ? 4 : 8), + itemCount: resultItems.length, + staggeredTileBuilder: (int index) => StaggeredTile.fit( + MediaQuery.of(context).size.width > 600 ? 4 : 8), mainAxisSpacing: 12, crossAxisSpacing: 12, itemBuilder: (BuildContext context, int index) { - return [ - ResultStressStrainWidget( - mechanicalTensor: widget.resultTensor, - ), - LaminarStressStrainLineChat( - title: "ε11 through the thickness", - data: epsilon11_datas, - ), - LaminarStressStrainLineChat( - title: "ε22 through the thickness", - data: epsilon22_datas, - ), - LaminarStressStrainLineChat( - title: "ε12 through the thickness", - data: epsilon12_datas, - ), - LaminarStressStrainLineChat( - title: "σ11 through the thickness", - data: sigma11_datas, - ), - LaminarStressStrainLineChat( - title: "σ22 through the thickness", - data: sigma22_datas, - ), - LaminarStressStrainLineChat( - title: "σ12 through the thickness", - data: sigma12_datas, - ) - ][index]; + return resultItems[index]; }), )); } + + List get resultItems { + return [ + ResultStressStrainWidget( + mechanicalTensor: resultTensor, + ), + LaminarStressStrainLineChat( + title: "ε11 through the thickness", + data: epsilon11_datas, + ), + LaminarStressStrainLineChat( + title: "ε22 through the thickness", + data: epsilon22_datas, + ), + LaminarStressStrainLineChat( + title: "ε12 through the thickness", + data: epsilon12_datas, + ), + LaminarStressStrainLineChat( + title: "σ11 through the thickness", + data: sigma11_datas, + ), + LaminarStressStrainLineChat( + title: "σ22 through the thickness", + data: sigma22_datas, + ), + LaminarStressStrainLineChat( + title: "σ12 through the thickness", + data: sigma12_datas, + ) + ]; + } + + MechanicalTensor get resultTensor { + if (widget.output.tensorType == TensorType.stress) { + return LaminateStress( + N11: widget.output.N11, + N22: widget.output.N22, + N12: widget.output.N12, + M11: widget.output.M11, + M22: widget.output.M22, + M12: widget.output.M12, + ); + } else { + return LaminateStrain( + epsilon11: widget.output.epsilon11, + epsilon22: widget.output.epsilon22, + epsilon12: widget.output.epsilon12, + kappa11: widget.output.kappa11, + kappa22: widget.output.kappa22, + kappa12: widget.output.kappa12, + ); + } + } } class ResultStressStrainWidget extends StatelessWidget { final MechanicalTensor mechanicalTensor; - const ResultStressStrainWidget({Key? key, required this.mechanicalTensor}) : super(key: key); + + const ResultStressStrainWidget({Key? key, required this.mechanicalTensor}) + : super(key: key); _propertyRow(BuildContext context, String title, double? value) { return Consumer(builder: (context, precs, child) { return SizedBox( height: 40, - child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + child: + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: Theme.of(context).textTheme.titleMedium, @@ -185,7 +221,8 @@ class ResultStressStrainWidget extends StatelessWidget { String getValue(double? value, int precision) { String valueString = ""; if (value != null) { - valueString = value == 0 ? "0" : value.toStringAsExponential(precision).toString(); + valueString = + value == 0 ? "0" : value.toStringAsExponential(precision).toString(); } return valueString; } @@ -264,7 +301,9 @@ class ResultStressStrainWidget extends StatelessWidget { class LaminarStressStrainLineChat extends StatelessWidget { final String title; final List data; - const LaminarStressStrainLineChat({Key? key, required this.title, required this.data}) + + const LaminarStressStrainLineChat( + {Key? key, required this.title, required this.data}) : super(key: key); @override @@ -302,8 +341,10 @@ class LaminarStressStrainLineChat extends StatelessWidget { lineTouchData: LineTouchData(enabled: false), gridData: FlGridData( show: true, - horizontalInterval: verticalInterval > 0 ? verticalInterval : null, - verticalInterval: horizontalInterval > 0 ? horizontalInterval : null, + horizontalInterval: + verticalInterval > 0 ? verticalInterval : null, + verticalInterval: + horizontalInterval > 0 ? horizontalInterval : null, drawHorizontalLine: true, drawVerticalLine: true, ), @@ -334,7 +375,8 @@ class LaminarStressStrainLineChat extends StatelessWidget { borderData: FlBorderData( show: true, border: const Border( - left: BorderSide(color: Colors.grey), bottom: BorderSide(color: Colors.grey))), + left: BorderSide(color: Colors.grey), + bottom: BorderSide(color: Colors.grey))), minX: minX, maxX: maxX, minY: minY,