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:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-13 23:51:40 -04:00
1 parent 9bc4e1b182
commit d5bd74570f
268 files changed
+1666 -1666

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@
//! Every element is checked with the certified Jacobian test ([`crate::quality`]); a block
//! whose corners are not in hex8 order or whose curves fold it is an error.
use modelcraft_model::{ElementKind, MAX_COORD};
use fieldcraft_model::{ElementKind, MAX_COORD};
use crate::quad::{lattice_index, transfinite_faces, transfinite_grid_blended, transfinite_volume};
use crate::quality::{Validity, element_validity, planar_quad_validity};
+1 -1
View File
@@ -54,7 +54,7 @@ mod tests;
use std::collections::HashMap;
use modelcraft_model::ElementKind;
use fieldcraft_model::ElementKind;
use crate::delaunay::Triangulation;
use crate::predicates::{GenericPoint, Point3, Sign};
+1 -1
View File
@@ -1,4 +1,4 @@
use modelcraft_model::ElementKind;
use fieldcraft_model::ElementKind;
use super::*;
use crate::quality::{GateOptions, enclosed_volume, validity_gate_elements};
+3 -3
View File
@@ -54,7 +54,7 @@ use crate::size::SizeField;
use crate::surface::BoundarySurface;
use crate::vec3::{P, cross, dot, sub};
use crate::{Error, Result};
use modelcraft_model::ElementKind;
use fieldcraft_model::ElementKind;
/// Which structured method to use.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -323,7 +323,7 @@ fn finish(ctx: &Ctx, raw: Raw, method: HexMethod) -> Result<HexMesh> {
if hexes.len() > ctx.opts.max_elements {
return Err(Error::Limit(format!("the mesh has {} hexahedra; the limit is {}", hexes.len(), ctx.opts.max_elements)));
}
modelcraft_model::check_coordinates(nodes.as_flattened())?;
fieldcraft_model::check_coordinates(nodes.as_flattened())?;
let at = |nodes: &[P], i: u32| nodes.get(i as usize).copied().ok_or_else(|| Error::Failed(format!("node {i} out of range")));
// Boundary faces: hex faces used once.
let mut uses: HashMap<[u32; 4], u32> = HashMap::with_capacity(hexes.len() * 3);
@@ -548,6 +548,6 @@ fn mid_edge_nodes(ctx: &Ctx, nodes: &mut Vec<P>, hexes: &[[u32; 8]], boundary: &
}
out.push(m);
}
modelcraft_model::check_coordinates(nodes.as_flattened())?;
fieldcraft_model::check_coordinates(nodes.as_flattened())?;
Ok(out)
}
+1 -1
View File
@@ -5,7 +5,7 @@
use std::collections::{BTreeMap, BTreeSet, HashMap};
use modelcraft_model::{ElementKind, Model};
use fieldcraft_model::{ElementKind, Model};
use crate::vec3::{P, dot, sub};
use crate::{Error, Result};
+1 -1
View File
@@ -35,7 +35,7 @@ pub enum Error {
#[error("invalid boundary surface: {0}")]
Surface(surface::Defects),
#[error(transparent)]
Model(#[from] modelcraft_model::Error),
Model(#[from] fieldcraft_model::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -14,7 +14,7 @@
use std::collections::BTreeMap;
use modelcraft_model::ElementKind;
use fieldcraft_model::ElementKind;
use crate::quad::{QuadOptions, free_quad_mesh, free_tri_mesh};
use crate::size::{UniformSize, divide_polyline, edge_divisions, even_divisions, ideal_divisions};
+1 -1
View File
@@ -3,7 +3,7 @@
//! Each function returns `(x, y)` with `x = fl(a ∘ b)` and `y` the exact roundoff, so that
//! `a ∘ b = x + y` exactly. They assume IEEE 754 binary64 with round-to-nearest-even, no
//! intermediate extended precision and no fused multiply-add contraction; that is what Rust's
//! `f64` guarantees on every target ModelCraft builds for (x86_64 with SSE2, aarch64, wasm32):
//! `f64` guarantees on every target FieldCraft builds for (x86_64 with SSE2, aarch64, wasm32):
//! rustc never contracts `a * b + c` into an FMA and does not use x87. No overflow or underflow
//! may occur, which the coordinate domain of [`super::Point2`] / [`super::Point3`] guarantees.
+1 -1
View File
@@ -75,7 +75,7 @@ pub(crate) const CLEARANCE: f64 = 0.3;
/// model's coordinate range.
fn steiner_point(c: [f64; 2]) -> Option<Point2> {
let c = [snap_to_domain(c[0]), snap_to_domain(c[1])];
if !(c[0].abs() <= modelcraft_model::MAX_COORD && c[1].abs() <= modelcraft_model::MAX_COORD) {
if !(c[0].abs() <= fieldcraft_model::MAX_COORD && c[1].abs() <= fieldcraft_model::MAX_COORD) {
return None;
}
Point2::new(c[0], c[1]).ok()
+1 -1
View File
@@ -39,7 +39,7 @@ pub(crate) fn bbox(pts: impl IntoIterator<Item = [f64; 2]>) -> ([f64; 2], [f64;
/// Admissible exact-predicate point from user coordinates (finite, within the model limit; tiny
/// magnitudes rounded to zero).
pub(crate) fn admissible(c: [f64; 2]) -> Result<[f64; 2]> {
modelcraft_model::check_coordinates(&c)?;
fieldcraft_model::check_coordinates(&c)?;
Ok([snap_to_domain(c[0]), snap_to_domain(c[1])])
}
+1 -1
View File
@@ -22,7 +22,7 @@ pub(crate) fn mesh(loops: &[Vec<[f64; 2]>], size: &dyn SizeField, opts: &QuadOpt
if l.len() % 2 == 1 {
return Err(Error::Invalid(format!(
"loop {k} has an odd number ({}) of boundary points; an all-quadrilateral mesh needs an even number on every loop \
(choose the edge divisions with modelcraft_mesh::size::loop_divisions or even_divisions)",
(choose the edge divisions with fieldcraft_mesh::size::loop_divisions or even_divisions)",
l.len()
)));
}
+1 -1
View File
@@ -511,7 +511,7 @@ fn planar_quad_metrics() {
}
#[test]
#[ignore = "timing and quality report: cargo test --release -p modelcraft-mesh quad_report -- --ignored --nocapture"]
#[ignore = "timing and quality report: cargo test --release -p fieldcraft-mesh quad_report -- --ignored --nocapture"]
fn quad_report() {
let cases: Vec<(&str, Vec<Vec<[f64; 2]>>, f64)> = vec![
("rectangle", vec![rect(0.0, 0.0, 10.0, 5.0, 20, 10)], 0.5),
+1 -1
View File
@@ -85,7 +85,7 @@ fn grid<const D: usize>(
let count = (nu + 1).checked_mul(nv + 1).filter(|&c| c <= MAX_GRID_NODES);
let count = count.ok_or_else(|| Error::Limit(format!("a {nu} × {nv} grid exceeds {MAX_GRID_NODES} nodes")))?;
for side in [bottom, right, top, left] {
modelcraft_model::check_coordinates(side.as_flattened())?;
fieldcraft_model::check_coordinates(side.as_flattened())?;
}
let corner = |s: &[[f64; D]], last: bool| if last { s.last().copied() } else { s.first().copied() };
let (p00, p10, p01, p11) = match (corner(bottom, false), corner(bottom, true), corner(top, false), corner(top, true)) {
+2 -2
View File
@@ -1,7 +1,7 @@
//! The Jacobian determinant of a solid element as an exact polynomial, its certified sign and
//! the element's exact volume.
//!
//! The geometry map of every solid element ModelCraft knows is a polynomial on its reference
//! The geometry map of every solid element FieldCraft knows is a polynomial on its reference
//! domain, so its Jacobian determinant is one too: constant for tet4, cubic for tet10, degree
//! (2, 2) on triangle × segment for wedge6, degree (2, 2, 2) for hex8 and (5, 5, 5) for hex20. It
//! is built here in Bernstein form ([`super::bernstein`]) and its sign is settled by bounds and
@@ -22,7 +22,7 @@
//! - hex8/hex20: face 1-2-3-4, then 5-6-7-8 above it; mid-side nodes 9–12 on the edges of 1-2-3-4,
//! 13–16 on those of 5-6-7-8, 17–20 on edges 1-5, 2-6, 3-7, 4-8.
use modelcraft_model::ElementKind;
use fieldcraft_model::ElementKind;
use super::bernstein::{Bernstein, Factor};
use crate::{Error, Result};
+2 -2
View File
@@ -11,7 +11,7 @@
//! - Hexahedron, wedge and quadrilateral shape: Knupp, *Algebraic mesh quality metrics*, SIAM J.
//! Sci. Comput. 23(1):193–218, 2001.
//!
//! Inputs are hostile: coordinates must be finite and within [`modelcraft_model::MAX_COORD`],
//! Inputs are hostile: coordinates must be finite and within [`fieldcraft_model::MAX_COORD`],
//! and every metric has a defined value on degenerate and inverted elements.
//!
//! Linear tetrahedra take their validity from the exact `orient3d` ([`crate::predicates`]); the
@@ -23,7 +23,7 @@ pub mod jacobian;
mod report;
pub(crate) mod shape;
use modelcraft_model::{ElementKind, check_coordinates};
use fieldcraft_model::{ElementKind, check_coordinates};
pub use jacobian::{JacobianCheck, Validity};
pub use report::{
+3 -3
View File
@@ -2,7 +2,7 @@
use std::collections::{BTreeMap, BTreeSet};
use modelcraft_model::{Element, ElementKind, Model, check_coordinates};
use fieldcraft_model::{Element, ElementKind, Model, check_coordinates};
use super::{ElementQuality, JacobianCheck, Metric, Validity, element_quality, element_validity, is_measured};
use crate::{Error, Result};
@@ -49,7 +49,7 @@ fn coordinates(model: &Model, label: u32, element: &Element) -> Result<Vec<[f64;
.nodes
.iter()
.map(|n| {
model.node(*n).map(|node| node.xyz).ok_or_else(|| Error::Model(modelcraft_model::Error::NotFound(format!("element {label}: node {n}"))))
model.node(*n).map(|node| node.xyz).ok_or_else(|| Error::Model(fieldcraft_model::Error::NotFound(format!("element {label}: node {n}"))))
})
.collect()
}
@@ -62,7 +62,7 @@ fn selection<'a>(model: &'a Model, labels: Option<&[u32]>) -> Result<Vec<(u32, &
.iter()
.collect::<BTreeSet<_>>()
.into_iter()
.map(|l| model.element(*l).map(|e| (*l, e)).ok_or_else(|| Error::Model(modelcraft_model::Error::NotFound(format!("element {l}")))))
.map(|l| model.element(*l).map(|e| (*l, e)).ok_or_else(|| Error::Model(fieldcraft_model::Error::NotFound(format!("element {l}")))))
.collect(),
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
//! Analytic tests: every expected value is closed-form.
use modelcraft_model::{ElementKind, Model};
use fieldcraft_model::{ElementKind, Model};
use super::*;
+1 -1
View File
@@ -68,7 +68,7 @@ fn check_polyline(polyline: &[[f64; 3]]) -> Result<()> {
if polyline.len() > MAX_POLYLINE_POINTS {
return Err(Error::Limit(format!("polyline has {} points; the limit is {MAX_POLYLINE_POINTS}", polyline.len())));
}
modelcraft_model::check_coordinates(polyline.as_flattened())?;
fieldcraft_model::check_coordinates(polyline.as_flattened())?;
Ok(())
}
+3 -3
View File
@@ -4,7 +4,7 @@
//! tagged 3MF) into one that every volume mesher can rely on, or fails with the list of
//! [`Defect`]s, each located by input triangle or vertex index and a position:
//!
//! 1. **Coordinates and indices** are checked: finite, within [`modelcraft_model::MAX_COORD`],
//! 1. **Coordinates and indices** are checked: finite, within [`fieldcraft_model::MAX_COORD`],
//! in range.
//! 2. **Weld.** Vertices closer than a distance (relative to the bounding-box diagonal, or
//! absolute: [`SurfaceOptions`]) become one, in input order (the earliest vertex of a cluster
@@ -53,7 +53,7 @@ mod tests;
use std::fmt;
use modelcraft_model::{MAX_COORD, MAX_ELEMENTS, MAX_NODES};
use fieldcraft_model::{MAX_COORD, MAX_ELEMENTS, MAX_NODES};
use crate::predicates::Point3;
use crate::vec3::{cross, norm, sub};
@@ -83,7 +83,7 @@ pub struct SurfaceOptions {
pub weld_tolerance: f64,
/// Absolute weld distance in model units, at least 0 (the combined distance may be at most
/// [`MAX_RELATIVE_WELD`] of the bounding-box diagonal). A tessellation carries its own
/// (`modelcraft_geometry::SurfaceMesh::weld_distance`).
/// (`fieldcraft_geometry::SurfaceMesh::weld_distance`).
pub weld_distance: f64,
/// An edge inside one B-rep face is a feature when the normals of its two triangles differ
/// by more than this angle, in degrees, in `(0, 180]` (180: face boundaries only).