dkx 2.3.0__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. {dkx-2.3.0 → dkx-2.3.1}/PKG-INFO +1 -1
  2. {dkx-2.3.0 → dkx-2.3.1}/dkx/__init__.py +1 -1
  3. {dkx-2.3.0 → dkx-2.3.1}/dkx/solve.py +155 -7
  4. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/PKG-INFO +1 -1
  5. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/SOURCES.txt +2 -0
  6. {dkx-2.3.0 → dkx-2.3.1}/pyproject.toml +1 -1
  7. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_workflow_browser.py +7 -2
  8. dkx-2.3.1/tests/test_scan_survives_a_failing_point.py +108 -0
  9. {dkx-2.3.0 → dkx-2.3.1}/tests/test_solve.py +11 -4
  10. dkx-2.3.1/tests/test_tier2_stall_escalates_instead_of_crashing.py +101 -0
  11. {dkx-2.3.0 → dkx-2.3.1}/LICENSE +0 -0
  12. {dkx-2.3.0 → dkx-2.3.1}/README.md +0 -0
  13. {dkx-2.3.0 → dkx-2.3.1}/dkx/__main__.py +0 -0
  14. {dkx-2.3.0 → dkx-2.3.1}/dkx/ambipolar.py +0 -0
  15. {dkx-2.3.0 → dkx-2.3.1}/dkx/api.py +0 -0
  16. {dkx-2.3.0 → dkx-2.3.1}/dkx/batch.py +0 -0
  17. {dkx-2.3.0 → dkx-2.3.1}/dkx/bootstrap.py +0 -0
  18. {dkx-2.3.0 → dkx-2.3.1}/dkx/bounce_averaged.py +0 -0
  19. {dkx-2.3.0 → dkx-2.3.1}/dkx/cli.py +0 -0
  20. {dkx-2.3.0 → dkx-2.3.1}/dkx/coarse_precond.py +0 -0
  21. {dkx-2.3.0 → dkx-2.3.1}/dkx/collisions.py +0 -0
  22. {dkx-2.3.0 → dkx-2.3.1}/dkx/collocation.py +0 -0
  23. {dkx-2.3.0 → dkx-2.3.1}/dkx/compare.py +0 -0
  24. {dkx-2.3.0 → dkx-2.3.1}/dkx/console.py +0 -0
  25. {dkx-2.3.0 → dkx-2.3.1}/dkx/constants.py +0 -0
  26. {dkx-2.3.0 → dkx-2.3.1}/dkx/drift_kinetic.py +0 -0
  27. {dkx-2.3.0 → dkx-2.3.1}/dkx/er.py +0 -0
  28. {dkx-2.3.0 → dkx-2.3.1}/dkx/impurity.py +0 -0
  29. {dkx-2.3.0 → dkx-2.3.1}/dkx/input_compat.py +0 -0
  30. {dkx-2.3.0 → dkx-2.3.1}/dkx/inputs.py +0 -0
  31. {dkx-2.3.0 → dkx-2.3.1}/dkx/io.py +0 -0
  32. {dkx-2.3.0 → dkx-2.3.1}/dkx/magnetic_geometry.py +0 -0
  33. {dkx-2.3.0 → dkx-2.3.1}/dkx/moments.py +0 -0
  34. {dkx-2.3.0 → dkx-2.3.1}/dkx/momentum_correction.py +0 -0
  35. {dkx-2.3.0 → dkx-2.3.1}/dkx/monoenergetic.py +0 -0
  36. {dkx-2.3.0 → dkx-2.3.1}/dkx/multigrid.py +0 -0
  37. {dkx-2.3.0 → dkx-2.3.1}/dkx/namelist.py +0 -0
  38. {dkx-2.3.0 → dkx-2.3.1}/dkx/paths.py +0 -0
  39. {dkx-2.3.0 → dkx-2.3.1}/dkx/phase_space.py +0 -0
  40. {dkx-2.3.0 → dkx-2.3.1}/dkx/phi1.py +0 -0
  41. {dkx-2.3.0 → dkx-2.3.1}/dkx/plotting.py +0 -0
  42. {dkx-2.3.0 → dkx-2.3.1}/dkx/profiling.py +0 -0
  43. {dkx-2.3.0 → dkx-2.3.1}/dkx/representative.py +0 -0
  44. {dkx-2.3.0 → dkx-2.3.1}/dkx/run.py +0 -0
  45. {dkx-2.3.0 → dkx-2.3.1}/dkx/sensitivity.py +0 -0
  46. {dkx-2.3.0 → dkx-2.3.1}/dkx/shaing_callen.py +0 -0
  47. {dkx-2.3.0 → dkx-2.3.1}/dkx/solver_trace.py +0 -0
  48. {dkx-2.3.0 → dkx-2.3.1}/dkx/sparse_precond.py +0 -0
  49. {dkx-2.3.0 → dkx-2.3.1}/dkx/species.py +0 -0
  50. {dkx-2.3.0 → dkx-2.3.1}/dkx/units.py +0 -0
  51. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/__init__.py +0 -0
  52. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/artifacts.py +0 -0
  53. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/data_fetch.py +0 -0
  54. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/equilibria_manifest.json +0 -0
  55. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/fortran.py +0 -0
  56. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/lanes.py +0 -0
  57. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/panels.py +0 -0
  58. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/policy.py +0 -0
  59. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/release.py +0 -0
  60. {dkx-2.3.0 → dkx-2.3.1}/dkx/validation/series.py +0 -0
  61. {dkx-2.3.0 → dkx-2.3.1}/dkx/validity.py +0 -0
  62. {dkx-2.3.0 → dkx-2.3.1}/dkx/variational.py +0 -0
  63. {dkx-2.3.0 → dkx-2.3.1}/dkx/vmec_ascii.py +0 -0
  64. {dkx-2.3.0 → dkx-2.3.1}/dkx/workflows/__init__.py +0 -0
  65. {dkx-2.3.0 → dkx-2.3.1}/dkx/workflows/geometry_adapters.py +0 -0
  66. {dkx-2.3.0 → dkx-2.3.1}/dkx/workflows/optimization.py +0 -0
  67. {dkx-2.3.0 → dkx-2.3.1}/dkx/workflows/scans.py +0 -0
  68. {dkx-2.3.0 → dkx-2.3.1}/dkx/writer.py +0 -0
  69. {dkx-2.3.0 → dkx-2.3.1}/dkx/xgrid.py +0 -0
  70. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/dependency_links.txt +0 -0
  71. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/entry_points.txt +0 -0
  72. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/requires.txt +0 -0
  73. {dkx-2.3.0 → dkx-2.3.1}/dkx.egg-info/top_level.txt +0 -0
  74. {dkx-2.3.0 → dkx-2.3.1}/setup.cfg +0 -0
  75. {dkx-2.3.0 → dkx-2.3.1}/tests/test_api_contracts.py +0 -0
  76. {dkx-2.3.0 → dkx-2.3.1}/tests/test_audit_suite_output_keys.py +0 -0
  77. {dkx-2.3.0 → dkx-2.3.1}/tests/test_audit_suite_runtime_drift.py +0 -0
  78. {dkx-2.3.0 → dkx-2.3.1}/tests/test_batch.py +0 -0
  79. {dkx-2.3.0 → dkx-2.3.1}/tests/test_benchmark_artifact_policy.py +0 -0
  80. {dkx-2.3.0 → dkx-2.3.1}/tests/test_benchmark_doc_claims.py +0 -0
  81. {dkx-2.3.0 → dkx-2.3.1}/tests/test_bootstrap_objective.py +0 -0
  82. {dkx-2.3.0 → dkx-2.3.1}/tests/test_bounce_averaged.py +0 -0
  83. {dkx-2.3.0 → dkx-2.3.1}/tests/test_classical_transport_physics_gates.py +0 -0
  84. {dkx-2.3.0 → dkx-2.3.1}/tests/test_cli_solve_mode.py +0 -0
  85. {dkx-2.3.0 → dkx-2.3.1}/tests/test_cli_validation_io_fast_coverage.py +0 -0
  86. {dkx-2.3.0 → dkx-2.3.1}/tests/test_coarse_precond_constants.py +0 -0
  87. {dkx-2.3.0 → dkx-2.3.1}/tests/test_collision_physics_gates.py +0 -0
  88. {dkx-2.3.0 → dkx-2.3.1}/tests/test_collisionality_artifact.py +0 -0
  89. {dkx-2.3.0 → dkx-2.3.1}/tests/test_collisions_improved_sugama.py +0 -0
  90. {dkx-2.3.0 → dkx-2.3.1}/tests/test_collocation.py +0 -0
  91. {dkx-2.3.0 → dkx-2.3.1}/tests/test_compare_reference_corruption.py +0 -0
  92. {dkx-2.3.0 → dkx-2.3.1}/tests/test_compilation_cache_is_not_size_capped.py +0 -0
  93. {dkx-2.3.0 → dkx-2.3.1}/tests/test_create_production_benchmark_inputs.py +0 -0
  94. {dkx-2.3.0 → dkx-2.3.1}/tests/test_data_fetch.py +0 -0
  95. {dkx-2.3.0 → dkx-2.3.1}/tests/test_domain_package_import_contracts.py +0 -0
  96. {dkx-2.3.0 → dkx-2.3.1}/tests/test_drift_kinetic.py +0 -0
  97. {dkx-2.3.0 → dkx-2.3.1}/tests/test_environment_guard.py +0 -0
  98. {dkx-2.3.0 → dkx-2.3.1}/tests/test_er.py +0 -0
  99. {dkx-2.3.0 → dkx-2.3.1}/tests/test_er_scan_and_ambipolar.py +0 -0
  100. {dkx-2.3.0 → dkx-2.3.1}/tests/test_er_trajectory_sweep.py +0 -0
  101. {dkx-2.3.0 → dkx-2.3.1}/tests/test_er_trajectory_sweep_artifact.py +0 -0
  102. {dkx-2.3.0 → dkx-2.3.1}/tests/test_example_docstrings_stay_short.py +0 -0
  103. {dkx-2.3.0 → dkx-2.3.1}/tests/test_example_qa_bootstrap.py +0 -0
  104. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_bootstrap_dkx.py +0 -0
  105. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_optimization.py +0 -0
  106. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_pedagogic.py +0 -0
  107. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_tree_contract.py +0 -0
  108. {dkx-2.3.0 → dkx-2.3.1}/tests/test_examples_tutorials.py +0 -0
  109. {dkx-2.3.0 → dkx-2.3.1}/tests/test_export_f_canonical_parity.py +0 -0
  110. {dkx-2.3.0 → dkx-2.3.1}/tests/test_figure_provenance.py +0 -0
  111. {dkx-2.3.0 → dkx-2.3.1}/tests/test_finite_beta_vmec_example.py +0 -0
  112. {dkx-2.3.0 → dkx-2.3.1}/tests/test_float64_single_owner.py +0 -0
  113. {dkx-2.3.0 → dkx-2.3.1}/tests/test_fokker_planck_phi1_reduces_to_no_phi1.py +0 -0
  114. {dkx-2.3.0 → dkx-2.3.1}/tests/test_fortran_mpi_wrapper.py +0 -0
  115. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_autodiff_sensitivity_validation.py +0 -0
  116. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_fortran_suite_benchmark_summary.py +0 -0
  117. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_readme_fast_branch_audit.py +0 -0
  118. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_sfincs_paper_figs.py +0 -0
  119. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_validation_dashboard.py +0 -0
  120. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generate_w7x_high_nu_performance.py +0 -0
  121. {dkx-2.3.0 → dkx-2.3.1}/tests/test_generated_deck_coverage.py +0 -0
  122. {dkx-2.3.0 → dkx-2.3.1}/tests/test_geometry_scheme11_parity.py +0 -0
  123. {dkx-2.3.0 → dkx-2.3.1}/tests/test_getting_started_examples.py +0 -0
  124. {dkx-2.3.0 → dkx-2.3.1}/tests/test_gpu_solver_path_artifacts.py +0 -0
  125. {dkx-2.3.0 → dkx-2.3.1}/tests/test_h5_parity.py +0 -0
  126. {dkx-2.3.0 → dkx-2.3.1}/tests/test_helper_module_coverage.py +0 -0
  127. {dkx-2.3.0 → dkx-2.3.1}/tests/test_impurity.py +0 -0
  128. {dkx-2.3.0 → dkx-2.3.1}/tests/test_input_compat.py +0 -0
  129. {dkx-2.3.0 → dkx-2.3.1}/tests/test_input_namelist_writer.py +0 -0
  130. {dkx-2.3.0 → dkx-2.3.1}/tests/test_inputs_console.py +0 -0
  131. {dkx-2.3.0 → dkx-2.3.1}/tests/test_jax_geometry_adapters.py +0 -0
  132. {dkx-2.3.0 → dkx-2.3.1}/tests/test_kinetic_operator_fortran_parity.py +0 -0
  133. {dkx-2.3.0 → dkx-2.3.1}/tests/test_magnetic_drift_diagonal.py +0 -0
  134. {dkx-2.3.0 → dkx-2.3.1}/tests/test_magnetic_drifts_parity.py +0 -0
  135. {dkx-2.3.0 → dkx-2.3.1}/tests/test_magnetic_geometry.py +0 -0
  136. {dkx-2.3.0 → dkx-2.3.1}/tests/test_momentum_correction.py +0 -0
  137. {dkx-2.3.0 → dkx-2.3.1}/tests/test_monoenergetic_database.py +0 -0
  138. {dkx-2.3.0 → dkx-2.3.1}/tests/test_multigrid.py +0 -0
  139. {dkx-2.3.0 → dkx-2.3.1}/tests/test_namelist.py +0 -0
  140. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_comparison.py +0 -0
  141. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_evidence.py +0 -0
  142. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_ladder.py +0 -0
  143. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_neoclassical_objectives.py +0 -0
  144. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_promotion.py +0 -0
  145. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_public_scripts_cli.py +0 -0
  146. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_real_artifacts.py +0 -0
  147. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_wave3_coverage.py +0 -0
  148. {dkx-2.3.0 → dkx-2.3.1}/tests/test_optimization_workflow.py +0 -0
  149. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_coordinate_physics_gates.py +0 -0
  150. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_formats.py +0 -0
  151. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_constraintscheme34_parity.py +0 -0
  152. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_magdrift_schemes_parity.py +0 -0
  153. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_nonstelsym_vmec_scheme5_parity.py +0 -0
  154. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme11_parity.py +0 -0
  155. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme13_parity.py +0 -0
  156. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme1_parity.py +0 -0
  157. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme2_parity.py +0 -0
  158. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme4_parity.py +0 -0
  159. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme4_quick2species_parity.py +0 -0
  160. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_scheme5_parity.py +0 -0
  161. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_h5_xgrid_schemes_parity.py +0 -0
  162. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_key_coverage_regressions.py +0 -0
  163. {dkx-2.3.0 → dkx-2.3.1}/tests/test_output_npz_canonical_parity.py +0 -0
  164. {dkx-2.3.0 → dkx-2.3.1}/tests/test_package_metadata.py +0 -0
  165. {dkx-2.3.0 → dkx-2.3.1}/tests/test_paper_benchmark_bootstrap_loop.py +0 -0
  166. {dkx-2.3.0 → dkx-2.3.1}/tests/test_paper_benchmark_electron_root.py +0 -0
  167. {dkx-2.3.0 → dkx-2.3.1}/tests/test_paper_benchmark_monoenergetic.py +0 -0
  168. {dkx-2.3.0 → dkx-2.3.1}/tests/test_paper_benchmark_w7x_ambipolar.py +0 -0
  169. {dkx-2.3.0 → dkx-2.3.1}/tests/test_phase_space.py +0 -0
  170. {dkx-2.3.0 → dkx-2.3.1}/tests/test_phase_timing.py +0 -0
  171. {dkx-2.3.0 → dkx-2.3.1}/tests/test_phi1.py +0 -0
  172. {dkx-2.3.0 → dkx-2.3.1}/tests/test_plot_pdf_paging_is_documented_correctly.py +0 -0
  173. {dkx-2.3.0 → dkx-2.3.1}/tests/test_plotting.py +0 -0
  174. {dkx-2.3.0 → dkx-2.3.1}/tests/test_preconditioner_xi_semantics.py +0 -0
  175. {dkx-2.3.0 → dkx-2.3.1}/tests/test_profile_write_output_trace.py +0 -0
  176. {dkx-2.3.0 → dkx-2.3.1}/tests/test_profiling.py +0 -0
  177. {dkx-2.3.0 → dkx-2.3.1}/tests/test_profiling_helpers.py +0 -0
  178. {dkx-2.3.0 → dkx-2.3.1}/tests/test_public_docs_wording_contract.py +0 -0
  179. {dkx-2.3.0 → dkx-2.3.1}/tests/test_public_facades_and_paths.py +0 -0
  180. {dkx-2.3.0 → dkx-2.3.1}/tests/test_readme_quickstart_runs.py +0 -0
  181. {dkx-2.3.0 → dkx-2.3.1}/tests/test_reference_goldens_lightweight.py +0 -0
  182. {dkx-2.3.0 → dkx-2.3.1}/tests/test_release_gate_metadata.py +0 -0
  183. {dkx-2.3.0 → dkx-2.3.1}/tests/test_remaining_public_contracts.py +0 -0
  184. {dkx-2.3.0 → dkx-2.3.1}/tests/test_repo_size_policy.py +0 -0
  185. {dkx-2.3.0 → dkx-2.3.1}/tests/test_representative.py +0 -0
  186. {dkx-2.3.0 → dkx-2.3.1}/tests/test_representative_run_works_when_installed.py +0 -0
  187. {dkx-2.3.0 → dkx-2.3.1}/tests/test_research_lane_policy.py +0 -0
  188. {dkx-2.3.0 → dkx-2.3.1}/tests/test_rhsmode1_current_closure.py +0 -0
  189. {dkx-2.3.0 → dkx-2.3.1}/tests/test_rhsmode1_phi1_write_output_end_to_end.py +0 -0
  190. {dkx-2.3.0 → dkx-2.3.1}/tests/test_rhsmode1_write_output_end_to_end.py +0 -0
  191. {dkx-2.3.0 → dkx-2.3.1}/tests/test_rosenbluth_quadrature.py +0 -0
  192. {dkx-2.3.0 → dkx-2.3.1}/tests/test_run_function_is_not_shadowed_by_run_module.py +0 -0
  193. {dkx-2.3.0 → dkx-2.3.1}/tests/test_run_rhsmode1.py +0 -0
  194. {dkx-2.3.0 → dkx-2.3.1}/tests/test_run_transport.py +0 -0
  195. {dkx-2.3.0 → dkx-2.3.1}/tests/test_runtime_helper_coverage.py +0 -0
  196. {dkx-2.3.0 → dkx-2.3.1}/tests/test_scans_progress_and_recycle.py +0 -0
  197. {dkx-2.3.0 → dkx-2.3.1}/tests/test_sensitivity.py +0 -0
  198. {dkx-2.3.0 → dkx-2.3.1}/tests/test_shaing_callen.py +0 -0
  199. {dkx-2.3.0 → dkx-2.3.1}/tests/test_solver_path_artifacts.py +0 -0
  200. {dkx-2.3.0 → dkx-2.3.1}/tests/test_solver_trace.py +0 -0
  201. {dkx-2.3.0 → dkx-2.3.1}/tests/test_solver_trace_canonical_parity.py +0 -0
  202. {dkx-2.3.0 → dkx-2.3.1}/tests/test_source_tree_consolidation.py +0 -0
  203. {dkx-2.3.0 → dkx-2.3.1}/tests/test_sparse_precond.py +0 -0
  204. {dkx-2.3.0 → dkx-2.3.1}/tests/test_species_constants.py +0 -0
  205. {dkx-2.3.0 → dkx-2.3.1}/tests/test_tier1_refinement.py +0 -0
  206. {dkx-2.3.0 → dkx-2.3.1}/tests/test_tier2_memory_guard.py +0 -0
  207. {dkx-2.3.0 → dkx-2.3.1}/tests/test_transport_matrix_write_output_end_to_end.py +0 -0
  208. {dkx-2.3.0 → dkx-2.3.1}/tests/test_units.py +0 -0
  209. {dkx-2.3.0 → dkx-2.3.1}/tests/test_upstream_scanplot2_smoke.py +0 -0
  210. {dkx-2.3.0 → dkx-2.3.1}/tests/test_utils_smoke.py +0 -0
  211. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_artifacts.py +0 -0
  212. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_deferred_lane_gates.py +0 -0
  213. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_figures.py +0 -0
  214. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_manifest_schema.py +0 -0
  215. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_math.py +0 -0
  216. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_petsc_and_upstream_helpers.py +0 -0
  217. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validation_policy_coverage.py +0 -0
  218. {dkx-2.3.0 → dkx-2.3.1}/tests/test_validity.py +0 -0
  219. {dkx-2.3.0 → dkx-2.3.1}/tests/test_variational_bounds.py +0 -0
  220. {dkx-2.3.0 → dkx-2.3.1}/tests/test_vmec_wout_ascii.py +0 -0
  221. {dkx-2.3.0 → dkx-2.3.1}/tests/test_vmec_wout_conventions.py +0 -0
  222. {dkx-2.3.0 → dkx-2.3.1}/tests/test_vmex_workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkx
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Neoclassical transport solver with CPU/GPU and differentiable JAX workflows
5
5
  Project-URL: Homepage, https://github.com/uwplasma/DKX
