@@ -21,6 +21,8 @@ import {
2121 ModelicaFunctionCallExpression ,
2222 ModelicaNameExpression ,
2323} from "./dae.js" ;
24+ import { type SolverOptions } from "./solver-options.js" ;
25+ import { getCachedSundialsWasm } from "./sundials-wasm.js" ;
2426import { ModelicaVariability } from "./syntax.js" ;
2527
2628/** Result of initial equation solving. */
@@ -246,6 +248,7 @@ export function solveInitialEquations(
246248 startValues : Map < string , number > ,
247249 parameters : Map < string , number > ,
248250 startTime : number ,
251+ solverOptions ?: SolverOptions ,
249252) : InitSolverResult {
250253 const result : InitSolverResult = {
251254 values : new Map ( startValues ) ,
@@ -368,13 +371,55 @@ export function solveInitialEquations(
368371 }
369372
370373 // Newton-Raphson iteration
371- const maxIter = 50 ;
372- const tol = 1e-10 ;
374+ const maxIter = solverOptions ?. maxNonlinearIterations ?? 50 ;
375+ const tol = solverOptions ?. atol ?? 1e-10 ;
373376 const nSolve = Math . min ( nResiduals , nUnknowns ) ; // Square system for Newton
374377
375378 // Initialize z from current env
376379 const z = unknownList . map ( ( name ) => env . get ( name ) ?? 0 ) ;
377380
381+ const useKinsol = solverOptions ?. nonlinear === "kinsol" || solverOptions ?. nonlinear === "hybrid" ;
382+
383+ if ( useKinsol ) {
384+ const solver = getCachedSundialsWasm ( ) ;
385+ if ( ! solver ) {
386+ throw new Error (
387+ "KINSOL solver requested but SUNDIALS WASM module is not loaded. Use simulateAsync() or loadSundialsWasm() first." ,
388+ ) ;
389+ }
390+
391+ const F = ( zArr : number [ ] ) : number [ ] => {
392+ for ( let i = 0 ; i < nUnknowns ; i ++ ) {
393+ const name = unknownList [ i ] ;
394+ if ( name ) env . set ( name , zArr [ i ] ?? 0 ) ;
395+ }
396+ const res = new Array ( nSolve ) ;
397+ for ( let row = 0 ; row < nSolve ; row ++ ) {
398+ const td = tapeData [ row ] ;
399+ if ( ! td ) continue ;
400+ const tArr = evaluateTapeForward ( td . ops , env ) ;
401+ res [ row ] = tArr [ td . outputIndex ] ?? 0 ;
402+ }
403+ return res ;
404+ } ;
405+
406+ const kResult = solver . kinsol ( F , z , { atol : tol , rtol : tol } ) ;
407+ if ( kResult . converged || solverOptions ?. nonlinear === "kinsol" ) {
408+ result . converged = kResult . converged ;
409+ if ( kResult . converged ) {
410+ for ( let i = 0 ; i < nUnknowns ; i ++ ) {
411+ const name = unknownList [ i ] ;
412+ if ( name ) result . values . set ( name , kResult . solution [ i ] ?? 0 ) ;
413+ }
414+ }
415+ if ( ! kResult . converged && solverOptions ?. nonlinear === "hybrid" ) {
416+ // Fall through to Newton-Raphson if hybrid and KINSOL failed
417+ } else {
418+ return result ;
419+ }
420+ }
421+ }
422+
378423 for ( let iter = 0 ; iter < maxIter ; iter ++ ) {
379424 result . iterations = iter + 1 ;
380425
0 commit comments