add liebermanIteration function

This commit is contained in:
wyq 2024-06-09 17:51:36 +08:00
parent b11475d83f
commit 54476160dd
4 changed files with 68 additions and 15 deletions

View File

@ -19,16 +19,16 @@
</Path> </Path>
<File> <File>
<OpenedFiles> <OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_2.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/>
</OpenedFiles> </OpenedFiles>
<RecentFiles> <RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_2.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/>
</RecentFiles> </RecentFiles>
</File> </File>
<Font> <Font>
@ -36,5 +36,5 @@
</Font> </Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/> <LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/> <Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1398,806"/> <Startup MainFormLocation="-7,0" MainFormSize="1493,844"/>
</MeteoInfo> </MeteoInfo>

View File

@ -55,20 +55,26 @@ def _grad_atmos(longitude, latitude, H):
grad_y = grad_y / dy grad_y = grad_y / dy
return grad_x, grad_y return grad_x, grad_y
def velocity_potential(longitude, latitude, u, v, loop_max=1e10, epsilon=1e-10): def velocity_potential(longitude, latitude, u, v, loop_max=1e6, epsilon=1e-7, sor_index=0.2):
""" """
Calculate velocity potential using Richardson iterative method. Calculate velocity potential using Richardson iterative method.
Parameters Parameters
---------- ----------
lon : (M, N) `array` lon : (M, N) `array`
longitude array longitude array.
lat : (M, N) `array` lat : (M, N) `array`
latitude array latitude array.
u : (M, N) `array` u : (M, N) `array`
x component of the wind x component of the wind.
v : (M, N) `array` v : (M, N) `array`
y component of the wind y component of the wind.
loop_max : `int`
Maximum iteration loop number. Default is `1e6`.
epsilon : `float`
Minimum error value. Default is `1e-7`
sor_index : `float`
Super relaxation coefficient [0.2 - 0.5]. Default is `0.2`.
Returns Returns
------- -------
@ -81,8 +87,8 @@ def velocity_potential(longitude, latitude, u, v, loop_max=1e10, epsilon=1e-10):
divh = _divh_atmos(longitude, latitude, u, v) # vertical divergence divh = _divh_atmos(longitude, latitude, u, v) # vertical divergence
dx2 = _dx_atmos(longitude, latitude)**2 # square of latitude gradient dx2 = _dx_atmos(longitude, latitude)**2 # square of latitude gradient
dy2 = _dy_atmos(latitude)**2 # square of longitude gradient dy2 = _dy_atmos(latitude)**2 # square of longitude gradient
phi = np.NDArray(MeteoMath.richardsonIteration(divh._array, dx2._array, dy2._array, phi = np.NDArray(MeteoMath.liebermanIteration(divh._array, dx2._array, dy2._array,
loop_max, epsilon)) loop_max, epsilon, sor_index))
phi = -phi phi = -phi
# divergence wind # divergence wind
@ -98,7 +104,7 @@ def velocity_potential(longitude, latitude, u, v, loop_max=1e10, epsilon=1e-10):
return phi, Uphi, Vphi return phi, Uphi, Vphi
def stream_function(longitude, latitude, u, v, loop_max=int(1e10), epsilon=1e-10): def stream_function(longitude, latitude, u, v, loop_max=int(1e10), epsilon=1e-10, sor_index=0.2):
""" """
Calculate stream function using Richardson iterative method. Calculate stream function using Richardson iterative method.
@ -112,6 +118,12 @@ def stream_function(longitude, latitude, u, v, loop_max=int(1e10), epsilon=1e-10
x component of the wind x component of the wind
v : (M, N) `array` v : (M, N) `array`
y component of the wind y component of the wind
loop_max : `int`
Maximum iteration loop number. Default is `1e6`.
epsilon : `float`
Minimum error value. Default is `1e-7`
sor_index : `float`
Super relaxation coefficient [0.2 - 0.5]. Default is `0.2`.
Returns Returns
------- -------
@ -124,8 +136,8 @@ def stream_function(longitude, latitude, u, v, loop_max=int(1e10), epsilon=1e-10
curlz = _curlz_atmos(longitude, latitude, u, v) # vorticity curlz = _curlz_atmos(longitude, latitude, u, v) # vorticity
dx2 = _dx_atmos(longitude, latitude)**2 # square of latitude gradient dx2 = _dx_atmos(longitude, latitude)**2 # square of latitude gradient
dy2 = _dy_atmos(latitude)**2 # square of longitude gradient dy2 = _dy_atmos(latitude)**2 # square of longitude gradient
psi = np.NDArray(MeteoMath.richardsonIteration(curlz._array, dx2._array, dy2._array, psi = np.NDArray(MeteoMath.liebermanIteration(curlz._array, dx2._array, dy2._array,
loop_max, epsilon)) loop_max, epsilon, sor_index))
psi = -psi psi = -psi
# vorticity wind # vorticity wind

View File

@ -1154,9 +1154,9 @@ public class MeteoMath {
// calculate residual // calculate residual
res.setDouble(i * n + j, (phi.getDouble((i + 1) * n + j) + res.setDouble(i * n + j, (phi.getDouble((i + 1) * n + j) +
phi.getDouble((i - 1) * n + j) - 2 * phi.getDouble(i * n + j)) / phi.getDouble((i - 1) * n + j) - 2 * phi.getDouble(i * n + j)) /
dx2.getDouble(i * n + j) + (phi.getDouble(i * n + j + 1) + dy2.getDouble(i * n + j) + (phi.getDouble(i * n + j + 1) +
phi.getDouble(i * n + j - 1) - 2 * phi.getDouble(i * n + j)) / phi.getDouble(i * n + j - 1) - 2 * phi.getDouble(i * n + j)) /
dy2.getDouble(i * n + j) + array.getDouble(i * n + j)); dx2.getDouble(i * n + j) + array.getDouble(i * n + j));
// iterator // iterator
phi.setDouble(i * n + j, phi.getDouble(i * n + j) + res.getDouble(i * n + j) / phi.setDouble(i * n + j, phi.getDouble(i * n + j) + res.getDouble(i * n + j) /
(2 / dx2.getDouble(i * n + j) + 2 / dy2.getDouble(i * n + j))); (2 / dx2.getDouble(i * n + j) + 2 / dy2.getDouble(i * n + j)));
@ -1171,4 +1171,45 @@ public class MeteoMath {
return phi; return phi;
} }
/**
* Lieberman's iteration method for calculating Poisson equation
*
* @param array Input array - 2D
* @param dx2 X gradient square
* @param dy2 Y gradient square
* @param loopMax Maximum loop number
* @param epsilon Minimum error value
* @param sorIndex Super relaxation coefficient
* @return Poisson equation output
*/
public static Array liebermanIteration(Array array, Array dx2, Array dy2, long loopMax, double epsilon,
double sorIndex) {
int[] shape = array.getShape();
int m = shape[0];
int n = shape[1];
Array phi = ArrayUtil.zeros(shape, DataType.DOUBLE);
Array res = ArrayUtil.full(shape, -9999., DataType.DOUBLE);
for (int k=0; k < loopMax; k++) {
for (int i = 1; i < m - 1; i++) {
for (int j = 1; j < n - 1; j++) {
// calculate residual
res.setDouble(i * n + j, (phi.getDouble((i + 1) * n + j) +
phi.getDouble((i - 1) * n + j) - 2 * phi.getDouble(i * n + j)) /
dy2.getDouble(i * n + j) + (phi.getDouble(i * n + j + 1) +
phi.getDouble(i * n + j - 1) - 2 * phi.getDouble(i * n + j)) /
dx2.getDouble(i * n + j) + array.getDouble(i * n + j));
// iterator
phi.setDouble(i * n + j, phi.getDouble(i * n + j) + (1 + sorIndex) * res.getDouble(i * n + j) /
(2 / dx2.getDouble(i * n + j) + 2 / dy2.getDouble(i * n + j)));
}
}
if (ArrayMath.max(res).doubleValue() < epsilon) {
break;
}
}
return phi;
}
} }