@@ -458,3 +458,181 @@ function stepStateConstraints!(
458458
459459 return nothing
460460end
461+
462+
463+ """
464+ $(TYPEDSIGNATURES)
465+
466+ Build sparsity pattern for Jacobian of constraints
467+ """
468+ function DOCP_Jacobian_pattern (docp:: DOCP{<: GenericIRKStagewise} )
469+ disc = disc_model (docp)
470+ dims = docp. dims
471+
472+ # vector format for sparse matrix
473+ Is = Vector {Int} (undef, 0 )
474+ Js = Vector {Int} (undef, 0 )
475+
476+ s = disc. stage
477+
478+ # index alias for v
479+ v_start = docp. dim_NLP_variables - dims. NLP_v + 1
480+ v_end = docp. dim_NLP_variables
481+
482+ # 1. main loop over steps
483+ for i in 1 : docp. time. steps
484+
485+ # constraints block and offset: state equation, stage equations, path constraints
486+ c_block = disc. _state_stage_eqs_block + disc. _step_pathcons_block
487+ c_offset = (i- 1 )* c_block
488+ dyn_start = c_offset + 1
489+ dyn_end = c_offset + dims. NLP_x
490+ dyn_lag = c_offset + dims. NLP_x
491+ stage_start = c_offset + dims. NLP_x + 1
492+ stage_end = c_offset + (s+ 1 ) * dims. NLP_x
493+ path_start = c_offset + (s+ 1 ) * dims. NLP_x + 1
494+ path_end = c_offset + c_block
495+
496+ # contiguous variables blocks will be used when possible
497+ # x_i u_ij k_ij x_i+1
498+ var_offset = (i- 1 )* disc. _step_variables_block
499+ xi_start = var_offset + 1
500+ xi_end = var_offset + dims. NLP_x
501+ ui_start = var_offset + dims. NLP_x + 1
502+ ui_end = var_offset + dims. NLP_x + dims. NLP_u* s
503+ ki_start = var_offset + dims. NLP_x + dims. NLP_u* s + 1
504+ ki_end = var_offset + disc. _step_variables_block
505+ xip1_end = var_offset + disc. _step_variables_block + dims. NLP_x
506+
507+ # 1.1 state eq 0 = x_i+1 - (x_i + h_i sum_j b_j k_ij)
508+ # depends on x_i, k_ij, x_i+1, and v for h_i in variable times case !
509+ # skip u_ij; should skip k_i[n+1] also but annoying...
510+ add_nonzero_block! (Is, Js, dyn_start, dyn_end, xi_start, xi_end)
511+ add_nonzero_block! (Is, Js, dyn_start, dyn_end, ki_start, xip1_end)
512+ add_nonzero_block! (Is, Js, dyn_start, dyn_end, v_start, v_end)
513+
514+ # 1.3 stage equations k_ij = f(t_ij, x_ij, u_ij, v)
515+ # with x_ij = x_i + sum_l a_il k_jl
516+ # depends on x_i, u_ij, k_ij, and v; (we could distinguish each j...)
517+ add_nonzero_block! (Is, Js, stage_start, stage_end, xi_start, ki_end)
518+ add_nonzero_block! (Is, Js, stage_start, stage_end, v_start, v_end)
519+
520+ # 1.4 path constraint g(t_i, x_i, u_i, v)
521+ # depends on x_i, u_i (check actual value used), v;
522+ add_nonzero_block! (Is, Js, path_start, path_end, xi_start, ui_end)
523+ add_nonzero_block! (Is, Js, path_start, path_end, v_start, v_end)
524+ end
525+
526+ # 2. final path constraints (xf, uf, v)
527+ c_offset = docp. time. steps * (disc. _state_stage_eqs_block + disc. _step_pathcons_block)
528+ c_block = disc. _step_pathcons_block
529+ var_offset = docp. time. steps* disc. _step_variables_block
530+ xf_start = var_offset + 1
531+ xf_end = var_offset + dims. NLP_x
532+ # NB convention u(tf) = U_N-1
533+ uf_start = var_offset - disc. _step_variables_block + dims. NLP_x + 1
534+ uf_end = var_offset - disc. _step_variables_block + dims. NLP_x + dims. NLP_u* s
535+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, xf_start, xf_end)
536+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, uf_start, uf_end)
537+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, v_start, v_end)
538+
539+ # 3. boundary constraints (x0, xf, v)
540+ c_offset =
541+ docp. time. steps * (disc. _state_stage_eqs_block + disc. _step_pathcons_block) +
542+ disc. _step_pathcons_block
543+ c_block = dims. boundary_cons
544+ x0_start = 1
545+ x0_end = dims. NLP_x
546+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, x0_start, x0_end)
547+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, xf_start, xf_end)
548+ add_nonzero_block! (Is, Js, c_offset+ 1 , c_offset+ c_block, v_start, v_end)
549+ # 3.4 null initial condition for lagrangian cost state l0
550+ if docp. flags. lagrange
551+ add_nonzero_block! (Is, Js, docp. dim_NLP_constraints, dims. NLP_x)
552+ end
553+
554+ # build and return sparse matrix
555+ nnzj = length (Is)
556+ Vs = ones (Bool, nnzj)
557+ return SparseArrays. sparse (Is, Js, Vs, docp. dim_NLP_constraints, docp. dim_NLP_variables)
558+ end
559+
560+ """
561+ $(TYPEDSIGNATURES)
562+
563+ Build sparsity pattern for Hessian of Lagrangian
564+ """
565+ function DOCP_Hessian_pattern (docp:: DOCP{<: GenericIRKStagewise} )
566+ disc = disc_model (docp)
567+ dims = docp. dims
568+
569+ # NB. need to provide full pattern for coloring, not just upper/lower part
570+ Is = Vector {Int} (undef, 0 )
571+ Js = Vector {Int} (undef, 0 )
572+
573+ s = disc. stage
574+
575+ # index alias for v
576+ v_start = docp. dim_NLP_variables - dims. NLP_v + 1
577+ v_end = docp. dim_NLP_variables
578+
579+ # 0. objective
580+ # 0.1 mayer cost (x0, xf, v)
581+ # -> grouped with term 3. for boundary conditions
582+ # 0.2 lagrange case sum h_i l(ti, xi, ui, v)
583+ # -> included in stage equations terms see 1.2
584+
585+ # 1. main loop over steps
586+ # 1.0 v / v term
587+ add_nonzero_block! (Is, Js, v_start, v_end, v_start, v_end)
588+
589+ for i in 1 : docp. time. steps
590+
591+ # contiguous variables blocks will be used when possible
592+ # x_i u_ij k_ij x_i+1
593+ var_offset = (i- 1 )* disc. _step_variables_block
594+ xi_start = var_offset + 1
595+ xi_end = var_offset + dims. NLP_x
596+ ui_start = var_offset + dims. NLP_x + 1
597+ ui_end = var_offset + dims. NLP_x + dims. NLP_u* s
598+ ki_start = var_offset + dims. NLP_x + dims. NLP_u* s + 1
599+ ki_end = var_offset + disc. _step_variables_block
600+
601+ # 1.1 state eq 0 = x_i+1 - (x_i + h_i sum_j b_j k_ij)
602+ # -> 2nd order terms are zero
603+
604+ # 1.2 stage equations 0 = k_ij - f(t_ij, x_ij, u_ij, v)
605+ # with x_ij = x_i + sum_l a_il k_jl
606+ # 2nd order terms depend on x_i, u_ij, k_ij, and v; (we could distinguish each j...)
607+ add_nonzero_block! (Is, Js, xi_start, ki_end, xi_start, ki_end)
608+ add_nonzero_block! (Is, Js, xi_start, ki_end, v_start, v_end; sym= true )
609+
610+ # 1.3 path constraint g(t_i, x_i, u_i, v)
611+ # -> included in 1.3
612+ end
613+
614+ # 2. final path constraints (xf, uf, v) (assume present) +++ done in 1.4 above ?
615+ var_offset = docp. time. steps * disc. _step_variables_block
616+ xf_start = var_offset + 1
617+ xf_end = var_offset + dims. NLP_x
618+ # NB convention u(tf) = U_N-1
619+ uf_start = var_offset - disc. _step_variables_block + dims. NLP_x + 1
620+ uf_end = var_offset - disc. _step_variables_block + dims. NLP_x + dims. NLP_u* s
621+ add_nonzero_block! (Is, Js, xf_start, xf_end, xf_start, xf_end)
622+ add_nonzero_block! (Is, Js, uf_start, uf_end, uf_start, uf_end)
623+ add_nonzero_block! (Is, Js, xf_start, xf_end, uf_start, uf_end; sym= true )
624+ add_nonzero_block! (Is, Js, xf_start, uf_end, v_start, v_end; sym= true )
625+ add_nonzero_block! (Is, Js, uf_start, uf_end, v_start, v_end; sym= true )
626+
627+ # 3. boundary constraints (x0, xf, v) or mayer cost g0(x0, xf, v) (assume present)
628+ # -> x0 / x0, x0 / v terms included in first loop iteration
629+ # -> xf / xf, xf / v terms included in 2.
630+ x0_start = 1
631+ x0_end = dims. NLP_x
632+ add_nonzero_block! (Is, Js, x0_start, x0_end, xf_start, xf_end; sym= true )
633+
634+ # build and return sparse matrix
635+ nnzj = length (Is)
636+ Vs = ones (Bool, nnzj)
637+ return SparseArrays. sparse (Is, Js, Vs, docp. dim_NLP_variables, docp. dim_NLP_variables)
638+ end
0 commit comments