Skip to content

Add adapt_to_depletion_and_bias_voltage!#612

Open
hervasa2 wants to merge 2 commits into
JuliaPhysics:mainfrom
hervasa2:adapt-simulation-to-depletion-and-bias
Open

Add adapt_to_depletion_and_bias_voltage!#612
hervasa2 wants to merge 2 commits into
JuliaPhysics:mainfrom
hervasa2:adapt-simulation-to-depletion-and-bias

Conversation

@hervasa2

@hervasa2 hervasa2 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Added adapt_to_depletion_and_bias_voltage!.

adapt_to_depletion_and_bias_voltage!(sim, dep, bias) adapts a Simulation in place to a target depletion voltage dep and operating (bias) voltage bias by rescaling the impurity density component of the electric potential (f = dep / dep_sim) and swapping in the bias contact potential via superposition — without re-solving the field. Note that the actual sim.detector.semiconductor.impurity_density_model and sim.detector.contacts[id].potential fields are also modified in place to reflect the change.

Tests check that this is performed correctly, and that after adapt_to_depletion_and_bias_voltage! is run on a simulation, a subsequent calculate_electric_potential! returns compatible results.
This is then compared to the manual way a user would have to do things: initializing a fresh simulation, modifying the sim.detector.semiconductor.impurity_density_model and sim.detector.contacts[id].potential fields and then running calculate_electric_potential!.

This function is useful when the user wants to modify the simulation on the fly to reflect real-world conditions: a different measured depletion voltage and changing operating voltages without having to recalculate the electric potential. Note that in this process the weighting potential will be calculated and populated in the simulation.

Note that this only works on depleted simulations. This check is done when estimate_depletion_voltage is called internally.

Changes

  • Export adapt_to_depletion_and_bias_voltage!.
  • Input validation: dep and bias must share the same (non-zero) sign, and abs(bias) > abs(dep) (the detector must be over-depleted at the operating voltage). Both polarities are supported.
  • Docstring describing the impurity-rescaling / superposition mechanism, arguments, keywords, and an example.
  • Tests in test/test_depletion.jl:
    • round-trip: after adapting, the bias contact sits at bias and the re-estimated depletion voltage ≈ dep;
    • an in-place re-solve still matches;
    • a freshly built equivalent simulation (same adapted impurity model + bias) reproduces the same depletion voltage.

Testing

test/test_depletion.jl passes locally (11/11).

@hervasa2 hervasa2 changed the title Export, document, and guard adapt_simulation_to_depletion_and_bias! Add adapt_simulation_to_depletion_and_bias! Jun 22, 2026
@hervasa2 hervasa2 requested a review from fhagemann June 22, 2026 14:24
@hervasa2 hervasa2 added enhancement Improvement of existing features new feature Add new feature labels Jun 22, 2026
@hervasa2 hervasa2 force-pushed the adapt-simulation-to-depletion-and-bias branch from dd43303 to fe61010 Compare June 22, 2026 14:28
@hervasa2 hervasa2 changed the title Add adapt_simulation_to_depletion_and_bias! Add adapt_to_depletion_and_bias_voltage! Jun 22, 2026
…and tests

- Export `adapt_to_depletion_and_bias_voltage!`.
- Add input validation: depletion and operating voltages must share the same
  (non-zero) sign and `abs(op) > abs(dep)` (detector over-depleted at bias).
- Add a docstring describing the impurity-rescaling / superposition mechanism.
- Add tests covering the round-trip (adapt then re-estimate), an in-place
  re-solve, and a comparison against a freshly built equivalent simulation.
@hervasa2 hervasa2 force-pushed the adapt-simulation-to-depletion-and-bias branch from fe61010 to 10e4637 Compare June 22, 2026 14:33
@fhagemann

Copy link
Copy Markdown
Collaborator

Can you let me know once you’re done force pushing for me to look at this PR? 😅

@hervasa2

Copy link
Copy Markdown
Collaborator Author

Sorry Im done. Just some last minute naming changes for consistency

@fhagemann fhagemann left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a very useful function and I think it would be a nice addition to SSD.
I have some comments on the name of the function, the requirement of having to pass BOTH a target depletion and bias voltage, the docstring, and error handling in the tests :)

Comment thread src/Simulation/Depletion.jl Outdated

