-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add laminate stress strain function tool (#16)
- Loading branch information
1 parent
fb22db0
commit 0f4c7e3
Showing
11 changed files
with
657 additions
and
170 deletions.
There are no files selected for viewing
156 changes: 156 additions & 0 deletions
156
composite_calculator/lib/calculators/laminar_stress_strain_calculator.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<double> 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<double> bzi = []; | ||
List<Matrix> 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<Matrix> getQMatrices(LaminarStressStrainInput input) { | ||
double thickness = input.layerThickness; | ||
List<double> 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<double> bzi = []; | ||
List<Matrix> 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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
composite_calculator/lib/models/laminar_stress_strain_input.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String, dynamic> 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<String, dynamic> 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(), | ||
); | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
composite_calculator/lib/models/laminar_stress_strain_output.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String, double> toJson() { | ||
Map<String, double> 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; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
composite_calculator/test/laminar_stress_strain_calculator_tests.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)); | ||
}); | ||
|
||
}); | ||
} |
Oops, something went wrong.