forked from 1b-agent/fieldcraft-upstream
Rename the project to FieldCraft
Crates fieldcraft-*, binaries fieldcraft and fieldcraft-cli, the .fieldcraft file (format tag fieldcraft/1, manifest fieldcraft.json), FIELDCRAFT_* environment variables, the MCP server name, egui widget ids (fc_*), the app icon document FieldCraft.icon and its generated family, docs and licences. No compatibility shim: no files of the earlier name exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
9bc4e1b182
commit
d5bd74570f
268 files changed
+1666
-1666
No files matched your search
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "modelcraft-lbm"
|
||||
description = "ModelCraft's lattice Boltzmann flow solver: D3Q19 two-relaxation-time collision, bounce-back walls, Zou–He inlets and outlets, exact voxelisation of face-tagged surfaces, momentum-exchange wall forces"
|
||||
name = "fieldcraft-lbm"
|
||||
description = "FieldCraft's lattice Boltzmann flow solver: D3Q19 two-relaxation-time collision, bounce-back walls, Zou–He inlets and outlets, exact voxelisation of face-tagged surfaces, momentum-exchange wall forces"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
@@ -9,7 +9,7 @@ license.workspace = true
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
modelcraft-model = { workspace = true }
|
||||
modelcraft-mesh = { workspace = true }
|
||||
modelcraft-parallel = { workspace = true }
|
||||
fieldcraft-model = { workspace = true }
|
||||
fieldcraft-mesh = { workspace = true }
|
||||
fieldcraft-parallel = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
@@ -36,9 +36,9 @@
|
||||
//! only its own populations; the wall forces are summed in link order. There are no parallel
|
||||
//! reductions, so the result is the same bit for bit on any number of threads and platform.
|
||||
|
||||
use modelcraft_model::{BoxFace, FaceCondition, Profile};
|
||||
use fieldcraft_model::{BoxFace, FaceCondition, Profile};
|
||||
|
||||
use modelcraft_parallel as parallel;
|
||||
use fieldcraft_parallel as parallel;
|
||||
|
||||
use crate::lattice::{C, Q, W, c, equilibrium, moving_wall, opposite};
|
||||
use crate::setup::{MAX_LATTICE_SPEED, Obstacle, Setup};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! ModelCraft's lattice Boltzmann flow solver (CPU).
|
||||
//! FieldCraft's lattice Boltzmann flow solver (CPU).
|
||||
//!
|
||||
//! It solves a fluid step of the model ([`modelcraft_model::Procedure::Fluid`]) in its fluid
|
||||
//! It solves a fluid step of the model ([`fieldcraft_model::Procedure::Fluid`]) in its fluid
|
||||
//! domain: weakly compressible, isothermal, Newtonian flow on a uniform grid of cubic cells that
|
||||
//! fills the domain's box, less the cells inside the obstacle bodies.
|
||||
//!
|
||||
@@ -33,14 +33,14 @@
|
||||
//! - P. Lallemand, L.-S. Luo, *Theory of the lattice Boltzmann method: dispersion, dissipation,
|
||||
//! isotropy, Galilean invariance, and stability*, PRE 61:6546, 2000 (stability limits).
|
||||
//! - H. Edelsbrunner, E. P. Mücke, *Simulation of Simplicity*, ACM TOG 9(1):66–104, 1990;
|
||||
//! J. R. Shewchuk 1997 (exact predicates, through `modelcraft_mesh::predicates`).
|
||||
//! J. R. Shewchuk 1997 (exact predicates, through `fieldcraft_mesh::predicates`).
|
||||
//!
|
||||
//! No code of any lattice Boltzmann package was read; everything is written from these papers and
|
||||
//! the book.
|
||||
//!
|
||||
//! # Determinism
|
||||
//! Double precision and fixed loop orders. Collision and streaming run on threads by fixed blocks
|
||||
//! of cells ([`modelcraft_parallel`]), each cell's update independent of the others; the wall
|
||||
//! of cells ([`fieldcraft_parallel`]), each cell's update independent of the others; the wall
|
||||
//! forces and every other sum run in a fixed order on one thread. The same model gives the same
|
||||
//! result bit for bit on any number of threads and on every platform, wasm included.
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
@@ -71,9 +71,9 @@ pub enum Error {
|
||||
#[error("unstable: {0}")]
|
||||
Unstable(String),
|
||||
#[error(transparent)]
|
||||
Model(#[from] modelcraft_model::Error),
|
||||
Model(#[from] fieldcraft_model::Error),
|
||||
#[error(transparent)]
|
||||
Mesh(#[from] modelcraft_mesh::Error),
|
||||
Mesh(#[from] fieldcraft_mesh::Error),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
//! While running, a lattice speed above [`MAX_LATTICE_SPEED`] or a non-finite or non-positive
|
||||
//! density stops the run with [`crate::Error::Unstable`].
|
||||
|
||||
use modelcraft_mesh::surface::BoundarySurface;
|
||||
use modelcraft_model::{BoxFace, FaceCondition, FluidDomain, Model, Procedure, SurfaceCondition};
|
||||
use fieldcraft_mesh::surface::BoundarySurface;
|
||||
use fieldcraft_model::{BoxFace, FaceCondition, FluidDomain, Model, Procedure, SurfaceCondition};
|
||||
|
||||
use crate::voxel::Grid;
|
||||
use crate::{Error, Limits, Result};
|
||||
@@ -101,7 +101,7 @@ fn norm(v: [f64; 3]) -> f64 {
|
||||
}
|
||||
|
||||
/// The fluid step named `step` (or the only fluid step when `step` is `None`) and its domain.
|
||||
pub fn fluid_step<'m>(model: &'m Model, step: Option<&str>) -> Result<(&'m modelcraft_model::Step, &'m FluidDomain)> {
|
||||
pub fn fluid_step<'m>(model: &'m Model, step: Option<&str>) -> Result<(&'m fieldcraft_model::Step, &'m FluidDomain)> {
|
||||
let s = model.select_step(step, |p| p.fluid_domain().is_some(), "fluid")?;
|
||||
let name = s.procedure.fluid_domain().unwrap_or_default();
|
||||
let domain = model.fluid_domain(name).ok_or_else(|| Error::NotFound(format!("fluid domain `{name}`")))?;
|
||||
@@ -258,7 +258,7 @@ impl Setup {
|
||||
for sb in domain.surfaces.iter().filter(|sb| &sb.face.body == body) {
|
||||
let mut hit = false;
|
||||
for (tag, name) in names.iter().enumerate() {
|
||||
if sb.face.selects(&modelcraft_model::GeometryRef::face(body.as_str(), name.as_str())?) {
|
||||
if sb.face.selects(&fieldcraft_model::GeometryRef::face(body.as_str(), name.as_str())?) {
|
||||
hit = true;
|
||||
if let (Some(slot), SurfaceCondition::MovingWall { velocity }) = (velocities.get_mut(tag), sb.condition) {
|
||||
*slot = velocity.map(|c| c * dt / h);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Running a fluid step: the time loop, output frames and force histories, in model units.
|
||||
|
||||
use modelcraft_model::Model;
|
||||
use fieldcraft_model::Model;
|
||||
|
||||
use crate::flow::Flow;
|
||||
use crate::setup::{Obstacle, Setup};
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
//! lower triangle index, so the assignment is deterministic. This is a classification for
|
||||
//! reporting, not a meshing decision, so floating-point distances are adequate.
|
||||
|
||||
use modelcraft_mesh::predicates::{Point2, Point3, Sign, orient2d, orient3d, snap_to_domain};
|
||||
use modelcraft_mesh::surface::BoundarySurface;
|
||||
use fieldcraft_mesh::predicates::{Point2, Point3, Sign, orient2d, orient3d, snap_to_domain};
|
||||
use fieldcraft_mesh::surface::BoundarySurface;
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
@@ -373,7 +373,7 @@ impl TriangleTree {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use modelcraft_mesh::surface::SurfaceOptions;
|
||||
use fieldcraft_mesh::surface::SurfaceOptions;
|
||||
|
||||
/// The surface of the box [lo, hi], outward, two triangles per side, side k tagged k.
|
||||
pub(crate) fn cube(lo: [f64; 3], hi: [f64; 3]) -> BoundarySurface {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
//! Benchmark suite: comparisons with published numerical reference values (not analytic; the
|
||||
//! analytic suite in `verification.rs` is the gate). Each case names its source. The cases are
|
||||
//! long, so they are ignored by default:
|
||||
//! `cargo test --release -p modelcraft-lbm --test benchmark -- --ignored --nocapture`.
|
||||
//! `cargo test --release -p fieldcraft-lbm --test benchmark -- --ignored --nocapture`.
|
||||
|
||||
mod common;
|
||||
|
||||
use common::*;
|
||||
use modelcraft_lbm::{Limits, solve_fluid};
|
||||
use modelcraft_model::{FaceCondition, Procedure, Profile};
|
||||
use fieldcraft_lbm::{Limits, solve_fluid};
|
||||
use fieldcraft_model::{FaceCondition, Procedure, Profile};
|
||||
|
||||
/// Benchmark "2D-1" (steady flow around a cylinder at Re = 20): M. Schäfer, S. Turek, *Benchmark
|
||||
/// computations of laminar flow around a cylinder*, in: Flow Simulation with High-Performance
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use modelcraft_lbm::{Flow, Limits, Obstacle, Setup};
|
||||
use modelcraft_mesh::surface::{BoundarySurface, SurfaceOptions};
|
||||
use modelcraft_model::{BoxFaces, Fluid, FluidDomain, Material, Model, Procedure, Step};
|
||||
use fieldcraft_lbm::{Flow, Limits, Obstacle, Setup};
|
||||
use fieldcraft_mesh::surface::{BoundarySurface, SurfaceOptions};
|
||||
use fieldcraft_model::{BoxFaces, Fluid, FluidDomain, Material, Model, Procedure, Step};
|
||||
|
||||
/// A domain over [min, max] with walls on every face.
|
||||
pub fn domain(min: [f64; 3], max: [f64; 3], spacing: f64) -> FluidDomain {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//! Throughput of the solver (ignored; run with
|
||||
//! `cargo test --release -p modelcraft-lbm --test throughput -- --ignored --nocapture`).
|
||||
//! `cargo test --release -p fieldcraft-lbm --test throughput -- --ignored --nocapture`).
|
||||
|
||||
mod common;
|
||||
|
||||
use common::*;
|
||||
use modelcraft_model::{BoxFace, FaceCondition};
|
||||
use fieldcraft_model::{BoxFace, FaceCondition};
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
@@ -26,7 +26,7 @@ fn cell_updates_per_second() {
|
||||
1.0,
|
||||
1.0 / 6.0,
|
||||
d,
|
||||
modelcraft_model::Procedure::Fluid {
|
||||
fieldcraft_model::Procedure::Fluid {
|
||||
domain: "Flow".into(),
|
||||
end_time: None,
|
||||
steps: Some(steps),
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
//! of a periodic array of spheres (Hasimoto 1959), inlet/outlet channel flow, mass conservation
|
||||
//! to round-off, and the stability limits.
|
||||
//!
|
||||
//! Each test prints its errors and measured orders (`cargo test -p modelcraft-lbm -- --nocapture`).
|
||||
//! Each test prints its errors and measured orders (`cargo test -p fieldcraft-lbm -- --nocapture`).
|
||||
|
||||
mod common;
|
||||
|
||||
use common::*;
|
||||
use modelcraft_lbm::{Error, Limits, Setup, solve_fluid};
|
||||
use modelcraft_model::{FaceCondition, Profile};
|
||||
use fieldcraft_lbm::{Error, Limits, Setup, solve_fluid};
|
||||
use fieldcraft_model::{FaceCondition, Profile};
|
||||
|
||||
const PERIODIC: FaceCondition = FaceCondition::Periodic {};
|
||||
|
||||
@@ -100,7 +100,7 @@ fn taylor_green(n: usize) -> (f64, f64) {
|
||||
let (nu, u0, l) = (0.1, 0.1, 2.0 * std::f64::consts::PI);
|
||||
let dx = l / n as f64;
|
||||
let mut d = domain([0.0; 3], [l, l, dx], dx);
|
||||
for f in modelcraft_model::BoxFace::ALL {
|
||||
for f in fieldcraft_model::BoxFace::ALL {
|
||||
*d.faces.get_mut(f) = PERIODIC;
|
||||
}
|
||||
// τ = 0.8: Δt = 0.3 Δx² / (3 ν).
|
||||
@@ -222,7 +222,7 @@ fn sphere_drag(r: f64, l: usize, steps: u64) -> (f64, f64) {
|
||||
let (nu, a) = (5.0 / 6.0, 1e-6);
|
||||
let side = l as f64;
|
||||
let mut d = domain([0.0; 3], [side; 3], 1.0);
|
||||
for f in modelcraft_model::BoxFace::ALL {
|
||||
for f in fieldcraft_model::BoxFace::ALL {
|
||||
*d.faces.get_mut(f) = PERIODIC;
|
||||
}
|
||||
d.acceleration = [a, 0.0, 0.0];
|
||||
@@ -232,7 +232,7 @@ fn sphere_drag(r: f64, l: usize, steps: u64) -> (f64, f64) {
|
||||
1.0,
|
||||
nu,
|
||||
d,
|
||||
modelcraft_model::Procedure::Fluid {
|
||||
fieldcraft_model::Procedure::Fluid {
|
||||
domain: "Flow".into(),
|
||||
end_time: None,
|
||||
steps: Some(steps),
|
||||
@@ -287,7 +287,7 @@ fn channel_with_a_parabolic_inlet_and_a_pressure_outlet_develops_poiseuille_flow
|
||||
// τ = 0.6. The pressure drop changes the density along the channel by Δp / (ρ c_s²) in lattice
|
||||
// units (the weakly compressible error), here 0.07%; the automatic time step would give 1.6%.
|
||||
let dt = 0.1 / 3.0 * dx * dx / nu;
|
||||
let procedure = modelcraft_model::Procedure::Fluid {
|
||||
let procedure = fieldcraft_model::Procedure::Fluid {
|
||||
domain: "Flow".into(),
|
||||
end_time: Some(4.0 * h * h / nu),
|
||||
steps: None,
|
||||
@@ -372,7 +372,7 @@ fn results_are_bit_for_bit_reproducible() {
|
||||
1.0,
|
||||
0.01,
|
||||
d,
|
||||
modelcraft_model::Procedure::Fluid { domain: "Flow".into(), end_time: Some(1.0), steps: None, time_step: None, frames: 3, magic: None },
|
||||
fieldcraft_model::Procedure::Fluid { domain: "Flow".into(), end_time: Some(1.0), steps: None, time_step: None, frames: 3, magic: None },
|
||||
);
|
||||
let a = solve_fluid(&m, None, std::slice::from_ref(&ball), &Limits::default()).unwrap();
|
||||
let b = solve_fluid(&m, None, std::slice::from_ref(&ball), &Limits::default()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user