241104_vortex_lamb
This commit is contained in:
parent
acf2b36b8c
commit
5f6337078f
5
.gitignore
vendored
5
.gitignore
vendored
@ -0,0 +1,5 @@
|
|||||||
|
ParaView/
|
||||||
|
ParaView-X/
|
||||||
|
ParaView-O/
|
||||||
|
ParaView-E/
|
||||||
|
output/
|
||||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"github.copilot"
|
||||||
|
]
|
||||||
|
}
|
||||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"[cuda-cpp]": {
|
"[cuda-cpp]": {
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "disabled"
|
"C_Cpp.errorSquiggles": "disabled",
|
||||||
|
"python.analysis.extraPaths": [
|
||||||
|
"./ParaView/lib/python3.9/site-packages"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
Binary file not shown.
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import pycuda.driver as cuda
|
import pycuda.driver as cuda
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import struct
|
||||||
|
from scipy.special import jv, expi
|
||||||
from typing import List, Tuple, Union, Optional
|
from typing import List, Tuple, Union, Optional
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
@ -13,7 +15,7 @@ SOLID = 0b00000010
|
|||||||
GAS = 0b00000100
|
GAS = 0b00000100
|
||||||
INTERFACE = 0b00001000
|
INTERFACE = 0b00001000
|
||||||
SENSOR = 0b00010000
|
SENSOR = 0b00010000
|
||||||
|
V_TAYLOR = np.int32(1)
|
||||||
|
|
||||||
class FlowField:
|
class FlowField:
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -94,12 +96,14 @@ class FlowField:
|
|||||||
self.flag = np.ones(self.FIELD_SIZE, dtype=np.uint8)
|
self.flag = np.ones(self.FIELD_SIZE, dtype=np.uint8)
|
||||||
self.indx = np.zeros(self.FIELD_SIZE, dtype=np.int32)
|
self.indx = np.zeros(self.FIELD_SIZE, dtype=np.int32)
|
||||||
self.delta_curve = np.zeros(0, dtype=self.DATA_TYPE)
|
self.delta_curve = np.zeros(0, dtype=self.DATA_TYPE)
|
||||||
|
self.vortex_config = np.zeros(7, dtype=float)
|
||||||
|
|
||||||
self.ddf_gpu = cuda.mem_alloc(self.ddf.nbytes)
|
self.ddf_gpu = cuda.mem_alloc(self.ddf.nbytes)
|
||||||
self.temp_gpu = cuda.mem_alloc(self.ddf.nbytes)
|
self.temp_gpu = cuda.mem_alloc(self.ddf.nbytes)
|
||||||
self.flag_gpu = cuda.mem_alloc(self.flag.nbytes)
|
self.flag_gpu = cuda.mem_alloc(self.flag.nbytes)
|
||||||
self.indx_gpu = cuda.mem_alloc(self.indx.nbytes)
|
self.indx_gpu = cuda.mem_alloc(self.indx.nbytes)
|
||||||
self.delta_gpu = cuda.mem_alloc(1)
|
self.delta_gpu = cuda.mem_alloc(1)
|
||||||
|
self.vortex_gpu = cuda.mem_alloc(self.vortex_config.nbytes)
|
||||||
|
|
||||||
self.objects = {}
|
self.objects = {}
|
||||||
self.action = np.zeros(0, dtype=self.DATA_TYPE)
|
self.action = np.zeros(0, dtype=self.DATA_TYPE)
|
||||||
@ -181,7 +185,7 @@ class FlowField:
|
|||||||
self.action_gpu = cuda.mem_alloc(self.action.nbytes)
|
self.action_gpu = cuda.mem_alloc(self.action.nbytes)
|
||||||
|
|
||||||
self.obs = np.zeros(len(self.objects) * self.DIM, dtype=self.DATA_TYPE)
|
self.obs = np.zeros(len(self.objects) * self.DIM, dtype=self.DATA_TYPE)
|
||||||
if hasattr(self, "force_gpu"):
|
if hasattr(self, "obs_gpu"):
|
||||||
self.obs_gpu.free()
|
self.obs_gpu.free()
|
||||||
self.obs_gpu = cuda.mem_alloc(self.obs.nbytes)
|
self.obs_gpu = cuda.mem_alloc(self.obs.nbytes)
|
||||||
|
|
||||||
@ -236,12 +240,108 @@ class FlowField:
|
|||||||
self.ptx = cuda.module_from_file(compiler.kernel_path("kernel.ptx"))
|
self.ptx = cuda.module_from_file(compiler.kernel_path("kernel.ptx"))
|
||||||
self.step = self.ptx.get_function("OneStep")
|
self.step = self.ptx.get_function("OneStep")
|
||||||
|
|
||||||
|
def add_vortex(self, center: Tuple[float, float, float], radius: float, strength: float, direction: float, type: str):
|
||||||
|
x_c, y_c, z_c = center
|
||||||
|
|
||||||
|
if (
|
||||||
|
x_c - radius <= 0
|
||||||
|
or x_c + radius >= self.FIELD_SHAPE[0] - 1
|
||||||
|
or y_c - radius <= 0
|
||||||
|
or y_c + radius >= self.FIELD_SHAPE[1] - 1
|
||||||
|
):
|
||||||
|
raise ValueError("Vortex is out of bounds.")
|
||||||
|
|
||||||
|
if type not in ["lamb", "oseen", "taylor"]:
|
||||||
|
raise ValueError("Vortex type" + type + " is not supported.")
|
||||||
|
|
||||||
|
x = np.linspace(-x_c, self.FIELD_SHAPE[0] - 1 - x_c, self.FIELD_SHAPE[0])
|
||||||
|
y = np.linspace(-y_c, self.FIELD_SHAPE[1] - 1 - y_c, self.FIELD_SHAPE[1])
|
||||||
|
X, Y = np.meshgrid(x, y)
|
||||||
|
r = np.sqrt(X**2 + Y**2)
|
||||||
|
nu = self.field_config.viscosity
|
||||||
|
theta = np.arctan2(Y, X)
|
||||||
|
psi = np.zeros_like(r)
|
||||||
|
|
||||||
|
if type == "lamb":
|
||||||
|
b = 3.831705970207512
|
||||||
|
n = b / radius
|
||||||
|
u0 = strength
|
||||||
|
inside = r <= radius
|
||||||
|
outside = r > radius
|
||||||
|
|
||||||
|
psi[inside] = (2 * u0 / n / jv(0, b) * jv(1, n * r[inside]) - u0 * r[inside]) * np.sin(theta[inside])
|
||||||
|
psi[outside] = -u0 * radius**2 / r[outside] * np.sin(theta[outside])
|
||||||
|
|
||||||
|
u_vor = np.gradient(psi, axis=0)
|
||||||
|
v_vor = -np.gradient(psi, axis=1)
|
||||||
|
p_vor = -2 * (np.gradient(v_vor, axis=1) - np.gradient(u_vor, axis=0)) * psi - (u_vor**2 + v_vor**2) / 2
|
||||||
|
elif type == "oseen":
|
||||||
|
# 4 nu t = radius^2 / 4
|
||||||
|
kappa = 2 * np.pi * radius **2 * strength
|
||||||
|
u_vor = - kappa / (2 * np.pi * r) * (1 - np.exp(-4 * r**2 / radius**2)) * np.sin(theta)
|
||||||
|
v_vor = kappa / (2 * np.pi * r) * (1 - np.exp(-4 * r**2 / radius**2)) * np.cos(theta)
|
||||||
|
zeta = 4 * r**2 / radius**2
|
||||||
|
p_vor = -kappa**2 / 8 / np.pi**2 / r**2 * (-2 * zeta * (expi(-zeta) - expi(-2 * zeta)) + (1 - np.exp(-zeta))**2)
|
||||||
|
elif type == "taylor":
|
||||||
|
# 4 nu t = radius^2
|
||||||
|
M = strength * np.pi * radius**4 / 8 / nu
|
||||||
|
u_vor = - M * r * 4 * nu / radius**4 * np.exp(-r**2 / radius**2) * np.sin(theta)
|
||||||
|
v_vor = M * r * 4 * nu / radius**4 * np.exp(-r**2 / radius**2) * np.cos(theta)
|
||||||
|
p_vor = -4 * M**2 * nu**2 * np.exp(-2 * r**2 / radius**2) / np.pi**2 / radius**6
|
||||||
|
|
||||||
|
cuda.memcpy_dtoh(self.ddf, self.ddf_gpu)
|
||||||
|
ddf_temp = self.ddf.copy().reshape((self.LATTICE, self.FIELD_SHAPE[1], self.FIELD_SHAPE[0])).transpose(2, 1, 0)
|
||||||
|
u_ddf = ddf_temp[:, :, 1] + ddf_temp[:, :, 5] + ddf_temp[:, :, 8] - ddf_temp[:, :, 3] - ddf_temp[:, :, 6] - ddf_temp[:, :, 7]
|
||||||
|
v_ddf = ddf_temp[:, :, 2] + ddf_temp[:, :, 5] + ddf_temp[:, :, 6] - ddf_temp[:, :, 4] - ddf_temp[:, :, 7] - ddf_temp[:, :, 8]
|
||||||
|
p_ddf = np.sum(ddf_temp, axis=2) / 3
|
||||||
|
|
||||||
|
for i in range(self.FIELD_SHAPE[0]):
|
||||||
|
for j in range(self.FIELD_SHAPE[1]):
|
||||||
|
k = i + j * self.FIELD_SHAPE[0]
|
||||||
|
if (j == 0 or j == self.FIELD_SHAPE[1] - 1) or (i == 0 or i == self.FIELD_SHAPE[0] - 1):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
for e in range(self.LATTICE):
|
||||||
|
u = u_ddf[i, j] + u_vor[j, i]
|
||||||
|
v = v_ddf[i, j] + v_vor[j, i]
|
||||||
|
p = p_ddf[i, j] + p_vor[j, i]
|
||||||
|
eu = self.E[e][0] * u + self.E[e][1] * v
|
||||||
|
u2 = u ** 2 + v ** 2
|
||||||
|
self.ddf[k + e * self.FIELD_SIZE] = self.WW[e] * (3 * p + 3 * eu + 4.5 * eu ** 2 - 1.5 * u2)
|
||||||
|
|
||||||
|
cuda.memcpy_htod(self.ddf_gpu, self.ddf)
|
||||||
|
|
||||||
|
# def add_vortex_gpu(self, center: Tuple[float, float, float], radius: float, strength: float, direction: float, type: str):
|
||||||
|
# x_c, y_c, z_c = center
|
||||||
|
|
||||||
|
# if (
|
||||||
|
# x_c - radius <= 0
|
||||||
|
# or x_c + radius >= self.FIELD_SHAPE[0] - 1
|
||||||
|
# or y_c - radius <= 0
|
||||||
|
# or y_c + radius >= self.FIELD_SHAPE[1] - 1
|
||||||
|
# ):
|
||||||
|
# raise ValueError("Vortex is out of bounds.")
|
||||||
|
|
||||||
|
# if type not in ["lamb", "oseen", "taylor"]:
|
||||||
|
# raise ValueError("Vortex type" + type + " is not supported.")
|
||||||
|
|
||||||
|
# add_vortex = self.ptx.get_function("AddVortex")
|
||||||
|
|
||||||
|
# self.vortex_config[0:3] = np.array(center, dtype=float)
|
||||||
|
# self.vortex_config[3] = radius
|
||||||
|
# self.vortex_config[4] = strength
|
||||||
|
# self.vortex_config[5] = direction
|
||||||
|
# if type == "taylor":
|
||||||
|
# self.vortex_config[6] =
|
||||||
|
|
||||||
def run(self, num_steps: int, action_target: np.ndarray):
|
def run(self, num_steps: int, action_target: np.ndarray):
|
||||||
if (
|
if (
|
||||||
action_target.size != len(self.objects)
|
action_target.size != len(self.objects)
|
||||||
or action_target.dtype != self.DATA_TYPE
|
or action_target.dtype != self.DATA_TYPE
|
||||||
):
|
):
|
||||||
raise ValueError("action data type or size does not match the objects.")
|
raise ValueError("action data type or size does not match the objects.")
|
||||||
|
elif len(self.objects) == 0:
|
||||||
|
raise ValueError("No objects have been added to the flow field.")
|
||||||
|
|
||||||
weight = 0.1
|
weight = 0.1
|
||||||
stream = cuda.Stream()
|
stream = cuda.Stream()
|
||||||
|
|||||||
@ -187,4 +187,36 @@ extern "C"
|
|||||||
f[k + i * totalCells] = f_share[threadIdx.x + i * NT];
|
f[k + i * totalCells] = f_share[threadIdx.x + i * NT];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// __global__ void AddVortex(LBtype *f, int32_t *config)
|
||||||
|
// {
|
||||||
|
// __shared__ LBtype f_share[NT * NQ];
|
||||||
|
// int x, y, k;
|
||||||
|
// LBtype u, v, u_vor, v_vor;
|
||||||
|
// Index_lattice(x, y, k);
|
||||||
|
// int totalCells = NX * NY;
|
||||||
|
|
||||||
|
// for (int i = 0; i < NQ; i++)
|
||||||
|
// {
|
||||||
|
// f_share[threadIdx.x + i * NT] = f[k + i * totalCells];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// __syncthreads();
|
||||||
|
|
||||||
|
// u = f_share[threadIdx.x + 1 * NT] - f_share[threadIdx.x + 3 * NT] + f_share[threadIdx.x + 5 * NT] - f_share[threadIdx.x + 6 * NT] - f_share[threadIdx.x + 7 * NT] + f_share[threadIdx.x + 8 * NT];
|
||||||
|
// v = f_share[threadIdx.x + 2 * NT] - f_share[threadIdx.x + 4 * NT] + f_share[threadIdx.x + 5 * NT] + f_share[threadIdx.x + 6 * NT] - f_share[threadIdx.x + 7 * NT] - f_share[threadIdx.x + 8 * NT];
|
||||||
|
|
||||||
|
// if type & V_TAYLOR
|
||||||
|
// {
|
||||||
|
// u_vor = -2 * PI * U0 * sin(2 * PI * x / NX) * sin(2 * PI * y / NY);
|
||||||
|
// v_vor = 2 * PI * U0 * cos(2 * PI * x / NX) * cos(2 * PI * y / NY);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// u_vor = 0;
|
||||||
|
// v_vor = 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@ -9,15 +9,15 @@
|
|||||||
|
|
||||||
// flow parameters
|
// flow parameters
|
||||||
#define LBtype float
|
#define LBtype float
|
||||||
#define UX 12
|
#define UX 10
|
||||||
#define UY 20
|
#define UY 16
|
||||||
#define UZ 1
|
#define UZ 1
|
||||||
#define NX 1536
|
#define NX 1280
|
||||||
#define NY 640
|
#define NY 512
|
||||||
#define NZ 1
|
#define NZ 1
|
||||||
#define DIM 2
|
#define DIM 2
|
||||||
#define NQ 9
|
#define NQ 9
|
||||||
#define VIS 0.006
|
#define VIS 0.004
|
||||||
#define RHO 1.0
|
#define RHO 1.0
|
||||||
#define U0 0.01
|
#define U0 0.01
|
||||||
|
|
||||||
@ -29,6 +29,9 @@
|
|||||||
#define INTERFACE 0b00001000
|
#define INTERFACE 0b00001000
|
||||||
#define SENSOR 0b00010000
|
#define SENSOR 0b00010000
|
||||||
|
|
||||||
|
// vortex type
|
||||||
|
#define V_TAYLOR 0b00000001
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
#define N_OBJS 7
|
#define N_OBJS 6
|
||||||
// #define N_SENS 2
|
// #define N_SENS 2
|
||||||
@ -2,8 +2,8 @@
|
|||||||
"data_type": "FP32",
|
"data_type": "FP32",
|
||||||
"dimensionality": 2,
|
"dimensionality": 2,
|
||||||
"lattice": 9,
|
"lattice": 9,
|
||||||
"field_dim_in_U": [12, 20, 1],
|
"field_dim_in_U": [10, 16, 1],
|
||||||
"viscosity": 0.006,
|
"viscosity": 0.004,
|
||||||
"velocity": 0.01,
|
"velocity": 0.01,
|
||||||
"boundary_conditions": {
|
"boundary_conditions": {
|
||||||
"x": ["parabolic", "outflow"],
|
"x": ["parabolic", "outflow"],
|
||||||
|
|||||||
BIN
models/SEN_best4.zip
Normal file
BIN
models/SEN_best4.zip
Normal file
Binary file not shown.
BIN
models/d0a3o12_c0.zip
Normal file
BIN
models/d0a3o12_c0.zip
Normal file
Binary file not shown.
BIN
models/d1a3o12_re100_erase_d0.zip
Normal file
BIN
models/d1a3o12_re100_erase_d0.zip
Normal file
Binary file not shown.
Binary file not shown.
BIN
models/d1a3o12_sensonly_a0.zip
Normal file
BIN
models/d1a3o12_sensonly_a0.zip
Normal file
Binary file not shown.
BIN
models/d1a3o12_sensonly_a1.zip
Normal file
BIN
models/d1a3o12_sensonly_a1.zip
Normal file
Binary file not shown.
BIN
models/d1a3o12_sensonly_b0.zip
Normal file
BIN
models/d1a3o12_sensonly_b0.zip
Normal file
Binary file not shown.
BIN
models/vortex_lamb.zip
Normal file
BIN
models/vortex_lamb.zip
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
511
scripts/241009.ipynb
Normal file
511
scripts/241009.ipynb
Normal file
File diff suppressed because one or more lines are too long
586
scripts/241031_lambdipole.ipynb
Normal file
586
scripts/241031_lambdipole.ipynb
Normal file
File diff suppressed because one or more lines are too long
209
scripts/Paraview_test.ipynb
Normal file
209
scripts/Paraview_test.ipynb
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import sys\n",
|
||||||
|
"import os\n",
|
||||||
|
"\n",
|
||||||
|
"current_dir = os.path.dirname(os.path.abspath(\"__file__\"))\n",
|
||||||
|
"parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))\n",
|
||||||
|
"paraview_dir = os.path.join(parent_dir, \"ParaView\")\n",
|
||||||
|
"\n",
|
||||||
|
"os.environ['PYTHONPATH'] = f\"{paraview_dir}/lib:{paraview_dir}/lib/python3.9/site-packages\"\n",
|
||||||
|
"os.environ['LD_LIBRARY_PATH'] = os.path.join(paraview_dir, \"bin\")\n",
|
||||||
|
"\n",
|
||||||
|
"sys.path.append(parent_dir)\n",
|
||||||
|
"sys.path.append(os.path.join(paraview_dir, \"lib\"))\n",
|
||||||
|
"sys.path.append(os.path.join(paraview_dir, \"bin\"))\n",
|
||||||
|
"sys.path.append(os.path.join(paraview_dir, \"lib/python3.9/site-packages\"))\n",
|
||||||
|
"\n",
|
||||||
|
"# from paraview.simple import *\n",
|
||||||
|
"import paraview.simple as pv\n",
|
||||||
|
"from CelerisLab import FlowField\n",
|
||||||
|
"from CelerisLab import utils\n",
|
||||||
|
"\n",
|
||||||
|
"from collections import deque\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"from gym_env import CustomEnv\n",
|
||||||
|
"from stable_baselines3 import PPO\n",
|
||||||
|
"import pycuda.driver as cuda\n",
|
||||||
|
"import pickle\n",
|
||||||
|
"\n",
|
||||||
|
"FIFO_LEN = 120\n",
|
||||||
|
"SAMPLE_INTERVAL = 800\n",
|
||||||
|
"DATA_TYPE = np.float32\n",
|
||||||
|
"CONV_LEN = 60\n",
|
||||||
|
"SAMP_RATE = 60"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"renderView1 = pv.GetActiveViewOrCreate('RenderView')\n",
|
||||||
|
"renderView1.ViewSize = [1200, 480]\n",
|
||||||
|
"renderView1.InteractionMode = '2D'\n",
|
||||||
|
"renderView1.OrientationAxesVisibility = 0\n",
|
||||||
|
"renderView1.CameraPosition = [0.0, 0.0, 3.0]\n",
|
||||||
|
"renderView1.UseLight = 0\n",
|
||||||
|
"name_files = []\n",
|
||||||
|
"for i in range(1, 30):\n",
|
||||||
|
" name_files.append(os.path.join(parent_dir, f\"output/d1a0/field.dat.{i:02}\"))\n",
|
||||||
|
"dat = pv.TecplotReader(registrationName='field.dat*', FileNames=name_files)\n",
|
||||||
|
"dat.DataArrayStatus = ['flag', 'U', 'V']\n",
|
||||||
|
"calculator1 = pv.Calculator(registrationName='Calculator1', Input=dat)\n",
|
||||||
|
"calculator1.ResultArrayName = 'W'\n",
|
||||||
|
"calculator1.Function = '0'\n",
|
||||||
|
"mergeVectorComponents1 = pv.MergeVectorComponents(registrationName='MergeVectorComponents1', Input=calculator1)\n",
|
||||||
|
"mergeVectorComponents1.XArray = 'U'\n",
|
||||||
|
"mergeVectorComponents1.YArray = 'V'\n",
|
||||||
|
"mergeVectorComponents1.ZArray = 'W'\n",
|
||||||
|
"gradient1 = pv.Gradient(registrationName='Gradient1', Input=mergeVectorComponents1)\n",
|
||||||
|
"gradient1.ScalarArray = ['POINTS', 'Vector']\n",
|
||||||
|
"gradient1.ComputeGradient = 0\n",
|
||||||
|
"gradient1.ComputeVorticity = 1\n",
|
||||||
|
"calculator1 = pv.Calculator(registrationName='Calculator1', Input=dat)\n",
|
||||||
|
"calculator1.ResultArrayName = 'Sensor'\n",
|
||||||
|
"calculator1.Function = '1/(flag-17)'\n",
|
||||||
|
"calculator1.ReplacementValue = 1000.0\n",
|
||||||
|
"calculator2 = pv.Calculator(registrationName='Calculator2', Input=dat)\n",
|
||||||
|
"calculator2.ResultArrayName = 'Solid'\n",
|
||||||
|
"calculator2.Function = '1/(flag-2)/(flag-9)'\n",
|
||||||
|
"calculator2.ReplacementValue = 1000.0\n",
|
||||||
|
"\n",
|
||||||
|
"vorticityTF2D = pv.GetTransferFunction2D('Vorticity')\n",
|
||||||
|
"vorticityTF2D.ScalarRangeInitialized = 1\n",
|
||||||
|
"vorticityTF2D.Range = [-0.1, 0.1, 0.0, 1.0]\n",
|
||||||
|
"vorticityLUT = pv.GetColorTransferFunction('Vorticity')\n",
|
||||||
|
"vorticityLUT.AutomaticRescaleRangeMode = 'Never'\n",
|
||||||
|
"vorticityLUT.TransferFunction2D = vorticityTF2D\n",
|
||||||
|
"vorticityLUT.RGBPoints = [-0.1, 0.23137254902, 0.298039215686, 0.752941176471, -0.0125, 1.0, 1.0, 1.0, 0.0125, 1.0, 1.0, 1.0, 0.1, 0.705882352941, 0.0156862745098, 0.149019607843]\n",
|
||||||
|
"vorticityLUT.NumberOfTableValues = 16\n",
|
||||||
|
"vorticityLUT.ScalarRangeInitialized = 1.0\n",
|
||||||
|
"vorticityLUT.VectorComponent = 2\n",
|
||||||
|
"vorticityLUT.VectorMode = 'Component'\n",
|
||||||
|
"vorticityPWF = pv.GetOpacityTransferFunction('Vorticity')\n",
|
||||||
|
"vorticityPWF.Points = [-0.1, 0.0, 0.5, 0.0, 0.1, 1.0, 0.5, 0.0]\n",
|
||||||
|
"vorticityPWF.ScalarRangeInitialized = 1\n",
|
||||||
|
"\n",
|
||||||
|
"sensorTF2D = pv.GetTransferFunction2D('Sensor')\n",
|
||||||
|
"sensorLUT = pv.GetColorTransferFunction('Sensor')\n",
|
||||||
|
"sensorLUT.EnableOpacityMapping = 1\n",
|
||||||
|
"sensorLUT.TransferFunction2D = sensorTF2D\n",
|
||||||
|
"sensorLUT.RGBPoints = [-0.14285714285714285, 1.0, 1.0, 1.0, 1000.0, 0.4, 0.8, 0.4]\n",
|
||||||
|
"sensorLUT.ColorSpace = 'RGB'\n",
|
||||||
|
"sensorLUT.NanColor = [1.0, 0.0, 0.0]\n",
|
||||||
|
"sensorLUT.NumberOfTableValues = 10\n",
|
||||||
|
"sensorLUT.ScalarRangeInitialized = 1.0\n",
|
||||||
|
"sensorPWF = pv.GetOpacityTransferFunction('Sensor')\n",
|
||||||
|
"sensorPWF.Points = [-0.14285714285714285, 0.0, 0.5, 0.0, 499.87855928449983, 0.0, 0.5, 0.0, 1000.0, 1.0, 0.5, 0.0]\n",
|
||||||
|
"sensorPWF.ScalarRangeInitialized = 1\n",
|
||||||
|
"\n",
|
||||||
|
"solidTF2D = pv.GetTransferFunction2D('Solid')\n",
|
||||||
|
"solidLUT = pv.GetColorTransferFunction('Solid')\n",
|
||||||
|
"solidLUT.EnableOpacityMapping = 1\n",
|
||||||
|
"solidLUT.TransferFunction2D = solidTF2D\n",
|
||||||
|
"solidLUT.RGBPoints = [-0.14285714285714285, 1.0, 1.0, 1.0, 1000.0, 0.0, 0.0, 0.0]\n",
|
||||||
|
"solidLUT.ColorSpace = 'RGB'\n",
|
||||||
|
"solidLUT.NanColor = [1.0, 0.0, 0.0]\n",
|
||||||
|
"solidLUT.NumberOfTableValues = 10\n",
|
||||||
|
"solidLUT.ScalarRangeInitialized = 1.0\n",
|
||||||
|
"solidPWF = pv.GetOpacityTransferFunction('Solid')\n",
|
||||||
|
"solidPWF.Points = [-0.14285714285714285, 0.0, 0.5, 0.0, 500.0, 0.0, 0.5, 0.0, 1000.0, 1.0, 0.5, 0.0]\n",
|
||||||
|
"solidPWF.ScalarRangeInitialized = 1\n",
|
||||||
|
"\n",
|
||||||
|
"Display = pv.Show(gradient1, renderView1)\n",
|
||||||
|
"Display.ColorArrayName = ['POINTS', 'Vorticity']\n",
|
||||||
|
"Display.LookupTable = vorticityLUT\n",
|
||||||
|
"Display.ScalarOpacityFunction = vorticityPWF\n",
|
||||||
|
"calculator1Display = pv.Show(calculator1, renderView1, 'StructuredGridRepresentation')\n",
|
||||||
|
"calculator1Display.ColorArrayName = ['POINTS', 'Sensor']\n",
|
||||||
|
"calculator1Display.LookupTable = sensorLUT\n",
|
||||||
|
"calculator1Display.ScalarOpacityFunction = sensorPWF\n",
|
||||||
|
"calculator2Display = pv.Show(calculator2, renderView1, 'StructuredGridRepresentation')\n",
|
||||||
|
"calculator2Display.ColorArrayName = ['POINTS', 'Solid']\n",
|
||||||
|
"calculator2Display.LookupTable = solidLUT\n",
|
||||||
|
"calculator2Display.ScalarOpacityFunction = solidPWF\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 3,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"pv.Render()\n",
|
||||||
|
"renderView1.CameraParallelScale = 240\n",
|
||||||
|
"pv.SaveScreenshot(os.path.join(parent_dir, \"output\", \"test.png\"), view=renderView1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"True"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 4,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"pv.SaveAnimation(filename=os.path.join(parent_dir, \"output\", \"d1a0\", \"anim\", \"anim.png\"), viewOrLayout=renderView1, SuffixFormat='.%02d', FrameWindow=[0, 29], FrameStride=1)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# help(dat)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "pycuda_3_10",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.10.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 2
|
||||||
|
}
|
||||||
BIN
scripts/__pycache__/env_manifold.cpython-310.pyc
Normal file
BIN
scripts/__pycache__/env_manifold.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
scripts/__pycache__/gym_env_d1a0.cpython-310.pyc
Normal file
BIN
scripts/__pycache__/gym_env_d1a0.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
scripts/__pycache__/gym_env_sensonly.cpython-310.pyc
Normal file
BIN
scripts/__pycache__/gym_env_sensonly.cpython-310.pyc
Normal file
Binary file not shown.
BIN
scripts/__pycache__/gym_env_uniflow.cpython-310.pyc
Normal file
BIN
scripts/__pycache__/gym_env_uniflow.cpython-310.pyc
Normal file
Binary file not shown.
BIN
scripts/__pycache__/gym_env_vortex.cpython-310.pyc
Normal file
BIN
scripts/__pycache__/gym_env_vortex.cpython-310.pyc
Normal file
Binary file not shown.
@ -6,7 +6,7 @@ import torch
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from torch.nn import Module
|
from torch.nn import Module
|
||||||
import gymnasium as gym
|
import gymnasium as gym
|
||||||
from gym_env_1 import CustomEnv
|
from gym_env_uniflow import CustomEnv
|
||||||
from stable_baselines3 import PPO
|
from stable_baselines3 import PPO
|
||||||
from stable_baselines3.common.vec_env import SubprocVecEnv
|
from stable_baselines3.common.vec_env import SubprocVecEnv
|
||||||
from stable_baselines3.common.vec_env import DummyVecEnv
|
from stable_baselines3.common.vec_env import DummyVecEnv
|
||||||
@ -26,7 +26,7 @@ class Sin(Module):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
vec_env = CustomEnv(device_id=1)
|
vec_env = CustomEnv(device_id=1)
|
||||||
name = "d0a3o12_b0"
|
name = "d0a3o12_c0"
|
||||||
|
|
||||||
# model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_a0"), env=vec_env, device=torch.device("cuda:1"))
|
# model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_a0"), env=vec_env, device=torch.device("cuda:1"))
|
||||||
|
|
||||||
@ -35,13 +35,15 @@ if __name__ == '__main__':
|
|||||||
policy_kwargs=dict(activation_fn=Sin),
|
policy_kwargs=dict(activation_fn=Sin),
|
||||||
env=vec_env,
|
env=vec_env,
|
||||||
device=torch.device("cuda:1"),
|
device=torch.device("cuda:1"),
|
||||||
|
n_steps=2400,
|
||||||
|
batch_size=240,
|
||||||
verbose=0)
|
verbose=0)
|
||||||
|
|
||||||
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
||||||
max_reward = 0
|
max_reward = 0
|
||||||
|
|
||||||
for i in range(240):
|
for i in range(100):
|
||||||
model.learn(total_timesteps=240)
|
model.learn(total_timesteps=2400)
|
||||||
test_env = model.get_env()
|
test_env = model.get_env()
|
||||||
test_obs = test_env.reset()
|
test_obs = test_env.reset()
|
||||||
list_reward = []
|
list_reward = []
|
||||||
|
|||||||
72
scripts/d0a3o12_lamb.py
Normal file
72
scripts/d0a3o12_lamb.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import os
|
||||||
|
os.environ['MKL_THREADING_LAYER'] = 'GNU'
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "16"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "16"
|
||||||
|
import torch
|
||||||
|
import numpy as np
|
||||||
|
from torch.nn import Module
|
||||||
|
import gymnasium as gym
|
||||||
|
from gym_env_vortex import CustomEnv
|
||||||
|
from stable_baselines3 import PPO
|
||||||
|
from stable_baselines3.common.vec_env import SubprocVecEnv
|
||||||
|
from stable_baselines3.common.vec_env import DummyVecEnv
|
||||||
|
from sb3_contrib import RecurrentPPO
|
||||||
|
from torch.utils.tensorboard import SummaryWriter
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
|
||||||
|
class Sin(Module):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
return torch.sin(x)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
vec_env = CustomEnv(device_id=3)
|
||||||
|
name = "vortex_lamb"
|
||||||
|
|
||||||
|
model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_re100"), env=vec_env, device=torch.device("cuda:3"))
|
||||||
|
|
||||||
|
# model = PPO(
|
||||||
|
# "MlpPolicy",
|
||||||
|
# policy_kwargs=dict(activation_fn=Sin),
|
||||||
|
# env=vec_env,
|
||||||
|
# device=torch.device("cuda:3"),
|
||||||
|
# n_steps=3600,
|
||||||
|
# batch_size=360,
|
||||||
|
# verbose=0)
|
||||||
|
|
||||||
|
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
||||||
|
max_reward = 0
|
||||||
|
|
||||||
|
history_data = []
|
||||||
|
|
||||||
|
for i in range(100):
|
||||||
|
model.learn(total_timesteps=2000)
|
||||||
|
test_env = model.get_env()
|
||||||
|
test_obs = test_env.reset()
|
||||||
|
list_reward = []
|
||||||
|
# episolde_data = {'actions': [], 'observations': [], 'rewards': []}
|
||||||
|
|
||||||
|
for step in range(200):
|
||||||
|
test_action, _states = model.predict(observation=test_obs)
|
||||||
|
test_obs, test_rewards, test_dones, info = test_env.step(test_action)
|
||||||
|
list_reward.append(test_rewards)
|
||||||
|
# episolde_data['actions'].append(test_action[0, :])
|
||||||
|
# episolde_data['observations'].append(np.array(test_obs))
|
||||||
|
# episolde_data['rewards'].append(test_rewards)
|
||||||
|
|
||||||
|
# history_data.append(episolde_data)
|
||||||
|
|
||||||
|
avg_reward = np.mean(list_reward[-180:])
|
||||||
|
writer.add_scalar('Reward', np.mean(avg_reward), i)
|
||||||
|
if avg_reward > max_reward:
|
||||||
|
max_reward = avg_reward
|
||||||
|
model.save(os.path.join(parent_dir, "models", name + ".zip"))
|
||||||
|
|
||||||
|
# with open(os.path.join(parent_dir, "output", name + ".pkl"), 'wb') as f:
|
||||||
|
# pickle.dump(history_data, f)
|
||||||
@ -36,6 +36,8 @@ if __name__ == '__main__':
|
|||||||
policy_kwargs=dict(activation_fn=Sin),
|
policy_kwargs=dict(activation_fn=Sin),
|
||||||
env=vec_env,
|
env=vec_env,
|
||||||
device=torch.device("cuda:3"),
|
device=torch.device("cuda:3"),
|
||||||
|
n_steps=3600,
|
||||||
|
batch_size=360,
|
||||||
verbose=0)
|
verbose=0)
|
||||||
|
|
||||||
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
||||||
@ -43,8 +45,8 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
history_data = []
|
history_data = []
|
||||||
|
|
||||||
for i in range(400):
|
for i in range(100):
|
||||||
model.learn(total_timesteps=360)
|
model.learn(total_timesteps=3600)
|
||||||
test_env = model.get_env()
|
test_env = model.get_env()
|
||||||
test_obs = test_env.reset()
|
test_obs = test_env.reset()
|
||||||
list_reward = []
|
list_reward = []
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class Sin(Module):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
vec_env = CustomEnv(device_id=1)
|
vec_env = CustomEnv(device_id=1)
|
||||||
name = "d1a3o12_re100_erase_c0"
|
name = "d1a3o12_re100_erase_d0"
|
||||||
|
|
||||||
# model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_re100_erase_b0"), env=vec_env, device=torch.device("cuda:1"))
|
# model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_re100_erase_b0"), env=vec_env, device=torch.device("cuda:1"))
|
||||||
|
|
||||||
|
|||||||
72
scripts/d1a3o12_sensonly.py
Normal file
72
scripts/d1a3o12_sensonly.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import os
|
||||||
|
os.environ['MKL_THREADING_LAYER'] = 'GNU'
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "8"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "8"
|
||||||
|
import torch
|
||||||
|
import numpy as np
|
||||||
|
from torch.nn import Module
|
||||||
|
import gymnasium as gym
|
||||||
|
from gym_env_sensonly import CustomEnv
|
||||||
|
from stable_baselines3 import PPO
|
||||||
|
from stable_baselines3.common.vec_env import SubprocVecEnv
|
||||||
|
from stable_baselines3.common.vec_env import DummyVecEnv
|
||||||
|
from sb3_contrib import RecurrentPPO
|
||||||
|
from torch.utils.tensorboard import SummaryWriter
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
|
||||||
|
class Sin(Module):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def forward(self, x):
|
||||||
|
return torch.sin(x)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
vec_env = CustomEnv(device_id=3)
|
||||||
|
name = "d1a3o12_sensonly_b0"
|
||||||
|
|
||||||
|
# model = PPO.load(os.path.join(parent_dir, "models", "d1a3o12_sensonly_a0"), env=vec_env, device=torch.device("cuda:1"))
|
||||||
|
|
||||||
|
model = PPO(
|
||||||
|
"MlpPolicy",
|
||||||
|
policy_kwargs=dict(activation_fn=Sin),
|
||||||
|
env=vec_env,
|
||||||
|
device=torch.device("cuda:3"),
|
||||||
|
n_steps=7200,
|
||||||
|
batch_size=720,
|
||||||
|
verbose=0)
|
||||||
|
|
||||||
|
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
||||||
|
max_reward = 0
|
||||||
|
|
||||||
|
history_data = []
|
||||||
|
|
||||||
|
for i in range(100):
|
||||||
|
model.learn(total_timesteps=7200)
|
||||||
|
test_env = model.get_env()
|
||||||
|
test_obs = test_env.reset()
|
||||||
|
list_reward = []
|
||||||
|
episolde_data = {'actions': [], 'observations': [], 'rewards': []}
|
||||||
|
|
||||||
|
for step in range(360):
|
||||||
|
test_action, _states = model.predict(observation=test_obs)
|
||||||
|
test_obs, test_rewards, test_dones, info = test_env.step(test_action)
|
||||||
|
list_reward.append(test_rewards)
|
||||||
|
episolde_data['actions'].append(test_action[0, :])
|
||||||
|
episolde_data['observations'].append(np.array(test_obs))
|
||||||
|
episolde_data['rewards'].append(test_rewards)
|
||||||
|
|
||||||
|
history_data.append(episolde_data)
|
||||||
|
|
||||||
|
avg_reward = np.mean(list_reward[-180:])
|
||||||
|
writer.add_scalar('Reward', np.mean(avg_reward), i)
|
||||||
|
if avg_reward > max_reward:
|
||||||
|
max_reward = avg_reward
|
||||||
|
model.save(os.path.join(parent_dir, "models", name + ".zip"))
|
||||||
|
|
||||||
|
with open(os.path.join(parent_dir, "output", name + ".pkl"), 'wb') as f:
|
||||||
|
pickle.dump(history_data, f)
|
||||||
61
scripts/data.csv
Normal file
61
scripts/data.csv
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
,div,amp,sin,pha,lin,rad,target
|
||||||
|
0,1.4045084971874737,2.2022542485937366,1.8044569186997115,2.4045084971874733,2.000008520514539,3.205367751045167,2.4045084971874737
|
||||||
|
1,1.9007606340087433,2.4503803170043716,2.332087743170836,2.0743362624719874,2.000003626756254,0.8461854338136477,2.9007606340087433
|
||||||
|
2,1.9901746746922298,2.495087337346115,2.8003643744408384,1.4850331349799533,2.000002768705942,2.1318252162776163,2.9901746746922298
|
||||||
|
3,1.7828033402113457,2.391401670105673,3.125591517469359,0.8679592634873357,2.000009725903628,0.8826745225681839,2.7828033402113457
|
||||||
|
4,1.5235721267084505,2.2617860633542253,3.2496411772354152,0.5412664647004362,2.000003167213289,2.69235119966044,2.5235721267084505
|
||||||
|
5,1.4065386972205927,2.2032693486102963,3.1503419016944787,0.7110698414412506,2.0000017363419866,1.5229136911774184,2.4065386972205927
|
||||||
|
6,1.4393159515757463,2.219657975787873,2.845441495474666,1.3337158208533584,2.0000083303175944,3.226434054111396,2.4393159515757463
|
||||||
|
7,1.450798066146493,2.2253990330732467,2.3894349466929015,2.1326710741083486,2.000008622178289,1.4497088303289274,2.450798066146493
|
||||||
|
8,1.2346026177490346,2.1173013088745174,1.8638245129722457,2.760807746204077,2.000004945419158,3.189635332867647,2.234602617749035
|
||||||
|
9,0.7255102977301549,1.8627551488650775,1.3625527859112463,3.001998665019795,2.0000000531831943,2.877279259114057,1.7255102977301549
|
||||||
|
10,0.0820556181948704,1.5410278090974352,0.975212289010335,2.88067987853731,2.0000005575959126,1.2314074364106393,1.0820556181948704
|
||||||
|
11,-0.3879391919354942,1.3060304040322528,0.7710325652455938,2.611352030311411,2.0000011985974036,2.6002073722377497,0.6120608080645058
|
||||||
|
12,-0.41407120900178107,1.2929643954991095,0.786506749402337,2.4285527467390455,2.0000057465295193,3.306797327017787,0.5859287909982189
|
||||||
|
13,0.06100662286373426,1.5305033114318671,1.0188691335164597,2.4176302954029674,2.0000057394450335,2.6280688418490845,1.0610066228637343
|
||||||
|
14,0.835358997163627,1.9176794985818135,1.4265894831152983,2.4635124212075232,2.000000157237956,2.7192885075569535,1.835358997163627
|
||||||
|
15,1.563785256388725,2.2818926281943623,1.9367957548917019,2.3511982850939934,2.000006669712237,0.8122113537334713,2.5637852563887247
|
||||||
|
16,1.9607571648768625,2.4803785824384312,2.458298550109379,1.945425564199183,2.000004826412877,1.3568097107043613,2.9607571648768625
|
||||||
|
17,1.9575426437755965,2.4787713218877983,2.897889437265479,1.3209370919592596,2.0000061089806707,2.703953845842629,2.9575426437755965
|
||||||
|
18,1.7129748348749259,2.356487417437463,3.177000137396772,0.7476065856898844,2.0000023343173337,1.9619846399137617,2.7129748348749256
|
||||||
|
19,1.4769767527601103,2.238488376380055,3.245745068271543,0.5341169662306902,2.000009743244121,2.554909616055127,2.4769767527601103
|
||||||
|
20,1.4050548066467907,2.2025274033233955,3.091837417164398,0.8319516950415051,2.0000014714851497,2.8928645533304156,2.4050548066467905
|
||||||
|
21,1.453105741163031,2.2265528705815156,2.7427851684764506,1.5309207382643764,2.000009510045682,1.5236138503556755,2.453105741163031
|
||||||
|
22,1.4242001789372487,2.2121000894686245,2.260974589186704,2.3177558292528886,2.0000029201944813,1.1128963991461416,2.4242001789372485
|
||||||
|
23,1.1324126591923536,2.066206329596177,1.7325199030134266,2.8607338096979964,2.00000130393951,1.55124335985003,2.1324126591923536
|
||||||
|
24,0.5665635064491743,1.7832817532245873,1.251872056088139,2.9994769870458047,2.000002995999825,1.598407927631956,1.5665635064491743
|
||||||
|
25,-0.0645293951381749,1.4677353024309125,0.9049374564453916,2.8168711382038927,2.000008336199793,1.7278190560997833,0.9354706048618251
|
||||||
|
26,-0.4429180340888781,1.278540982955561,0.7537238826883124,2.5507059799726233,2.0000012857027403,0.6107197064229589,0.5570819659111219
|
||||||
|
27,-0.33846574623936587,1.3307671268803172,0.825257805549346,2.4110604228245562,2.000004987984852,3.4037899272581957,0.6615342537606341
|
||||||
|
28,0.23903171004548185,1.6195158550227409,1.1067539344983808,2.431766427122485,2.0000000509206517,1.2488627569071316,1.2390317100454817
|
||||||
|
29,1.0355368653934778,2.017768432696739,1.5479003385274301,2.4583021126527274,2.0000068960696913,2.478842653195267,2.035536865393478
|
||||||
|
30,1.7011821415149164,2.350591070757458,2.0698507204359053,2.278416894255669,2.000006795035744,2.4855685723209735,2.7011821415149164
|
||||||
|
31,1.9945249814914687,2.4972624907457344,2.5793166513483756,1.8017902644144659,2.0000051477822907,1.077676696370284,2.9945249814914687
|
||||||
|
32,1.9093462173987017,2.454673108699351,2.9852410539874885,1.1598200483347811,2.0000096781408714,2.9247971085095115,2.909346217398702
|
||||||
|
33,1.644201157110716,2.322100578555358,3.215072875462088,0.6505771430492158,2.0000037725918194,0.7538239571282532,2.6442011571107162
|
||||||
|
34,1.4417206196960188,2.2208603098480095,3.2277341699096813,0.5603200863539506,2.000005012787531,2.844416571695295,2.4417206196960186
|
||||||
|
35,1.4119000393085435,2.2059500196542716,3.0209619784217483,0.978986558711912,2.0000091115805527,0.9619684813354784,2.4119000393085432
|
||||||
|
36,1.4620321158832907,2.2310160579416456,2.6317127887175022,1.7337109653776412,2.0000095376463367,2.833020040831371,2.4620321158832907
|
||||||
|
37,1.3802335725311756,2.190116786265588,2.129557285304864,2.4866779222155304,2.0000043047827845,1.769832064714908,2.3802335725311754
|
||||||
|
38,1.0119070418531917,2.005953520926596,1.6042459494330863,2.934092044751843,2.000003905537697,2.803852496436914,2.011907041853192
|
||||||
|
39,0.40294385993855586,1.701471929969278,1.1496679148063091,2.9760469715438402,2.0000007180273607,2.131201389557444,1.402943859938556
|
||||||
|
40,-0.19485966147474865,1.4025701692626256,0.847070120063711,2.748000125054671,2.0000001093900077,2.0376363601421827,0.8051403385252514
|
||||||
|
41,-0.4664416299100693,1.2667791850449652,0.7505360065268409,2.498926619274973,2.0000069850336386,2.695685474229468,0.5335583700899307
|
||||||
|
42,-0.231992651617571,1.3840036741912145,0.8773191601626429,2.4046129001987686,2.0000067946428204,0.5573683128875674,0.768007348382429
|
||||||
|
43,0.43125272386142244,1.7156263619307113,1.2047595703254492,2.4465843245391046,2.0000092860315317,0.9376305556112953,1.4312527238614225
|
||||||
|
44,1.2269506963336099,2.113475348166805,1.6743336637539006,2.439537667628344,2.0000034022459325,0.7072786555155116,2.22695069633361
|
||||||
|
45,1.8140483595050712,2.4070241797525354,2.202114249406634,2.185894935461177,2.0000093538461576,3.1294668511809527,2.814048359505071
|
||||||
|
46,2.003541692443701,2.5017708462218504,2.693770863444402,1.6469180199044717,2.0000083144795253,0.529828807947389,3.003541692443701
|
||||||
|
47,1.849675452591932,2.4248377262959657,3.0614294958854664,1.0070514968511075,2.0000012422880085,1.514247920878469,2.849675452591932
|
||||||
|
48,1.580068820844247,2.2900344104221233,3.2393783523299313,0.5807775985973418,2.000006209921787,2.542983184031196,2.580068820844247
|
||||||
|
49,1.4183564738688161,2.209178236934408,3.1958125528250614,0.6197322135263754,2.0000052610632344,1.6971866871871057,2.4183564738688164
|
||||||
|
50,1.4243914289223738,2.212195714461187,2.9385186325078756,1.147903061632729,2.0000009298767467,3.2577962123058857,2.4243914289223736
|
||||||
|
51,1.462409275671654,2.231204637835827,2.513482850642765,1.9362041472166056,2.000008043007149,1.9470354748148022,2.462409275671654
|
||||||
|
52,1.3172807335233632,2.1586403667616816,1.99667204561206,2.635407725561501,2.0000050502324247,2.209506930036168,2.317280733523363
|
||||||
|
53,0.8752494142060003,1.9376247071030002,1.4804560473809683,2.9808495449283816,2.000009814190974,2.7451310260842656,1.8752494142060003
|
||||||
|
54,0.23967224876362314,1.6198361243818116,1.0570983758251855,2.935141104542965,2.0000094206736994,3.2669332189128264,1.2396722487636231
|
||||||
|
55,-0.30408572820629276,1.3479571358968536,0.8022659399091139,2.6782199338017216,2.0000098588441992,2.6908547104274865,0.6959142717937072
|
||||||
|
56,-0.45696846239829014,1.271515768800855,0.7615050566719004,2.457875614325721,2.00000520701219,1.9002676865371069,0.5430315376017099
|
||||||
|
57,-0.09755188185213548,1.4512240590739323,0.9421009372918006,2.407589657860142,2.0000012780634977,3.3328107970338094,0.9024481181478645
|
||||||
|
58,0.631986262644157,1.8159931313220785,1.311775597982686,2.4584106341809147,2.000001988251098,1.0803693179920704,1.631986262644157
|
||||||
|
59,1.4045084971874737,2.2022542485937366,1.804456918699709,2.404508497187476,2.0000042089252625,2.955378256729254,2.4045084971874737
|
||||||
|
154
scripts/env_manifold.py
Normal file
154
scripts/env_manifold.py
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import gymnasium as gym
|
||||||
|
import numpy as np
|
||||||
|
from gymnasium import spaces
|
||||||
|
from collections import deque
|
||||||
|
from typing import Tuple
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import queue
|
||||||
|
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "1"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "1"
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
sys.path.append(parent_dir)
|
||||||
|
from CelerisLab import FlowField
|
||||||
|
from CelerisLab import utils
|
||||||
|
|
||||||
|
config_cuda = utils.load_cuda_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_cuda.json")
|
||||||
|
)
|
||||||
|
config_field = utils.load_flow_field_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_flowfield.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
S_DIM, A_DIM = 12, 3
|
||||||
|
U0 = config_field.velocity
|
||||||
|
T0 = 1000
|
||||||
|
SAMPLE_INTERVAL = 800
|
||||||
|
FIFO_LEN = 360
|
||||||
|
MAX_STEPS = 500
|
||||||
|
if config_field.data_type == "FP32":
|
||||||
|
DATA_TYPE = np.float32
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported data type {config_field.data_type}.")
|
||||||
|
|
||||||
|
|
||||||
|
class CustomEnv(gym.Env):
|
||||||
|
"""Custom Environment that follows gym interface."""
|
||||||
|
|
||||||
|
metadata = {"render_modes": ["human"], "render_fps": T0 / SAMPLE_INTERVAL}
|
||||||
|
|
||||||
|
def __init__(self, device_id=0):
|
||||||
|
super().__init__()
|
||||||
|
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
||||||
|
self.observation_space = spaces.Box(
|
||||||
|
low=-5, high=5, shape=(S_DIM,), dtype=DATA_TYPE
|
||||||
|
)
|
||||||
|
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.save_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.current_step = 0
|
||||||
|
|
||||||
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
|
L0 = 20
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
center: Tuple[float, float, float] = (20 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 + 3 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 - 3 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
self.flow_field.run(int(4*NX/U0), np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy())
|
||||||
|
|
||||||
|
self.save_states = self.fifo_states.copy()
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
self.flow_field.save_ddf()
|
||||||
|
|
||||||
|
|
||||||
|
def step(self, action):
|
||||||
|
assert self.action_space.contains(action), "%r (%s) invalid" % (
|
||||||
|
action,
|
||||||
|
type(action),
|
||||||
|
)
|
||||||
|
|
||||||
|
def run_flow_field(action):
|
||||||
|
self.flow_field.context.push()
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
L0 = 20
|
||||||
|
try:
|
||||||
|
temp = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
temp[0:3] = np.array((action*4+[0,-4,+4])*U0, dtype=DATA_TYPE)
|
||||||
|
if self.current_step == 0:
|
||||||
|
self.flow_field.run(int(2*NX/U0), temp)
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
||||||
|
finally:
|
||||||
|
state = self.flow_field.obs.copy()
|
||||||
|
force = state[0:6] / (L0*U0*U0)
|
||||||
|
sens = state[6:12] / 78 / U0
|
||||||
|
self.fifo_states.append([force, sens])
|
||||||
|
self.flow_field.context.pop()
|
||||||
|
|
||||||
|
run_flow_field(action)
|
||||||
|
|
||||||
|
truncated = False
|
||||||
|
observation = 0.0
|
||||||
|
terminated = self.current_step >= MAX_STEPS
|
||||||
|
self.current_step += 1
|
||||||
|
return observation, 0.0, terminated, truncated, {}
|
||||||
|
|
||||||
|
def reset(self, seed=None):
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
self.current_step = 0
|
||||||
|
self.fifo_states = self.save_states.copy()
|
||||||
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
|
def render(self, mode="human"):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
speed = np.sqrt(ux**2 + uy**2)
|
||||||
|
plt.figure(figsize=(10, 5))
|
||||||
|
plt.imshow(speed.T, origin='lower', cmap='viridis', extent=[0, NX, 0, NY])
|
||||||
|
plt.colorbar(label='Speed')
|
||||||
|
plt.title('Scalar Velocity Field')
|
||||||
|
plt.xlabel('X')
|
||||||
|
plt.ylabel('Y')
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def save_field(self, filename):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
flag_plot = self.flow_field.flag.copy().reshape((NY, NX)).transpose(1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
with open(os.path.join(parent_dir, "output", filename), "w") as f:
|
||||||
|
f.write("Title= \"LBM 2D\"\r\n")
|
||||||
|
f.write("VARIABLES= \"X\",\"Y\",\"flag\",\"U\",\"V\",\r\n")
|
||||||
|
f.write(f"ZONE T= \"BOX\",I= {NX},J= {NY},F=POINT\r\n")
|
||||||
|
for j in range(NY):
|
||||||
|
for i in range(NX):
|
||||||
|
f.write(f"{i},{j},{flag_plot[i, j]},{ux[i, j]},{uy[i, j]}\r\n")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.flow_field.__del__()
|
||||||
@ -31,7 +31,7 @@ T0 = 1000
|
|||||||
SAMPLE_INTERVAL = 800
|
SAMPLE_INTERVAL = 800
|
||||||
FIFO_LEN = 120
|
FIFO_LEN = 120
|
||||||
CONV_LEN = 60
|
CONV_LEN = 60
|
||||||
MAX_STEPS = 360
|
MAX_STEPS = 500
|
||||||
if config_field.data_type == "FP32":
|
if config_field.data_type == "FP32":
|
||||||
DATA_TYPE = np.float32
|
DATA_TYPE = np.float32
|
||||||
else:
|
else:
|
||||||
@ -54,6 +54,10 @@ class CustomEnv(gym.Env):
|
|||||||
self.force_norm_fact = 1.0
|
self.force_norm_fact = 1.0
|
||||||
self.sens_norm_fact = np.ones(6, dtype=DATA_TYPE)
|
self.sens_norm_fact = np.ones(6, dtype=DATA_TYPE)
|
||||||
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
self.reward_cd = 0.0
|
||||||
|
self.reward_cl = 0.0
|
||||||
|
self.reward_sim = 0.0
|
||||||
|
self.current_step = 0
|
||||||
|
|
||||||
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
L0 = 20
|
L0 = 20
|
||||||
@ -89,6 +93,9 @@ class CustomEnv(gym.Env):
|
|||||||
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(7, dtype=DATA_TYPE))
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(7, dtype=DATA_TYPE))
|
||||||
self.fifo_states.append(self.flow_field.obs.copy()[2:14])
|
self.fifo_states.append(self.flow_field.obs.copy()[2:14])
|
||||||
|
|
||||||
|
self.save_states = self.fifo_states.copy()
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
|
||||||
temp_states = np.array(self.fifo_states)
|
temp_states = np.array(self.fifo_states)
|
||||||
self.force_norm_fact = 6 * np.max(np.abs(temp_states[:, 6:12]))
|
self.force_norm_fact = 6 * np.max(np.abs(temp_states[:, 6:12]))
|
||||||
for i in range(6):
|
for i in range(6):
|
||||||
@ -144,35 +151,58 @@ class CustomEnv(gym.Env):
|
|||||||
aligned_state = np.roll(state, lag)
|
aligned_state = np.roll(state, lag)
|
||||||
|
|
||||||
if lag >= 0:
|
if lag >= 0:
|
||||||
seq_target = target[-CONV_LEN:]-target_mean
|
# seq_target = target[-CONV_LEN:]-target_mean
|
||||||
seq_state = aligned_state[-CONV_LEN:]-state_mean
|
# seq_state = aligned_state[-CONV_LEN:]-state_mean
|
||||||
|
seq_target = target[-CONV_LEN:]
|
||||||
|
seq_state = aligned_state[-CONV_LEN:]
|
||||||
else:
|
else:
|
||||||
seq_target = target[:CONV_LEN]-target_mean
|
# seq_target = target[:CONV_LEN]-target_mean
|
||||||
seq_state = aligned_state[:CONV_LEN]-state_mean
|
# seq_state = aligned_state[:CONV_LEN]-state_mean
|
||||||
|
seq_target = target[:CONV_LEN]
|
||||||
|
seq_state = aligned_state[:CONV_LEN]
|
||||||
|
|
||||||
seq_diff = seq_target - seq_state
|
def dtw(target, state):
|
||||||
sim_cor = 10*(np.corrcoef(seq_target, seq_state)[0, 1] - 1)
|
n = len(target)
|
||||||
sim_div = -np.abs((target_mean - state_mean) / target_std * 0.75)
|
m = len(state)
|
||||||
sim_amp = -np.abs(np.std(seq_diff) / target_std * 2)
|
|
||||||
|
dtw_matrix = np.full((n + 1, m + 1), np.inf)
|
||||||
|
dtw_matrix[0, 0] = 0
|
||||||
|
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
for j in range(1, m + 1):
|
||||||
|
cost = abs(target[i - 1] - state[j - 1])
|
||||||
|
last_min = min(dtw_matrix[i - 1, j],
|
||||||
|
dtw_matrix[i, j - 1],
|
||||||
|
dtw_matrix[i - 1, j - 1])
|
||||||
|
dtw_matrix[i, j] = cost + last_min
|
||||||
|
|
||||||
return np.exp((sim_cor + sim_div + sim_amp) / 3)
|
return 1 - (dtw_matrix[n, m] / len(target))
|
||||||
|
|
||||||
|
# seq_diff = seq_target - seq_state
|
||||||
|
# sim_cor = 10*(np.corrcoef(seq_target, seq_state)[0, 1] - 1)
|
||||||
|
# sim_div = -np.abs((target_mean - state_mean) / target_std * 0.75)
|
||||||
|
# sim_amp = -np.abs(np.std(seq_diff) / target_std * 2)
|
||||||
|
|
||||||
|
# return np.exp((sim_cor + sim_div + sim_amp) / 3)
|
||||||
|
return dtw(seq_target, seq_state)
|
||||||
|
|
||||||
id_sens = 0
|
id_sens = 0
|
||||||
target_seq = self.target_states[:, id_sens]
|
target_seq = self.target_states[:, id_sens]
|
||||||
state_seq = (states[:, id_sens] - self.sens_deviation[id_sens]) / self.sens_norm_fact[id_sens]
|
state_seq = (states[:, id_sens] - self.sens_deviation[id_sens]) / self.sens_norm_fact[id_sens]
|
||||||
lag = calc_lag(target_seq, state_seq)
|
lag = calc_lag(target_seq, state_seq)
|
||||||
similarities += calc_sim(target_seq, state_seq, lag) / 6
|
# similarities += calc_sim(target_seq, state_seq, lag) / 6
|
||||||
|
similarities += calc_sim(target_seq*self.sens_norm_fact[id_sens]+self.sens_deviation[id_sens], state_seq*self.sens_norm_fact[id_sens]+self.sens_deviation[id_sens], lag) / 6
|
||||||
|
|
||||||
for i in range(1, 6):
|
for i in range(1, 6):
|
||||||
target_seq = self.target_states[:, i]
|
target_seq = self.target_states[:, i]
|
||||||
state_seq = (states[:, i] - self.sens_deviation[i]) / self.sens_norm_fact[i]
|
state_seq = (states[:, i] - self.sens_deviation[i]) / self.sens_norm_fact[i]
|
||||||
similarities += calc_sim(target_seq, state_seq, lag) / 6
|
# similarities += calc_sim(target_seq, state_seq, lag) / 6
|
||||||
|
similarities += calc_sim(target_seq*self.sens_norm_fact[id_sens]+self.sens_deviation[id_sens], state_seq*self.sens_norm_fact[id_sens]+self.sens_deviation[id_sens], lag) / 6
|
||||||
|
|
||||||
reward_cd = np.exp(-np.abs(cd * 20))
|
self.reward_cd = np.exp(-np.abs(cd * 20))
|
||||||
reward_cl = np.exp(-np.abs(cl * 80))
|
self.reward_cl = np.exp(-np.abs(cl * 80))
|
||||||
# reward_sim = np.exp(2 * (similarities - 1))
|
self.reward_sim = similarities
|
||||||
reward_sim = similarities
|
reward = np.minimum(0.3 * self.reward_cd + 0.4 * self.reward_cl + 0.5 * self.reward_sim, 1.0)
|
||||||
reward = np.minimum(0.3 * reward_cd + 0.3 * reward_cl + 0.4 * reward_sim, 1.0)
|
|
||||||
# barrier.wait()
|
# barrier.wait()
|
||||||
result_queue.put((np.hstack([forces, sens]), reward))
|
result_queue.put((np.hstack([forces, sens]), reward))
|
||||||
|
|
||||||
@ -182,11 +212,14 @@ class CustomEnv(gym.Env):
|
|||||||
|
|
||||||
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
||||||
observation = np.clip(observation, -1, 1)
|
observation = np.clip(observation, -1, 1)
|
||||||
# truncated = False
|
self.current_step += 1
|
||||||
return observation, float(reward), False, truncated, {}
|
done = self.current_step >= MAX_STEPS
|
||||||
|
return observation, float(reward), done, truncated, {}
|
||||||
|
|
||||||
def reset(self, seed=None):
|
def reset(self, seed=None):
|
||||||
self.flow_field.apply_ddf()
|
self.flow_field.apply_ddf()
|
||||||
|
self.fifo_states = self.save_states.copy()
|
||||||
|
self.current_step = 0
|
||||||
return np.zeros(S_DIM, dtype=np.float32), {}
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
def render(self, mode="human"):
|
def render(self, mode="human"):
|
||||||
|
|||||||
139
scripts/gym_env_d1a0.py
Normal file
139
scripts/gym_env_d1a0.py
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
import gymnasium as gym
|
||||||
|
import numpy as np
|
||||||
|
from gymnasium import spaces
|
||||||
|
import ctypes
|
||||||
|
from collections import deque
|
||||||
|
from typing import Tuple
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import queue
|
||||||
|
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "1"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "1"
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
sys.path.append(parent_dir)
|
||||||
|
from CelerisLab import FlowField
|
||||||
|
from CelerisLab import utils
|
||||||
|
|
||||||
|
config_cuda = utils.load_cuda_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_cuda.json")
|
||||||
|
)
|
||||||
|
config_field = utils.load_flow_field_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_flowfield.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
S_DIM, A_DIM = 12, 3
|
||||||
|
U0 = config_field.velocity
|
||||||
|
T0 = 1000
|
||||||
|
SAMPLE_INTERVAL = 800
|
||||||
|
FIFO_LEN = 120
|
||||||
|
CONV_LEN = 60
|
||||||
|
MAX_STEPS = 500
|
||||||
|
if config_field.data_type == "FP32":
|
||||||
|
DATA_TYPE = np.float32
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported data type {config_field.data_type}.")
|
||||||
|
|
||||||
|
|
||||||
|
class CustomEnv(gym.Env):
|
||||||
|
"""Custom Environment that follows gym interface."""
|
||||||
|
|
||||||
|
metadata = {"render_modes": ["human"], "render_fps": T0 / SAMPLE_INTERVAL}
|
||||||
|
|
||||||
|
def __init__(self, device_id=0):
|
||||||
|
super().__init__()
|
||||||
|
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
||||||
|
self.observation_space = spaces.Box(
|
||||||
|
low=-1, high=1, shape=(S_DIM,), dtype=DATA_TYPE
|
||||||
|
)
|
||||||
|
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.target_states = np.empty((0, 6), dtype=DATA_TYPE)
|
||||||
|
self.force_norm_fact = 1.0
|
||||||
|
self.sens_norm_fact = np.ones(6, dtype=DATA_TYPE)
|
||||||
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
self.reward_cd = 0.0
|
||||||
|
self.reward_cl = 0.0
|
||||||
|
self.reward_sim = 0.0
|
||||||
|
self.current_step = 0
|
||||||
|
|
||||||
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
|
L0 = 20
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0)
|
||||||
|
self.flow_field.run(int(4*NX/U0), np.zeros(1, dtype=DATA_TYPE))
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
|
||||||
|
|
||||||
|
def step(self, action):
|
||||||
|
assert self.action_space.contains(action), "%r (%s) invalid" % (
|
||||||
|
action,
|
||||||
|
type(action),
|
||||||
|
)
|
||||||
|
|
||||||
|
# barrier = threading.Barrier(2)
|
||||||
|
result_queue = queue.Queue()
|
||||||
|
|
||||||
|
def run_flow_field(action):
|
||||||
|
self.flow_field.context.push()
|
||||||
|
U0 = config_field.velocity
|
||||||
|
try:
|
||||||
|
temp = np.zeros(1, dtype=DATA_TYPE)
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
||||||
|
finally:
|
||||||
|
self.flow_field.context.pop()
|
||||||
|
# barrier.wait()
|
||||||
|
|
||||||
|
run_flow_field(action)
|
||||||
|
|
||||||
|
truncated = False
|
||||||
|
observation = np.zeros(12, dtype=DATA_TYPE)
|
||||||
|
self.current_step += 1
|
||||||
|
done = self.current_step >= MAX_STEPS
|
||||||
|
return observation, float(1), done, truncated, {}
|
||||||
|
|
||||||
|
def reset(self, seed=None):
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
self.current_step = 0
|
||||||
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
|
def render(self, mode="human"):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
speed = np.sqrt(ux**2 + uy**2)
|
||||||
|
plt.figure(figsize=(10, 5))
|
||||||
|
plt.imshow(speed.T, origin='lower', cmap='viridis', extent=[0, NX, 0, NY])
|
||||||
|
plt.colorbar(label='Speed')
|
||||||
|
plt.title('Scalar Velocity Field')
|
||||||
|
plt.xlabel('X')
|
||||||
|
plt.ylabel('Y')
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def save_field(self, filename):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
flag_plot = self.flow_field.flag.copy().reshape((NY, NX)).transpose(1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
with open(os.path.join(parent_dir, "output", filename), "w") as f:
|
||||||
|
f.write("Title= \"LBM 2D\"\r\n")
|
||||||
|
f.write("VARIABLES= \"X\",\"Y\",\"flag\",\"U\",\"V\",\r\n")
|
||||||
|
f.write(f"ZONE T= \"BOX\",I= {NX},J= {NY},F=POINT\r\n")
|
||||||
|
for j in range(NY):
|
||||||
|
for i in range(NX):
|
||||||
|
f.write(f"{i},{j},{flag_plot[i, j]},{ux[i, j]},{uy[i, j]}\r\n")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.flow_field.__del__()
|
||||||
@ -57,7 +57,7 @@ class CustomEnv(gym.Env):
|
|||||||
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
|
||||||
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
L0 = 30
|
L0 = 20
|
||||||
U0 = config_field.velocity
|
U0 = config_field.velocity
|
||||||
NX = self.flow_field.FIELD_SHAPE[0]
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
NY = self.flow_field.FIELD_SHAPE[1]
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
@ -80,11 +80,11 @@ class CustomEnv(gym.Env):
|
|||||||
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
||||||
self.flow_field.add_cylinder(center, L0)
|
self.flow_field.add_cylinder(center, L0)
|
||||||
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 /2*1.5)
|
||||||
center: Tuple[float, float, float] = ((30+1.3) * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
center: Tuple[float, float, float] = ((30+1.3*1.5) * L0, (NY - 1) / 2 + 0.75*1.5 * L0, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 /2*1.5)
|
||||||
center: Tuple[float, float, float] = ((30+1.3) * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
center: Tuple[float, float, float] = ((30+1.3*1.5) * L0, (NY - 1) / 2 - 0.75*1.5 * L0, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 /2*1.5)
|
||||||
|
|
||||||
self.flow_field.run(int(4*NX/U0), np.zeros(7, dtype=DATA_TYPE))
|
self.flow_field.run(int(4*NX/U0), np.zeros(7, dtype=DATA_TYPE))
|
||||||
self.flow_field.get_ddf()
|
self.flow_field.get_ddf()
|
||||||
|
|||||||
248
scripts/gym_env_sensonly.py
Normal file
248
scripts/gym_env_sensonly.py
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
import gymnasium as gym
|
||||||
|
import numpy as np
|
||||||
|
from gymnasium import spaces
|
||||||
|
import ctypes
|
||||||
|
from collections import deque
|
||||||
|
from typing import Tuple
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import queue
|
||||||
|
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "1"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "1"
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
sys.path.append(parent_dir)
|
||||||
|
from CelerisLab import FlowField
|
||||||
|
from CelerisLab import utils
|
||||||
|
|
||||||
|
config_cuda = utils.load_cuda_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_cuda.json")
|
||||||
|
)
|
||||||
|
config_field = utils.load_flow_field_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_flowfield.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
S_DIM, A_DIM = 12, 3
|
||||||
|
U0 = config_field.velocity
|
||||||
|
T0 = 1000
|
||||||
|
SAMPLE_INTERVAL = 800
|
||||||
|
FIFO_LEN = 120
|
||||||
|
CONV_LEN = 60
|
||||||
|
MAX_STEPS = 720
|
||||||
|
if config_field.data_type == "FP32":
|
||||||
|
DATA_TYPE = np.float32
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported data type {config_field.data_type}.")
|
||||||
|
|
||||||
|
|
||||||
|
class CustomEnv(gym.Env):
|
||||||
|
"""Custom Environment that follows gym interface."""
|
||||||
|
|
||||||
|
metadata = {"render_modes": ["human"], "render_fps": T0 / SAMPLE_INTERVAL}
|
||||||
|
|
||||||
|
def __init__(self, device_id=0):
|
||||||
|
super().__init__()
|
||||||
|
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
||||||
|
self.observation_space = spaces.Box(
|
||||||
|
low=-1, high=1, shape=(S_DIM,), dtype=DATA_TYPE
|
||||||
|
)
|
||||||
|
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.fifo_target = deque(maxlen=FIFO_LEN)
|
||||||
|
self.fifo_forces = deque(maxlen=FIFO_LEN)
|
||||||
|
self.force_norm_fact = 1.0
|
||||||
|
self.sens_norm_fact = np.ones(6, dtype=DATA_TYPE)
|
||||||
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
self.reward_sim_now = 0.0
|
||||||
|
self.reward_yaw = 0.0
|
||||||
|
self.reward_sim = 0.0
|
||||||
|
self.current_step = 0
|
||||||
|
|
||||||
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
|
L0 = 20
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0)
|
||||||
|
center: Tuple[float, float, float] = (25 * L0, (NY - 1) / 2 + 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (25 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (25 * L0, (NY - 1) / 2 - 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (40 * L0, (NY - 1) / 2 + 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (40 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (40 * L0, (NY - 1) / 2 - 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
self.flow_field.run(int(4*NX/U0), np.zeros(7, dtype=DATA_TYPE))
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(7, dtype=DATA_TYPE))
|
||||||
|
self.fifo_target.append(self.flow_field.obs.copy()[2:8])
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy()[8:14])
|
||||||
|
|
||||||
|
# target = np.array(self.fifo_target)[:, 0]
|
||||||
|
# state = np.array(self.fifo_states)[:, 0]
|
||||||
|
# target_mean = np.mean(target)
|
||||||
|
# state_mean = np.mean(state)
|
||||||
|
# correlation = np.correlate(target - target_mean, state - state_mean, "full")
|
||||||
|
# lags = np.arange(-len(target) + 1, len(target))
|
||||||
|
# self.LAG = lags[np.argmax(correlation)]
|
||||||
|
self.LAG = -9
|
||||||
|
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (31.3 * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (31.3 * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
self.flow_field.run(int(4*NX/U0), np.zeros(10, dtype=DATA_TYPE))
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(10, dtype=DATA_TYPE))
|
||||||
|
self.fifo_target.append(self.flow_field.obs.copy()[2:8])
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy()[8:14])
|
||||||
|
self.fifo_forces.append(self.flow_field.obs.copy()[14:20])
|
||||||
|
|
||||||
|
self.save_target = self.fifo_target.copy()
|
||||||
|
self.save_states = self.fifo_states.copy()
|
||||||
|
self.save_forces = self.fifo_forces.copy()
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
|
||||||
|
temp_states = np.array(self.fifo_states)
|
||||||
|
self.force_norm_fact = 6 * np.max(np.abs(np.array(self.fifo_forces)))
|
||||||
|
for i in range(6):
|
||||||
|
self.sens_deviation[i] = np.mean(temp_states[:, i])
|
||||||
|
self.sens_norm_fact[i] = 5 * np.max(np.abs(temp_states[:, i] - self.sens_deviation[i]))
|
||||||
|
|
||||||
|
|
||||||
|
def step(self, action):
|
||||||
|
assert self.action_space.contains(action), "%r (%s) invalid" % (
|
||||||
|
action,
|
||||||
|
type(action),
|
||||||
|
)
|
||||||
|
|
||||||
|
# barrier = threading.Barrier(2)
|
||||||
|
result_queue = queue.Queue()
|
||||||
|
|
||||||
|
def run_flow_field(action):
|
||||||
|
self.flow_field.context.push()
|
||||||
|
U0 = config_field.velocity
|
||||||
|
try:
|
||||||
|
temp = np.zeros(10, dtype=DATA_TYPE)
|
||||||
|
temp[7:10] = np.array((action*8+[0,-4,4])*U0, dtype=DATA_TYPE)
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
||||||
|
finally:
|
||||||
|
self.flow_field.context.pop()
|
||||||
|
# barrier.wait()
|
||||||
|
self.fifo_target.append(self.flow_field.obs.copy()[2:8])
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy()[8:14])
|
||||||
|
self.fifo_forces.append(self.flow_field.obs.copy()[14:20])
|
||||||
|
|
||||||
|
def proc_data():
|
||||||
|
target = np.array(self.fifo_target)
|
||||||
|
states = np.array(self.fifo_states)
|
||||||
|
forces = np.array(self.fifo_forces)[-1, :] / self.force_norm_fact
|
||||||
|
cd = (forces[0] + forces[2] + forces[4]) / 3
|
||||||
|
cl = (forces[1] + forces[3] + forces[5]) / 3
|
||||||
|
ave_v = np.mean(states[:, 1] + states[:, 3] + states[:, 5]) / 3
|
||||||
|
targ = (target[-1, :] - self.sens_deviation) / self.sens_norm_fact
|
||||||
|
sens = (states[-1, :] - self.sens_deviation) / self.sens_norm_fact
|
||||||
|
|
||||||
|
similarities = 0.0
|
||||||
|
sim_now = 0.0
|
||||||
|
|
||||||
|
def calc_sim(target, state, lag):
|
||||||
|
target_mean = np.mean(target)
|
||||||
|
state_mean = np.mean(state)
|
||||||
|
target_std = np.std(target)
|
||||||
|
|
||||||
|
aligned_state = np.roll(state, lag)
|
||||||
|
|
||||||
|
if lag >= 0:
|
||||||
|
seq_target = target[-CONV_LEN:]-target_mean
|
||||||
|
seq_state = aligned_state[-CONV_LEN:]-state_mean
|
||||||
|
else:
|
||||||
|
seq_target = target[:CONV_LEN]-target_mean
|
||||||
|
seq_state = aligned_state[:CONV_LEN]-state_mean
|
||||||
|
|
||||||
|
seq_diff = seq_target - seq_state
|
||||||
|
sim_cor = 10*(np.corrcoef(seq_target, seq_state)[0, 1] - 1)
|
||||||
|
sim_div = -np.abs((target_mean - state_mean) / target_std * 0.75)
|
||||||
|
sim_amp = -np.abs(np.std(seq_diff) / target_std * 2)
|
||||||
|
|
||||||
|
return np.exp((sim_cor + sim_div + sim_amp) / 3)
|
||||||
|
|
||||||
|
for i in range(0, 6):
|
||||||
|
target_seq = (target[:, i] - self.sens_deviation[i]) / self.sens_norm_fact[i]
|
||||||
|
state_seq = (states[:, i] - self.sens_deviation[i]) / self.sens_norm_fact[i]
|
||||||
|
similarities += calc_sim(target_seq, state_seq, -self.LAG) / 6
|
||||||
|
sim_now += np.abs(target_seq[self.LAG-1] - state_seq[-1]) / 6
|
||||||
|
|
||||||
|
self.reward_sim_now = np.exp(-sim_now*10)
|
||||||
|
self.reward_yaw = 1 - np.exp(-np.abs(ave_v * 10))
|
||||||
|
self.reward_sim = similarities
|
||||||
|
reward = np.clip(0.5 * self.reward_sim_now - 0.3 * self.reward_yaw + 0.8 * self.reward_sim, 0, 1)
|
||||||
|
# barrier.wait()
|
||||||
|
result_queue.put((np.hstack([targ, sens]), reward))
|
||||||
|
|
||||||
|
run_flow_field(action)
|
||||||
|
proc_data()
|
||||||
|
observation, reward = result_queue.get()
|
||||||
|
|
||||||
|
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
||||||
|
observation = np.clip(observation, -1, 1)
|
||||||
|
self.current_step += 1
|
||||||
|
done = self.current_step >= MAX_STEPS
|
||||||
|
return observation, float(reward), done, truncated, {}
|
||||||
|
|
||||||
|
def reset(self, seed=None):
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
self.fifo_target = self.save_target.copy()
|
||||||
|
self.fifo_states = self.save_states.copy()
|
||||||
|
self.fifo_forces = self.save_forces.copy()
|
||||||
|
self.current_step = 0
|
||||||
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
|
def render(self, mode="human"):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
speed = np.sqrt(ux**2 + uy**2)
|
||||||
|
plt.figure(figsize=(10, 5))
|
||||||
|
plt.imshow(speed.T, origin='lower', cmap='viridis', extent=[0, NX, 0, NY])
|
||||||
|
plt.colorbar(label='Speed')
|
||||||
|
plt.title('Scalar Velocity Field')
|
||||||
|
plt.xlabel('X')
|
||||||
|
plt.ylabel('Y')
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def save_field(self, filename):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
flag_plot = self.flow_field.flag.copy().reshape((NY, NX)).transpose(1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
with open(os.path.join(parent_dir, "output", filename), "w") as f:
|
||||||
|
f.write("Title= \"LBM 2D\"\r\n")
|
||||||
|
f.write("VARIABLES= \"X\",\"Y\",\"flag\",\"U\",\"V\",\r\n")
|
||||||
|
f.write(f"ZONE T= \"BOX\",I= {NX},J= {NY},F=POINT\r\n")
|
||||||
|
for j in range(NY):
|
||||||
|
for i in range(NX):
|
||||||
|
f.write(f"{i},{j},{flag_plot[i, j]},{ux[i, j]},{uy[i, j]}\r\n")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.flow_field.__del__()
|
||||||
@ -30,7 +30,7 @@ T0 = 1000
|
|||||||
SAMPLE_INTERVAL = 800
|
SAMPLE_INTERVAL = 800
|
||||||
FIFO_LEN = 120
|
FIFO_LEN = 120
|
||||||
CONV_LEN = 60
|
CONV_LEN = 60
|
||||||
MAX_STEPS = 240
|
MAX_STEPS = 500
|
||||||
if config_field.data_type == "FP32":
|
if config_field.data_type == "FP32":
|
||||||
DATA_TYPE = np.float32
|
DATA_TYPE = np.float32
|
||||||
else:
|
else:
|
||||||
@ -46,12 +46,16 @@ class CustomEnv(gym.Env):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
||||||
self.observation_space = spaces.Box(
|
self.observation_space = spaces.Box(
|
||||||
low=-1, high=1, shape=(S_DIM,), dtype=DATA_TYPE
|
low=-7, high=7, shape=(S_DIM,), dtype=DATA_TYPE
|
||||||
)
|
)
|
||||||
self.fifo_states = deque(maxlen=FIFO_LEN)
|
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.save_states = deque(maxlen=FIFO_LEN)
|
||||||
self.force_norm_fact = 1.0
|
self.force_norm_fact = 1.0
|
||||||
self.sens_norm_fact = 1.0
|
self.sens_norm_fact = 1.0
|
||||||
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
self.reward_cd = 0.0
|
||||||
|
self.reward_cl = 0.0
|
||||||
|
self.reward_sim = 0.0
|
||||||
self.current_step = 0
|
self.current_step = 0
|
||||||
|
|
||||||
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
@ -59,32 +63,27 @@ class CustomEnv(gym.Env):
|
|||||||
U0 = config_field.velocity
|
U0 = config_field.velocity
|
||||||
NX = self.flow_field.FIELD_SHAPE[0]
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
NY = self.flow_field.FIELD_SHAPE[1]
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 + 2 * L0, 0)
|
|
||||||
self.flow_field.add_sensor(center, L0 / 4)
|
|
||||||
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
|
||||||
self.flow_field.add_sensor(center, L0 / 4)
|
|
||||||
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 - 2 * L0, 0)
|
|
||||||
self.flow_field.add_sensor(center, L0 / 4)
|
|
||||||
center: Tuple[float, float, float] = (20 * L0, (NY - 1) / 2, 0)
|
center: Tuple[float, float, float] = (20 * L0, (NY - 1) / 2, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
center: Tuple[float, float, float] = (21.3 * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
||||||
self.flow_field.add_cylinder(center, L0 / 2)
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 + 3 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2 - 3 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
self.flow_field.run(int(4*NX/U0), np.zeros(6, dtype=DATA_TYPE))
|
self.flow_field.run(int(4*NX/U0), np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy())
|
||||||
|
|
||||||
|
self.save_states = self.fifo_states.copy()
|
||||||
self.flow_field.get_ddf()
|
self.flow_field.get_ddf()
|
||||||
self.flow_field.save_ddf()
|
self.flow_field.save_ddf()
|
||||||
|
|
||||||
# for i in range(FIFO_LEN):
|
|
||||||
# self.flow_field.run(SAMPLE_INTERVAL, np.zeros(6, dtype=DATA_TYPE))
|
|
||||||
# self.fifo_states.append(self.flow_field.obs.copy())
|
|
||||||
|
|
||||||
# temp_states = np.array(self.fifo_states)
|
|
||||||
# self.force_norm_fact = 3 * np.max(np.abs(temp_states[:, 6:12]))
|
|
||||||
# for i in range(3):
|
|
||||||
# self.sens_deviation[2*i] = np.mean(temp_states[:, 2*i])
|
|
||||||
# # self.sens_deviation[2*i] = 0.0
|
|
||||||
# self.sens_norm_fact = 6 * np.max(np.abs(temp_states[:, 1]))
|
|
||||||
|
|
||||||
|
|
||||||
def step(self, action):
|
def step(self, action):
|
||||||
@ -100,18 +99,21 @@ class CustomEnv(gym.Env):
|
|||||||
U0 = config_field.velocity
|
U0 = config_field.velocity
|
||||||
try:
|
try:
|
||||||
temp = np.zeros(6, dtype=DATA_TYPE)
|
temp = np.zeros(6, dtype=DATA_TYPE)
|
||||||
temp[3:6] = np.array((action*8)*U0, dtype=DATA_TYPE)
|
temp[0:3] = np.array((action*5+[0,-2.5,2.5])*U0, dtype=DATA_TYPE)
|
||||||
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
||||||
finally:
|
finally:
|
||||||
self.fifo_states.append(self.flow_field.obs.copy())
|
self.fifo_states.append(self.flow_field.obs.copy())
|
||||||
self.flow_field.context.pop()
|
self.flow_field.context.pop()
|
||||||
|
|
||||||
def proc_data():
|
def proc_data():
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
L0 = 20
|
||||||
states = np.array(self.fifo_states)
|
states = np.array(self.fifo_states)
|
||||||
forces = states[-1, 6:12] * 50
|
forces = states[-1, 0:6] / (L0*U0*U0)
|
||||||
cd = (forces[0] + forces[2] + forces[4]) / 3
|
cd = (forces[0] + forces[2] + forces[4])
|
||||||
cl = (forces[1] + forces[3] + forces[5]) / 3
|
cl = (forces[1] + forces[3] + forces[5])
|
||||||
sens = states[-1, 0:6] / 2
|
sens = states[-1, 6:12] / 78 / U0
|
||||||
|
|
||||||
def theo_velo(y):
|
def theo_velo(y):
|
||||||
NY = self.flow_field.FIELD_SHAPE[1]
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
@ -121,18 +123,17 @@ class CustomEnv(gym.Env):
|
|||||||
return u
|
return u
|
||||||
|
|
||||||
similarities = 0.0
|
similarities = 0.0
|
||||||
NY = self.flow_field.FIELD_SHAPE[1]
|
|
||||||
L0 = 20
|
|
||||||
sens_pos = np.array([(NY - 1) / 2 + 2 * L0, (NY - 1) / 2, (NY - 1) / 2 - 2 * L0])
|
sens_pos = np.array([(NY - 1) / 2 + 2 * L0, (NY - 1) / 2, (NY - 1) / 2 - 2 * L0])
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
u = theo_velo(sens_pos[i])
|
u = theo_velo(sens_pos[i])*78
|
||||||
similarities += np.exp(-4*np.abs(states[-1, 2*i] - u))/6 + np.exp(-8*np.abs(states[-1, 2*i+1] - 0))/6
|
similarities += np.exp(-4*np.abs(states[-1, 2*i+6] - u))/6 + np.exp(-8*np.abs(states[-1, 2*i+7] - 0))/6
|
||||||
|
|
||||||
reward_cd = np.exp(-np.abs(cd * 10))
|
self.reward_cd = np.exp(-np.abs(cd))
|
||||||
reward_cl = np.exp(-np.abs(cl * 10))
|
self.reward_cl = np.exp(-np.abs(cl))
|
||||||
|
# self.reward_cl = cd * 10.0
|
||||||
# reward_sim = np.exp(2 * (similarities - 1))
|
# reward_sim = np.exp(2 * (similarities - 1))
|
||||||
reward_sim = similarities
|
self.reward_sim = similarities
|
||||||
reward = np.minimum(0.4 * reward_cd + 0.6 * reward_cl + 0.0 * reward_sim, 1.0)
|
reward = np.clip(0.6 * self.reward_cd + 0.4 * self.reward_cl + 0.0 * self.reward_sim, 0, 1.0)
|
||||||
# barrier.wait()
|
# barrier.wait()
|
||||||
result_queue.put((np.hstack([forces, sens]), reward))
|
result_queue.put((np.hstack([forces, sens]), reward))
|
||||||
|
|
||||||
@ -140,8 +141,8 @@ class CustomEnv(gym.Env):
|
|||||||
proc_data()
|
proc_data()
|
||||||
observation, reward = result_queue.get()
|
observation, reward = result_queue.get()
|
||||||
|
|
||||||
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
truncated = bool(np.any(observation > 7) or np.any(observation < -7))
|
||||||
observation = np.clip(observation, -1, 1)
|
observation = np.clip(observation, -7, 7)
|
||||||
terminated = self.current_step >= MAX_STEPS
|
terminated = self.current_step >= MAX_STEPS
|
||||||
self.current_step += 1
|
self.current_step += 1
|
||||||
return observation, float(reward), terminated, truncated, {}
|
return observation, float(reward), terminated, truncated, {}
|
||||||
@ -149,6 +150,7 @@ class CustomEnv(gym.Env):
|
|||||||
def reset(self, seed=None):
|
def reset(self, seed=None):
|
||||||
self.flow_field.apply_ddf()
|
self.flow_field.apply_ddf()
|
||||||
self.current_step = 0
|
self.current_step = 0
|
||||||
|
self.fifo_states = self.save_states.copy()
|
||||||
return np.zeros(S_DIM, dtype=np.float32), {}
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
def render(self, mode="human"):
|
def render(self, mode="human"):
|
||||||
222
scripts/gym_env_vortex.py
Normal file
222
scripts/gym_env_vortex.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import gymnasium as gym
|
||||||
|
import numpy as np
|
||||||
|
from gymnasium import spaces
|
||||||
|
import ctypes
|
||||||
|
from collections import deque
|
||||||
|
from typing import Tuple
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import queue
|
||||||
|
|
||||||
|
os.environ["OMP_NUM_THREADS"] = "1"
|
||||||
|
os.environ["MKL_NUM_THREADS"] = "1"
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
sys.path.append(parent_dir)
|
||||||
|
from CelerisLab import FlowField
|
||||||
|
from CelerisLab import utils
|
||||||
|
|
||||||
|
config_cuda = utils.load_cuda_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_cuda.json")
|
||||||
|
)
|
||||||
|
config_field = utils.load_flow_field_config(
|
||||||
|
os.path.join(parent_dir, "configs", "config_flowfield.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
S_DIM, A_DIM = 12, 3
|
||||||
|
U0 = config_field.velocity
|
||||||
|
T0 = 1000
|
||||||
|
SAMPLE_INTERVAL = 800
|
||||||
|
FIFO_LEN = 200
|
||||||
|
CONV_LEN = 40
|
||||||
|
MAX_STEPS = 200
|
||||||
|
if config_field.data_type == "FP32":
|
||||||
|
DATA_TYPE = np.float32
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported data type {config_field.data_type}.")
|
||||||
|
|
||||||
|
|
||||||
|
class CustomEnv(gym.Env):
|
||||||
|
"""Custom Environment that follows gym interface."""
|
||||||
|
|
||||||
|
metadata = {"render_modes": ["human"], "render_fps": T0 / SAMPLE_INTERVAL}
|
||||||
|
|
||||||
|
def __init__(self, device_id=0):
|
||||||
|
super().__init__()
|
||||||
|
self.action_space = spaces.Box(low=-1, high=1, shape=(A_DIM,), dtype=DATA_TYPE)
|
||||||
|
self.observation_space = spaces.Box(
|
||||||
|
low=-1, high=1, shape=(S_DIM,), dtype=DATA_TYPE
|
||||||
|
)
|
||||||
|
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||||
|
self.target_states = np.empty((0, 6), dtype=DATA_TYPE)
|
||||||
|
self.force_norm_fact = 1.0
|
||||||
|
self.sens_norm_fact = np.ones(6, dtype=DATA_TYPE)
|
||||||
|
self.sens_deviation = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
self.reward_cd = 0.0
|
||||||
|
self.reward_cl = 0.0
|
||||||
|
self.reward_sim = 0.0
|
||||||
|
self.current_step = 0
|
||||||
|
|
||||||
|
self.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||||
|
L0 = 20
|
||||||
|
U0 = config_field.velocity
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
center: Tuple[float, float, float] = (50 * L0, (NY - 1) / 2 + 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (50 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
center: Tuple[float, float, float] = (50 * L0, (NY - 1) / 2 - 2 * L0, 0)
|
||||||
|
self.flow_field.add_sensor(center, L0 / 4)
|
||||||
|
self.flow_field.run(int(1*NX/U0), np.zeros(3, dtype=DATA_TYPE))
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
self.flow_field.save_ddf()
|
||||||
|
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_vortex(center, L0 * 2, 0.4*U0, 0, "lamb")
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(3, dtype=DATA_TYPE))
|
||||||
|
new_state = self.flow_field.obs.copy()
|
||||||
|
self.target_states = np.vstack((self.target_states, new_state))
|
||||||
|
|
||||||
|
self.flow_field.restore_ddf()
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
center: Tuple[float, float, float] = (40 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (41.3 * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
center: Tuple[float, float, float] = (41.3 * L0, (NY - 1) / 2 - 0.75 * L0, 0)
|
||||||
|
self.flow_field.add_cylinder(center, L0 / 2)
|
||||||
|
self.flow_field.run(int(4*NX/U0), np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
center: Tuple[float, float, float] = (10 * L0, (NY - 1) / 2, 0)
|
||||||
|
self.flow_field.add_vortex(center, L0 * 2, 0.4*U0, 0, "lamb")
|
||||||
|
self.flow_field.save_ddf()
|
||||||
|
|
||||||
|
for i in range(FIFO_LEN):
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(6, dtype=DATA_TYPE))
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy())
|
||||||
|
|
||||||
|
self.save_states = self.fifo_states.copy()
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
|
||||||
|
temp_states = np.array(self.fifo_states)
|
||||||
|
self.force_norm_fact = 6 * np.max(np.abs(temp_states[:, 6:12]))
|
||||||
|
for i in range(6):
|
||||||
|
self.sens_deviation[i] = np.mean(temp_states[:, i])
|
||||||
|
self.sens_norm_fact[i] = 5 * np.max(np.abs(temp_states[:, i] - self.sens_deviation[i]))
|
||||||
|
|
||||||
|
|
||||||
|
def step(self, action):
|
||||||
|
assert self.action_space.contains(action), "%r (%s) invalid" % (
|
||||||
|
action,
|
||||||
|
type(action),
|
||||||
|
)
|
||||||
|
|
||||||
|
# barrier = threading.Barrier(2)
|
||||||
|
result_queue = queue.Queue()
|
||||||
|
|
||||||
|
def run_flow_field(action):
|
||||||
|
self.flow_field.context.push()
|
||||||
|
U0 = config_field.velocity
|
||||||
|
try:
|
||||||
|
temp = np.zeros(6, dtype=DATA_TYPE)
|
||||||
|
temp[3:6] = np.array((action*8+[0,-4,4])*U0, dtype=DATA_TYPE)
|
||||||
|
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
||||||
|
finally:
|
||||||
|
self.flow_field.context.pop()
|
||||||
|
# barrier.wait()
|
||||||
|
self.fifo_states.append(self.flow_field.obs.copy())
|
||||||
|
|
||||||
|
def proc_data():
|
||||||
|
states = np.array(self.fifo_states)
|
||||||
|
forces = states[-1, 6:12] / self.force_norm_fact
|
||||||
|
cd = (forces[0] + forces[2] + forces[4]) / 3
|
||||||
|
cl = (forces[1] + forces[3] + forces[5]) / 3
|
||||||
|
sens = (states[-1, 0:6] - self.sens_deviation) / self.sens_norm_fact
|
||||||
|
|
||||||
|
similarities = 0.0
|
||||||
|
|
||||||
|
def calc_sim(target, state):
|
||||||
|
|
||||||
|
n = len(target)
|
||||||
|
m = len(state)
|
||||||
|
|
||||||
|
dtw_matrix = np.full((n + 1, m + 1), np.inf)
|
||||||
|
dtw_matrix[0, 0] = 0
|
||||||
|
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
for j in range(1, m + 1):
|
||||||
|
cost = abs(target[i - 1] - state[j - 1])
|
||||||
|
last_min = min(dtw_matrix[i - 1, j],
|
||||||
|
dtw_matrix[i, j - 1],
|
||||||
|
dtw_matrix[i - 1, j - 1])
|
||||||
|
dtw_matrix[i, j] = cost + last_min
|
||||||
|
|
||||||
|
return 1 - (dtw_matrix[n, m] / len(target))
|
||||||
|
|
||||||
|
for i in range(0, 6):
|
||||||
|
target_seq = np.roll(self.target_states[-CONV_LEN:, i], -self.current_step-1)
|
||||||
|
state_seq = states[-CONV_LEN:, i]
|
||||||
|
similarities += calc_sim(target_seq, state_seq) / 6
|
||||||
|
|
||||||
|
self.reward_cd = np.exp(-np.abs(cd * 20))
|
||||||
|
self.reward_cl = np.exp(-np.abs(cl * 80))
|
||||||
|
self.reward_sim = np.exp(-10*np.abs(similarities - 1))
|
||||||
|
reward = np.minimum(0.3 * self.reward_cd + 0.4 * self.reward_cl + 0.5 * self.reward_sim, 1.0)
|
||||||
|
# barrier.wait()
|
||||||
|
result_queue.put((np.hstack([forces, sens]), reward))
|
||||||
|
|
||||||
|
run_flow_field(action)
|
||||||
|
proc_data()
|
||||||
|
observation, reward = result_queue.get()
|
||||||
|
|
||||||
|
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
||||||
|
observation = np.clip(observation, -1, 1)
|
||||||
|
self.current_step += 1
|
||||||
|
done = self.current_step >= MAX_STEPS
|
||||||
|
return observation, float(reward), done, truncated, {}
|
||||||
|
|
||||||
|
def reset(self, seed=None):
|
||||||
|
self.flow_field.restore_ddf()
|
||||||
|
self.flow_field.apply_ddf()
|
||||||
|
self.fifo_states = self.save_states.copy()
|
||||||
|
self.current_step = 0
|
||||||
|
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||||
|
|
||||||
|
def render(self, mode="human"):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
speed = np.sqrt(ux**2 + uy**2)
|
||||||
|
plt.figure(figsize=(10, 5))
|
||||||
|
plt.imshow(speed.T, origin='lower', cmap='viridis', extent=[0, NX, 0, NY])
|
||||||
|
plt.colorbar(label='Speed')
|
||||||
|
plt.title('Scalar Velocity Field')
|
||||||
|
plt.xlabel('X')
|
||||||
|
plt.ylabel('Y')
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
def save_field(self, filename):
|
||||||
|
NX = self.flow_field.FIELD_SHAPE[0]
|
||||||
|
NY = self.flow_field.FIELD_SHAPE[1]
|
||||||
|
self.flow_field.get_ddf()
|
||||||
|
ddf_plot = self.flow_field.ddf.copy().reshape((9, NY, NX)).transpose(2, 1, 0)
|
||||||
|
flag_plot = self.flow_field.flag.copy().reshape((NY, NX)).transpose(1, 0)
|
||||||
|
ux = (ddf_plot[:, :, 1] + ddf_plot[:, :, 5] + ddf_plot[:, :, 8] - ddf_plot[:, :, 3] - ddf_plot[:, :, 6] - ddf_plot[:, :, 7]) / U0
|
||||||
|
uy = (ddf_plot[:, :, 2] + ddf_plot[:, :, 5] + ddf_plot[:, :, 6] - ddf_plot[:, :, 4] - ddf_plot[:, :, 7] - ddf_plot[:, :, 8]) / U0
|
||||||
|
with open(os.path.join(parent_dir, "output", filename), "w") as f:
|
||||||
|
f.write("Title= \"LBM 2D\"\r\n")
|
||||||
|
f.write("VARIABLES= \"X\",\"Y\",\"flag\",\"U\",\"V\",\r\n")
|
||||||
|
f.write(f"ZONE T= \"BOX\",I= {NX},J= {NY},F=POINT\r\n")
|
||||||
|
for j in range(NY):
|
||||||
|
for i in range(NX):
|
||||||
|
f.write(f"{i},{j},{flag_plot[i, j]},{ux[i, j]},{uy[i, j]}\r\n")
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.flow_field.__del__()
|
||||||
163
scripts/manifold.ipynb
Normal file
163
scripts/manifold.ipynb
Normal file
File diff suppressed because one or more lines are too long
53
scripts/manifold.py
Normal file
53
scripts/manifold.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pickle
|
||||||
|
import pycuda.driver as cuda
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
current_dir = os.path.dirname(os.path.abspath("__file__"))
|
||||||
|
parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
|
||||||
|
output_dir = os.path.join(parent_dir, "output")
|
||||||
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
sys.path.append(parent_dir)
|
||||||
|
|
||||||
|
cuda.init()
|
||||||
|
|
||||||
|
context = cuda.Device(3).make_context()
|
||||||
|
|
||||||
|
DATA_TYPE = np.float32
|
||||||
|
|
||||||
|
from env_manifold import CustomEnv
|
||||||
|
|
||||||
|
context.push()
|
||||||
|
env = CustomEnv(device_id=3)
|
||||||
|
context.pop()
|
||||||
|
|
||||||
|
size = [10, 10, 10]
|
||||||
|
|
||||||
|
def generate_random_group(size, low, high):
|
||||||
|
intervals = np.linspace(low, high, size + 1)
|
||||||
|
group = np.concatenate([np.random.uniform(intervals[i], intervals[i+1], 1) for i in range(size)])
|
||||||
|
return np.sort(group)
|
||||||
|
|
||||||
|
group1 = generate_random_group(size[0], -1, 1)
|
||||||
|
group2 = generate_random_group(size[1], -1, 1)
|
||||||
|
group3 = generate_random_group(size[2], -1, 1)
|
||||||
|
|
||||||
|
data = np.empty(size, dtype=object)
|
||||||
|
for i, a1 in enumerate(sorted(group1)):
|
||||||
|
for j, a2 in enumerate(sorted(group2)):
|
||||||
|
for k, a3 in enumerate(sorted(group3)):
|
||||||
|
context.push()
|
||||||
|
action = np.array([a1, a2, a3], dtype=np.float32)
|
||||||
|
env.reset()
|
||||||
|
for _ in range(400):
|
||||||
|
_, _, _, _, _ = env.step(action)
|
||||||
|
context.pop()
|
||||||
|
fifo = np.array(env.fifo_states.copy())
|
||||||
|
data[i, j, k] = {'action': action, 'fifo': fifo}
|
||||||
|
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
print(f"{current_time} - ({i}, {j}, {k})")
|
||||||
|
|
||||||
|
with open(os.path.join(output_dir, "manifold_1k.pkl"), 'wb') as f:
|
||||||
|
pickle.dump(data, f)
|
||||||
@ -1,16 +0,0 @@
|
|||||||
Traceback (most recent call last):
|
|
||||||
File "/home/frank14f/Frank_LBM/scripts/d1a3o12_imit.py", line 55, in <module>
|
|
||||||
test_obs, test_rewards, test_dones, info = test_env.step(test_action)
|
|
||||||
File "/home/frank14f/anaconda3/envs/pycuda_3_10/lib/python3.10/site-packages/stable_baselines3/common/vec_env/base_vec_env.py", line 206, in step
|
|
||||||
return self.step_wait()
|
|
||||||
File "/home/frank14f/anaconda3/envs/pycuda_3_10/lib/python3.10/site-packages/stable_baselines3/common/vec_env/dummy_vec_env.py", line 58, in step_wait
|
|
||||||
obs, self.buf_rews[env_idx], terminated, truncated, self.buf_infos[env_idx] = self.envs[env_idx].step(
|
|
||||||
File "/home/frank14f/anaconda3/envs/pycuda_3_10/lib/python3.10/site-packages/stable_baselines3/common/monitor.py", line 94, in step
|
|
||||||
observation, reward, terminated, truncated, info = self.env.step(action)
|
|
||||||
File "/home/frank14f/Frank_LBM/scripts/gym_env_imit.py", line 190, in step
|
|
||||||
run_flow_field(action)
|
|
||||||
File "/home/frank14f/Frank_LBM/scripts/gym_env_imit.py", line 117, in run_flow_field
|
|
||||||
self.flow_field.run(SAMPLE_INTERVAL, temp)
|
|
||||||
File "/home/frank14f/Frank_LBM/CelerisLab/driver.py", line 254, in run
|
|
||||||
cuda.memcpy_htod_async(self.action_gpu, action_pinned, stream)
|
|
||||||
KeyboardInterrupt
|
|
||||||
214
scripts/sim_test.ipynb
Normal file
214
scripts/sim_test.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@
|
|||||||
"from collections import deque\n",
|
"from collections import deque\n",
|
||||||
"import matplotlib.pyplot as plt\n",
|
"import matplotlib.pyplot as plt\n",
|
||||||
"import numpy as np\n",
|
"import numpy as np\n",
|
||||||
"from gym_env_erase import CustomEnv\n",
|
"from gym_env import CustomEnv\n",
|
||||||
"from stable_baselines3 import PPO\n",
|
"from stable_baselines3 import PPO\n",
|
||||||
"import pycuda.driver as cuda\n",
|
"import pycuda.driver as cuda\n",
|
||||||
"from scipy.optimize import curve_fit\n",
|
"from scipy.optimize import curve_fit\n",
|
||||||
@ -115,34 +115,34 @@
|
|||||||
"context2.push()\n",
|
"context2.push()\n",
|
||||||
"vec_env = CustomEnv(device_id=2)\n",
|
"vec_env = CustomEnv(device_id=2)\n",
|
||||||
"context2.pop()\n",
|
"context2.pop()\n",
|
||||||
"model = PPO.load(os.path.join(parent_dir, \"models\", \"d1a3o12_re100_imit_re50.zip\"), env=vec_env, device=\"cuda:2\")"
|
"model = PPO.load(os.path.join(parent_dir, \"models\", \"d1a3o12_re100_new_reward.zip\"), env=vec_env, device=\"cuda:2\")"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 4,
|
"execution_count": 3,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"max_reward = 0\n",
|
"max_reward = 0\n",
|
||||||
"best_seed = 0\n",
|
"best_seed = 0\n",
|
||||||
"for seed in range(1, 11):\n",
|
"# for seed in range(1, 11):\n",
|
||||||
" model.set_random_seed(seed=seed)\n",
|
"# model.set_random_seed(seed=seed)\n",
|
||||||
" context2.push()\n",
|
"# context2.push()\n",
|
||||||
" model_env = model.get_env()\n",
|
"# model_env = model.get_env()\n",
|
||||||
" obs = model_env.reset()\n",
|
"# obs = model_env.reset()\n",
|
||||||
" context2.pop()\n",
|
"# context2.pop()\n",
|
||||||
" reward_list = deque(maxlen=FIFO_LEN)\n",
|
"# reward_list = deque(maxlen=FIFO_LEN)\n",
|
||||||
" for _ in range(240):\n",
|
"# for _ in range(240):\n",
|
||||||
" context2.push()\n",
|
"# context2.push()\n",
|
||||||
" action, _states = model.predict(observation=obs, deterministic=True)\n",
|
"# action, _states = model.predict(observation=obs, deterministic=True)\n",
|
||||||
" obs, rewards, dones, info = model_env.step(action)\n",
|
"# obs, rewards, dones, info = model_env.step(action)\n",
|
||||||
" states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
"# states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
||||||
" context2.pop()\n",
|
"# context2.pop()\n",
|
||||||
" reward_list.append(rewards)\n",
|
"# reward_list.append(rewards)\n",
|
||||||
" if np.mean(reward_list) > max_reward:\n",
|
"# if np.mean(reward_list) > max_reward:\n",
|
||||||
" max_reward = np.mean(np.array(reward_list)[-FIFO_LEN:])\n",
|
"# max_reward = np.mean(np.array(reward_list)[-FIFO_LEN:])\n",
|
||||||
" best_seed = seed"
|
"# best_seed = seed"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -154,7 +154,7 @@
|
|||||||
"model.set_random_seed(seed=best_seed)\n",
|
"model.set_random_seed(seed=best_seed)\n",
|
||||||
"states_list = []\n",
|
"states_list = []\n",
|
||||||
"reward_list = []\n",
|
"reward_list = []\n",
|
||||||
"cl_list, cd_list, diff_list = [], [], []\n",
|
"cl_list, cd_list, sim_list = [], [], []\n",
|
||||||
"action_list = deque(maxlen=FIFO_LEN)\n",
|
"action_list = deque(maxlen=FIFO_LEN)\n",
|
||||||
"fifo_states = deque(maxlen=FIFO_LEN)\n",
|
"fifo_states = deque(maxlen=FIFO_LEN)\n",
|
||||||
"\n",
|
"\n",
|
||||||
@ -165,8 +165,8 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"for _ in range(240):\n",
|
"for _ in range(240):\n",
|
||||||
" context2.push()\n",
|
" context2.push()\n",
|
||||||
" # action, _states = model.predict(observation=obs, deterministic=True)\n",
|
" action, _states = model.predict(observation=obs, deterministic=True)\n",
|
||||||
" action = np.array([0.0, 0.5, -0.5], dtype=np.float32)[np.newaxis, :]\n",
|
" # action = np.array([0.0, 0.5, -0.5], dtype=np.float32)[np.newaxis, :]\n",
|
||||||
" obs, rewards, dones, info = model_env.step(action)\n",
|
" obs, rewards, dones, info = model_env.step(action)\n",
|
||||||
" states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
" states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
||||||
" context2.pop()\n",
|
" context2.pop()\n",
|
||||||
@ -175,9 +175,9 @@
|
|||||||
" reward_list.append(rewards)\n",
|
" reward_list.append(rewards)\n",
|
||||||
" action_list.append(action[0,:])\n",
|
" action_list.append(action[0,:])\n",
|
||||||
" states_list.append(np.array(states))\n",
|
" states_list.append(np.array(states))\n",
|
||||||
" cd_list.append(obs[0, 3])\n",
|
" cd_list.append(model_env.envs[0].flow_field.reward_cd.copy())\n",
|
||||||
" cl_list.append(obs[0, 4])\n",
|
" cl_list.append(model_env.envs[0].flow_field.reward_cl.copy())\n",
|
||||||
" diff_list.append(obs[0, 5])\n",
|
" sim_list.append(model_env.envs[0].flow_field.reward_sim.copy())\n",
|
||||||
"\n",
|
"\n",
|
||||||
"ave_reward = np.mean(np.array(reward_list)[-CONV_LEN:])\n"
|
"ave_reward = np.mean(np.array(reward_list)[-CONV_LEN:])\n"
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user