feat(RayFEM): initial commit
This commit is contained in:
111
.gitignore
vendored
Normal file
111
.gitignore
vendored
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.env
|
||||||
|
*.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
ENV.bak/
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# C and C++ (using Meson)
|
||||||
|
build/
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.d
|
||||||
|
*.dSYM/
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.obj
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.pdb
|
||||||
|
*.exp
|
||||||
|
*.log
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Fortran
|
||||||
|
*.mod
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Doxygen
|
||||||
|
html/
|
||||||
|
latex/
|
||||||
|
xml/
|
||||||
|
man/
|
||||||
|
rtf/
|
||||||
|
tags
|
||||||
|
|
||||||
|
## Misc
|
||||||
|
*.swp
|
||||||
|
*._DS_Store
|
||||||
|
*.DS_Store
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
*.cache
|
||||||
|
*.private
|
||||||
|
*.private/
|
||||||
|
|
||||||
|
subprojects/mfem/
|
||||||
|
subprojects/tetgen/
|
||||||
|
subprojects/yaml-cpp/
|
||||||
|
subprojects/quill/
|
||||||
|
subprojects/googletest-*/
|
||||||
|
subprojects/opat-core/
|
||||||
|
subprojects/pybind11*/
|
||||||
|
subprojects/packagecache/
|
||||||
|
subprojects/hypre/
|
||||||
|
subprojects/qhull/
|
||||||
|
subprojects/libconstants/
|
||||||
|
subprojects/liblogging/
|
||||||
|
subprojects/libconfig/
|
||||||
|
subprojects/libcomposition/
|
||||||
|
subprojects/GridFire/
|
||||||
|
subprojects/tomlplusplus-*/
|
||||||
|
subprojects/CLI11-*/
|
||||||
|
subprojects/magic_enum-*/
|
||||||
|
subprojects/raylib/
|
||||||
|
subprojects/czmq/
|
||||||
|
|
||||||
|
|
||||||
|
qhull.wrap
|
||||||
|
quill.wrap
|
||||||
|
yaml-cpp.wrap
|
||||||
|
cppad.wrap
|
||||||
|
tomlplusplus.wrap
|
||||||
|
gtest.wrap
|
||||||
|
|
||||||
|
subprojects/quill.wrap
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
*.log
|
||||||
|
mpi-install-log.txt
|
||||||
|
|
||||||
|
output/
|
||||||
|
|
||||||
|
.boost_installed
|
||||||
|
4DSSE_logs/
|
||||||
|
.last_build_flags
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
scratch/
|
||||||
|
|
||||||
|
releases/
|
||||||
|
stroid-dist/
|
||||||
|
stroid-universal-dist.tar.gz
|
||||||
|
stroid-*/
|
||||||
|
stroid-*.tar.gz
|
||||||
2
build-config/CLI11/meson.build
Normal file
2
build-config/CLI11/meson.build
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
cli11_proj = subproject('cli11')
|
||||||
|
dependencies += cli11_proj.get_variable('CLI11_dep')
|
||||||
12
build-config/czmq/meson.build
Normal file
12
build-config/czmq/meson.build
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
czmq_opts = cmake.subproject_options()
|
||||||
|
czmq_opts.add_cmake_defines({
|
||||||
|
'CMAKE_POLICY_VERSION_MINIMUM': '3.5',
|
||||||
|
'CMAKE_C_FLAGS': '-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0',
|
||||||
|
'CMAKE_CXX_FLAGS': '-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0'
|
||||||
|
})
|
||||||
|
|
||||||
|
czmq_opts.set_install(false)
|
||||||
|
|
||||||
|
czmq_subproject = cmake.subproject('czmq', options: czmq_opts)
|
||||||
|
|
||||||
|
dependencies += czmq_subproject.dependency('czmq')
|
||||||
8
build-config/libconfig/meson.build
Normal file
8
build-config/libconfig/meson.build
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
config_p = subproject('libconfig',
|
||||||
|
default_options:[
|
||||||
|
'default_library=static',
|
||||||
|
'pkg_config=false',
|
||||||
|
'build_tests=false',
|
||||||
|
'build_examples=false'
|
||||||
|
])
|
||||||
|
dependencies += config_p.get_variable('config_dep')
|
||||||
7
build-config/meson.build
Normal file
7
build-config/meson.build
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
cmake = import('cmake')
|
||||||
|
|
||||||
|
subdir('raylib')
|
||||||
|
subdir('czmq')
|
||||||
|
subdir('mfem')
|
||||||
|
subdir('CLI11')
|
||||||
|
subdir('libconfig')
|
||||||
16
build-config/mfem/meson.build
Normal file
16
build-config/mfem/meson.build
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
cmake = import('cmake')
|
||||||
|
mfem_cmake_options = cmake.subproject_options()
|
||||||
|
mfem_cmake_options.add_cmake_defines({
|
||||||
|
'MFEM_ENABLE_EXAMPLES': 'OFF',
|
||||||
|
'MFEM_ENABLE_TESTING': 'OFF',
|
||||||
|
'MFEM_ENABLE_MINIAPPS': 'OFF',
|
||||||
|
'MFEM_USE_BENCMARK': 'OFF',
|
||||||
|
'BUILD_SHARED_LIBS': 'OFF',
|
||||||
|
'BUILD_STATIC_LIBS': 'ON',
|
||||||
|
})
|
||||||
|
mfem_cmake_options.set_install(true)
|
||||||
|
|
||||||
|
mfem_sp = cmake.subproject(
|
||||||
|
'mfem',
|
||||||
|
options: mfem_cmake_options)
|
||||||
|
dependencies += mfem_sp.dependency('mfem')
|
||||||
39
build-config/raylib/meson.build
Normal file
39
build-config/raylib/meson.build
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
raylib_opts = cmake.subproject_options()
|
||||||
|
raylib_opts.set_install(false)
|
||||||
|
raylib_opts.add_cmake_defines({
|
||||||
|
'BUILD_EXAMPLES': 'OFF',
|
||||||
|
})
|
||||||
|
if cc.get_id() == 'emscripten'
|
||||||
|
raylib_opts.add_cmake_defines({
|
||||||
|
'PLATFORM': 'Web',
|
||||||
|
})
|
||||||
|
else
|
||||||
|
raylib_opts.add_cmake_defines({
|
||||||
|
'PLATFORM': 'Desktop',
|
||||||
|
})
|
||||||
|
endif
|
||||||
|
raylib_subproject = cmake.subproject('raylib', options: raylib_opts)
|
||||||
|
dependencies += raylib_subproject.dependency('raylib')
|
||||||
|
|
||||||
|
# General configuration
|
||||||
|
if host_machine.system() == 'windows'
|
||||||
|
dependencies += [
|
||||||
|
cc.find_library('winmm'),
|
||||||
|
]
|
||||||
|
elif host_machine.system() == 'darwin'
|
||||||
|
link_args += [
|
||||||
|
'-framework', 'AppKit',
|
||||||
|
'-framework', 'IOKit',
|
||||||
|
]
|
||||||
|
elif host_machine.system() == 'linux'
|
||||||
|
dependencies += [
|
||||||
|
cc.find_library('m'),
|
||||||
|
cc.find_library('dl'),
|
||||||
|
]
|
||||||
|
elif host_machine.system() == 'emscripten'
|
||||||
|
link_args += [
|
||||||
|
'-s', 'ENVIRONMENT=web',
|
||||||
|
'-s', 'USE_GLFW=3',
|
||||||
|
]
|
||||||
|
name_suffix = 'html'
|
||||||
|
endif
|
||||||
10
default.toml
Normal file
10
default.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[main]
|
||||||
|
core_steepness = 1.0
|
||||||
|
flattening = 0.0
|
||||||
|
include_external_domain = false
|
||||||
|
order = 1
|
||||||
|
r_core = 1.5
|
||||||
|
r_infinity = 6.0
|
||||||
|
r_instability = 1e-14
|
||||||
|
r_star = 5.0
|
||||||
|
refinement_levels = 2
|
||||||
17
meson.build
Normal file
17
meson.build
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
project('RayFEM', ['cpp', 'c'],
|
||||||
|
version : '0.1.0',
|
||||||
|
default_options : ['warning_level=3', 'cpp_std=c++23'])
|
||||||
|
|
||||||
|
c_args = []
|
||||||
|
cpp_args = []
|
||||||
|
link_args = []
|
||||||
|
name_suffix = []
|
||||||
|
dependencies = []
|
||||||
|
|
||||||
|
add_project_arguments('-U_FORTIFY_SOURCE', '-D_FORTIFY_SOURCE=0', language: 'cpp')
|
||||||
|
|
||||||
|
cc = meson.get_compiler('c')
|
||||||
|
cxx = meson.get_compiler('cpp')
|
||||||
|
|
||||||
|
subdir('build-config')
|
||||||
|
subdir('src')
|
||||||
41
src/app/client.cpp
Normal file
41
src/app/client.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "libRayfem/network/client.hpp"
|
||||||
|
#include "mfem.hpp"
|
||||||
|
#include "fourdst/config/config.h"
|
||||||
|
#include "CLI/CLI.hpp"
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
struct config {
|
||||||
|
std::string host = "localhost";
|
||||||
|
int port = 5555;
|
||||||
|
std::string mesh_file = "stroid.mesh";
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
fourdst::config::Config<config> cfg;
|
||||||
|
CLI::App app{"RayFEM Client"};
|
||||||
|
fourdst::config::register_as_cli(cfg, app, "config");
|
||||||
|
CLI11_PARSE(app, argc, argv)
|
||||||
|
|
||||||
|
auto mesh = std::make_unique<mfem::Mesh>(cfg->mesh_file.c_str());
|
||||||
|
mesh->EnsureNodes();
|
||||||
|
|
||||||
|
mfem::FiniteElementSpace fespace(mesh.get(), new mfem::H1_FECollection(1, mesh->Dimension()), 1);
|
||||||
|
mfem::GridFunction gf(&fespace);
|
||||||
|
gf = 0.5;
|
||||||
|
|
||||||
|
RayFEM::Client client(cfg->host, cfg->port);
|
||||||
|
|
||||||
|
RayFEM::FrameMetadata meta;
|
||||||
|
meta.frame_index = 0;
|
||||||
|
meta.sim_time = 0.0;
|
||||||
|
|
||||||
|
|
||||||
|
if (client.send(*mesh, gf, meta)) {
|
||||||
|
std::println("Frame sent successfully.");
|
||||||
|
} else {
|
||||||
|
std::println("Failed to send frame.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
50
src/app/main.cpp
Normal file
50
src/app/main.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include <print>
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include "libRayfem/network/server.hpp"
|
||||||
|
|
||||||
|
#include "fourdst/config/config.h"
|
||||||
|
|
||||||
|
#include "CLI/CLI.hpp"
|
||||||
|
#include "czmq.h"
|
||||||
|
|
||||||
|
struct Options {
|
||||||
|
std::string listen = "0.0.0.0";
|
||||||
|
int port = 5555;
|
||||||
|
int target_fps = 60;
|
||||||
|
int screenwidth = 800;
|
||||||
|
int screenheight = 600;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
zsys_init();
|
||||||
|
|
||||||
|
fourdst::config::Config<Options> config;
|
||||||
|
CLI::App app{"RayFEM Server"};
|
||||||
|
fourdst::config::register_as_cli(config, app, "config");
|
||||||
|
CLI11_PARSE(app, argc, argv)
|
||||||
|
|
||||||
|
const int screenwidth = config->screenwidth;
|
||||||
|
const int screenheight = config->screenheight;
|
||||||
|
|
||||||
|
InitWindow(screenwidth, screenheight, "raylib");
|
||||||
|
|
||||||
|
SetTargetFPS(config->target_fps);
|
||||||
|
|
||||||
|
RayFEM::Server server(config->listen, config->port);
|
||||||
|
bool hasRecivedData = false;
|
||||||
|
|
||||||
|
while (!WindowShouldClose()) {
|
||||||
|
auto frame = server.fetchLatestFrame();
|
||||||
|
if (frame) {
|
||||||
|
hasRecivedData = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BeginDrawing();
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
std::string msg = std::format("Has Received {} frames", server.getReceivedFrameCount());
|
||||||
|
DrawText(msg.c_str(), 250, 280, 20, DARKGREEN);
|
||||||
|
EndDrawing();
|
||||||
|
}
|
||||||
|
CloseWindow();
|
||||||
|
}
|
||||||
19
src/libRayfem/include/libRayfem/frame/render.hpp
Normal file
19
src/libRayfem/include/libRayfem/frame/render.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mfem.hpp"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "libRayfem/network/packet.hpp"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
struct RenderFrame {
|
||||||
|
FrameMetadata metadata;
|
||||||
|
std::unique_ptr<mfem::Mesh> mesh;
|
||||||
|
std::unique_ptr<mfem::GridFunction> gf;
|
||||||
|
|
||||||
|
Model rayModel;
|
||||||
|
bool isUploaded = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
8
src/libRayfem/include/libRayfem/mesh/converter.hpp
Normal file
8
src/libRayfem/include/libRayfem/mesh/converter.hpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "mfem.hpp"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
Model LoadModelFromMFEM(mfem::Mesh& mesh, mfem::GridFunction& gf);
|
||||||
|
}
|
||||||
20
src/libRayfem/include/libRayfem/network/client.hpp
Normal file
20
src/libRayfem/include/libRayfem/network/client.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "mfem.hpp"
|
||||||
|
#include "libRayfem/network/packet.hpp"
|
||||||
|
#include "zmq.hpp"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
Client(const std::string& host, size_t port);
|
||||||
|
bool send(mfem::Mesh& mesh, mfem::GridFunction& gf, const FrameMetadata& meta);
|
||||||
|
private:
|
||||||
|
std::string m_host;
|
||||||
|
size_t m_port;
|
||||||
|
std::string m_address;
|
||||||
|
|
||||||
|
SocketPtr m_socket;
|
||||||
|
};
|
||||||
|
}
|
||||||
21
src/libRayfem/include/libRayfem/network/packet.hpp
Normal file
21
src/libRayfem/include/libRayfem/network/packet.hpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
struct FrameMetadata {
|
||||||
|
uint32_t frame_index = 0;
|
||||||
|
double sim_time = 0;
|
||||||
|
char label[64] = "MFEM Simulation";
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct PacketHeader {
|
||||||
|
uint64_t magic = 0x52415946454D;
|
||||||
|
FrameMetadata metadata;
|
||||||
|
uint64_t mesh_bytes = 0;
|
||||||
|
uint64_t gf_bytes = 0;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
}
|
||||||
32
src/libRayfem/include/libRayfem/network/server.hpp
Normal file
32
src/libRayfem/include/libRayfem/network/server.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <deque>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "libRayfem/frame/render.hpp"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
class Server {
|
||||||
|
public:
|
||||||
|
Server(const std::string& listen, size_t port);
|
||||||
|
~Server();
|
||||||
|
|
||||||
|
std::unique_ptr<RenderFrame> fetchLatestFrame();
|
||||||
|
size_t getReceivedFrameCount() const { return m_frameCount.load(); }
|
||||||
|
private:
|
||||||
|
std::string m_listen;
|
||||||
|
int m_port;
|
||||||
|
std::atomic<bool> m_running;
|
||||||
|
std::atomic<size_t> m_frameCount{0};
|
||||||
|
std::thread m_worker;
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::deque<std::unique_ptr<RenderFrame>> m_frameQueue;
|
||||||
|
private:
|
||||||
|
void networkLoop();
|
||||||
|
};
|
||||||
|
}
|
||||||
42
src/libRayfem/include/libRayfem/network/zmq.hpp
Normal file
42
src/libRayfem/include/libRayfem/network/zmq.hpp
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "czmq.h"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
template <typename T, void (*Destroyer)(T**)>
|
||||||
|
class ZmqPtr {
|
||||||
|
public:
|
||||||
|
ZmqPtr(T* ptr = nullptr) : ptr_(ptr) {}
|
||||||
|
~ZmqPtr() { if (ptr_) Destroyer(&ptr_); }
|
||||||
|
|
||||||
|
ZmqPtr(const ZmqPtr&) = delete;
|
||||||
|
ZmqPtr& operator=(const ZmqPtr&) = delete;
|
||||||
|
|
||||||
|
ZmqPtr(ZmqPtr&& other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; }
|
||||||
|
ZmqPtr& operator=(ZmqPtr&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
if (ptr_) Destroyer(&ptr_);
|
||||||
|
ptr_ = other.ptr_;
|
||||||
|
other.ptr_ = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* release() {
|
||||||
|
T* temp = ptr_;
|
||||||
|
ptr_ = nullptr;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get() const { return ptr_; }
|
||||||
|
operator T*() const { return ptr_; }
|
||||||
|
T** operator&() { return &ptr_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* ptr_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
using SocketPtr = ZmqPtr<zsock_t, zsock_destroy>;
|
||||||
|
using MsgPtr = ZmqPtr<zmsg_t, zmsg_destroy>;
|
||||||
|
using FramePtr = ZmqPtr<zframe_t, zframe_destroy>;
|
||||||
|
}
|
||||||
118
src/libRayfem/lib/mesh/converter.cpp
Normal file
118
src/libRayfem/lib/mesh/converter.cpp
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#include "libRayfem/mesh/converter.hpp"
|
||||||
|
#include "mfem.hpp"
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Color GetColorFromValue(double val, double min, double max) {
|
||||||
|
double t = (val - min) / (max - min);
|
||||||
|
t = std::clamp(t, 0.0, 1.0);
|
||||||
|
return ColorFromNormalized({t, 1-t, 0.5+(t*0.5), 1};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
Model LoadModelFromMFEM(mfem::Mesh &mesh, mfem::GridFunction &gf) {
|
||||||
|
Mesh rMesh = { 0 };
|
||||||
|
int numElements = mesh.GetNE();
|
||||||
|
|
||||||
|
int totalTriangles = 0;
|
||||||
|
for (int i = 0; i < numElements; i++) {
|
||||||
|
mfem::Geometry::Type geom = mesh.GetElementBaseGeometry(i);
|
||||||
|
switch (geom) {
|
||||||
|
case mfem::Geometry::TRIANGLE:
|
||||||
|
totalTriangles += 1;
|
||||||
|
break;
|
||||||
|
case mfem::Geometry::SQUARE:
|
||||||
|
totalTriangles += 2;
|
||||||
|
break;
|
||||||
|
case mfem::Geometry::TETRAHEDRON:
|
||||||
|
totalTriangles += 4;
|
||||||
|
break;
|
||||||
|
case mfem::Geometry::CUBE:
|
||||||
|
totalTriangles += 12;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("Unsupported element geometry in MFEM to Raylib converter.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rMesh.triangleCount = totalTriangles;
|
||||||
|
|
||||||
|
rMesh.vertexCount = rMesh.triangleCount * 3;
|
||||||
|
|
||||||
|
rMesh.vertices = (float *)RL_MALLOC(rMesh.vertexCount * 3 * sizeof(float));
|
||||||
|
rMesh.colors = (unsigned char *)RL_MALLOC(rMesh.vertexCount * 4 * sizeof(unsigned char));
|
||||||
|
|
||||||
|
double vMin = gf.Min();
|
||||||
|
double vMax = gf.Max();
|
||||||
|
|
||||||
|
|
||||||
|
int vOffset =0;
|
||||||
|
auto AddTriangle = [&](const mfem::Vector& p1, const mfem::Vector& p2, const mfem::Vector& p3, double val1, double val2, double val3) {
|
||||||
|
float* v = rMesh.vertices;
|
||||||
|
|
||||||
|
v[vOffset * 3 + 0] = static_cast<float>(p1(0));
|
||||||
|
v[vOffset * 3 + 1] = static_cast<float>(p1(1));
|
||||||
|
v[vOffset * 3 + 2] = static_cast<float>(p1(2));
|
||||||
|
|
||||||
|
v[vOffset * 3 + 3] = static_cast<float>(p2(0));
|
||||||
|
v[vOffset * 3 + 4] = static_cast<float>(p2(1));
|
||||||
|
v[vOffset * 3 + 5] = static_cast<float>(p2(2));
|
||||||
|
|
||||||
|
v[vOffset * 3 + 6] = static_cast<float>(p3(0));
|
||||||
|
v[vOffset * 3 + 7] = static_cast<float>(p3(1));
|
||||||
|
v[vOffset * 3 + 8] = static_cast<float>(p3(2));
|
||||||
|
|
||||||
|
const Color c1 = GetColorFromValue(val1, vMin, vMax);
|
||||||
|
const Color c2 = GetColorFromValue(val2, vMin, vMax);
|
||||||
|
const Color c3 = GetColorFromValue(val3, vMin, vMax);
|
||||||
|
|
||||||
|
unsigned char* c = rMesh.colors;
|
||||||
|
c[vOffset * 4 + 0] = c1.r;
|
||||||
|
c[vOffset * 4 + 1] = c1.g;
|
||||||
|
c[vOffset * 4 + 2] = c1.b;
|
||||||
|
c[vOffset * 4 + 3] = c1.a;
|
||||||
|
|
||||||
|
c[vOffset * 4 + 4] = c2.r;
|
||||||
|
c[vOffset * 4 + 5] = c2.g;
|
||||||
|
c[vOffset * 4 + 6] = c2.b;
|
||||||
|
c[vOffset * 4 + 7] = c2.a;
|
||||||
|
|
||||||
|
c[vOffset * 4 + 8] = c3.r;
|
||||||
|
c[vOffset * 4 + 9] = c3.g;
|
||||||
|
c[vOffset * 4 + 10] = c3.b;
|
||||||
|
c[vOffset * 4 + 11] = c3.a;
|
||||||
|
|
||||||
|
vOffset += 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < numElements; i++) {
|
||||||
|
mfem::Element* el = mesh.GetElement(i);
|
||||||
|
mfem::Array<int> verticies;
|
||||||
|
mesh.GetElementVertices(i, verticies);
|
||||||
|
|
||||||
|
auto GetPV = [&](int localIdx) {
|
||||||
|
mfem::Vector pos;
|
||||||
|
pos = mesh.GetVertex(verticies[localIdx]);
|
||||||
|
|
||||||
|
if (pos.Size() == 2) {
|
||||||
|
pos.SetSize(3);
|
||||||
|
pos(2) = 0.0;
|
||||||
|
}
|
||||||
|
return std::make_pair(pos, gf(verticies[localIdx]));
|
||||||
|
};
|
||||||
|
|
||||||
|
mfem::Geometry::Type geom = mesh.GetElementBaseGeometry(i);
|
||||||
|
switch (geom) {
|
||||||
|
case mfem::Geometry::TRIANGLE: {
|
||||||
|
auto [p0, v0] = GetPV(0);
|
||||||
|
auto [p1, v1] = GetPV(1);
|
||||||
|
auto [p2, v2] = GetPV(2);
|
||||||
|
|
||||||
|
AddTriangle(p0, p1, p2, v0, v1, v2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/libRayfem/lib/network/client.cpp
Normal file
57
src/libRayfem/lib/network/client.cpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#include "libRayfem/network/client.hpp"
|
||||||
|
#include "libRayfem/network/zmq.hpp"
|
||||||
|
#include "libRayfem/network/packet.hpp"
|
||||||
|
#include "czmq.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string format_address(const std::string& host, const size_t port) {
|
||||||
|
return "tcp://" + host + ":" + std::to_string(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
Client::Client(
|
||||||
|
const std::string &host,
|
||||||
|
const size_t port
|
||||||
|
)
|
||||||
|
:
|
||||||
|
m_host(host),
|
||||||
|
m_port(port),
|
||||||
|
m_address(format_address(m_host, m_port)),
|
||||||
|
m_socket(zsock_new_push(m_address.c_str())) {
|
||||||
|
if (!m_socket) {
|
||||||
|
throw std::runtime_error("Failed to create ZMQ socket to " + m_address);
|
||||||
|
}
|
||||||
|
zsock_set_linger(m_socket, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Client::send(mfem::Mesh &mesh, mfem::GridFunction &gf, const FrameMetadata& meta) {
|
||||||
|
if (!m_socket) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream m_ss, g_ss;
|
||||||
|
|
||||||
|
mesh.Print(m_ss);
|
||||||
|
gf.Save(g_ss);
|
||||||
|
|
||||||
|
std::string m_data = m_ss.str();
|
||||||
|
std::string g_data = g_ss.str();
|
||||||
|
|
||||||
|
MsgPtr msg(zmsg_new());
|
||||||
|
|
||||||
|
PacketHeader header{.metadata = meta, .mesh_bytes = m_data.size(), .gf_bytes = g_data.size()};
|
||||||
|
zmsg_addmem(msg, &header, sizeof(PacketHeader));
|
||||||
|
zmsg_addstr(msg, m_data.c_str());
|
||||||
|
zmsg_addstr(msg, g_data.c_str());
|
||||||
|
|
||||||
|
zmsg_t* raw_msg = msg.get();
|
||||||
|
int rc = zmsg_send(&raw_msg, m_socket);
|
||||||
|
msg.release();
|
||||||
|
return rc == 0;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
95
src/libRayfem/lib/network/server.cpp
Normal file
95
src/libRayfem/lib/network/server.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include "libRayfem/frame/render.hpp"
|
||||||
|
#include "libRayfem/network/server.hpp"
|
||||||
|
#include "libRayfem/network/zmq.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include "czmq.h"
|
||||||
|
|
||||||
|
namespace RayFEM {
|
||||||
|
Server::Server(
|
||||||
|
const std::string& listen,
|
||||||
|
const size_t port
|
||||||
|
) :
|
||||||
|
m_listen(listen),
|
||||||
|
m_port(port),
|
||||||
|
m_running(true),
|
||||||
|
m_worker(std::thread(&Server::networkLoop, this)) {}
|
||||||
|
|
||||||
|
Server::~Server() {
|
||||||
|
m_running = false;
|
||||||
|
if (m_worker.joinable()) {
|
||||||
|
m_worker.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<RenderFrame> Server::fetchLatestFrame() {
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
if (m_frameQueue.empty()) return nullptr;
|
||||||
|
|
||||||
|
auto frame = std::move(m_frameQueue.back());
|
||||||
|
m_frameQueue.clear();
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::networkLoop() {
|
||||||
|
std::string address = "tcp://" + m_listen + ":" + std::to_string(m_port);
|
||||||
|
|
||||||
|
SocketPtr pull(zsock_new_pull(address.c_str()));
|
||||||
|
|
||||||
|
zpoller_t *poller = zpoller_new(pull.get(), NULL);
|
||||||
|
|
||||||
|
while (m_running) {
|
||||||
|
void *which = zpoller_wait(poller, 100);
|
||||||
|
if (!which) continue;
|
||||||
|
|
||||||
|
MsgPtr msg(zmsg_recv(pull.get()));
|
||||||
|
if (!msg) continue;
|
||||||
|
|
||||||
|
auto frame = std::make_unique<RenderFrame>();
|
||||||
|
|
||||||
|
zframe_t *h_frame = zmsg_pop(msg.get());
|
||||||
|
if (zframe_size(h_frame) == sizeof(PacketHeader)) {
|
||||||
|
frame->metadata = reinterpret_cast<PacketHeader *>(zframe_data(h_frame))->metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
zframe_destroy(&h_frame);
|
||||||
|
|
||||||
|
zframe_t *m_frame = zmsg_pop(msg.get());
|
||||||
|
zframe_t *g_frame = zmsg_pop(msg.get());
|
||||||
|
|
||||||
|
if (m_frame && g_frame) {
|
||||||
|
std::string m_data(reinterpret_cast<char *>(zframe_data(m_frame)), zframe_size(m_frame));
|
||||||
|
std::string g_data(reinterpret_cast<char *>(zframe_data(g_frame)), zframe_size(g_frame));
|
||||||
|
|
||||||
|
std::cout << g_data << std::endl;
|
||||||
|
|
||||||
|
std::stringstream m_ss(m_data);
|
||||||
|
std::stringstream g_ss(g_data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
frame->mesh = std::make_unique<mfem::Mesh>(m_ss);
|
||||||
|
frame->mesh->EnsureNodes();
|
||||||
|
frame->gf = std::make_unique<mfem::GridFunction>(frame->mesh.get(), g_ss);
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "Error creating mesh frame" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
++m_frameCount;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
m_frameQueue.push_back(std::move(frame));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zframe_destroy(&m_frame);
|
||||||
|
zframe_destroy(&g_frame);
|
||||||
|
|
||||||
|
}
|
||||||
|
zpoller_destroy(&poller);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/libRayfem/meson.build
Normal file
23
src/libRayfem/meson.build
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
include_dirs = include_directories('include')
|
||||||
|
sources = files(
|
||||||
|
'lib/network/client.cpp',
|
||||||
|
'lib/network/server.cpp',
|
||||||
|
'lib/mesh/converter.cpp'
|
||||||
|
)
|
||||||
|
|
||||||
|
libRayFem = library(
|
||||||
|
'libRayFem',
|
||||||
|
sources,
|
||||||
|
include_directories: include_dirs,
|
||||||
|
dependencies: dependencies,
|
||||||
|
cpp_args: cpp_args,
|
||||||
|
install: true
|
||||||
|
)
|
||||||
|
|
||||||
|
rayfem_dep = declare_dependency(
|
||||||
|
include_directories: include_dirs,
|
||||||
|
link_with: libRayFem,
|
||||||
|
sources: sources,
|
||||||
|
dependencies: dependencies,
|
||||||
|
compile_args: cpp_args,
|
||||||
|
)
|
||||||
17
src/meson.build
Normal file
17
src/meson.build
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
subdir('libRayFem')
|
||||||
|
executable(
|
||||||
|
'RayFEM',
|
||||||
|
'app/main.cpp',
|
||||||
|
dependencies: [dependencies, rayfem_dep],
|
||||||
|
cpp_args: cpp_args,
|
||||||
|
c_args: c_args,
|
||||||
|
link_args: link_args
|
||||||
|
)
|
||||||
|
executable(
|
||||||
|
'exampleClient',
|
||||||
|
'app/client.cpp',
|
||||||
|
dependencies: [dependencies, rayfem_dep],
|
||||||
|
cpp_args: cpp_args,
|
||||||
|
c_args: c_args,
|
||||||
|
link_args: link_args
|
||||||
|
)
|
||||||
2128
stroid.mesh
Normal file
2128
stroid.mesh
Normal file
File diff suppressed because it is too large
Load Diff
0
subprojects/.wraplock
Normal file
0
subprojects/.wraplock
Normal file
10
subprojects/cli11.wrap
Normal file
10
subprojects/cli11.wrap
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[wrap-file]
|
||||||
|
directory = CLI11-2.6.1
|
||||||
|
source_url = https://github.com/CLIUtils/CLI11/archive/refs/tags/v2.6.1.tar.gz
|
||||||
|
source_filename = CLI11-2.6.1.tar.gz
|
||||||
|
source_hash = 377691f3fac2b340f12a2f79f523c780564578ba3d6eaf5238e9f35895d5ba95
|
||||||
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cli11_2.6.1-1/CLI11-2.6.1.tar.gz
|
||||||
|
wrapdb_version = 2.6.1-1
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
dependency_names = CLI11
|
||||||
6
subprojects/czmq.wrap
Normal file
6
subprojects/czmq.wrap
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/zeromq/czmq
|
||||||
|
revision = v4.2.1
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
[cmake]
|
||||||
4
subprojects/libconfig.wrap
Normal file
4
subprojects/libconfig.wrap
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/4D-STAR/libconfig.git
|
||||||
|
revision = v2.1.0
|
||||||
|
depth = 1
|
||||||
7
subprojects/mfem.wrap
Normal file
7
subprojects/mfem.wrap
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/mfem/mfem.git
|
||||||
|
revision = v4.8-rc0
|
||||||
|
diff_files = mfem/disable_mfem_selfcheck.patch
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
[cmake]
|
||||||
6
subprojects/packagefiles/hypre/CMakeLists.txt
Normal file
6
subprojects/packagefiles/hypre/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# subprojects/packagefiles/hypre/CMakeLists.txt
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(hypre-wrapper C CXX)
|
||||||
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
# This file is just used to redirect to the src directory where hypre stores its CMakeLists.txt
|
||||||
41
subprojects/packagefiles/mfem/disable_mfem_selfcheck.patch
Normal file
41
subprojects/packagefiles/mfem/disable_mfem_selfcheck.patch
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
--- mfem/CMakeLists.txt 2025-02-12 15:54:52.454728232 -0500
|
||||||
|
+++ CMakeLists.txt.bak 2025-02-12 16:08:06.654542689 -0500
|
||||||
|
@@ -765,7 +765,7 @@
|
||||||
|
if (MFEM_ENABLE_EXAMPLES)
|
||||||
|
add_subdirectory(examples) #install examples if enabled
|
||||||
|
else()
|
||||||
|
- add_subdirectory(examples EXCLUDE_FROM_ALL)
|
||||||
|
+ # add_subdirectory(examples EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Create a target for all miniapps and, optionally, enable it.
|
||||||
|
@@ -774,7 +774,7 @@
|
||||||
|
if (MFEM_ENABLE_MINIAPPS)
|
||||||
|
add_subdirectory(miniapps) #install miniapps if enabled
|
||||||
|
else()
|
||||||
|
- add_subdirectory(miniapps EXCLUDE_FROM_ALL)
|
||||||
|
+ # add_subdirectory(miniapps EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Target to build all executables, i.e. everything.
|
||||||
|
@@ -801,19 +801,7 @@
|
||||||
|
add_dependencies(${MFEM_EXEC_PREREQUISITES_TARGET_NAME} copy_data)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
-# Add 'check' target - quick test
|
||||||
|
-set(MFEM_CHECK_TARGET_NAME ${MFEM_CUSTOM_TARGET_PREFIX}check)
|
||||||
|
-if (NOT MFEM_USE_MPI)
|
||||||
|
- add_custom_target(${MFEM_CHECK_TARGET_NAME}
|
||||||
|
- ${CMAKE_CTEST_COMMAND} -R \"^ex1_ser\" -C ${CMAKE_CFG_INTDIR}
|
||||||
|
- USES_TERMINAL)
|
||||||
|
- add_dependencies(${MFEM_CHECK_TARGET_NAME} ex1)
|
||||||
|
-else()
|
||||||
|
- add_custom_target(${MFEM_CHECK_TARGET_NAME}
|
||||||
|
- ${CMAKE_CTEST_COMMAND} -R \"^ex1p\" -C ${CMAKE_CFG_INTDIR}
|
||||||
|
- USES_TERMINAL)
|
||||||
|
- add_dependencies(${MFEM_CHECK_TARGET_NAME} ex1p)
|
||||||
|
-endif()
|
||||||
|
+message(STATUS "MFEM Miniapps and Examples disabled by patch!")
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Documentation
|
||||||
6
subprojects/raylib.wrap
Normal file
6
subprojects/raylib.wrap
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/raysan5/raylib.git
|
||||||
|
revision = 5.5
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
[cmake]
|
||||||
Reference in New Issue
Block a user