User API¶
The user API covers reading the database, choosing and configuring a model, describing the problem and launching the optimizer. For a guided example, see the calibration workflow; for the full per-model parameter bounds see Constitutive models.
A complete calibration uses four objects:
from ACT.utilities.excel import excel # 1. read experimental data
from ACT.models import hypoplasticity_isa # 2. pick a constitutive model
from ACT import globals, DEEM # 3. configure + 4. optimize
1. Read the data with excel¶
Reads an Excel database (one sheet per test) into Python. The reader works by cell position; the required layout is documented on the Excel sheet reference.
Constructor¶
Takes no arguments. Create one instance, then call collect on it.
collect()¶
Reads filename and populates the reader instance in place (it mutates the
object and returns None). After calling it, the parsed tests are available as
list attributes:
| Attribute | Test type (sheet) |
|---|---|
.oedometer |
oedometric compression (OED-#) |
.isotropic_compression_test |
isotropic compression (IC-#) |
.triax_CD |
drained triaxial (CD-#) |
.triax_CU |
undrained triaxial (CU-#) |
.triax_CUcyc |
undrained cyclic triaxial (CUCYC-#) |
.triax_CDcyc_HCA |
drained HCA triaxial (CDCYC_HCA-#) |
.triax_CUcyc_HCA |
undrained HCA triaxial (CUCYC_HCA-#) |
.USScyc |
undrained cyclic simple shear (USScyc-#) |
.DSS |
drained direct simple shear (DSS-#) |
database = excel()
database.collect("database-kfs-monotonic-cyclic.xlsx")
print(len(database.triax_CD)) # how many drained triaxial tests were read
Call it on a variable
collect returns None and stores the data on the instance. Use
db = excel(); db.collect(path), not tests = excel().collect(path).
2. Choose a model¶
Every model is a class with the shared optimiser-facing parameter contract.
Import the class, construct it, and set its initial values. Most classes also
provide set_bounds(...); the base sanisand class uses fixed built-in bounds
and is the documented exception. The complete class list and model-specific
interfaces are under Constitutive models.
Constructor¶
| Argument | Default | Description |
|---|---|---|
out_dir |
"./results/" |
comparison data, plots and lightweight-optimizer histories |
out_dir2 |
"./run_tmp/" |
temporary per-evaluation run files |
out_dir3 |
"./run_final/" |
raw files of the final (best) numgeo run |
The constructor resolves these inputs immediately and stores canonical absolute
paths on the model. Relative inputs are therefore relative to the process
working directory at construction time, not to a later
globals.setup(path=...) value. For an unambiguous layout, derive all three
paths from one resolved working directory as shown in the full example below.
Use dedicated ACT-only directories
Model construction manages and cleans all three directories. In particular,
out_dir2 is recursively reset; direct files and symbolic links in
out_dir are removed; and non-report subdirectories in out_dir3 are
removed. Use three separate, dedicated ACT-only directories. Never point
any of them at a project folder, dataset folder, home directory or another
directory containing files you need to keep. ACT rejects broad roots,
overlapping paths, links and several other unsafe configurations, but it
cannot recognise every mistakenly selected ordinary folder.
Configuring parameters¶
| Method | Purpose |
|---|---|
set(<param>=<value>, ...) |
assign initial / fixed parameter values |
set_bounds(<param>=[lo, hi], ...) |
override individual search intervals where the model implements this convenience method |
update(parameter, value) |
set a single parameter by name |
get_parameter(parameter) |
read a single parameter by name |
model = hypoplasticity_isa() # defaults + default bounds pre-set
model.set(hs=4.0, n=0.27, ed=0.55, ec=0.95) # hs is expressed in GPa
model.set_bounds(n=[0.20, 0.35], ec=[0.85, 1.05]) # narrow some intervals
model.update("alpha", 0.12)
print(model.get_parameter("alpha"))
The per-model set / set_bounds argument names and angle conventions are
model-specific; see each model page. In
particular, do not call set_bounds on the base sanisand class.
Optional: fit critical-state-line parameters¶
The CSL helper is imported from the utilities package:
fit_csl(...) returns a dictionary. The fitted parameters are stored by name, not by position. For the Bauer CSL this means:
result = fit_csl(
model='bauer',
p=[25., 50., 100., 200., 400.],
e=[0.91, 0.88, 0.85, 0.82, 0.79],
result_dir=model.out_dir,
)
params = result['parameters']
ec0 = params['ec0']
hs = params['hs']
n = params['n']
print(result['r2'])
For oedometric compression data, do not pass the vertical stress as p. Pass it as vertical_stress or sigma_v, and provide K0 and void_ratio:
result = fit_csl(
model='bauer',
vertical_stress=[25., 50., 100., 200., 400.],
K0=0.45,
void_ratio=[0.91, 0.88, 0.85, 0.82, 0.79],
result_dir=model.out_dir,
)
ACT then converts the data internally with \(p=\sigma_v(1+2K_0)/3\). If p and e are provided directly, K0 is ignored because ACT assumes that p is already the mean effective stress.
For ACT oedometer sheets with stress-strain data, pass the measured strain and initial void ratio. Several collected ACT oedometer tests can be passed with fit_csl_oedometer_tests(db.oedometer, ...); see the full utility page for the complete example. For a single test, pass arrays directly. For loading-unloading-reloading curves the default evaluation='auto' uses the virgin loading envelope:
result = fit_csl(
model='bauer',
vertical_stress=sigma_v,
K0=K0,
strain=eps_ax,
e_initial=e0,
evaluation='auto',
result_dir=model.out_dir,
)
For Li-Wang CSL parameters, use:
result = fit_csl(model='li-wang', p=p_data, e=e_data, result_dir=model.out_dir)
params = result['parameters']
e0 = params['e0']
lambdac = params['lambdac']
xi = params['xi']
For the full utility reference, including Bolton-generated CSL points and update_model, see Utilities → CSL calibration.
3. Configure the problem with globals.setup¶
setup registers the calibration problem: the model, which parameters are free,
which tests to honour, and the objective settings.
globals.setup(
Model=None, Free_parameter=[],
oedometer=[], triaxCD=[], triaxCU=[], triaxCUcyc=[],
triaxCDcycHCA=[], triaxCUcycHCA=[], USScyc=[], DSS=[], iso_comp=[],
Similarity='frechet', Weights=None,
path=None, Timeout=None, Experimental_database=None,
)
Model & parameters
| Argument | Default | Description |
|---|---|---|
Model |
None |
the constitutive-model instance to calibrate |
Free_parameter |
[] |
list of parameter names to optimize; the rest stay fixed unless the selected model defines a dependency |
Model-dependent parameters
Free_parameter can activate model-specific dependencies. For Hypo-IGS, if mR is listed but mT is not listed, ACT uses the dependent value mT = 0.7*mR during the numgeo back-calculations and in the generated reports. To optimize mT independently, include both mR and mT in Free_parameter.
Tests to honour: pass the matching reader attributes from step 1.
| Argument | Reader attribute | Test |
|---|---|---|
oedometer |
database.oedometer |
oedometric compression |
iso_comp |
database.isotropic_compression_test |
isotropic compression |
triaxCD |
database.triax_CD |
drained triaxial |
triaxCU |
database.triax_CU |
undrained triaxial |
triaxCUcyc |
database.triax_CUcyc |
undrained cyclic triaxial |
triaxCDcycHCA |
database.triax_CDcyc_HCA |
drained HCA |
triaxCUcycHCA |
database.triax_CUcyc_HCA |
undrained HCA |
USScyc |
database.USScyc |
cyclic simple shear |
DSS |
database.DSS |
drained direct simple shear |
Objective & run settings
| Argument | Default | Description |
|---|---|---|
Similarity |
'frechet' |
curve-distance measure (see objective function) |
Weights |
None |
custom weight dictionary; None uses the defaults |
path |
None |
working directory for the calibration |
Timeout |
None |
per-test simulation timeouts (see timeouts) |
Experimental_database |
None |
workbook path/name recorded in the report; ACT can infer it from selected tests |
globals.setup(
Model=model,
Free_parameter=["hs", "n", "ed", "ec", "alpha", "beta"],
oedometer=database.oedometer,
triaxCD=database.triax_CD,
triaxCU=database.triax_CU,
path="./calibration/",
Experimental_database="database-kfs-monotonic-cyclic.xlsx",
)
4. Run an optimiser¶
DEEM global search¶
Runs the global optimization defined by setup. Writes the
outputs (PDF report, log, comparison plots) when finished.
DEEM.optimize(
maxiter=200, n_cpu=1,
nparticles_max=100, nparticles_min=100,
npop_max=4, npop_min=4,
exit_iter=100, tolerance=1e-4,
sampling='LHS', similarity=None,
method='DEEM', termination='tolerance',
)
Budget & parallelism
| Argument | Default | Description |
|---|---|---|
maxiter |
200 |
maximum number of iterations (generations) |
n_cpu |
1 |
parallel workers; set to the number of available cores |
Population
| Argument | Default | Description |
|---|---|---|
nparticles_max |
100 |
maximum population size |
nparticles_min |
100 |
minimum population size (set < max to shrink over time) |
npop_max |
4 |
maximum number of sub-populations |
npop_min |
4 |
minimum number of sub-populations |
Termination & sampling
| Argument | Default | Description |
|---|---|---|
termination |
'tolerance' |
'tolerance' stops early on convergence; 'iterations' runs the full maxiter |
tolerance |
1e-4 |
early-termination tolerance |
exit_iter |
100 |
iterations below the tolerance before stopping |
sampling |
'LHS' |
initial sampling (Latin Hypercube by default) |
similarity |
None |
compatibility argument; omit it, or repeat the value configured by setup exactly |
method |
'DEEM' |
optimizer; 'no_optimization' runs the initial parameters once |
Dry run first
DEEM.optimize(method='no_optimization') simulates every test once with the
initial parameter set without optimization. Use it to confirm the database and
starting values produce sensible results before committing to a full run.
IPOP-CMA-ES¶
from ACT import CMAES
result = CMAES.optimize(
max_evaluations=600,
n_cpu=4,
population_size=None,
initial_step=0.3,
restarts=0,
population_multiplier=2,
exit_iter=None,
tolerance=1e-5,
random_state=0,
)
This bounded CMA-ES implementation is included with ACT and needs no additional
package. It adapts correlated search directions and can increase the population
after stagnation. This makes it a practical choice for rugged continuous soil
calibrations. max_evaluations is a strict budget that includes the current
parameter vector. Restarts only pay off for budgets clearly above about 150
evaluations per free parameter; see the
optimisation page for guidance.
| Argument | Default | Description |
|---|---|---|
max_evaluations |
600 |
strict total objective-evaluation budget |
n_cpu |
1 |
worker processes used to evaluate each population |
population_size |
None |
4 + floor(3*log(n)) for n free parameters |
initial_step |
0.3 |
initial standard deviation as a fraction of every bound range |
restarts |
0 |
maximum increasing-population restarts |
population_multiplier |
2 |
population growth factor per restart |
exit_iter |
None |
evaluations without improvement of the current run's best value before a restart or stop; None selects 10*population_size + 30*n |
tolerance |
1e-5 |
minimum normalised search-distribution width |
random_state |
0 |
random seed |
SMAC-style search¶
from ACT import SMAC
result = SMAC.optimize(
max_evaluations=240,
n_cpu=4,
init_points=None,
exit_iter=80,
tolerance=1e-4,
random_state=0,
surrogate="auto",
n_candidates=4096,
exploration=0.01,
)
max_evaluations is a strict budget including the current parameter vector and
the initial design. Penalised (failed) evaluations are imputed with the worst
successful value before the surrogate is fitted. surrogate="auto" uses scikit-learn Extra Trees if already
installed and otherwise selects the bundled NumPy Gaussian process. Use
surrogate="numpy" for the same backend choice on every computer. SMAC3 is a
compatibility alias for this ACT module, not the external SMAC3 package.
Local pattern search¶
from ACT import local
result = local.optimize(
max_evaluations=100,
n_cpu=4,
initial_step=0.2,
step_decay=0.5,
tolerance=1e-4,
)
This is a bounded, deterministic local refinement. The step and tolerance are fractions of each parameter's bound range. It should start from a suitable parameter set, not replace a global search on a multimodal problem.
All three functions return a CalibrationResult with x, fun, nfev, nit,
success, message, history_x, history_fun, backend, log_file,
report_file, history_file, transcript_file, result_directory and
final_directory. The last two identify the persistent comparison-data/plot
directory and the matching raw final numgeo run. The timestamped PDF, text log
and terminal transcript are written directly under globals.setup(path=...),
not inside result_directory. See
Optimisation for algorithm selection and budget semantics.
Full minimal example¶
from pathlib import Path
from ACT import DEEM, globals
from ACT.models import hypoplasticity_isa
from ACT.utilities.excel import excel
def run_calibration():
database_path = Path("database-kfs-monotonic-cyclic.xlsx").resolve()
workdir = Path("calibration").resolve()
workdir.mkdir(parents=True, exist_ok=True)
database = excel()
database.collect(str(database_path))
model = hypoplasticity_isa(
out_dir=str(workdir / "results"),
out_dir2=str(workdir / "temporary"),
out_dir3=str(workdir / "final"),
)
model.set(
phic=30.0, fei=1.10, ec=1.054, ed=0.677,
hs=4.0, n=0.27, alpha=0.14, beta=2.5,
R=1.4e-4, mR=5.0, beta_h0=0.3, beta_hmax=2.0,
chi0=5.0, chi_max=20.0, eps_acc=0.02, cz=600.0,
)
model.set_bounds(
hs=[1.0, 10.0], n=[0.20, 0.40],
ed=[0.50, 0.75], ec=[0.90, 1.20],
)
globals.setup(
Model=model,
Free_parameter=["hs", "n", "ed", "ec", "alpha", "beta"],
oedometer=database.oedometer,
triaxCD=database.triax_CD,
triaxCU=database.triax_CU,
path=str(workdir),
Experimental_database=database_path,
)
DEEM.optimize(maxiter=200, n_cpu=8)
if __name__ == "__main__":
run_calibration()
For the model interface, similarity-measure functions, weighting and reporting modules, and instructions for adding a model, see the Developer API.