surface_builder

Configuration & data classes

class biochar.surface_builder.SurfaceConfig(target_num_carbons=50, H_C_ratio=0.3, O_C_ratio=0.05, functional_groups=None, aromaticity_percent=95.0, pore_type='slit', num_sheets=2, pore_diameter=10.0, max_attempts=500, amorphous_fallback=None, min_separation=3.0, sheet_overrides=None, box_padding_xy=1.0, box_padding_z=1.0, system_name='SLIT', sheet_base_name='SHT', seed=None, pH=None, defect_fraction=0.0, strict=True)[source]

Bases: object

Configuration for SurfaceBuilder.

Parameters:
  • target_num_carbons (int)

  • H_C_ratio (float)

  • O_C_ratio (float)

  • functional_groups (Dict[str, int] | None)

  • aromaticity_percent (float)

  • pore_type (str)

  • num_sheets (int)

  • pore_diameter (float)

  • max_attempts (int)

  • amorphous_fallback (str | None)

  • min_separation (float)

  • sheet_overrides (List[Dict] | None)

  • box_padding_xy (float)

  • box_padding_z (float)

  • system_name (str)

  • sheet_base_name (str)

  • seed (int | None)

  • pH (float | None)

  • defect_fraction (float)

  • strict (bool)

target_num_carbons

Carbon atoms per sheet (passed to BiocharGenerator).

H_C_ratio

Target H/C ratio for each sheet.

O_C_ratio

Target O/C ratio (used when functional_groups is None).

functional_groups

Functional groups applied to every sheet, e.g. {"phenolic": 2, "ether": 1}. Overridden per-sheet via sheet_overrides.

aromaticity_percent

Target aromatic carbon fraction (percentage).

pore_type

Pore geometry. "slit" stacks parallel sheets along z; "amorphous" performs random rigid-body placement with steric rejection (each sheet independently rotated/translated).

num_sheets

Number of parallel sheets. Must be ≥ 2.

pore_diameter

Gap between the inner van-der-Waals surfaces of adjacent sheets, in Ångströms. The centre-to-centre sheet separation is pore_diameter + 3.4 Å (slit pore only).

max_attempts

Maximum random placement attempts per sheet for pore_type="amorphous" before raising RuntimeError or triggering amorphous_fallback.

amorphous_fallback

What to do when amorphous packing fails within max_attempts. None (default) re-raises RuntimeError. "slit" emits a warning and falls back to slit-pore geometry.

min_separation

Minimum allowed inter-sheet atom-atom distance (Ångströms) used as the steric-rejection criterion for pore_type="amorphous".

sheet_overrides

Per-sheet configuration overrides. If provided, must be a list of dicts (one per sheet) with keys matching GeneratorConfig fields. If None, all sheets are chemically identical (one .itp with count = num_sheets).

box_padding_xy

Padding added to each side of the bounding box in x and y, in nm.

box_padding_z

Padding added to each side of the bounding box in z, in nm.

system_name

Name written to the [ system ] section of the .top file.

sheet_base_name

Residue name prefix for sheet molecules. Must be ≤ 3 characters so that the full name (prefix + digit) fits within GROMACS’ 5-character residue-name limit.

seed

Random seed passed to each BiocharGenerator.

defect_fraction

Pentagon insertion probability for each sheet (see defect_fraction).

class biochar.surface_builder.SheetResult(mol, coords, composition, atom_types, charges, molecule_name)[source]

Bases: object

Result of generating and positioning a single sheet.

Parameters:
mol

RDKit molecule with 3-D conformer and OPLS-AA types.

coords

Atomic coordinates in Ångströms, shape (N, 3). Updated in-place by SurfaceBuilder.build() to world coordinates (translated along z after flattening).

composition

Atom counts and ratios (CompositionInfo).

atom_types

Mapping of atom index → OPLS-AA type string.

charges

Mapping of atom index → partial charge (electrons).

molecule_name

Residue name used in .gro and .itp files. Identical for all sheets when sheet_overrides is None; indexed (e.g. SHT1, SHT2) for distinct sheets.

Builder

class biochar.surface_builder.SurfaceBuilder(config)[source]

Bases: object

Build slit-pore surface systems from parallel biochar sheets.

The builder orchestrates a three-phase pipeline:

  1. Sheet generation — creates each sheet via BiocharGenerator, assigns OPLS-AA types and charges, then flattens the sheet to the xy plane using SVD.

  2. Positioning — translates sheet i to z = i × (pore_diameter + 3.4 Å) so consecutive sheets are separated by the requested pore gap.

  3. Box computation — wraps all sheets in an orthogonal periodic box padded by SurfaceConfig.box_padding_xy (nm) in x/y and SurfaceConfig.box_padding_z (nm) in z, then centres the system inside the box.

When SurfaceConfig.sheet_overrides is None and SurfaceConfig.pH is None all sheets are chemically identical: only the first sheet is generated; the rest are deep-copied. A single .itp is produced and the .top lists it with count = num_sheets.

Setting pH breaks that identity — protonation is a per-site random draw, so sheets built at the same pH are independent samples, not copies. Each sheet is then generated from its own seed and written to its own .itp.

Use generate_surface() for a one-call convenience wrapper.

Examples:

config = SurfaceConfig(
    target_num_carbons=60,
    functional_groups={"phenolic": 2},
    pore_diameter=12.0,
    num_sheets=2,
    seed=42,
)
builder = SurfaceBuilder(config)
sheets, box_nm = builder.build()
gro, top, itps = builder.export_gromacs("output", "slit_pore")
Parameters:

config (SurfaceConfig)

build()[source]

Generate all sheets and compute their positioned coordinates.

Return type:

Tuple[List[SheetResult], ndarray]

Returns:

(list_of_SheetResult, box_vectors_nm)

Each SheetResult.coords is updated in place to world coordinates (translated along z so sheets are stacked with the requested pore gap).

export_gromacs(output_directory='.', basename='surface')[source]

Export the positioned surface system to GROMACS files.

Return type:

Tuple[Path, Path, List[Path]]

Returns:

(gro_path, top_path, list_of_itp_paths)

Parameters:
  • output_directory (str)

  • basename (str)