{
  "$defs": {
    "CoilCurrentSolver": {
      "description": "Elmer's ``CoilSolver``: the divergence-conforming coil current distribution, the source stage of the ``COIL_MAGNETOSTATICS`` chain.\n\nIt acts only on [`CoilDrive`][femforge.physical.conditions.CoilDrive] bodies, because Elmer requires every body it covers to belong to a ``Component``.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Direct",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "umfpack",
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 2000,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "CoilCurrent",
          "default": "CoilCurrent",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "CoilSolver",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"CoilSolver\" \"CoilSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Before simulation",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "coil_closed": {
          "default": false,
          "description": "False: an open coil whose ends are the ``Coil Start`` / ``Coil End`` electrode boundaries.",
          "title": "Coil Closed",
          "type": "boolean"
        },
        "normalize_coil_current": {
          "default": false,
          "description": "Must stay OFF for a massive coil: it rescales |J| to a UNIFORM magnitude, which on a varying cross-section\nauthors a non-conservative source that Jfix redistributes (silently reduced drive current in the winding).\n``Desired Coil Current`` scaling happens regardless, so the total current is still exact with this off.",
          "title": "Normalize Coil Current",
          "type": "boolean"
        },
        "calculate_elemental_fields": {
          "default": true,
          "description": "Export the DG ``CoilCurrent e`` field (what ``Use Elemental CoilCurrent`` reads); the nodal field stays too.",
          "title": "Calculate Elemental Fields",
          "type": "boolean"
        }
      },
      "title": "CoilCurrentSolver",
      "type": "object"
    },
    "Constants": {
      "description": "The Elmer ``Constants`` block: each constant is an optional field carrying its sif keyword; a physics sets only the constants it needs, and an unset one is omitted.",
      "properties": {
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "permeability_of_vacuum": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "`\u03bc\u2080` `[H/m]`: Needed by the magnetostatic solver.",
          "title": "Permeability Of Vacuum"
        },
        "permittivity_of_vacuum": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "`\u03b5\u2080` `[F/m]`: Needed by the electrostatic solver.",
          "title": "Permittivity Of Vacuum"
        },
        "stefan_boltzmann": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "`\u03c3_SB` `[W/(m\u00b2\u00b7K\u2074)]`: Needed for thermal radiation.",
          "title": "Stefan Boltzmann"
        }
      },
      "title": "Constants",
      "type": "object"
    },
    "CoordinateSystem": {
      "description": "Elmer's ``Coordinate System``.",
      "enum": [
        "Cartesian",
        "Cylindric",
        "Cylindric Symmetric",
        "Axi Symmetric",
        "Polar"
      ],
      "title": "CoordinateSystem",
      "type": "string"
    },
    "ElectrostaticsSolver": {
      "description": "SCAFFOLD: electrostatics (StatElecSolver). No nonlinear iteration.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-05,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Iterative",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 500,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-10,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "Electrostatics",
          "default": "Electrostatics",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "Electrostatics",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"StatElecSolve\" \"StatElecSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Potential",
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "calculate_electric_field": {
          "default": true,
          "description": "Recover E from the potential.",
          "title": "Calculate Electric Field",
          "type": "boolean"
        }
      },
      "title": "ElectrostaticsSolver",
      "type": "object"
    },
    "ExecSolver": {
      "description": "When Elmer executes a solver (the ``Exec Solver`` keyword).",
      "enum": [
        "Always",
        "Before simulation",
        "After simulation",
        "Before timestep",
        "After timestep",
        "Never"
      ],
      "title": "ExecSolver",
      "type": "string"
    },
    "GenericSolver": {
      "description": "Escape hatch: an arbitrary Elmer solver block for anything the typed hierarchy doesn't model yet \u2014 set\n``equation``/``procedure`` and author the rest through ``extra_keywords`` (plus the shared typed knobs).",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Iterative",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "Generic",
          "default": "Generic",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        }
      },
      "required": [
        "equation",
        "procedure"
      ],
      "title": "GenericSolver",
      "type": "object"
    },
    "HeatSolver": {
      "description": "SCAFFOLD: steady heat conduction. Wire-ready; its boundary conditions land on the adjacency-derived surface groups via the condition-driven boundary loop.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 50,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Direct",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "umfpack",
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 1000,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "HeatSolver",
          "default": "HeatSolver",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "HeatSolver",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"HeatSolve\" \"HeatSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Temperature",
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 1,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        }
      },
      "title": "HeatSolver",
      "type": "object"
    },
    "IterativeMethod": {
      "description": "The Krylov method for an iterative linear solve (``Linear System Iterative Method``).",
      "enum": [
        "BiCGStab",
        "BiCGStabl",
        "CG",
        "CGS",
        "GMRES",
        "GCR",
        "TFQMR"
      ],
      "title": "IterativeMethod",
      "type": "string"
    },
    "LinearSolverType": {
      "description": "The ``Linear System Solver`` strategy: an iterative Krylov method or a direct factorization.",
      "enum": [
        "Iterative",
        "Direct"
      ],
      "title": "LinearSolverType",
      "type": "string"
    },
    "MagnetoDynamics2DSolver": {
      "description": "Axisymmetric magnetostatics (MagnetoDynamics2D): the scalar azimuthal potential A_phi under ``Coordinate System = Axi Symmetric``.\n\nThe mesh lies flat in the XY plane (Z = 0), with X the radial distance from the symmetry axis (X >= 0) and Y the position along it.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-07,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 50,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1.0,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "solution",
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Direct",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "umfpack",
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "MagnetoDynamics2D",
          "default": "MagnetoDynamics2D",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "MgDyn2D",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"MagnetoDynamics2D\" \"MagnetoDynamics2D\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Potential",
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 1,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        }
      },
      "title": "MagnetoDynamics2DSolver",
      "type": "object"
    },
    "MagnetoDynamicsCalcFieldsSolver": {
      "description": "Post-processing: recover B, H, fluxes and nodal forces from the computed A. Inherits ``Linear System *`` because\nnodal-field recovery solves an (SPD, hence CG) mass-matrix system \u2014 without a linear solver Elmer aborts.",
      "properties": {
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Iterative",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "CG",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 500,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "MagnetoDynamicsCalcFields",
          "default": "MagnetoDynamicsCalcFields",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "MgDynCalc",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"MagnetoDynamics\" \"MagnetoDynamicsCalcFields\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "potential_variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The vector-potential variable to post-process; None lets the solver pick up the (default-named) MgDyn variable.",
          "title": "Potential Variable"
        },
        "average_within_materials": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Average recovered fields within each material so the B/H jump at a magnet surface is resolved cleanly.",
          "title": "Average Within Materials"
        },
        "calculate_magnetic_field_strength": {
          "default": true,
          "description": "Recover H.",
          "title": "Calculate Magnetic Field Strength",
          "type": "boolean"
        },
        "calculate_magnetic_flux_density": {
          "default": true,
          "description": "Recover B.",
          "title": "Calculate Magnetic Flux Density",
          "type": "boolean"
        },
        "calculate_nodal_forces": {
          "default": true,
          "description": "Recover nodal forces (drives the motor-force optimisation).",
          "title": "Calculate Nodal Forces",
          "type": "boolean"
        },
        "calculate_nodal_fields": {
          "default": false,
          "description": "Recover nodal field values.",
          "title": "Calculate Nodal Fields",
          "type": "boolean"
        },
        "calculate_joule_heating": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Recover the eddy/Joule loss field. Identically zero for a steady real-valued solve \u2014 set False there:\nthe zero-RHS projection it triggers when a Current Density body force is present segfaults CalcFields.",
          "title": "Calculate Joule Heating"
        },
        "calculate_electric_field": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Recover E = -dA/dt - grad V. Identically zero at steady state \u2014 set False for the chained coil solve,\nwhere its zero-RHS projection is what segfaults CalcFields after the B components.",
          "title": "Calculate Electric Field"
        },
        "calculate_magnetic_vector_potential": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Project the edge-element av onto a nodal A field; None keeps the solver default.",
          "title": "Calculate Magnetic Vector Potential"
        },
        "separate_magnetic_energy": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Export the magnetic field energy as SaveScalars-visible scalars (the ElmerCSC mgdyn_bh recipe) \u2014 the\nenergy-method inductance observable: L_eff = 2W/I\u00b2.",
          "title": "Separate Magnetic Energy"
        },
        "calculate_relative_permeability": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Recover the local relative permeability; the mgdyn_bh energy recipe enables it alongside the energy export.",
          "title": "Calculate Relative Permeability"
        },
        "calculate_elemental_fields": {
          "default": true,
          "description": "Recover elemental field values.",
          "title": "Calculate Elemental Fields",
          "type": "boolean"
        }
      },
      "title": "MagnetoDynamicsCalcFieldsSolver",
      "type": "object"
    },
    "MagnetoDynamicsSolver": {
      "description": "3D magnetostatics (WhitneyAVSolver), with each magnet's drive entering as ``Magnetization`` on its material rather than as a body force.\n\nLeave ``variable`` unset, so the far-field boundary condition can still name ``AV {e}``.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-10,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 50,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 3,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 0.001,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1.0,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Iterative",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStabl",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 500,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "None",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 10,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": false,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 4,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "MagnetoDynamics",
          "default": "MagnetoDynamics",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "MgDyn",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"MagnetoDynamics\" \"WhitneyAVSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "fix_input_current_density": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Project the source J onto a divergence-free field before the AV solve: the discrete J is not exactly solenoidal\nedge-element-wise, and an unfixed source makes the gauge-non-unique system inconsistent. None omits the keyword.",
          "title": "Fix Input Current Density"
        },
        "use_elemental_coilcurrent": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Read the source J from CoilSolver's *elemental* (DG) field instead of a nodal Body Force: nodal J is\nGalerkin-averaged across the conductor-air interface and silently dilutes the drive ~2x on thin traces.\nRequires a CoilSolver in the stack; None omits the keyword.",
          "title": "Use Elemental Coilcurrent"
        }
      },
      "title": "MagnetoDynamicsSolver",
      "type": "object"
    },
    "OperatingPoint": {
      "description": "The point at which a material's property functions are evaluated when stripping to Elmer's bare SI floats.\n``Static`` properties ignore it; temperature-dependent properties consume it via [`as_mapping`][].",
      "properties": {
        "temperature": {
          "description": "`T` `[K]`: Evaluation temperature for material property functions.",
          "title": "Temperature",
          "type": "string",
          "x-unit-dimensionality": "[temperature]"
        }
      },
      "title": "OperatingPoint",
      "type": "object"
    },
    "PhysicsConfig": {
      "description": "The fully populated, typed solver stack for one physics: ordered solvers plus simulation settings, activated constants and operating point.",
      "properties": {
        "solvers": {
          "description": "The ordered concrete solver instances Elmer runs for this physics.",
          "items": {
            "discriminator": {
              "mapping": {
                "CoilCurrent": "#/$defs/CoilCurrentSolver",
                "Electrostatics": "#/$defs/ElectrostaticsSolver",
                "Generic": "#/$defs/GenericSolver",
                "HeatSolver": "#/$defs/HeatSolver",
                "MagnetoDynamics": "#/$defs/MagnetoDynamicsSolver",
                "MagnetoDynamics2D": "#/$defs/MagnetoDynamics2DSolver",
                "MagnetoDynamicsCalcFields": "#/$defs/MagnetoDynamicsCalcFieldsSolver",
                "ResultOutputSolver": "#/$defs/ResultOutputSolver",
                "SaveScalars": "#/$defs/SaveScalarsSolver",
                "StatCurrent": "#/$defs/StatCurrentSolver",
                "StressSolver": "#/$defs/StressSolver"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/MagnetoDynamicsSolver"
              },
              {
                "$ref": "#/$defs/MagnetoDynamics2DSolver"
              },
              {
                "$ref": "#/$defs/MagnetoDynamicsCalcFieldsSolver"
              },
              {
                "$ref": "#/$defs/ResultOutputSolver"
              },
              {
                "$ref": "#/$defs/HeatSolver"
              },
              {
                "$ref": "#/$defs/StatCurrentSolver"
              },
              {
                "$ref": "#/$defs/CoilCurrentSolver"
              },
              {
                "$ref": "#/$defs/SaveScalarsSolver"
              },
              {
                "$ref": "#/$defs/ElectrostaticsSolver"
              },
              {
                "$ref": "#/$defs/StressSolver"
              },
              {
                "$ref": "#/$defs/GenericSolver"
              }
            ]
          },
          "title": "Solvers",
          "type": "array"
        },
        "simulation": {
          "$ref": "#/$defs/SimulationSettings",
          "description": "The Elmer Simulation block (run type, coordinate system, output files)."
        },
        "constants": {
          "$ref": "#/$defs/Constants",
          "description": "The physical constants this physics activates."
        },
        "operating_point": {
          "$ref": "#/$defs/OperatingPoint",
          "description": "Where material property functions are evaluated when stripping to SI."
        }
      },
      "required": [
        "solvers",
        "simulation",
        "constants",
        "operating_point"
      ],
      "title": "PhysicsConfig",
      "type": "object"
    },
    "Preconditioning": {
      "description": "The ``Linear System Preconditioning`` for an iterative solve.",
      "enum": [
        "None",
        "Diagonal",
        "ILU0",
        "ILU1",
        "ILU2",
        "ILU",
        "ILUT"
      ],
      "title": "Preconditioning",
      "type": "string"
    },
    "ResultOutputSolver": {
      "description": "Write VTU output for ParaView.",
      "properties": {
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "ResultOutputSolver",
          "default": "ResultOutputSolver",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "ResultOutputSolver",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"ResultOutputSolve\" \"ResultOutputSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "After timestep",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "vtu_format": {
          "default": true,
          "description": "Write VTU (ParaView) output.",
          "title": "Vtu Format",
          "type": "boolean"
        },
        "output_file_name": {
          "default": "File \"case\"",
          "description": "Stem of the written VTU (Elmer emits e.g. ``case_t0001.vtu``); pinned so the name never depends on Elmer defaults.",
          "title": "Output File Name",
          "type": "string"
        },
        "save_geometry_ids": {
          "default": true,
          "description": "Tag output cells with their gmsh geometry ids.",
          "title": "Save Geometry Ids",
          "type": "boolean"
        },
        "saved_scalar_fields": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Scalar fields to save (each a full sif RHS, e.g. ``'String \"joule heating\"'``); None saves every active variable.",
          "title": "Saved Scalar Fields"
        },
        "saved_vector_fields": {
          "anyOf": [
            {
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Vector fields to save; None saves every active variable.",
          "title": "Saved Vector Fields"
        },
        "discontinuous_bodies": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Average elemental fields body-wise onto a minimal discontinuous node set, so the VTU keeps cross-body discontinuities.",
          "title": "Discontinuous Bodies"
        }
      },
      "title": "ResultOutputSolver",
      "type": "object"
    },
    "SaveScalarsSolver": {
      "description": "SaveScalars (SaveData): export scalar reductions to ``scalars.dat`` and its ``.names`` sidecar.\n\nIts ``diffusive flux`` operator integrates each ``Save Scalars = True`` electrode's terminal current, the ``I`` in ``R = \u0394V / I``.",
      "properties": {
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "SaveScalars",
          "default": "SaveScalars",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "SaveScalars",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"SaveData\" \"SaveScalars\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "After timestep",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "save_component_results": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Also export the scalars arising from Component sections.",
          "title": "Save Component Results"
        },
        "parallel_reduce": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reduce a partitioned run's output to one ``scalars.dat`` instead of per-rank ``.dat.<rank>`` files.",
          "title": "Parallel Reduce"
        },
        "filename": {
          "default": "\"scalars.dat\"",
          "description": "The .dat the scalars land in (the run parser reads it, or its per-rank ``.dat.<rank>`` siblings, via the ``.names`` sidecar).",
          "title": "Filename",
          "type": "string"
        },
        "variable_1": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Potential",
          "description": "The variable the operator reduces.",
          "title": "Variable 1"
        },
        "operator_1": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "diffusive flux",
          "description": "The reduction: boundary integral of the conjugate flux of ``variable_1``.",
          "title": "Operator 1"
        },
        "coefficient_1": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Electric Conductivity",
          "description": "The material coefficient weighting the flux (\u03c3 \u2202\u03c6/\u2202n integrates to a current).",
          "title": "Coefficient 1"
        },
        "variable_2": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Joule Heating",
          "description": "Second reduction: the Joule loss field (requires ``Calculate Joule Heating``).",
          "title": "Variable 2"
        },
        "operator_2": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "int",
          "description": "Volume integral: total dissipated power P (W), the flux-independent cross-check R = \u0394V\u00b2/P.",
          "title": "Operator 2"
        },
        "variable_3": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Third reduction; the coupled joule-heating stack sets ``Temperature`` here.",
          "title": "Variable 3"
        },
        "operator_3": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Reduction for ``variable_3``; the coupled stack uses ``max`` (peak temperature).",
          "title": "Operator 3"
        }
      },
      "title": "SaveScalarsSolver",
      "type": "object"
    },
    "SimulationSettings": {
      "description": "The Elmer ``Simulation`` block. Defaults are a 3D Cartesian steady-state run, used for magnetostatics and steady thermal.",
      "properties": {
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "max_output_level": {
          "default": 5,
          "description": "Verbosity of ElmerSolver's console output (0-quiet \u2026 higher-noisier).",
          "title": "Max Output Level",
          "type": "integer"
        },
        "coordinate_system": {
          "$ref": "#/$defs/CoordinateSystem",
          "default": "Cartesian",
          "description": "The simulation coordinate system."
        },
        "coordinate_mapping": {
          "default": "1 2 3",
          "description": "Axis permutation for the coordinate system.",
          "title": "Coordinate Mapping",
          "type": "string"
        },
        "simulation_type": {
          "$ref": "#/$defs/SimulationType",
          "default": "Steady state",
          "description": "Steady-state, transient, or scanning run."
        },
        "steady_state_max_iterations": {
          "default": 1,
          "description": "Max steady-state (coupled-system) iterations.",
          "title": "Steady State Max Iterations",
          "type": "integer"
        },
        "output_intervals": {
          "default": 1,
          "description": "Write results every N steps.",
          "title": "Output Intervals",
          "type": "integer"
        },
        "timestepping_method": {
          "$ref": "#/$defs/TimesteppingMethod",
          "default": "BDF",
          "description": "Time integration scheme."
        },
        "bdf_order": {
          "default": 1,
          "description": "Order of the BDF timestepping method.",
          "title": "Bdf Order",
          "type": "integer"
        },
        "solver_input_file": {
          "default": "case.sif",
          "description": "Name of the generated .sif.",
          "title": "Solver Input File",
          "type": "string"
        },
        "post_file": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "ParaView/VTU post-processing output file; None (the default) leaves VTU output to the ResultOutputSolver \u2014\nsetting both trips Elmer's AddVtuOutputSolverHack and its log spam.",
          "title": "Post File"
        },
        "output_file": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "ElmerSolver restart/result file; None (the default) skips it \u2014 nothing downstream reads it and it grows to\nmulti-GB on large solves. Set a name only when a restart is wanted.",
          "title": "Output File"
        }
      },
      "title": "SimulationSettings",
      "type": "object"
    },
    "SimulationType": {
      "description": "Elmer's ``Simulation Type``.",
      "enum": [
        "Steady state",
        "Transient",
        "Scanning"
      ],
      "title": "SimulationType",
      "type": "string"
    },
    "StatCurrentSolver": {
      "description": "Static current conduction (Elmer's StatCurrentSolve): solves ``Potential`` from \u2207\u00b7(\u03c3\u2207\u03c6) = 0, excited by per-phase\n[`FixedPotential`][femforge.physical.conditions.FixedPotential] terminal pairs. The nonlinear block is inert while \u03c3 is Static.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 20,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Direct",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "umfpack",
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "CG",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 5000,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "StatCurrent",
          "default": "StatCurrent",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "Stat Current Solver",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"StatCurrentSolve\" \"StatCurrentSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Potential",
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 1,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "calculate_volume_current": {
          "default": true,
          "description": "Recover the volume current density J = -\u03c3\u2207\u03c6.",
          "title": "Calculate Volume Current",
          "type": "boolean"
        },
        "calculate_joule_heating": {
          "default": true,
          "description": "Recover the Joule loss density \u03c3|\u2207\u03c6|\u00b2 (the heat-solve coupling source).",
          "title": "Calculate Joule Heating",
          "type": "boolean"
        }
      },
      "title": "StatCurrentSolver",
      "type": "object"
    },
    "StressSolver": {
      "description": "SCAFFOLD: linear elasticity (Elmer's StressSolve). Consumes ``Youngs Modulus`` and ``Poisson Ratio`` material\nkeywords; the latter is not yet stored on MechanicalProperties.",
      "properties": {
        "steady_state_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-06,
          "description": "Steady-state convergence tolerance.",
          "title": "Steady State Convergence Tolerance"
        },
        "nonlinear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-07,
          "description": "Residual tolerance for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Convergence Tolerance"
        },
        "nonlinear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 1,
          "description": "Iteration cap for the nonlinear (outer) iteration.",
          "title": "Nonlinear System Max Iterations"
        },
        "nonlinear_system_newton_after_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton after this many outer iterations.",
          "title": "Nonlinear System Newton After Iterations"
        },
        "nonlinear_system_newton_after_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Switch from Picard to Newton once the residual drops below this.",
          "title": "Nonlinear System Newton After Tolerance"
        },
        "nonlinear_system_relaxation_factor": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Under/over-relaxation factor for the nonlinear update (1 = none).",
          "title": "Nonlinear System Relaxation Factor"
        },
        "nonlinear_system_convergence_measure": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Nonlinear residual measure (e.g. \"solution\"); None keeps Elmer's default.",
          "title": "Nonlinear System Convergence Measure"
        },
        "linear_system_solver": {
          "anyOf": [
            {
              "$ref": "#/$defs/LinearSolverType"
            },
            {
              "type": "null"
            }
          ],
          "default": "Iterative",
          "description": "Iterative (Krylov) or Direct linear solve."
        },
        "linear_system_direct_method": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Factorization backend for a Direct solve (e.g. \"umfpack\"); None omits the keyword.",
          "title": "Linear System Direct Method"
        },
        "linear_system_iterative_method": {
          "anyOf": [
            {
              "$ref": "#/$defs/IterativeMethod"
            },
            {
              "type": "null"
            }
          ],
          "default": "BiCGStab",
          "description": "Krylov method when the solve is iterative."
        },
        "linear_system_max_iterations": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 5000,
          "description": "Iteration cap for the linear solve.",
          "title": "Linear System Max Iterations"
        },
        "linear_system_convergence_tolerance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": 1e-08,
          "description": "Residual tolerance for the linear solve.",
          "title": "Linear System Convergence Tolerance"
        },
        "linear_system_preconditioning": {
          "anyOf": [
            {
              "$ref": "#/$defs/Preconditioning"
            },
            {
              "type": "null"
            }
          ],
          "default": "ILU0",
          "description": "Preconditioner for the iterative solve."
        },
        "linear_system_residual_output": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Print the linear residual every N iterations; None omits it.",
          "title": "Linear System Residual Output"
        },
        "linear_system_abort_not_converged": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Abort the run if the linear solve doesn't converge; False lets a stalled gauge-non-unique AV solve proceed.",
          "title": "Linear System Abort Not Converged"
        },
        "bicgstabl_polynomial_degree": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Polynomial degree l for the BiCGStab(l) Krylov method.",
          "title": "Bicgstabl Polynomial Degree"
        },
        "extra_keywords": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              },
              {
                "type": "number"
              },
              {
                "type": "boolean"
              }
            ]
          },
          "description": "Escape hatch: verbatim sif keyword/value pairs merged (last, so they win) into [`to_elmer`][] \u2014 any Elmer\nkeyword the typed fields don't model yet stays authorable without subclassing.",
          "title": "Extra Keywords",
          "type": "object"
        },
        "kind": {
          "const": "StressSolver",
          "default": "StressSolver",
          "description": "Discriminator that names this solver, doubling as its sif Solver label.",
          "title": "Kind",
          "type": "string"
        },
        "equation": {
          "default": "Linear elasticity",
          "description": "Elmer equation/solver name.",
          "title": "Equation",
          "type": "string"
        },
        "procedure": {
          "default": "\"StressSolve\" \"StressSolver\"",
          "description": "Elmer Procedure: \"library\" \"function\".",
          "title": "Procedure",
          "type": "string"
        },
        "variable": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": "Displacement",
          "description": "Primary solver variable; None for solvers that declare none.",
          "title": "Variable"
        },
        "variable_dofs": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "default": 3,
          "description": "Degrees of freedom per node; None lets Elmer infer.",
          "title": "Variable Dofs"
        },
        "exec_solver": {
          "$ref": "#/$defs/ExecSolver",
          "default": "Always",
          "description": "When Elmer runs this solver."
        },
        "stabilize": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Enable stabilization; None omits the keyword.",
          "title": "Stabilize"
        },
        "optimize_bandwidth": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": true,
          "description": "Reorder DOFs to reduce matrix bandwidth; None omits the keyword.",
          "title": "Optimize Bandwidth"
        },
        "calculate_stresses": {
          "default": true,
          "description": "Recover the stress tensor from the displacement.",
          "title": "Calculate Stresses",
          "type": "boolean"
        }
      },
      "title": "StressSolver",
      "type": "object"
    },
    "TimesteppingMethod": {
      "description": "Elmer's ``Timestepping Method`` (paired with ``BDF Order`` for BDF).",
      "enum": [
        "BDF",
        "Newmark",
        "Runge-Kutta"
      ],
      "title": "TimesteppingMethod",
      "type": "string"
    }
  },
  "description": "Which physics the Elmer stage solves; ``SimulationConfig`` derives the solved stack from this selection and its frame.",
  "properties": {
    "selected": {
      "default": "magnetostatics",
      "description": "The physics as authored (magnetostatics / thermal / ...); the config's frame decides the form it solves as.",
      "enum": [
        "magnetostatics",
        "thermal",
        "electrostatics",
        "current_conduction",
        "joule_heating",
        "coil_magnetostatics",
        "linear_elasticity"
      ],
      "title": "Physics",
      "type": "string"
    },
    "overrides": {
      "anyOf": [
        {
          "$ref": "#/$defs/PhysicsConfig"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The authored solver stack for this run (see ``SimulationConfig.customize_physics``); ``None`` solves the preset.\nPart of the config, so authored settings feed the run identity (``cache_key``) and the manifest."
    }
  },
  "title": "PhysicsSelection",
  "type": "object"
}
