pycsamt.agents.mare2dem_agent#

pycsamt.agents.mare2dem_agent#

Mare2DEMAgent — Orchestrate a complete MARE2DEM 2.5-D EM inversion workflow.

MARE2DEM (Modeling with Adaptively Refined Elements for 2.5-D Electromagnetic inversion) is a 2.5-D FEM MT and CSEM inversion code (Key 2016). Unlike Occam2D and ModEM, the MARE2DEM binary is NOT bundled with pycsamt and must be downloaded and compiled from source once per machine before any inversion run.

This agent handles the complete lifecycle:

  1. Source management (optional) — detect whether the MARE2DEM binary already exists; if not, offer to download and compile using SourceManager.

  2. Input preparation — write the .emdata data file, starting .resistivity model, and .settings parallel-decomposition file using InputBuilder. Accepts either an existing .emdata path or an inline survey specification via MTSurveyConfig / CSEMSurveyConfig.

  3. Inversion run (optional) — launch the MARE2DEM binary through Mare2DEMRunner when mode is "run" and the binary is available.

  4. Result reporting — scan the run directory with InversionResult and return the log, final model, and RMS convergence history. When an LLM API key is provided, a brief interpretation of the inversion outcome is appended.

References

Key, K. (2016). MARE2DEM: A 2-D inversion code for controlled-source electromagnetic and magnetotelluric data. Geophysical Journal International, 207(1), 571–588. doi:10.1093/gji/ggw290.

Classes

Mare2DEMAgent(*[, api_key, model, ...])

Orchestrate a complete MARE2DEM 2.5-D EM inversion workflow.

class pycsamt.agents.mare2dem_agent.Mare2DEMAgent(*, api_key=None, model=None, llm_provider='claude', n_procs=4, use_mpi=True, initial_rho=1.0, target_rms=1.0, max_iterations=150)[source]#

Bases: BaseAgent

Orchestrate a complete MARE2DEM 2.5-D EM inversion workflow.

Parameters:
  • api_key (str or None) – LLM API key (Anthropic / OpenAI / Gemini).

  • model (str or None) – LLM model identifier; defaults to the provider’s recommended model.

  • llm_provider (str) – "claude" (default), "openai", "gemini", "deepseek", or "minimax".

  • n_procs (int, optional) – Number of MPI processes for MARE2DEM (default 4).

  • use_mpi (bool) – Whether to prefix the binary with mpirun -np n_procs (default True). Set to False only for single-process debug builds.

  • initial_rho (float, optional) – Starting half-space resistivity in Ω·m (default 1.0).

  • target_rms (float, optional) – Target normalised RMS misfit (default 1.0).

  • max_iterations (int, optional) – Maximum Occam inversion iterations (default 150).

  • keys (Output data)

  • ----------

  • path (sites /) – EDI source (directory, files, or a loaded Sites). The agent converts the impedances to a MARE2DEM .emdata file via make_mt_data_from_edi() (TE = Zxy, TM = Zyx). Used when emdata/mt/csem are not supplied — this is the pathway the workflow orchestrator uses.

  • error_floor (float, optional) – Relative error floor applied to the TE/TM apparent resistivities built from EDI data (default 0.05 = 5 %).

  • output_modes (str, optional) – Data types written from EDI data: "all" (default), "TE", "TM", "TE+tipper", or "all impedance".

  • emdata (str or path-like, optional) – Path to an existing .emdata data file. When supplied the agent copies it to the output directory and uses it directly.

  • resistivity (str or path-like, optional) – Path to an existing starting .resistivity file. When omitted a homogeneous half-space model is written.

  • mt (dict, optional) – Keyword arguments for MTSurveyConfig when building the data file from survey parameters rather than a pre-existing file.

  • csem (dict, optional) – Keyword arguments for CSEMSurveyConfig.

  • topo (float or array-like, optional) – Topography for receiver/transmitter placement. Flat scalar (e.g. -1000.0 m for a flat seafloor) or an (n, 2) array of [y, z] pairs. Default 0.0 (flat surface).

  • output_dir (str) – Directory that will receive all MARE2DEM input files and run output. Created if absent (default "pycsamt_mare2dem").

  • mode ({"prepare", "run", "report"}) –

    Workflow mode:

    • "prepare" — write input files only (default).

    • "run" — write files then launch MARE2DEM.

    • "report" — scan an existing run directory and return results without (re-)running.

  • source_dir (str or path-like, optional) – Explicit path to the MARE2DEM source tree. Passed to SourceManager; auto-resolved when omitted.

  • download_source (bool) – When True and the binary is missing, execute() automatically runs SourceManager.download() and SourceManager.build(). Defaults to False (raises a warning instead).

  • n_procs – Per-call override for n_procs.

  • max_iterations – Per-call override.

  • target_rms – Per-call override.

  • initial_rho – Per-call override.

  • keys

  • ----------------

  • data_path (Path or None)

  • resistivity_path (Path or None)

  • settings_path (Path or None)

  • binary_found (bool)

  • source_downloaded (bool)

  • n_mt_receivers (int)

  • n_csem_transmitters (int)

  • n_data (int)

  • final_rms (float or None)

  • n_iterations (int)

  • converged (bool)

  • result (InversionResult or None)

  • output_dir

Examples

Prepare input files from an existing data file:

>>> agent  = Mare2DEMAgent(n_procs=8)
>>> result = agent.execute({
...     "emdata":     "/data/survey.emdata",
...     "output_dir": "/run/mare2dem",
... })
>>> print(result["data_path"])
/run/mare2dem/mare2dem.emdata

Build from MT survey parameters (flat seafloor at −1000 m):

>>> import numpy as np
>>> result = agent.execute({
...     "mt": {
...         "frequencies": list(np.logspace(-3, 3, 20)),
...         "rx_y":        list(np.linspace(-5000, 5000, 20)),
...         "rx_type":     "marine",
...         "lTE":         True,
...         "lTM":         True,
...     },
...     "topo":       -1000.0,
...     "output_dir": "/run/mare2dem_mt",
... })

Run a full inversion (requires compiled MARE2DEM binary):

>>> result = agent.execute({
...     "emdata":     "survey.emdata",
...     "output_dir": "./run",
...     "mode":       "run",
...     "n_procs":    16,
... })
>>> print(result["final_rms"])
0.98

Report results from a completed run directory:

>>> result = agent.execute({
...     "output_dir": "./run",
...     "mode":       "report",
... })
>>> result["converged"]
True
SYSTEM_PROMPT: str = 'You are an expert in 2.5-D EM inversion using MARE2DEM.\nGiven a summary of the survey geometry, input files, and inversion\noutcome, write 4–5 sentences that:\n1. Assess the receiver and transmitter coverage relative to the target depth.\n2. Comment on the starting resistivity model and Occam regularisation settings.\n3. Evaluate the convergence: is the final RMS close to target? Any stagnation?\n4. Recommend parallel decomposition settings (tx/rx per group) for the cluster size.\n5. Flag any data issues (low-amplitude offsets, asymmetric MT responses, topo artefacts).\nReply in plain English. Be specific about MARE2DEM parameters.\n'#

Override in subclasses to give the LLM its domain expertise.

execute(input_data)[source]#

Run this agent on input_data and return an AgentResult.

Subclasses must implement this method. The contract:

  • Reset self._last_cost = 0.0 at the top.

  • Record wall-clock time with t0 = time.time().

  • Return AgentResult(elapsed_seconds=time.time()-t0, cost_estimate_usd=self._last_cost, ...).

Parameters:

input_data (dict[str, Any])

Return type:

AgentResult