See also [`estimate_depletion_voltage`](@ref).
"""
function adapt_to_depletion_and_bias_voltage!(sim::Simulation{T}, dep::RealQuantity, bias::RealQuantity;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we can probably find a better name to make clear that ONLY the electric potential (but e.g. not the electric field) is updated.

  • Can we avoid the verb adapt to avoid confusion with adapt from Adapt.jl? I know we used adapt for the internal function to map the grids of electric and weighting potentials, but for an exported function I would like to be a bit more careful with wording.
  • It would also be nice to have a method that doesn't expect a bias and just lets the bias remain whatever it was before. Same thing if someone were to just change the bias without planning on changing the depletion voltage. Would it make sense to split this into two functions (one called something like update_electric_potential_to_match_depletion! and the other one update_electric_potential_to_match_bias! -- these are probably not the best names to choose from), which are then called by this overall function that allows to change both if wanted? Not sure what's the best way to go here, so I'm open for suggestions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am in favor of splitting it into update_electric_potential_to_match_depletion! and update_electric_potential_to_match_bias!. But I would not add a third function that calls both. I am happy with the names you chose

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like the verb update, because that's usually the verb we use to actually run the SOR, and this is explicitly not doing that, though 😅

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if there's any suggestion other than update or adapt, I'd be happy to discuss :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't what is really happening here is that the impurities are rescaled. I think the current function name is a bit obtuse and doesn't really tell you that (regardless of the update / adapt discussion).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data in sim.electric.potential.data is also updated in this function, but not using the standard way of using the SOR algorithm, but by calculating it from a linear combination of the electric potential and the weighting potentials on the same grid.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screencast.from.2026-06-24.13-48-57.webm

Electric potential from impurity density + Electric potential from bias voltage = Final electric potential

So, here, it's subtracting the contribution from the bias voltage, rescaling it to match the depletion voltage, and adding the electric potential with an updated bias voltage back onto it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if in practice youd want to recompute the electric_potiential in the standard way before running sims (even if a bit unnecessary)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hervasa2 One could think about adding an (optional) extra convergence step afterwards.

Comment thread src/Simulation/Depletion.jl Outdated
Comment thread test/test_depletion.jl Outdated
Comment thread src/Simulation/Depletion.jl Outdated
Comment thread src/Simulation/Depletion.jl Outdated
bias::T = _parse_value(T, bias, internal_voltage_unit)
@assert dep * bias > 0 "The depletion voltage ($(dep)$(internal_voltage_unit)) and operating voltage ($(bias)$(internal_voltage_unit)) must have the same (non-zero) sign."
@assert abs(bias) > abs(dep) "The operating voltage ($(bias)$(internal_voltage_unit)) must exceed the depletion voltage ($(dep)$(internal_voltage_unit)) in magnitude (the detector must be over-depleted)."
dep_sim = _parse_value(T, estimate_depletion_voltage(sim; contact_id = contact_id, verbose = verbose, kwargs...), internal_voltage_unit)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to allow the user to pass the expected depletion voltage also to the function? I can't judge how long estimate_depletion_voltage takes, especially if sim.electric_potential and sim.weighting_potentials[contact.id] are already defined on the same grid.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added U_min and U_max as args which passes the range to estimate_depletion_voltage

Comment thread src/Simulation/Depletion.jl
@tdixon97

Copy link
Copy Markdown
Contributor

@hervasa2 this is of course very useful. But I do not understand this part about the fields not being relculated? Doesn't this have to happen? Maybe it can be at the end, since the fields are needed to get the right charge drift

@fhagemann

Copy link
Copy Markdown
Collaborator

My understanding is that the electric POTENTIAL is recalculated, but NOT using the whole SOR relaxation algorithm, but just a linear combination of the old electric potential and the weighting potential of the contact that you're applying the bias voltage to (which allows you to skip the costly SOR algorithm step).

However, it is true that you need to recalculate the electric FIELD still would need to be recalculated with calculate_electric_field! in order for the charge drift to be based on the updated electric field.

@tdixon97

Copy link
Copy Markdown
Contributor

Yeah then the docs need to reflect that?

- Drop `adapt_to_depletion_and_bias_voltage!`; export two functions instead:
  `superpose_electric_potential_to_match_depletion!` (rescale the impurity density)
  and `superpose_electric_potential_to_match_bias!` (shift the bias), each adjusting
  `sim.electric_potential` analytically via superposition.
- `reconverge_after_superpose` (default true) re-relaxes the field and restores the
  bulk/undepleted/inactive-layer point-type markings via `_reconverge_after_superpose`.
- Both functions validate that target and reference voltages share sign and that the
  detector is over-depleted (ArgumentError otherwise).
- `estimate_depletion_voltage` now throws `ArgumentError` (was a warning) when the
  result is outside the search range.
- `update_till_convergence!` and `refine!` default `depletion_handling` to the sim's
  current state via `has_depletion_handling(sim.point_types)`.
- Update docstrings; rework tests for the split API and add error-path tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement of existing features new feature Add new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants