241104_vortex_lamb

This commit is contained in:
Frank14f 2024-11-04 18:10:36 +08:00
parent acf2b36b8c
commit 5f6337078f
54 changed files with 3292 additions and 883 deletions

5
.gitignore vendored
View File

@ -0,0 +1,5 @@
ParaView/
ParaView-X/
ParaView-O/
ParaView-E/
output/

5
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"recommendations": [
"github.copilot"
]
}

View File

@ -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"
]
} }

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

BIN
models/d0a3o12_c0.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

209
scripts/Paraview_test.ipynb Normal file
View 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
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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
View 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)

View File

@ -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 = []

View File

@ -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"))

View 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
View 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
1 div amp sin pha lin rad target
2 0 1.4045084971874737 2.2022542485937366 1.8044569186997115 2.4045084971874733 2.000008520514539 3.205367751045167 2.4045084971874737
3 1 1.9007606340087433 2.4503803170043716 2.332087743170836 2.0743362624719874 2.000003626756254 0.8461854338136477 2.9007606340087433
4 2 1.9901746746922298 2.495087337346115 2.8003643744408384 1.4850331349799533 2.000002768705942 2.1318252162776163 2.9901746746922298
5 3 1.7828033402113457 2.391401670105673 3.125591517469359 0.8679592634873357 2.000009725903628 0.8826745225681839 2.7828033402113457
6 4 1.5235721267084505 2.2617860633542253 3.2496411772354152 0.5412664647004362 2.000003167213289 2.69235119966044 2.5235721267084505
7 5 1.4065386972205927 2.2032693486102963 3.1503419016944787 0.7110698414412506 2.0000017363419866 1.5229136911774184 2.4065386972205927
8 6 1.4393159515757463 2.219657975787873 2.845441495474666 1.3337158208533584 2.0000083303175944 3.226434054111396 2.4393159515757463
9 7 1.450798066146493 2.2253990330732467 2.3894349466929015 2.1326710741083486 2.000008622178289 1.4497088303289274 2.450798066146493
10 8 1.2346026177490346 2.1173013088745174 1.8638245129722457 2.760807746204077 2.000004945419158 3.189635332867647 2.234602617749035
11 9 0.7255102977301549 1.8627551488650775 1.3625527859112463 3.001998665019795 2.0000000531831943 2.877279259114057 1.7255102977301549
12 10 0.0820556181948704 1.5410278090974352 0.975212289010335 2.88067987853731 2.0000005575959126 1.2314074364106393 1.0820556181948704
13 11 -0.3879391919354942 1.3060304040322528 0.7710325652455938 2.611352030311411 2.0000011985974036 2.6002073722377497 0.6120608080645058
14 12 -0.41407120900178107 1.2929643954991095 0.786506749402337 2.4285527467390455 2.0000057465295193 3.306797327017787 0.5859287909982189
15 13 0.06100662286373426 1.5305033114318671 1.0188691335164597 2.4176302954029674 2.0000057394450335 2.6280688418490845 1.0610066228637343
16 14 0.835358997163627 1.9176794985818135 1.4265894831152983 2.4635124212075232 2.000000157237956 2.7192885075569535 1.835358997163627
17 15 1.563785256388725 2.2818926281943623 1.9367957548917019 2.3511982850939934 2.000006669712237 0.8122113537334713 2.5637852563887247
18 16 1.9607571648768625 2.4803785824384312 2.458298550109379 1.945425564199183 2.000004826412877 1.3568097107043613 2.9607571648768625
19 17 1.9575426437755965 2.4787713218877983 2.897889437265479 1.3209370919592596 2.0000061089806707 2.703953845842629 2.9575426437755965
20 18 1.7129748348749259 2.356487417437463 3.177000137396772 0.7476065856898844 2.0000023343173337 1.9619846399137617 2.7129748348749256
21 19 1.4769767527601103 2.238488376380055 3.245745068271543 0.5341169662306902 2.000009743244121 2.554909616055127 2.4769767527601103
22 20 1.4050548066467907 2.2025274033233955 3.091837417164398 0.8319516950415051 2.0000014714851497 2.8928645533304156 2.4050548066467905
23 21 1.453105741163031 2.2265528705815156 2.7427851684764506 1.5309207382643764 2.000009510045682 1.5236138503556755 2.453105741163031
24 22 1.4242001789372487 2.2121000894686245 2.260974589186704 2.3177558292528886 2.0000029201944813 1.1128963991461416 2.4242001789372485
25 23 1.1324126591923536 2.066206329596177 1.7325199030134266 2.8607338096979964 2.00000130393951 1.55124335985003 2.1324126591923536
26 24 0.5665635064491743 1.7832817532245873 1.251872056088139 2.9994769870458047 2.000002995999825 1.598407927631956 1.5665635064491743
27 25 -0.0645293951381749 1.4677353024309125 0.9049374564453916 2.8168711382038927 2.000008336199793 1.7278190560997833 0.9354706048618251
28 26 -0.4429180340888781 1.278540982955561 0.7537238826883124 2.5507059799726233 2.0000012857027403 0.6107197064229589 0.5570819659111219
29 27 -0.33846574623936587 1.3307671268803172 0.825257805549346 2.4110604228245562 2.000004987984852 3.4037899272581957 0.6615342537606341
30 28 0.23903171004548185 1.6195158550227409 1.1067539344983808 2.431766427122485 2.0000000509206517 1.2488627569071316 1.2390317100454817
31 29 1.0355368653934778 2.017768432696739 1.5479003385274301 2.4583021126527274 2.0000068960696913 2.478842653195267 2.035536865393478
32 30 1.7011821415149164 2.350591070757458 2.0698507204359053 2.278416894255669 2.000006795035744 2.4855685723209735 2.7011821415149164
33 31 1.9945249814914687 2.4972624907457344 2.5793166513483756 1.8017902644144659 2.0000051477822907 1.077676696370284 2.9945249814914687
34 32 1.9093462173987017 2.454673108699351 2.9852410539874885 1.1598200483347811 2.0000096781408714 2.9247971085095115 2.909346217398702
35 33 1.644201157110716 2.322100578555358 3.215072875462088 0.6505771430492158 2.0000037725918194 0.7538239571282532 2.6442011571107162
36 34 1.4417206196960188 2.2208603098480095 3.2277341699096813 0.5603200863539506 2.000005012787531 2.844416571695295 2.4417206196960186
37 35 1.4119000393085435 2.2059500196542716 3.0209619784217483 0.978986558711912 2.0000091115805527 0.9619684813354784 2.4119000393085432
38 36 1.4620321158832907 2.2310160579416456 2.6317127887175022 1.7337109653776412 2.0000095376463367 2.833020040831371 2.4620321158832907
39 37 1.3802335725311756 2.190116786265588 2.129557285304864 2.4866779222155304 2.0000043047827845 1.769832064714908 2.3802335725311754
40 38 1.0119070418531917 2.005953520926596 1.6042459494330863 2.934092044751843 2.000003905537697 2.803852496436914 2.011907041853192
41 39 0.40294385993855586 1.701471929969278 1.1496679148063091 2.9760469715438402 2.0000007180273607 2.131201389557444 1.402943859938556
42 40 -0.19485966147474865 1.4025701692626256 0.847070120063711 2.748000125054671 2.0000001093900077 2.0376363601421827 0.8051403385252514
43 41 -0.4664416299100693 1.2667791850449652 0.7505360065268409 2.498926619274973 2.0000069850336386 2.695685474229468 0.5335583700899307
44 42 -0.231992651617571 1.3840036741912145 0.8773191601626429 2.4046129001987686 2.0000067946428204 0.5573683128875674 0.768007348382429
45 43 0.43125272386142244 1.7156263619307113 1.2047595703254492 2.4465843245391046 2.0000092860315317 0.9376305556112953 1.4312527238614225
46 44 1.2269506963336099 2.113475348166805 1.6743336637539006 2.439537667628344 2.0000034022459325 0.7072786555155116 2.22695069633361
47 45 1.8140483595050712 2.4070241797525354 2.202114249406634 2.185894935461177 2.0000093538461576 3.1294668511809527 2.814048359505071
48 46 2.003541692443701 2.5017708462218504 2.693770863444402 1.6469180199044717 2.0000083144795253 0.529828807947389 3.003541692443701
49 47 1.849675452591932 2.4248377262959657 3.0614294958854664 1.0070514968511075 2.0000012422880085 1.514247920878469 2.849675452591932
50 48 1.580068820844247 2.2900344104221233 3.2393783523299313 0.5807775985973418 2.000006209921787 2.542983184031196 2.580068820844247
51 49 1.4183564738688161 2.209178236934408 3.1958125528250614 0.6197322135263754 2.0000052610632344 1.6971866871871057 2.4183564738688164
52 50 1.4243914289223738 2.212195714461187 2.9385186325078756 1.147903061632729 2.0000009298767467 3.2577962123058857 2.4243914289223736
53 51 1.462409275671654 2.231204637835827 2.513482850642765 1.9362041472166056 2.000008043007149 1.9470354748148022 2.462409275671654
54 52 1.3172807335233632 2.1586403667616816 1.99667204561206 2.635407725561501 2.0000050502324247 2.209506930036168 2.317280733523363
55 53 0.8752494142060003 1.9376247071030002 1.4804560473809683 2.9808495449283816 2.000009814190974 2.7451310260842656 1.8752494142060003
56 54 0.23967224876362314 1.6198361243818116 1.0570983758251855 2.935141104542965 2.0000094206736994 3.2669332189128264 1.2396722487636231
57 55 -0.30408572820629276 1.3479571358968536 0.8022659399091139 2.6782199338017216 2.0000098588441992 2.6908547104274865 0.6959142717937072
58 56 -0.45696846239829014 1.271515768800855 0.7615050566719004 2.457875614325721 2.00000520701219 1.9002676865371069 0.5430315376017099
59 57 -0.09755188185213548 1.4512240590739323 0.9421009372918006 2.407589657860142 2.0000012780634977 3.3328107970338094 0.9024481181478645
60 58 0.631986262644157 1.8159931313220785 1.311775597982686 2.4584106341809147 2.000001988251098 1.0803693179920704 1.631986262644157
61 59 1.4045084971874737 2.2022542485937366 1.804456918699709 2.404508497187476 2.0000042089252625 2.955378256729254 2.4045084971874737

154
scripts/env_manifold.py Normal file
View 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__()

View File

@ -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
View 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__()

View File

@ -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
View 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__()

View File

@ -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
View 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

File diff suppressed because one or more lines are too long

53
scripts/manifold.py Normal file
View 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)

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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"
] ]