Skip to content

Commit

Permalink
Merge pull request #6 from andrei-punko/add-task-with-border-types-2-…
Browse files Browse the repository at this point in the history
…conditions

Add solution of diffusion problem with border types 2 conditions
  • Loading branch information
andrei-punko authored Oct 28, 2024
2 parents a727719 + 67b8beb commit 343d66d
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 12 deletions.
5 changes: 3 additions & 2 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ and solve it with help of tridiagonal matrix algorithm (or Thomas algorithm) (or
## Usage notes

Check solved problems in tests:
- [ParabolicEquationSolverTest](src/test/java/by/andd3dfx/math/pde/solver/ParabolicEquationSolverTest.java)
- [HyperbolicEquationSolverTest](src/test/java/by/andd3dfx/math/pde/solver/HyperbolicEquationSolverTest.java)
- [Diffusion problem with type 1 of both condition types](src/test/java/by/andd3dfx/math/pde/solver/ParabolicEquationSolver11Test.java)
- [Diffusion problem with type 2 of both condition types](src/test/java/by/andd3dfx/math/pde/solver/ParabolicEquationSolver22Test.java)
- [Wave equation (plucked string) with type 1 of both condition types](src/test/java/by/andd3dfx/math/pde/solver/HyperbolicEquationSolver11Test.java)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

/**
* <pre>
* Test for HyperbolicEquationSolver with type 1 of border conditions on both sides.
*
* Solution of wave equation: Utt = c^2*Uxx
* - constant displacement U=0 on the left & right borders
* - initial displacement with triangle profile (see method getU0(x))
Expand All @@ -20,7 +22,7 @@
*
* @see <a href="https://math.libretexts.org/Bookshelves/Differential_Equations/Differential_Equations_(Chasnov)/09%3A_Partial_Differential_Equations/9.06%3A_Solution_of_the_Wave_Equation">article</a>
*/
class HyperbolicEquationSolverTest {
class HyperbolicEquationSolver11Test {

private final double U_MAX = 0.005; // Max displacement, m
private final double L = 0.100; // Length of string, m
Expand All @@ -43,10 +45,10 @@ void solve() {

// Save numeric solution to file
var numericU = solution.gUt(TIME);
FileUtil.save(numericU, "./build/hyperbolic-numeric.txt", true);
FileUtil.save(numericU, "./build/hyperbolic11-numeric.txt", true);

// Save analytic solution to file
FileUtil.saveFunc(solution.area().x(), (x) -> analyticSolution(x, TIME), "./build/hyperbolic-analytic.txt");
FileUtil.saveFunc(solution.area().x(), (x) -> analyticSolution(x, TIME), "./build/hyperbolic11-analytic.txt");

// Compare numeric & analytic solutions
for (var i = 0; i < numericU.getN(); i++) {
Expand Down Expand Up @@ -103,7 +105,7 @@ private double getU0(double x) {
private double analyticSolution(double x, double t) {
var result = 0d;
for (int n = 1; n <= 100; n++) {
result += b(n) * sin(n * PI * x / L) * cos(n * PI * C_coeff * t / L);
result += b_n(n) * sin(n * PI * x / L) * cos(n * PI * C_coeff * t / L);
}
return result;
}
Expand All @@ -114,7 +116,7 @@ private double analyticSolution(double x, double t) {
* @param n number of coefficient
* @return b_n value
*/
private double b(int n) {
private double b_n(int n) {
var integral = 0d;
var N = 100d;
var dx = L / N;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

/**
* <pre>
* Test for ParabolicEquationSolver with type 1 of border conditions on both sides.
*
* Solution of diffusion equation: Ut = D*Uxx
* - constant concentration C=0 on the left & right borders
* - initial concentration with triangle profile: most mass concentrated in the center (see method getU0(x))
Expand All @@ -20,7 +22,7 @@
*
* @see <a href="https://math.libretexts.org/Bookshelves/Differential_Equations/Differential_Equations_(Chasnov)/09%3A_Partial_Differential_Equations/9.05%3A_Solution_of_the_Diffusion_Equation">article</a>
*/
class ParabolicEquationSolverTest {
class ParabolicEquationSolver11Test {

private final double C_MAX = 100.0;
private final double L = 0.001; // Thickness of plate, m
Expand All @@ -43,10 +45,10 @@ void solve() {

// Save numeric solution to file
var numericU = solution.gUt(TIME);
FileUtil.save(numericU, "./build/parabolic-numeric.txt", true);
FileUtil.save(numericU, "./build/parabolic11-numeric.txt", true);

// Save analytic solution to file
FileUtil.saveFunc(solution.area().x(), (x) -> analyticSolution(x, TIME), "./build/parabolic-analytic.txt");
FileUtil.saveFunc(solution.area().x(), (x) -> analyticSolution(x, TIME), "./build/parabolic11-analytic.txt");

// Compare numeric & analytic solutions
for (var i = 0; i < numericU.getN(); i++) {
Expand Down Expand Up @@ -106,7 +108,7 @@ private double getU0(double x) {
private double analyticSolution(double x, double t) {
var result = 0d;
for (int n = 1; n <= 100; n++) {
result += b(n) * sin(n * PI * x / L) * exp(-n * n * PI * PI * D * t / (L * L));
result += b_n(n) * sin(n * PI * x / L) * exp(-Math.pow(n * PI / L, 2.) * D * t);
}
return result;
}
Expand All @@ -117,7 +119,7 @@ private double analyticSolution(double x, double t) {
* @param n number of coefficient
* @return b_n value
*/
private double b(int n) {
private double b_n(int n) {
var integral = 0d;
var N = 100d;
var dx = L / N;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package by.andd3dfx.math.pde.solver;

import by.andd3dfx.math.pde.border.BorderConditionType2;
import by.andd3dfx.math.pde.equation.ParabolicEquation;
import by.andd3dfx.util.FileUtil;
import org.junit.jupiter.api.Test;

import static java.lang.Math.PI;
import static java.lang.Math.cos;
import static java.lang.Math.exp;
import static org.assertj.core.api.Assertions.assertThat;

/**
* <pre>
* Test for ParabolicEquationSolver with type 2 of border conditions on both sides.
*
* Solution of diffusion equation: Ut = D*Uxx
* - sealed pipe ends, so no diffusion through the ends
* - initial concentration with triangle profile: most mass concentrated in the center (see method getU0(x))
* - constant diffusion coefficient
* </pre>
*
* @see <a href="https://math.libretexts.org/Bookshelves/Differential_Equations/Differential_Equations_(Chasnov)/09%3A_Partial_Differential_Equations/9.05%3A_Solution_of_the_Diffusion_Equation">article</a>
*/
class ParabolicEquationSolver22Test {

private final double C_MAX = 100.0;
private final double L = 0.001; // Thickness of plate, m
private final double TIME = 1; // Investigated time, sec
private final double D = 1e-9; // Diffusion coefficient

private final double h = L / 100.0;
private final double tau = TIME / 100.0;

// We allow difference between numeric & analytic solution no more than 1% of max concentration value
private final double EPSILON = C_MAX / 100.;

@Test
void solve() {
var diffusionEquation = buildParabolicEquation();

// Solve equation
var solution = new ParabolicEquationSolver()
.solve(diffusionEquation, h, tau);

// Save numeric solution to file
var numericU = solution.gUt(TIME);
FileUtil.save(numericU, "./build/parabolic22-numeric.txt", true);

// Save analytic solution to file
FileUtil.saveFunc(solution.area().x(), (x) -> analyticSolution(x, TIME), "./build/parabolic22-analytic.txt");

// Compare numeric & analytic solutions
for (var i = 0; i < numericU.getN(); i++) {
var x = numericU.x(i);
var numericY = numericU.y(i);
var analyticY = analyticSolution(x, TIME);
assertThat(Math.abs(numericY - analyticY)).isLessThanOrEqualTo(EPSILON);
}
}

private ParabolicEquation buildParabolicEquation() {
var leftBorderCondition = new BorderConditionType2();
var rightBorderCondition = new BorderConditionType2();

return new ParabolicEquation(0, L, TIME, leftBorderCondition, rightBorderCondition) {
@Override
public double gK(double x, double t, double U) {
return D;
}

@Override
public double gU0(double x) {
return getU0(x);
}
};
}

/**
* Initial concentration profile
*
* @param x space coordinate
* @return concentration C_0(x)
*/
private double getU0(double x) {
x /= L;
if (0.4 <= x && x <= 0.5) {
return C_MAX * (10 * x - 4);
}
if (0.5 <= x && x <= 0.6) {
return C_MAX * (-10 * x + 6);
}
return 0;
}

/**
* <pre>
* Analytic solution:
* U(x,t) = a_0/2 + Sum(a_n*u_n(x,t)) = a_0/2 + Sum(a_n*cos(n*PI*x/L))*exp(-(n*PI/L)^2 * D*t)
*
* According to <a href="https://math.libretexts.org/Bookshelves/Differential_Equations/Differential_Equations_(Chasnov)/09%3A_Partial_Differential_Equations/9.05%3A_Solution_of_the_Diffusion_Equation">article</a>
* </pre>
*
* @param x space coordinate
* @param t time
* @return concentration C(x,t)
*/
private double analyticSolution(double x, double t) {
var result = 0d;
for (int n = 1; n <= 100; n++) {
result += a_n(n) * cos(n * PI * x / L) * exp(-Math.pow(n * PI / L, 2.) * D * t);
}
return a_n(0) / 2. + result;
}

/**
* Coefficient a_n of a Fourier sine series
*
* @param n number of coefficient
* @return b_n value
*/
private double a_n(int n) {
var integral = 0d;
var N = 100d;
var dx = L / N;
for (int i = 0; i < N; i++) {
var x = dx * (i + 0.5);
integral += getU0(x) * cos(n * PI * x / L) * dx;
}
return 2. / L * integral;
}
}

0 comments on commit 343d66d

Please sign in to comment.