/* -----------------------------------------------------------------
 * Programmer(s): Allan Taylor, Alan Hindmarsh, Radu Serban, and
 *                Aaron Collier, Shelby Lockhart @ LLNL
 * -----------------------------------------------------------------
 * SUNDIALS Copyright Start
 * Copyright (c) 2002-2024, Lawrence Livermore National Security
 * and Southern Methodist University.
 * All rights reserved.
 *
 * See the top-level LICENSE and NOTICE files for details.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 * SUNDIALS Copyright End
 * -----------------------------------------------------------------
 * This is the header file for the main KINSOL solver.
 * -----------------------------------------------------------------*/

#ifndef _KINSOL_H
#define _KINSOL_H

#include <kinsol/kinsol_ls.h>
#include <stdio.h>
#include <sundials/sundials_core.h>

#ifdef __cplusplus /* wrapper to enable C++ usage */
extern "C" {
#endif

/* -----------------
 * KINSOL Constants
 * ----------------- */

/*  return values */

#define KIN_SUCCESS          0
#define KIN_INITIAL_GUESS_OK 1
#define KIN_STEP_LT_STPTOL   2

#define KIN_WARNING 99

#define KIN_MEM_NULL            -1
#define KIN_ILL_INPUT           -2
#define KIN_NO_MALLOC           -3
#define KIN_MEM_FAIL            -4
#define KIN_LINESEARCH_NONCONV  -5
#define KIN_MAXITER_REACHED     -6
#define KIN_MXNEWT_5X_EXCEEDED  -7
#define KIN_LINESEARCH_BCFAIL   -8
#define KIN_LINSOLV_NO_RECOVERY -9
#define KIN_LINIT_FAIL          -10
#define KIN_LSETUP_FAIL         -11
#define KIN_LSOLVE_FAIL         -12

#define KIN_SYSFUNC_FAIL      -13
#define KIN_FIRST_SYSFUNC_ERR -14
#define KIN_REPTD_SYSFUNC_ERR -15

#define KIN_VECTOROP_ERR -16

#define KIN_CONTEXT_ERR -17

/* Anderson Acceleration Orthogonalization Choice */
#define KIN_ORTH_MGS   0
#define KIN_ORTH_ICWY  1
#define KIN_ORTH_CGS2  2
#define KIN_ORTH_DCGS2 3

/* Enumeration for eta choice */
#define KIN_ETACHOICE1  1
#define KIN_ETACHOICE2  2
#define KIN_ETACONSTANT 3

/* Enumeration for global strategy */
#define KIN_NONE       0
#define KIN_LINESEARCH 1
#define KIN_PICARD     2
#define KIN_FP         3

/* ------------------------------
 * User-Supplied Function Types
 * ------------------------------ */

typedef int (*KINSysFn)(N_Vector uu, N_Vector fval, void* user_data);

typedef void (*KINInfoHandlerFn)(const char* module, const char* function,
                                 char* msg, void* user_data);

/* -------------------
 * Exported Functions
 * ------------------- */

/* Creation function */
SUNDIALS_EXPORT void* KINCreate(SUNContext sunctx);

/* Initialization function */
SUNDIALS_EXPORT int KINInit(void* kinmem, KINSysFn func, N_Vector tmpl);

/* Solver function */
SUNDIALS_EXPORT int KINSol(void* kinmem, N_Vector uu, int strategy,
                           N_Vector u_scale, N_Vector f_scale);

/* Optional input functions */
SUNDIALS_EXPORT int KINSetUserData(void* kinmem, void* user_data);
SUNDIALS_EXPORT int KINSetDamping(void* kinmem, sunrealtype beta);
SUNDIALS_EXPORT int KINSetMAA(void* kinmem, long int maa);
SUNDIALS_EXPORT int KINSetOrthAA(void* kinmem, int orthaa);
SUNDIALS_EXPORT int KINSetDelayAA(void* kinmem, long int delay);
SUNDIALS_EXPORT int KINSetDampingAA(void* kinmem, sunrealtype beta);
SUNDIALS_EXPORT int KINSetReturnNewest(void* kinmem, sunbooleantype ret_newest);
SUNDIALS_EXPORT int KINSetNumMaxIters(void* kinmem, long int mxiter);
SUNDIALS_EXPORT int KINSetNoInitSetup(void* kinmem, sunbooleantype noInitSetup);
SUNDIALS_EXPORT int KINSetNoResMon(void* kinmem, sunbooleantype noNNIResMon);
SUNDIALS_EXPORT int KINSetMaxSetupCalls(void* kinmem, long int msbset);
SUNDIALS_EXPORT int KINSetMaxSubSetupCalls(void* kinmem, long int msbsetsub);
SUNDIALS_EXPORT int KINSetEtaForm(void* kinmem, int etachoice);
SUNDIALS_EXPORT int KINSetEtaConstValue(void* kinmem, sunrealtype eta);
SUNDIALS_EXPORT int KINSetEtaParams(void* kinmem, sunrealtype egamma,
                                    sunrealtype ealpha);
SUNDIALS_EXPORT int KINSetResMonParams(void* kinmem, sunrealtype omegamin,
                                       sunrealtype omegamax);
SUNDIALS_EXPORT int KINSetResMonConstValue(void* kinmem, sunrealtype omegaconst);
SUNDIALS_EXPORT int KINSetNoMinEps(void* kinmem, sunbooleantype noMinEps);
SUNDIALS_EXPORT int KINSetMaxNewtonStep(void* kinmem, sunrealtype mxnewtstep);
SUNDIALS_EXPORT int KINSetMaxBetaFails(void* kinmem, long int mxnbcf);
SUNDIALS_EXPORT int KINSetRelErrFunc(void* kinmem, sunrealtype relfunc);
SUNDIALS_EXPORT int KINSetFuncNormTol(void* kinmem, sunrealtype fnormtol);
SUNDIALS_EXPORT int KINSetScaledStepTol(void* kinmem, sunrealtype scsteptol);
SUNDIALS_EXPORT int KINSetConstraints(void* kinmem, N_Vector constraints);
SUNDIALS_EXPORT int KINSetSysFunc(void* kinmem, KINSysFn func);

/* Optional output functions */
SUNDIALS_EXPORT int KINGetWorkSpace(void* kinmem, long int* lenrw,
                                    long int* leniw);
SUNDIALS_EXPORT int KINGetNumNonlinSolvIters(void* kinmem, long int* nniters);
SUNDIALS_EXPORT int KINGetNumFuncEvals(void* kinmem, long int* nfevals);
SUNDIALS_EXPORT int KINGetNumBetaCondFails(void* kinmem, long int* nbcfails);
SUNDIALS_EXPORT int KINGetNumBacktrackOps(void* kinmem, long int* nbacktr);
SUNDIALS_EXPORT int KINGetFuncNorm(void* kinmem, sunrealtype* fnorm);
SUNDIALS_EXPORT int KINGetStepLength(void* kinmem, sunrealtype* steplength);
SUNDIALS_EXPORT int KINGetUserData(void* kinmem, void** user_data);
SUNDIALS_EXPORT int KINPrintAllStats(void* kinmem, FILE* outfile,
                                     SUNOutputFormat fmt);
SUNDIALS_EXPORT char* KINGetReturnFlagName(long int flag);

/* Free function */
SUNDIALS_EXPORT void KINFree(void** kinmem);

/* KINLS interface function that depends on KINSysFn */
SUNDIALS_EXPORT int KINSetJacTimesVecSysFn(void* kinmem, KINSysFn jtimesSysFn);

#ifdef __cplusplus
}
#endif

#endif
