diff --git a/config/elliptic.vlm b/config/elliptic.vlm index aca14cf..2727c38 100644 --- a/config/elliptic.vlm +++ b/config/elliptic.vlm @@ -11,5 +11,4 @@ backend = cpu s_ref = 3.92699 # half wing area c_ref = 0.85 ref_pt = [0.25, 0.0, 0.0] -test = [ [ 123, 5, 12], [ 98, 234, 53, 12, 531]] wake_included = false diff --git a/headeronly/tinyconfig.hpp b/headeronly/tinyconfig.hpp index f24fc90..ee3ac4e 100644 --- a/headeronly/tinyconfig.hpp +++ b/headeronly/tinyconfig.hpp @@ -27,6 +27,7 @@ SOFTWARE. #pragma once +#include #include // std::is_same, std::is_integral, std::is_floating_point, std::disjunction #include // std::unordered_map #include // std::vector @@ -37,7 +38,7 @@ SOFTWARE. #include // std::filesystem #include // std::runtime_error #include // std::initializer_list -#include // dbg +// #include // dbg namespace tiny { @@ -119,34 +120,51 @@ inline static std::string clean_str(const std::string& str) { return str.substr(start, end - start + 1); } -inline bool extract_depth0_token(std::string_view& stream, std::string_view& token, const char delimiter, const char marker_open, const char marker_close) { - int depth = 0; - // Loop through each character in the stream - for(auto it = stream.begin(); it != stream.end(); ++it) { - if (*it == marker_open) { - depth++; - } else if (*it == marker_close) { - if (depth > 0) { - depth--; - if (depth == 0) { - // Extract last possible token - token = stream.substr(0, it - stream.begin() + 1); - stream.remove_prefix(it - stream.begin() + 1); - return true; +inline static std::string_view trim_space(std::string_view str) { + while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1); + while (!str.empty() && std::isspace(str.back())) str.remove_suffix(1); + return str; +} + +class Extractor { + public: + bool extract(std::string_view& token) { + // Loop through each character in the stream + token = stream; + for(auto it = stream.begin(); it != stream.end(); ++it) { + if (*it == '[' || *it == '{') { + depth++; + if (depth == 1) { + token.remove_prefix(it - stream.begin() + 1); } - } else { - // Mismatched delimiters - return false; + } else if (*it == ']' || *it == '}') { + if (depth > 0) { + depth--; + if (depth == 0) { + // Extract last possible token + token = token.substr(0, it - token.begin()); + stream.remove_prefix(it - stream.begin() + 1); + return true; + } + } else { + // Mismatched delimiters + throw std::runtime_error("Mismatched delimiters"); + } + } else if (*it == ',' && depth == 1) { + // Extract the token from the stream + token = token.substr(0, it - token.begin()); + stream.remove_prefix(it - stream.begin() + 1); + return true; } - } else if (*it == delimiter && depth == 0) { - // Extract the token from the stream - token = stream.substr(0, it - stream.begin()); - stream.remove_prefix(it - stream.begin() + 1); - return true; } + return false; // no match } - return false; // no match -} + Extractor(const std::string& s) : stream{s} {} + + public: + std::string_view stream; + int depth = 0; +}; // Base template for Converter template @@ -168,9 +186,9 @@ struct Converter, std::enable_if_t 2) { std::vector result; - std::istringstream stream(s.substr(1, s.size() - 2)); - std::string token; - while (std::getline(stream, token, ',')) result.push_back(Converter::convert(clean_str(token))); + std::string_view token; + Extractor ex{s}; + while (ex.extract(token)) result.push_back(Converter::convert(std::string{trim_space(token)})); return result; } else { return {}; @@ -187,12 +205,11 @@ struct Converter, std::enable_if_t 2) { std::array result; - std::istringstream stream(s.substr(1, s.size() - 2)); - std::string token; + std::string_view token; + Extractor ex{s}; for (std::size_t i = 0; i < N; i++) { - if (std::getline(stream, token, ',')) { - std::cout << s << " " << token << std::endl; - result[i] = Converter::convert(clean_str(token)); + if (ex.extract(token)) { + result[i] = Converter::convert(std::string{trim_space(token)}); } else throw std::runtime_error("Array size mismatch. Expected: " + std::to_string(N) + " elements. String: " + s); } diff --git a/headeronly/tinyfwd.hpp b/headeronly/tinyfwd.hpp new file mode 100644 index 0000000..8ed637f --- /dev/null +++ b/headeronly/tinyfwd.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace tiny { + class Config; +} \ No newline at end of file diff --git a/vlm/dev/main.cpp b/vlm/dev/main.cpp index 4bdbbdd..1e77c8c 100644 --- a/vlm/dev/main.cpp +++ b/vlm/dev/main.cpp @@ -4,6 +4,8 @@ #include "vlm_types.hpp" #include "vlm_utils.hpp" +#include "tinyconfig.hpp" + #include #include #include diff --git a/vlm/dev/tests.cpp b/vlm/dev/tests.cpp deleted file mode 100644 index d91d3f4..0000000 --- a/vlm/dev/tests.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include "vlm.hpp" -#include "parser.hpp" -#include "vlm_types.hpp" -#include "vlm_solver.hpp" - -#include -#include -#include -#include -#include -#include - -// area of whole wing -float s_ref(float a, float b) { - return 0.5f * vlm::PI_f * a * b; -} - -// wing aspect ratio -float aspect_ratio(float a, float b) { - return (2*b)*(2*b) / s_ref(a, b); -} - -float analytical_cl(float alpha, float a, float b) { - alpha *= vlm::PI_f / 180.0f; // convert to rad - return 2.0f * vlm::PI_f * alpha / (1.0f + 2.0f/aspect_ratio(a, b)); -} - -float analytical_cd(float cl, float a, float b) { - return cl*cl / (vlm::PI_f * aspect_ratio(a, b)); -} - -float analytical_gamma(float y, float a, float b, float alpha) { - const float gamma0 = analytical_cl(alpha, a, b) * 1.0f * s_ref(a, b) / (vlm::PI_f * b); - const float ratio = y / b; - return gamma0 * std::sqrt(1.0f - ratio*ratio); -} - -bool elliptic_convergence() { - tiny::Config cfg("../../../../config/elliptic.vlm"); - - vlm::VLM vlm(cfg); - - std::vector dimensions = { - 16, 32, 45, 64, 90, 128 - }; - - const float a = 1.0f; // wing chord root - const float b = 5.0f; // half wing span - - std::vector norm_l1; - std::vector norm_l2; - std::vector norm_linf; - - const float alpha = 0.1f; // degrees - - for (const auto& dim : dimensions) { - std::string filename = std::format("../../../../mesh/elliptic_{}x{}.x", dim, dim); - vlm.mesh.io_read(filename); - vlm.init(); - vlm::Solver solver(vlm.mesh, vlm.data, cfg); - solver.run(alpha); - - double l1 = 0.0f; - double l2 = 0.0f; - double linf = 0.0f; - int begin = (vlm.mesh.nc - 1) * vlm.mesh.ns; - int end = vlm.mesh.nc * vlm.mesh.ns; - // loop over last row of panels - for (int i = begin; i < end; i++) { - const float y = vlm.mesh.colloc.y[i]; - const float gamma = vlm.data.gamma[i]; - const float gamma_analytical = analytical_gamma(y, a, b, alpha); - const double error = std::abs((gamma - gamma_analytical) / (gamma_analytical + 1e-7f)); - std::printf("y: %f, gamma: %f, gamma_analytical: %f, error: %f \n", y, gamma, gamma_analytical, error); - - l1 += error; - l2 += error * error; - linf = std::max(linf, error); - } - l1 /= (end - begin); - l2 = std::sqrt(l2) / (end - begin); - std::printf("L1: %f, L2: %f, Linf: %f\n", l1, l2, linf); - - norm_l1.push_back(l1); - norm_l2.push_back(l2); - norm_linf.push_back(linf); - } - - double order_l1 = 0.0f; - double order_l2 = 0.0f; - double order_linf = 0.0f; - - auto order = [=](double norm0, double norm1, float dim0, float dim1) { - return std::log(norm0 / norm1) / std::log((b/dim0)/(b/dim1)); - }; - - for (int i = 0; i < dimensions.size() - 1; i++) { - order_l1 += order(norm_l1[i], norm_l1[i+1], dimensions[i], dimensions[i+1]); - order_l2 += order(norm_l2[i], norm_l2[i+1], dimensions[i], dimensions[i+1]); - order_linf += order(norm_linf[i], norm_linf[i+1], dimensions[i], dimensions[i+1]); - } - order_l1 /= (dimensions.size() - 1); - order_l2 /= (dimensions.size() - 1); - order_linf /= (dimensions.size() - 1); - std::printf("Order L1: %f, Order L2: %f, Order Linf: %f\n", order_l1, order_l2, order_linf); - return 0; -} - -bool elliptic_coeffs() { - tiny::Config cfg("../../../../config/elliptic.vlm"); - - vlm::VLM vlm(cfg); - - // std::vector alphas = { - // 2, 4, 6, 8, 10, 12, 14, 16 - // }; // degrees - std::vector alphas = { - 5 - }; - const float a = 1.0f; // wing chord root - const float b = 5.0f; // half wing span - - std::string filename = "../../../../mesh/elliptic_64x64.x"; - vlm.mesh.io_read(filename); - vlm.init(); - - vlm::Solver solver(vlm.mesh, vlm.data, cfg); - for (auto alpha : alphas) { - solver.run(alpha); - std::printf("Analytical cl: %f\n", analytical_cl(alpha, a, b)); - std::printf("Analytical cd: %f\n", analytical_cd(analytical_cl(alpha, a, b), a, b)); - - int begin = (vlm.mesh.nc - 1) * vlm.mesh.ns; - int end = vlm.mesh.nc * vlm.mesh.ns; - std::ofstream file(std::format("gamma_{}.txt", alpha)); - // loop over last row of panels - for (int i = begin; i < end; i++) { - file << vlm.mesh.colloc.y[i] << " " << vlm.data.gamma[i] << "\n"; - } - file.close(); - }; - return 0; -} - -int main(int argc, char **argv) { - try { - //std::printf(">>> Elliptic convergence | %d", elliptic_convergence()); - std::printf(">>> Elliptic coefficients | %d", elliptic_coeffs()); - } catch (std::exception& e) { - std::cout << e.what() << std::endl; - return 1; - } - return 0; -} \ No newline at end of file diff --git a/vlm/include/vlm.hpp b/vlm/include/vlm.hpp index 0b5f049..d10d322 100644 --- a/vlm/include/vlm.hpp +++ b/vlm/include/vlm.hpp @@ -4,6 +4,7 @@ #include "vlm_data.hpp" #include "vlm_types.hpp" #include "vlm_backend.hpp" +#include "tinyfwd.hpp" namespace vlm { diff --git a/vlm/include/vlm_mesh.hpp b/vlm/include/vlm_mesh.hpp index 37b9877..6942998 100644 --- a/vlm/include/vlm_mesh.hpp +++ b/vlm/include/vlm_mesh.hpp @@ -1,6 +1,7 @@ #pragma once #include "vlm_types.hpp" +#include "tinyfwd.hpp" namespace vlm { diff --git a/vlm/include/vlm_types.hpp b/vlm/include/vlm_types.hpp index 2d0a931..50fd032 100644 --- a/vlm/include/vlm_types.hpp +++ b/vlm/include/vlm_types.hpp @@ -7,9 +7,9 @@ #include #include #include +#include #include "linalg.h" -#include "tinyconfig.hpp" namespace vlm { diff --git a/vlm/src/vlm.cpp b/vlm/src/vlm.cpp index aec90c7..c0bbc30 100644 --- a/vlm/src/vlm.cpp +++ b/vlm/src/vlm.cpp @@ -2,6 +2,7 @@ #include "vlm_backend.hpp" #include "tinytimer.hpp" +#include "tinyconfig.hpp" #include "vlm_data.hpp" #include diff --git a/vlm/src/vlm_mesh.cpp b/vlm/src/vlm_mesh.cpp index 89578bc..c690f0c 100644 --- a/vlm/src/vlm_mesh.cpp +++ b/vlm/src/vlm_mesh.cpp @@ -1,6 +1,7 @@ #include "vlm_mesh.hpp" #include "linalg.h" #include "vlm_types.hpp" +#include "tinyconfig.hpp" #include #include @@ -19,13 +20,6 @@ Mesh::Mesh(const tiny::Config& cfg) : cfg().section("mesh").get("c_ref", 0.0f), linalg::alias::float3{cfg().section("mesh").get>("ref_pt").data()} ) { - // auto res = cfg().section("mesh").get, 2>>("test"); - // for (auto& v : res) { - // for (auto& e : v) { - // std::cout << e << " "; - // } - // std::cout << "\n"; - // } } Mesh::Mesh( diff --git a/vlm/xmake.lua b/vlm/xmake.lua index 5034b65..3a780c2 100644 --- a/vlm/xmake.lua +++ b/vlm/xmake.lua @@ -2,6 +2,7 @@ add_requires("taskflow_custom") target("libvlm") set_kind("static") + set_policy("build.merge_archive", true) add_packages("taskflow_custom", {public = true}) for _,name in ipairs(backends) do