├── .gitignore ├── script ├── u_velocity_at_x05.png ├── u_velocity_contour.png ├── plot.u@.y.py └── plot.py ├── MatrixInterface.cpp ├── version.1.1DDiffusion_POP ├── CMakeLists.txt └── main.cpp ├── version.2.1DDiffusion_OOP ├── CMakeLists.txt ├── Inputs.h ├── main.cpp ├── MatrixCoeff.h └── Mesh.h ├── version.3.1DDiffusion-Convection ├── CMakeLists.txt ├── main.cpp ├── Inputs.h ├── MatrixCoeff.h └── Mesh.h ├── version.4.1DDiffusion-Convection-Upwind ├── CMakeLists.txt ├── main.cpp ├── Inputs.h ├── MatrixCoeff.h └── Mesh.h ├── install.eigen.sh ├── MatrixInterface.h ├── version.5.1DDiffusion-Neumann-Boundary ├── CMakeLists.txt ├── config.json ├── main.cpp ├── Inputs.h ├── Inputs.cpp ├── MatrixCoeff.h └── Mesh.h ├── ref.data ├── u.@.y.Re1000.csv └── u.@.y.txt ├── PWIM.h ├── config.json ├── XMomentumEqn.h ├── YMomentumEqn.h ├── TransportEqn.cpp ├── EnergyEqn.h ├── Field.h ├── PWIM.cpp ├── CMakeLists.txt ├── README.md ├── Inputs.h ├── MatrixWrapper.h ├── TransportEqn.h ├── Mesh.cpp ├── Inputs.cpp ├── EnergyEqn.cpp ├── Output.h ├── YMomentumEqn.cpp ├── XMomentumEqn.cpp ├── Mesh.h ├── main.cpp ├── MatrixCoeff.h ├── docs └── plot_notes.md ├── v.csv ├── Co-Located SIMPLE.md └── u.csv /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .cache/ 3 | .vscode/ 4 | eigen-3.3.7/ 5 | lib_eigen337/ 6 | lib_json/ -------------------------------------------------------------------------------- /script/u_velocity_at_x05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yinweijie/CFD-Eigen-Solver/HEAD/script/u_velocity_at_x05.png -------------------------------------------------------------------------------- /script/u_velocity_contour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yinweijie/CFD-Eigen-Solver/HEAD/script/u_velocity_contour.png -------------------------------------------------------------------------------- /MatrixInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "MatrixInterface.h" 2 | 3 | // 纯虚析构函数必须保留一个类外实现,因为子类在析构的时候会调用父类的析构函数,如果不定义会编译报错 4 | MatrixInterface::~MatrixInterface() 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /version.1.1DDiffusion_POP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS_V1 2 | main.cpp 3 | ) 4 | # add the executable 5 | add_executable(CFD_Eigen_v1 ${SRCS_V1}) 6 | target_include_directories(CFD_Eigen_v1 PRIVATE ${EIGEN3_INCLUDE_DIR}) -------------------------------------------------------------------------------- /version.2.1DDiffusion_OOP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS_V2 2 | main.cpp 3 | ) 4 | # add the executable 5 | add_executable(CFD_Eigen_v2 ${SRCS_V2}) 6 | target_include_directories(CFD_Eigen_v2 PRIVATE ${EIGEN3_INCLUDE_DIR}) -------------------------------------------------------------------------------- /version.3.1DDiffusion-Convection/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS_V3 2 | main.cpp 3 | ) 4 | # add the executable 5 | add_executable(CFD_Eigen_v3 ${SRCS_V3}) 6 | target_include_directories(CFD_Eigen_v3 PRIVATE ${EIGEN3_INCLUDE_DIR}) -------------------------------------------------------------------------------- /version.4.1DDiffusion-Convection-Upwind/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS_V4 2 | main.cpp 3 | ) 4 | # add the executable 5 | add_executable(CFD_Eigen_v4 ${SRCS_V4}) 6 | target_include_directories(CFD_Eigen_v4 PRIVATE ${EIGEN3_INCLUDE_DIR}) -------------------------------------------------------------------------------- /install.eigen.sh: -------------------------------------------------------------------------------- 1 | tar xvf eigen-3.3.7.tar.gz 2 | cd eigen-3.3.7/ 3 | mkdir build 4 | cd build 5 | cmake -DCMAKE_BUILD_TYPE=release \ 6 | -DCMAKE_INSTALL_PREFIX=../../lib_eigen337 \ 7 | .. 8 | make -j 9 | make check 10 | make install -------------------------------------------------------------------------------- /MatrixInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_INTERFACE_H__ 2 | #define __MATRIX_INTERFACE_H__ 3 | 4 | class MatrixInterface 5 | { 6 | public: 7 | virtual void setNum(int row, int col, double value) = 0; 8 | virtual ~MatrixInterface() = 0; 9 | }; 10 | 11 | #endif -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS_V5 2 | main.cpp 3 | Inputs.cpp 4 | ) 5 | # add the executable 6 | add_executable(CFD_Eigen_v5 ${SRCS_V5}) 7 | target_include_directories(CFD_Eigen_v5 PRIVATE ${EIGEN3_INCLUDE_DIR}) 8 | target_link_libraries(CFD_Eigen_v5 PRIVATE nlohmann_json::nlohmann_json) -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "thermal_conductivity": 100.0, 3 | "cross_sectional_area": 0.1, 4 | "length": 5.0, 5 | "number_of_cells": 5, 6 | "temperature_left": 100.0, 7 | "temperature_right": 200.0, 8 | "heat_source": 1000.0, 9 | "density": 1.0, 10 | "specific_heat": 1000.0, 11 | "fluid_velocity": 0.0, 12 | "heat_flux_boundary": -100.0 13 | } -------------------------------------------------------------------------------- /ref.data/u.@.y.Re1000.csv: -------------------------------------------------------------------------------- 1 | x,y,u 2 | 0.5,1 , 1 3 | 0.5,0.9766, 0.6644227 4 | 0.5,0.9688, 0.5808359 5 | 0.5,0.9609, 0.5169277 6 | 0.5,0.9531, 0.4723329 7 | 0.5,0.8516, 0.3372212 8 | 0.5,0.7344, 0.1886747 9 | 0.5,0.6172, 0.0570178 10 | 0.5,0.5 ,-0.0620561 11 | 0.5,0.4531,-0.1081999 12 | 0.5,0.2813,-0.2803696 13 | 0.5,0.1719,-0.3885691 14 | 0.5,0.1016,-0.3004561 15 | 0.5,0.0703,-0.2228955 16 | 0.5,0.0625,-0.20233 17 | 0.5,0.0547,-0.1812881 18 | 0.5,0 , 0 -------------------------------------------------------------------------------- /PWIM.h: -------------------------------------------------------------------------------- 1 | #ifndef __PWIM_H__ 2 | #define __PWIM_H__ 3 | 4 | #include "Field.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | #include "XMomentumEqn.h" 8 | #include "YMomentumEqn.h" 9 | #include "Inputs.h" 10 | 11 | class PWIM 12 | { 13 | private: 14 | Inputs* inputs; 15 | Field* field; 16 | Mesh* mesh; 17 | MatrixCoeff* xMatrixCoeff; 18 | MatrixCoeff* yMatrixCoeff; 19 | 20 | using XMat = MatrixCoeff; 21 | using YMat = MatrixCoeff; 22 | 23 | public: 24 | PWIM(Inputs* inputs_, Field* field_, Mesh* mesh_, XMat* xMat, YMat* yMat) 25 | : inputs(inputs_), field(field_), mesh(mesh_), xMatrixCoeff(xMat), yMatrixCoeff(yMat) { } 26 | 27 | void updateFaceVel(); 28 | }; 29 | 30 | #endif -------------------------------------------------------------------------------- /version.2.1DDiffusion_OOP/Inputs.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUTS_H__ 2 | #define __INPUTS_H__ 3 | 4 | namespace Inputs 5 | { 6 | // # Thermal Conductivity of the bar (W/mK) 7 | constexpr double k = 100; 8 | 9 | // # Cross-sectional Area of the bar (m2) 10 | constexpr double A = 0.1; 11 | 12 | // # Length of the bar (m) 13 | constexpr double L = 5; 14 | 15 | // # Number of cells in the mesh 16 | constexpr int N = 5; 17 | 18 | // # Temperature at the left hand side of the bar (deg C) 19 | constexpr double T_A = 100; 20 | 21 | // # Temperature at the left hand side of the bar (deg C) 22 | constexpr double T_B = 200; 23 | 24 | // # Heat source per unit volume (W/m3) 25 | constexpr double S_bar = 1000; 26 | } 27 | 28 | #endif -------------------------------------------------------------------------------- /version.2.1DDiffusion_OOP/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Inputs.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::VectorXd; 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | // 创建网格 15 | unique_ptr mesh = make_unique(Inputs::L, Inputs::N); 16 | 17 | // 初始化矩阵 18 | unique_ptr MCoeff = make_unique(mesh.get()); 19 | 20 | // 获取矩阵 21 | MatrixXd& A_m = MCoeff->get_A_m(); 22 | VectorXd& b_m = MCoeff->get_b_m(); 23 | VectorXd& x = MCoeff->get_x(); 24 | 25 | // 求解矩阵 26 | x = A_m.fullPivLu().solve(b_m); 27 | 28 | // 输出结果 29 | cout << "Solution: " << endl << x << endl; 30 | } 31 | -------------------------------------------------------------------------------- /version.3.1DDiffusion-Convection/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Inputs.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::VectorXd; 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | // 创建网格 15 | unique_ptr mesh = make_unique(Inputs::L, Inputs::N); 16 | 17 | // 初始化矩阵 18 | unique_ptr MCoeff = make_unique(mesh.get()); 19 | 20 | // 获取矩阵 21 | MatrixXd& A_m = MCoeff->get_A_m(); 22 | VectorXd& b_m = MCoeff->get_b_m(); 23 | VectorXd& x = MCoeff->get_x(); 24 | 25 | // 求解矩阵 26 | x = A_m.fullPivLu().solve(b_m); 27 | 28 | // 输出结果 29 | cout << "Solution: " << endl << x << endl; 30 | } 31 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "geometry": { 3 | "XLen": 1, 4 | "YLen": 1, 5 | "ZLen": 1 6 | }, 7 | "physcial_properties": { 8 | "k": 100, 9 | "rho": 1.0, 10 | "cp": 1000, 11 | "mu": 0.1 12 | }, 13 | "boundary": { 14 | "T_left": 100, 15 | "T_right": 200, 16 | "T_bottom": 250, 17 | "T_top": 150, 18 | "q_w": 100, 19 | "U_left": 0.0, 20 | "U_right": 0.0, 21 | "U_top": 1.0, 22 | "U_bottom": 0.0, 23 | "V_left": 0.0, 24 | "V_right": 0.0, 25 | "V_top": 0.0, 26 | "V_bottom": 0.0, 27 | "p_left": 0.0, 28 | "p_right": 0.0, 29 | "p_top": 0.0, 30 | "p_bottom": 0.0 31 | }, 32 | "source": { 33 | "S_bar": 1000 34 | } 35 | } -------------------------------------------------------------------------------- /version.4.1DDiffusion-Convection-Upwind/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Inputs.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::VectorXd; 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | // 创建网格 15 | unique_ptr mesh = make_unique(Inputs::L, Inputs::N); 16 | 17 | // 初始化矩阵 18 | unique_ptr MCoeff = make_unique(mesh.get()); 19 | 20 | // 获取矩阵 21 | MatrixXd& A_m = MCoeff->get_A_m(); 22 | VectorXd& b_m = MCoeff->get_b_m(); 23 | VectorXd& x = MCoeff->get_x(); 24 | 25 | // 求解矩阵 26 | x = A_m.fullPivLu().solve(b_m); 27 | 28 | // 输出结果 29 | cout << "Solution: " << endl << x << endl; 30 | } 31 | -------------------------------------------------------------------------------- /XMomentumEqn.h: -------------------------------------------------------------------------------- 1 | #ifndef __XMOMENTUMEQN_H__ 2 | #define __XMOMENTUMEQN_H__ 3 | 4 | #include "TransportEqn.h" 5 | #include "Inputs.h" 6 | 7 | class XMomentumEqn : public TransportEqn 8 | { 9 | private: 10 | double mu; 11 | 12 | MatrixCoeff* mat; 13 | 14 | double gamma() override { return mu; } 15 | double density() override { return rho; } 16 | void init_S(); 17 | public: 18 | XMomentumEqn(Mesh* mesh, Field* field, Inputs* inputs, MatrixCoeff* matrix_coeff, Boundary* boundary, Source* source) 19 | : TransportEqn(mesh, field, inputs, boundary, source) 20 | { 21 | mu = inputs->physcial_properties.mu; 22 | 23 | mat = matrix_coeff; 24 | 25 | init_S(); 26 | } 27 | 28 | TransportEqn& addConvectionTerm() override; 29 | TransportEqn& addDiffusionTerm() override; 30 | TransportEqn& addSourceTerm() override; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /YMomentumEqn.h: -------------------------------------------------------------------------------- 1 | #ifndef __YMOMENTUMEQN_H__ 2 | #define __YMOMENTUMEQN_H__ 3 | 4 | #include "TransportEqn.h" 5 | #include "Inputs.h" 6 | 7 | class YMomentumEqn : public TransportEqn 8 | { 9 | private: 10 | double mu; 11 | 12 | MatrixCoeff* mat; 13 | 14 | double gamma() override { return mu; } 15 | double density() override { return rho; } 16 | void init_S(); 17 | public: 18 | YMomentumEqn(Mesh* mesh, Field* field, Inputs* inputs, MatrixCoeff* matrix_coeff, Boundary* boundary, Source* source) 19 | : TransportEqn(mesh, field, inputs, boundary, source) 20 | { 21 | mu = inputs->physcial_properties.mu; 22 | 23 | mat = matrix_coeff; 24 | 25 | init_S(); 26 | } 27 | 28 | TransportEqn& addConvectionTerm() override; 29 | TransportEqn& addDiffusionTerm() override; 30 | TransportEqn& addSourceTerm() override; 31 | }; 32 | 33 | #endif -------------------------------------------------------------------------------- /version.3.1DDiffusion-Convection/Inputs.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUTS_H__ 2 | #define __INPUTS_H__ 3 | 4 | namespace Inputs 5 | { 6 | // # Thermal Conductivity of the bar (W/mK) 7 | constexpr double k = 100; 8 | 9 | // # Cross-sectional Area of the bar (m2) 10 | constexpr double A = 0.1; 11 | 12 | // # Length of the bar (m) 13 | constexpr double L = 5; 14 | 15 | // # Number of cells in the mesh 16 | constexpr int N = 5; 17 | 18 | // # Temperature at the left hand side of the bar (deg C) 19 | constexpr double T_A = 100; 20 | 21 | // # Temperature at the left hand side of the bar (deg C) 22 | constexpr double T_B = 200; 23 | 24 | // # Heat source per unit volume (W/m3) 25 | constexpr double S_bar = 1000; 26 | 27 | // 密度 kg/m^3 28 | double rho = 1.0; 29 | 30 | // 比热容 J/kg/k 31 | double cp = 1000; 32 | 33 | // 流体速度 34 | double U = 0.01; 35 | } 36 | 37 | #endif -------------------------------------------------------------------------------- /version.4.1DDiffusion-Convection-Upwind/Inputs.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUTS_H__ 2 | #define __INPUTS_H__ 3 | 4 | namespace Inputs 5 | { 6 | // # Thermal Conductivity of the bar (W/mK) 7 | constexpr double k = 100; 8 | 9 | // # Cross-sectional Area of the bar (m2) 10 | constexpr double A = 0.1; 11 | 12 | // # Length of the bar (m) 13 | constexpr double L = 5; 14 | 15 | // # Number of cells in the mesh 16 | constexpr int N = 5; 17 | 18 | // # Temperature at the left hand side of the bar (deg C) 19 | constexpr double T_A = 100; 20 | 21 | // # Temperature at the left hand side of the bar (deg C) 22 | constexpr double T_B = 200; 23 | 24 | // # Heat source per unit volume (W/m3) 25 | constexpr double S_bar = 1000; 26 | 27 | // 密度 kg/m^3 28 | double rho = 1.0; 29 | 30 | // 比热容 J/kg/k 31 | double cp = 1000; 32 | 33 | // 流体速度 34 | double U = 0.01; 35 | } 36 | 37 | #endif -------------------------------------------------------------------------------- /TransportEqn.cpp: -------------------------------------------------------------------------------- 1 | #include "TransportEqn.h" 2 | 3 | void TransportEqn::init_DA() 4 | { 5 | const VectorXd& d_LP = mesh->get_d_LP(); 6 | const VectorXd& d_PR = mesh->get_d_PR(); 7 | const VectorXd& d_PT = mesh->get_d_PT(); 8 | const VectorXd& d_BP = mesh->get_d_BP(); 9 | 10 | double Ax = mesh->get_Ax(); 11 | double Ay = mesh->get_Ay(); 12 | 13 | DA_w = gamma() * Ax * d_LP.cwiseInverse(); 14 | DA_e = gamma() * Ax * d_PR.cwiseInverse(); 15 | DA_n = gamma() * Ay * d_PT.cwiseInverse(); 16 | DA_s = gamma() * Ay * d_BP.cwiseInverse(); 17 | } 18 | 19 | void TransportEqn::init_F() 20 | { 21 | double Ax = mesh->get_Ax(); 22 | double Ay = mesh->get_Ay(); 23 | 24 | const VectorXd& u_e = field->u_e; 25 | const VectorXd& u_w = field->u_w; 26 | const VectorXd& v_n = field->v_n; 27 | const VectorXd& v_s = field->v_s; 28 | 29 | F_w = density() * u_w * Ax; 30 | F_e = density() * u_e * Ax; 31 | F_s = density() * v_s * Ay; 32 | F_n = density() * v_n * Ay; 33 | } 34 | -------------------------------------------------------------------------------- /EnergyEqn.h: -------------------------------------------------------------------------------- 1 | #ifndef __ENERGYEQN_H__ 2 | #define __ENERGYEQN_H__ 3 | 4 | #include "TransportEqn.h" 5 | #include "Inputs.h" 6 | 7 | class EnergyEqn : public TransportEqn 8 | { 9 | private: 10 | double k; 11 | double cp; 12 | double S_bar; 13 | 14 | MatrixCoeff* mat; 15 | 16 | double gamma() override { return k; } 17 | double density() override { return rho * cp; } 18 | void init_S(); 19 | public: 20 | EnergyEqn(Mesh* mesh, Field* field, Inputs* inputs, MatrixCoeff* matrix_coeff, Boundary* boundary, Source* source) 21 | : TransportEqn(mesh, field, inputs, boundary, source) 22 | { 23 | k = inputs->physcial_properties.k; 24 | cp = inputs->physcial_properties.cp; 25 | S_bar = inputs->source.S_bar; 26 | 27 | mat = matrix_coeff; 28 | 29 | init_S(); 30 | } 31 | 32 | TransportEqn& addConvectionTerm() override; 33 | TransportEqn& addDiffusionTerm() override; 34 | TransportEqn& addSourceTerm() override; 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Inputs.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::VectorXd; 10 | using namespace std; 11 | 12 | int main() 13 | { 14 | // 读取数据 15 | try { 16 | InputReader inputReader("config.json"); 17 | } catch (const std::exception& e) { 18 | cerr << "程序终止: " << e.what() << endl; 19 | return EXIT_FAILURE; 20 | } 21 | 22 | // 创建网格 23 | unique_ptr mesh = make_unique(Inputs::L, Inputs::N); 24 | 25 | // 初始化矩阵 26 | unique_ptr MCoeff = make_unique(mesh.get()); 27 | 28 | // 获取矩阵 29 | MatrixXd& A_m = MCoeff->get_A_m(); 30 | VectorXd& b_m = MCoeff->get_b_m(); 31 | VectorXd& x = MCoeff->get_x(); 32 | 33 | // 求解矩阵 34 | x = A_m.fullPivLu().solve(b_m); 35 | 36 | // 输出结果 37 | cout << "Solution: " << endl << x << endl; 38 | } 39 | -------------------------------------------------------------------------------- /Field.h: -------------------------------------------------------------------------------- 1 | #ifndef __FIELD_H__ 2 | #define __FIELD_H__ 3 | 4 | #include "Mesh.h" 5 | 6 | struct Field 7 | { 8 | // cell value of the velocity 9 | VectorXd u; // X direction 10 | VectorXd v; // Y direction 11 | 12 | // face value of the velocity 13 | // Todo: 14 | // 这里可以做性能优化,例如 i 网格的 u_e 等于 i+1 网格的 u_w 15 | // 只用保留其中一个即可 16 | VectorXd u_e; // east face u velocity 17 | VectorXd u_w; // west face u velocity 18 | VectorXd v_n; // north face v velocity 19 | VectorXd v_s; // south face v velocity 20 | 21 | VectorXd T; // Temperature 22 | 23 | VectorXd p; // Pressure 24 | 25 | int cellNum; // number of cells 26 | 27 | Field(int N) 28 | { 29 | u = VectorXd::Zero(N); 30 | v = VectorXd::Zero(N); 31 | u_e = VectorXd::Zero(N); 32 | u_w = VectorXd::Zero(N); 33 | v_n = VectorXd::Zero(N); 34 | v_s = VectorXd::Zero(N); 35 | 36 | T = VectorXd::Zero(N); 37 | 38 | p = VectorXd::Zero(N); 39 | 40 | cellNum = N; 41 | } 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /PWIM.cpp: -------------------------------------------------------------------------------- 1 | #include "PWIM.h" 2 | 3 | void PWIM::updateFaceVel() 4 | { 5 | for(int i = 0; i < field->cellNum; i++) 6 | { 7 | double uO = field->u[i]; 8 | 9 | double dxdy = mesh->get_Az(); 10 | double dx = mesh->get_dx(); 11 | 12 | VectorXd& aO = xMatrixCoeff->get_aO(); 13 | double AOO = aO[i]; 14 | 15 | double pO = field->p[i]; 16 | 17 | if(mesh->is_at_left_boundary(i)) 18 | { 19 | double AOE = aO[mesh->right_of(i)]; 20 | double pE = field->p[mesh->right_of(i)]; 21 | double pEE = field->p[mesh->right_of(mesh->right_of(i))]; 22 | double uE = field->u[mesh->right_of(i)]; 23 | 24 | double gradX_pO = ((pE + pO) * 0.5 - pO) / dx; 25 | double gradX_pE = (pEE - pO) / (2 * dx); 26 | double gradX_pe = (pE - pO) / dx; 27 | 28 | field->u_e[i] = 0.5 * (uO + uE) + 0.5 * dxdy * 29 | (gradX_pO / AOO + gradX_pE / AOE - (1 / AOE + 1 / AOO) * gradX_pe); 30 | } 31 | else if(mesh->is_at_right_boundary(i)) 32 | { 33 | field->u_e[i] = inputs->boundary.U_right; 34 | } 35 | else if(mesh->is_at_left_boundary(mesh->right_of(i))) 36 | { 37 | 38 | } 39 | else 40 | { 41 | 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | # set the project name 4 | project(CFD_Eigen) 5 | 6 | set(CMAKE_CXX_STANDARD 17) 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 8 | 9 | # 关闭Eigen中的这条警告 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-copy") 11 | # 关闭unused变量警告 12 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-variable") 13 | 14 | # lib eigen337 15 | list(APPEND CMAKE_PREFIX_PATH "lib_eigen337") # 安装路径前缀 16 | find_package(Eigen3 REQUIRED) 17 | 18 | if (EIGEN3_FOUND) 19 | message(STATUS "Found Eigen3") 20 | message(STATUS "Eigen3 include dir: ${EIGEN3_INCLUDE_DIR}") 21 | endif() 22 | 23 | # lib nlohmann_json 24 | list(APPEND CMAKE_PREFIX_PATH "lib_json") # 安装路径前缀 25 | find_package(nlohmann_json 3.12.0 REQUIRED) 26 | 27 | # 查找当前目录下的所有源文件 28 | # 并将名称保存到 DIR_SRCS 变量 29 | aux_source_directory(. DIR_SRCS) 30 | 31 | add_subdirectory("version.1.1DDiffusion_POP") 32 | 33 | add_subdirectory("version.2.1DDiffusion_OOP") 34 | 35 | add_subdirectory("version.3.1DDiffusion-Convection") 36 | 37 | add_subdirectory("version.4.1DDiffusion-Convection-Upwind") 38 | 39 | add_subdirectory("version.5.1DDiffusion-Neumann-Boundary") 40 | 41 | # add the executable 42 | add_executable(CFD_Eigen ${DIR_SRCS}) 43 | target_include_directories(CFD_Eigen PRIVATE ${EIGEN3_INCLUDE_DIR}) 44 | target_link_libraries(CFD_Eigen PRIVATE nlohmann_json::nlohmann_json) 45 | target_compile_options(CFD_Eigen PRIVATE -Wall -Wextra -Werror) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | # 简介 8 | 9 | 基于[Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page) 3.3.7开发的简易CFD Sovler,可用于熟悉CFD基本理论和实现过程。 10 | 11 | 标量输运部分编写参考[Fluid 101](https://www.fluidmechanics101.com/) 12 | [course 1](https://www.udemy.com/course/computational-fluid-dynamics-fundamentals-course/) 13 | [course 2](https://www.udemy.com/course/computational-fluid-dynamics-fundamentals-course-2/) 14 | 15 | SIMPLE算法部分编写参考[Sandip CFD Lectures](https://www.youtube.com/channel/UCtNV6Ew24I_T2XIJJdYT2kQ) 16 | 17 | 笔记整理见: 18 | 19 | [Co-Located SIMPLE · 语雀](https://www.yuque.com/yinweijie/gr78mf/edyam2148k7cvng8?singleDoc#) 20 | 21 | [TheoryNotes · 语雀](https://www.yuque.com/yinweijie/gr78mf/hqe7xfpr5lyiurpd?singleDoc#) 22 | 23 | --- 24 | 25 | # 编译 26 | 27 | 下载Eigen库 28 | 29 | ```bash 30 | cd CFD-Eigen-Solver 31 | wget https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz 32 | ``` 33 | 34 | 下载nlohmann/json库 35 | 36 | ```bash 37 | git clone --branch v3.12.0 https://github.com/nlohmann/json.git 38 | ``` 39 | 40 | 编译Eigen: 41 | 42 | ```bash 43 | tar xvf eigen-3.3.7.tar.gz 44 | cd eigen-3.3.7/ 45 | mkdir build 46 | cd build 47 | cmake -DCMAKE_BUILD_TYPE=release \ 48 | -DCMAKE_INSTALL_PREFIX=../../lib_eigen337 \ 49 | .. 50 | make -j 51 | make check 52 | make install 53 | ``` 54 | 55 | 编译nlohmann/json库 56 | 57 | ```bash 58 | cd json/ 59 | mkdir build 60 | cd build 61 | cmake -DCMAKE_BUILD_TYPE=release \ 62 | -DCMAKE_INSTALL_PREFIX=../../lib_json \ 63 | .. 64 | make -j6 65 | make install 66 | ``` 67 | 68 | 编译CFD_Eigen: 69 | 70 | ```bash 71 | cmake -S . -B build 72 | cmake --build build 73 | ``` 74 | -------------------------------------------------------------------------------- /Inputs.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUTS_H__ 2 | #define __INPUTS_H__ 3 | 4 | #include 5 | #include 6 | 7 | struct Geometry 8 | { 9 | // 计算域X,Y,Z方向长度 (m) 10 | double XLen; 11 | double YLen; 12 | double ZLen; 13 | int Nx; 14 | int Ny; 15 | int Nz; 16 | }; 17 | 18 | struct PhysicalPropterties 19 | { 20 | // Thermal Conductivity of the bar (W/mK) 21 | double k; 22 | // 密度 kg/m^3 23 | double rho; 24 | // 比热容 J/kg/k 25 | double cp; 26 | // 动力粘度 kg/(m.s) 27 | double mu; 28 | }; 29 | 30 | struct Boundary 31 | { 32 | // Temperature at the left boundary (deg C) 33 | double T_left; 34 | // Temperature at the right boundary (deg C) 35 | double T_right; 36 | // Temperature at the bottom boundary (deg C) 37 | double T_bottom; 38 | // Temperature at the top boundary (deg C) 39 | double T_top; 40 | // 左边界热流密度 (W/m^2) 41 | double q_w; 42 | 43 | double U_left; 44 | double U_right; 45 | double U_top; 46 | double U_bottom; 47 | 48 | double V_left; 49 | double V_right; 50 | double V_top; 51 | double V_bottom; 52 | 53 | double p_left; 54 | double p_right; 55 | double p_top; 56 | double p_bottom; 57 | }; 58 | 59 | struct Source 60 | { 61 | // Heat source per unit volume (W/m3) 62 | double S_bar; 63 | }; 64 | 65 | class Inputs 66 | { 67 | public: 68 | 69 | Geometry geometry; 70 | 71 | // 物性 72 | PhysicalPropterties physcial_properties; 73 | 74 | // 边界 75 | Boundary boundary; 76 | 77 | // 源项 78 | Source source; 79 | 80 | public: 81 | Inputs(const std::string& fileName); 82 | 83 | void loadInputs(); 84 | 85 | private: 86 | nlohmann::json config; 87 | }; 88 | 89 | #endif -------------------------------------------------------------------------------- /script/plot.u@.y.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import pandas as pd 4 | import matplotlib 5 | matplotlib.use('Agg') # 设置非交互式后端 6 | import matplotlib.pyplot as plt 7 | import numpy as np 8 | 9 | # 读取CSV文件 10 | csv_file = '../u.csv' 11 | df = pd.read_csv(csv_file) 12 | df_ref = pd.read_csv('../ref.data/u.@.y.Re1000.csv') 13 | 14 | # 去除列名中的空格 15 | df.columns = df.columns.str.strip() 16 | df_ref.columns = df_ref.columns.str.strip() 17 | 18 | # 筛选x=0.5的数据点 19 | x_target = 0.5 20 | tolerance = 1e-10 # 浮点数比较容差 21 | data_at_x05 = df[abs(df['x'] - x_target) < tolerance].copy() 22 | 23 | # 按y坐标排序 24 | data_at_x05 = data_at_x05.sort_values('y') 25 | df_ref = df_ref.sort_values('y') 26 | 27 | # 创建图形 28 | plt.figure(figsize=(10, 8)) 29 | plt.plot(data_at_x05['y'], data_at_x05['u'], 'b-o', linewidth=2, markersize=4, label='u velocity') 30 | plt.plot(df_ref['y'], df_ref['u'], 'ro', markersize=4, label='Reference u velocity') 31 | 32 | # 设置图形属性 33 | plt.ylabel('u velocity', fontsize=12) 34 | plt.xlabel('y axis', fontsize=12) 35 | plt.title(f'x = {x_target}, velocity distribution', fontsize=14) 36 | plt.grid(True, alpha=0.3) 37 | plt.legend() 38 | 39 | # 设置坐标轴范围 40 | plt.ylim(min(data_at_x05['u']) * 0.9 - 0.5, max(data_at_x05['u']) * 1.1) 41 | plt.xlim(0, 1) 42 | 43 | # 显示图形 44 | plt.tight_layout() 45 | 46 | # 保存图片到文件 47 | output_file = 'u_velocity_at_x05.png' 48 | plt.savefig(output_file, dpi=300, bbox_inches='tight') 49 | print(f"图片已保存到: {output_file}") 50 | 51 | # 如果有显示环境,也尝试显示 52 | try: 53 | plt.show() 54 | except: 55 | print("无法显示图形,但图片已保存") 56 | 57 | # 打印一些统计信息 58 | print(f"在x = {x_target} 处找到 {len(data_at_x05)} 个数据点") 59 | print(f"速度范围: {min(data_at_x05['u']):.6f} 到 {max(data_at_x05['u']):.6f}") 60 | print(f"y坐标范围: {min(data_at_x05['y']):.2f} 到 {max(data_at_x05['y']):.2f}") 61 | -------------------------------------------------------------------------------- /MatrixWrapper.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_WRAPPER_H__ 2 | #define __MATRIX_WRAPPER_H__ 3 | 4 | #include 5 | #include 6 | #include "MatrixInterface.h" 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::SparseMatrix; 10 | 11 | class DenseMatrixWrapper : public MatrixInterface 12 | { 13 | private: 14 | MatrixXd m_dense_matrix; 15 | public: 16 | DenseMatrixWrapper() = default; 17 | DenseMatrixWrapper(int row, int col) 18 | { 19 | m_dense_matrix = MatrixXd::Zero(row, col); 20 | } 21 | 22 | void setNum(int row, int col, double value) 23 | { 24 | m_dense_matrix(row, col) = value; 25 | } 26 | 27 | MatrixXd& getMatrix() 28 | { 29 | return m_dense_matrix; 30 | } 31 | 32 | DenseMatrixWrapper& operator=(DenseMatrixWrapper&& rhs) 33 | { 34 | if(this != &rhs) 35 | m_dense_matrix = std::move(rhs.m_dense_matrix); 36 | 37 | return *this; 38 | } 39 | }; 40 | 41 | class SparseMatrixWrapper : public MatrixInterface 42 | { 43 | private: 44 | SparseMatrix m_sparse_matrix; 45 | public: 46 | SparseMatrixWrapper() = default; 47 | SparseMatrixWrapper(int row, int col) : m_sparse_matrix(row, col) { } 48 | 49 | void setNum(int row, int col, double value) 50 | { 51 | // ref. http://eigen.tuxfamily.org/dox/group__TutorialSparse.html - Filling a sparse matrix 52 | m_sparse_matrix.insert(row, col) = value; // alternative: A.coeffRef(i,j) += v_ij; 53 | } 54 | 55 | SparseMatrix& getMatrix() 56 | { 57 | return m_sparse_matrix; 58 | } 59 | 60 | SparseMatrixWrapper& operator=(SparseMatrixWrapper&& rhs) 61 | { 62 | if(this != &rhs) 63 | m_sparse_matrix = std::move(rhs.m_sparse_matrix); 64 | 65 | return *this; 66 | } 67 | }; 68 | 69 | #endif -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/Inputs.h: -------------------------------------------------------------------------------- 1 | #ifndef __INPUTS_H__ 2 | #define __INPUTS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using json = nlohmann::json; 10 | 11 | class InputReader 12 | { 13 | private: 14 | json config; 15 | 16 | public: 17 | InputReader(const std::string& fileName) 18 | { 19 | try { 20 | std::ifstream file(fileName); 21 | if (!file.is_open()) { 22 | throw std::runtime_error("无法打开配置文件: " + fileName); 23 | } 24 | 25 | file >> config; 26 | file.close(); 27 | 28 | // 读取配置并赋值给Inputs命名空间 29 | loadInputs(); 30 | 31 | } catch (const std::exception& e) { 32 | std::cerr << "读取配置文件错误: " << e.what() << std::endl; 33 | throw; 34 | } 35 | } 36 | 37 | private: 38 | void loadInputs(); 39 | }; 40 | 41 | namespace Inputs 42 | { 43 | // Thermal Conductivity of the bar (W/mK) 44 | extern double k; 45 | 46 | // Cross-sectional Area of the bar (m2) 47 | extern double A; 48 | 49 | // Length of the bar (m) 50 | extern double L; 51 | 52 | // Number of cells in the mesh 53 | extern int N; 54 | 55 | // Temperature at the left hand side of the bar (deg C) 56 | extern double T_A; 57 | 58 | // Temperature at the right hand side of the bar (deg C) 59 | extern double T_B; 60 | 61 | // Heat source per unit volume (W/m3) 62 | extern double S_bar; 63 | 64 | // 密度 kg/m^3 65 | extern double rho; 66 | 67 | // 比热容 J/kg/k 68 | extern double cp; 69 | 70 | // 流体速度 71 | extern double U; 72 | 73 | // 左边界热流密度 (W/m^2) 74 | extern double q_w; 75 | } 76 | 77 | #endif -------------------------------------------------------------------------------- /TransportEqn.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRANSPORTEQN_H__ 2 | #define __TRANSPORTEQN_H__ 3 | 4 | #include "Mesh.h" 5 | #include "Field.h" 6 | #include "Inputs.h" 7 | #include "MatrixCoeff.h" 8 | 9 | class TransportEqn 10 | { 11 | protected: 12 | Mesh* mesh; 13 | int N; 14 | 15 | Field* field; 16 | 17 | Inputs* inputs; 18 | 19 | const Boundary* boundary; 20 | const Source* source; 21 | 22 | // Energy Eqn: DA = k * A / d 23 | // Momentum Eqn: DA = mu * A / d 24 | VectorXd DA_w, DA_e, DA_s, DA_n; 25 | 26 | // Energy Eqn: F = rho * cp * U * A 27 | // Momentum Eqn: F = rho * U * A 28 | VectorXd F_w, F_e, F_s, F_n; 29 | 30 | // Energy Eqn: S = S_bar * V 31 | // X Momentum Eqn: S = dp / dx 32 | // Y Momentum Eqn: S = dp / dy 33 | VectorXd S; 34 | 35 | double rho; 36 | 37 | // 注意:init_DA()和init_F()都调用了虚函数,因此不能放在构造函数里 38 | void init_DA(); 39 | void init_F(); 40 | public: 41 | TransportEqn(Mesh* mesh, Field* field, Inputs* inputs, Boundary* boundary, Source* source) 42 | : mesh(mesh), N(mesh->get_N()), field(field), inputs(inputs), boundary(boundary), source(source) 43 | { 44 | DA_w = VectorXd(N); 45 | DA_e = VectorXd(N); 46 | DA_s = VectorXd(N); 47 | DA_n = VectorXd(N); 48 | 49 | F_w = VectorXd(N); 50 | F_e = VectorXd(N); 51 | F_s = VectorXd(N); 52 | F_n = VectorXd(N); 53 | 54 | S = VectorXd(N); 55 | 56 | rho = inputs->physcial_properties.rho; 57 | } 58 | 59 | void init() 60 | { 61 | init_DA(); 62 | init_F(); 63 | } 64 | 65 | // Energy Eqn: gamma = k 66 | // Momentum Eqn: gamma = mu 67 | virtual double gamma() = 0; 68 | 69 | // Energy Eqn: density = rho * cp 70 | // Momentum Eqn: density = rho 71 | virtual double density() = 0; 72 | 73 | virtual TransportEqn& addConvectionTerm() = 0; 74 | virtual TransportEqn& addDiffusionTerm() = 0; 75 | virtual TransportEqn& addSourceTerm() = 0; 76 | }; 77 | 78 | #endif -------------------------------------------------------------------------------- /script/plot.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import pandas as pd 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | from scipy.interpolate import griddata 7 | import matplotlib 8 | import matplotlib.font_manager as fm 9 | 10 | # 使用非交互式后端 11 | matplotlib.use('Agg') 12 | 13 | # 解决中文字体问题 14 | plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS', 'Liberation Sans'] 15 | plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 16 | 17 | # 如果上面的方法不行,使用英文标题 18 | USE_ENGLISH = True # 设置为True使用英文,False使用中文 19 | 20 | # 读取CSV文件,跳过空格 21 | df = pd.read_csv('../u.csv', skipinitialspace=True) 22 | 23 | # 提取坐标和速度数据,忽略z列 24 | x = np.array(df['x']) 25 | y = np.array(df['y']) 26 | u = np.array(df['u']) 27 | 28 | # 创建网格用于插值 29 | x_unique = np.unique(x) 30 | y_unique = np.unique(y) 31 | X, Y = np.meshgrid(x_unique, y_unique) 32 | 33 | # 将散点数据插值到规则网格 34 | U = griddata((x, y), u, (X, Y), method='linear') 35 | 36 | # 创建等高线图 37 | plt.figure(figsize=(12, 10)) 38 | 39 | # 等高线图 40 | cs = plt.contourf(X, Y, U, levels=40, cmap='viridis') 41 | plt.title('U-Velocity Contour Plot', pad=20) 42 | plt.xlabel('x (m)') 43 | plt.ylabel('y (m)') 44 | plt.axis('equal') 45 | cbar = plt.colorbar(cs, label='u (m/s)', shrink=0.8) 46 | cbar.ax.tick_params(labelsize=10) 47 | 48 | 49 | # 添加边界条件标注 50 | plt.text(0.5, 1.08, 'U_top = 0.01 m/s', transform=plt.gca().transAxes, 51 | ha='center', fontsize=10, bbox=dict(boxstyle="round,pad=0.3", facecolor="yellow", alpha=0.7)) 52 | # plt.text(-0.12, 0.5, 'U_left = 0', transform=plt.gca().transAxes, 53 | # ha='center', rotation=90, fontsize=10, bbox=dict(boxstyle="round,pad=0.3", facecolor="lightblue", alpha=0.7)) 54 | 55 | plt.tight_layout() 56 | plt.savefig('u_velocity_contour.png', dpi=300, bbox_inches='tight') 57 | 58 | # 打印数据统计信息 59 | print("=== Data Statistics ===") 60 | print(f"Total data points: {len(x)}") 61 | print(f"X coordinate range: [{x.min():.3f}, {x.max():.3f}]") 62 | print(f"Y coordinate range: [{y.min():.3f}, {y.max():.3f}]") 63 | print(f"U velocity range: [{u.min():.6f}, {u.max():.6f}]") 64 | print(f"Unique X coordinates: {len(x_unique)}") 65 | print(f"Unique Y coordinates: {len(y_unique)}") 66 | print(f"Max velocity location: x={x[np.argmax(u)]:.3f}, y={y[np.argmax(u)]:.3f}") 67 | 68 | plt.show() -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/Inputs.cpp: -------------------------------------------------------------------------------- 1 | #include "Inputs.h" 2 | 3 | 4 | // 实现文件中的定义(需要在.cpp文件中或者在头文件中inline定义) 5 | namespace Inputs 6 | { 7 | double k = 100.0; 8 | double A = 0.1; 9 | double L = 5.0; 10 | int N = 5; 11 | double T_A = 100.0; 12 | double T_B = 200.0; 13 | double S_bar = 1000.0; 14 | double rho = 1.0; 15 | double cp = 1000.0; 16 | double U = 0.0; 17 | double q_w = -100.0; 18 | } 19 | 20 | void InputReader::loadInputs() 21 | { 22 | // 读取JSON配置并赋值,提供默认值防止键不存在 23 | Inputs::k = config.value("thermal_conductivity", 100.0); 24 | Inputs::A = config.value("cross_sectional_area", 0.1); 25 | Inputs::L = config.value("length", 5.0); 26 | Inputs::N = config.value("number_of_cells", 5); 27 | Inputs::T_A = config.value("temperature_left", 100.0); 28 | Inputs::T_B = config.value("temperature_right", 200.0); 29 | Inputs::S_bar = config.value("heat_source", 1000.0); 30 | Inputs::rho = config.value("density", 1.0); 31 | Inputs::cp = config.value("specific_heat", 1000.0); 32 | Inputs::U = config.value("fluid_velocity", 0.0); 33 | Inputs::q_w = config.value("heat_flux_boundary", 100.0); 34 | 35 | // 输出读取的配置信息 36 | std::cout << "--------------------------------" << std::endl; 37 | std::cout << "配置读取:" << std::endl; 38 | std::cout << "--------------------------------" << std::endl; 39 | std::cout << "热导率: " << Inputs::k << " W/mK" << std::endl; 40 | std::cout << "截面积: " << Inputs::A << " m²" << std::endl; 41 | std::cout << "长度: " << Inputs::L << " m" << std::endl; 42 | std::cout << "网格数: " << Inputs::N << std::endl; 43 | std::cout << "左端温度: " << Inputs::T_A << " °C" << std::endl; 44 | std::cout << "右端温度: " << Inputs::T_B << " °C" << std::endl; 45 | std::cout << "单位体积热源: " << Inputs::S_bar << " W/m³" << std::endl; 46 | std::cout << "密度: " << Inputs::rho << " kg/m³" << std::endl; 47 | std::cout << "比热容: " << Inputs::cp << " J/kg/K" << std::endl; 48 | std::cout << "流体速度: " << Inputs::U << " m/s" << std::endl; 49 | std::cout << "左边界热流密度: " << Inputs::q_w << " W/m²" << std::endl; 50 | std::cout << "--------------------------------" << std::endl; 51 | std::cout << "配置文件加载成功。" << std::endl; 52 | std::cout << "--------------------------------" << std::endl; 53 | std::cout << std::endl; 54 | } -------------------------------------------------------------------------------- /version.2.1DDiffusion_OOP/MatrixCoeff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_COEFF__ 2 | #define __MATRIX_COEFF__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | #include "Mesh.h" 7 | 8 | using namespace std; 9 | 10 | // N: 网格数 11 | class MatrixCoeff 12 | { 13 | private: 14 | VectorXd aL, aR, aP, Sp, Su; 15 | 16 | MatrixXd A_m; 17 | VectorXd b_m; 18 | VectorXd x; 19 | 20 | private: 21 | // Matrix系数初始化 22 | void initMatrix(const Mesh* mesh); 23 | 24 | public: 25 | MatrixCoeff(const Mesh* mesh) 26 | { 27 | int N = mesh->get_N(); 28 | 29 | aL = VectorXd(N); 30 | aR = VectorXd(N); 31 | aP = VectorXd(N); 32 | Sp = VectorXd(N); 33 | Su = VectorXd(N); 34 | 35 | A_m = MatrixXd(N, N); 36 | b_m = VectorXd(N); 37 | x = VectorXd (N); 38 | 39 | initMatrix(mesh); 40 | } 41 | 42 | MatrixXd& get_A_m() { return A_m; } 43 | VectorXd& get_b_m() { return b_m; } 44 | VectorXd& get_x() { return x; } 45 | }; 46 | 47 | // a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u} 48 | inline void MatrixCoeff::initMatrix(const Mesh* mesh) 49 | { 50 | using namespace Inputs; 51 | 52 | const VectorXd& DA_L = mesh->get_DA_L(); 53 | const VectorXd& DA_R = mesh->get_DA_R(); 54 | const VectorXd& V = mesh->get_V(); 55 | 56 | aL = DA_L; 57 | aL[0] = 0; // 左边界系数 58 | 59 | aR = DA_R; 60 | aR[N-1] = 0; // 右边界系数 61 | 62 | Sp = VectorXd::Zero(N); 63 | Sp[0] = -2 * DA_L[0]; // 左边界引入系数矩阵的不规则项 64 | Sp[N-1] = -2 * DA_R[N-1]; // 右边界引入系数矩阵的不规则项 65 | 66 | aP = aL + aR - Sp; 67 | 68 | Su = S_bar * V; 69 | Su[0] = T_A*(2*DA_L[0]) + S_bar * V[0]; 70 | Su[N-1] = T_B*(2*DA_R[N-1]) + S_bar * V[N-1]; 71 | 72 | for(int i = 0; i < N; i++) 73 | { 74 | if(i == 0) 75 | { 76 | A_m(i, i) = aP[i]; 77 | A_m(i, i+1) = -aR[i]; 78 | } 79 | else if(i == N-1) 80 | { 81 | A_m(i, i) = aP[i]; 82 | A_m(i, i-1) = -aL[i]; 83 | } 84 | else 85 | { 86 | A_m(i, i) = aP[i]; 87 | A_m(i, i-1) = -aL[i]; 88 | A_m(i, i+1) = -aR[i]; 89 | } 90 | } 91 | 92 | b_m = Su; 93 | 94 | cout << "A_m: " << endl << A_m << endl; 95 | cout << endl; 96 | 97 | cout << "b_m: " << endl << b_m << endl; 98 | cout << endl; 99 | } 100 | 101 | #endif -------------------------------------------------------------------------------- /Mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "Mesh.h" 2 | 3 | void Mesh::initMesh(const Inputs* inputs) 4 | { 5 | dx = inputs->geometry.XLen / Nx; 6 | dy = inputs->geometry.YLen / Ny; 7 | dz = inputs->geometry.ZLen / Nz; 8 | 9 | // 网格横截面积 10 | Ax = dy * dz; 11 | Ay = dx * dz; 12 | Az = dx * dy; 13 | 14 | // 面坐标,x,y,z方向 15 | for(int i = 0; i <= Nx; i++) 16 | { 17 | xFace[i] = dx * i; 18 | } 19 | for(int i = 0; i <= Ny; i++) 20 | { 21 | yFace[i] = dy * i; 22 | } 23 | for(int i = 0; i <= Nz; i++) 24 | { 25 | zFace[i] = dz * i; 26 | } 27 | // cout << xFace << endl; 28 | 29 | // 网格中心坐标 30 | for(int i = 0; i < N; i++) 31 | { 32 | int ix = i % Nx; 33 | int iy = i / Nx; // floor division 34 | int iz = i / (Nx * Ny); // floor division 35 | 36 | xCentroid[i] = 0.5 * (xFace[ix] + xFace[ix+1]); 37 | yCentroid[i] = 0.5 * (yFace[iy] + yFace[iy+1]); 38 | zCentroid[i] = 0.5 * (zFace[iz] + zFace[iz+1]); 39 | } 40 | 41 | // 网格中心相关量 42 | for(int i = 0; i < N; i++) 43 | { 44 | if(is_at_left_boundary(i)) // 左边界的d_LP需要特殊处理 45 | { 46 | d_LP[i] = 2 * (xCentroid[i] - xFace.head(1)[0]); 47 | flag_d_LP[i] = 1; 48 | } 49 | if(is_at_right_boundary(i)) // 右边界的d_PR需要特殊处理 50 | { 51 | d_PR[i] = 2 * (xFace.tail(1)[0] - xCentroid[i]); 52 | flag_d_PR[i] = 1; 53 | } 54 | if(is_at_bottom_boundary(i)) // 下边界的d_BP需要特殊处理 55 | { 56 | d_BP[i] = 2 * (yCentroid[i] - yFace.head(1)[0]); 57 | flag_d_BP[i] = 1; 58 | } 59 | if(is_at_top_boundary(i)) // 上边界的d_PT需要特殊处理 60 | { 61 | d_PT[i] = 2 * (yFace.tail(1)[0] - yCentroid[i]); 62 | flag_d_PT[i] = 1; 63 | } 64 | 65 | int i_l = left_of(i); 66 | int i_r = right_of(i); 67 | int i_t = top_of(i); 68 | int i_b = bottom_of(i); 69 | 70 | // 未特殊处理的网格在这里统一赋值 71 | if(!flag_d_LP[i]) (d_LP[i] = xCentroid[i] - xCentroid[i_l], flag_d_LP[i]); 72 | if(!flag_d_PR[i]) (d_PR[i] = xCentroid[i_r] - xCentroid[i], flag_d_PR[i]); 73 | if(!flag_d_PT[i]) (d_PT[i] = yCentroid[i_t] - yCentroid[i], flag_d_PT[i]); 74 | if(!flag_d_BP[i]) (d_BP[i] = yCentroid[i] - yCentroid[i_b], flag_d_BP[i]); 75 | 76 | // 网格体积 = faceArea * dx 77 | int ix = i % Nx; 78 | V[i] = Ax * (xFace[ix+1] - xFace[ix]); 79 | } 80 | } -------------------------------------------------------------------------------- /version.2.1DDiffusion_OOP/Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESH_H__ 2 | #define __MESH_H__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | 7 | using Eigen::MatrixXd; 8 | using Eigen::VectorXd; 9 | 10 | // N: 网格数 11 | // L: 计算域长度 12 | class Mesh 13 | { 14 | private: 15 | // 网格数量 16 | int N; 17 | // 网格x方向面坐标 18 | VectorXd xFace; 19 | // 网格x方向中心坐标 20 | VectorXd xCentroid; 21 | // d_LP, d_PR:网格中心与左右相邻网格中心举例 22 | VectorXd d_LP, d_PR; 23 | // k*A/d 24 | VectorXd DA_L, DA_R; 25 | // 网格体积 26 | VectorXd V; 27 | 28 | private: 29 | // 初始化网格 30 | void initMesh(double L, int N); 31 | public: 32 | Mesh(double L, int N_) 33 | { 34 | N = N_; 35 | xFace = VectorXd(N + 1); 36 | xCentroid = VectorXd(N); 37 | d_LP = VectorXd(N); 38 | d_PR = VectorXd(N); 39 | DA_L = VectorXd(N); 40 | DA_R = VectorXd(N); 41 | V = VectorXd(N); 42 | 43 | initMesh(L, N); 44 | } 45 | 46 | const VectorXd& get_DA_L() const { return DA_L; } 47 | const VectorXd& get_DA_R() const { return DA_R; } 48 | const VectorXd& get_V() const { return V; } 49 | int get_N() const { return N; } 50 | }; 51 | 52 | inline void Mesh::initMesh(double L, int N) 53 | { 54 | using namespace Inputs; 55 | 56 | // x方向网格长度 57 | double dx = L / N; 58 | 59 | // 网格面x坐标 60 | for(int i = 0; i <= N; i++) 61 | { 62 | xFace[i] = dx * i; 63 | } 64 | // cout << xFace << endl; 65 | 66 | // 网格中心坐标 67 | for(int i = 0; i < N; i++) 68 | { 69 | xCentroid[i] = 0.5 * (xFace[i] + xFace[i+1]); 70 | } 71 | // cout << xCentroid << endl; 72 | 73 | // 网格中心相关量 74 | for(int i = 0; i < N; i++) 75 | { 76 | if(i == 0) // 左边界的d_LP需要特殊处理 77 | { 78 | d_LP[i] = 2 * (xCentroid[i] - xFace[i]); 79 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 80 | } 81 | else if(i == N - 1) // 右边界的d_PR需要特殊处理 82 | { 83 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 84 | d_PR[i] = 2 * (xFace[i+1] - xCentroid[i]); 85 | } 86 | else // 内点的d_LP, d_PR 87 | { 88 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 89 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 90 | } 91 | 92 | DA_L[i] = k * A / d_LP[i]; 93 | DA_R[i] = k * A / d_PR[i]; 94 | 95 | // 网格体积 = faceArea * dx 96 | V[i] = A * (xFace[i+1] - xFace[i]); 97 | } 98 | } 99 | 100 | #endif -------------------------------------------------------------------------------- /version.3.1DDiffusion-Convection/MatrixCoeff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_COEFF__ 2 | #define __MATRIX_COEFF__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | #include "Mesh.h" 7 | 8 | using namespace std; 9 | 10 | // N: 网格数 11 | class MatrixCoeff 12 | { 13 | private: 14 | VectorXd aL, aR, aP, Sp, Su; 15 | 16 | MatrixXd A_m; 17 | VectorXd b_m; 18 | VectorXd x; 19 | 20 | private: 21 | // Matrix系数初始化 22 | void initMatrix(const Mesh* mesh); 23 | 24 | public: 25 | MatrixCoeff(const Mesh* mesh) 26 | { 27 | int N = mesh->get_N(); 28 | 29 | aL = VectorXd(N); 30 | aR = VectorXd(N); 31 | aP = VectorXd(N); 32 | Sp = VectorXd(N); 33 | Su = VectorXd(N); 34 | 35 | A_m = MatrixXd(N, N); 36 | b_m = VectorXd(N); 37 | x = VectorXd (N); 38 | 39 | initMatrix(mesh); 40 | } 41 | 42 | MatrixXd& get_A_m() { return A_m; } 43 | VectorXd& get_b_m() { return b_m; } 44 | VectorXd& get_x() { return x; } 45 | }; 46 | 47 | // a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u} 48 | inline void MatrixCoeff::initMatrix(const Mesh* mesh) 49 | { 50 | using namespace Inputs; 51 | 52 | const VectorXd& DA_L = mesh->get_DA_L(); 53 | const VectorXd& DA_R = mesh->get_DA_R(); 54 | const VectorXd& F_l = mesh->get_F_l(); 55 | const VectorXd& F_r = mesh->get_F_r(); 56 | const VectorXd& V = mesh->get_V(); 57 | 58 | aL = DA_L + F_l / 2; 59 | aL[0] = 0; // 左边界系数 60 | 61 | aR = DA_R - F_r / 2; 62 | aR[N-1] = 0; // 右边界系数 63 | 64 | Sp = VectorXd::Zero(N); 65 | Sp[0] = -(2 * DA_L[0] + F_l[0]); // 左边界引入系数矩阵的不规则项 66 | Sp[N-1] = -(2 * DA_R[N-1] - F_r[N-1]); // 右边界引入系数矩阵的不规则项 67 | 68 | aP = aL + aR + (F_r - F_l) - Sp; 69 | 70 | Su = S_bar * V; 71 | Su[0] = T_A*(2*DA_L[0] + F_l[0]) + S_bar * V[0]; 72 | Su[N-1] = T_B*(2*DA_R[N-1] - F_r[0]) + S_bar * V[N-1]; 73 | 74 | for(int i = 0; i < N; i++) 75 | { 76 | if(i == 0) 77 | { 78 | A_m(i, i) = aP[i]; 79 | A_m(i, i+1) = -aR[i]; 80 | } 81 | else if(i == N-1) 82 | { 83 | A_m(i, i) = aP[i]; 84 | A_m(i, i-1) = -aL[i]; 85 | } 86 | else 87 | { 88 | A_m(i, i) = aP[i]; 89 | A_m(i, i-1) = -aL[i]; 90 | A_m(i, i+1) = -aR[i]; 91 | } 92 | } 93 | 94 | b_m = Su; 95 | 96 | cout << "A_m: " << endl << A_m << endl; 97 | cout << endl; 98 | 99 | cout << "b_m: " << endl << b_m << endl; 100 | cout << endl; 101 | } 102 | 103 | #endif -------------------------------------------------------------------------------- /version.4.1DDiffusion-Convection-Upwind/MatrixCoeff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_COEFF__ 2 | #define __MATRIX_COEFF__ 3 | 4 | #include 5 | #include 6 | #include "Inputs.h" 7 | #include "Mesh.h" 8 | 9 | using namespace std; 10 | 11 | // N: 网格数 12 | class MatrixCoeff 13 | { 14 | private: 15 | VectorXd aL, aR, aP, Sp, Su; 16 | 17 | MatrixXd A_m; 18 | VectorXd b_m; 19 | VectorXd x; 20 | 21 | private: 22 | // Matrix系数初始化 23 | void initMatrix(const Mesh* mesh); 24 | 25 | public: 26 | MatrixCoeff(const Mesh* mesh) 27 | { 28 | int N = mesh->get_N(); 29 | 30 | aL = VectorXd(N); 31 | aR = VectorXd(N); 32 | aP = VectorXd(N); 33 | Sp = VectorXd(N); 34 | Su = VectorXd(N); 35 | 36 | A_m = MatrixXd(N, N); 37 | b_m = VectorXd(N); 38 | x = VectorXd (N); 39 | 40 | initMatrix(mesh); 41 | } 42 | 43 | MatrixXd& get_A_m() { return A_m; } 44 | VectorXd& get_b_m() { return b_m; } 45 | VectorXd& get_x() { return x; } 46 | }; 47 | 48 | // a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u} 49 | inline void MatrixCoeff::initMatrix(const Mesh* mesh) 50 | { 51 | using namespace Inputs; 52 | 53 | const VectorXd& DA_L = mesh->get_DA_L(); 54 | const VectorXd& DA_R = mesh->get_DA_R(); 55 | const VectorXd& F_l = mesh->get_F_l(); 56 | const VectorXd& F_r = mesh->get_F_r(); 57 | const VectorXd& V = mesh->get_V(); 58 | 59 | aL = DA_L + F_l.cwiseMax(VectorXd::Zero(N)); 60 | aL[0] = 0; // 左边界系数 61 | 62 | aR = DA_R + (-F_r).cwiseMax(VectorXd::Zero(N)); 63 | aR[N-1] = 0; // 右边界系数 64 | 65 | Sp = VectorXd::Zero(N); 66 | Sp[0] = -(2 * DA_L[0] + std::max(F_l[0], 0.0)); // 左边界引入系数矩阵的不规则项 67 | Sp[N-1] = -(2 * DA_R[N-1] + std::max(-F_r[N-1], 0.0)); // 右边界引入系数矩阵的不规则项 68 | 69 | aP = aL + aR + (F_r - F_l) - Sp; 70 | 71 | Su = S_bar * V; 72 | Su[0] = T_A*(2*DA_L[0] + std::max(F_l[0], 0.0)) + S_bar * V[0]; 73 | Su[N-1] = T_B*(2*DA_R[N-1] + std::max(-F_r[0], 0.0)) + S_bar * V[N-1]; 74 | 75 | for(int i = 0; i < N; i++) 76 | { 77 | if(i == 0) 78 | { 79 | A_m(i, i) = aP[i]; 80 | A_m(i, i+1) = -aR[i]; 81 | } 82 | else if(i == N-1) 83 | { 84 | A_m(i, i) = aP[i]; 85 | A_m(i, i-1) = -aL[i]; 86 | } 87 | else 88 | { 89 | A_m(i, i) = aP[i]; 90 | A_m(i, i-1) = -aL[i]; 91 | A_m(i, i+1) = -aR[i]; 92 | } 93 | } 94 | 95 | b_m = Su; 96 | 97 | cout << "A_m: " << endl << A_m << endl; 98 | cout << endl; 99 | 100 | cout << "b_m: " << endl << b_m << endl; 101 | cout << endl; 102 | } 103 | 104 | #endif -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/MatrixCoeff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_COEFF__ 2 | #define __MATRIX_COEFF__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | #include "Mesh.h" 7 | 8 | using namespace std; 9 | 10 | // N: 网格数 11 | class MatrixCoeff 12 | { 13 | private: 14 | VectorXd aL, aR, aP, Sp, Su; 15 | 16 | MatrixXd A_m; 17 | VectorXd b_m; 18 | VectorXd x; 19 | 20 | private: 21 | // Matrix系数初始化 22 | void initMatrix(const Mesh* mesh); 23 | 24 | public: 25 | MatrixCoeff(const Mesh* mesh) 26 | { 27 | int N = mesh->get_N(); 28 | 29 | aL = VectorXd(N); 30 | aR = VectorXd(N); 31 | aP = VectorXd(N); 32 | Sp = VectorXd(N); 33 | Su = VectorXd(N); 34 | 35 | A_m = MatrixXd(N, N); 36 | b_m = VectorXd(N); 37 | x = VectorXd (N); 38 | 39 | initMatrix(mesh); 40 | } 41 | 42 | MatrixXd& get_A_m() { return A_m; } 43 | VectorXd& get_b_m() { return b_m; } 44 | VectorXd& get_x() { return x; } 45 | }; 46 | 47 | // a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u} 48 | inline void MatrixCoeff::initMatrix(const Mesh* mesh) 49 | { 50 | using namespace Inputs; 51 | 52 | const VectorXd& DA_L = mesh->get_DA_L(); 53 | const VectorXd& DA_R = mesh->get_DA_R(); 54 | const VectorXd& F_l = mesh->get_F_l(); 55 | const VectorXd& F_r = mesh->get_F_r(); 56 | const VectorXd& V = mesh->get_V(); 57 | int N = mesh->get_N(); 58 | 59 | aL = DA_L + F_l.cwiseMax(VectorXd::Zero(N)); 60 | aL[0] = 0; // 左边界系数 61 | 62 | aR = DA_R + (-F_r).cwiseMax(VectorXd::Zero(N)); 63 | aR[N-1] = 0; // 右边界系数 64 | 65 | Sp = VectorXd::Zero(N); 66 | // 黎曼边界不会引入Sp 67 | // Sp[0] = -(2*DA_L[0] + max(F_l[0], 0.0)); // 左边界引入系数矩阵的不规则项 68 | // Sp[N-1] = -(2*DA_R[N-1] + max(-F_r[0], 0.0)); // 右边界引入系数矩阵的不规则项 69 | 70 | aP = aL + aR - Sp + (F_r - F_l); 71 | 72 | Su = S_bar * V; 73 | Su[0] = /*T_A*(2*DA_L[0] + max(F_l[0], 0.0))*/q_w*A + S_bar * V[0]; // 左边界使用黎曼边界条件 74 | Su[N-1] = T_B*(2*DA_R[N-1] + max(-F_r[N-1], 0.0)) + S_bar * V[N-1]; // 右边界用狄拉克边界条件 75 | 76 | for(int i = 0; i < N; i++) 77 | { 78 | if(i == 0) 79 | { 80 | A_m(i, i) = aP[i]; 81 | A_m(i, i+1) = -aR[i]; 82 | } 83 | else if(i == N-1) 84 | { 85 | A_m(i, i) = aP[i]; 86 | A_m(i, i-1) = -aL[i]; 87 | } 88 | else 89 | { 90 | A_m(i, i) = aP[i]; 91 | A_m(i, i-1) = -aL[i]; 92 | A_m(i, i+1) = -aR[i]; 93 | } 94 | } 95 | 96 | b_m = Su; 97 | 98 | cout << "A_m: " << endl << A_m << endl; 99 | cout << endl; 100 | 101 | cout << "b_m: " << endl << b_m << endl; 102 | cout << endl; 103 | } 104 | 105 | #endif -------------------------------------------------------------------------------- /version.3.1DDiffusion-Convection/Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESH_H__ 2 | #define __MESH_H__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | 7 | using Eigen::MatrixXd; 8 | using Eigen::VectorXd; 9 | 10 | // N: 网格数 11 | // L: 计算域长度 12 | class Mesh 13 | { 14 | private: 15 | // 网格数量 16 | int N; 17 | // 网格x方向面坐标 18 | VectorXd xFace; 19 | // 网格x方向中心坐标 20 | VectorXd xCentroid; 21 | // d_LP, d_PR:网格中心与左右相邻网格中心举例 22 | VectorXd d_LP, d_PR; 23 | // k*A/d 24 | VectorXd DA_L, DA_R; 25 | // F = rho * cp * U * A 26 | VectorXd F_l, F_r; 27 | // 网格左/右面速度 28 | VectorXd U_l, U_r; 29 | // 网格体积 30 | VectorXd V; 31 | 32 | private: 33 | // 初始化网格 34 | void initMesh(double L, int N); 35 | public: 36 | Mesh(double L, int N_) 37 | { 38 | N = N_; 39 | xFace = VectorXd(N + 1); 40 | xCentroid = VectorXd(N); 41 | d_LP = VectorXd(N); 42 | d_PR = VectorXd(N); 43 | DA_L = VectorXd(N); 44 | DA_R = VectorXd(N); 45 | F_l = VectorXd(N); 46 | F_r = VectorXd(N); 47 | U_l = VectorXd(N); 48 | U_r = VectorXd(N); 49 | V = VectorXd(N); 50 | 51 | initMesh(L, N); 52 | } 53 | 54 | const VectorXd& get_DA_L() const { return DA_L; } 55 | const VectorXd& get_DA_R() const { return DA_R; } 56 | const VectorXd& get_F_l() const { return F_l; } 57 | const VectorXd& get_F_r() const { return F_r; } 58 | const VectorXd& get_V() const { return V; } 59 | int get_N() const { return N; } 60 | }; 61 | 62 | inline void Mesh::initMesh(double L, int N) 63 | { 64 | using namespace Inputs; 65 | 66 | // x方向网格长度 67 | double dx = L / N; 68 | 69 | // 网格面x坐标 70 | for(int i = 0; i <= N; i++) 71 | { 72 | xFace[i] = dx * i; 73 | } 74 | // cout << xFace << endl; 75 | 76 | // 网格中心坐标 77 | for(int i = 0; i < N; i++) 78 | { 79 | xCentroid[i] = 0.5 * (xFace[i] + xFace[i+1]); 80 | } 81 | // cout << xCentroid << endl; 82 | 83 | // 网格中心相关量 84 | for(int i = 0; i < N; i++) 85 | { 86 | if(i == 0) // 左边界的d_LP需要特殊处理 87 | { 88 | d_LP[i] = 2 * (xCentroid[i] - xFace[i]); 89 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 90 | } 91 | else if(i == N - 1) // 右边界的d_PR需要特殊处理 92 | { 93 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 94 | d_PR[i] = 2 * (xFace[i+1] - xCentroid[i]); 95 | } 96 | else // 内点的d_LP, d_PR 97 | { 98 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 99 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 100 | } 101 | 102 | DA_L[i] = k * A / d_LP[i]; 103 | DA_R[i] = k * A / d_PR[i]; 104 | 105 | // 这里速度是均匀的 106 | U_l[i] = U; 107 | U_r[i] = U; 108 | F_l[i] = rho * cp * U_l[i] * A; 109 | F_r[i] = rho * cp * U_r[i] * A; 110 | 111 | // 网格体积 = faceArea * dx 112 | V[i] = A * (xFace[i+1] - xFace[i]); 113 | } 114 | } 115 | 116 | #endif -------------------------------------------------------------------------------- /version.5.1DDiffusion-Neumann-Boundary/Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESH_H__ 2 | #define __MESH_H__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | 7 | using Eigen::MatrixXd; 8 | using Eigen::VectorXd; 9 | 10 | // N: 网格数 11 | // L: 计算域长度 12 | class Mesh 13 | { 14 | private: 15 | // 网格x方向面坐标 16 | VectorXd xFace; 17 | // 网格x方向中心坐标 18 | VectorXd xCentroid; 19 | // d_LP, d_PR:网格中心与左右相邻网格中心举例 20 | VectorXd d_LP, d_PR; 21 | // k*A/d 22 | VectorXd DA_L, DA_R; 23 | // F = rho * cp * U * A 24 | VectorXd F_l, F_r; 25 | // 网格左/右面速度 26 | VectorXd U_l, U_r; 27 | // 网格体积 28 | VectorXd V; 29 | // 网格数量 30 | int N; 31 | private: 32 | // 初始化网格 33 | void initMesh(double L, int N); 34 | public: 35 | Mesh(double L, int N_) 36 | { 37 | N = N_; 38 | xFace = VectorXd(N + 1); 39 | xCentroid = VectorXd(N); 40 | d_LP = VectorXd(N); 41 | d_PR = VectorXd(N); 42 | DA_L = VectorXd(N); 43 | DA_R = VectorXd(N); 44 | F_l = VectorXd(N); 45 | F_r = VectorXd(N); 46 | U_l = VectorXd(N); 47 | U_r = VectorXd(N); 48 | V = VectorXd(N); 49 | 50 | initMesh(L, N); 51 | } 52 | 53 | const VectorXd& get_DA_L() const { return DA_L; } 54 | const VectorXd& get_DA_R() const { return DA_R; } 55 | const VectorXd& get_F_l() const { return F_l; } 56 | const VectorXd& get_F_r() const { return F_r; } 57 | const VectorXd& get_V() const { return V; } 58 | int get_N() const { return N; } 59 | }; 60 | 61 | inline void Mesh::initMesh(double L, int N) 62 | { 63 | using namespace Inputs; 64 | 65 | // x方向网格长度 66 | double dx = L / N; 67 | 68 | // 网格面x坐标 69 | for(int i = 0; i <= N; i++) 70 | { 71 | xFace[i] = dx * i; 72 | } 73 | // cout << xFace << endl; 74 | 75 | // 网格中心坐标 76 | for(int i = 0; i < N; i++) 77 | { 78 | xCentroid[i] = 0.5 * (xFace[i] + xFace[i+1]); 79 | } 80 | // cout << xCentroid << endl; 81 | 82 | // 网格中心相关量 83 | for(int i = 0; i < N; i++) 84 | { 85 | if(i == 0) // 左边界的d_LP需要特殊处理 86 | { 87 | d_LP[i] = 2 * (xCentroid[i] - xFace[i]); 88 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 89 | } 90 | else if(i == N - 1) // 右边界的d_PR需要特殊处理 91 | { 92 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 93 | d_PR[i] = 2 * (xFace[i+1] - xCentroid[i]); 94 | } 95 | else // 内点的d_LP, d_PR 96 | { 97 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 98 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 99 | } 100 | 101 | DA_L[i] = k * A / d_LP[i]; 102 | DA_R[i] = k * A / d_PR[i]; 103 | 104 | // 这里速度是均匀的 105 | U_l.setConstant(U); 106 | U_r.setConstant(U); 107 | F_l = rho * cp * U_l * A; 108 | F_r = rho * cp * U_r * A; 109 | 110 | // 网格体积 = faceArea * dx 111 | V[i] = A * (xFace[i+1] - xFace[i]); 112 | } 113 | } 114 | 115 | #endif -------------------------------------------------------------------------------- /version.4.1DDiffusion-Convection-Upwind/Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESH_H__ 2 | #define __MESH_H__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | 7 | using Eigen::MatrixXd; 8 | using Eigen::VectorXd; 9 | 10 | // N: 网格数 11 | // L: 计算域长度 12 | class Mesh 13 | { 14 | private: 15 | // 网格数量 16 | int N; 17 | // 网格x方向面坐标 18 | VectorXd xFace; 19 | // 网格x方向中心坐标 20 | VectorXd xCentroid; 21 | // d_LP, d_PR:网格中心与左右相邻网格中心举例 22 | VectorXd d_LP, d_PR; 23 | // k*A/d 24 | VectorXd DA_L, DA_R; 25 | // F = rho * cp * U * A 26 | VectorXd F_l, F_r; 27 | // 网格左/右面速度 28 | VectorXd U_l, U_r; 29 | // 网格体积 30 | VectorXd V; 31 | 32 | private: 33 | // 初始化网格 34 | void initMesh(double L, int N); 35 | public: 36 | Mesh(double L, int N_) 37 | { 38 | N = N_; 39 | xFace = VectorXd(N + 1); 40 | xCentroid = VectorXd(N); 41 | d_LP = VectorXd(N); 42 | d_PR = VectorXd(N); 43 | DA_L = VectorXd(N); 44 | DA_R = VectorXd(N); 45 | F_l = VectorXd(N); 46 | F_r = VectorXd(N); 47 | U_l = VectorXd(N); 48 | U_r = VectorXd(N); 49 | V = VectorXd(N); 50 | 51 | initMesh(L, N); 52 | } 53 | 54 | const VectorXd& get_DA_L() const { return DA_L; } 55 | const VectorXd& get_DA_R() const { return DA_R; } 56 | const VectorXd& get_F_l() const { return F_l; } 57 | const VectorXd& get_F_r() const { return F_r; } 58 | const VectorXd& get_V() const { return V; } 59 | int get_N() const { return N; } 60 | }; 61 | 62 | inline void Mesh::initMesh(double L, int N) 63 | { 64 | using namespace Inputs; 65 | 66 | // x方向网格长度 67 | double dx = L / N; 68 | 69 | // 网格面x坐标 70 | for(int i = 0; i <= N; i++) 71 | { 72 | xFace[i] = dx * i; 73 | } 74 | // cout << xFace << endl; 75 | 76 | // 网格中心坐标 77 | for(int i = 0; i < N; i++) 78 | { 79 | xCentroid[i] = 0.5 * (xFace[i] + xFace[i+1]); 80 | } 81 | // cout << xCentroid << endl; 82 | 83 | // 网格中心相关量 84 | for(int i = 0; i < N; i++) 85 | { 86 | if(i == 0) // 左边界的d_LP需要特殊处理 87 | { 88 | d_LP[i] = 2 * (xCentroid[i] - xFace[i]); 89 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 90 | } 91 | else if(i == N - 1) // 右边界的d_PR需要特殊处理 92 | { 93 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 94 | d_PR[i] = 2 * (xFace[i+1] - xCentroid[i]); 95 | } 96 | else // 内点的d_LP, d_PR 97 | { 98 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 99 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 100 | } 101 | 102 | DA_L[i] = k * A / d_LP[i]; 103 | DA_R[i] = k * A / d_PR[i]; 104 | 105 | // 这里速度是均匀的 106 | U_l[i] = U; 107 | U_r[i] = U; 108 | F_l[i] = rho * cp * U_l[i] * A; 109 | F_r[i] = rho * cp * U_r[i] * A; 110 | 111 | // 网格体积 = faceArea * dx 112 | V[i] = A * (xFace[i+1] - xFace[i]); 113 | } 114 | } 115 | 116 | #endif -------------------------------------------------------------------------------- /Inputs.cpp: -------------------------------------------------------------------------------- 1 | #include "Inputs.h" 2 | #include 3 | #include 4 | 5 | Inputs::Inputs(const std::string& fileName) 6 | { 7 | try { 8 | std::ifstream file(fileName); 9 | if (!file.is_open()) { 10 | throw std::runtime_error("无法打开配置文件: " + fileName); 11 | } 12 | 13 | file >> config; 14 | file.close(); 15 | 16 | // 读取配置并赋值 17 | loadInputs(); 18 | 19 | } catch (const std::exception& e) { 20 | std::cerr << "读取配置文件错误: " << e.what() << std::endl; 21 | throw; 22 | } 23 | } 24 | 25 | void Inputs::loadInputs() 26 | { 27 | // 提取几何参数 28 | if (config.contains("geometry")) { 29 | auto geom = config["geometry"]; 30 | geometry.Nx = geom.value("Nx", 50); // 从JSON中读取,默认值50 31 | geometry.Ny = geom.value("Ny", 25); // 从JSON中读取,默认值25 32 | geometry.Nz = geom.value("Nz", 1); // 从JSON中读取,默认值1 33 | geometry.XLen = geom.value("XLen", 1.0); 34 | geometry.YLen = geom.value("YLen", 1.0); 35 | geometry.ZLen = geom.value("ZLen", 1.0); 36 | } 37 | 38 | // 提取物理属性 39 | if (config.contains("physcial_properties")) { 40 | auto props = config["physcial_properties"]; 41 | physcial_properties.k = props.value("k", 100.0); 42 | physcial_properties.rho = props.value("rho", 1.0); 43 | physcial_properties.cp = props.value("cp", 1000.0); 44 | physcial_properties.mu = props.value("mu", 0.01); 45 | } 46 | 47 | // 提取边界条件 48 | if (config.contains("boundary")) { 49 | auto bound = config["boundary"]; 50 | boundary.T_left = bound.value("T_left", 100.0); 51 | boundary.T_right = bound.value("T_right", 200.0); 52 | boundary.T_bottom = bound.value("T_bottom", 250.0); 53 | boundary.T_top = bound.value("T_top", 150.0); 54 | boundary.q_w = bound.value("q_w", 100.0); 55 | 56 | boundary.U_left = bound.value("U_left", 0.0); 57 | boundary.U_right = bound.value("U_right", 0.0); 58 | boundary.U_top = bound.value("U_top", 0.01); 59 | boundary.U_bottom = bound.value("U_bottom", 0.0); 60 | 61 | boundary.V_left = bound.value("V_left", 0.0); 62 | boundary.V_right = bound.value("V_right", 0.0); 63 | boundary.V_top = bound.value("V_top", 0.0); 64 | boundary.V_bottom = bound.value("V_bottom", 0.0); 65 | 66 | boundary.p_left = bound.value("p_left", 0.0); 67 | boundary.p_right = bound.value("p_right", 0.0); 68 | boundary.p_top = bound.value("p_top", 0.0); 69 | boundary.p_bottom = bound.value("p_bottom", 0.0); 70 | } 71 | 72 | // 提取源项 73 | if (config.contains("source")) { 74 | auto src = config["source"]; 75 | source.S_bar = src.value("S_bar", 1000.0); 76 | } 77 | 78 | // 输出读取的配置信息以验证 79 | std::cout << "配置读取完成:" << std::endl; 80 | std::cout << "网格尺寸: " << geometry.Nx << "x" << geometry.Ny << "x" << geometry.Nz << std::endl; 81 | std::cout << "计算域尺寸: " << geometry.XLen << "x" << geometry.YLen << "x" << geometry.ZLen << std::endl; 82 | std::cout << "热导率: " << physcial_properties.k << " W/mK" << std::endl; 83 | std::cout << "左边界温度: " << boundary.T_left << " °C" << std::endl; 84 | } -------------------------------------------------------------------------------- /EnergyEqn.cpp: -------------------------------------------------------------------------------- 1 | #include "EnergyEqn.h" 2 | #include "MatrixCoeff.h" 3 | 4 | void EnergyEqn::init_S() 5 | { 6 | const VectorXd& V = mesh->get_V(); 7 | 8 | S = S_bar * V; 9 | } 10 | 11 | TransportEqn& EnergyEqn::addConvectionTerm() 12 | { 13 | double T_l = boundary->T_left; 14 | double T_r = boundary->T_right; 15 | double T_b = boundary->T_bottom; 16 | double T_t = boundary->T_top; 17 | 18 | double q_w = boundary->q_w; 19 | 20 | double Ax = mesh->get_Ax(); 21 | double Ay = mesh->get_Ay(); 22 | double Az = mesh->get_Az(); 23 | 24 | mat->aW += F_w.cwiseMax(VectorXd::Zero(N)); 25 | mat->aE += (-F_e).cwiseMax(VectorXd::Zero(N)); 26 | mat->aS += F_s.cwiseMax(VectorXd::Zero(N)); 27 | mat->aN += (-F_n).cwiseMax(VectorXd::Zero(N)); 28 | 29 | for(int i = 0; i < N; i++) 30 | { 31 | if(mesh->is_at_left_boundary(i)) 32 | { 33 | mat->aW[i] = 0; // 左边界 34 | mat->SO[i] += -(max(F_w[i], 0.0)); 35 | mat->Su[i] += T_l * max(F_e[i], 0.0); 36 | } 37 | if(mesh->is_at_right_boundary(i)) 38 | { 39 | mat->aE[i] = 0; // 右边界 40 | mat->SO[i] += -(max(-F_e[i], 0.0)); 41 | mat->Su[i] += T_r * max(-F_e[i], 0.0); 42 | } 43 | if(mesh->is_at_bottom_boundary(i)) 44 | { 45 | mat->aS[i] = 0; // 下边界 46 | mat->SO[i] += -(max(F_s[i], 0.0)); 47 | mat->Su[i] += T_b * max(F_s[i], 0.0); 48 | } 49 | if(mesh->is_at_top_boundary(i)) 50 | { 51 | mat->aN[i] = 0; // 上边界 52 | mat->SO[i] += -(max(-F_n[i], 0.0)); 53 | mat->Su[i] += T_t * max(-F_n[i], 0.0); 54 | } 55 | } 56 | 57 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO + (F_e - F_w + F_n - F_s); 58 | 59 | return *this; 60 | } 61 | 62 | TransportEqn& EnergyEqn::addDiffusionTerm() 63 | { 64 | double T_l = boundary->T_left; 65 | double T_r = boundary->T_right; 66 | double T_b = boundary->T_bottom; 67 | double T_t = boundary->T_top; 68 | double q_w = boundary->q_w; 69 | 70 | double Ax = mesh->get_Ax(); 71 | double Ay = mesh->get_Ay(); 72 | double Az = mesh->get_Az(); 73 | 74 | mat->aW += DA_w; 75 | mat->aE += DA_e; 76 | mat->aS += DA_s; 77 | mat->aN += DA_n; 78 | 79 | for(int i = 0; i < N; i++) 80 | { 81 | if(mesh->is_at_left_boundary(i)) 82 | { 83 | mat->aW[i] = 0; // 左边界 84 | mat->SO[i] += -2*DA_w[i]; 85 | mat->Su[i] += T_l * 2*DA_w[i]; 86 | // Su[i] += -q_w*Ax; // 左边界使用黎曼边界条件 87 | } 88 | if(mesh->is_at_right_boundary(i)) 89 | { 90 | mat->aE[i] = 0; // 右边界 91 | mat->SO[i] += -2*DA_e[i]; 92 | mat->Su[i] += T_r * 2*DA_e[i]; 93 | } 94 | if(mesh->is_at_bottom_boundary(i)) 95 | { 96 | mat->aS[i] = 0; // 下边界 97 | mat->SO[i] += -2*DA_s[i]; 98 | mat->Su[i] += T_b * 2*DA_s[i]; 99 | } 100 | if(mesh->is_at_top_boundary(i)) 101 | { 102 | mat->aN[i] = 0; // 上边界 103 | mat->SO[i] += -2*DA_n[i]; 104 | mat->Su[i] += T_t * 2*DA_n[i]; 105 | } 106 | } 107 | 108 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO; 109 | 110 | return *this; 111 | } 112 | 113 | TransportEqn& EnergyEqn::addSourceTerm() 114 | { 115 | mat->Su += S; 116 | 117 | return *this; 118 | } -------------------------------------------------------------------------------- /Output.h: -------------------------------------------------------------------------------- 1 | #ifndef __OUTPUT_H__ 2 | #define __OUTPUT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Field.h" 8 | #include "Mesh.h" 9 | 10 | using namespace std; 11 | 12 | class Output 13 | { 14 | private: 15 | Mesh* mesh; 16 | public: 17 | Output(Mesh* mesh) : mesh(mesh){ } 18 | 19 | void write(const VectorXd& var, double bc_left, double bc_right, double bc_top, double bc_bottom, string varName) 20 | { 21 | string FileName = varName + ".csv"s; 22 | 23 | ofstream tempFile(FileName); 24 | 25 | tempFile << "x, " << "y, " << "z, " << varName << endl; 26 | 27 | int N = mesh->get_N(); 28 | 29 | const VectorXd& x = mesh->get_xCentroid(); 30 | const VectorXd& y = mesh->get_yCentroid(); 31 | const VectorXd& z = mesh->get_zCentroid(); 32 | 33 | const VectorXd& xFace = mesh->get_xFace(); 34 | const VectorXd& yFace = mesh->get_yFace(); 35 | const VectorXd& zFace = mesh->get_zFace(); 36 | 37 | // 底部边界温度 38 | for(int i = 0; i < xFace.size(); i++) 39 | { 40 | if(i == 0) // 左下角 41 | { 42 | tempFile << xFace[i] << ", " << 0.0 << ", " << zFace[0] << ", " << (0.5*((bc_bottom) + (bc_left))) << endl; 43 | } 44 | else if(i == xFace.size() - 1) // 右下角 45 | { 46 | tempFile << xFace[i] << ", " << 0.0 << ", " << zFace[0] << ", " << (0.5*((bc_bottom) + (bc_right))) << endl; 47 | } 48 | else 49 | { 50 | tempFile << xFace[i] << ", " << 0.0 << ", " << zFace[0] << ", " << (bc_bottom) << endl; 51 | } 52 | } 53 | 54 | // 顶部边界温度 55 | for(int i = 0; i < xFace.size(); i++) 56 | { 57 | if(i == 0) // 左上角 58 | { 59 | tempFile << xFace[i] << ", " << yFace[yFace.size()-1] << ", " << zFace[0] << ", " << (0.5*((bc_top) + (bc_left))) << endl; 60 | } 61 | else if(i == xFace.size() - 1) // 右上角 62 | { 63 | tempFile << xFace[i] << ", " << yFace[yFace.size()-1] << ", " << zFace[0] << ", " << (0.5*((bc_top) + (bc_right))) << endl; 64 | } 65 | else 66 | { 67 | tempFile << xFace[i] << ", " << yFace[yFace.size()-1] << ", " << zFace[0] << ", " << (bc_top) << endl; 68 | } 69 | } 70 | 71 | // 左侧边界温度 (不包括顶点) 72 | for(int i = 1; i < yFace.size() - 1; i++) 73 | { 74 | tempFile << 0.0 << ", " << yFace[i] << ", " << zFace[0] << ", " << (bc_left) << endl; 75 | } 76 | 77 | // 右侧边界温度 (不包括顶点) 78 | for(int i = 1; i < yFace.size() - 1; i++) 79 | { 80 | tempFile << xFace[xFace.size()-1] << ", " << yFace[i] << ", " << zFace[0] << ", " << (bc_right) << endl; 81 | } 82 | 83 | // 内部顶点温度 84 | for(int i = 0; i < N; i++) 85 | { 86 | // 体心与左下角顶点一一对应 87 | if(!(mesh->is_at_left_boundary(i) || mesh->is_at_bottom_boundary(i))) 88 | { 89 | double cellLeftVar = var[mesh->left_of(i)]; 90 | double cellBottomVar = var[mesh->bottom_of(i)]; 91 | double cellBottomLeftVar = var[mesh->left_of(mesh->bottom_of(i))]; 92 | 93 | double varNode = 0.25 * (var[i] + cellLeftVar + cellBottomVar + cellBottomLeftVar); 94 | 95 | // ix, iy, iz编号正好与左下角xFace, yFace, zFace编号相同 96 | tempFile << xFace[mesh->ix_of(i)] << ", " << yFace[mesh->iy_of(i)] << ", " << zFace[mesh->iz_of(i)] << ", " << varNode << endl; 97 | } 98 | } 99 | } 100 | }; 101 | 102 | #endif -------------------------------------------------------------------------------- /YMomentumEqn.cpp: -------------------------------------------------------------------------------- 1 | #include "YMomentumEqn.h" 2 | #include "MatrixCoeff.h" 3 | 4 | void YMomentumEqn::init_S() 5 | { 6 | double Ay = mesh->get_Ay(); 7 | VectorXd& p = field->p; 8 | 9 | for(int i = 0; i < N; i++) 10 | { 11 | int i_n = mesh->top_of(i); 12 | int i_s = mesh->bottom_of(i); 13 | 14 | if(mesh->is_at_top_boundary(i)) 15 | { 16 | S[i] = (p[i_s] - p[i]) * Ay / 2; 17 | } 18 | else if(mesh->is_at_bottom_boundary(i)) 19 | { 20 | S[i] = (p[i] - p[i_n]) * Ay / 2; 21 | } 22 | else 23 | { 24 | S[i] = (p[i_s] -p[i_n]) * Ay / 2; 25 | } 26 | } 27 | } 28 | 29 | TransportEqn& YMomentumEqn::addConvectionTerm() 30 | { 31 | double V_t = boundary->V_top; 32 | 33 | double Ax = mesh->get_Ax(); 34 | double Ay = mesh->get_Ay(); 35 | double Az = mesh->get_Az(); 36 | 37 | mat->aW += F_w.cwiseMax(VectorXd::Zero(N)); 38 | mat->aE += (-F_e).cwiseMax(VectorXd::Zero(N)); 39 | mat->aS += F_s.cwiseMax(VectorXd::Zero(N)); 40 | mat->aN += (-F_n).cwiseMax(VectorXd::Zero(N)); 41 | 42 | // 边界条件这里暂时先写死,后期再做通用性优化 43 | for(int i = 0; i < N; i++) 44 | { 45 | if(mesh->is_at_left_boundary(i)) 46 | { 47 | mat->aW[i] = 0.0; // 左边界 48 | mat->SO[i] += 0.0; 49 | mat->Su[i] += 0.0; 50 | F_w[i] = 0; 51 | } 52 | if(mesh->is_at_right_boundary(i)) 53 | { 54 | mat->aE[i] = 0.0; // 右边界 55 | mat->SO[i] += 0.0; 56 | mat->Su[i] += 0.0; 57 | F_e[i] = 0; 58 | } 59 | if(mesh->is_at_bottom_boundary(i)) 60 | { 61 | mat->aS[i] = 0; // 下边界 62 | mat->SO[i] += 0.0; 63 | mat->Su[i] += 0.0; 64 | F_s[i] = 0; 65 | } 66 | if(mesh->is_at_top_boundary(i)) 67 | { 68 | mat->aN[i] = 0; // 上边界 69 | mat->SO[i] += 0; 70 | mat->Su[i] += -rho * V_t * V_t; 71 | F_n[i] = 0; 72 | } 73 | } 74 | 75 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO + (F_e - F_w + F_n - F_s); 76 | 77 | return *this; 78 | } 79 | 80 | TransportEqn& YMomentumEqn::addDiffusionTerm() 81 | { 82 | double V_t = boundary->V_top; 83 | 84 | double Ax = mesh->get_Ax(); 85 | double Ay = mesh->get_Ay(); 86 | double Az = mesh->get_Az(); 87 | 88 | mat->aW += DA_w; 89 | mat->aE += DA_e; 90 | mat->aS += DA_s; 91 | mat->aN += DA_n; 92 | 93 | for(int i = 0; i < N; i++) 94 | { 95 | if(mesh->is_at_left_boundary(i)) 96 | { 97 | mat->aW[i] = 0; // 左边界 98 | mat->SO[i] += -3*DA_w[i]; 99 | mat->SE[i] += -DA_w[i] / 3; 100 | mat->Su[i] += 0.0; 101 | } 102 | if(mesh->is_at_right_boundary(i)) 103 | { 104 | mat->aE[i] = 0; // 右边界 105 | mat->SO[i] += -3*DA_e[i]; 106 | mat->SW[i] += -DA_e[i] / 3; 107 | mat->Su[i] += 0.0; 108 | } 109 | if(mesh->is_at_bottom_boundary(i)) 110 | { 111 | mat->aS[i] = 0; // 下边界 112 | mat->SO[i] += -3*DA_s[i]; 113 | mat->SN[i] += -DA_s[i] / 3; 114 | mat->Su[i] += 0.0; 115 | } 116 | if(mesh->is_at_top_boundary(i)) 117 | { 118 | mat->aN[i] = 0; // 上边界 119 | mat->SO[i] += -3*DA_n[i]; 120 | mat->SS[i] += DA_n[i] / 3; 121 | mat->Su[i] += V_t * (8.0/3)*DA_n[i]; 122 | } 123 | } 124 | 125 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO; 126 | 127 | return *this; 128 | } 129 | 130 | TransportEqn& YMomentumEqn::addSourceTerm() 131 | { 132 | mat->Su += S; // 将S^u加到S_u一起 133 | 134 | return *this; 135 | } -------------------------------------------------------------------------------- /XMomentumEqn.cpp: -------------------------------------------------------------------------------- 1 | #include "XMomentumEqn.h" 2 | #include "MatrixCoeff.h" 3 | 4 | void XMomentumEqn::init_S() 5 | { 6 | double Ax = mesh->get_Ax(); 7 | VectorXd& p = field->p; 8 | 9 | for(int i = 0; i < N; i++) 10 | { 11 | int i_e = mesh->right_of(i); 12 | int i_w = mesh->left_of(i); 13 | 14 | if(mesh->is_at_left_boundary(i)) 15 | { 16 | S[i] = (p[i] - p[i_e]) * Ax / 2; 17 | } 18 | else if(mesh->is_at_right_boundary(i)) 19 | { 20 | S[i] = (p[i_w] - p[i]) * Ax / 2; 21 | } 22 | else 23 | { 24 | S[i] = (p[i_w] - p[i_e]) * Ax / 2; 25 | } 26 | } 27 | } 28 | 29 | TransportEqn& XMomentumEqn::addConvectionTerm() 30 | { 31 | double U_t = boundary->U_top; 32 | double V_t = boundary->V_top; 33 | 34 | double Ax = mesh->get_Ax(); 35 | double Ay = mesh->get_Ay(); 36 | double Az = mesh->get_Az(); 37 | 38 | mat->aW += F_w.cwiseMax(VectorXd::Zero(N)); 39 | mat->aE += (-F_e).cwiseMax(VectorXd::Zero(N)); 40 | mat->aS += F_s.cwiseMax(VectorXd::Zero(N)); 41 | mat->aN += (-F_n).cwiseMax(VectorXd::Zero(N)); 42 | 43 | // 边界条件这里暂时先写死,后期再做通用性优化 44 | for(int i = 0; i < N; i++) 45 | { 46 | if(mesh->is_at_left_boundary(i)) 47 | { 48 | mat->aW[i] = 0.0; // 左边界 49 | mat->SO[i] += 0.0; 50 | mat->Su[i] += 0.0; 51 | F_w[i] = 0; 52 | } 53 | if(mesh->is_at_right_boundary(i)) 54 | { 55 | mat->aE[i] = 0.0; // 右边界 56 | mat->SO[i] += 0.0; 57 | mat->Su[i] += 0.0; 58 | F_e[i] = 0; 59 | } 60 | if(mesh->is_at_bottom_boundary(i)) 61 | { 62 | mat->aS[i] = 0; // 下边界 63 | mat->SO[i] += 0.0; 64 | mat->Su[i] += 0.0; 65 | F_s[i] = 0; 66 | } 67 | if(mesh->is_at_top_boundary(i)) 68 | { 69 | mat->aN[i] = 0; // 上边界 70 | mat->SO[i] += 0; 71 | mat->Su[i] += -rho * V_t * U_t; 72 | F_n[i] = 0; 73 | } 74 | } 75 | 76 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO + (F_e - F_w + F_n - F_s); 77 | 78 | return *this; 79 | } 80 | 81 | TransportEqn& XMomentumEqn::addDiffusionTerm() 82 | { 83 | double U_t = boundary->U_top; 84 | 85 | double Ax = mesh->get_Ax(); 86 | double Ay = mesh->get_Ay(); 87 | double Az = mesh->get_Az(); 88 | 89 | mat->aW += DA_w; 90 | mat->aE += DA_e; 91 | mat->aS += DA_s; 92 | mat->aN += DA_n; 93 | 94 | for(int i = 0; i < N; i++) 95 | { 96 | if(mesh->is_at_left_boundary(i)) 97 | { 98 | mat->aW[i] = 0; // 左边界 99 | mat->SO[i] += -3*DA_w[i]; 100 | mat->SE[i] += -DA_w[i] / 3; 101 | mat->Su[i] += 0.0; 102 | } 103 | if(mesh->is_at_right_boundary(i)) 104 | { 105 | mat->aE[i] = 0; // 右边界 106 | mat->SO[i] += -3*DA_e[i]; 107 | mat->SW[i] += -DA_e[i] / 3; 108 | mat->Su[i] += 0.0; 109 | } 110 | if(mesh->is_at_bottom_boundary(i)) 111 | { 112 | mat->aS[i] = 0; // 下边界 113 | mat->SO[i] += -3*DA_s[i]; 114 | mat->SN[i] += -DA_s[i] / 3; 115 | mat->Su[i] += 0.0; 116 | } 117 | if(mesh->is_at_top_boundary(i)) 118 | { 119 | mat->aN[i] = 0; // 上边界 120 | mat->SO[i] += -3*DA_n[i]; 121 | mat->SS[i] += DA_n[i] / 3; 122 | mat->Su[i] += U_t * (8.0/3)*DA_n[i]; 123 | } 124 | } 125 | 126 | mat->aO += mat->aW + mat->aE + mat->aS + mat->aN - mat->SO; 127 | 128 | return *this; 129 | } 130 | 131 | TransportEqn& XMomentumEqn::addSourceTerm() 132 | { 133 | mat->Su += S; // 将S^u加到S_u一起 134 | 135 | return *this; 136 | } -------------------------------------------------------------------------------- /Mesh.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESH_H__ 2 | #define __MESH_H__ 3 | 4 | #include 5 | #include "Inputs.h" 6 | #include 7 | 8 | using Eigen::MatrixXd; 9 | using Eigen::VectorXd; 10 | using Eigen::VectorXi; 11 | 12 | class Mesh 13 | { 14 | private: 15 | // x, y, z方向,面坐标 16 | VectorXd xFace, yFace, zFace; 17 | // 网格x, y, z方向中心坐标 18 | VectorXd xCentroid, yCentroid, zCentroid; 19 | // 网格中心与左/右/下/上,相邻网格中心距离 20 | VectorXd d_LP, d_PR, d_BP, d_PT; 21 | // 标记是否已被赋值,0未赋值,1已赋值 22 | VectorXi flag_d_LP, flag_d_PR, flag_d_BP, flag_d_PT; 23 | // 网格体积 24 | VectorXd V; 25 | // 网格数量 26 | int Nx, Ny, Nz, N; 27 | // 网格横截面积 28 | double Ax, Ay, Az; 29 | // 网格长度 30 | double dx, dy, dz; 31 | 32 | private: 33 | // 初始化网格 34 | void initMesh(const Inputs* inputs); 35 | 36 | public: 37 | Mesh(const Inputs* inputs) 38 | : Nx(inputs->geometry.Nx), 39 | Ny(inputs->geometry.Ny), 40 | Nz(inputs->geometry.Nz), 41 | N(Nx*Ny*Nz) 42 | { 43 | xFace = VectorXd(Nx + 1); 44 | yFace = VectorXd(Ny + 1); 45 | zFace = VectorXd(Nz + 1); 46 | 47 | xCentroid = VectorXd(N); 48 | yCentroid = VectorXd(N); 49 | zCentroid = VectorXd(N); 50 | 51 | d_LP = VectorXd(N); 52 | d_PR = VectorXd(N); 53 | d_BP = VectorXd(N); 54 | d_PT = VectorXd(N); 55 | 56 | flag_d_LP = VectorXi::Zero(N); 57 | flag_d_PR = VectorXi::Zero(N); 58 | flag_d_BP = VectorXi::Zero(N); 59 | flag_d_PT = VectorXi::Zero(N); 60 | 61 | V = VectorXd(N); 62 | 63 | initMesh(inputs); 64 | } 65 | 66 | const VectorXd& get_V() const { return V; } 67 | 68 | const VectorXd& get_d_LP() const { return d_LP; } 69 | const VectorXd& get_d_PR() const { return d_PR; } 70 | const VectorXd& get_d_BP() const { return d_BP; } 71 | const VectorXd& get_d_PT() const { return d_PT; } 72 | 73 | int get_N() const { return N; } 74 | 75 | double get_Ax() const { return Ax; } 76 | double get_Ay() const { return Ay; } 77 | double get_Az() const { return Az; } 78 | 79 | double get_dx() const { return dx; } 80 | double get_dy() const { return dy; } 81 | double get_dz() const { return dz; } 82 | 83 | // 判断网格是否紧邻边界 84 | bool is_at_left_boundary(int global_index) const { return ((global_index % Nx) == 0); } 85 | bool is_at_right_boundary(int global_index) const { return ((global_index % Nx) == Nx - 1); } 86 | bool is_at_bottom_boundary(int global_index) const { return ((global_index / Nx) == 0); } 87 | bool is_at_top_boundary(int global_index) const { return ((global_index / Nx) == Ny - 1); } 88 | bool is_at_front_boundary(int global_index) const { return ((global_index / (Nx * Ny)) == 0); } 89 | bool is_at_back_boundary(int global_index) const { return ((global_index / (Nx * Ny)) == Nz - 1); } 90 | 91 | // 返回当前网格 左/右/下/上 的全局编号 92 | int left_of(int global_index) const { return (global_index - 1); } 93 | int right_of(int global_index) const { return (global_index + 1); } 94 | int bottom_of(int global_index) const { return (global_index - Nx); } 95 | int top_of(int global_index) const { return (global_index + Nx); } 96 | 97 | const VectorXd& get_xCentroid() const { return xCentroid; } 98 | const VectorXd& get_yCentroid() const { return yCentroid; } 99 | const VectorXd& get_zCentroid() const { return zCentroid; } 100 | 101 | const VectorXd& get_xFace() const { return xFace; } 102 | const VectorXd& get_yFace() const { return yFace; } 103 | const VectorXd& get_zFace() const { return zFace; } 104 | 105 | int ix_of(int global_index) const { return (global_index % Nx); } 106 | int iy_of(int global_index) const { return (global_index / Nx); } 107 | int iz_of(int global_index) const { return (global_index / (Nx * Ny)); } 108 | }; 109 | 110 | #endif -------------------------------------------------------------------------------- /version.1.1DDiffusion_POP/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using Eigen::MatrixXd; 5 | using Eigen::VectorXd; 6 | using namespace std; 7 | 8 | namespace Inputs 9 | { 10 | // # Thermal Conductivity of the bar (W/mK) 11 | double k = 100; 12 | 13 | // # Cross-sectional Area of the bar (m2) 14 | double A = 0.1; 15 | 16 | // # Length of the bar (m) 17 | double L = 5; 18 | 19 | // # Number of cells in the mesh 20 | int N = 5; 21 | 22 | // # Temperature at the left hand side of the bar (deg C) 23 | double T_A = 100; 24 | 25 | // # Temperature at the left hand side of the bar (deg C) 26 | double T_B = 200; 27 | 28 | // # Heat source per unit volume (W/m3) 29 | double S_bar = 1000; 30 | } 31 | 32 | namespace Mesh 33 | { 34 | using Inputs::N; 35 | 36 | // 网格x方向面坐标 37 | VectorXd xFace(N + 1); 38 | 39 | // 网格x方向中心坐标 40 | VectorXd xCentroid(N); 41 | 42 | // d_LP, d_PR:网格中心与左右相邻网格中心举例 43 | VectorXd d_LP(N), d_PR(N); 44 | 45 | // k*A/d 46 | VectorXd DA_L(N), DA_R(N); 47 | 48 | // 网格体积 49 | VectorXd V(N); 50 | } 51 | 52 | namespace MatrixCoeff 53 | { 54 | using Inputs::N; 55 | 56 | VectorXd aL(N), aR(N), aP(N), Sp(N), Su(N); 57 | 58 | MatrixXd A_m(N, N); 59 | VectorXd b_m(N); 60 | VectorXd x(N); 61 | } 62 | 63 | // 初始化网格 64 | void initMesh(double L, int N); 65 | 66 | // Matrix系数初始化 67 | void initMatrix(); 68 | 69 | int main() 70 | { 71 | // 创建网格 72 | initMesh(Inputs::L, Inputs::N); 73 | 74 | // 初始化矩阵 75 | initMatrix(); 76 | 77 | // 求解矩阵 78 | MatrixCoeff::x = MatrixCoeff::A_m.fullPivLu().solve(MatrixCoeff::b_m); 79 | 80 | // 输出结果 81 | cout << "Solution: " << endl << MatrixCoeff::x << endl; 82 | } 83 | 84 | void initMesh(double L, int N) 85 | { 86 | using namespace Inputs; 87 | using namespace Mesh; 88 | 89 | // x方向网格长度 90 | double dx = L / N; 91 | 92 | // 网格面x坐标 93 | for(int i = 0; i <= N; i++) 94 | { 95 | xFace[i] = dx * i; 96 | } 97 | // cout << xFace << endl; 98 | 99 | // 网格中心坐标 100 | for(int i = 0; i < N; i++) 101 | { 102 | xCentroid[i] = 0.5 * (xFace[i] + xFace[i+1]); 103 | } 104 | // cout << xCentroid << endl; 105 | 106 | // 网格中心相关量 107 | for(int i = 0; i < N; i++) 108 | { 109 | if(i == 0) // 左边界的d_LP需要特殊处理 110 | { 111 | d_LP[i] = 2 * (xCentroid[i] - xFace[i]); 112 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 113 | } 114 | else if(i == N - 1) // 右边界的d_PR需要特殊处理 115 | { 116 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 117 | d_PR[i] = 2 * (xFace[i+1] - xCentroid[i]); 118 | } 119 | else // 内点的d_LP, d_PR 120 | { 121 | d_LP[i] = xCentroid[i] - xCentroid[i-1]; 122 | d_PR[i] = xCentroid[i+1] - xCentroid[i]; 123 | } 124 | 125 | DA_L[i] = k * A / d_LP[i]; 126 | DA_R[i] = k * A / d_PR[i]; 127 | 128 | // 网格体积 = faceArea * dx 129 | V[i] = A * (xFace[i+1] - xFace[i]); 130 | } 131 | } 132 | 133 | // a_{p} T_{p}=a_{L} T_{L}+a_{R} T_{R}+S_{u} 134 | void initMatrix() 135 | { 136 | using namespace Inputs; 137 | using namespace Mesh; 138 | using namespace MatrixCoeff; 139 | 140 | aL = DA_L; 141 | aL[0] = 0; // 左边界系数 142 | 143 | aR = DA_R; 144 | aR[N-1] = 0; // 右边界系数 145 | 146 | Sp = VectorXd::Zero(N); 147 | Sp[0] = -2 * DA_L[0]; // 左边界引入系数矩阵的不规则项 148 | Sp[N-1] = -2 * DA_R[N-1]; // 右边界引入系数矩阵的不规则项 149 | 150 | aP = aL + aR - Sp; 151 | 152 | Su = S_bar * V; 153 | Su[0] = T_A*(2*DA_L[0]) + S_bar * V[0]; 154 | Su[N-1] = T_B*(2*DA_R[N-1]) + S_bar * V[N-1]; 155 | 156 | for(int i = 0; i < N; i++) 157 | { 158 | if(i == 0) 159 | { 160 | A_m(i, i) = aP[i]; 161 | A_m(i, i+1) = -aR[i]; 162 | } 163 | else if(i == N-1) 164 | { 165 | A_m(i, i) = aP[i]; 166 | A_m(i, i-1) = -aL[i]; 167 | } 168 | else 169 | { 170 | A_m(i, i) = aP[i]; 171 | A_m(i, i-1) = -aL[i]; 172 | A_m(i, i+1) = -aR[i]; 173 | } 174 | } 175 | 176 | b_m = Su; 177 | 178 | cout << "A_m: " << endl << A_m << endl; 179 | cout << endl; 180 | 181 | cout << "b_m: " << endl << b_m << endl; 182 | cout << endl; 183 | } -------------------------------------------------------------------------------- /ref.data/u.@.y.txt: -------------------------------------------------------------------------------- 1 | # Ghia, U. K. N. G., Ghia, K. N., & Shin, C. T. (1982). 2 | # High-Re solutions for incompressible flow using the Navier-Stokes equations and a multigrid method. 3 | # Journal of computational physics, 48(3), 387-411. 4 | # 5 | # TABLE I 6 | # Results for $u$-velocity along Vertical Line through Geometric Center of Cavity 7 | #-------------------------------------------------------------------- 8 | # Re 9 | # ------------------------------------------------------------- 10 | # y 100 400 1000 3200 5000 7500 10000 11 | #-------------------------------------------------------------------- 12 | 1.0000 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 13 | 0.9766 0.84123 0.75837 0.65928 0.53236 0.48223 0.47244 0.47221 14 | 0.9688 0.78871 0.68439 0.57492 0.48296 0.46120 0.47048 0.47783 15 | 0.9609 0.73722 0.61756 0.51117 0.46547 0.45992 0.47323 0.48070 16 | 0.9531 0.68717 0.55892 0.46604 0.46101 0.46036 0.47167 0.47804 17 | 0.8516 0.23151 0.29093 0.33304 0.34682 0.33556 0.34228 0.34635 18 | 0.7344 0.00332 0.16256 0.18719 0.19791 0.20087 0.20591 0.20673 19 | 0.6172 -0.13641 0.02135 0.05702 0.07156 0.08183 0.08342 0.08344 20 | 0.5000 -0.20581 -0.11477 -0.06080 -0.04272 -0.03039 -0.03800 0.03111 21 | 0.4531 -0.21090 -0.17119 -0.10648 -0.86636 -0.07404 -0.07503 -0.07540 22 | 0.2813 -0.15662 -0.32726 -0.27805 -0.24427 -0.22855 -0.23176 -0.23186 23 | 0.1719 -0.10150 -0.24299 -0.38289 -0.34323 -0.33050 -0.32393 -0.32709 24 | 0.1016 -0.06434 -0.14612 -0.29730 -0.41933 -0.40435 -0.38324 -0.38000 25 | 0.0703 -0.04775 -0.10338 -0.22220 -0.37827 -0.43643 -0.43025 -0.41657 26 | 0.0625 -0.04192 -0.09266 -0.20196 -0.35344 -0.42901 -0.43590 -0.42537 27 | 0.0547 -0.03717 -0.08186 -0.18109 -0.32407 -0.41165 -0.43154 -0.42735 28 | 0.0000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 29 | 30 | # ref. https://gist.github.com/ivan-pi/3e9326d18a366ffe6a8e5bfda6353219 31 | 32 | # other ref. 33 | # https://www.openfoam.com/documentation/tutorial-guide/2-incompressible-flow/2.1-lid-driven-cavity-flow#x6-60002.1 34 | # https://www.acenumerics.com/the-benchmarks.html 35 | 36 | --- 37 | 38 | Table 2. Velocity components and vorticity values through the centrelines of the cavity at Re = 1000, computed at the locations given in [1] 39 | 40 | x = 0.5 y = 0.5 41 | y ux Ref. [1] ux ω Ref. [1] ω x uy Ref. [1] uy ω Ref. [1] ω 42 | 1 1 1 -14.7534 -14.7534 1 0 0 5.46217 5.46216 43 | 0.9766 0.6644227 0.6644227 -12.067 -12.0670 0.9688 -0.2279225 -0.2279225 8.4435 8.44350 44 | 0.9688 0.5808359 0.5808359 -9.49496 -9.49495 0.9609 -0.2936869 -0.2936869 8.24616 8.24616 45 | 0.9609 0.5169277 0.5169277 -6.95968 -6.95966 0.9531 -0.3553213 -0.3553213 7.58524 7.58524 46 | 0.9531 0.4723329 0.4723329 -4.85754 -4.85753 0.9453 -0.4103754 -0.4103754 6.50867 6.50867 47 | 0.8516 0.3372212 0.3372212 -1.762 -1.76199 0.9063 -0.5264392 -0.5264392 -0.92291 -0.92291 48 | 0.7344 0.1886747 0.1886747 -2.09121 -2.09121 0.8594 -0.4264545 -0.4264545 -3.43016 -3.43016 49 | 0.6172 0.0570178 0.0570178 -2.06539 -2.06539 0.8047 -0.3202137 -0.3202137 -2.21171 -2.21171 50 | 0.5 -0.0620561 -0.0620561 -2.06722 -2.06722 0.5 0.0257995 0.0257995 -2.06722 -2.06722 51 | 0.4531 -0.1081999 -0.1081999 -2.06215 -2.06215 0.2344 0.3253592 0.3253592 -2.06122 -2.06122 52 | 0.2813 -0.2803696 -0.2803696 -2.26772 -2.26772 0.2266 0.3339924 0.3339924 -2.00174 -2.00174 53 | 0.1719 -0.3885691 -0.3885691 -1.05467 -1.05466 0.1563 0.3769189 0.3769189 -0.74207 -0.74207 54 | 0.1016 -0.3004561 -0.3004561 1.63436 1.63436 0.0938 0.3330442 0.3330442 0.82398 0.82398 55 | 0.0703 -0.2228955 -0.2228955 2.20175 2.20175 0.0781 0.3099097 0.3099097 1.23991 1.23991 56 | 0.0625 -0.20233 -0.2023300 2.31786 2.31786 0.0703 0.2962703 0.2962703 1.50306 1.50306 57 | 0.0547 -0.1812881 -0.1812881 2.4496 2.44960 0.0625 0.2807056 0.2807056 1.83308 1.83308 58 | 0 0 0 4.16648 4.16648 0 0 0 7.66369 7.66368 59 | 60 | # ref. https://www.acenumerics.com/the-cavity-sessions-validation.html -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Inputs.h" 5 | #include "Mesh.h" 6 | #include "MatrixCoeff.h" 7 | #include "Field.h" 8 | #include "EnergyEqn.h" 9 | #include "XMomentumEqn.h" 10 | #include "YMomentumEqn.h" 11 | #include "Output.h" 12 | #include "PWIM.h" 13 | 14 | #define MAM_ITER 2000 15 | 16 | using Eigen::MatrixXd; 17 | using Eigen::VectorXd; 18 | using namespace std; 19 | 20 | int main() 21 | { 22 | // 读取数据 23 | Inputs* inputs = new Inputs("config.json"); 24 | 25 | // 创建网格 26 | Mesh* mesh = new Mesh(inputs); 27 | 28 | // 创建标量场 29 | Field* field = new Field(mesh->get_N()); 30 | 31 | // 初始化field 32 | field->u.setConstant(0.0); field->v.setConstant(0.0); 33 | field->p.setConstant(0.0); field->T.setConstant(0.0); 34 | field->u_e.setConstant(0.0); field->u_w.setConstant(0.0); 35 | field->v_n.setConstant(0.0); field->v_s.setConstant(0.0); 36 | 37 | //////////////////////////////// MomentumEqn ///////////////////////////////// 38 | // 创建动量方程系数矩阵 39 | MatrixCoeff* xMatrixCoeff = new MatrixCoeff(mesh); 40 | MatrixCoeff* yMatrixCoeff = new MatrixCoeff(mesh); 41 | 42 | // 获取边界条件与源项 43 | Boundary& boundary = inputs->boundary; 44 | Source& source = inputs->source; 45 | 46 | // 创建动量输运方程 47 | XMomentumEqn* xMomentumEqn = new XMomentumEqn(mesh, field, inputs, xMatrixCoeff, &boundary, &source); 48 | YMomentumEqn* yMomentumEqn = new YMomentumEqn(mesh, field, inputs, yMatrixCoeff, &boundary, &source); 49 | 50 | //=============================== Start Outer Loop Iteration ================================// 51 | 52 | // double tol_outer = 1.e-10; 53 | double tol_inner = 1.e-3; 54 | // double relax_momentum = 0.8; 55 | // double relax_pressure = 0.2; 56 | 57 | double res_u = 0.0; 58 | double res_v = 0.0; 59 | // double res_p = 0.0; 60 | 61 | PWIM pwim(inputs, field, mesh, xMatrixCoeff, yMatrixCoeff); 62 | 63 | // for(int iter = 0; iter < MAM_ITER; iter++) 64 | // { 65 | /* call links */ // 计算Link coefficient,并初始化矩阵系数 66 | 67 | xMomentumEqn->init(); // init_DA(), init_F() 68 | (*xMomentumEqn).addConvectionTerm().addDiffusionTerm().addSourceTerm(); 69 | 70 | yMomentumEqn->init(); 71 | (*yMomentumEqn).addConvectionTerm().addDiffusionTerm().addSourceTerm(); 72 | 73 | /* call solve_x_mom */ // 求解矩阵 74 | 75 | xMatrixCoeff->Solve(field->u, res_u, tol_inner); 76 | 77 | /* call solve_y_mom */ 78 | 79 | yMatrixCoeff->Solve(field->v, res_v, tol_inner); 80 | 81 | /* call face_velocity */ // Face Velocity using PWIM 82 | 83 | pwim.updateFaceVel(); 84 | 85 | /* call solve_pp */ 86 | 87 | /* call uv_correct */ 88 | 89 | /* call pres_correct */ 90 | 91 | // if(res_u < tol_outer && res_v < tol_outer && res_p < tol_outer) break; 92 | // } 93 | 94 | //================================ End Outer Loop Iteration =================================// 95 | 96 | // 变量输出 97 | Output out(mesh); 98 | out.write(field->u, boundary.U_left, boundary.U_right, boundary.U_top, boundary.U_bottom, "u"); 99 | out.write(field->v, boundary.V_left, boundary.V_right, boundary.V_top, boundary.V_bottom, "v"); 100 | //////////////////////////////// MomentumEqn ///////////////////////////////// 101 | 102 | //////////////////////////////// EnergyEqn ///////////////////////////////// 103 | // // 创建能量方程系数矩阵 104 | // MatrixCoeff* matrix_coeff = new MatrixCoeff(mesh); 105 | 106 | // // 获取边界条件与源项 107 | // Boundary& boundary = inputs->boundary; 108 | // Source& source = inputs->source; 109 | 110 | // // 创建能量输运方程 111 | // TransportEqn* eqn = new EnergyEqn(mesh, field, inputs, matrix_coeff, &boundary, &source); 112 | // eqn->init(); 113 | // (*eqn).addConvectionTerm().addDiffusionTerm().addSourceTerm(); 114 | 115 | // // 求解矩阵 116 | // // matrix_coeff->DebugSolve(&(field->T)); 117 | // matrix_coeff->Solve(&(field->T)); 118 | 119 | // // 变量输出 120 | // Output out(mesh); 121 | // out.write(field->T, boundary.T_left, boundary.T_right, boundary.T_top, boundary.T_bottom, "Temperature"); 122 | //////////////////////////////// EnergyEqn ///////////////////////////////// 123 | 124 | // delete matrix_coeff; 125 | // delete eqn; 126 | // delete field; 127 | // delete mesh; 128 | // delete inputs; 129 | } 130 | -------------------------------------------------------------------------------- /MatrixCoeff.h: -------------------------------------------------------------------------------- 1 | #ifndef __MATRIX_COEFF_H__ 2 | #define __MATRIX_COEFF_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Inputs.h" 8 | #include "Mesh.h" 9 | #include "MatrixWrapper.h" 10 | 11 | using Eigen::SparseMatrix; 12 | using Eigen::BiCGSTAB; 13 | using namespace std; 14 | 15 | template 16 | class MatrixCoeff 17 | { 18 | private: 19 | const Mesh* mesh; 20 | // 网格数量 21 | int N; 22 | 23 | VectorXd aW, aE, aS, aN, aO, SO, SE, SW, SN, SS, Su; 24 | 25 | VectorXd b_m; 26 | VectorXd x; 27 | 28 | /** 29 | * MatrixXd和SparseMatrix的封装类,封装后的Wrapper类共同继承接口MatrixInterface, 30 | * 并实现接口函数MatrixInterface::setNum,这个函数用来往矩阵中插入元素 31 | */ 32 | DenseMatrixWrapper dense_matrix_wrapper; 33 | SparseMatrixWrapper sparse_matrix_wrapper; 34 | 35 | double m_res; 36 | double epsilon; 37 | 38 | friend T; 39 | public: 40 | MatrixCoeff(const Mesh* mesh) 41 | : mesh(mesh), N(mesh->get_N()) 42 | { 43 | aW = VectorXd::Zero(N); 44 | aE = VectorXd::Zero(N); 45 | aS = VectorXd::Zero(N); 46 | aN = VectorXd::Zero(N); 47 | aO = VectorXd::Zero(N); 48 | 49 | SO = VectorXd::Zero(N); 50 | SE = VectorXd::Zero(N); 51 | SW = VectorXd::Zero(N); 52 | SN = VectorXd::Zero(N); 53 | SS = VectorXd::Zero(N); 54 | 55 | Su = VectorXd::Zero(N); 56 | 57 | b_m = VectorXd::Zero(N); 58 | x = VectorXd::Zero(N); 59 | 60 | m_res = 0.0; 61 | epsilon = 1.e-10; 62 | } 63 | 64 | VectorXd& get_b_m() { return b_m; } 65 | VectorXd& get_x() { return x; } 66 | VectorXd& get_aO() { return aO; } 67 | 68 | // MatrixXd系数初始化 69 | void initDenseMatrix(); 70 | 71 | // SparseMatrix系数初始化 72 | void initSparseMatrix(); 73 | 74 | void init(MatrixInterface* matrix); 75 | 76 | // 系数矩阵存在非稀疏矩阵MatrixXd中,方便打印输出 77 | void DebugSolve(VectorXd& field_var); 78 | 79 | // 系数矩阵存在稀疏矩阵SparseMatrix中,用于迭代求解 80 | void Solve(VectorXd& field_var, double& res, double tolerance = 1.e-10); 81 | }; 82 | 83 | template 84 | void MatrixCoeff::initDenseMatrix() 85 | { 86 | dense_matrix_wrapper = DenseMatrixWrapper(N, N); 87 | 88 | init(&dense_matrix_wrapper); 89 | 90 | b_m = Su; 91 | } 92 | 93 | template 94 | void MatrixCoeff::initSparseMatrix() 95 | { 96 | sparse_matrix_wrapper = SparseMatrixWrapper(N, N); 97 | 98 | SparseMatrix& A_m = sparse_matrix_wrapper.getMatrix(); 99 | 100 | // 每列预留5个元素的空间,用于插入 101 | // ref. http://eigen.tuxfamily.org/dox/group__TutorialSparse.html - Filling a sparse matrix 102 | A_m.reserve(VectorXi::Constant(N, 5)); 103 | 104 | init(&sparse_matrix_wrapper); 105 | 106 | A_m.makeCompressed(); // optional 107 | 108 | b_m = Su; 109 | } 110 | 111 | template 112 | void MatrixCoeff::init(MatrixInterface* matrix) 113 | { 114 | for(int i = 0; i < N; i++) 115 | { 116 | int i_l = mesh->left_of(i); 117 | int i_r = mesh->right_of(i); 118 | int i_t = mesh->top_of(i); 119 | int i_b = mesh->bottom_of(i); 120 | 121 | matrix->setNum(i, i, aO[i]); 122 | 123 | if(!mesh->is_at_left_boundary(i)) 124 | { 125 | matrix->setNum(i, i_l, -(aW[i] - SW[i])); 126 | } 127 | if(!mesh->is_at_right_boundary(i)) 128 | { 129 | matrix->setNum(i, i_r, -(aE[i] - SE[i])); 130 | } 131 | if(!mesh->is_at_bottom_boundary(i)) 132 | { 133 | matrix->setNum(i, i_b, -(aS[i] - SS[i])); 134 | } 135 | if(!mesh->is_at_top_boundary(i)) 136 | { 137 | matrix->setNum(i, i_t, -(aN[i] - SN[i])); 138 | } 139 | } 140 | } 141 | 142 | template 143 | void MatrixCoeff::DebugSolve(VectorXd& field_var) 144 | { 145 | initDenseMatrix(); 146 | 147 | MatrixXd& A_m = dense_matrix_wrapper.getMatrix(); 148 | 149 | // 输出结果 150 | cout << "A_m: " << endl; 151 | // for(int i = 0; i < A_m.rows(); i++) 152 | // { 153 | // for(int j = 0; j < A_m.cols(); j++) 154 | // { 155 | // cout << A_m(i, j) << ", "; 156 | // } 157 | // cout << endl; 158 | // } 159 | cout << A_m << endl; 160 | cout << endl; 161 | 162 | // 求解矩阵 163 | field_var = A_m.fullPivLu().solve(b_m); 164 | 165 | cout << "b_m: " << endl << b_m << endl; 166 | cout << endl; 167 | 168 | cout << "Solution: " << endl << field_var << endl; 169 | } 170 | 171 | template 172 | void MatrixCoeff::Solve(VectorXd& field_var, double& res, double tolerance) 173 | { 174 | initSparseMatrix(); 175 | 176 | SparseMatrix& A_m = sparse_matrix_wrapper.getMatrix(); 177 | VectorXd& x = field_var; 178 | 179 | // 计算残差 180 | m_res = (b_m - A_m * x).norm(); 181 | res = m_res; 182 | 183 | if(res < epsilon) return; 184 | 185 | // ref. http://eigen.tuxfamily.org/dox/classEigen_1_1BiCGSTAB.html 186 | // ref. http://eigen.tuxfamily.org/dox/group__TopicSparseSystems.html#TutorialSparseSolverConcept 187 | // ref. http://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html 188 | 189 | // BiCGSTAB, Eigen::IdentityPreconditioner> solver; 190 | BiCGSTAB, Eigen::IncompleteLUT> solver; 191 | solver.compute(A_m).setTolerance(tolerance); 192 | x = solver.solve(b_m); 193 | 194 | std::cout << "# inner iterations: " << solver.iterations() << std::endl; 195 | std::cout << "estimated error: " << solver.error() << std::endl; 196 | 197 | // std::cout << "Solution: " << std::endl << x << std::endl; 198 | } 199 | 200 | #endif -------------------------------------------------------------------------------- /docs/plot_notes.md: -------------------------------------------------------------------------------- 1 | # Python科学绘图技巧详解 2 | 3 | 本笔记基于CFD数据可视化脚本,详细介绍Python绘图中的关键技巧和数据处理方法。 4 | 5 | ## 1. 库导入和后端设置 6 | 7 | ### 1.1 matplotlib后端设置 8 | ```python 9 | import matplotlib 10 | matplotlib.use('Agg') # 使用非交互式后端 11 | ``` 12 | 13 | **技巧解释:** 14 | - `Agg`后端:Anti-Grain Geometry,用于生成光栅图像(PNG、JPG等) 15 | - 非交互式后端:不显示图形窗口,适合服务器环境或批量处理 16 | - 其他常用后端:`TkAgg`(交互式)、`Qt5Agg`(交互式) 17 | 18 | ### 1.2 中文字体配置 19 | ```python 20 | plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS', 'Liberation Sans'] 21 | plt.rcParams['axes.unicode_minus'] = False 22 | ``` 23 | 24 | **技巧解释:** 25 | - `rcParams`:matplotlib的全局配置字典 26 | - 字体优先级列表:系统会按顺序尝试字体 27 | - `unicode_minus`:解决中文环境下负号显示问题 28 | 29 | ## 2. 数据读取和预处理 30 | 31 | ### 2.1 CSV数据读取 32 | ```python 33 | df = pd.read_csv('../u.csv', skipinitialspace=True) 34 | ``` 35 | 36 | **参数说明:** 37 | - `skipinitialspace=True`:自动去除分隔符后的空格 38 | - 适用于格式不规范的CSV文件 39 | 40 | ### 2.2 数据提取和类型转换 41 | ```python 42 | x = np.array(df['x']) 43 | y = np.array(df['y']) 44 | u = np.array(df['u']) 45 | ``` 46 | 47 | **数据结构说明:** 48 | - `pandas.Series` → `numpy.array`转换 49 | - numpy数组优势:更快的数值计算、内存效率更高 50 | 51 | **示例:** 52 | ```python 53 | # DataFrame结构示例 54 | # x y u 55 | # 0 0.1 0.1 0.001 56 | # 1 0.2 0.1 0.002 57 | # 2 0.1 0.2 0.003 58 | 59 | # 转换后的numpy数组 60 | x = [0.1, 0.2, 0.1] # 一维数组 61 | y = [0.1, 0.1, 0.2] # 一维数组 62 | u = [0.001, 0.002, 0.003] # 一维数组 63 | ``` 64 | 65 | ## 3. 网格生成和数据插值 66 | 67 | ### 3.1 唯一值提取和网格生成 68 | ```python 69 | x_unique = np.unique(x) 70 | y_unique = np.unique(y) 71 | X, Y = np.meshgrid(x_unique, y_unique) 72 | ``` 73 | 74 | **数据结构详解:** 75 | 76 | **np.unique()示例:** 77 | ```python 78 | x = [0.1, 0.2, 0.1, 0.3, 0.2] 79 | x_unique = np.unique(x) # [0.1, 0.2, 0.3] 80 | ``` 81 | 82 | **np.meshgrid()详解:** 83 | ```python 84 | x_unique = [0, 1, 2] 85 | y_unique = [0, 1] 86 | 87 | X, Y = np.meshgrid(x_unique, y_unique) 88 | 89 | # X矩阵(每行相同): 90 | # [[0, 1, 2], 91 | # [0, 1, 2]] 92 | 93 | # Y矩阵(每列相同): 94 | # [[0, 0, 0], 95 | # [1, 1, 1]] 96 | ``` 97 | 98 | **用途:** 99 | - 创建规则网格,用于等高线图和3D绘图 100 | - X、Y矩阵的每个对应位置(i,j)代表一个网格点坐标 101 | 102 | ### 3.2 散点数据插值 103 | ```python 104 | U = griddata((x, y), u, (X, Y), method='linear') 105 | ``` 106 | 107 | **griddata函数详解:** 108 | - `(x, y)`:已知散点的坐标 109 | - `u`:已知散点的数值 110 | - `(X, Y)`:目标网格点坐标 111 | - `method='linear'`:线性插值方法 112 | 113 | **插值方法对比:** 114 | ```python 115 | # 线性插值:速度快,平滑度一般 116 | U_linear = griddata((x, y), u, (X, Y), method='linear') 117 | 118 | # 立方插值:更平滑,计算量大 119 | U_cubic = griddata((x, y), u, (X, Y), method='cubic') 120 | 121 | # 最近邻插值:保持原始数据特征 122 | U_nearest = griddata((x, y), u, (X, Y), method='nearest') 123 | ``` 124 | 125 | ## 4. 等高线图绘制技巧 126 | 127 | ### 4.1 contourf函数详解 128 | ```python 129 | cs = plt.contourf(X, Y, U, levels=40, cmap='viridis') 130 | ``` 131 | 132 | **参数说明:** 133 | - `X, Y`:网格坐标矩阵 134 | - `U`:对应的数值矩阵 135 | - `levels=40`:等高线数量(或自定义等高线值列表) 136 | - `cmap='viridis'`:颜色映射 137 | 138 | **levels参数的不同用法:** 139 | ```python 140 | # 方法1:指定等高线数量 141 | cs = plt.contourf(X, Y, U, levels=20) 142 | 143 | # 方法2:指定具体等高线值 144 | cs = plt.contourf(X, Y, U, levels=[0, 0.005, 0.01, 0.015, 0.02]) 145 | 146 | # 方法3:使用numpy生成等间距值 147 | cs = plt.contourf(X, Y, U, levels=np.linspace(U.min(), U.max(), 30)) 148 | ``` 149 | 150 | ### 4.2 颜色映射(colormap)选择 151 | ```python 152 | # 科学可视化推荐色彩 153 | cmap='viridis' # 感知均匀,色盲友好 154 | cmap='plasma' # 高对比度 155 | cmap='coolwarm' # 双极数据(正负值) 156 | cmap='RdYlBu_r' # 传统彩虹色(反向) 157 | ``` 158 | 159 | ## 5. 图形美化技巧 160 | 161 | ### 5.1 坐标轴设置 162 | ```python 163 | plt.axis('equal') # 等比例坐标轴 164 | plt.xlabel('x (m)') # 带单位的标签 165 | plt.ylabel('y (m)') 166 | ``` 167 | 168 | **axis参数详解:** 169 | ```python 170 | plt.axis('equal') # x、y轴比例相等 171 | plt.axis('scaled') # 类似equal,但允许缩放 172 | plt.axis('tight') # 紧贴数据范围 173 | plt.axis('off') # 关闭坐标轴 174 | ``` 175 | 176 | ### 5.2 颜色条(colorbar)定制 177 | ```python 178 | cbar = plt.colorbar(cs, label='u (m/s)', shrink=0.8) 179 | cbar.ax.tick_params(labelsize=10) 180 | ``` 181 | 182 | **颜色条参数:** 183 | - `shrink=0.8`:缩放至原高度的80% 184 | - `label`:颜色条标签 185 | - `orientation='horizontal'`:水平放置 186 | - `pad=0.1`:与主图的间距 187 | 188 | ### 5.3 文本标注技巧 189 | ```python 190 | plt.text(0.5, 1.08, 'U_top = 0.01 m/s', 191 | transform=plt.gca().transAxes, 192 | ha='center', fontsize=10, 193 | bbox=dict(boxstyle="round,pad=0.3", facecolor="yellow", alpha=0.7)) 194 | ``` 195 | 196 | **坐标系统详解:** 197 | - `transform=plt.gca().transAxes`:使用轴坐标系(0-1范围) 198 | - `transform=None`:使用数据坐标系(默认) 199 | 200 | **文本对齐参数:** 201 | ```python 202 | ha='center' # 水平对齐:'left', 'center', 'right' 203 | va='center' # 垂直对齐:'bottom', 'center', 'top' 204 | rotation=90 # 旋转角度 205 | ``` 206 | 207 | **文本框样式:** 208 | ```python 209 | bbox=dict( 210 | boxstyle="round,pad=0.3", # 圆角矩形,内边距0.3 211 | facecolor="yellow", # 背景色 212 | alpha=0.7, # 透明度 213 | edgecolor="black", # 边框色 214 | linewidth=1 # 边框宽度 215 | ) 216 | ``` 217 | 218 | ## 6. 图形输出和保存 219 | 220 | ### 6.1 高质量图像保存 221 | ```python 222 | plt.savefig('u_velocity_contour.png', dpi=300, bbox_inches='tight') 223 | ``` 224 | 225 | **保存参数详解:** 226 | - `dpi=300`:分辨率,300 DPI适合印刷 227 | - `bbox_inches='tight'`:自动裁剪空白边缘 228 | - `facecolor='white'`:设置背景色 229 | - `transparent=True`:透明背景 230 | 231 | **不同格式对比:** 232 | ```python 233 | plt.savefig('figure.png', dpi=300) # 光栅图,适合网页 234 | plt.savefig('figure.pdf') # 矢量图,适合印刷 235 | plt.savefig('figure.svg') # 矢量图,适合网页 236 | plt.savefig('figure.eps') # 矢量图,适合学术期刊 237 | ``` 238 | 239 | ## 7. 数据分析和统计 240 | 241 | ### 7.1 数组统计函数 242 | ```python 243 | print(f"U velocity range: [{u.min():.6f}, {u.max():.6f}]") 244 | print(f"Max velocity location: x={x[np.argmax(u)]:.3f}, y={y[np.argmax(u)]:.3f}") 245 | ``` 246 | 247 | **常用统计函数:** 248 | ```python 249 | u.min() # 最小值 250 | u.max() # 最大值 251 | u.mean() # 平均值 252 | u.std() # 标准差 253 | np.argmin(u) # 最小值索引 254 | np.argmax(u) # 最大值索引 255 | np.percentile(u, 95) # 95百分位数 256 | ``` 257 | 258 | ### 7.2 字符串格式化技巧 259 | ```python 260 | # f-string格式化(Python 3.6+) 261 | print(f"Value: {value:.3f}") # 保留3位小数 262 | print(f"Count: {count:,}") # 千位分隔符 263 | print(f"Percent: {ratio:.2%}") # 百分比格式 264 | 265 | # 科学计数法 266 | print(f"Scientific: {value:.2e}") # 2.34e-05 267 | ``` 268 | 269 | ## 8. 高级技巧和最佳实践 270 | 271 | ### 8.1 内存优化 272 | ```python 273 | # 对于大数据集,使用视图而不是副本 274 | x_view = df['x'].values # 直接获取numpy数组 275 | y_view = df['y'].values # 避免额外的转换开销 276 | ``` 277 | 278 | ### 8.2 错误处理 279 | ```python 280 | try: 281 | U = griddata((x, y), u, (X, Y), method='linear') 282 | # 检查插值结果 283 | if np.all(np.isnan(U)): 284 | print("Warning: All interpolated values are NaN") 285 | U = griddata((x, y), u, (X, Y), method='nearest') 286 | except Exception as e: 287 | print(f"Interpolation failed: {e}") 288 | ``` 289 | 290 | ### 8.3 性能优化建议 291 | ```python 292 | # 1. 预分配数组大小 293 | n_points = len(x) 294 | result = np.empty(n_points) 295 | 296 | # 2. 使用向量化操作 297 | u_normalized = (u - u.min()) / (u.max() - u.min()) # 而不是循环 298 | 299 | # 3. 适当的数据类型 300 | x = x.astype(np.float32) # 如果精度允许,使用float32节省内存 301 | ``` 302 | 303 | ## 9. 总结 304 | 305 | 本脚本展示了科学计算可视化的典型流程: 306 | 1. **数据预处理**:清洗、转换数据格式 307 | 2. **网格化**:将散乱数据插值到规则网格 308 | 3. **可视化**:使用等高线图展示空间分布 309 | 4. **美化**:添加标签、颜色条、注释 310 | 5. **输出**:保存高质量图像 311 | 312 | 这些技巧广泛应用于CFD、气象学、地质学等领域的数据可视化工作。 -------------------------------------------------------------------------------- /v.csv: -------------------------------------------------------------------------------- 1 | x, y, z, v 2 | 0, 0, 0, 0 3 | 0.02, 0, 0, 0 4 | 0.04, 0, 0, 0 5 | 0.06, 0, 0, 0 6 | 0.08, 0, 0, 0 7 | 0.1, 0, 0, 0 8 | 0.12, 0, 0, 0 9 | 0.14, 0, 0, 0 10 | 0.16, 0, 0, 0 11 | 0.18, 0, 0, 0 12 | 0.2, 0, 0, 0 13 | 0.22, 0, 0, 0 14 | 0.24, 0, 0, 0 15 | 0.26, 0, 0, 0 16 | 0.28, 0, 0, 0 17 | 0.3, 0, 0, 0 18 | 0.32, 0, 0, 0 19 | 0.34, 0, 0, 0 20 | 0.36, 0, 0, 0 21 | 0.38, 0, 0, 0 22 | 0.4, 0, 0, 0 23 | 0.42, 0, 0, 0 24 | 0.44, 0, 0, 0 25 | 0.46, 0, 0, 0 26 | 0.48, 0, 0, 0 27 | 0.5, 0, 0, 0 28 | 0.52, 0, 0, 0 29 | 0.54, 0, 0, 0 30 | 0.56, 0, 0, 0 31 | 0.58, 0, 0, 0 32 | 0.6, 0, 0, 0 33 | 0.62, 0, 0, 0 34 | 0.64, 0, 0, 0 35 | 0.66, 0, 0, 0 36 | 0.68, 0, 0, 0 37 | 0.7, 0, 0, 0 38 | 0.72, 0, 0, 0 39 | 0.74, 0, 0, 0 40 | 0.76, 0, 0, 0 41 | 0.78, 0, 0, 0 42 | 0.8, 0, 0, 0 43 | 0.82, 0, 0, 0 44 | 0.84, 0, 0, 0 45 | 0.86, 0, 0, 0 46 | 0.88, 0, 0, 0 47 | 0.9, 0, 0, 0 48 | 0.92, 0, 0, 0 49 | 0.94, 0, 0, 0 50 | 0.96, 0, 0, 0 51 | 0.98, 0, 0, 0 52 | 1, 0, 0, 0 53 | 0, 1, 0, 0 54 | 0.02, 1, 0, 0 55 | 0.04, 1, 0, 0 56 | 0.06, 1, 0, 0 57 | 0.08, 1, 0, 0 58 | 0.1, 1, 0, 0 59 | 0.12, 1, 0, 0 60 | 0.14, 1, 0, 0 61 | 0.16, 1, 0, 0 62 | 0.18, 1, 0, 0 63 | 0.2, 1, 0, 0 64 | 0.22, 1, 0, 0 65 | 0.24, 1, 0, 0 66 | 0.26, 1, 0, 0 67 | 0.28, 1, 0, 0 68 | 0.3, 1, 0, 0 69 | 0.32, 1, 0, 0 70 | 0.34, 1, 0, 0 71 | 0.36, 1, 0, 0 72 | 0.38, 1, 0, 0 73 | 0.4, 1, 0, 0 74 | 0.42, 1, 0, 0 75 | 0.44, 1, 0, 0 76 | 0.46, 1, 0, 0 77 | 0.48, 1, 0, 0 78 | 0.5, 1, 0, 0 79 | 0.52, 1, 0, 0 80 | 0.54, 1, 0, 0 81 | 0.56, 1, 0, 0 82 | 0.58, 1, 0, 0 83 | 0.6, 1, 0, 0 84 | 0.62, 1, 0, 0 85 | 0.64, 1, 0, 0 86 | 0.66, 1, 0, 0 87 | 0.68, 1, 0, 0 88 | 0.7, 1, 0, 0 89 | 0.72, 1, 0, 0 90 | 0.74, 1, 0, 0 91 | 0.76, 1, 0, 0 92 | 0.78, 1, 0, 0 93 | 0.8, 1, 0, 0 94 | 0.82, 1, 0, 0 95 | 0.84, 1, 0, 0 96 | 0.86, 1, 0, 0 97 | 0.88, 1, 0, 0 98 | 0.9, 1, 0, 0 99 | 0.92, 1, 0, 0 100 | 0.94, 1, 0, 0 101 | 0.96, 1, 0, 0 102 | 0.98, 1, 0, 0 103 | 1, 1, 0, 0 104 | 0, 0.04, 0, 0 105 | 0, 0.08, 0, 0 106 | 0, 0.12, 0, 0 107 | 0, 0.16, 0, 0 108 | 0, 0.2, 0, 0 109 | 0, 0.24, 0, 0 110 | 0, 0.28, 0, 0 111 | 0, 0.32, 0, 0 112 | 0, 0.36, 0, 0 113 | 0, 0.4, 0, 0 114 | 0, 0.44, 0, 0 115 | 0, 0.48, 0, 0 116 | 0, 0.52, 0, 0 117 | 0, 0.56, 0, 0 118 | 0, 0.6, 0, 0 119 | 0, 0.64, 0, 0 120 | 0, 0.68, 0, 0 121 | 0, 0.72, 0, 0 122 | 0, 0.76, 0, 0 123 | 0, 0.8, 0, 0 124 | 0, 0.84, 0, 0 125 | 0, 0.88, 0, 0 126 | 0, 0.92, 0, 0 127 | 0, 0.96, 0, 0 128 | 1, 0.04, 0, 0 129 | 1, 0.08, 0, 0 130 | 1, 0.12, 0, 0 131 | 1, 0.16, 0, 0 132 | 1, 0.2, 0, 0 133 | 1, 0.24, 0, 0 134 | 1, 0.28, 0, 0 135 | 1, 0.32, 0, 0 136 | 1, 0.36, 0, 0 137 | 1, 0.4, 0, 0 138 | 1, 0.44, 0, 0 139 | 1, 0.48, 0, 0 140 | 1, 0.52, 0, 0 141 | 1, 0.56, 0, 0 142 | 1, 0.6, 0, 0 143 | 1, 0.64, 0, 0 144 | 1, 0.68, 0, 0 145 | 1, 0.72, 0, 0 146 | 1, 0.76, 0, 0 147 | 1, 0.8, 0, 0 148 | 1, 0.84, 0, 0 149 | 1, 0.88, 0, 0 150 | 1, 0.92, 0, 0 151 | 1, 0.96, 0, 0 152 | 0.02, 0.04, 0, 0 153 | 0.04, 0.04, 0, 0 154 | 0.06, 0.04, 0, 0 155 | 0.08, 0.04, 0, 0 156 | 0.1, 0.04, 0, 0 157 | 0.12, 0.04, 0, 0 158 | 0.14, 0.04, 0, 0 159 | 0.16, 0.04, 0, 0 160 | 0.18, 0.04, 0, 0 161 | 0.2, 0.04, 0, 0 162 | 0.22, 0.04, 0, 0 163 | 0.24, 0.04, 0, 0 164 | 0.26, 0.04, 0, 0 165 | 0.28, 0.04, 0, 0 166 | 0.3, 0.04, 0, 0 167 | 0.32, 0.04, 0, 0 168 | 0.34, 0.04, 0, 0 169 | 0.36, 0.04, 0, 0 170 | 0.38, 0.04, 0, 0 171 | 0.4, 0.04, 0, 0 172 | 0.42, 0.04, 0, 0 173 | 0.44, 0.04, 0, 0 174 | 0.46, 0.04, 0, 0 175 | 0.48, 0.04, 0, 0 176 | 0.5, 0.04, 0, 0 177 | 0.52, 0.04, 0, 0 178 | 0.54, 0.04, 0, 0 179 | 0.56, 0.04, 0, 0 180 | 0.58, 0.04, 0, 0 181 | 0.6, 0.04, 0, 0 182 | 0.62, 0.04, 0, 0 183 | 0.64, 0.04, 0, 0 184 | 0.66, 0.04, 0, 0 185 | 0.68, 0.04, 0, 0 186 | 0.7, 0.04, 0, 0 187 | 0.72, 0.04, 0, 0 188 | 0.74, 0.04, 0, 0 189 | 0.76, 0.04, 0, 0 190 | 0.78, 0.04, 0, 0 191 | 0.8, 0.04, 0, 0 192 | 0.82, 0.04, 0, 0 193 | 0.84, 0.04, 0, 0 194 | 0.86, 0.04, 0, 0 195 | 0.88, 0.04, 0, 0 196 | 0.9, 0.04, 0, 0 197 | 0.92, 0.04, 0, 0 198 | 0.94, 0.04, 0, 0 199 | 0.96, 0.04, 0, 0 200 | 0.98, 0.04, 0, 0 201 | 0.02, 0.08, 0, 0 202 | 0.04, 0.08, 0, 0 203 | 0.06, 0.08, 0, 0 204 | 0.08, 0.08, 0, 0 205 | 0.1, 0.08, 0, 0 206 | 0.12, 0.08, 0, 0 207 | 0.14, 0.08, 0, 0 208 | 0.16, 0.08, 0, 0 209 | 0.18, 0.08, 0, 0 210 | 0.2, 0.08, 0, 0 211 | 0.22, 0.08, 0, 0 212 | 0.24, 0.08, 0, 0 213 | 0.26, 0.08, 0, 0 214 | 0.28, 0.08, 0, 0 215 | 0.3, 0.08, 0, 0 216 | 0.32, 0.08, 0, 0 217 | 0.34, 0.08, 0, 0 218 | 0.36, 0.08, 0, 0 219 | 0.38, 0.08, 0, 0 220 | 0.4, 0.08, 0, 0 221 | 0.42, 0.08, 0, 0 222 | 0.44, 0.08, 0, 0 223 | 0.46, 0.08, 0, 0 224 | 0.48, 0.08, 0, 0 225 | 0.5, 0.08, 0, 0 226 | 0.52, 0.08, 0, 0 227 | 0.54, 0.08, 0, 0 228 | 0.56, 0.08, 0, 0 229 | 0.58, 0.08, 0, 0 230 | 0.6, 0.08, 0, 0 231 | 0.62, 0.08, 0, 0 232 | 0.64, 0.08, 0, 0 233 | 0.66, 0.08, 0, 0 234 | 0.68, 0.08, 0, 0 235 | 0.7, 0.08, 0, 0 236 | 0.72, 0.08, 0, 0 237 | 0.74, 0.08, 0, 0 238 | 0.76, 0.08, 0, 0 239 | 0.78, 0.08, 0, 0 240 | 0.8, 0.08, 0, 0 241 | 0.82, 0.08, 0, 0 242 | 0.84, 0.08, 0, 0 243 | 0.86, 0.08, 0, 0 244 | 0.88, 0.08, 0, 0 245 | 0.9, 0.08, 0, 0 246 | 0.92, 0.08, 0, 0 247 | 0.94, 0.08, 0, 0 248 | 0.96, 0.08, 0, 0 249 | 0.98, 0.08, 0, 0 250 | 0.02, 0.12, 0, 0 251 | 0.04, 0.12, 0, 0 252 | 0.06, 0.12, 0, 0 253 | 0.08, 0.12, 0, 0 254 | 0.1, 0.12, 0, 0 255 | 0.12, 0.12, 0, 0 256 | 0.14, 0.12, 0, 0 257 | 0.16, 0.12, 0, 0 258 | 0.18, 0.12, 0, 0 259 | 0.2, 0.12, 0, 0 260 | 0.22, 0.12, 0, 0 261 | 0.24, 0.12, 0, 0 262 | 0.26, 0.12, 0, 0 263 | 0.28, 0.12, 0, 0 264 | 0.3, 0.12, 0, 0 265 | 0.32, 0.12, 0, 0 266 | 0.34, 0.12, 0, 0 267 | 0.36, 0.12, 0, 0 268 | 0.38, 0.12, 0, 0 269 | 0.4, 0.12, 0, 0 270 | 0.42, 0.12, 0, 0 271 | 0.44, 0.12, 0, 0 272 | 0.46, 0.12, 0, 0 273 | 0.48, 0.12, 0, 0 274 | 0.5, 0.12, 0, 0 275 | 0.52, 0.12, 0, 0 276 | 0.54, 0.12, 0, 0 277 | 0.56, 0.12, 0, 0 278 | 0.58, 0.12, 0, 0 279 | 0.6, 0.12, 0, 0 280 | 0.62, 0.12, 0, 0 281 | 0.64, 0.12, 0, 0 282 | 0.66, 0.12, 0, 0 283 | 0.68, 0.12, 0, 0 284 | 0.7, 0.12, 0, 0 285 | 0.72, 0.12, 0, 0 286 | 0.74, 0.12, 0, 0 287 | 0.76, 0.12, 0, 0 288 | 0.78, 0.12, 0, 0 289 | 0.8, 0.12, 0, 0 290 | 0.82, 0.12, 0, 0 291 | 0.84, 0.12, 0, 0 292 | 0.86, 0.12, 0, 0 293 | 0.88, 0.12, 0, 0 294 | 0.9, 0.12, 0, 0 295 | 0.92, 0.12, 0, 0 296 | 0.94, 0.12, 0, 0 297 | 0.96, 0.12, 0, 0 298 | 0.98, 0.12, 0, 0 299 | 0.02, 0.16, 0, 0 300 | 0.04, 0.16, 0, 0 301 | 0.06, 0.16, 0, 0 302 | 0.08, 0.16, 0, 0 303 | 0.1, 0.16, 0, 0 304 | 0.12, 0.16, 0, 0 305 | 0.14, 0.16, 0, 0 306 | 0.16, 0.16, 0, 0 307 | 0.18, 0.16, 0, 0 308 | 0.2, 0.16, 0, 0 309 | 0.22, 0.16, 0, 0 310 | 0.24, 0.16, 0, 0 311 | 0.26, 0.16, 0, 0 312 | 0.28, 0.16, 0, 0 313 | 0.3, 0.16, 0, 0 314 | 0.32, 0.16, 0, 0 315 | 0.34, 0.16, 0, 0 316 | 0.36, 0.16, 0, 0 317 | 0.38, 0.16, 0, 0 318 | 0.4, 0.16, 0, 0 319 | 0.42, 0.16, 0, 0 320 | 0.44, 0.16, 0, 0 321 | 0.46, 0.16, 0, 0 322 | 0.48, 0.16, 0, 0 323 | 0.5, 0.16, 0, 0 324 | 0.52, 0.16, 0, 0 325 | 0.54, 0.16, 0, 0 326 | 0.56, 0.16, 0, 0 327 | 0.58, 0.16, 0, 0 328 | 0.6, 0.16, 0, 0 329 | 0.62, 0.16, 0, 0 330 | 0.64, 0.16, 0, 0 331 | 0.66, 0.16, 0, 0 332 | 0.68, 0.16, 0, 0 333 | 0.7, 0.16, 0, 0 334 | 0.72, 0.16, 0, 0 335 | 0.74, 0.16, 0, 0 336 | 0.76, 0.16, 0, 0 337 | 0.78, 0.16, 0, 0 338 | 0.8, 0.16, 0, 0 339 | 0.82, 0.16, 0, 0 340 | 0.84, 0.16, 0, 0 341 | 0.86, 0.16, 0, 0 342 | 0.88, 0.16, 0, 0 343 | 0.9, 0.16, 0, 0 344 | 0.92, 0.16, 0, 0 345 | 0.94, 0.16, 0, 0 346 | 0.96, 0.16, 0, 0 347 | 0.98, 0.16, 0, 0 348 | 0.02, 0.2, 0, 0 349 | 0.04, 0.2, 0, 0 350 | 0.06, 0.2, 0, 0 351 | 0.08, 0.2, 0, 0 352 | 0.1, 0.2, 0, 0 353 | 0.12, 0.2, 0, 0 354 | 0.14, 0.2, 0, 0 355 | 0.16, 0.2, 0, 0 356 | 0.18, 0.2, 0, 0 357 | 0.2, 0.2, 0, 0 358 | 0.22, 0.2, 0, 0 359 | 0.24, 0.2, 0, 0 360 | 0.26, 0.2, 0, 0 361 | 0.28, 0.2, 0, 0 362 | 0.3, 0.2, 0, 0 363 | 0.32, 0.2, 0, 0 364 | 0.34, 0.2, 0, 0 365 | 0.36, 0.2, 0, 0 366 | 0.38, 0.2, 0, 0 367 | 0.4, 0.2, 0, 0 368 | 0.42, 0.2, 0, 0 369 | 0.44, 0.2, 0, 0 370 | 0.46, 0.2, 0, 0 371 | 0.48, 0.2, 0, 0 372 | 0.5, 0.2, 0, 0 373 | 0.52, 0.2, 0, 0 374 | 0.54, 0.2, 0, 0 375 | 0.56, 0.2, 0, 0 376 | 0.58, 0.2, 0, 0 377 | 0.6, 0.2, 0, 0 378 | 0.62, 0.2, 0, 0 379 | 0.64, 0.2, 0, 0 380 | 0.66, 0.2, 0, 0 381 | 0.68, 0.2, 0, 0 382 | 0.7, 0.2, 0, 0 383 | 0.72, 0.2, 0, 0 384 | 0.74, 0.2, 0, 0 385 | 0.76, 0.2, 0, 0 386 | 0.78, 0.2, 0, 0 387 | 0.8, 0.2, 0, 0 388 | 0.82, 0.2, 0, 0 389 | 0.84, 0.2, 0, 0 390 | 0.86, 0.2, 0, 0 391 | 0.88, 0.2, 0, 0 392 | 0.9, 0.2, 0, 0 393 | 0.92, 0.2, 0, 0 394 | 0.94, 0.2, 0, 0 395 | 0.96, 0.2, 0, 0 396 | 0.98, 0.2, 0, 0 397 | 0.02, 0.24, 0, 0 398 | 0.04, 0.24, 0, 0 399 | 0.06, 0.24, 0, 0 400 | 0.08, 0.24, 0, 0 401 | 0.1, 0.24, 0, 0 402 | 0.12, 0.24, 0, 0 403 | 0.14, 0.24, 0, 0 404 | 0.16, 0.24, 0, 0 405 | 0.18, 0.24, 0, 0 406 | 0.2, 0.24, 0, 0 407 | 0.22, 0.24, 0, 0 408 | 0.24, 0.24, 0, 0 409 | 0.26, 0.24, 0, 0 410 | 0.28, 0.24, 0, 0 411 | 0.3, 0.24, 0, 0 412 | 0.32, 0.24, 0, 0 413 | 0.34, 0.24, 0, 0 414 | 0.36, 0.24, 0, 0 415 | 0.38, 0.24, 0, 0 416 | 0.4, 0.24, 0, 0 417 | 0.42, 0.24, 0, 0 418 | 0.44, 0.24, 0, 0 419 | 0.46, 0.24, 0, 0 420 | 0.48, 0.24, 0, 0 421 | 0.5, 0.24, 0, 0 422 | 0.52, 0.24, 0, 0 423 | 0.54, 0.24, 0, 0 424 | 0.56, 0.24, 0, 0 425 | 0.58, 0.24, 0, 0 426 | 0.6, 0.24, 0, 0 427 | 0.62, 0.24, 0, 0 428 | 0.64, 0.24, 0, 0 429 | 0.66, 0.24, 0, 0 430 | 0.68, 0.24, 0, 0 431 | 0.7, 0.24, 0, 0 432 | 0.72, 0.24, 0, 0 433 | 0.74, 0.24, 0, 0 434 | 0.76, 0.24, 0, 0 435 | 0.78, 0.24, 0, 0 436 | 0.8, 0.24, 0, 0 437 | 0.82, 0.24, 0, 0 438 | 0.84, 0.24, 0, 0 439 | 0.86, 0.24, 0, 0 440 | 0.88, 0.24, 0, 0 441 | 0.9, 0.24, 0, 0 442 | 0.92, 0.24, 0, 0 443 | 0.94, 0.24, 0, 0 444 | 0.96, 0.24, 0, 0 445 | 0.98, 0.24, 0, 0 446 | 0.02, 0.28, 0, 0 447 | 0.04, 0.28, 0, 0 448 | 0.06, 0.28, 0, 0 449 | 0.08, 0.28, 0, 0 450 | 0.1, 0.28, 0, 0 451 | 0.12, 0.28, 0, 0 452 | 0.14, 0.28, 0, 0 453 | 0.16, 0.28, 0, 0 454 | 0.18, 0.28, 0, 0 455 | 0.2, 0.28, 0, 0 456 | 0.22, 0.28, 0, 0 457 | 0.24, 0.28, 0, 0 458 | 0.26, 0.28, 0, 0 459 | 0.28, 0.28, 0, 0 460 | 0.3, 0.28, 0, 0 461 | 0.32, 0.28, 0, 0 462 | 0.34, 0.28, 0, 0 463 | 0.36, 0.28, 0, 0 464 | 0.38, 0.28, 0, 0 465 | 0.4, 0.28, 0, 0 466 | 0.42, 0.28, 0, 0 467 | 0.44, 0.28, 0, 0 468 | 0.46, 0.28, 0, 0 469 | 0.48, 0.28, 0, 0 470 | 0.5, 0.28, 0, 0 471 | 0.52, 0.28, 0, 0 472 | 0.54, 0.28, 0, 0 473 | 0.56, 0.28, 0, 0 474 | 0.58, 0.28, 0, 0 475 | 0.6, 0.28, 0, 0 476 | 0.62, 0.28, 0, 0 477 | 0.64, 0.28, 0, 0 478 | 0.66, 0.28, 0, 0 479 | 0.68, 0.28, 0, 0 480 | 0.7, 0.28, 0, 0 481 | 0.72, 0.28, 0, 0 482 | 0.74, 0.28, 0, 0 483 | 0.76, 0.28, 0, 0 484 | 0.78, 0.28, 0, 0 485 | 0.8, 0.28, 0, 0 486 | 0.82, 0.28, 0, 0 487 | 0.84, 0.28, 0, 0 488 | 0.86, 0.28, 0, 0 489 | 0.88, 0.28, 0, 0 490 | 0.9, 0.28, 0, 0 491 | 0.92, 0.28, 0, 0 492 | 0.94, 0.28, 0, 0 493 | 0.96, 0.28, 0, 0 494 | 0.98, 0.28, 0, 0 495 | 0.02, 0.32, 0, 0 496 | 0.04, 0.32, 0, 0 497 | 0.06, 0.32, 0, 0 498 | 0.08, 0.32, 0, 0 499 | 0.1, 0.32, 0, 0 500 | 0.12, 0.32, 0, 0 501 | 0.14, 0.32, 0, 0 502 | 0.16, 0.32, 0, 0 503 | 0.18, 0.32, 0, 0 504 | 0.2, 0.32, 0, 0 505 | 0.22, 0.32, 0, 0 506 | 0.24, 0.32, 0, 0 507 | 0.26, 0.32, 0, 0 508 | 0.28, 0.32, 0, 0 509 | 0.3, 0.32, 0, 0 510 | 0.32, 0.32, 0, 0 511 | 0.34, 0.32, 0, 0 512 | 0.36, 0.32, 0, 0 513 | 0.38, 0.32, 0, 0 514 | 0.4, 0.32, 0, 0 515 | 0.42, 0.32, 0, 0 516 | 0.44, 0.32, 0, 0 517 | 0.46, 0.32, 0, 0 518 | 0.48, 0.32, 0, 0 519 | 0.5, 0.32, 0, 0 520 | 0.52, 0.32, 0, 0 521 | 0.54, 0.32, 0, 0 522 | 0.56, 0.32, 0, 0 523 | 0.58, 0.32, 0, 0 524 | 0.6, 0.32, 0, 0 525 | 0.62, 0.32, 0, 0 526 | 0.64, 0.32, 0, 0 527 | 0.66, 0.32, 0, 0 528 | 0.68, 0.32, 0, 0 529 | 0.7, 0.32, 0, 0 530 | 0.72, 0.32, 0, 0 531 | 0.74, 0.32, 0, 0 532 | 0.76, 0.32, 0, 0 533 | 0.78, 0.32, 0, 0 534 | 0.8, 0.32, 0, 0 535 | 0.82, 0.32, 0, 0 536 | 0.84, 0.32, 0, 0 537 | 0.86, 0.32, 0, 0 538 | 0.88, 0.32, 0, 0 539 | 0.9, 0.32, 0, 0 540 | 0.92, 0.32, 0, 0 541 | 0.94, 0.32, 0, 0 542 | 0.96, 0.32, 0, 0 543 | 0.98, 0.32, 0, 0 544 | 0.02, 0.36, 0, 0 545 | 0.04, 0.36, 0, 0 546 | 0.06, 0.36, 0, 0 547 | 0.08, 0.36, 0, 0 548 | 0.1, 0.36, 0, 0 549 | 0.12, 0.36, 0, 0 550 | 0.14, 0.36, 0, 0 551 | 0.16, 0.36, 0, 0 552 | 0.18, 0.36, 0, 0 553 | 0.2, 0.36, 0, 0 554 | 0.22, 0.36, 0, 0 555 | 0.24, 0.36, 0, 0 556 | 0.26, 0.36, 0, 0 557 | 0.28, 0.36, 0, 0 558 | 0.3, 0.36, 0, 0 559 | 0.32, 0.36, 0, 0 560 | 0.34, 0.36, 0, 0 561 | 0.36, 0.36, 0, 0 562 | 0.38, 0.36, 0, 0 563 | 0.4, 0.36, 0, 0 564 | 0.42, 0.36, 0, 0 565 | 0.44, 0.36, 0, 0 566 | 0.46, 0.36, 0, 0 567 | 0.48, 0.36, 0, 0 568 | 0.5, 0.36, 0, 0 569 | 0.52, 0.36, 0, 0 570 | 0.54, 0.36, 0, 0 571 | 0.56, 0.36, 0, 0 572 | 0.58, 0.36, 0, 0 573 | 0.6, 0.36, 0, 0 574 | 0.62, 0.36, 0, 0 575 | 0.64, 0.36, 0, 0 576 | 0.66, 0.36, 0, 0 577 | 0.68, 0.36, 0, 0 578 | 0.7, 0.36, 0, 0 579 | 0.72, 0.36, 0, 0 580 | 0.74, 0.36, 0, 0 581 | 0.76, 0.36, 0, 0 582 | 0.78, 0.36, 0, 0 583 | 0.8, 0.36, 0, 0 584 | 0.82, 0.36, 0, 0 585 | 0.84, 0.36, 0, 0 586 | 0.86, 0.36, 0, 0 587 | 0.88, 0.36, 0, 0 588 | 0.9, 0.36, 0, 0 589 | 0.92, 0.36, 0, 0 590 | 0.94, 0.36, 0, 0 591 | 0.96, 0.36, 0, 0 592 | 0.98, 0.36, 0, 0 593 | 0.02, 0.4, 0, 0 594 | 0.04, 0.4, 0, 0 595 | 0.06, 0.4, 0, 0 596 | 0.08, 0.4, 0, 0 597 | 0.1, 0.4, 0, 0 598 | 0.12, 0.4, 0, 0 599 | 0.14, 0.4, 0, 0 600 | 0.16, 0.4, 0, 0 601 | 0.18, 0.4, 0, 0 602 | 0.2, 0.4, 0, 0 603 | 0.22, 0.4, 0, 0 604 | 0.24, 0.4, 0, 0 605 | 0.26, 0.4, 0, 0 606 | 0.28, 0.4, 0, 0 607 | 0.3, 0.4, 0, 0 608 | 0.32, 0.4, 0, 0 609 | 0.34, 0.4, 0, 0 610 | 0.36, 0.4, 0, 0 611 | 0.38, 0.4, 0, 0 612 | 0.4, 0.4, 0, 0 613 | 0.42, 0.4, 0, 0 614 | 0.44, 0.4, 0, 0 615 | 0.46, 0.4, 0, 0 616 | 0.48, 0.4, 0, 0 617 | 0.5, 0.4, 0, 0 618 | 0.52, 0.4, 0, 0 619 | 0.54, 0.4, 0, 0 620 | 0.56, 0.4, 0, 0 621 | 0.58, 0.4, 0, 0 622 | 0.6, 0.4, 0, 0 623 | 0.62, 0.4, 0, 0 624 | 0.64, 0.4, 0, 0 625 | 0.66, 0.4, 0, 0 626 | 0.68, 0.4, 0, 0 627 | 0.7, 0.4, 0, 0 628 | 0.72, 0.4, 0, 0 629 | 0.74, 0.4, 0, 0 630 | 0.76, 0.4, 0, 0 631 | 0.78, 0.4, 0, 0 632 | 0.8, 0.4, 0, 0 633 | 0.82, 0.4, 0, 0 634 | 0.84, 0.4, 0, 0 635 | 0.86, 0.4, 0, 0 636 | 0.88, 0.4, 0, 0 637 | 0.9, 0.4, 0, 0 638 | 0.92, 0.4, 0, 0 639 | 0.94, 0.4, 0, 0 640 | 0.96, 0.4, 0, 0 641 | 0.98, 0.4, 0, 0 642 | 0.02, 0.44, 0, 0 643 | 0.04, 0.44, 0, 0 644 | 0.06, 0.44, 0, 0 645 | 0.08, 0.44, 0, 0 646 | 0.1, 0.44, 0, 0 647 | 0.12, 0.44, 0, 0 648 | 0.14, 0.44, 0, 0 649 | 0.16, 0.44, 0, 0 650 | 0.18, 0.44, 0, 0 651 | 0.2, 0.44, 0, 0 652 | 0.22, 0.44, 0, 0 653 | 0.24, 0.44, 0, 0 654 | 0.26, 0.44, 0, 0 655 | 0.28, 0.44, 0, 0 656 | 0.3, 0.44, 0, 0 657 | 0.32, 0.44, 0, 0 658 | 0.34, 0.44, 0, 0 659 | 0.36, 0.44, 0, 0 660 | 0.38, 0.44, 0, 0 661 | 0.4, 0.44, 0, 0 662 | 0.42, 0.44, 0, 0 663 | 0.44, 0.44, 0, 0 664 | 0.46, 0.44, 0, 0 665 | 0.48, 0.44, 0, 0 666 | 0.5, 0.44, 0, 0 667 | 0.52, 0.44, 0, 0 668 | 0.54, 0.44, 0, 0 669 | 0.56, 0.44, 0, 0 670 | 0.58, 0.44, 0, 0 671 | 0.6, 0.44, 0, 0 672 | 0.62, 0.44, 0, 0 673 | 0.64, 0.44, 0, 0 674 | 0.66, 0.44, 0, 0 675 | 0.68, 0.44, 0, 0 676 | 0.7, 0.44, 0, 0 677 | 0.72, 0.44, 0, 0 678 | 0.74, 0.44, 0, 0 679 | 0.76, 0.44, 0, 0 680 | 0.78, 0.44, 0, 0 681 | 0.8, 0.44, 0, 0 682 | 0.82, 0.44, 0, 0 683 | 0.84, 0.44, 0, 0 684 | 0.86, 0.44, 0, 0 685 | 0.88, 0.44, 0, 0 686 | 0.9, 0.44, 0, 0 687 | 0.92, 0.44, 0, 0 688 | 0.94, 0.44, 0, 0 689 | 0.96, 0.44, 0, 0 690 | 0.98, 0.44, 0, 0 691 | 0.02, 0.48, 0, 0 692 | 0.04, 0.48, 0, 0 693 | 0.06, 0.48, 0, 0 694 | 0.08, 0.48, 0, 0 695 | 0.1, 0.48, 0, 0 696 | 0.12, 0.48, 0, 0 697 | 0.14, 0.48, 0, 0 698 | 0.16, 0.48, 0, 0 699 | 0.18, 0.48, 0, 0 700 | 0.2, 0.48, 0, 0 701 | 0.22, 0.48, 0, 0 702 | 0.24, 0.48, 0, 0 703 | 0.26, 0.48, 0, 0 704 | 0.28, 0.48, 0, 0 705 | 0.3, 0.48, 0, 0 706 | 0.32, 0.48, 0, 0 707 | 0.34, 0.48, 0, 0 708 | 0.36, 0.48, 0, 0 709 | 0.38, 0.48, 0, 0 710 | 0.4, 0.48, 0, 0 711 | 0.42, 0.48, 0, 0 712 | 0.44, 0.48, 0, 0 713 | 0.46, 0.48, 0, 0 714 | 0.48, 0.48, 0, 0 715 | 0.5, 0.48, 0, 0 716 | 0.52, 0.48, 0, 0 717 | 0.54, 0.48, 0, 0 718 | 0.56, 0.48, 0, 0 719 | 0.58, 0.48, 0, 0 720 | 0.6, 0.48, 0, 0 721 | 0.62, 0.48, 0, 0 722 | 0.64, 0.48, 0, 0 723 | 0.66, 0.48, 0, 0 724 | 0.68, 0.48, 0, 0 725 | 0.7, 0.48, 0, 0 726 | 0.72, 0.48, 0, 0 727 | 0.74, 0.48, 0, 0 728 | 0.76, 0.48, 0, 0 729 | 0.78, 0.48, 0, 0 730 | 0.8, 0.48, 0, 0 731 | 0.82, 0.48, 0, 0 732 | 0.84, 0.48, 0, 0 733 | 0.86, 0.48, 0, 0 734 | 0.88, 0.48, 0, 0 735 | 0.9, 0.48, 0, 0 736 | 0.92, 0.48, 0, 0 737 | 0.94, 0.48, 0, 0 738 | 0.96, 0.48, 0, 0 739 | 0.98, 0.48, 0, 0 740 | 0.02, 0.52, 0, 0 741 | 0.04, 0.52, 0, 0 742 | 0.06, 0.52, 0, 0 743 | 0.08, 0.52, 0, 0 744 | 0.1, 0.52, 0, 0 745 | 0.12, 0.52, 0, 0 746 | 0.14, 0.52, 0, 0 747 | 0.16, 0.52, 0, 0 748 | 0.18, 0.52, 0, 0 749 | 0.2, 0.52, 0, 0 750 | 0.22, 0.52, 0, 0 751 | 0.24, 0.52, 0, 0 752 | 0.26, 0.52, 0, 0 753 | 0.28, 0.52, 0, 0 754 | 0.3, 0.52, 0, 0 755 | 0.32, 0.52, 0, 0 756 | 0.34, 0.52, 0, 0 757 | 0.36, 0.52, 0, 0 758 | 0.38, 0.52, 0, 0 759 | 0.4, 0.52, 0, 0 760 | 0.42, 0.52, 0, 0 761 | 0.44, 0.52, 0, 0 762 | 0.46, 0.52, 0, 0 763 | 0.48, 0.52, 0, 0 764 | 0.5, 0.52, 0, 0 765 | 0.52, 0.52, 0, 0 766 | 0.54, 0.52, 0, 0 767 | 0.56, 0.52, 0, 0 768 | 0.58, 0.52, 0, 0 769 | 0.6, 0.52, 0, 0 770 | 0.62, 0.52, 0, 0 771 | 0.64, 0.52, 0, 0 772 | 0.66, 0.52, 0, 0 773 | 0.68, 0.52, 0, 0 774 | 0.7, 0.52, 0, 0 775 | 0.72, 0.52, 0, 0 776 | 0.74, 0.52, 0, 0 777 | 0.76, 0.52, 0, 0 778 | 0.78, 0.52, 0, 0 779 | 0.8, 0.52, 0, 0 780 | 0.82, 0.52, 0, 0 781 | 0.84, 0.52, 0, 0 782 | 0.86, 0.52, 0, 0 783 | 0.88, 0.52, 0, 0 784 | 0.9, 0.52, 0, 0 785 | 0.92, 0.52, 0, 0 786 | 0.94, 0.52, 0, 0 787 | 0.96, 0.52, 0, 0 788 | 0.98, 0.52, 0, 0 789 | 0.02, 0.56, 0, 0 790 | 0.04, 0.56, 0, 0 791 | 0.06, 0.56, 0, 0 792 | 0.08, 0.56, 0, 0 793 | 0.1, 0.56, 0, 0 794 | 0.12, 0.56, 0, 0 795 | 0.14, 0.56, 0, 0 796 | 0.16, 0.56, 0, 0 797 | 0.18, 0.56, 0, 0 798 | 0.2, 0.56, 0, 0 799 | 0.22, 0.56, 0, 0 800 | 0.24, 0.56, 0, 0 801 | 0.26, 0.56, 0, 0 802 | 0.28, 0.56, 0, 0 803 | 0.3, 0.56, 0, 0 804 | 0.32, 0.56, 0, 0 805 | 0.34, 0.56, 0, 0 806 | 0.36, 0.56, 0, 0 807 | 0.38, 0.56, 0, 0 808 | 0.4, 0.56, 0, 0 809 | 0.42, 0.56, 0, 0 810 | 0.44, 0.56, 0, 0 811 | 0.46, 0.56, 0, 0 812 | 0.48, 0.56, 0, 0 813 | 0.5, 0.56, 0, 0 814 | 0.52, 0.56, 0, 0 815 | 0.54, 0.56, 0, 0 816 | 0.56, 0.56, 0, 0 817 | 0.58, 0.56, 0, 0 818 | 0.6, 0.56, 0, 0 819 | 0.62, 0.56, 0, 0 820 | 0.64, 0.56, 0, 0 821 | 0.66, 0.56, 0, 0 822 | 0.68, 0.56, 0, 0 823 | 0.7, 0.56, 0, 0 824 | 0.72, 0.56, 0, 0 825 | 0.74, 0.56, 0, 0 826 | 0.76, 0.56, 0, 0 827 | 0.78, 0.56, 0, 0 828 | 0.8, 0.56, 0, 0 829 | 0.82, 0.56, 0, 0 830 | 0.84, 0.56, 0, 0 831 | 0.86, 0.56, 0, 0 832 | 0.88, 0.56, 0, 0 833 | 0.9, 0.56, 0, 0 834 | 0.92, 0.56, 0, 0 835 | 0.94, 0.56, 0, 0 836 | 0.96, 0.56, 0, 0 837 | 0.98, 0.56, 0, 0 838 | 0.02, 0.6, 0, 0 839 | 0.04, 0.6, 0, 0 840 | 0.06, 0.6, 0, 0 841 | 0.08, 0.6, 0, 0 842 | 0.1, 0.6, 0, 0 843 | 0.12, 0.6, 0, 0 844 | 0.14, 0.6, 0, 0 845 | 0.16, 0.6, 0, 0 846 | 0.18, 0.6, 0, 0 847 | 0.2, 0.6, 0, 0 848 | 0.22, 0.6, 0, 0 849 | 0.24, 0.6, 0, 0 850 | 0.26, 0.6, 0, 0 851 | 0.28, 0.6, 0, 0 852 | 0.3, 0.6, 0, 0 853 | 0.32, 0.6, 0, 0 854 | 0.34, 0.6, 0, 0 855 | 0.36, 0.6, 0, 0 856 | 0.38, 0.6, 0, 0 857 | 0.4, 0.6, 0, 0 858 | 0.42, 0.6, 0, 0 859 | 0.44, 0.6, 0, 0 860 | 0.46, 0.6, 0, 0 861 | 0.48, 0.6, 0, 0 862 | 0.5, 0.6, 0, 0 863 | 0.52, 0.6, 0, 0 864 | 0.54, 0.6, 0, 0 865 | 0.56, 0.6, 0, 0 866 | 0.58, 0.6, 0, 0 867 | 0.6, 0.6, 0, 0 868 | 0.62, 0.6, 0, 0 869 | 0.64, 0.6, 0, 0 870 | 0.66, 0.6, 0, 0 871 | 0.68, 0.6, 0, 0 872 | 0.7, 0.6, 0, 0 873 | 0.72, 0.6, 0, 0 874 | 0.74, 0.6, 0, 0 875 | 0.76, 0.6, 0, 0 876 | 0.78, 0.6, 0, 0 877 | 0.8, 0.6, 0, 0 878 | 0.82, 0.6, 0, 0 879 | 0.84, 0.6, 0, 0 880 | 0.86, 0.6, 0, 0 881 | 0.88, 0.6, 0, 0 882 | 0.9, 0.6, 0, 0 883 | 0.92, 0.6, 0, 0 884 | 0.94, 0.6, 0, 0 885 | 0.96, 0.6, 0, 0 886 | 0.98, 0.6, 0, 0 887 | 0.02, 0.64, 0, 0 888 | 0.04, 0.64, 0, 0 889 | 0.06, 0.64, 0, 0 890 | 0.08, 0.64, 0, 0 891 | 0.1, 0.64, 0, 0 892 | 0.12, 0.64, 0, 0 893 | 0.14, 0.64, 0, 0 894 | 0.16, 0.64, 0, 0 895 | 0.18, 0.64, 0, 0 896 | 0.2, 0.64, 0, 0 897 | 0.22, 0.64, 0, 0 898 | 0.24, 0.64, 0, 0 899 | 0.26, 0.64, 0, 0 900 | 0.28, 0.64, 0, 0 901 | 0.3, 0.64, 0, 0 902 | 0.32, 0.64, 0, 0 903 | 0.34, 0.64, 0, 0 904 | 0.36, 0.64, 0, 0 905 | 0.38, 0.64, 0, 0 906 | 0.4, 0.64, 0, 0 907 | 0.42, 0.64, 0, 0 908 | 0.44, 0.64, 0, 0 909 | 0.46, 0.64, 0, 0 910 | 0.48, 0.64, 0, 0 911 | 0.5, 0.64, 0, 0 912 | 0.52, 0.64, 0, 0 913 | 0.54, 0.64, 0, 0 914 | 0.56, 0.64, 0, 0 915 | 0.58, 0.64, 0, 0 916 | 0.6, 0.64, 0, 0 917 | 0.62, 0.64, 0, 0 918 | 0.64, 0.64, 0, 0 919 | 0.66, 0.64, 0, 0 920 | 0.68, 0.64, 0, 0 921 | 0.7, 0.64, 0, 0 922 | 0.72, 0.64, 0, 0 923 | 0.74, 0.64, 0, 0 924 | 0.76, 0.64, 0, 0 925 | 0.78, 0.64, 0, 0 926 | 0.8, 0.64, 0, 0 927 | 0.82, 0.64, 0, 0 928 | 0.84, 0.64, 0, 0 929 | 0.86, 0.64, 0, 0 930 | 0.88, 0.64, 0, 0 931 | 0.9, 0.64, 0, 0 932 | 0.92, 0.64, 0, 0 933 | 0.94, 0.64, 0, 0 934 | 0.96, 0.64, 0, 0 935 | 0.98, 0.64, 0, 0 936 | 0.02, 0.68, 0, 0 937 | 0.04, 0.68, 0, 0 938 | 0.06, 0.68, 0, 0 939 | 0.08, 0.68, 0, 0 940 | 0.1, 0.68, 0, 0 941 | 0.12, 0.68, 0, 0 942 | 0.14, 0.68, 0, 0 943 | 0.16, 0.68, 0, 0 944 | 0.18, 0.68, 0, 0 945 | 0.2, 0.68, 0, 0 946 | 0.22, 0.68, 0, 0 947 | 0.24, 0.68, 0, 0 948 | 0.26, 0.68, 0, 0 949 | 0.28, 0.68, 0, 0 950 | 0.3, 0.68, 0, 0 951 | 0.32, 0.68, 0, 0 952 | 0.34, 0.68, 0, 0 953 | 0.36, 0.68, 0, 0 954 | 0.38, 0.68, 0, 0 955 | 0.4, 0.68, 0, 0 956 | 0.42, 0.68, 0, 0 957 | 0.44, 0.68, 0, 0 958 | 0.46, 0.68, 0, 0 959 | 0.48, 0.68, 0, 0 960 | 0.5, 0.68, 0, 0 961 | 0.52, 0.68, 0, 0 962 | 0.54, 0.68, 0, 0 963 | 0.56, 0.68, 0, 0 964 | 0.58, 0.68, 0, 0 965 | 0.6, 0.68, 0, 0 966 | 0.62, 0.68, 0, 0 967 | 0.64, 0.68, 0, 0 968 | 0.66, 0.68, 0, 0 969 | 0.68, 0.68, 0, 0 970 | 0.7, 0.68, 0, 0 971 | 0.72, 0.68, 0, 0 972 | 0.74, 0.68, 0, 0 973 | 0.76, 0.68, 0, 0 974 | 0.78, 0.68, 0, 0 975 | 0.8, 0.68, 0, 0 976 | 0.82, 0.68, 0, 0 977 | 0.84, 0.68, 0, 0 978 | 0.86, 0.68, 0, 0 979 | 0.88, 0.68, 0, 0 980 | 0.9, 0.68, 0, 0 981 | 0.92, 0.68, 0, 0 982 | 0.94, 0.68, 0, 0 983 | 0.96, 0.68, 0, 0 984 | 0.98, 0.68, 0, 0 985 | 0.02, 0.72, 0, 0 986 | 0.04, 0.72, 0, 0 987 | 0.06, 0.72, 0, 0 988 | 0.08, 0.72, 0, 0 989 | 0.1, 0.72, 0, 0 990 | 0.12, 0.72, 0, 0 991 | 0.14, 0.72, 0, 0 992 | 0.16, 0.72, 0, 0 993 | 0.18, 0.72, 0, 0 994 | 0.2, 0.72, 0, 0 995 | 0.22, 0.72, 0, 0 996 | 0.24, 0.72, 0, 0 997 | 0.26, 0.72, 0, 0 998 | 0.28, 0.72, 0, 0 999 | 0.3, 0.72, 0, 0 1000 | 0.32, 0.72, 0, 0 1001 | 0.34, 0.72, 0, 0 1002 | 0.36, 0.72, 0, 0 1003 | 0.38, 0.72, 0, 0 1004 | 0.4, 0.72, 0, 0 1005 | 0.42, 0.72, 0, 0 1006 | 0.44, 0.72, 0, 0 1007 | 0.46, 0.72, 0, 0 1008 | 0.48, 0.72, 0, 0 1009 | 0.5, 0.72, 0, 0 1010 | 0.52, 0.72, 0, 0 1011 | 0.54, 0.72, 0, 0 1012 | 0.56, 0.72, 0, 0 1013 | 0.58, 0.72, 0, 0 1014 | 0.6, 0.72, 0, 0 1015 | 0.62, 0.72, 0, 0 1016 | 0.64, 0.72, 0, 0 1017 | 0.66, 0.72, 0, 0 1018 | 0.68, 0.72, 0, 0 1019 | 0.7, 0.72, 0, 0 1020 | 0.72, 0.72, 0, 0 1021 | 0.74, 0.72, 0, 0 1022 | 0.76, 0.72, 0, 0 1023 | 0.78, 0.72, 0, 0 1024 | 0.8, 0.72, 0, 0 1025 | 0.82, 0.72, 0, 0 1026 | 0.84, 0.72, 0, 0 1027 | 0.86, 0.72, 0, 0 1028 | 0.88, 0.72, 0, 0 1029 | 0.9, 0.72, 0, 0 1030 | 0.92, 0.72, 0, 0 1031 | 0.94, 0.72, 0, 0 1032 | 0.96, 0.72, 0, 0 1033 | 0.98, 0.72, 0, 0 1034 | 0.02, 0.76, 0, 0 1035 | 0.04, 0.76, 0, 0 1036 | 0.06, 0.76, 0, 0 1037 | 0.08, 0.76, 0, 0 1038 | 0.1, 0.76, 0, 0 1039 | 0.12, 0.76, 0, 0 1040 | 0.14, 0.76, 0, 0 1041 | 0.16, 0.76, 0, 0 1042 | 0.18, 0.76, 0, 0 1043 | 0.2, 0.76, 0, 0 1044 | 0.22, 0.76, 0, 0 1045 | 0.24, 0.76, 0, 0 1046 | 0.26, 0.76, 0, 0 1047 | 0.28, 0.76, 0, 0 1048 | 0.3, 0.76, 0, 0 1049 | 0.32, 0.76, 0, 0 1050 | 0.34, 0.76, 0, 0 1051 | 0.36, 0.76, 0, 0 1052 | 0.38, 0.76, 0, 0 1053 | 0.4, 0.76, 0, 0 1054 | 0.42, 0.76, 0, 0 1055 | 0.44, 0.76, 0, 0 1056 | 0.46, 0.76, 0, 0 1057 | 0.48, 0.76, 0, 0 1058 | 0.5, 0.76, 0, 0 1059 | 0.52, 0.76, 0, 0 1060 | 0.54, 0.76, 0, 0 1061 | 0.56, 0.76, 0, 0 1062 | 0.58, 0.76, 0, 0 1063 | 0.6, 0.76, 0, 0 1064 | 0.62, 0.76, 0, 0 1065 | 0.64, 0.76, 0, 0 1066 | 0.66, 0.76, 0, 0 1067 | 0.68, 0.76, 0, 0 1068 | 0.7, 0.76, 0, 0 1069 | 0.72, 0.76, 0, 0 1070 | 0.74, 0.76, 0, 0 1071 | 0.76, 0.76, 0, 0 1072 | 0.78, 0.76, 0, 0 1073 | 0.8, 0.76, 0, 0 1074 | 0.82, 0.76, 0, 0 1075 | 0.84, 0.76, 0, 0 1076 | 0.86, 0.76, 0, 0 1077 | 0.88, 0.76, 0, 0 1078 | 0.9, 0.76, 0, 0 1079 | 0.92, 0.76, 0, 0 1080 | 0.94, 0.76, 0, 0 1081 | 0.96, 0.76, 0, 0 1082 | 0.98, 0.76, 0, 0 1083 | 0.02, 0.8, 0, 0 1084 | 0.04, 0.8, 0, 0 1085 | 0.06, 0.8, 0, 0 1086 | 0.08, 0.8, 0, 0 1087 | 0.1, 0.8, 0, 0 1088 | 0.12, 0.8, 0, 0 1089 | 0.14, 0.8, 0, 0 1090 | 0.16, 0.8, 0, 0 1091 | 0.18, 0.8, 0, 0 1092 | 0.2, 0.8, 0, 0 1093 | 0.22, 0.8, 0, 0 1094 | 0.24, 0.8, 0, 0 1095 | 0.26, 0.8, 0, 0 1096 | 0.28, 0.8, 0, 0 1097 | 0.3, 0.8, 0, 0 1098 | 0.32, 0.8, 0, 0 1099 | 0.34, 0.8, 0, 0 1100 | 0.36, 0.8, 0, 0 1101 | 0.38, 0.8, 0, 0 1102 | 0.4, 0.8, 0, 0 1103 | 0.42, 0.8, 0, 0 1104 | 0.44, 0.8, 0, 0 1105 | 0.46, 0.8, 0, 0 1106 | 0.48, 0.8, 0, 0 1107 | 0.5, 0.8, 0, 0 1108 | 0.52, 0.8, 0, 0 1109 | 0.54, 0.8, 0, 0 1110 | 0.56, 0.8, 0, 0 1111 | 0.58, 0.8, 0, 0 1112 | 0.6, 0.8, 0, 0 1113 | 0.62, 0.8, 0, 0 1114 | 0.64, 0.8, 0, 0 1115 | 0.66, 0.8, 0, 0 1116 | 0.68, 0.8, 0, 0 1117 | 0.7, 0.8, 0, 0 1118 | 0.72, 0.8, 0, 0 1119 | 0.74, 0.8, 0, 0 1120 | 0.76, 0.8, 0, 0 1121 | 0.78, 0.8, 0, 0 1122 | 0.8, 0.8, 0, 0 1123 | 0.82, 0.8, 0, 0 1124 | 0.84, 0.8, 0, 0 1125 | 0.86, 0.8, 0, 0 1126 | 0.88, 0.8, 0, 0 1127 | 0.9, 0.8, 0, 0 1128 | 0.92, 0.8, 0, 0 1129 | 0.94, 0.8, 0, 0 1130 | 0.96, 0.8, 0, 0 1131 | 0.98, 0.8, 0, 0 1132 | 0.02, 0.84, 0, 0 1133 | 0.04, 0.84, 0, 0 1134 | 0.06, 0.84, 0, 0 1135 | 0.08, 0.84, 0, 0 1136 | 0.1, 0.84, 0, 0 1137 | 0.12, 0.84, 0, 0 1138 | 0.14, 0.84, 0, 0 1139 | 0.16, 0.84, 0, 0 1140 | 0.18, 0.84, 0, 0 1141 | 0.2, 0.84, 0, 0 1142 | 0.22, 0.84, 0, 0 1143 | 0.24, 0.84, 0, 0 1144 | 0.26, 0.84, 0, 0 1145 | 0.28, 0.84, 0, 0 1146 | 0.3, 0.84, 0, 0 1147 | 0.32, 0.84, 0, 0 1148 | 0.34, 0.84, 0, 0 1149 | 0.36, 0.84, 0, 0 1150 | 0.38, 0.84, 0, 0 1151 | 0.4, 0.84, 0, 0 1152 | 0.42, 0.84, 0, 0 1153 | 0.44, 0.84, 0, 0 1154 | 0.46, 0.84, 0, 0 1155 | 0.48, 0.84, 0, 0 1156 | 0.5, 0.84, 0, 0 1157 | 0.52, 0.84, 0, 0 1158 | 0.54, 0.84, 0, 0 1159 | 0.56, 0.84, 0, 0 1160 | 0.58, 0.84, 0, 0 1161 | 0.6, 0.84, 0, 0 1162 | 0.62, 0.84, 0, 0 1163 | 0.64, 0.84, 0, 0 1164 | 0.66, 0.84, 0, 0 1165 | 0.68, 0.84, 0, 0 1166 | 0.7, 0.84, 0, 0 1167 | 0.72, 0.84, 0, 0 1168 | 0.74, 0.84, 0, 0 1169 | 0.76, 0.84, 0, 0 1170 | 0.78, 0.84, 0, 0 1171 | 0.8, 0.84, 0, 0 1172 | 0.82, 0.84, 0, 0 1173 | 0.84, 0.84, 0, 0 1174 | 0.86, 0.84, 0, 0 1175 | 0.88, 0.84, 0, 0 1176 | 0.9, 0.84, 0, 0 1177 | 0.92, 0.84, 0, 0 1178 | 0.94, 0.84, 0, 0 1179 | 0.96, 0.84, 0, 0 1180 | 0.98, 0.84, 0, 0 1181 | 0.02, 0.88, 0, 0 1182 | 0.04, 0.88, 0, 0 1183 | 0.06, 0.88, 0, 0 1184 | 0.08, 0.88, 0, 0 1185 | 0.1, 0.88, 0, 0 1186 | 0.12, 0.88, 0, 0 1187 | 0.14, 0.88, 0, 0 1188 | 0.16, 0.88, 0, 0 1189 | 0.18, 0.88, 0, 0 1190 | 0.2, 0.88, 0, 0 1191 | 0.22, 0.88, 0, 0 1192 | 0.24, 0.88, 0, 0 1193 | 0.26, 0.88, 0, 0 1194 | 0.28, 0.88, 0, 0 1195 | 0.3, 0.88, 0, 0 1196 | 0.32, 0.88, 0, 0 1197 | 0.34, 0.88, 0, 0 1198 | 0.36, 0.88, 0, 0 1199 | 0.38, 0.88, 0, 0 1200 | 0.4, 0.88, 0, 0 1201 | 0.42, 0.88, 0, 0 1202 | 0.44, 0.88, 0, 0 1203 | 0.46, 0.88, 0, 0 1204 | 0.48, 0.88, 0, 0 1205 | 0.5, 0.88, 0, 0 1206 | 0.52, 0.88, 0, 0 1207 | 0.54, 0.88, 0, 0 1208 | 0.56, 0.88, 0, 0 1209 | 0.58, 0.88, 0, 0 1210 | 0.6, 0.88, 0, 0 1211 | 0.62, 0.88, 0, 0 1212 | 0.64, 0.88, 0, 0 1213 | 0.66, 0.88, 0, 0 1214 | 0.68, 0.88, 0, 0 1215 | 0.7, 0.88, 0, 0 1216 | 0.72, 0.88, 0, 0 1217 | 0.74, 0.88, 0, 0 1218 | 0.76, 0.88, 0, 0 1219 | 0.78, 0.88, 0, 0 1220 | 0.8, 0.88, 0, 0 1221 | 0.82, 0.88, 0, 0 1222 | 0.84, 0.88, 0, 0 1223 | 0.86, 0.88, 0, 0 1224 | 0.88, 0.88, 0, 0 1225 | 0.9, 0.88, 0, 0 1226 | 0.92, 0.88, 0, 0 1227 | 0.94, 0.88, 0, 0 1228 | 0.96, 0.88, 0, 0 1229 | 0.98, 0.88, 0, 0 1230 | 0.02, 0.92, 0, 0 1231 | 0.04, 0.92, 0, 0 1232 | 0.06, 0.92, 0, 0 1233 | 0.08, 0.92, 0, 0 1234 | 0.1, 0.92, 0, 0 1235 | 0.12, 0.92, 0, 0 1236 | 0.14, 0.92, 0, 0 1237 | 0.16, 0.92, 0, 0 1238 | 0.18, 0.92, 0, 0 1239 | 0.2, 0.92, 0, 0 1240 | 0.22, 0.92, 0, 0 1241 | 0.24, 0.92, 0, 0 1242 | 0.26, 0.92, 0, 0 1243 | 0.28, 0.92, 0, 0 1244 | 0.3, 0.92, 0, 0 1245 | 0.32, 0.92, 0, 0 1246 | 0.34, 0.92, 0, 0 1247 | 0.36, 0.92, 0, 0 1248 | 0.38, 0.92, 0, 0 1249 | 0.4, 0.92, 0, 0 1250 | 0.42, 0.92, 0, 0 1251 | 0.44, 0.92, 0, 0 1252 | 0.46, 0.92, 0, 0 1253 | 0.48, 0.92, 0, 0 1254 | 0.5, 0.92, 0, 0 1255 | 0.52, 0.92, 0, 0 1256 | 0.54, 0.92, 0, 0 1257 | 0.56, 0.92, 0, 0 1258 | 0.58, 0.92, 0, 0 1259 | 0.6, 0.92, 0, 0 1260 | 0.62, 0.92, 0, 0 1261 | 0.64, 0.92, 0, 0 1262 | 0.66, 0.92, 0, 0 1263 | 0.68, 0.92, 0, 0 1264 | 0.7, 0.92, 0, 0 1265 | 0.72, 0.92, 0, 0 1266 | 0.74, 0.92, 0, 0 1267 | 0.76, 0.92, 0, 0 1268 | 0.78, 0.92, 0, 0 1269 | 0.8, 0.92, 0, 0 1270 | 0.82, 0.92, 0, 0 1271 | 0.84, 0.92, 0, 0 1272 | 0.86, 0.92, 0, 0 1273 | 0.88, 0.92, 0, 0 1274 | 0.9, 0.92, 0, 0 1275 | 0.92, 0.92, 0, 0 1276 | 0.94, 0.92, 0, 0 1277 | 0.96, 0.92, 0, 0 1278 | 0.98, 0.92, 0, 0 1279 | 0.02, 0.96, 0, 0 1280 | 0.04, 0.96, 0, 0 1281 | 0.06, 0.96, 0, 0 1282 | 0.08, 0.96, 0, 0 1283 | 0.1, 0.96, 0, 0 1284 | 0.12, 0.96, 0, 0 1285 | 0.14, 0.96, 0, 0 1286 | 0.16, 0.96, 0, 0 1287 | 0.18, 0.96, 0, 0 1288 | 0.2, 0.96, 0, 0 1289 | 0.22, 0.96, 0, 0 1290 | 0.24, 0.96, 0, 0 1291 | 0.26, 0.96, 0, 0 1292 | 0.28, 0.96, 0, 0 1293 | 0.3, 0.96, 0, 0 1294 | 0.32, 0.96, 0, 0 1295 | 0.34, 0.96, 0, 0 1296 | 0.36, 0.96, 0, 0 1297 | 0.38, 0.96, 0, 0 1298 | 0.4, 0.96, 0, 0 1299 | 0.42, 0.96, 0, 0 1300 | 0.44, 0.96, 0, 0 1301 | 0.46, 0.96, 0, 0 1302 | 0.48, 0.96, 0, 0 1303 | 0.5, 0.96, 0, 0 1304 | 0.52, 0.96, 0, 0 1305 | 0.54, 0.96, 0, 0 1306 | 0.56, 0.96, 0, 0 1307 | 0.58, 0.96, 0, 0 1308 | 0.6, 0.96, 0, 0 1309 | 0.62, 0.96, 0, 0 1310 | 0.64, 0.96, 0, 0 1311 | 0.66, 0.96, 0, 0 1312 | 0.68, 0.96, 0, 0 1313 | 0.7, 0.96, 0, 0 1314 | 0.72, 0.96, 0, 0 1315 | 0.74, 0.96, 0, 0 1316 | 0.76, 0.96, 0, 0 1317 | 0.78, 0.96, 0, 0 1318 | 0.8, 0.96, 0, 0 1319 | 0.82, 0.96, 0, 0 1320 | 0.84, 0.96, 0, 0 1321 | 0.86, 0.96, 0, 0 1322 | 0.88, 0.96, 0, 0 1323 | 0.9, 0.96, 0, 0 1324 | 0.92, 0.96, 0, 0 1325 | 0.94, 0.96, 0, 0 1326 | 0.96, 0.96, 0, 0 1327 | 0.98, 0.96, 0, 0 1328 | -------------------------------------------------------------------------------- /Co-Located SIMPLE.md: -------------------------------------------------------------------------------- 1 | # 动量方程推导 2 | 3 | ## $X$方向动量方程 4 | 5 | 对于每个网格,$X$方向的动量方程通量形式为: 6 | 7 | $$ 8 | \left(J_{e}^{X}-J_{w}^{X}\right) \Delta y+\left(J_{n}^{X}-J_{s}^{X}\right) \Delta x=-\int_{s}^{n} \int_{w}^{e} \frac{\partial p}{\partial x} d x d y 9 | $$ 10 | 11 | 其中: 12 | 13 | $$ 14 | J_{e}^{X}=\rho_{e} u_{e} u_{e}-\left.\mu_{e} \frac{\partial u}{\partial x}\right|_{e}\\ 15 | J_{w}^{X}=\rho_{w} u_{w} u_{w}-\left.\mu_{w} \frac{\partial u}{\partial x}\right|_{w}\\ 16 | J_{n}^{X}=\rho_{n} v_{n} u_{n}-\left.\mu_{n} \frac{\partial u}{\partial y}\right|_{n}\\ 17 | J_{s}^{X}=\rho_{s} v_{s} u_{s}-\left.\mu_{s} \frac{\partial u}{\partial y}\right|_{s} 18 | $$ 19 | 20 | 将face value表示为cell value得到: 21 | 22 | $$ 23 | \begin{aligned} 24 | &\left[\frac{\left|(\rho u)_{e}\right|+(\rho u)_{e}}{2} u_{O}-\frac{\left|(\rho u)_{e}\right|-(\rho u)_{e}}{2} u_{E}-\mu_{e} \frac{u_{E}-u_{O}}{\Delta x}\right] \Delta y\\ 25 | -&\left[\frac{\left|(\rho u)_{w}\right|+(\rho u)_{w}}{2} u_{W}-\frac{\left|(\rho u)_{w}\right|-(\rho u)_{w}}{2} u_{O}-\mu_{w} \frac{u_{O}-u_{W}}{\Delta x}\right] \Delta y\\ 26 | +&\left[\frac{\left|(\rho v)_{n}\right|+(\rho v)_{n}}{2} u_{O}-\frac{\left|(\rho v)_{n}\right|-(\rho v)_{n}}{2} u_{N}-\mu_{n} \frac{u_{N}-u_{O}}{\Delta y}\right] \Delta x\\ 27 | -&\left[\frac{\left|(\rho v)_{s}\right|+(\rho v)_{s}}{2} u_{S}-\frac{\left|(\rho v)_{s}\right|-(\rho v)_{s}}{2} u_{O}-\mu_{s} \frac{u_{O}-u_{S}}{\Delta y}\right] \Delta x=-\left(p_{e}-p_{w}\right) \Delta y 28 | \end{aligned} 29 | $$ 30 | 31 | ## 对流项一阶迎风的另一种表达 32 | 33 | 其中**对流项**用的是一阶迎风格式,还有**另一种表达形式**: 34 | 35 | $$ 36 | \begin{align} 37 | (\rho u \phi)_{e}&=\rho_e u_e \phi_{e}=\phi_{O} \max \left(\rho_e u_e, 0\right)-\phi_{E} \max \left(-\rho_e u_e, 0\right)\\ 38 | (\rho u \phi)_{w}&=\rho_w u_w \phi_{w}=\phi_{W} \max \left(\rho_w u_w, 0\right)-\phi_{O} \max \left(-\rho_w u_w, 0\right)\\ 39 | (\rho v \phi)_{n}&=\rho_n v_n \phi_{n}=\phi_{O} \max \left(\rho_n v_n, 0\right)-\phi_{N} \max \left(-\rho_n v_n, 0\right)\\ 40 | (\rho v \phi)_{s}&=\rho_s v_s \phi_{s}=\phi_{S} \max \left(\rho_s v_s, 0\right)-\phi_{O} \max \left(-\rho_s v_s, 0\right) 41 | \end{align} 42 | $$ 43 | 44 | 因为: 45 | 46 | $$ 47 | \max \left(\rho_e u_e, 0\right) = \frac{\left|(\rho u)_{e}\right|+(\rho u)_{e}}{2}\qquad 48 | \max \left(-\rho_e u_e, 0\right) = \frac{\left|(\rho u)_{e}\right|-(\rho u)_{e}}{2}\\ 49 | \max \left(\rho_w u_w, 0\right) = \frac{\left|(\rho u)_{w}\right|+(\rho u)_{w}}{2} \qquad 50 | \max \left(-\rho_w u_w, 0\right) = \frac{\left|(\rho u)_{w}\right|-(\rho u)_{w}}{2} \\ 51 | \max \left(\rho_n v_n, 0\right) = \frac{\left|(\rho v)_{n}\right|+(\rho v)_{n}}{2} \qquad 52 | \max \left(-\rho_n v_n, 0\right) = \frac{\left|(\rho v)_{n}\right|-(\rho v)_{n}}{2}\\ 53 | \max \left(\rho_s v_s, 0\right) = \frac{\left|(\rho v)_{s}\right|+(\rho v)_{s}}{2} \qquad 54 | \max \left(-\rho_s v_s, 0\right) = \frac{\left|(\rho v)_{s}\right|-(\rho v)_{s}}{2} 55 | $$ 56 | 57 | 对于动量方程,只需要把$\phi$替换为$u$即可。 58 | 59 | 由上面的关系,可以容易得到如下关系: 60 | 61 | $$ 62 | \rho_e u_e + \max(-\rho_e u_e, 0) = \max(\rho_e u_e, 0), \quad \max(\rho_e u_e, 0) - \rho_e u_e = max(-\rho_e u_e, 0) \\ 63 | \rho_w u_w + \max(-\rho_w u_w, 0) = \max(\rho_w u_w, 0), \quad \max(\rho_w u_w, 0) - \rho_w u_w = max(-\rho_w u_w, 0) \\ 64 | \vdots 65 | $$ 66 | 67 | 这个关系在下面推导Link Coefficient形式会用到。 68 | 69 | ## 标量输运与动量输运的异同 70 | 71 | 可以看到,动量输运方程实际上可以看成是特殊的标量输运方程,只不过输运对象为$u$,因此在做face value差值的时候,我们只对对流项($\rho u u$)中其中一个$u$做差值,另一个$u$依旧保留face value,认为是已知的,这个默认已知的值,只在simple算法中的outer iteration中更新,后面会具体介绍。 72 | 73 | ## Link Coefficients形式 74 | 75 | 写成Link coefficients形式: 76 | 77 | $$ 78 | A_{O} \phi_{O}+A_{E} \phi_{E}+A_{W} \phi_{W}+A_{N} \phi_{N}+A_{S} \phi_{S}=S\\ 79 | $$ 80 | 81 | 其中: 82 | 83 | $$ 84 | \begin{aligned} 85 | A_{E} &=-\frac{\left|(\rho u)_{e}\right|-(\rho u)_{e}}{2} \Delta y-\frac{\mu_{e}}{\Delta x} \Delta y \\ 86 | A_{W} &=-\frac{\left|(\rho u)_{w}\right|+(\rho u)_{w}}{2} \Delta y-\frac{\mu_{w}}{\Delta x} \Delta y \\ 87 | A_{N} &=-\frac{\left|(\rho v)_{n}\right|-(\rho v)_{n}}{2} \Delta x-\frac{\mu_{n}}{\Delta y} \Delta x \\ 88 | A_{S} &=-\frac{\left|(\rho v)_{s}\right|+(\rho v)_{s}}{2}\Delta x-\frac{\mu_{s}}{\Delta y} \Delta x\\ 89 | A_{O}&=-(A_E+A_W+A_N+A_S)+\left[(\rho u)_e\Delta y - (\rho u)_w\Delta y + (\rho v)_n\Delta x - (\rho v)_s\Delta x\right] 90 | \end{aligned} 91 | \begin{array}{l} 92 | S^{X}=\left(p_{w}-p_{e}\right) \Delta y \\ 93 | S^{Y}=\left(p_{s}-p_{n}\right) \Delta x 94 | \end{array} 95 | $$ 96 | 97 | **注意**:这里给出的是interior网格的形式,对于boundary网格,需要从最原始的通量形式重新推导,以免出现错误。 98 | 99 | # SIMPLE算法步骤与推导 100 | 101 | ## step 1:猜测初值 102 | 103 | 猜测网格初值:$u^{k}, v^{k}, p^{k}$ 104 | 105 | ## step 2:计算速度face value 106 | 107 | 用cell value速度差值face value法向速度: 108 | 109 | - 当$k=1$的,依旧用distance-weighted interpolation($u_{e}=\frac{u_{E}+u_{O}}{2} \text { etc. }$),因为此时的压力是猜测值,不宜用PWIM差值 110 | - 当$k\neq1$时,用上一步PWIM差值计算得到的速度face value和velocity correction,得到这一步的速度face value 111 | 112 | ## step 3:计算速度Link coefficient 113 | 114 | - 计算X方向和Y方向动量方程的Link coefficient(They are the same) 115 | 116 | - 计算压力: 117 | 118 | $$ 119 | S^{X}=\left(p_{w}-p_{e}\right) \Delta y=\left(\frac{p_{O}+p_{W}}{2}-\frac{p_{O}+p_{E}}{2}\right) \Delta y=\frac{1}{2}\left(p_{W}-p_{E}\right) \Delta y\\S^{Y}=\left(p_{s}-p_{n}\right) \Delta x=\frac{1}{2}\left(p_{S}-p_{N}\right) \Delta x 120 | $$ 121 | 122 | ## step 4:迭代求解动量方程 123 | 124 | 迭代计算动量方程,得到$u, v$ 125 | 126 | **注意**: 127 | 128 | - 这里不需要完全收敛 129 | - 课程中求解的是correction form + inertial damping形式,需要自己写迭代算法,这里暂时使用迭代求解器 130 | 131 | 这里可以进一步写出速度的表达式,以供后面推导使用: 132 | 133 | $$ 134 | \hat{u}_{O}=-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{u}_{n b}\bigg|_{O}+\frac{\left(p_{W}^{(k)}-p_{E}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \tag{1}\\ 135 | \hat{v}_{O}=-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{v}_{n b}\bigg|_{O}+\frac{\left(p_{s}^{(k)}-p_{N}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta x 136 | $$ 137 | 138 | ## step 5:PWIM差值计算速度face value 139 | 140 | 用上面的式子,表达east方向的中心速度: 141 | 142 | $$ 143 | \hat{u}_{E}=-\frac{1}{\left.A_{O}\right|_{E}} \sum_{n b} A_{n b}\bigg|_{E} \hat{u}_{n b}\bigg|_{E}+\frac{\left(p_{O}^{(k)}-p_{E E}^{(k)}\right)}{\left.2 A_{O}\right|_{E}} \Delta y \tag{2} 144 | $$ 145 | 146 | 假设east方向的面上有一个速度,可以类似地表达为: 147 | 148 | $$ 149 | \hat{u}_{e}=-\frac{1}{\left.A_{O}\right|_{e}} \sum_{n b} A_{n b}\bigg|_{e} \hat{u}_{n b}\bigg|_{e}+\frac{\left(p_{O}^{(k)}-p_{E}^{(k)}\right)}{\left.A_{O}\right|_{e}} \Delta y \tag{3} 150 | $$ 151 | 152 | 但是上式与面相关的值(如:$A_O\big|_e$)我们都不知道,因此可以用cell value做平均: 153 | 154 | $$ 155 | \frac{1}{\left.A_{O}\right|_{e}} \sum_{n b} A_{n b}\bigg|_{e} \hat{u}_{n b}\bigg|_{e}=\frac{1}{2}\left[\frac{1}{\left.A_{O}\right|_{E}} \sum_{n b} A_{n b}\bigg|_{E} \hat{u}_{n b}\bigg|_{E}+\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{u}_{n b}\bigg|_{O}\right] \tag{4} 156 | $$ 157 | 158 | $$ 159 | \frac{1}{\left.A_{O}\right|_{e}}=\frac{1}{2}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \tag{5} 160 | $$ 161 | 162 | $A_O\big|_e$类似在做调和平均。 163 | 164 | 将式$(4), (5)$带入式$(3)$,得到: 165 | 166 | $$ 167 | \hat{u}_{e}=-\frac{1}{2}\left[\frac{1}{\left.A_{O}\right|_{E}} \sum_{n b} A_{n b}\bigg|_{E} \hat{u}_{n b}\bigg|_{E}+\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{u}_{n b}\bigg|_{O}\right]\\ 168 | +\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{(k)}-p_{E}^{(k)}\right)}{2} \Delta y \tag{6} 169 | $$ 170 | 171 | 利用式$(1), (2)$的关系有: 172 | 173 | $$ 174 | -\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{u}_{n b}\bigg|_{O}=\hat{u}_{O}-\frac{\left(p_{W}^{(k)}-p_{E}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \\ 175 | -\frac{1}{\left.A_{O}\right|_{E}} \sum_{n b} A_{n b}\bigg|_{E} \hat{u}_{n b}\bigg|_{E}=\hat{u}_{E}-\frac{\left(p_{O}^{(k)}-p_{E E}^{(k)}\right)}{\left.2 A_{O}\right|_{E}} \Delta y \tag{7} 176 | $$ 177 | 178 | 将式$(7)$带入式$(6)$得到: 179 | 180 | $$ 181 | \hat{u}_{e}=\frac{1}{2}\left[\hat{u}_{O}-\frac{\left(p_{W}^{(k)}-p_{E}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y+\hat{u}_{E}-\frac{\left(p_{O}^{(k)}-p_{E E}^{(k)}\right)}{\left.2 A_{o}\right|_{E}} \Delta y\right]+\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{(k)}-p_{E}^{(k)}\right)}{2} \Delta y 182 | $$ 183 | 184 | 整理得到: 185 | 186 | $$ 187 | \hat{u}_{e}=\frac{1}{2}\left(\hat{u}_{O}+\hat{u}_{E}\right)+\frac{1}{2} \frac{\left(p_{E}^{(k)}-p_{W}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y+\frac{1}{2} \frac{\left(p_{E E}^{(k)}-p_{O}^{(k)}\right)}{\left.2 A_{O}\right|_{E}} \Delta y-\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{E}^{(k)}-p_{O}^{(k)}\right)}{2} \Delta y 188 | $$ 189 | 190 | 这里得到的就是**PWIM差值格式**,用来差值速度的face value。可以看到,对于同位网格,速度的face value除了用cell value平均,还得额外加上压力的影响。 191 | 192 | **注意**:这个差值格式只在$k>1$以后才开始使用,第一次迭代只用简单的平均。 193 | 194 | 为了进一步推导方便,将上式写成微分形式: 195 | 196 | $$ 197 | \hat{u}_{e}=\frac{1}{2}\left(\hat{u}_{O}+\hat{u}_{E}\right)+\frac{1}{2} \Delta x \Delta y\left[\left.\frac{1}{\left.A_{O}\right|_{O}} \frac{\partial p^{(k)}}{\partial x}\right|_{O}+\left.\frac{1}{\left.A_{O}\right|_{E}} \frac{\partial p^{(k)}}{\partial x}\right|_{E}-\left.\left(\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right) \frac{\partial p^{(k)}}{\partial x}\right|_{e}\right] 198 | $$ 199 | 200 | 类似Y方向的速度: 201 | 202 | $$ 203 | \hat{v}_{n}=\frac{1}{2}\left(\hat{v}_{O}+\hat{v}_{N}\right)+\frac{1}{2} \frac{\left(p_{N}^{(k)}-p_{S}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta x+\frac{1}{2} \frac{\left(p_{N N}^{(k)}-p_{O}^{(k)}\right)}{\left.2 A_{O}\right|_{N}} \Delta x-\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{N}^{(k)}-p_{O}^{(k)}\right)}{2} \Delta x\\ 204 | 205 | \hat{v}_{n}=\frac{1}{2}\left(\hat{v}_{O}+\hat{v}_{N}\right)+\frac{1}{2} \Delta x \Delta y\left[\left.\frac{1}{\left.A_{O}\right|_{O}} \frac{\partial p^{(k)}}{\partial y}\right|_{O}+\left.\frac{1}{\left.A_{O}\right|_{N}} \frac{\partial p^{(k)}}{\partial y}\right|_{N}-\left.\left(\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right) \frac{\partial p^{(k)}}{\partial y}\right|_{n}\right] 206 | $$ 207 | 208 | **注**:PWIM差值在编程的时候可以封装一个函数 209 | 210 | ## step 6:velocity correction equation 211 | 212 | 接下来推导velocity correction equation 213 | 214 | **注意**:这里既需要修正cell value,也需要修正face value 215 | 216 | - cell value修正 217 | 218 | 这里认为两次outer iteration之间速度差值为$u'$: 219 | 220 | $$ 221 | \hat{u}_{O}=-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{u}_{n b}\bigg|_{O}+\frac{\left(p_{W}^{(k)}-p_{E}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \\ 222 | 223 | \hat{\hat{u}}_{O}=-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} \hat{\hat{u}}_{n b}\bigg|_{O}+\frac{\left(p_{W}^{(k+1)}-p_{E}^{(k+1)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \\ 224 | 225 | u_{O}^{\prime}=\hat{\hat{u}}_{O}-\hat{u}_{O}=-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\bigg|_{O} u_{n b}^{\prime}\bigg|_{O}+\frac{\left(p_{W}^{\prime}-p_{E}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta y 226 | $$ 227 | 228 | 将$-\frac{1}{\left.A_{O}\right|_{O}} \sum_{n b} A_{n b}\big|_{O} u_{n b}^{\prime}\big|_{O}$忽略。因此有: 229 | 230 | $$ 231 | u_{O}^{\prime}=\frac{\left(p_{W}^{\prime}-p_{E}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \quad \text { and } \quad v_{O}^{\prime}=\frac{\left(p_{S}^{\prime}-p_{N}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta x 232 | $$ 233 | 234 | - face value修正 235 | 236 | 和上面步骤类似: 237 | 238 | $$ 239 | \hat{u}_{e}=\frac{1}{2}\left[\hat{u}_{O}-\frac{\left(p_{W}^{(k)}-p_{E}^{(k)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y+\hat{u}_{E}-\frac{\left(p_{O}^{(k)}-p_{E E}^{(k)}\right)}{\left.2 A_{o}\right|_{E}} \Delta y\right] 240 | +\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{(k)}-p_{E}^{(k)}\right)}{2} \Delta y\\ 241 | 242 | \hat{\hat{u}}_{e}=\frac{1}{2}\left[\hat{\hat{u}}_{O}-\frac{\left(p_{W}^{(k+1)}-p_{E}^{(k+1)}\right)}{\left.2 A_{O}\right|_{O}} \Delta y+\hat{\hat{u}}_{E}-\frac{\left(p_{O}^{(k+1)}-p_{E E}^{(k+1)}\right)}{\left.2 A_{O}\right|_{E}} \Delta y\right]\\ 243 | +\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{(k+1)}-p_{E}^{(k+1)}\right)}{2} \Delta y 244 | $$ 245 | 246 | 相减得到: 247 | 248 | $$ 249 | u_{e}^{\prime}=\hat{\hat{u}}_{e}-\hat{u}_{e}\\ 250 | =\frac{1}{2}\left[u_{O}^{\prime}-\frac{\left(p_{W}^{\prime}-p_{E}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta y+u_{E}^{\prime}-\frac{\left(p_{O}^{\prime}-p_{E E}^{\prime}\right)}{\left.2 A_{O}\right|_{E}} \Delta y\right]+\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{E}^{\prime}\right)}{2} \Delta y 251 | $$ 252 | 253 | 进一步化简得到: 254 | 255 | $$ 256 | u_{e}^{\prime}=\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{E}^{\prime}\right)}{2} \Delta y 257 | $$ 258 | 259 | 类似地: 260 | 261 | $$ 262 | v_{n}^{\prime}=\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{N}^{\prime}\right)}{2} \Delta x 263 | $$ 264 | 265 | ## step 7:pressure correction equation 266 | 267 | 推导pressure correction equation 268 | 269 | 由连续性方程有: 270 | 271 | $$ 272 | \begin{array}{l} 273 | \left(\rho_{e} \hat{\hat{u}}_{e}-\rho_{w} \hat{\hat{u}}_{w}\right) \Delta y+\left(\rho_{n} \hat{\hat{v}}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x&=0 \\ 274 | \left(\rho_{e} u_{e}^{\prime}-\rho_{w} u_{w}^{\prime}\right) \Delta y+\left(\rho_{n} v_{n}^{\prime}-\rho_{s} v_{s}^{\prime}\right) \Delta x&= \\ 275 | -\left[\left(\rho_{e} \hat{u}_{e}-\rho_{w} \hat{u}_{w}\right) \Delta y+\left(\rho_{n} \hat{v}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x\right]&=-\dot{m}_\text{imbalance} 276 | \end{array} 277 | $$ 278 | 279 | 将step 6推导的结果带入得到: 280 | 281 | $$ 282 | \left(\rho_{e}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{o}\right|_{o}}\right] \frac{\left(p_{O}^{\prime}-p_{E}^{\prime}\right)}{2}-\rho_{w}\left[\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{W}^{\prime}-p_{O}^{\prime}\right)}{2} \right)(\Delta y)^{2}+ \\ 283 | \left(\rho_{n}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{N}^{\prime}\right)}{2}-\rho_{s}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{S}^{\prime}-p_{O}^{\prime}\right)}{2}\right)(\Delta x)^{2}=-\dot{m}_\text{imbalance} 284 | $$ 285 | 286 | 写成Link coefficients形式: 287 | 288 | $$ 289 | A_{O}^{p} p_{O}^{\prime}+A_{E}^{p} p_{E}^{\prime}+A_{W}^{p} p_{W}^{\prime}+A_{N}^{p} p_{N}^{\prime}+A_{S}^{p} p_{S}^{\prime}=A_{O}^{p} p_{O}^{\prime}+\sum_{n b} A_{n b}^{p} p_{n b}^{\prime}=S_{O}^{p} 290 | $$ 291 | 292 | 其中: 293 | 294 | $$ 295 | A_{E}^{p}=-\frac{\rho_{e}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right], A_{W}^{p}=-\frac{\rho_{w}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 296 | A_{N}^{p}=-\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right], A_{S}^{p}=-\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 297 | A_O^p = -(A_E^p + A_W^p + A_N^p + A_S^p) \\ 298 | S_{O}^{p}=-\left[\left(\rho_{e} \hat{u}_{e}-\rho_{w} \hat{u}_{w}\right) \Delta y+\left(\rho_{n} \hat{v}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x\right]=-\dot{m}_\text{imbalance} 299 | $$ 300 | 301 | ## step 8:压力、速度修正 302 | 303 | 修正压力和速度: 304 | 305 | - cell value 306 | 307 | $$ 308 | p_{O}^{(k+1)}=p_{O}^{(k)}+\omega_{p} p_{O}^{\prime} \\ 309 | 310 | u_{O}^{(k+1)}=\hat{u}_{O}+\omega_{u v} u_{O}^{\prime}=\hat{u}_{O}+\omega_{u w} \frac{\left(p_{W}^{\prime}-p_{E}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta y \\ 311 | 312 | v_{O}^{(k+1)}=\hat{v}_{O}+\omega_{u v} v_{O}^{\prime}=\hat{v}_{O}+\omega_{u w} \frac{\left(p_{S}^{\prime}-p_{N}^{\prime}\right)}{\left.2 A_{O}\right|_{O}} \Delta x 313 | $$ 314 | 315 | - face value 316 | 317 | $$ 318 | u_{e}^{(k+1)}=\hat{u}_{e}+\omega_{uv} u_{e}^{\prime}=\hat{u}_{e}+\omega_{uv}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{E}^{\prime}\right)}{2} \Delta y \\ 319 | 320 | v_{n}^{(k+1)}=\hat{v}_{n}+\omega_{uv} v_{n}^{\prime}=\hat{v}_{n}+\omega_{uv}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{O}^{\prime}-p_{N}^{\prime}\right)}{2} \Delta x 321 | $$ 322 | 323 | 需要注意,对于边界条件给定了速度的face value的时候,就不需要对边界面进行差值了 324 | 325 | **注意**:编程的时候,这里的face value需要保存,以供下一次outer iteration计算Link coefficient时使用。 326 | 327 | 课程中提到,有些人编程会直接保存$\mathbf{U}_\text{face}\cdot\mathbf{n}_\text{face}$这个标量,对于正交网格,有如下关系: 328 | 329 | $$ 330 | \mathbf U_e \cdot \mathbf n_e = u_e, \quad 331 | \mathbf U_w \cdot \mathbf n_w = -u_w, \quad 332 | \mathbf U_n \cdot \mathbf n_n = v_n, \quad 333 | \mathbf U_s \cdot \mathbf n_s = -v_s 334 | $$ 335 | 336 | 因此对于正交网格,保存速度值即可。 337 | 338 | ## SIMPLE流程图 339 | 340 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/2020-08-21_161754.png) 341 | 342 | # 边界条件 343 | 344 | ## Momentum Equations, Walls (No slip) 345 | 346 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822193030.png) 347 | 348 | 假如壁面在左侧,考虑$X$方向动量方程,从通量形式开始推导: 349 | 350 | $$ 351 | \left(J_{e}^{X}-J_{w}^{X}\right) \Delta y+\left(J_{n}^{X}-J_{s}^{X}\right) \Delta x=-\left(p_{e}-p_{w}\right) \Delta y \\ 352 | 353 | J_{w}^{X}=\rho_{w} u_{w} u_{w}-\left.\mu_{w} \frac{\partial u}{\partial x}\right|_{w} = 0 - \left.\mu_{w} \frac{\partial u}{\partial x}\right|_{w} 354 | $$ 355 | 356 | 课程中扩散项给出了二阶形式: 357 | 358 | $$ 359 | \left.\frac{\partial u}{\partial x}\right|_{w} \approx \frac{9 u_{O}-u_{E}-8 u_{w}}{3 \Delta x}=\frac{9 u_{O}-u_{E}}{3 \Delta x} 360 | $$ 361 | 362 | 如果用一阶格式: 363 | 364 | $$ 365 | \left.\frac{\partial u}{\partial x}\right|_{w} \approx \frac{u_O - u_w}{\Delta x / 2} 366 | $$ 367 | 368 | 压力的face value: 369 | 370 | $$ 371 | p_{e}=\left(p_{O}+p_{E}\right) / 2 \\ 372 | p_{w} \approx p_{O} 373 | $$ 374 | 375 | **注意**:通过量纲分析可以得出,壁面法向压降相对流动方向压降可以忽略不计,因此这里有上式的关系。 376 | 377 | 粘度系数的face value用一阶近似: 378 | 379 | $$ 380 | \mu_w \approx \mu_O 381 | $$ 382 | 383 | Link coefficient形式: 384 | 385 | $$ 386 | \begin{aligned}{} 387 | A_{E} &=-\frac{\left|(\rho u)_{e}\right|-(\rho u)_{e}}{2} \Delta y-\frac{\mu_{e}}{\Delta x} \Delta y-\frac{\mu_{O}}{3 \Delta x} \Delta y \\ 388 | 389 | A_{W} &=0 \\ 390 | 391 | A_{N} &=-\frac{\left|(\rho v)_{n}\right|-(\rho v)_{n}}{2} \Delta x-\frac{\mu_{n}}{\Delta y} \Delta x \\ 392 | 393 | A_{S} &=-\frac{\left|(\rho v)_{s}\right|+(\rho v)_{s}}{2} \Delta x-\frac{\mu_{s}}{\Delta y} \Delta x \\ 394 | 395 | A_{O} &=\frac{\left|(\rho u)_{e}\right|+(\rho u)_{e}}{2} \Delta y+\frac{\mu_{e}}{\Delta x} \Delta y+\frac{3 \mu_{O}}{\Delta x} \Delta y \\ 396 | &+\frac{\left|(\rho v)_{n}\right|+(\rho v)_{n}}{2} \Delta x+\frac{\mu_{n}}{\Delta y} \Delta x+\frac{\left|(\rho v)_{s}\right|-(\rho v)_{s}}{2} \Delta x+\frac{\mu_{s}}{\Delta y} \Delta x\\ 397 | 398 | A_{O} & u_{O}+A_{E} u_{E}+A_{N} u_{N}+A_{S} u_{S}=S^{X} \\ 399 | S^{X} &= \left(p_{O}-\frac{p_{O}+p_{E}}{2}\right) \Delta y 400 | 401 | \end{aligned} 402 | $$ 403 | 404 | ## Momentum Equations, Inlet (Fixed velocity) 405 | 406 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822201615.png) 407 | 408 | 假设速度入口在左侧,考虑$X$方向动量方程,从通量形式开始推导: 409 | 410 | $$ 411 | \begin{aligned} 412 | \left(J_{e}^{X}-J_{w}^{X}\right) \Delta y+\left(J_{n}^{X}-J_{s}^{X}\right) \Delta x=-\left(p_{e}-p_{w}\right) \Delta y \\ 413 | J_{w}^{X}=\rho_{w} u_{w} u_{w}-\left.\mu_{w} \frac{\partial u}{\partial x}\right|_{w}=\rho_{i n} u_{i n} u_{i n}-\left.\mu_{i n} \frac{\partial u}{\partial x}\right|_{i n} 414 | \end{aligned} 415 | $$ 416 | 417 | 扩散项二阶近似: 418 | 419 | $$ 420 | \left.\frac{\partial u}{\partial x}\right|_{i n} \approx \frac{9 u_{O}-u_{E}-8 u_{w}}{3 \Delta x}=\frac{9 u_{0}-u_{E}-8 u_{i n}}{3 \Delta x} 421 | $$ 422 | 423 | 一阶近似为: 424 | 425 | $$ 426 | \left.\frac{\partial u}{\partial x}\right|_{i n} \approx \frac{u_O - u_{in}}{\Delta x / 2} 427 | $$ 428 | 429 | 压力的face value: 430 | 431 | $$ 432 | p_{e} = \left(p_{O}+p_{E}\right) / 2 \qquad 2^\text{nd}\text{ order accurate!}\\ 433 | p_{w} \approx p_{O} \qquad \qquad \qquad 1^\text{st}\text{ order accurate!} \\ 434 | p_{w} = \frac{3}{2} p_{O}-\frac{1}{2} p_{E} \qquad 2^\text{nd}\text{ order accurate!} 435 | $$ 436 | 437 | 课程中提到,这里壁面压力为了方便,通常大家只用一阶精度,可以通过增加壁面网格层数减小误差。 438 | 439 | ## Momentum Equations, Inlet (Fixed pressure) 440 | 441 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822205053.png) 442 | 443 | 压力的face value已知: 444 | 445 | $$ 446 | p_{w}=p_{i n} 447 | $$ 448 | 449 | 速度的face value: 450 | 451 | $$ 452 | u_{w}=u_{O} \qquad \qquad 1^{\text {st }} \text{order accurate!} \\ 453 | u_{w}=\frac{3}{2} u_{O}-\frac{1}{2} u_{E} \quad 2^{\text {nd }} \text { order accurate! } 454 | $$ 455 | 456 | **注意**:对于给定压力边界的情况,边界速度是不知道的,迭代过程中也会不断变化,最终收敛时趋于稳定。 457 | 458 | ## Momentum Equations, outlet (Fixed pressure) 459 | 460 | CFD中,出口的速度既可以流入,也可以流出,通常**速度**具体值我们也**无法直接给出**,只能给出压力,而且通常只知道出口的**压力单一值**,而不知道面上的**压力分布**,因此,出口的位置选择就很重要了,要保证出口位置是**充分发展段**,此时截面压力才能假设为单一值,否则会出现**回流问题**,而且计算结果会有问题(即使收敛)。 461 | 462 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822212229.png) 463 | 464 | 假设出口在右侧,$X$方向动量方程通量形式为: 465 | 466 | $$ 467 | \left(J_{e}^{X}-J_{w}^{X}\right) \Delta y+\left(J_{n}^{X}-J_{s}^{X}\right) \Delta x=-\left(p_{e}-p_{w}\right) \Delta y 468 | $$ 469 | 470 | 出口通量: 471 | 472 | $$ 473 | J_{e}^{X}=\rho_{e} u_{e} u_{e}-\left.\mu_{e} \frac{\partial u}{\partial x}\right|_{e} 474 | $$ 475 | 476 | 忽略出口粘性作用,并且将出口速度近似为网格中心速度,出口通量通常简化为: 477 | 478 | $$ 479 | J_{e}^{X}=\rho_{O} u_{O} u_{O} 480 | $$ 481 | 482 | 这里我们实际上采用了一阶迎风格式,且认为速度是从出口流出,如果真实情况产生回流,这样的假设就不再成立,计算结果也不可靠。因此一定要将出口放在充分发展段。 483 | 484 | 压力的face value: 485 | 486 | $$ 487 | \begin{aligned} 488 | p_{w} &=\frac{p_{W}+p_{o}}{2} \\ 489 | p_{e} &=p_{out} \qquad \text{(prescribed BC)} 490 | \end{aligned} 491 | $$ 492 | 493 | Link coefficient形式: 494 | 495 | $$ 496 | \begin{aligned} 497 | A_{E} &=0 \\ 498 | A_{W} &=-\frac{\left|(\rho u)_{w}\right|+(\rho u)_{w}}{2} \Delta y-\frac{\mu_{w}}{\Delta x} \Delta y \\ 499 | A_{N} &=-\frac{\left|(\rho v)_{n}\right|-(\rho v)_{n}}{2} \Delta x-\frac{\mu_{n}}{\Delta y} \Delta x \\ 500 | A_{S} &=-\frac{\left|(\rho v)_{s}\right|+(\rho v)_{s}}{2} \Delta x-\frac{\mu_{s}}{\Delta y} \Delta x \\ 501 | 502 | A_{O} &=\rho_{O} u_{O}+\frac{\left|(\rho u)_{w}\right|-(\rho u)_{w}}{2} \Delta y+\frac{\mu_{w}}{\Delta x} \Delta y+\\ 503 | &+\frac{\left|(\rho v)_{n}\right|+(\rho v)_{n}}{2} \Delta x+\frac{\mu_{n}}{\Delta y} \Delta x+\frac{\left|(\rho v)_{s}\right|-(\rho v)_{s}}{2} \Delta x+\frac{\mu_{s}}{\Delta y} \Delta x \\ 504 | 505 | 506 | A_{O} & u_{O}+A_{W} u_{W}+A_{N} u_{N}+A_{S} u_{S}=S^{X} \\ 507 | S^{X} &=\left(\frac{p_{O}+p_{W}}{2}-p_{{out}}\right) \Delta y 508 | 509 | 510 | \end{aligned} 511 | $$ 512 | 513 | ## Pressure Correction Equations, Walls (No slip) 514 | 515 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822220740.png) 516 | 517 | 由于压力修正方程是以连续性方程为约束条件,因此从连续性方程出发: 518 | 519 | $$ 520 | \left(\rho_{e} \hat{\hat{u}}_{e}-\rho_{w} \hat{\hat{u}}_{w}\right) \Delta y+\left(\rho_{n} \hat{\hat{v}}_{n}-\rho_{s} \hat{\hat{v}}_{s}\right) \Delta x=0 521 | $$ 522 | 523 | 对于壁面$\hat{\hat{u}}_w = 0$,因此壁面处网格的压力修正方程的Link coefficient形式为: 524 | 525 | $$ 526 | \begin{aligned} 527 | A_{O}^{p} &=\frac{\rho_{e}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 528 | 529 | 530 | A_{E}^{p} &=-\frac{\rho_{e}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right]\\ 531 | A_{W}^{p} &=0 \\ 532 | A_{N}^{p} &=-\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right]\\ 533 | A_{s}^{p} &=-\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 534 | S_{O}^{P} &=-\left[\left(\rho_{e} \hat{u}_{e}\right) \Delta y+\left(\rho_{n} \hat{v}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x\right]=-\dot{m}_{i m b a l a n c e} 535 | \end{aligned} 536 | $$ 537 | 538 | ## Pressure Correction Equations, Inlet (Prescribed Velocity) 539 | 540 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822222324.png) 541 | 542 | 同样从连续性方程出发: 543 | 544 | $$ 545 | \left(\rho_{e} \hat{\hat{u}}_{e}-\rho_{w} \hat{\hat{u}}_{w}\right) \Delta y+\left(\rho_{n} \hat{\hat{v}}_{n}-\rho_{s} \hat{\hat{v}}_{s}\right) \Delta x=0 546 | $$ 547 | 548 | 对于速度入口处网格,有$\rho_w \hat{\hat{u}}_w = \rho_{in} u_{in}$,因此速度入口处网格的压力修正方程的Link coefficient形式为: 549 | 550 | $$ 551 | \begin{aligned} 552 | A_{O}^{p} &=\frac{\rho_{e}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 553 | 554 | A_{E}^{p} &=-\frac{\rho_{e}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{o}\right|_{E}}+\frac{1}{\left.A_{o}\right|_{o}}\right] \\ 555 | A_{W}^{p} &=0 \\ 556 | A_{N}^{p} &=-\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right]\\ 557 | A_{S}^{p} &=-\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 558 | S_{o}^{P} &=-\left[\left(\rho_{e} \hat{u}_{e}-\rho_{i n} u_{i n}\right) \Delta y+\left(\rho_{n} \hat{v}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x\right]=-\dot{m}_{i m b a l a n c e} 559 | \end{aligned} 560 | $$ 561 | 562 | **注意**:边界处的velocity correction永远为$0$ 563 | 564 | ## Pressure Correction Equations, Outlet (Fixed Pressure) 565 | 566 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200822225702.png) 567 | 568 | 从连续性方程出发: 569 | 570 | $$ 571 | \left(\rho_{e} \hat{\hat{u}}_{e}-\rho_{w} \hat{\hat{u}}_{w}\right) \Delta y+\left(\rho_{n} \hat{\hat{v}}_{n}-\rho_{s} \hat{\hat{v}}_{s}\right) \Delta x=0 572 | $$ 573 | 574 | 对于真正的出口,应该有$\rho_{e} \hat{\hat{u}}_{e}=\rho_{O} \hat{\hat{u}}_{O}$,因此: 575 | 576 | $$ 577 | \left(\rho_{O} \hat{\hat{u}}_{O}-\rho_{w} \hat{\hat{u}}_{w}\right) \Delta y+\left(\rho_{n} \hat{\hat{v}}_{n}-\rho_{s} \hat{\hat{v}}_{s}\right) \Delta x=0 \\ 578 | 579 | \left(\rho_{O} u_{O}^{\prime}-\rho_{w} u_{w}^{\prime}\right) \Delta y+\left(\rho_{n} v_{n}^{\prime}-\rho_{s} v_{s}^{\prime}\right) \Delta x=-\left[\left(\rho_{O} \hat{u}_{O}-\rho_{w} \hat{u}_{w}\right) \Delta y+\left(\rho_{n} \hat{v}_{n}-\rho_{s} \hat{v}_{s}\right) \Delta x\right] 580 | $$ 581 | 582 | 其中: 583 | 584 | $$ 585 | \begin{aligned} 586 | u_{O}^{\prime} &=\frac{\Delta y}{\left.A_{O}\right|_{O}}\left(p_{w}^{\prime}-p_{e}^{\prime}\right)=\frac{\Delta y}{\left.A_{O}\right|_{O}}\left(\frac{p_{W}^{\prime}+p_{O}^{\prime}}{2}-p_{e}^{\prime}\right)=\frac{\Delta y}{\left.A_{O}\right|_{O}}\left(\frac{p_{W}^{\prime}+p_{O}^{\prime}}{2}-0\right) \\ 587 | 588 | u_{w}^{\prime} &=\left[\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \frac{\left(p_{W}^{\prime}-p_{O}^{\prime}\right)}{2} \Delta y \quad \text { etc. } 589 | \end{aligned} 590 | $$ 591 | 592 | 注意到,$u_O'$需要特殊处理,即出口的压力保持不变,因此压力修正为$0$,其他方向保持不变。 593 | 594 | 因此压力修正方程,在压力出口处网格的Link coefficient形式为: 595 | 596 | $$ 597 | \begin{aligned} 598 | A_{W}^{p} &=-\frac{\rho_{w}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{O}(\Delta y)^{2}}{\left.2 A_{O}\right|_{O}}\\ 599 | 600 | A_{E}^{p} &=0 \\ 601 | 602 | A_{N}^{p} &=-\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 603 | 604 | A_{S}^{p} &=-\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] \\ 605 | 606 | 607 | A_{O}^{p} &=\frac{\rho_{w}(\Delta y)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{O}(\Delta y)^{2}}{\left.2 A_{O}\right|_{O}} \\ 608 | &+\frac{\rho_{n}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{N}}+\frac{1}{\left.A_{O}\right|_{O}}\right]+\frac{\rho_{s}(\Delta x)^{2}}{2}\left[\frac{1}{\left.A_{O}\right|_{S}}+\frac{1}{\left.A_{O}\right|_{O}}\right] 609 | 610 | \end{aligned} 611 | $$ 612 | 613 | **注意**:压力出口处的Link coefficient**不再满足**$A_O = -(A_W + A_E + A_N + A_S)$,$\frac{\rho_{O}(\Delta y)^{2}}{\left.2 A_{O}\right|_{O}}$这一项在$A_O$和$A_W$中前面都是正号。 614 | 615 | # PWIM格式计算边界速度 616 | 617 | ## Inlet / Wall 618 | 619 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200823145305.png) 620 | 621 | 左侧边界速度直接根据边界条件给出: 622 | 623 | $$ 624 | \begin{array}{ll} 625 | \text { Inlet: } & \hat{u}_{w}=u_{i n} \\ 626 | \text { Wall: } & \hat{u}_{w}=0 627 | \end{array} 628 | $$ 629 | 630 | 右侧速度根据前面推导的结果: 631 | 632 | $$ 633 | \hat{u}_{e}=\frac{1}{2}\left(\hat{u}_{O}+\hat{u}_{E}\right)+\frac{1}{2} \Delta x \Delta y\left[\left.\frac{1}{\left.A_{O}\right|_{O}} \frac{\partial p}{\partial x}\right|_{O}+\left.\frac{1}{\left.A_{O}\right|_{E}} \frac{\partial p}{\partial x}\right|_{E}-\left.\left(\frac{1}{\left.A_{O}\right|_{E}}+\frac{1}{\left.A_{O}\right|_{O}}\right) \frac{\partial p}{\partial x}\right|_{e}\right] 634 | $$ 635 | 636 | 其中$\left. \frac{\partial p}{\partial x} \right|_O$无法再通过左右两侧的网格中心压力计算出来,因为左侧为边界,没有网格,因此这里我们用face value计算: 637 | 638 | $$ 639 | \left.\frac{\partial p}{\partial x}\right|_{O}=\frac{p_{e}-p_{w}}{\Delta x}=\frac{1}{\Delta x}\left[\frac{p_{E}+p_{O}}{2}-p_{w}\right] 640 | $$ 641 | 642 | 左侧压力如果采用一阶精度有: 643 | 644 | $$ 645 | p_{w}=p_{O} 646 | $$ 647 | 648 | **注意**:这里边界$p_w$使用的阶数需要和动量方程保持一致。 649 | 650 | ## Outlet 651 | 652 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200823150627.png) 653 | 654 | 右侧出口边界速度由一阶迎风给出: 655 | 656 | $$ 657 | \hat{u}_{e}=\hat{u}_{O} 658 | $$ 659 | 660 | 左侧速度PWIM格式: 661 | 662 | $$ 663 | \hat{u}_{w}=\frac{1}{2}\left(\hat{u}_{O}+\hat{u}_{W}\right)+\frac{1}{2} \Delta x \Delta y\left[\left.\frac{1}{\left.A_{O}\right|_{O}} \frac{\partial p}{\partial x}\right|_{O}+\left.\frac{1}{\left.A_{O}\right|_{W}} \frac{\partial p}{\partial x}\right|_{W}-\left.\left(\frac{1}{\left.A_{O}\right|_{W}}+\frac{1}{\left.A_{O}\right|_{O}}\right) \frac{\partial p}{\partial x}\right|_{w}\right] 664 | $$ 665 | 666 | 同样地,$\left. \frac{\partial p}{\partial x} \right|_O$也无法用两侧cell value求出,因此只能用face value求得: 667 | 668 | $$ 669 | \left.\frac{\partial p}{\partial x}\right|_{O}=\frac{p_{e}-p_{w}}{\Delta x}=\frac{1}{\Delta x}\left[p_{{out}}-\frac{p_{W}+p_{O}}{2}\right] 670 | $$ 671 | 672 | **注意**:不要计算两次face value,相邻网格只要有一个计算了face value就可以了。 673 | 674 | # 算例 675 | 676 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200823152548.png) 677 | 678 | ![](https://md-pic-1259272405.cos.ap-guangzhou.myqcloud.com/img/20200823153443.png) 679 | -------------------------------------------------------------------------------- /u.csv: -------------------------------------------------------------------------------- 1 | x, y, z, u 2 | 0, 0, 0, 0 3 | 0.02, 0, 0, 0 4 | 0.04, 0, 0, 0 5 | 0.06, 0, 0, 0 6 | 0.08, 0, 0, 0 7 | 0.1, 0, 0, 0 8 | 0.12, 0, 0, 0 9 | 0.14, 0, 0, 0 10 | 0.16, 0, 0, 0 11 | 0.18, 0, 0, 0 12 | 0.2, 0, 0, 0 13 | 0.22, 0, 0, 0 14 | 0.24, 0, 0, 0 15 | 0.26, 0, 0, 0 16 | 0.28, 0, 0, 0 17 | 0.3, 0, 0, 0 18 | 0.32, 0, 0, 0 19 | 0.34, 0, 0, 0 20 | 0.36, 0, 0, 0 21 | 0.38, 0, 0, 0 22 | 0.4, 0, 0, 0 23 | 0.42, 0, 0, 0 24 | 0.44, 0, 0, 0 25 | 0.46, 0, 0, 0 26 | 0.48, 0, 0, 0 27 | 0.5, 0, 0, 0 28 | 0.52, 0, 0, 0 29 | 0.54, 0, 0, 0 30 | 0.56, 0, 0, 0 31 | 0.58, 0, 0, 0 32 | 0.6, 0, 0, 0 33 | 0.62, 0, 0, 0 34 | 0.64, 0, 0, 0 35 | 0.66, 0, 0, 0 36 | 0.68, 0, 0, 0 37 | 0.7, 0, 0, 0 38 | 0.72, 0, 0, 0 39 | 0.74, 0, 0, 0 40 | 0.76, 0, 0, 0 41 | 0.78, 0, 0, 0 42 | 0.8, 0, 0, 0 43 | 0.82, 0, 0, 0 44 | 0.84, 0, 0, 0 45 | 0.86, 0, 0, 0 46 | 0.88, 0, 0, 0 47 | 0.9, 0, 0, 0 48 | 0.92, 0, 0, 0 49 | 0.94, 0, 0, 0 50 | 0.96, 0, 0, 0 51 | 0.98, 0, 0, 0 52 | 1, 0, 0, 0 53 | 0, 1, 0, 0.5 54 | 0.02, 1, 0, 1 55 | 0.04, 1, 0, 1 56 | 0.06, 1, 0, 1 57 | 0.08, 1, 0, 1 58 | 0.1, 1, 0, 1 59 | 0.12, 1, 0, 1 60 | 0.14, 1, 0, 1 61 | 0.16, 1, 0, 1 62 | 0.18, 1, 0, 1 63 | 0.2, 1, 0, 1 64 | 0.22, 1, 0, 1 65 | 0.24, 1, 0, 1 66 | 0.26, 1, 0, 1 67 | 0.28, 1, 0, 1 68 | 0.3, 1, 0, 1 69 | 0.32, 1, 0, 1 70 | 0.34, 1, 0, 1 71 | 0.36, 1, 0, 1 72 | 0.38, 1, 0, 1 73 | 0.4, 1, 0, 1 74 | 0.42, 1, 0, 1 75 | 0.44, 1, 0, 1 76 | 0.46, 1, 0, 1 77 | 0.48, 1, 0, 1 78 | 0.5, 1, 0, 1 79 | 0.52, 1, 0, 1 80 | 0.54, 1, 0, 1 81 | 0.56, 1, 0, 1 82 | 0.58, 1, 0, 1 83 | 0.6, 1, 0, 1 84 | 0.62, 1, 0, 1 85 | 0.64, 1, 0, 1 86 | 0.66, 1, 0, 1 87 | 0.68, 1, 0, 1 88 | 0.7, 1, 0, 1 89 | 0.72, 1, 0, 1 90 | 0.74, 1, 0, 1 91 | 0.76, 1, 0, 1 92 | 0.78, 1, 0, 1 93 | 0.8, 1, 0, 1 94 | 0.82, 1, 0, 1 95 | 0.84, 1, 0, 1 96 | 0.86, 1, 0, 1 97 | 0.88, 1, 0, 1 98 | 0.9, 1, 0, 1 99 | 0.92, 1, 0, 1 100 | 0.94, 1, 0, 1 101 | 0.96, 1, 0, 1 102 | 0.98, 1, 0, 1 103 | 1, 1, 0, 0.5 104 | 0, 0.04, 0, 0 105 | 0, 0.08, 0, 0 106 | 0, 0.12, 0, 0 107 | 0, 0.16, 0, 0 108 | 0, 0.2, 0, 0 109 | 0, 0.24, 0, 0 110 | 0, 0.28, 0, 0 111 | 0, 0.32, 0, 0 112 | 0, 0.36, 0, 0 113 | 0, 0.4, 0, 0 114 | 0, 0.44, 0, 0 115 | 0, 0.48, 0, 0 116 | 0, 0.52, 0, 0 117 | 0, 0.56, 0, 0 118 | 0, 0.6, 0, 0 119 | 0, 0.64, 0, 0 120 | 0, 0.68, 0, 0 121 | 0, 0.72, 0, 0 122 | 0, 0.76, 0, 0 123 | 0, 0.8, 0, 0 124 | 0, 0.84, 0, 0 125 | 0, 0.88, 0, 0 126 | 0, 0.92, 0, 0 127 | 0, 0.96, 0, 0 128 | 1, 0.04, 0, 0 129 | 1, 0.08, 0, 0 130 | 1, 0.12, 0, 0 131 | 1, 0.16, 0, 0 132 | 1, 0.2, 0, 0 133 | 1, 0.24, 0, 0 134 | 1, 0.28, 0, 0 135 | 1, 0.32, 0, 0 136 | 1, 0.36, 0, 0 137 | 1, 0.4, 0, 0 138 | 1, 0.44, 0, 0 139 | 1, 0.48, 0, 0 140 | 1, 0.52, 0, 0 141 | 1, 0.56, 0, 0 142 | 1, 0.6, 0, 0 143 | 1, 0.64, 0, 0 144 | 1, 0.68, 0, 0 145 | 1, 0.72, 0, 0 146 | 1, 0.76, 0, 0 147 | 1, 0.8, 0, 0 148 | 1, 0.84, 0, 0 149 | 1, 0.88, 0, 0 150 | 1, 0.92, 0, 0 151 | 1, 0.96, 0, 0 152 | 0.02, 0.04, 0, 0.000728682 153 | 0.04, 0.04, 0, 0.00145452 154 | 0.06, 0.04, 0, 0.00217429 155 | 0.08, 0.04, 0, 0.00288501 156 | 0.1, 0.04, 0, 0.00358375 157 | 0.12, 0.04, 0, 0.00426763 158 | 0.14, 0.04, 0, 0.00493389 159 | 0.16, 0.04, 0, 0.00558007 160 | 0.18, 0.04, 0, 0.00620357 161 | 0.2, 0.04, 0, 0.00680166 162 | 0.22, 0.04, 0, 0.00737203 163 | 0.24, 0.04, 0, 0.00791248 164 | 0.26, 0.04, 0, 0.00842096 165 | 0.28, 0.04, 0, 0.00889556 166 | 0.3, 0.04, 0, 0.00933455 167 | 0.32, 0.04, 0, 0.00973637 168 | 0.34, 0.04, 0, 0.0100996 169 | 0.36, 0.04, 0, 0.0104233 170 | 0.38, 0.04, 0, 0.010706 171 | 0.4, 0.04, 0, 0.0109474 172 | 0.42, 0.04, 0, 0.0111467 173 | 0.44, 0.04, 0, 0.0113021 174 | 0.46, 0.04, 0, 0.0114133 175 | 0.48, 0.04, 0, 0.0114799 176 | 0.5, 0.04, 0, 0.0115018 177 | 0.52, 0.04, 0, 0.0114788 178 | 0.54, 0.04, 0, 0.0114113 179 | 0.56, 0.04, 0, 0.0112994 180 | 0.58, 0.04, 0, 0.0111436 181 | 0.6, 0.04, 0, 0.0109446 182 | 0.62, 0.04, 0, 0.0107042 183 | 0.64, 0.04, 0, 0.0104231 184 | 0.66, 0.04, 0, 0.0101008 185 | 0.68, 0.04, 0, 0.0097382 186 | 0.7, 0.04, 0, 0.00933674 187 | 0.72, 0.04, 0, 0.00889791 188 | 0.74, 0.04, 0, 0.00842336 189 | 0.76, 0.04, 0, 0.0079149 190 | 0.78, 0.04, 0, 0.00737445 191 | 0.8, 0.04, 0, 0.00680408 192 | 0.82, 0.04, 0, 0.00620601 193 | 0.84, 0.04, 0, 0.00558257 194 | 0.86, 0.04, 0, 0.00493624 195 | 0.88, 0.04, 0, 0.00426961 196 | 0.9, 0.04, 0, 0.00358535 197 | 0.92, 0.04, 0, 0.00288626 198 | 0.94, 0.04, 0, 0.00217521 199 | 0.96, 0.04, 0, 0.00145512 200 | 0.98, 0.04, 0, 0.000728982 201 | 0.02, 0.08, 0, 0.00146876 202 | 0.04, 0.08, 0, 0.00293177 203 | 0.06, 0.08, 0, 0.00438252 204 | 0.08, 0.08, 0, 0.00581498 205 | 0.1, 0.08, 0, 0.00722321 206 | 0.12, 0.08, 0, 0.0086014 207 | 0.14, 0.08, 0, 0.00994418 208 | 0.16, 0.08, 0, 0.0112463 209 | 0.18, 0.08, 0, 0.0125024 210 | 0.2, 0.08, 0, 0.0137073 211 | 0.22, 0.08, 0, 0.0148563 212 | 0.24, 0.08, 0, 0.0159449 213 | 0.26, 0.08, 0, 0.016969 214 | 0.28, 0.08, 0, 0.0179247 215 | 0.3, 0.08, 0, 0.0188086 216 | 0.32, 0.08, 0, 0.0196173 217 | 0.34, 0.08, 0, 0.020348 218 | 0.36, 0.08, 0, 0.021 219 | 0.38, 0.08, 0, 0.0215708 220 | 0.4, 0.08, 0, 0.0220573 221 | 0.42, 0.08, 0, 0.0224578 222 | 0.44, 0.08, 0, 0.0227702 223 | 0.46, 0.08, 0, 0.0229938 224 | 0.48, 0.08, 0, 0.0231276 225 | 0.5, 0.08, 0, 0.0231714 226 | 0.52, 0.08, 0, 0.0231251 227 | 0.54, 0.08, 0, 0.0229889 228 | 0.56, 0.08, 0, 0.0227633 229 | 0.58, 0.08, 0, 0.0224492 230 | 0.6, 0.08, 0, 0.0220502 231 | 0.62, 0.08, 0, 0.0215682 232 | 0.64, 0.08, 0, 0.0210021 233 | 0.66, 0.08, 0, 0.0203526 234 | 0.68, 0.08, 0, 0.0196222 235 | 0.7, 0.08, 0, 0.0188136 236 | 0.72, 0.08, 0, 0.0179298 237 | 0.74, 0.08, 0, 0.016974 238 | 0.76, 0.08, 0, 0.0159498 239 | 0.78, 0.08, 0, 0.0148611 240 | 0.8, 0.08, 0, 0.0137121 241 | 0.82, 0.08, 0, 0.0125071 242 | 0.84, 0.08, 0, 0.011251 243 | 0.86, 0.08, 0, 0.00994867 244 | 0.88, 0.08, 0, 0.0086053 245 | 0.9, 0.08, 0, 0.00722634 246 | 0.92, 0.08, 0, 0.00581741 247 | 0.94, 0.08, 0, 0.0043843 248 | 0.96, 0.08, 0, 0.00293294 249 | 0.98, 0.08, 0, 0.00146934 250 | 0.02, 0.12, 0, 0.00223341 251 | 0.04, 0.12, 0, 0.00445802 252 | 0.06, 0.12, 0, 0.00666391 253 | 0.08, 0.12, 0, 0.00884186 254 | 0.1, 0.12, 0, 0.0109828 255 | 0.12, 0.12, 0, 0.0130779 256 | 0.14, 0.12, 0, 0.0151187 257 | 0.16, 0.12, 0, 0.0170975 258 | 0.18, 0.12, 0, 0.0190061 259 | 0.2, 0.12, 0, 0.0208367 260 | 0.22, 0.12, 0, 0.022582 261 | 0.24, 0.12, 0, 0.0242354 262 | 0.26, 0.12, 0, 0.0257905 263 | 0.28, 0.12, 0, 0.0272415 264 | 0.3, 0.12, 0, 0.028583 265 | 0.32, 0.12, 0, 0.0298099 266 | 0.34, 0.12, 0, 0.0309197 267 | 0.36, 0.12, 0, 0.0319103 268 | 0.38, 0.12, 0, 0.0327768 269 | 0.4, 0.12, 0, 0.0335145 270 | 0.42, 0.12, 0, 0.034121 271 | 0.44, 0.12, 0, 0.0345943 272 | 0.46, 0.12, 0, 0.0349328 273 | 0.48, 0.12, 0, 0.0351355 274 | 0.5, 0.12, 0, 0.0352017 275 | 0.52, 0.12, 0, 0.0351311 276 | 0.54, 0.12, 0, 0.0349239 277 | 0.56, 0.12, 0, 0.034581 278 | 0.58, 0.12, 0, 0.0341069 279 | 0.6, 0.12, 0, 0.0335054 280 | 0.62, 0.12, 0, 0.0327746 281 | 0.64, 0.12, 0, 0.0319145 282 | 0.66, 0.12, 0, 0.0309282 283 | 0.68, 0.12, 0, 0.0298192 284 | 0.7, 0.12, 0, 0.0285914 285 | 0.72, 0.12, 0, 0.0272494 286 | 0.74, 0.12, 0, 0.0257981 287 | 0.76, 0.12, 0, 0.0242427 288 | 0.78, 0.12, 0, 0.0225892 289 | 0.8, 0.12, 0, 0.0208437 290 | 0.82, 0.12, 0, 0.0190131 291 | 0.84, 0.12, 0, 0.0171044 292 | 0.86, 0.12, 0, 0.0151252 293 | 0.88, 0.12, 0, 0.0130833 294 | 0.9, 0.12, 0, 0.0109872 295 | 0.92, 0.12, 0, 0.00884528 296 | 0.94, 0.12, 0, 0.00666643 297 | 0.96, 0.12, 0, 0.00445967 298 | 0.98, 0.12, 0, 0.00223423 299 | 0.02, 0.16, 0, 0.0030356 300 | 0.04, 0.16, 0, 0.00605916 301 | 0.06, 0.16, 0, 0.00905709 302 | 0.08, 0.16, 0, 0.0120168 303 | 0.1, 0.16, 0, 0.0149259 304 | 0.12, 0.16, 0, 0.0177722 305 | 0.14, 0.16, 0, 0.0205443 306 | 0.16, 0.16, 0, 0.023231 307 | 0.18, 0.16, 0, 0.025822 308 | 0.2, 0.16, 0, 0.0283069 309 | 0.22, 0.16, 0, 0.0306755 310 | 0.24, 0.16, 0, 0.0329188 311 | 0.26, 0.16, 0, 0.0350284 312 | 0.28, 0.16, 0, 0.0369965 313 | 0.3, 0.16, 0, 0.0388158 314 | 0.32, 0.16, 0, 0.0404798 315 | 0.34, 0.16, 0, 0.0419844 316 | 0.36, 0.16, 0, 0.0433262 317 | 0.38, 0.16, 0, 0.0444988 318 | 0.4, 0.16, 0, 0.0454969 319 | 0.42, 0.16, 0, 0.0463173 320 | 0.44, 0.16, 0, 0.0469575 321 | 0.46, 0.16, 0, 0.0474154 322 | 0.48, 0.16, 0, 0.0476895 323 | 0.5, 0.16, 0, 0.0477789 324 | 0.52, 0.16, 0, 0.0476832 325 | 0.54, 0.16, 0, 0.0474024 326 | 0.56, 0.16, 0, 0.0469409 327 | 0.58, 0.16, 0, 0.0463041 328 | 0.6, 0.16, 0, 0.0454903 329 | 0.62, 0.16, 0, 0.0444984 330 | 0.64, 0.16, 0, 0.0433319 331 | 0.66, 0.16, 0, 0.0419945 332 | 0.68, 0.16, 0, 0.0404909 333 | 0.7, 0.16, 0, 0.0388263 334 | 0.72, 0.16, 0, 0.0370066 335 | 0.74, 0.16, 0, 0.0350382 336 | 0.76, 0.16, 0, 0.0329284 337 | 0.78, 0.16, 0, 0.0306849 338 | 0.8, 0.16, 0, 0.0283162 339 | 0.82, 0.16, 0, 0.0258312 340 | 0.84, 0.16, 0, 0.0232398 341 | 0.86, 0.16, 0, 0.020552 342 | 0.88, 0.16, 0, 0.0177787 343 | 0.9, 0.16, 0, 0.0149311 344 | 0.92, 0.16, 0, 0.0120209 345 | 0.94, 0.16, 0, 0.00906014 346 | 0.96, 0.16, 0, 0.00606117 347 | 0.98, 0.16, 0, 0.0030366 348 | 0.02, 0.2, 0, 0.00388919 349 | 0.04, 0.2, 0, 0.00776279 350 | 0.06, 0.2, 0, 0.0116032 351 | 0.08, 0.2, 0, 0.0153942 352 | 0.1, 0.2, 0, 0.0191197 353 | 0.12, 0.2, 0, 0.0227642 354 | 0.14, 0.2, 0, 0.0263126 355 | 0.16, 0.2, 0, 0.0297505 356 | 0.18, 0.2, 0, 0.0330644 357 | 0.2, 0.2, 0, 0.0362419 358 | 0.22, 0.2, 0, 0.0392702 359 | 0.24, 0.2, 0, 0.0421373 360 | 0.26, 0.2, 0, 0.0448326 361 | 0.28, 0.2, 0, 0.0473465 362 | 0.3, 0.2, 0, 0.04967 363 | 0.32, 0.2, 0, 0.0517954 364 | 0.34, 0.2, 0, 0.0537155 365 | 0.36, 0.2, 0, 0.0554251 366 | 0.38, 0.2, 0, 0.0569187 367 | 0.4, 0.2, 0, 0.05819 368 | 0.42, 0.2, 0, 0.0592346 369 | 0.44, 0.2, 0, 0.0600498 370 | 0.46, 0.2, 0, 0.0606331 371 | 0.48, 0.2, 0, 0.0609821 372 | 0.5, 0.2, 0, 0.0610964 373 | 0.52, 0.2, 0, 0.0609758 374 | 0.54, 0.2, 0, 0.0606201 375 | 0.56, 0.2, 0, 0.0600366 376 | 0.58, 0.2, 0, 0.0592273 377 | 0.6, 0.2, 0, 0.0581879 378 | 0.62, 0.2, 0, 0.0569216 379 | 0.64, 0.2, 0, 0.0554326 380 | 0.66, 0.2, 0, 0.0537258 381 | 0.68, 0.2, 0, 0.0518067 382 | 0.7, 0.2, 0, 0.0496818 383 | 0.72, 0.2, 0, 0.0473583 384 | 0.74, 0.2, 0, 0.0448443 385 | 0.76, 0.2, 0, 0.0421488 386 | 0.78, 0.2, 0, 0.0392816 387 | 0.8, 0.2, 0, 0.0362533 388 | 0.82, 0.2, 0, 0.0330755 389 | 0.84, 0.2, 0, 0.0297604 390 | 0.86, 0.2, 0, 0.0263211 391 | 0.88, 0.2, 0, 0.0227713 392 | 0.9, 0.2, 0, 0.0191255 393 | 0.92, 0.2, 0, 0.0153988 394 | 0.94, 0.2, 0, 0.0116066 395 | 0.96, 0.2, 0, 0.00776505 396 | 0.98, 0.2, 0, 0.00389031 397 | 0.02, 0.24, 0, 0.00480932 398 | 0.04, 0.24, 0, 0.00959907 399 | 0.06, 0.24, 0, 0.0143472 400 | 0.08, 0.24, 0, 0.0190334 401 | 0.1, 0.24, 0, 0.0236376 402 | 0.12, 0.24, 0, 0.0281403 403 | 0.14, 0.24, 0, 0.032523 404 | 0.16, 0.24, 0, 0.0367676 405 | 0.18, 0.24, 0, 0.0408572 406 | 0.2, 0.24, 0, 0.0447766 407 | 0.22, 0.24, 0, 0.0485102 408 | 0.24, 0.24, 0, 0.052043 409 | 0.26, 0.24, 0, 0.0553629 410 | 0.28, 0.24, 0, 0.0584579 411 | 0.3, 0.24, 0, 0.0613178 412 | 0.32, 0.24, 0, 0.0639332 413 | 0.34, 0.24, 0, 0.0662953 414 | 0.36, 0.24, 0, 0.0683961 415 | 0.38, 0.24, 0, 0.0702296 416 | 0.4, 0.24, 0, 0.0717897 417 | 0.42, 0.24, 0, 0.0730716 418 | 0.44, 0.24, 0, 0.0740719 419 | 0.46, 0.24, 0, 0.0747875 420 | 0.48, 0.24, 0, 0.0752159 421 | 0.5, 0.24, 0, 0.0753555 422 | 0.52, 0.24, 0, 0.0752092 423 | 0.54, 0.24, 0, 0.0747791 424 | 0.56, 0.24, 0, 0.0740662 425 | 0.58, 0.24, 0, 0.0730708 426 | 0.6, 0.24, 0, 0.0717928 427 | 0.62, 0.24, 0, 0.070236 428 | 0.64, 0.24, 0, 0.0684053 429 | 0.66, 0.24, 0, 0.0663064 430 | 0.68, 0.24, 0, 0.063946 431 | 0.7, 0.24, 0, 0.0613317 432 | 0.72, 0.24, 0, 0.058472 433 | 0.74, 0.24, 0, 0.0553765 434 | 0.76, 0.24, 0, 0.0520561 435 | 0.78, 0.24, 0, 0.0485225 436 | 0.8, 0.24, 0, 0.0447888 437 | 0.82, 0.24, 0, 0.0408689 438 | 0.84, 0.24, 0, 0.0367779 439 | 0.86, 0.24, 0, 0.0325319 440 | 0.88, 0.24, 0, 0.0281479 441 | 0.9, 0.24, 0, 0.0236438 442 | 0.92, 0.24, 0, 0.0190383 443 | 0.94, 0.24, 0, 0.0143509 444 | 0.96, 0.24, 0, 0.00960149 445 | 0.98, 0.24, 0, 0.00481052 446 | 0.02, 0.28, 0, 0.0058129 447 | 0.04, 0.28, 0, 0.0116017 448 | 0.06, 0.28, 0, 0.0173393 449 | 0.08, 0.28, 0, 0.0230006 450 | 0.1, 0.28, 0, 0.0285611 451 | 0.12, 0.28, 0, 0.033997 452 | 0.14, 0.28, 0, 0.0392855 453 | 0.16, 0.28, 0, 0.0444048 454 | 0.18, 0.28, 0, 0.0493349 455 | 0.2, 0.28, 0, 0.0540565 456 | 0.22, 0.28, 0, 0.0585509 457 | 0.24, 0.28, 0, 0.0628011 458 | 0.26, 0.28, 0, 0.0667923 459 | 0.28, 0.28, 0, 0.0705101 460 | 0.3, 0.28, 0, 0.073945 461 | 0.32, 0.28, 0, 0.0770857 462 | 0.34, 0.28, 0, 0.0799199 463 | 0.36, 0.28, 0, 0.082439 464 | 0.38, 0.28, 0, 0.0846355 465 | 0.4, 0.28, 0, 0.0865032 466 | 0.42, 0.28, 0, 0.088038 467 | 0.44, 0.28, 0, 0.0892363 468 | 0.46, 0.28, 0, 0.0900942 469 | 0.48, 0.28, 0, 0.090609 470 | 0.5, 0.28, 0, 0.0907783 471 | 0.52, 0.28, 0, 0.0906048 472 | 0.54, 0.28, 0, 0.0900924 473 | 0.56, 0.28, 0, 0.0892393 474 | 0.58, 0.28, 0, 0.088045 475 | 0.6, 0.28, 0, 0.0865127 476 | 0.62, 0.28, 0, 0.0846464 477 | 0.64, 0.28, 0, 0.0824514 478 | 0.66, 0.28, 0, 0.0799339 479 | 0.68, 0.28, 0, 0.0771016 480 | 0.7, 0.28, 0, 0.0739633 481 | 0.72, 0.28, 0, 0.0705285 482 | 0.74, 0.28, 0, 0.0668086 483 | 0.76, 0.28, 0, 0.0628158 484 | 0.78, 0.28, 0, 0.0585642 485 | 0.8, 0.28, 0, 0.054069 486 | 0.82, 0.28, 0, 0.0493468 487 | 0.84, 0.28, 0, 0.0444156 488 | 0.86, 0.28, 0, 0.0392947 489 | 0.88, 0.28, 0, 0.0340048 490 | 0.9, 0.28, 0, 0.0285675 491 | 0.92, 0.28, 0, 0.0230057 492 | 0.94, 0.28, 0, 0.0173431 493 | 0.96, 0.28, 0, 0.0116042 494 | 0.98, 0.28, 0, 0.00581415 495 | 0.02, 0.32, 0, 0.00691929 496 | 0.04, 0.32, 0, 0.0138092 497 | 0.06, 0.32, 0, 0.0206366 498 | 0.08, 0.32, 0, 0.0273711 499 | 0.1, 0.32, 0, 0.0339828 500 | 0.12, 0.32, 0, 0.0404431 501 | 0.14, 0.32, 0, 0.0467245 502 | 0.16, 0.32, 0, 0.052801 503 | 0.18, 0.32, 0, 0.0586482 504 | 0.2, 0.32, 0, 0.0642437 505 | 0.22, 0.32, 0, 0.0695661 506 | 0.24, 0.32, 0, 0.0745955 507 | 0.26, 0.32, 0, 0.0793144 508 | 0.28, 0.32, 0, 0.0837067 509 | 0.3, 0.32, 0, 0.0877607 510 | 0.32, 0.32, 0, 0.0914648 511 | 0.34, 0.32, 0, 0.0948052 512 | 0.36, 0.32, 0, 0.097772 513 | 0.38, 0.32, 0, 0.100357 514 | 0.4, 0.32, 0, 0.102553 515 | 0.42, 0.32, 0, 0.104355 516 | 0.44, 0.32, 0, 0.105764 517 | 0.46, 0.32, 0, 0.106777 518 | 0.48, 0.32, 0, 0.107386 519 | 0.5, 0.32, 0, 0.10759 520 | 0.52, 0.32, 0, 0.107388 521 | 0.54, 0.32, 0, 0.106783 522 | 0.56, 0.32, 0, 0.105777 523 | 0.58, 0.32, 0, 0.104371 524 | 0.6, 0.32, 0, 0.102568 525 | 0.62, 0.32, 0, 0.100372 526 | 0.64, 0.32, 0, 0.0977873 527 | 0.66, 0.32, 0, 0.0948217 528 | 0.68, 0.32, 0, 0.091483 529 | 0.7, 0.32, 0, 0.0877808 530 | 0.72, 0.32, 0, 0.0837262 531 | 0.74, 0.32, 0, 0.0793317 532 | 0.76, 0.32, 0, 0.0746111 533 | 0.78, 0.32, 0, 0.0695804 534 | 0.8, 0.32, 0, 0.0642571 535 | 0.82, 0.32, 0, 0.0586606 536 | 0.84, 0.32, 0, 0.0528119 537 | 0.86, 0.32, 0, 0.0467338 538 | 0.88, 0.32, 0, 0.040451 539 | 0.9, 0.32, 0, 0.0339893 540 | 0.92, 0.32, 0, 0.0273762 541 | 0.94, 0.32, 0, 0.0206404 542 | 0.96, 0.32, 0, 0.0138117 543 | 0.98, 0.32, 0, 0.00692053 544 | 0.02, 0.36, 0, 0.00815109 545 | 0.04, 0.36, 0, 0.0162665 546 | 0.06, 0.36, 0, 0.0243059 547 | 0.08, 0.36, 0, 0.0322325 548 | 0.1, 0.36, 0, 0.0400104 549 | 0.12, 0.36, 0, 0.047605 550 | 0.14, 0.36, 0, 0.0549835 551 | 0.16, 0.36, 0, 0.0621151 552 | 0.18, 0.36, 0, 0.068971 553 | 0.2, 0.36, 0, 0.0755249 554 | 0.22, 0.36, 0, 0.0817527 555 | 0.24, 0.36, 0, 0.0876322 556 | 0.26, 0.36, 0, 0.0931432 557 | 0.28, 0.36, 0, 0.0982682 558 | 0.3, 0.36, 0, 0.102992 559 | 0.32, 0.36, 0, 0.107301 560 | 0.34, 0.36, 0, 0.111185 561 | 0.36, 0.36, 0, 0.114633 562 | 0.38, 0.36, 0, 0.117634 563 | 0.4, 0.36, 0, 0.120182 564 | 0.42, 0.36, 0, 0.122271 565 | 0.44, 0.36, 0, 0.123903 566 | 0.46, 0.36, 0, 0.125077 567 | 0.48, 0.36, 0, 0.125785 568 | 0.5, 0.36, 0, 0.126022 569 | 0.52, 0.36, 0, 0.125789 570 | 0.54, 0.36, 0, 0.125087 571 | 0.56, 0.36, 0, 0.123919 572 | 0.58, 0.36, 0, 0.122289 573 | 0.6, 0.36, 0, 0.120198 574 | 0.62, 0.36, 0, 0.117649 575 | 0.64, 0.36, 0, 0.114648 576 | 0.66, 0.36, 0, 0.111202 577 | 0.68, 0.36, 0, 0.107319 578 | 0.7, 0.36, 0, 0.103009 579 | 0.72, 0.36, 0, 0.0982846 580 | 0.74, 0.36, 0, 0.0931588 581 | 0.76, 0.36, 0, 0.0876471 582 | 0.78, 0.36, 0, 0.0817671 583 | 0.8, 0.36, 0, 0.0755384 584 | 0.82, 0.36, 0, 0.0689831 585 | 0.84, 0.36, 0, 0.0621256 586 | 0.86, 0.36, 0, 0.0549925 587 | 0.88, 0.36, 0, 0.0476125 588 | 0.9, 0.36, 0, 0.0400166 589 | 0.92, 0.36, 0, 0.0322374 590 | 0.94, 0.36, 0, 0.0243096 591 | 0.96, 0.36, 0, 0.0162688 592 | 0.98, 0.36, 0, 0.00815228 593 | 0.02, 0.4, 0, 0.00953536 594 | 0.04, 0.4, 0, 0.0190272 595 | 0.06, 0.4, 0, 0.0284267 596 | 0.08, 0.4, 0, 0.0376891 597 | 0.1, 0.4, 0, 0.0467709 598 | 0.12, 0.4, 0, 0.0556309 599 | 0.14, 0.4, 0, 0.0642301 600 | 0.16, 0.4, 0, 0.0725322 601 | 0.18, 0.4, 0, 0.0805034 602 | 0.2, 0.4, 0, 0.0881133 603 | 0.22, 0.4, 0, 0.0953346 604 | 0.24, 0.4, 0, 0.102143 605 | 0.26, 0.4, 0, 0.108516 606 | 0.28, 0.4, 0, 0.114435 607 | 0.3, 0.4, 0, 0.119883 608 | 0.32, 0.4, 0, 0.124847 609 | 0.34, 0.4, 0, 0.129315 610 | 0.36, 0.4, 0, 0.133277 611 | 0.38, 0.4, 0, 0.136724 612 | 0.4, 0.4, 0, 0.139648 613 | 0.42, 0.4, 0, 0.142046 614 | 0.44, 0.4, 0, 0.143915 615 | 0.46, 0.4, 0, 0.145256 616 | 0.48, 0.4, 0, 0.146064 617 | 0.5, 0.4, 0, 0.146335 618 | 0.52, 0.4, 0, 0.146068 619 | 0.54, 0.4, 0, 0.145264 620 | 0.56, 0.4, 0, 0.143926 621 | 0.58, 0.4, 0, 0.142057 622 | 0.6, 0.4, 0, 0.139659 623 | 0.62, 0.4, 0, 0.136735 624 | 0.64, 0.4, 0, 0.133289 625 | 0.66, 0.4, 0, 0.129329 626 | 0.68, 0.4, 0, 0.124862 627 | 0.7, 0.4, 0, 0.119898 628 | 0.72, 0.4, 0, 0.11445 629 | 0.74, 0.4, 0, 0.10853 630 | 0.76, 0.4, 0, 0.102157 631 | 0.78, 0.4, 0, 0.0953482 632 | 0.8, 0.4, 0, 0.088126 633 | 0.82, 0.4, 0, 0.0805146 634 | 0.84, 0.4, 0, 0.072542 635 | 0.86, 0.4, 0, 0.0642386 636 | 0.88, 0.4, 0, 0.055638 637 | 0.9, 0.4, 0, 0.0467767 638 | 0.92, 0.4, 0, 0.0376936 639 | 0.94, 0.4, 0, 0.0284301 640 | 0.96, 0.4, 0, 0.0190294 641 | 0.98, 0.4, 0, 0.00953646 642 | 0.02, 0.44, 0, 0.0111053 643 | 0.04, 0.44, 0, 0.0221573 644 | 0.06, 0.44, 0, 0.0330963 645 | 0.08, 0.44, 0, 0.0438676 646 | 0.1, 0.44, 0, 0.0544187 647 | 0.12, 0.44, 0, 0.0647002 648 | 0.14, 0.44, 0, 0.0746656 649 | 0.16, 0.44, 0, 0.0842723 650 | 0.18, 0.44, 0, 0.0934813 651 | 0.2, 0.44, 0, 0.102258 652 | 0.22, 0.44, 0, 0.110572 653 | 0.24, 0.44, 0, 0.118396 654 | 0.26, 0.44, 0, 0.125707 655 | 0.28, 0.44, 0, 0.132485 656 | 0.3, 0.44, 0, 0.138713 657 | 0.32, 0.44, 0, 0.144379 658 | 0.34, 0.44, 0, 0.149472 659 | 0.36, 0.44, 0, 0.153982 660 | 0.38, 0.44, 0, 0.1579 661 | 0.4, 0.44, 0, 0.161223 662 | 0.42, 0.44, 0, 0.163944 663 | 0.44, 0.44, 0, 0.166065 664 | 0.46, 0.44, 0, 0.167584 665 | 0.48, 0.44, 0, 0.168495 666 | 0.5, 0.44, 0, 0.1688 667 | 0.52, 0.44, 0, 0.168496 668 | 0.54, 0.44, 0, 0.167584 669 | 0.56, 0.44, 0, 0.166068 670 | 0.58, 0.44, 0, 0.163948 671 | 0.6, 0.44, 0, 0.161227 672 | 0.62, 0.44, 0, 0.157906 673 | 0.64, 0.44, 0, 0.153989 674 | 0.66, 0.44, 0, 0.149482 675 | 0.68, 0.44, 0, 0.144392 676 | 0.7, 0.44, 0, 0.138727 677 | 0.72, 0.44, 0, 0.132498 678 | 0.74, 0.44, 0, 0.12572 679 | 0.76, 0.44, 0, 0.118409 680 | 0.78, 0.44, 0, 0.110584 681 | 0.8, 0.44, 0, 0.10227 682 | 0.82, 0.44, 0, 0.0934917 683 | 0.84, 0.44, 0, 0.0842813 684 | 0.86, 0.44, 0, 0.0746734 685 | 0.88, 0.44, 0, 0.0647067 686 | 0.9, 0.44, 0, 0.0544239 687 | 0.92, 0.44, 0, 0.0438716 688 | 0.94, 0.44, 0, 0.0330992 689 | 0.96, 0.44, 0, 0.0221593 690 | 0.98, 0.44, 0, 0.0111063 691 | 0.02, 0.48, 0, 0.0129028 692 | 0.04, 0.48, 0, 0.0257396 693 | 0.06, 0.48, 0, 0.0384365 694 | 0.08, 0.48, 0, 0.0509264 695 | 0.1, 0.48, 0, 0.0631455 696 | 0.12, 0.48, 0, 0.0750338 697 | 0.14, 0.48, 0, 0.0865362 698 | 0.16, 0.48, 0, 0.0976029 699 | 0.18, 0.48, 0, 0.108189 700 | 0.2, 0.48, 0, 0.118256 701 | 0.22, 0.48, 0, 0.12777 702 | 0.24, 0.48, 0, 0.136703 703 | 0.26, 0.48, 0, 0.145031 704 | 0.28, 0.48, 0, 0.152734 705 | 0.3, 0.48, 0, 0.159797 706 | 0.32, 0.48, 0, 0.166208 707 | 0.34, 0.48, 0, 0.171961 708 | 0.36, 0.48, 0, 0.177048 709 | 0.38, 0.48, 0, 0.181461 710 | 0.4, 0.48, 0, 0.185198 711 | 0.42, 0.48, 0, 0.188258 712 | 0.44, 0.48, 0, 0.190639 713 | 0.46, 0.48, 0, 0.19234 714 | 0.48, 0.48, 0, 0.193358 715 | 0.5, 0.48, 0, 0.193696 716 | 0.52, 0.48, 0, 0.193354 717 | 0.54, 0.48, 0, 0.192331 718 | 0.56, 0.48, 0, 0.190628 719 | 0.58, 0.48, 0, 0.188249 720 | 0.6, 0.48, 0, 0.185193 721 | 0.62, 0.48, 0, 0.18146 722 | 0.64, 0.48, 0, 0.177051 723 | 0.66, 0.48, 0, 0.17197 724 | 0.68, 0.48, 0, 0.166221 725 | 0.7, 0.48, 0, 0.15981 726 | 0.72, 0.48, 0, 0.152746 727 | 0.74, 0.48, 0, 0.145043 728 | 0.76, 0.48, 0, 0.136715 729 | 0.78, 0.48, 0, 0.127781 730 | 0.8, 0.48, 0, 0.118266 731 | 0.82, 0.48, 0, 0.108198 732 | 0.84, 0.48, 0, 0.0976111 733 | 0.86, 0.48, 0, 0.0865433 734 | 0.88, 0.48, 0, 0.0750397 735 | 0.9, 0.48, 0, 0.0631503 736 | 0.92, 0.48, 0, 0.0509302 737 | 0.94, 0.48, 0, 0.0384393 738 | 0.96, 0.48, 0, 0.0257414 739 | 0.98, 0.48, 0, 0.0129037 740 | 0.02, 0.52, 0, 0.0149822 741 | 0.04, 0.52, 0, 0.0298812 742 | 0.06, 0.52, 0, 0.0446046 743 | 0.08, 0.52, 0, 0.0590688 744 | 0.1, 0.52, 0, 0.0731951 745 | 0.12, 0.52, 0, 0.0869107 746 | 0.14, 0.52, 0, 0.10015 747 | 0.16, 0.52, 0, 0.112855 748 | 0.18, 0.52, 0, 0.124975 749 | 0.2, 0.52, 0, 0.136467 750 | 0.22, 0.52, 0, 0.147295 751 | 0.24, 0.52, 0, 0.157432 752 | 0.26, 0.52, 0, 0.166854 753 | 0.28, 0.52, 0, 0.175544 754 | 0.3, 0.52, 0, 0.183491 755 | 0.32, 0.52, 0, 0.190685 756 | 0.34, 0.52, 0, 0.197124 757 | 0.36, 0.52, 0, 0.202805 758 | 0.38, 0.52, 0, 0.207725 759 | 0.4, 0.52, 0, 0.211885 760 | 0.42, 0.52, 0, 0.215285 761 | 0.44, 0.52, 0, 0.217928 762 | 0.46, 0.52, 0, 0.219812 763 | 0.48, 0.52, 0, 0.22094 764 | 0.5, 0.52, 0, 0.221315 765 | 0.52, 0.52, 0, 0.220935 766 | 0.54, 0.52, 0, 0.219801 767 | 0.56, 0.52, 0, 0.217912 768 | 0.58, 0.52, 0, 0.215268 769 | 0.6, 0.52, 0, 0.211872 770 | 0.62, 0.52, 0, 0.20772 771 | 0.64, 0.52, 0, 0.202806 772 | 0.66, 0.52, 0, 0.197131 773 | 0.68, 0.52, 0, 0.190695 774 | 0.7, 0.52, 0, 0.183502 775 | 0.72, 0.52, 0, 0.175555 776 | 0.74, 0.52, 0, 0.166865 777 | 0.76, 0.52, 0, 0.157442 778 | 0.78, 0.52, 0, 0.147305 779 | 0.8, 0.52, 0, 0.136476 780 | 0.82, 0.52, 0, 0.124983 781 | 0.84, 0.52, 0, 0.112862 782 | 0.86, 0.52, 0, 0.100157 783 | 0.88, 0.52, 0, 0.0869164 784 | 0.9, 0.52, 0, 0.0731998 785 | 0.92, 0.52, 0, 0.0590727 786 | 0.94, 0.52, 0, 0.0446075 787 | 0.96, 0.52, 0, 0.0298831 788 | 0.98, 0.52, 0, 0.0149831 789 | 0.02, 0.56, 0, 0.0174161 790 | 0.04, 0.56, 0, 0.0347255 791 | 0.06, 0.56, 0, 0.0518098 792 | 0.08, 0.56, 0, 0.0685631 793 | 0.1, 0.56, 0, 0.0848872 794 | 0.12, 0.56, 0, 0.100693 795 | 0.14, 0.56, 0, 0.115902 796 | 0.16, 0.56, 0, 0.130447 797 | 0.18, 0.56, 0, 0.144272 798 | 0.2, 0.56, 0, 0.157331 799 | 0.22, 0.56, 0, 0.169589 800 | 0.24, 0.56, 0, 0.181019 801 | 0.26, 0.56, 0, 0.191604 802 | 0.28, 0.56, 0, 0.20133 803 | 0.3, 0.56, 0, 0.210193 804 | 0.32, 0.56, 0, 0.218191 805 | 0.34, 0.56, 0, 0.225327 806 | 0.36, 0.56, 0, 0.231607 807 | 0.38, 0.56, 0, 0.237032 808 | 0.4, 0.56, 0, 0.241609 809 | 0.42, 0.56, 0, 0.245342 810 | 0.44, 0.56, 0, 0.248238 811 | 0.46, 0.56, 0, 0.250302 812 | 0.48, 0.56, 0, 0.251539 813 | 0.5, 0.56, 0, 0.251951 814 | 0.52, 0.56, 0, 0.251537 815 | 0.54, 0.56, 0, 0.250297 816 | 0.56, 0.56, 0, 0.248228 817 | 0.58, 0.56, 0, 0.24533 818 | 0.6, 0.56, 0, 0.241599 819 | 0.62, 0.56, 0, 0.23703 820 | 0.64, 0.56, 0, 0.231611 821 | 0.66, 0.56, 0, 0.225336 822 | 0.68, 0.56, 0, 0.218202 823 | 0.7, 0.56, 0, 0.210205 824 | 0.72, 0.56, 0, 0.201341 825 | 0.74, 0.56, 0, 0.191614 826 | 0.76, 0.56, 0, 0.181029 827 | 0.78, 0.56, 0, 0.169598 828 | 0.8, 0.56, 0, 0.157339 829 | 0.82, 0.56, 0, 0.14428 830 | 0.84, 0.56, 0, 0.130454 831 | 0.86, 0.56, 0, 0.115908 832 | 0.88, 0.56, 0, 0.100698 833 | 0.9, 0.56, 0, 0.0848918 834 | 0.92, 0.56, 0, 0.0685669 835 | 0.94, 0.56, 0, 0.0518127 836 | 0.96, 0.56, 0, 0.0347275 837 | 0.98, 0.56, 0, 0.0174171 838 | 0.02, 0.6, 0, 0.0203057 839 | 0.04, 0.6, 0, 0.0404707 840 | 0.06, 0.6, 0, 0.0603395 841 | 0.08, 0.6, 0, 0.0797751 842 | 0.1, 0.6, 0, 0.0986528 843 | 0.12, 0.6, 0, 0.116863 844 | 0.14, 0.6, 0, 0.134311 845 | 0.16, 0.6, 0, 0.150921 846 | 0.18, 0.6, 0, 0.166632 847 | 0.2, 0.6, 0, 0.1814 848 | 0.22, 0.6, 0, 0.195192 849 | 0.24, 0.6, 0, 0.207991 850 | 0.26, 0.6, 0, 0.219784 851 | 0.28, 0.6, 0, 0.230572 852 | 0.3, 0.6, 0, 0.240358 853 | 0.32, 0.6, 0, 0.249151 854 | 0.34, 0.6, 0, 0.25697 855 | 0.36, 0.6, 0, 0.263829 856 | 0.38, 0.6, 0, 0.269736 857 | 0.4, 0.6, 0, 0.274705 858 | 0.42, 0.6, 0, 0.278749 859 | 0.44, 0.6, 0, 0.28188 860 | 0.46, 0.6, 0, 0.28411 861 | 0.48, 0.6, 0, 0.285448 862 | 0.5, 0.6, 0, 0.285893 863 | 0.52, 0.6, 0, 0.285449 864 | 0.54, 0.6, 0, 0.284112 865 | 0.56, 0.6, 0, 0.281879 866 | 0.58, 0.6, 0, 0.278747 867 | 0.6, 0.6, 0, 0.274706 868 | 0.62, 0.6, 0, 0.269741 869 | 0.64, 0.6, 0, 0.263839 870 | 0.66, 0.6, 0, 0.256986 871 | 0.68, 0.6, 0, 0.249167 872 | 0.7, 0.6, 0, 0.240371 873 | 0.72, 0.6, 0, 0.230583 874 | 0.74, 0.6, 0, 0.219795 875 | 0.76, 0.6, 0, 0.208 876 | 0.78, 0.6, 0, 0.195202 877 | 0.8, 0.6, 0, 0.181408 878 | 0.82, 0.6, 0, 0.16664 879 | 0.84, 0.6, 0, 0.150927 880 | 0.86, 0.6, 0, 0.134317 881 | 0.88, 0.6, 0, 0.116867 882 | 0.9, 0.6, 0, 0.0986568 883 | 0.92, 0.6, 0, 0.0797784 884 | 0.94, 0.6, 0, 0.060342 885 | 0.96, 0.6, 0, 0.0404724 886 | 0.98, 0.6, 0, 0.0203066 887 | 0.02, 0.64, 0, 0.0237964 888 | 0.04, 0.64, 0, 0.0474007 889 | 0.06, 0.64, 0, 0.0706024 890 | 0.08, 0.64, 0, 0.0932192 891 | 0.1, 0.64, 0, 0.11509 892 | 0.12, 0.64, 0, 0.136078 893 | 0.14, 0.64, 0, 0.156073 894 | 0.16, 0.64, 0, 0.17499 895 | 0.18, 0.64, 0, 0.192769 896 | 0.2, 0.64, 0, 0.209371 897 | 0.22, 0.64, 0, 0.224776 898 | 0.24, 0.64, 0, 0.23898 899 | 0.26, 0.64, 0, 0.25199 900 | 0.28, 0.64, 0, 0.26382 901 | 0.3, 0.64, 0, 0.274495 902 | 0.32, 0.64, 0, 0.284038 903 | 0.34, 0.64, 0, 0.292482 904 | 0.36, 0.64, 0, 0.299859 905 | 0.38, 0.64, 0, 0.306191 906 | 0.4, 0.64, 0, 0.3115 907 | 0.42, 0.64, 0, 0.315811 908 | 0.44, 0.64, 0, 0.31914 909 | 0.46, 0.64, 0, 0.321507 910 | 0.48, 0.64, 0, 0.322926 911 | 0.5, 0.64, 0, 0.323401 912 | 0.52, 0.64, 0, 0.322932 913 | 0.54, 0.64, 0, 0.321516 914 | 0.56, 0.64, 0, 0.319147 915 | 0.58, 0.64, 0, 0.315815 916 | 0.6, 0.64, 0, 0.311506 917 | 0.62, 0.64, 0, 0.306201 918 | 0.64, 0.64, 0, 0.299874 919 | 0.66, 0.64, 0, 0.292501 920 | 0.68, 0.64, 0, 0.284054 921 | 0.7, 0.64, 0, 0.274507 922 | 0.72, 0.64, 0, 0.263831 923 | 0.74, 0.64, 0, 0.251999 924 | 0.76, 0.64, 0, 0.238989 925 | 0.78, 0.64, 0, 0.224784 926 | 0.8, 0.64, 0, 0.209378 927 | 0.82, 0.64, 0, 0.192775 928 | 0.84, 0.64, 0, 0.174995 929 | 0.86, 0.64, 0, 0.156078 930 | 0.88, 0.64, 0, 0.136082 931 | 0.9, 0.64, 0, 0.115093 932 | 0.92, 0.64, 0, 0.0932218 933 | 0.94, 0.64, 0, 0.0706043 934 | 0.96, 0.64, 0, 0.047402 935 | 0.98, 0.64, 0, 0.0237971 936 | 0.02, 0.68, 0, 0.0281074 937 | 0.04, 0.68, 0, 0.055941 938 | 0.06, 0.68, 0, 0.0832043 939 | 0.08, 0.68, 0, 0.109648 940 | 0.1, 0.68, 0, 0.135058 941 | 0.12, 0.68, 0, 0.159267 942 | 0.14, 0.68, 0, 0.182147 943 | 0.16, 0.68, 0, 0.203612 944 | 0.18, 0.68, 0, 0.223613 945 | 0.2, 0.68, 0, 0.24213 946 | 0.22, 0.68, 0, 0.259167 947 | 0.24, 0.68, 0, 0.274749 948 | 0.26, 0.68, 0, 0.28891 949 | 0.28, 0.68, 0, 0.301696 950 | 0.3, 0.68, 0, 0.313155 951 | 0.32, 0.68, 0, 0.323339 952 | 0.34, 0.68, 0, 0.332297 953 | 0.36, 0.68, 0, 0.34008 954 | 0.38, 0.68, 0, 0.346734 955 | 0.4, 0.68, 0, 0.352295 956 | 0.42, 0.68, 0, 0.356795 957 | 0.44, 0.68, 0, 0.360264 958 | 0.46, 0.68, 0, 0.362723 959 | 0.48, 0.68, 0, 0.364192 960 | 0.5, 0.68, 0, 0.364685 961 | 0.52, 0.68, 0, 0.364201 962 | 0.54, 0.68, 0, 0.362733 963 | 0.56, 0.68, 0, 0.360272 964 | 0.58, 0.68, 0, 0.356802 965 | 0.6, 0.68, 0, 0.352302 966 | 0.62, 0.68, 0, 0.346746 967 | 0.64, 0.68, 0, 0.340095 968 | 0.66, 0.68, 0, 0.332311 969 | 0.68, 0.68, 0, 0.32335 970 | 0.7, 0.68, 0, 0.313164 971 | 0.72, 0.68, 0, 0.301703 972 | 0.74, 0.68, 0, 0.288916 973 | 0.76, 0.68, 0, 0.274755 974 | 0.78, 0.68, 0, 0.259173 975 | 0.8, 0.68, 0, 0.242135 976 | 0.82, 0.68, 0, 0.223617 977 | 0.84, 0.68, 0, 0.203616 978 | 0.86, 0.68, 0, 0.18215 979 | 0.88, 0.68, 0, 0.15927 980 | 0.9, 0.68, 0, 0.135061 981 | 0.92, 0.68, 0, 0.109649 982 | 0.94, 0.68, 0, 0.0832056 983 | 0.96, 0.68, 0, 0.0559419 984 | 0.98, 0.68, 0, 0.0281079 985 | 0.02, 0.72, 0, 0.0335875 986 | 0.04, 0.72, 0, 0.0667627 987 | 0.06, 0.72, 0, 0.0990867 988 | 0.08, 0.72, 0, 0.130205 989 | 0.1, 0.72, 0, 0.159835 990 | 0.12, 0.72, 0, 0.187771 991 | 0.14, 0.72, 0, 0.21388 992 | 0.16, 0.72, 0, 0.238093 993 | 0.18, 0.72, 0, 0.260394 994 | 0.2, 0.72, 0, 0.280807 995 | 0.22, 0.72, 0, 0.299385 996 | 0.24, 0.72, 0, 0.3162 997 | 0.26, 0.72, 0, 0.331335 998 | 0.28, 0.72, 0, 0.344879 999 | 0.3, 0.72, 0, 0.356919 1000 | 0.32, 0.72, 0, 0.367541 1001 | 0.34, 0.72, 0, 0.376823 1002 | 0.36, 0.72, 0, 0.38484 1003 | 0.38, 0.72, 0, 0.391658 1004 | 0.4, 0.72, 0, 0.397331 1005 | 0.42, 0.72, 0, 0.401907 1006 | 0.44, 0.72, 0, 0.405424 1007 | 0.46, 0.72, 0, 0.407913 1008 | 0.48, 0.72, 0, 0.409397 1009 | 0.5, 0.72, 0, 0.409894 1010 | 0.52, 0.72, 0, 0.409406 1011 | 0.54, 0.72, 0, 0.407923 1012 | 0.56, 0.72, 0, 0.405434 1013 | 0.58, 0.72, 0, 0.401916 1014 | 0.6, 0.72, 0, 0.39734 1015 | 0.62, 0.72, 0, 0.391668 1016 | 0.64, 0.72, 0, 0.384851 1017 | 0.66, 0.72, 0, 0.376832 1018 | 0.68, 0.72, 0, 0.367548 1019 | 0.7, 0.72, 0, 0.356925 1020 | 0.72, 0.72, 0, 0.344883 1021 | 0.74, 0.72, 0, 0.331338 1022 | 0.76, 0.72, 0, 0.316202 1023 | 0.78, 0.72, 0, 0.299387 1024 | 0.8, 0.72, 0, 0.280809 1025 | 0.82, 0.72, 0, 0.260396 1026 | 0.84, 0.72, 0, 0.238095 1027 | 0.86, 0.72, 0, 0.213882 1028 | 0.88, 0.72, 0, 0.187773 1029 | 0.9, 0.72, 0, 0.159836 1030 | 0.92, 0.72, 0, 0.130206 1031 | 0.94, 0.72, 0, 0.0990874 1032 | 0.96, 0.72, 0, 0.0667632 1033 | 0.98, 0.72, 0, 0.0335877 1034 | 0.02, 0.76, 0, 0.0408282 1035 | 0.04, 0.76, 0, 0.0809889 1036 | 0.06, 0.76, 0, 0.119791 1037 | 0.08, 0.76, 0, 0.156716 1038 | 0.1, 0.76, 0, 0.191389 1039 | 0.12, 0.76, 0, 0.223584 1040 | 0.14, 0.76, 0, 0.253196 1041 | 0.16, 0.76, 0, 0.280222 1042 | 0.18, 0.76, 0, 0.304727 1043 | 0.2, 0.76, 0, 0.326824 1044 | 0.22, 0.76, 0, 0.346654 1045 | 0.24, 0.76, 0, 0.36437 1046 | 0.26, 0.76, 0, 0.380128 1047 | 0.28, 0.76, 0, 0.394076 1048 | 0.3, 0.76, 0, 0.406357 1049 | 0.32, 0.76, 0, 0.417098 1050 | 0.34, 0.76, 0, 0.426414 1051 | 0.36, 0.76, 0, 0.434407 1052 | 0.38, 0.76, 0, 0.441164 1053 | 0.4, 0.76, 0, 0.44676 1054 | 0.42, 0.76, 0, 0.451254 1055 | 0.44, 0.76, 0, 0.454697 1056 | 0.46, 0.76, 0, 0.457125 1057 | 0.48, 0.76, 0, 0.458574 1058 | 0.5, 0.76, 0, 0.459062 1059 | 0.52, 0.76, 0, 0.458587 1060 | 0.54, 0.76, 0, 0.457141 1061 | 0.56, 0.76, 0, 0.454709 1062 | 0.58, 0.76, 0, 0.451263 1063 | 0.6, 0.76, 0, 0.446767 1064 | 0.62, 0.76, 0, 0.441171 1065 | 0.64, 0.76, 0, 0.434413 1066 | 0.66, 0.76, 0, 0.42642 1067 | 0.68, 0.76, 0, 0.417102 1068 | 0.7, 0.76, 0, 0.40636 1069 | 0.72, 0.76, 0, 0.394078 1070 | 0.74, 0.76, 0, 0.380128 1071 | 0.76, 0.76, 0, 0.364369 1072 | 0.78, 0.76, 0, 0.346653 1073 | 0.8, 0.76, 0, 0.326823 1074 | 0.82, 0.76, 0, 0.304726 1075 | 0.84, 0.76, 0, 0.280222 1076 | 0.86, 0.76, 0, 0.253196 1077 | 0.88, 0.76, 0, 0.223584 1078 | 0.9, 0.76, 0, 0.191389 1079 | 0.92, 0.76, 0, 0.156716 1080 | 0.94, 0.76, 0, 0.119792 1081 | 0.96, 0.76, 0, 0.0809891 1082 | 0.98, 0.76, 0, 0.0408283 1083 | 0.02, 0.8, 0, 0.0509208 1084 | 0.04, 0.8, 0, 0.100648 1085 | 0.06, 0.8, 0, 0.148009 1086 | 0.08, 0.8, 0, 0.192229 1087 | 0.1, 0.8, 0, 0.232858 1088 | 0.12, 0.8, 0, 0.269724 1089 | 0.14, 0.8, 0, 0.30286 1090 | 0.16, 0.8, 0, 0.332433 1091 | 0.18, 0.8, 0, 0.35869 1092 | 0.2, 0.8, 0, 0.381909 1093 | 0.22, 0.8, 0, 0.402379 1094 | 0.24, 0.8, 0, 0.420376 1095 | 0.26, 0.8, 0, 0.436155 1096 | 0.28, 0.8, 0, 0.449947 1097 | 0.3, 0.8, 0, 0.461954 1098 | 0.32, 0.8, 0, 0.472354 1099 | 0.34, 0.8, 0, 0.481299 1100 | 0.36, 0.8, 0, 0.488917 1101 | 0.38, 0.8, 0, 0.495318 1102 | 0.4, 0.8, 0, 0.500591 1103 | 0.42, 0.8, 0, 0.504808 1104 | 0.44, 0.8, 0, 0.508027 1105 | 0.46, 0.8, 0, 0.510289 1106 | 0.48, 0.8, 0, 0.511633 1107 | 0.5, 0.8, 0, 0.512086 1108 | 0.52, 0.8, 0, 0.511649 1109 | 0.54, 0.8, 0, 0.510306 1110 | 0.56, 0.8, 0, 0.508038 1111 | 0.58, 0.8, 0, 0.504816 1112 | 0.6, 0.8, 0, 0.500596 1113 | 0.62, 0.8, 0, 0.495322 1114 | 0.64, 0.8, 0, 0.488921 1115 | 0.66, 0.8, 0, 0.481302 1116 | 0.68, 0.8, 0, 0.472356 1117 | 0.7, 0.8, 0, 0.461955 1118 | 0.72, 0.8, 0, 0.449947 1119 | 0.74, 0.8, 0, 0.436154 1120 | 0.76, 0.8, 0, 0.420373 1121 | 0.78, 0.8, 0, 0.402376 1122 | 0.8, 0.8, 0, 0.381906 1123 | 0.82, 0.8, 0, 0.358688 1124 | 0.84, 0.8, 0, 0.332432 1125 | 0.86, 0.8, 0, 0.302859 1126 | 0.88, 0.8, 0, 0.269724 1127 | 0.9, 0.8, 0, 0.232858 1128 | 0.92, 0.8, 0, 0.192229 1129 | 0.94, 0.8, 0, 0.148009 1130 | 0.96, 0.8, 0, 0.100648 1131 | 0.98, 0.8, 0, 0.0509208 1132 | 0.02, 0.84, 0, 0.0661174 1133 | 0.04, 0.84, 0, 0.12977 1134 | 0.06, 0.84, 0, 0.188794 1135 | 0.08, 0.84, 0, 0.242106 1136 | 0.1, 0.84, 0, 0.28938 1137 | 0.12, 0.84, 0, 0.330785 1138 | 0.14, 0.84, 0, 0.366773 1139 | 0.16, 0.84, 0, 0.397914 1140 | 0.18, 0.84, 0, 0.4248 1141 | 0.2, 0.84, 0, 0.447993 1142 | 0.22, 0.84, 0, 0.467998 1143 | 0.24, 0.84, 0, 0.485253 1144 | 0.26, 0.84, 0, 0.500134 1145 | 0.28, 0.84, 0, 0.512955 1146 | 0.3, 0.84, 0, 0.523982 1147 | 0.32, 0.84, 0, 0.533433 1148 | 0.34, 0.84, 0, 0.541489 1149 | 0.36, 0.84, 0, 0.5483 1150 | 0.38, 0.84, 0, 0.553986 1151 | 0.4, 0.84, 0, 0.558646 1152 | 0.42, 0.84, 0, 0.562358 1153 | 0.44, 0.84, 0, 0.565182 1154 | 0.46, 0.84, 0, 0.567163 1155 | 0.48, 0.84, 0, 0.568334 1156 | 0.5, 0.84, 0, 0.568722 1157 | 0.52, 0.84, 0, 0.568339 1158 | 0.54, 0.84, 0, 0.567168 1159 | 0.56, 0.84, 0, 0.565185 1160 | 0.58, 0.84, 0, 0.562359 1161 | 0.6, 0.84, 0, 0.558646 1162 | 0.62, 0.84, 0, 0.553984 1163 | 0.64, 0.84, 0, 0.548298 1164 | 0.66, 0.84, 0, 0.541488 1165 | 0.68, 0.84, 0, 0.533432 1166 | 0.7, 0.84, 0, 0.523981 1167 | 0.72, 0.84, 0, 0.512954 1168 | 0.74, 0.84, 0, 0.500132 1169 | 0.76, 0.84, 0, 0.485251 1170 | 0.78, 0.84, 0, 0.467994 1171 | 0.8, 0.84, 0, 0.447989 1172 | 0.82, 0.84, 0, 0.424797 1173 | 0.84, 0.84, 0, 0.397911 1174 | 0.86, 0.84, 0, 0.366772 1175 | 0.88, 0.84, 0, 0.330784 1176 | 0.9, 0.84, 0, 0.289379 1177 | 0.92, 0.84, 0, 0.242106 1178 | 0.94, 0.84, 0, 0.188793 1179 | 0.96, 0.84, 0, 0.12977 1180 | 0.98, 0.84, 0, 0.0661173 1181 | 0.02, 0.88, 0, 0.0918772 1182 | 0.04, 0.88, 0, 0.177412 1183 | 0.06, 0.88, 0, 0.25242 1184 | 0.08, 0.88, 0, 0.316141 1185 | 0.1, 0.88, 0, 0.369373 1186 | 0.12, 0.88, 0, 0.413518 1187 | 0.14, 0.88, 0, 0.450075 1188 | 0.16, 0.88, 0, 0.480411 1189 | 0.18, 0.88, 0, 0.505682 1190 | 0.2, 0.88, 0, 0.526832 1191 | 0.22, 0.88, 0, 0.544614 1192 | 0.24, 0.88, 0, 0.559629 1193 | 0.26, 0.88, 0, 0.572347 1194 | 0.28, 0.88, 0, 0.583143 1195 | 0.3, 0.88, 0, 0.592312 1196 | 0.32, 0.88, 0, 0.60009 1197 | 0.34, 0.88, 0, 0.606663 1198 | 0.36, 0.88, 0, 0.61218 1199 | 0.38, 0.88, 0, 0.616759 1200 | 0.4, 0.88, 0, 0.620493 1201 | 0.42, 0.88, 0, 0.623457 1202 | 0.44, 0.88, 0, 0.625706 1203 | 0.46, 0.88, 0, 0.627282 1204 | 0.48, 0.88, 0, 0.628214 1205 | 0.5, 0.88, 0, 0.628519 1206 | 0.52, 0.88, 0, 0.628208 1207 | 0.54, 0.88, 0, 0.627277 1208 | 0.56, 0.88, 0, 0.625702 1209 | 0.58, 0.88, 0, 0.623453 1210 | 0.6, 0.88, 0, 0.62049 1211 | 0.62, 0.88, 0, 0.616754 1212 | 0.64, 0.88, 0, 0.612176 1213 | 0.66, 0.88, 0, 0.606661 1214 | 0.68, 0.88, 0, 0.600089 1215 | 0.7, 0.88, 0, 0.592311 1216 | 0.72, 0.88, 0, 0.583142 1217 | 0.74, 0.88, 0, 0.572346 1218 | 0.76, 0.88, 0, 0.559627 1219 | 0.78, 0.88, 0, 0.544612 1220 | 0.8, 0.88, 0, 0.526829 1221 | 0.82, 0.88, 0, 0.505679 1222 | 0.84, 0.88, 0, 0.480409 1223 | 0.86, 0.88, 0, 0.450074 1224 | 0.88, 0.88, 0, 0.413516 1225 | 0.9, 0.88, 0, 0.369372 1226 | 0.92, 0.88, 0, 0.316141 1227 | 0.94, 0.88, 0, 0.252419 1228 | 0.96, 0.88, 0, 0.177412 1229 | 0.98, 0.88, 0, 0.0918771 1230 | 0.02, 0.92, 0, 0.145058 1231 | 0.04, 0.92, 0, 0.267162 1232 | 0.06, 0.92, 0, 0.361192 1233 | 0.08, 0.92, 0, 0.432136 1234 | 0.1, 0.92, 0, 0.485711 1235 | 0.12, 0.92, 0, 0.5266 1236 | 0.14, 0.92, 0, 0.558263 1237 | 0.16, 0.92, 0, 0.583168 1238 | 0.18, 0.92, 0, 0.60305 1239 | 0.2, 0.92, 0, 0.619137 1240 | 0.22, 0.92, 0, 0.632305 1241 | 0.24, 0.92, 0, 0.643188 1242 | 0.26, 0.92, 0, 0.652251 1243 | 0.28, 0.92, 0, 0.659838 1244 | 0.3, 0.92, 0, 0.666211 1245 | 0.32, 0.92, 0, 0.671567 1246 | 0.34, 0.92, 0, 0.676061 1247 | 0.36, 0.92, 0, 0.679811 1248 | 0.38, 0.92, 0, 0.682908 1249 | 0.4, 0.92, 0, 0.685424 1250 | 0.42, 0.92, 0, 0.687416 1251 | 0.44, 0.92, 0, 0.688923 1252 | 0.46, 0.92, 0, 0.689979 1253 | 0.48, 0.92, 0, 0.690602 1254 | 0.5, 0.92, 0, 0.690807 1255 | 0.52, 0.92, 0, 0.690598 1256 | 0.54, 0.92, 0, 0.689972 1257 | 0.56, 0.92, 0, 0.688916 1258 | 0.58, 0.92, 0, 0.687409 1259 | 0.6, 0.92, 0, 0.685419 1260 | 0.62, 0.92, 0, 0.682904 1261 | 0.64, 0.92, 0, 0.679808 1262 | 0.66, 0.92, 0, 0.67606 1263 | 0.68, 0.92, 0, 0.671566 1264 | 0.7, 0.92, 0, 0.66621 1265 | 0.72, 0.92, 0, 0.659837 1266 | 0.74, 0.92, 0, 0.65225 1267 | 0.76, 0.92, 0, 0.643187 1268 | 0.78, 0.92, 0, 0.632304 1269 | 0.8, 0.92, 0, 0.619135 1270 | 0.82, 0.92, 0, 0.603048 1271 | 0.84, 0.92, 0, 0.583166 1272 | 0.86, 0.92, 0, 0.558262 1273 | 0.88, 0.92, 0, 0.526599 1274 | 0.9, 0.92, 0, 0.485711 1275 | 0.92, 0.92, 0, 0.432136 1276 | 0.94, 0.92, 0, 0.361191 1277 | 0.96, 0.92, 0, 0.267161 1278 | 0.98, 0.92, 0, 0.145058 1279 | 0.02, 0.96, 0, 0.30065 1280 | 0.04, 0.96, 0, 0.469207 1281 | 0.06, 0.96, 0, 0.562305 1282 | 0.08, 0.96, 0, 0.61761 1283 | 0.1, 0.96, 0, 0.652797 1284 | 0.12, 0.96, 0, 0.67658 1285 | 0.14, 0.96, 0, 0.69349 1286 | 0.16, 0.96, 0, 0.706014 1287 | 0.18, 0.96, 0, 0.715597 1288 | 0.2, 0.96, 0, 0.723117 1289 | 0.22, 0.96, 0, 0.729137 1290 | 0.24, 0.96, 0, 0.734031 1291 | 0.26, 0.96, 0, 0.738055 1292 | 0.28, 0.96, 0, 0.741392 1293 | 0.3, 0.96, 0, 0.744173 1294 | 0.32, 0.96, 0, 0.746497 1295 | 0.34, 0.96, 0, 0.748438 1296 | 0.36, 0.96, 0, 0.750051 1297 | 0.38, 0.96, 0, 0.75138 1298 | 0.4, 0.96, 0, 0.752457 1299 | 0.42, 0.96, 0, 0.753307 1300 | 0.44, 0.96, 0, 0.753951 1301 | 0.46, 0.96, 0, 0.7544 1302 | 0.48, 0.96, 0, 0.754666 1303 | 0.5, 0.96, 0, 0.754754 1304 | 0.52, 0.96, 0, 0.754665 1305 | 0.54, 0.96, 0, 0.754397 1306 | 0.56, 0.96, 0, 0.753946 1307 | 0.58, 0.96, 0, 0.753303 1308 | 0.6, 0.96, 0, 0.752454 1309 | 0.62, 0.96, 0, 0.751378 1310 | 0.64, 0.96, 0, 0.75005 1311 | 0.66, 0.96, 0, 0.748437 1312 | 0.68, 0.96, 0, 0.746497 1313 | 0.7, 0.96, 0, 0.744173 1314 | 0.72, 0.96, 0, 0.741391 1315 | 0.74, 0.96, 0, 0.738054 1316 | 0.76, 0.96, 0, 0.73403 1317 | 0.78, 0.96, 0, 0.729136 1318 | 0.8, 0.96, 0, 0.723116 1319 | 0.82, 0.96, 0, 0.715596 1320 | 0.84, 0.96, 0, 0.706014 1321 | 0.86, 0.96, 0, 0.693489 1322 | 0.88, 0.96, 0, 0.67658 1323 | 0.9, 0.96, 0, 0.652796 1324 | 0.92, 0.96, 0, 0.617609 1325 | 0.94, 0.96, 0, 0.562305 1326 | 0.96, 0.96, 0, 0.469207 1327 | 0.98, 0.96, 0, 0.30065 1328 | --------------------------------------------------------------------------------