Structural & construction materials
Adhesive bond strength and cure kinetics, fiber-composite mechanics, concrete mix design and curing, ceramic fracture statistics, polymer chain/molecular-weight science, and rubber/elastomer testing,
Six small, independent modules for the arithmetic behind materials selection and testing in construction and manufacturing: how much adhesive a bonded joint needs and how long it takes to cure, how a fiber and a matrix combine into a composite's stiffness, how a concrete mix's water-cement ratio drives its strength and shrinkage, how a ceramic's measured strength translates into a failure probability at a different stress, how a polymer's molecular weight and chain statistics are computed from raw synthesis numbers, and how a rubber compound's hardness, set, and aging are quantified. Every function takes plain scalars — no shared struct, no cross-module imports — and returns a single Float64.
from algenta import MojoRuntime
runtime = MojoRuntime(mode="local")
runtime.execute("concrete", "water_cement_ratio", [175.0, 350.0])["result"]
# 0.5 — 175 kg water over 350 kg cement, a mid-range structural mix
runtime.execute("concrete", "modulus_of_elasticity", [32.0])["result"]
# 26587.214972614187 — ACI Ec = 4700 * sqrt(fc), fc = 32 MPaThe modules
adhesives
Lap-shear and peel strength, bond-area sizing, coverage rate, temperature-adjusted pot life and cure time, Arrhenius viscosity, contact-angle surface energy, and a simplified thermal-cycle-life estimate
composites
Rule-of-mixtures and Halpin-Tsai modulus, composite density, fiber volume fraction, laminate thickness, specific stiffness/strength, critical fiber length, shear-lag stress transfer, Charpy impact energy, and void content
concrete
Water-cement ratio, Abrams'-law compressive strength, mix-volume accounting, slump and Nurse-Saul maturity estimates, ACI modulus of elasticity and splitting tensile strength, drying shrinkage, carbonation depth, and rebar development length
ceramics
Weibull failure probability and characteristic strength, thermal shock resistance, porosity effects on modulus, sintering shrinkage, Archimedes/relative density, indentation fracture toughness, dielectric mixing, CTE, and a Kauzmann glass-transition estimate
polymer
Molecular-weight averages (Mn, Mw, PDI), degree of polymerization, Mark-Houwink intrinsic viscosity, Fox-equation blend Tg, Flory-Huggins mixing free energy, freely-jointed-chain end-to-end distance and radius of gyration, Carothers conversion, and melt-flow-index approximation
rubber
Shore A to Young's modulus, Mooney viscosity, tensile/compression set, elongation at break, tear strength, rebound resilience, aging hardness change, swelling, crosslink density, abrasion loss, and hysteresis heat buildup
Adhesives: bonding is sized by load, not just glued by feel
bond_area_from_load inverts the lap-shear formula to answer the design question directly — given a load and a safety factor, how much bonded area does the joint need:
Temperature enters two of the module's functions through algebraically the same Q10-style rate law, just written two different ways. cure_time_temperature divides by acceleration^((temp - ref_temp)/10); pot_life_temperature_adjusted multiplies by factor^((ref_temp - temp)/10) — dividing by x^y and multiplying by x^(-y) are the same operation, and (temp - ref_temp) is -(ref_temp - temp), so the two formulas are identical in shape with the sign folded into which side of the ratio is on top. Both quantities shrink as temperature rises above the reference — heat speeds up cure and shortens working time together, which is physically the same phenomenon (faster reaction kinetics) showing up in both numbers:
viscosity_temperature is a real Arrhenius model, eta = eta_ref * exp(Ea/R * (1/T - 1/T_ref)), using absolute temperature in kelvin rather than the /10 empirical shortcut the other two functions use:
Composites: the same fiber and matrix give two different moduli
rule_of_mixtures_modulus (Voigt, loading parallel to the fibers) and inverse_rule_of_mixtures (Reuss, loading transverse to them) take identical inputs and diverge sharply, because a fiber-reinforced composite is genuinely anisotropic — it is not one modulus, it is two:
halpin_tsai is a third, semi-empirical model for the same transverse direction, tunable through a reinforcement-geometry factor xi (2.0 is the textbook value for circular fibers) rather than the Reuss bound's implicit assumption of perfectly uniform stress:
The gap between 8.55 GPa and 17.61 GPa is not a bug in either function — Reuss is a lower-bound approximation that assumes equal stress in fiber and matrix, and Halpin-Tsai's xi corrects for the fact that real transverse loading does not actually split stress that way. Composite density and specific stiffness follow directly from the same Vf:
Concrete: one ratio drives strength, slump, and shrinkage together
Water-cement ratio is the input every strength and workability function in this module keys off:
compressive_strength_abrams takes a and b as caller-supplied coefficients rather than hardcoding a single calibration — the module's own docstring lists no default values, so the constants above (a = 96.5, b = 3.4) are representative of a normal-strength mix, not a fixed constant the kernel assumes; a real mix design calibrates a/b against trial batches first. Once a strength is known, the module's other functions derive stiffness and durability from it:
slump_estimate and maturity_nurse_saul both clamp: slump never goes negative (returns 0.0 below wc = 0.3 rather than a negative slump), and maturity returns 0.0 rather than a negative value when the curing temperature is below the datum temperature — a batch curing below freezing (with a typical -10C datum) is reported as gaining zero maturity, not negative maturity.
Ceramics: the same mean strength implies different failure odds at different stresses
weibull_failure_probability is the module's central function — brittle ceramics fail statistically because of pre-existing flaws, not at one fixed stress, and the Weibull modulus m controls how sharply the failure probability rises once stress passes the characteristic strength:
The stress == sigma0 case always returns 1 - exp(-1) = 0.6321205588285577 regardless of m — that is the definition of the characteristic strength, not a coincidence of the numbers chosen above. Porosity's effect on stiffness is a separate exponential decay, not tied to the Weibull statistics:
thermal_shock_resistance folds strength, stiffness, expansion, and Poisson's ratio into a single number in kelvin — the higher it is, the larger a sudden temperature change the material can survive without cracking:
weibull_characteristic_strength is explicitly the simplified case: its docstring and body both say the 1.1x mean-to-characteristic conversion factor is calibrated for m ~ 10, and the function does not actually use its own m argument in the computation — it is accepted for interface symmetry with the rest of the module, not read.
Polymer: molecular weight, chain size, and conversion from the same handful of ratios
degree_of_polymerization, number_average_mw, and weight_average_mw chain together the way a real characterization workflow does — monomer molecular weight and Mn in, PDI out, Mw derived:
glass_transition_fox blends two homopolymer Tg values by weight fraction — note the inputs are absolute kelvin, and the blend's Tg sits between the two components, closer to whichever has the larger weight fraction:
end_to_end_distance and radius_of_gyration model an ideal freely-jointed chain — radius_of_gyration takes the result of end_to_end_distance as its own input, not the raw bond count, so the two calls chain together:
Rubber: hardness, set, and swelling are all normalized-difference ratios
shore_a_to_youngs_modulus is a single empirical exponential — E = 0.5 * exp(0.04 * shore_a) — and the curve is genuinely steep: going from a soft 40 Shore A compound to a hard 90 pushes the estimated modulus up by a factor of roughly 7.4, not the roughly 2x a linear reading of the 40-90 scale would suggest:
tensile_set, compression_set, and elongation_at_break are all the same shape — a change in length or thickness normalized against a reference span — but each module's docstring specifies a different reference span, so the three are not interchangeable formulas with renamed arguments:
crosslink_density_estimate is the one function in this family that reaches for the ideal-rubber elasticity relation directly, nu = E / (3*R*T), so its inputs are in SI base units (pascals, kelvin) rather than the MPa/mm units the rest of the module favors:
Zero-denominator handling is not consistent across the family
These six modules do not share a common guard convention, and the difference is a real behavioral gap rather than a stylistic one:
adhesiveshas no guards at all. Every one of its twelve functions is a direct arithmetic expression —lap_shear_strength(5000.0, 0.0)divides by a zero bond area and returnsinf,bond_area_from_loadwith a zeroallowable_stressdoes the same, and nothing in the module catches it before returning.ceramicsguards every division with an epsilon tolerance,fabs(denominator) < 1e-30, returning0.0rather than dividing — this catches an exact zero and anything close enough to round to it, but a legitimately tiny nonzero denominator (say1e-25) still passes through and can produce a very large but finite result rather thaninf.concretemixes the same epsilon pattern with plain<= 0.0checks in the same file —water_cement_ratioandcement_contentusefabs(x) < 1e-30, whilemodulus_of_elasticity,splitting_tensile_strength,carbonation_depth, andrebar_development_lengthusefc_mpa <= 0.0/time_years <= 0.0/fc <= 0.0instead — stricter in one direction (a small positivefcis accepted where an epsilon guard would too) but with no epsilon band at all.compositesguards with a plain<= 0.0check on densities, moduli, and areas — this is stricter than the epsilon versions (a small positive value is not zero and is accepted) but also refuses legitimate zero-and-below inputs uniformly by returning0.0, folding "invalid input" and "mathematically undefined" into the same sentinel.polymerandrubbermix exact== 0.0checks with<= 0.0checks in the same module, not an epsilon band anywhere.polymer'sdegree_of_polymerization(m0 == 0.0),polydispersity_index(mn == 0.0), andglass_transition_fox(tg1 == 0.0/tg2 == 0.0/inv_tg == 0.0) all only catch a denominator that is exactly zero in floating point — a value like1e-300that is effectively zero for any physical purpose still divides through and returns a finite-looking but meaningless huge number instead of the0.0sentinel the exact-zero path would have produced.polymer's ownmark_houwinkandend_to_end_distance, right next to those, guard with<= 0.0instead.weight_average_mw(a plain multiply,mn * pdi) has no guard at all, but also has no division to protect.rubber'stensile_setandcompression_setfollow the exact== 0.0pattern on their length-difference denominators, while itselongation_at_break,tear_strength,resilience_rebound,swelling_percentage, andabrasion_loss_volumeuse<= 0.0, matchingcomposites' stricter convention within the same module.
None of this is documented as a deliberate design choice in the source — it reads as each module having been written independently against the same "return 0.0 instead of a garbage value" intent, with the exact threshold left to whichever guard the author reached for.
Verification
All six mojo/tests/libs/test_{adhesives,composites,concrete,ceramics,polymer,rubber}.mojo files are auto-generated coverage smoke tests: each calls every function once with a shared fixture (most arguments fixed at 0.5) and checks only that the result is finite, never pinning a specific numeric output. None of the worked examples above come from those files — every number was hand-computed independently in Python against the real formulas in mojo/engine/adhesives.mojo, composites.mojo, concrete.mojo, ceramics.mojo, polymer.mojo, and rubber.mojo, then cross-checked against the physical relationships each formula is named for (the Weibull 1 - exp(-1) identity at stress == sigma0, the Voigt/Reuss bounds bracketing Halpin-Tsai, the Arrhenius direction of viscosity with temperature) before being presented here. Every number given can be reproduced by re-running the same arithmetic against the source.
Next: see metallurgical strengthening and hardenability in Corrosion and electrochemical materials kernels, or browse the Runtime library catalog for every module and function.
Last updated
Was this helpful?