6
6
  Project-URL: Documentation, https://sfincs-jax.readthedocs.io/
@@ -393,4 +393,4 @@ __all__ = [
393
393
  "write_output",
394
394
  ]
395
395
 
396
- __version__ = "2.3.0"
396
+ __version__ = "2.3.1"
@@ -976,6 +976,144 @@ def materialize_dense(
976
976
  cols.append(np.asarray(batched(basis)))
977
977
  return np.concatenate(cols, axis=1)
978
978
 
979
+
980
+ def _escalate_after_tier2_stall(
981
+ op: KineticOperator,
982
+ rhs2d: jnp.ndarray,
983
+ *,
984
+ stalled: SolveResult,
985
+ tol: float,
986
+ atol: float,
987
+ x0,
988
+ recycle,
989
+ preconditioner: str,
990
+ drop_l_coupling_in_precond: bool,
991
+ restart: int,
992
+ recycle_dim: int,
993
+ max_restarts: int,
994
+ check_adjoint: bool,
995
+ adjoint_residual_factor: float,
996
+ max_dense_size: int,
997
+ ) -> SolveResult:
998
+ """Work through the remedies a user would otherwise have to know about.
999
+
1000
+ A stalled Krylov solve is a *preconditioner* problem, not a reason to
1001
+ change solver tier, and this is where DKX used to get it backwards: it
1002
+ announced a fall back to the tier-3 host direct solve, which obtains its
1003
+ matrix by applying the operator to ``n`` identity columns. At the sizes
1004
+ where tier 2 actually stalls that is hopeless -- a 66004-DOF deck needs
1005
+ 66004 matvecs and O(n^2) memory -- so the guard in :func:`_solve_tier3`
1006
+ refused, and a convergence problem surfaced as a hard crash telling the
1007
+ user to raise ``max_dense_size``. Taking that advice would have tried to
1008
+ allocate 32.5 GB.
1009
+
1010
+ SFINCS Fortran v3 does not have this failure mode, and the reason is worth
1011
+ stating because it dictates the order below. It assembles the simplified
1012
+ preconditioner matrix *analytically and sparsely*, factorizes it with a
1013
+ sparse direct LU (MUMPS or SuperLU_dist), and preconditions GMRES with
1014
+ that -- so its "direct solve" is a sparse factorization that handles 66004
1015
+ routinely, and GMRES needs few iterations on top of it. It also retries
1016
+ automatically, doubling the MUMPS working-memory factor on a failed
1017
+ factorization (``solver.F90``: ``mumps_icntl_14 = mumps_icntl_14 * 2``).
1018
+
1019
+ DKX already owns the equivalent of that preconditioner -- ``"sparse"``
1020
+ eliminates in a fill-reducing order and keeps the inverse exact -- and the
1021
+ stall above happened without ever trying it. So the ladder escalates the
1022
+ preconditioner first, in increasing cost, and only considers tier 3 at a
1023
+ size where tier 3 can actually run.
1024
+
1025
+ Returns the first converged result, or the best (lowest final residual) if
1026
+ none converges, so a caller that can tolerate a loose solve still gets the
1027
+ best available answer along with an honest ``converged=False``.
1028
+ """
1029
+ attempts: list[tuple[str, SolveResult]] = [(f"{preconditioner} preconditioner", stalled)]
1030
+
1031
+ def _residual(result: SolveResult) -> float:
1032
+ norms = np.asarray(result.residual_norms)
1033
+ return float(norms[-1]) if norms.size else float("inf")
1034
+
1035
+ print(
1036
+ f"[dkx.solve] tier-2 Krylov stalled with the {preconditioner} "
1037
+ f"preconditioner (iterations={stalled.iterations}, residual="
1038
+ f"{_residual(stalled):.3e}); escalating rather than giving up."
1039
+ )
1040
+
1041
+ # Rung 1: the strong preconditioner. This is the SFINCS analogue and the
1042
+ # single most likely fix, because "coarse" eliminates L first, which fills
1043
+ # the angular stencils in, while "sparse" eliminates in a fill-reducing
1044
+ # order and stays sparse.
1045
+ for kind in ("sparse", "multigrid"):
1046
+ if kind == preconditioner:
1047
+ continue
1048
+ try:
1049
+ print(f"[dkx.solve] retrying tier 2 with the {kind} preconditioner ...")
1050
+ candidate = _solve_tier2(
1051
+ op, rhs2d, tol=tol, atol=atol, x0=x0, recycle=recycle,
1052
+ preconditioner=kind,
1053
+ drop_l_coupling_in_precond=drop_l_coupling_in_precond,
1054
+ restart=restart, recycle_dim=recycle_dim,
1055
+ max_restarts=max_restarts, differentiable=False,
1056
+ check_adjoint=check_adjoint,
1057
+ adjoint_residual_factor=adjoint_residual_factor,
1058
+ )
1059
+ except Exception as exc: # a preconditioner that cannot build is a rung, not a failure
1060
+ print(f"[dkx.solve] {kind} preconditioner unavailable: {exc}")
1061
+ continue
1062
+ attempts.append((f"{kind} preconditioner", candidate))
1063
+ if candidate.converged:
1064
+ print(f"[dkx.solve] converged with the {kind} preconditioner.")
1065
+ return candidate
1066
+
1067
+ # Rung 2: more iterations. Cheap to ask for, and the remedy when the
1068
+ # preconditioner is adequate but the cap was simply too low for this Er.
1069
+ widened = max(max_restarts * 4, max_restarts + 1)
1070
+ best_kind = max(attempts, key=lambda item: -_residual(item[1]))[0].split()[0]
1071
+ if best_kind not in _TIER2_PRECONDITIONERS:
1072
+ best_kind = preconditioner
1073
+ try:
1074
+ print(
1075
+ f"[dkx.solve] retrying tier 2 with the {best_kind} preconditioner "
1076
+ f"and {widened} restarts (was {max_restarts}) ..."
1077
+ )
1078
+ candidate = _solve_tier2(
1079
+ op, rhs2d, tol=tol, atol=atol, x0=x0, recycle=recycle,
1080
+ preconditioner=best_kind,
1081
+ drop_l_coupling_in_precond=drop_l_coupling_in_precond,
1082
+ restart=restart, recycle_dim=recycle_dim,
1083
+ max_restarts=widened, differentiable=False,
1084
+ check_adjoint=check_adjoint,
1085
+ adjoint_residual_factor=adjoint_residual_factor,
1086
+ )
1087
+ attempts.append((f"{best_kind} preconditioner, {widened} restarts", candidate))
1088
+ if candidate.converged:
1089
+ print("[dkx.solve] converged with the widened iteration budget.")
1090
+ return candidate
1091
+ except Exception as exc:
1092
+ print(f"[dkx.solve] widened retry failed: {exc}")
1093
+
1094
+ # Rung 3: tier 3, but only where it can actually run. Announcing a
1095
+ # fallback that the size guard will refuse is what produced the original
1096
+ # crash, so the size is checked here rather than discovered downstream.
1097
+ if op.total_size <= max_dense_size:
1098
+ print("[dkx.solve] falling back to the tier-3 host direct solve ...")
1099
+ return _solve_tier3(op, rhs2d, tol=tol, atol=atol, max_dense_size=max_dense_size)
1100
+
1101
+ best_label, best = min(attempts, key=lambda item: _residual(item[1]))
1102
+ dense_gb = op.total_size**2 * 8 / 1024**3
1103
+ raise RuntimeError(
1104
+ f"the linear solve did not converge at total_size={op.total_size}.\n"
1105
+ f"Tried: {'; '.join(label for label, _ in attempts)}.\n"
1106
+ f"Best final residual {_residual(best):.3e} ({best_label}), tolerance {tol:.1e}.\n"
1107
+ "Tier 3 was not attempted: it materializes the operator column by "
1108
+ f"column, which at this size needs {op.total_size} matvecs and "
1109
+ f"{dense_gb:.1f} GB, so raising max_dense_size would not help.\n"
1110
+ "What usually does help, in order: lower the collisionality-scaled Er "
1111
+ "(stalls cluster at the largest |Er|, where the ExB term dominates); "
1112
+ "raise solverTolerance; or reduce Nxi/Ntheta/Nzeta at the offending "
1113
+ "point. Pass solver=SolverOptions(...) to control this directly."
1114
+ )
1115
+
1116
+
979
1117
  def _solve_tier3(
980
1118
  op: KineticOperator, rhs2d: jnp.ndarray, *, tol: float, atol: float, max_dense_size: int
981
1119
  ) -> SolveResult:
@@ -2085,13 +2223,23 @@ def solve(
2085
2223
  adjoint_residual_factor=adjoint_residual_factor,
2086
2224
  )
2087
2225
  if method == "auto" and not result.converged and not differentiable:
2088
- print(
2089
- "[dkx.solve] tier-2 Krylov breached its iteration cap "
2090
- f"(iterations={result.iterations}); falling back to the tier-3 "
2091
- "host direct solve."
2092
- )
2093
- result = _solve_tier3(
2094
- op, rhs2d, tol=tol, atol=atol, max_dense_size=max_dense_size
2226
+ requested = _resolve_preconditioner(preconditioner, use_preconditioner)
2227
+ result = _escalate_after_tier2_stall(
2228
+ op,
2229
+ rhs2d,
2230
+ stalled=result,
2231
+ tol=tol,
2232
+ atol=atol,
2233
+ x0=x0,
2234
+ recycle=recycle,
2235
+ preconditioner=requested,
2236
+ drop_l_coupling_in_precond=drop_l_coupling_in_precond,
2237
+ restart=restart,
2238
+ recycle_dim=recycle_dim,
2239
+ max_restarts=max_restarts,
2240
+ check_adjoint=check_adjoint,
2241
+ adjoint_residual_factor=adjoint_residual_factor,
2242
+ max_dense_size=max_dense_size,
2095
2243
  )
2096
2244
  else: # direct
2097
2245
  if differentiable:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkx
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Neoclassical transport solver with CPU/GPU and differentiable JAX workflows
5
5
  Project-URL: Homepage, https://github.com/uwplasma/DKX
6
6
  Project-URL: Documentation, https://sfincs-jax.readthedocs.io/
@@ -188,6 +188,7 @@ tests/test_run_function_is_not_shadowed_by_run_module.py
188
188
  tests/test_run_rhsmode1.py
189
189
  tests/test_run_transport.py
190
190
  tests/test_runtime_helper_coverage.py
191
+ tests/test_scan_survives_a_failing_point.py
191
192
  tests/test_scans_progress_and_recycle.py
192
193
  tests/test_sensitivity.py
193
194
  tests/test_shaing_callen.py
@@ -200,6 +201,7 @@ tests/test_sparse_precond.py
200
201
  tests/test_species_constants.py
201
202
  tests/test_tier1_refinement.py
202
203
  tests/test_tier2_memory_guard.py
204
+ tests/test_tier2_stall_escalates_instead_of_crashing.py
203
205
  tests/test_transport_matrix_write_output_end_to_end.py
204
206
  tests/test_units.py
205
207
  tests/test_upstream_scanplot2_smoke.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dkx"
7
- version = "2.3.0"
7
+ version = "2.3.1"
8
8
  description = "Neoclassical transport solver with CPU/GPU and differentiable JAX workflows"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -30,8 +30,13 @@ def test_workflow_browser_filters_by_physics_topic() -> None:
30
30
  vmec_geometry = module._matching_workflows(catalog, topic="vmec", search="geometry")
31
31
  assert {workflow["id"] for workflow in vmec_geometry} >= {"vmec_wout_path", "vmec_boozer_jax_pipeline"}
32
32
 
33
- gpu = module._matching_workflows(catalog, topic="gpu", search="")
34
- assert {workflow["id"] for workflow in gpu} >= {"output_format_benchmark"}
33
+ # There is no "gpu" topic any more: its only workflow was the
34
+ # output-format benchmark, which moved to tools/performance/ along with the
35
+ # rest of the maintainer tooling. The catalog indexes examples, and that
36
+ # script stopped being one.
37
+ transport = module._matching_workflows(catalog, topic="transport", search="")
38
+ assert {workflow["id"] for workflow in transport} >= {"transport_matrix"}
39
+ assert module._matching_workflows(catalog, topic="gpu", search="") == []
35
40
 
36
41
 
37
42
  def test_workflow_browser_json_cli_is_machine_readable() -> None:
@@ -0,0 +1,108 @@
1
+ """One unsolvable scan point must not discard the rest of the scan.
2
+
3
+ Reported from a scanType=5 run: tier-2 stalled at the largest |Er| on a
4
+ 66004-DOF deck, the exception propagated out of ``run_dkx``, and every
5
+ remaining Er point at that radius was lost. One radius folder finished with
6
+ zero of a hundred outputs, another with three. The loss was silent, and it
7
+ also stranded the process inside the failed run's directory, because the
8
+ scan loops ``chdir`` back only *after* the solve returns.
9
+
10
+ A point that will not solve is information, not a reason to throw away the
11
+ other ninety-nine.
12
+ """
13
+
14
+ import importlib.util
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ import pytest
19
+
20
+ UTILS = Path(__file__).resolve().parents[1] / "examples" / "sfincs_examples" / "utils"
21
+ SCAN_SCRIPTS = ("sfincsScan_1", "sfincsScan_2", "sfincsScan_3",
22
+ "sfincsScan_4", "sfincsScan_21", "sfincsScan_22")
23
+
24
+
25
+ def _load_common(tmp_path, monkeypatch):
26
+ """Exec sfincsScan_common the way sfincsScan does, in its own namespace."""
27
+ monkeypatch.syspath_prepend(str(UTILS))
28
+ namespace: dict = {"__file__": str(UTILS / "sfincsScan_common")}
29
+ exec((UTILS / "sfincsScan_common").read_text(), namespace) # noqa: S102
30
+ return namespace
31
+
32
+
33
+ def test_a_failing_point_is_recorded_and_the_scan_continues(tmp_path, monkeypatch):
34
+ ns = _load_common(tmp_path, monkeypatch)
35
+ run_scan_point = ns["run_scan_point"]
36
+
37
+ # Stand in for dkx_driver: fail only the third point, as a stalled solve
38
+ # would, and succeed on the rest.
39
+ calls = []
40
+
41
+ class _FakeDriver:
42
+ @staticmethod
43
+ def run_dkx(*, input_namelist, output_path, **kwargs):
44
+ calls.append(Path(output_path).parent.name)
45
+ if Path(output_path).parent.name == "Er3":
46
+ raise RuntimeError("the linear solve did not converge at total_size=66004")
47
+ Path(output_path).write_text("ok")
48
+
49
+ monkeypatch.setitem(sys.modules, "dkx_driver", _FakeDriver)
50
+
51
+ ok = []
52
+ for i in range(5):
53
+ directory = tmp_path / f"Er{i + 1}"
54
+ directory.mkdir()
55
+ (directory / "input.namelist").write_text("&general\n/\n")
56
+ ok.append(
57
+ run_scan_point(
58
+ input_namelist=directory / "input.namelist",
59
+ output_path=directory / "sfincsOutput.h5",
60
+ directory=directory.name,
61
+ )
62
+ )
63
+
64
+ # Every point was attempted, not just the ones before the failure.
65
+ assert len(calls) == 5
66
+ assert ok == [True, True, False, True, True]
67
+
68
+ # The four that solved have output; the one that did not is marked.
69
+ assert (tmp_path / "Er4" / "sfincsOutput.h5").is_file()
70
+ assert not (tmp_path / "Er3" / "sfincsOutput.h5").exists()
71
+ marker = tmp_path / "Er3" / ns["FAILURE_MARKER"]
72
+ assert marker.is_file()
73
+ assert "did not converge" in marker.read_text()
74
+
75
+ assert ns["report_scan_failures"]() == 1
76
+
77
+
78
+ def test_keyboard_interrupt_still_stops_the_scan(tmp_path, monkeypatch):
79
+ """Catching solver failures must not swallow the user pressing Ctrl-C."""
80
+ ns = _load_common(tmp_path, monkeypatch)
81
+
82
+ class _Interrupting:
83
+ @staticmethod
84
+ def run_dkx(**kwargs):
85
+ raise KeyboardInterrupt
86
+
87
+ monkeypatch.setitem(sys.modules, "dkx_driver", _Interrupting)
88
+ directory = tmp_path / "Er1"
89
+ directory.mkdir()
90
+ with pytest.raises(KeyboardInterrupt):
91
+ ns["run_scan_point"](
92
+ input_namelist=directory / "input.namelist",
93
+ output_path=directory / "sfincsOutput.h5",
94
+ directory="Er1",
95
+ )
96
+
97
+
98
+ @pytest.mark.parametrize("script", SCAN_SCRIPTS)
99
+ def test_every_scan_type_uses_the_resilient_helper(script: str) -> None:
100
+ """A raw run_dkx call in a scan loop is the bug returning."""
101
+ text = (UTILS / script).read_text()
102
+ assert "run_scan_point(" in text, f"{script} does not use the resilient helper"
103
+ body = "\n".join(
104
+ line for line in text.splitlines() if not line.lstrip().startswith("#")
105
+ )
106
+ assert " run_dkx(" not in body and " run_dkx(" not in body, (
107
+ f"{script} still calls run_dkx directly, so one bad point aborts the scan"
108
+ )
@@ -514,16 +514,23 @@ def test_tier1_refuses_er_xdot_l2_coupling() -> None:
514
514
  assert not ok
515
515
 
516
516
 
517
- def test_auto_policy_tier3_fallback_on_iteration_cap() -> None:
517
+ def test_auto_policy_recovers_a_starved_tier2_solve() -> None:
518
518
  # Starve tier 2 (no preconditioner, tiny restart budget) on the FP
519
- # fixture: the auto policy must breach the cap loudly and land on the
520
- # tier-3 host direct solve, which still returns the right answer.
519
+ # fixture: the auto policy must recover and still return the right answer.
520
+ #
521
+ # This used to assert result.method == "direct", because a cap breach fell
522
+ # straight to the tier-3 host solve. That fallback is a dead end at any
523
+ # real size -- tier 3 materializes the operator column by column, so a
524
+ # 66004-DOF deck would need 66004 matvecs -- and a user hit exactly that,
525
+ # losing a whole radius of an Er scan to the crash. A stalled Krylov solve
526
+ # is a preconditioner problem, so the policy now escalates the
527
+ # preconditioner first and only reaches tier 3 where tier 3 can run. What
528
+ # matters is that a starved solve still lands on the correct answer.
521
529
  op = _load_op("quick_2species_FPCollisions_noEr")
522
530
  rhs = op.rhs()
523
531
  result = solve(
524
532
  op, rhs, method="auto", tol=1e-10, use_preconditioner=False, max_restarts=2
525
533
  )
526
- assert result.method == "direct"
527
534
  assert result.converged
528
535
  x_ref = _dense_solve(op, np.asarray(rhs)[:, None])[:, 0]
529
536
  assert _rel_err(np.asarray(result.x), x_ref) < 1e-8
@@ -0,0 +1,101 @@
1
+ """A stalled Krylov solve must escalate, not crash on a fallback that cannot run.
2
+
3
+ Reported from a scanType=5 run (Er scan inside a radius scan) on a 66004-DOF
4
+ deck. Tier-2 GCROT hit its iteration cap at the largest |Er|, DKX announced a
5
+ fall back to the tier-3 host direct solve, and tier 3 refused immediately
6
+ because 66004 > max_dense_size=8192. The RuntimeError propagated out through
7
+ the scan driver and killed every remaining Er point at that radius: one radius
8
+ folder finished with zero outputs, another with three of a hundred.
9
+
10
+ Tier 3 obtains its matrix by applying the operator to n identity columns, so
11
+ at the sizes where tier 2 actually stalls it can never run -- the advice in the
12
+ old message, to raise max_dense_size, would have asked for 32.5 GB. A stalled
13
+ Krylov solve is a preconditioner problem, and DKX already ships the strong
14
+ preconditioner (``sparse``) that SFINCS's MUMPS LU is the analogue of; it was
15
+ simply never tried.
16
+ """
17
+
18
+ import numpy as np
19
+ import pytest
20
+
21
+ import dkx
22
+ from dkx.solve import SolveResult, _escalate_after_tier2_stall
23
+
24
+ CASE = dict(
25
+ geometryScheme=1, inputRadialCoordinate=3, rN_wish=0.3,
26
+ B0OverBBar=1.0, epsilon_t=-0.07, epsilon_h=0.0, iota=0.4542,
27
+ GHat=3.7481, IHat=0.0, psiAHat=0.15596, aHat=0.5585,
28
+ Zs=[1.0], mHats=[1.0], nHats=[1.0], THats=[1.0],
29
+ dNHatdrHats=[-0.5], dTHatdrHats=[-1.0],
30
+ Ntheta=9, Nzeta=1, Nxi=8, NL=4, Nx=4,
31
+ collisionOperator=1, Delta=4.5694e-3, alpha=1.0, nu_n=0.01,
32
+ )
33
+
34
+
35
+ def _operator():
36
+ return dkx.run(**CASE).operator
37
+
38
+
39
+ def _stalled(op) -> SolveResult:
40
+ """What tier 2 hands back when it breaches its cap."""
41
+ return SolveResult(
42
+ x=np.zeros((op.total_size, 1)),
43
+ method="gmres",
44
+ iterations=6000,
45
+ residual_norms=np.asarray([1.0, 0.5, 0.2]),
46
+ converged=False,
47
+ recycle=None,
48
+ timings={},
49
+ adjoint=None,
50
+ )
51
+
52
+
53
+ def _rhs2d(op):
54
+ """Tier 2 works in (n, nrhs); op.rhs() is (n,), as solve() reshapes it."""
55
+ return np.asarray(op.rhs()).reshape(op.total_size, -1)
56
+
57
+
58
+ def _escalate(op, **overrides):
59
+ kwargs = dict(
60
+ stalled=_stalled(op), tol=1e-10, atol=0.0, x0=None, recycle=None,
61
+ preconditioner="coarse", drop_l_coupling_in_precond=False,
62
+ restart=20, recycle_dim=8, max_restarts=200,
63
+ check_adjoint=False, adjoint_residual_factor=1e3,
64
+ max_dense_size=8192,
65
+ )
66
+ kwargs.update(overrides)
67
+ return _escalate_after_tier2_stall(op, _rhs2d(op), **kwargs)
68
+
69
+
70
+ def test_escalation_recovers_a_stalled_solve() -> None:
71
+ """The ladder must actually produce a converged answer, not just try."""
72
+ op = _operator()
73
+ result = _escalate(op)
74
+ assert result.converged, "escalation should recover a solvable system"
75
+ assert float(np.asarray(result.residual_norms)[-1]) < 1e-8
76
+
77
+
78
+ def test_a_deck_too_large_for_tier3_reports_the_real_problem() -> None:
79
+ """The failure the user hit: n > max_dense_size, so tier 3 cannot help.
80
+
81
+ The message must not send them to max_dense_size, and must name what was
82
+ tried and what actually helps.
83
+ """
84
+ op = _operator()
85
+ with pytest.raises(RuntimeError) as excinfo:
86
+ # Force every rung to fail by demanding a tolerance nothing can meet,
87
+ # with tier 3 excluded exactly as it is at 66004 DOFs.
88
+ _escalate(op, tol=1e-300, max_dense_size=1)
89
+ message = str(excinfo.value)
90
+ assert "did not converge" in message
91
+ assert "Tried:" in message
92
+ assert "raising max_dense_size would not help" in message
93
+ assert "Er" in message, "the remedy that matters should name the Er dependence"
94
+
95
+
96
+ def test_the_old_misleading_advice_is_gone() -> None:
97
+ """`raise max_dense_size explicitly` at 66004 DOFs asks for 32.5 GB."""
98
+ op = _operator()
99
+ with pytest.raises(RuntimeError) as excinfo:
100
+ _escalate(op, tol=1e-300, max_dense_size=1)
101
+ assert "raise max_dense_size explicitly if you really want this" not in str(excinfo.value)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes