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]": {
|
||||
},
|
||||
"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 numpy as np
|
||||
import struct
|
||||
from scipy.special import jv, expi
|
||||
from typing import List, Tuple, Union, Optional
|
||||
|
||||
from . import utils
|
||||
@ -13,7 +15,7 @@ SOLID = 0b00000010
|
||||
GAS = 0b00000100
|
||||
INTERFACE = 0b00001000
|
||||
SENSOR = 0b00010000
|
||||
|
||||
V_TAYLOR = np.int32(1)
|
||||
|
||||
class FlowField:
|
||||
def __init__(
|
||||
@ -94,12 +96,14 @@ class FlowField:
|
||||
self.flag = np.ones(self.FIELD_SIZE, dtype=np.uint8)
|
||||
self.indx = np.zeros(self.FIELD_SIZE, dtype=np.int32)
|
||||
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.temp_gpu = cuda.mem_alloc(self.ddf.nbytes)
|
||||
self.flag_gpu = cuda.mem_alloc(self.flag.nbytes)
|
||||
self.indx_gpu = cuda.mem_alloc(self.indx.nbytes)
|
||||
self.delta_gpu = cuda.mem_alloc(1)
|
||||
self.vortex_gpu = cuda.mem_alloc(self.vortex_config.nbytes)
|
||||
|
||||
self.objects = {}
|
||||
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.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 = cuda.mem_alloc(self.obs.nbytes)
|
||||
|
||||
@ -236,12 +240,108 @@ class FlowField:
|
||||
self.ptx = cuda.module_from_file(compiler.kernel_path("kernel.ptx"))
|
||||
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):
|
||||
if (
|
||||
action_target.size != len(self.objects)
|
||||
or action_target.dtype != self.DATA_TYPE
|
||||
):
|
||||
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
|
||||
stream = cuda.Stream()
|
||||
|
||||
@ -187,4 +187,36 @@ extern "C"
|
||||
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
|
||||
#define LBtype float
|
||||
#define UX 12
|
||||
#define UY 20
|
||||
#define UX 10
|
||||
#define UY 16
|
||||
#define UZ 1
|
||||
#define NX 1536
|
||||
#define NY 640
|
||||
#define NX 1280
|
||||
#define NY 512
|
||||
#define NZ 1
|
||||
#define DIM 2
|
||||
#define NQ 9
|
||||
#define VIS 0.006
|
||||
#define VIS 0.004
|
||||
#define RHO 1.0
|
||||
#define U0 0.01
|
||||
|
||||
@ -29,6 +29,9 @@
|
||||
#define INTERFACE 0b00001000
|
||||
#define SENSOR 0b00010000
|
||||
|
||||
// vortex type
|
||||
#define V_TAYLOR 0b00000001
|
||||
|
||||
// variables
|
||||
#define N_OBJS 7
|
||||
#define N_OBJS 6
|
||||
// #define N_SENS 2
|
||||
@ -2,8 +2,8 @@
|
||||
"data_type": "FP32",
|
||||
"dimensionality": 2,
|
||||
"lattice": 9,
|
||||
"field_dim_in_U": [12, 20, 1],
|
||||
"viscosity": 0.006,
|
||||
"field_dim_in_U": [10, 16, 1],
|
||||
"viscosity": 0.004,
|
||||
"velocity": 0.01,
|
||||
"boundary_conditions": {
|
||||
"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
|
||||
from torch.nn import Module
|
||||
import gymnasium as gym
|
||||
from gym_env_1 import CustomEnv
|
||||
from gym_env_uniflow import CustomEnv
|
||||
from stable_baselines3 import PPO
|
||||
from stable_baselines3.common.vec_env import SubprocVecEnv
|
||||
from stable_baselines3.common.vec_env import DummyVecEnv
|
||||
@ -26,7 +26,7 @@ class Sin(Module):
|
||||
if __name__ == '__main__':
|
||||
|
||||
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"))
|
||||
|
||||
@ -35,13 +35,15 @@ if __name__ == '__main__':
|
||||
policy_kwargs=dict(activation_fn=Sin),
|
||||
env=vec_env,
|
||||
device=torch.device("cuda:1"),
|
||||
n_steps=2400,
|
||||
batch_size=240,
|
||||
verbose=0)
|
||||
|
||||
writer = SummaryWriter(log_dir=os.path.join(parent_dir, "tensorboard", name))
|
||||
max_reward = 0
|
||||
|
||||
for i in range(240):
|
||||
model.learn(total_timesteps=240)
|
||||
for i in range(100):
|
||||
model.learn(total_timesteps=2400)
|
||||
test_env = model.get_env()
|
||||
test_obs = test_env.reset()
|
||||
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),
|
||||
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))
|
||||
@ -43,8 +45,8 @@ if __name__ == '__main__':
|
||||
|
||||
history_data = []
|
||||
|
||||
for i in range(400):
|
||||
model.learn(total_timesteps=360)
|
||||
for i in range(100):
|
||||
model.learn(total_timesteps=3600)
|
||||
test_env = model.get_env()
|
||||
test_obs = test_env.reset()
|
||||
list_reward = []
|
||||
|
||||
@ -27,7 +27,7 @@ class Sin(Module):
|
||||
if __name__ == '__main__':
|
||||
|
||||
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"))
|
||||
|
||||
|
||||
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
|
||||
FIFO_LEN = 120
|
||||
CONV_LEN = 60
|
||||
MAX_STEPS = 360
|
||||
MAX_STEPS = 500
|
||||
if config_field.data_type == "FP32":
|
||||
DATA_TYPE = np.float32
|
||||
else:
|
||||
@ -54,6 +54,10 @@ class CustomEnv(gym.Env):
|
||||
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
|
||||
@ -89,6 +93,9 @@ class CustomEnv(gym.Env):
|
||||
self.flow_field.run(SAMPLE_INTERVAL, np.zeros(7, dtype=DATA_TYPE))
|
||||
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)
|
||||
self.force_norm_fact = 6 * np.max(np.abs(temp_states[:, 6:12]))
|
||||
for i in range(6):
|
||||
@ -144,35 +151,58 @@ class CustomEnv(gym.Env):
|
||||
aligned_state = np.roll(state, lag)
|
||||
|
||||
if lag >= 0:
|
||||
seq_target = target[-CONV_LEN:]-target_mean
|
||||
seq_state = aligned_state[-CONV_LEN:]-state_mean
|
||||
# seq_target = target[-CONV_LEN:]-target_mean
|
||||
# seq_state = aligned_state[-CONV_LEN:]-state_mean
|
||||
seq_target = target[-CONV_LEN:]
|
||||
seq_state = aligned_state[-CONV_LEN:]
|
||||
else:
|
||||
seq_target = target[:CONV_LEN]-target_mean
|
||||
seq_state = aligned_state[:CONV_LEN]-state_mean
|
||||
# seq_target = target[:CONV_LEN]-target_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
|
||||
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)
|
||||
def dtw(target, state):
|
||||
n = len(target)
|
||||
m = len(state)
|
||||
|
||||
return np.exp((sim_cor + sim_div + sim_amp) / 3)
|
||||
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))
|
||||
|
||||
# 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
|
||||
target_seq = self.target_states[:, 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)
|
||||
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):
|
||||
target_seq = self.target_states[:, 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))
|
||||
reward_cl = np.exp(-np.abs(cl * 80))
|
||||
# reward_sim = np.exp(2 * (similarities - 1))
|
||||
reward_sim = similarities
|
||||
reward = np.minimum(0.3 * reward_cd + 0.3 * reward_cl + 0.4 * reward_sim, 1.0)
|
||||
self.reward_cd = np.exp(-np.abs(cd * 20))
|
||||
self.reward_cl = np.exp(-np.abs(cl * 80))
|
||||
self.reward_sim = similarities
|
||||
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))
|
||||
|
||||
@ -182,11 +212,14 @@ class CustomEnv(gym.Env):
|
||||
|
||||
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
||||
observation = np.clip(observation, -1, 1)
|
||||
# truncated = False
|
||||
return observation, float(reward), False, truncated, {}
|
||||
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_states = self.save_states.copy()
|
||||
self.current_step = 0
|
||||
return np.zeros(S_DIM, dtype=np.float32), {}
|
||||
|
||||
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.flow_field = FlowField(config_field, config_cuda, device_id)
|
||||
L0 = 30
|
||||
L0 = 20
|
||||
U0 = config_field.velocity
|
||||
NX = self.flow_field.FIELD_SHAPE[0]
|
||||
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)
|
||||
self.flow_field.add_cylinder(center, L0)
|
||||
center: Tuple[float, float, float] = (30 * L0, (NY - 1) / 2, 0)
|
||||
self.flow_field.add_cylinder(center, L0 / 2)
|
||||
center: Tuple[float, float, float] = ((30+1.3) * L0, (NY - 1) / 2 + 0.75 * L0, 0)
|
||||
self.flow_field.add_cylinder(center, L0 / 2)
|
||||
center: Tuple[float, float, float] = ((30+1.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*1.5)
|
||||
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*1.5)
|
||||
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*1.5)
|
||||
|
||||
self.flow_field.run(int(4*NX/U0), np.zeros(7, dtype=DATA_TYPE))
|
||||
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
|
||||
FIFO_LEN = 120
|
||||
CONV_LEN = 60
|
||||
MAX_STEPS = 240
|
||||
MAX_STEPS = 500
|
||||
if config_field.data_type == "FP32":
|
||||
DATA_TYPE = np.float32
|
||||
else:
|
||||
@ -46,12 +46,16 @@ class CustomEnv(gym.Env):
|
||||
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
|
||||
low=-7, high=7, shape=(S_DIM,), dtype=DATA_TYPE
|
||||
)
|
||||
self.fifo_states = deque(maxlen=FIFO_LEN)
|
||||
self.save_states = deque(maxlen=FIFO_LEN)
|
||||
self.force_norm_fact = 1.0
|
||||
self.sens_norm_fact = 1.0
|
||||
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)
|
||||
@ -59,33 +63,28 @@ class CustomEnv(gym.Env):
|
||||
U0 = config_field.velocity
|
||||
NX = self.flow_field.FIELD_SHAPE[0]
|
||||
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)
|
||||
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()
|
||||
|
||||
# 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):
|
||||
assert self.action_space.contains(action), "%r (%s) invalid" % (
|
||||
@ -100,18 +99,21 @@ class CustomEnv(gym.Env):
|
||||
U0 = config_field.velocity
|
||||
try:
|
||||
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)
|
||||
finally:
|
||||
self.fifo_states.append(self.flow_field.obs.copy())
|
||||
self.flow_field.context.pop()
|
||||
|
||||
def proc_data():
|
||||
U0 = config_field.velocity
|
||||
NY = self.flow_field.FIELD_SHAPE[1]
|
||||
L0 = 20
|
||||
states = np.array(self.fifo_states)
|
||||
forces = states[-1, 6:12] * 50
|
||||
cd = (forces[0] + forces[2] + forces[4]) / 3
|
||||
cl = (forces[1] + forces[3] + forces[5]) / 3
|
||||
sens = states[-1, 0:6] / 2
|
||||
forces = states[-1, 0:6] / (L0*U0*U0)
|
||||
cd = (forces[0] + forces[2] + forces[4])
|
||||
cl = (forces[1] + forces[3] + forces[5])
|
||||
sens = states[-1, 6:12] / 78 / U0
|
||||
|
||||
def theo_velo(y):
|
||||
NY = self.flow_field.FIELD_SHAPE[1]
|
||||
@ -121,18 +123,17 @@ class CustomEnv(gym.Env):
|
||||
return u
|
||||
|
||||
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])
|
||||
for i in range(3):
|
||||
u = theo_velo(sens_pos[i])
|
||||
similarities += np.exp(-4*np.abs(states[-1, 2*i] - u))/6 + np.exp(-8*np.abs(states[-1, 2*i+1] - 0))/6
|
||||
u = theo_velo(sens_pos[i])*78
|
||||
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))
|
||||
reward_cl = np.exp(-np.abs(cl * 10))
|
||||
self.reward_cd = np.exp(-np.abs(cd))
|
||||
self.reward_cl = np.exp(-np.abs(cl))
|
||||
# self.reward_cl = cd * 10.0
|
||||
# reward_sim = np.exp(2 * (similarities - 1))
|
||||
reward_sim = similarities
|
||||
reward = np.minimum(0.4 * reward_cd + 0.6 * reward_cl + 0.0 * reward_sim, 1.0)
|
||||
self.reward_sim = similarities
|
||||
reward = np.clip(0.6 * self.reward_cd + 0.4 * self.reward_cl + 0.0 * self.reward_sim, 0, 1.0)
|
||||
# barrier.wait()
|
||||
result_queue.put((np.hstack([forces, sens]), reward))
|
||||
|
||||
@ -140,8 +141,8 @@ class CustomEnv(gym.Env):
|
||||
proc_data()
|
||||
observation, reward = result_queue.get()
|
||||
|
||||
truncated = bool(np.any(observation > 1) or np.any(observation < -1))
|
||||
observation = np.clip(observation, -1, 1)
|
||||
truncated = bool(np.any(observation > 7) or np.any(observation < -7))
|
||||
observation = np.clip(observation, -7, 7)
|
||||
terminated = self.current_step >= MAX_STEPS
|
||||
self.current_step += 1
|
||||
return observation, float(reward), terminated, truncated, {}
|
||||
@ -149,6 +150,7 @@ class CustomEnv(gym.Env):
|
||||
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"):
|
||||
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",
|
||||
"import matplotlib.pyplot as plt\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",
|
||||
"import pycuda.driver as cuda\n",
|
||||
"from scipy.optimize import curve_fit\n",
|
||||
@ -115,34 +115,34 @@
|
||||
"context2.push()\n",
|
||||
"vec_env = CustomEnv(device_id=2)\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",
|
||||
"execution_count": 4,
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"max_reward = 0\n",
|
||||
"best_seed = 0\n",
|
||||
"for seed in range(1, 11):\n",
|
||||
" model.set_random_seed(seed=seed)\n",
|
||||
" context2.push()\n",
|
||||
" model_env = model.get_env()\n",
|
||||
" obs = model_env.reset()\n",
|
||||
" context2.pop()\n",
|
||||
" reward_list = deque(maxlen=FIFO_LEN)\n",
|
||||
" for _ in range(240):\n",
|
||||
" context2.push()\n",
|
||||
" action, _states = model.predict(observation=obs, deterministic=True)\n",
|
||||
" obs, rewards, dones, info = model_env.step(action)\n",
|
||||
" states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
||||
" context2.pop()\n",
|
||||
" reward_list.append(rewards)\n",
|
||||
" if np.mean(reward_list) > max_reward:\n",
|
||||
" max_reward = np.mean(np.array(reward_list)[-FIFO_LEN:])\n",
|
||||
" best_seed = seed"
|
||||
"# for seed in range(1, 11):\n",
|
||||
"# model.set_random_seed(seed=seed)\n",
|
||||
"# context2.push()\n",
|
||||
"# model_env = model.get_env()\n",
|
||||
"# obs = model_env.reset()\n",
|
||||
"# context2.pop()\n",
|
||||
"# reward_list = deque(maxlen=FIFO_LEN)\n",
|
||||
"# for _ in range(240):\n",
|
||||
"# context2.push()\n",
|
||||
"# action, _states = model.predict(observation=obs, deterministic=True)\n",
|
||||
"# obs, rewards, dones, info = model_env.step(action)\n",
|
||||
"# states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
||||
"# context2.pop()\n",
|
||||
"# reward_list.append(rewards)\n",
|
||||
"# if np.mean(reward_list) > max_reward:\n",
|
||||
"# max_reward = np.mean(np.array(reward_list)[-FIFO_LEN:])\n",
|
||||
"# best_seed = seed"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -154,7 +154,7 @@
|
||||
"model.set_random_seed(seed=best_seed)\n",
|
||||
"states_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",
|
||||
"fifo_states = deque(maxlen=FIFO_LEN)\n",
|
||||
"\n",
|
||||
@ -165,8 +165,8 @@
|
||||
"\n",
|
||||
"for _ in range(240):\n",
|
||||
" context2.push()\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, _states = model.predict(observation=obs, deterministic=True)\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",
|
||||
" states = model_env.envs[0].flow_field.obs.copy()[2:14]\n",
|
||||
" context2.pop()\n",
|
||||
@ -175,9 +175,9 @@
|
||||
" reward_list.append(rewards)\n",
|
||||
" action_list.append(action[0,:])\n",
|
||||
" states_list.append(np.array(states))\n",
|
||||
" cd_list.append(obs[0, 3])\n",
|
||||
" cl_list.append(obs[0, 4])\n",
|
||||
" diff_list.append(obs[0, 5])\n",
|
||||
" cd_list.append(model_env.envs[0].flow_field.reward_cd.copy())\n",
|
||||
" cl_list.append(model_env.envs[0].flow_field.reward_cl.copy())\n",
|
||||
" sim_list.append(model_env.envs[0].flow_field.reward_sim.copy())\n",
|
||||
"\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