Skip to content

Commit

Permalink
Reorganized organization of checkNvector routines (#647)
Browse files Browse the repository at this point in the history
Clean up how ARKODE and its steppers check for required and optional
N_Vector routines. 

1. Stepper-specific N_Vector operation checks have been removed.
2. ARKODE performs an initial check on the supplied N_Vector for
operations that are always required.
3. Individual ARKODE utilities perform their own N_Vector checks when
they are configured.
4. ARKODE then performs a final check after user configuration is
complete to check any remaining N_Vector operation requirements.

---------

Co-authored-by: David Gardner <[email protected]>
  • Loading branch information
drreynolds and gardner48 authored Jan 22, 2025
1 parent 767679f commit 7c540be
Show file tree
Hide file tree
Showing 18 changed files with 123 additions and 196 deletions.
110 changes: 93 additions & 17 deletions src/arkode/arkode.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,14 @@ int ARKodeSStolerances(void* arkode_mem, sunrealtype reltol, sunrealtype abstol)
return (ARK_ILL_INPUT);
}

/* Ensure that vector supports N_VAddConst */
if (!ark_mem->tempv1->ops->nvaddconst)
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VAddConst unimplemented (required for scalar abstol)");
return (ARK_ILL_INPUT);
}

/* Set flag indicating whether abstol == 0 */
ark_mem->atolmin0 = (abstol == ZERO);

Expand Down Expand Up @@ -446,6 +454,14 @@ int ARKodeResStolerance(void* arkode_mem, sunrealtype rabstol)
return (ARK_ILL_INPUT);
}

/* Ensure that vector supports N_VAddConst */
if (!ark_mem->tempv1->ops->nvaddconst)
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VAddConst unimplemented (required for scalar rabstol)");
return (ARK_ILL_INPUT);
}

/* Set flag indicating whether rabstol == 0 */
ark_mem->Ratolmin0 = (rabstol == ZERO);

Expand Down Expand Up @@ -1732,7 +1748,7 @@ int arkInit(ARKodeMem ark_mem, sunrealtype t0, N_Vector y0, int init_type)
}

/* Test if all required vector operations are implemented */
nvectorOK = arkCheckNvector(y0);
nvectorOK = arkCheckNvectorRequired(y0);
if (!nvectorOK)
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
Expand Down Expand Up @@ -1849,25 +1865,89 @@ sunbooleantype arkCheckTimestepper(ARKodeMem ark_mem)
}

/*---------------------------------------------------------------
arkCheckNvector:
arkCheckNvectorRequired:
This routine checks if all required vector operations are
present. If any of them is missing it returns SUNFALSE.
This routine checks if all absolutely-required vector
operations are present. If any of them is missing it returns
SUNFALSE.
---------------------------------------------------------------*/
sunbooleantype arkCheckNvector(N_Vector tmpl) /* to be updated?? */
sunbooleantype arkCheckNvectorRequired(N_Vector tmpl)
{
if ((tmpl->ops->nvclone == NULL) || (tmpl->ops->nvdestroy == NULL) ||
(tmpl->ops->nvlinearsum == NULL) || (tmpl->ops->nvconst == NULL) ||
(tmpl->ops->nvdiv == NULL) || (tmpl->ops->nvscale == NULL) ||
(tmpl->ops->nvabs == NULL) || (tmpl->ops->nvinv == NULL) ||
(tmpl->ops->nvaddconst == NULL) || (tmpl->ops->nvmaxnorm == NULL) ||
(tmpl->ops->nvwrmsnorm == NULL))
{
return (SUNFALSE);
}
else { return (SUNTRUE); }
}

/*---------------------------------------------------------------
arkCheckNvectorOptional:
This routine perform conditional checks on required vector
operations are present (i.e., if the current ARKODE
configuration requires additional N_Vector routines). If any
of them is missing it returns SUNFALSE.
---------------------------------------------------------------*/
sunbooleantype arkCheckNvectorOptional(ARKodeMem ark_mem)
{
/* If using a built-in routine for error/residual weights with abstol==0,
ensure that N_VMin is available */
if ((!ark_mem->user_efun) && (ark_mem->atolmin0) &&
(!ark_mem->tempv1->ops->nvmin))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VMin unimplemented (required by error-weight function)");
return (SUNFALSE);
}
if ((!ark_mem->user_rfun) && (!ark_mem->rwt_is_ewt) && (ark_mem->Ratolmin0) &&
(!ark_mem->tempv1->ops->nvmin))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VMin unimplemented (required by residual-weight function)");
return (SUNFALSE);
}

/* If the user has not specified a step size (and it will be estimated
internally), ensure that N_VDiv and N_VMaxNorm are available */
if ((ark_mem->h0u == ZERO) && (ark_mem->hin == ZERO) &&
(!ark_mem->tempv1->ops->nvdiv))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VDiv unimplemented (required for initial step estimation)");
return (SUNFALSE);
}
if ((ark_mem->h0u == ZERO) && (ark_mem->hin == ZERO) &&
(!ark_mem->tempv1->ops->nvmaxnorm))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VMaxNorm unimplemented (required for initial step estimation)");
return (SUNFALSE);
}

/* If using a scalar-valued absolute tolerance (for either the state or
residual), then ensure that N_VAddConst is available */
if ((ark_mem->itol == ARK_SS) && (!ark_mem->tempv1->ops->nvaddconst))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VAddConst unimplemented (required for scalar abstol)");
return (SUNFALSE);
}
if ((!ark_mem->rwt_is_ewt) && (ark_mem->ritol == ARK_SS) &&
(!ark_mem->tempv1->ops->nvaddconst))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VAddConst unimplemented (required for scalar rabstol)");
return (SUNFALSE);
}

/* If we made it here, then the vector is sufficient */
return (SUNTRUE);
}

/*---------------------------------------------------------------
arkInitialSetup
Expand Down Expand Up @@ -1896,19 +1976,12 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout)
return (ARK_ILL_INPUT);
}

/* If using a built-in routine for error/residual weights with abstol==0,
ensure that N_VMin is available */
if ((!ark_mem->user_efun) && (ark_mem->atolmin0) && (!ark_mem->yn->ops->nvmin))
/* Perform additional N_Vector checks here, now that ARKODE has been
fully configured by the user */
if (!arkCheckNvectorOptional(ark_mem))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
"N_VMin unimplemented (required by error-weight function)");
return (ARK_ILL_INPUT);
}
if ((!ark_mem->user_rfun) && (!ark_mem->rwt_is_ewt) && (ark_mem->Ratolmin0) &&
(!ark_mem->yn->ops->nvmin))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VMin unimplemented (required by residual-weight function)");
MSG_ARK_BAD_NVECTOR);
return (ARK_ILL_INPUT);
}

Expand Down Expand Up @@ -3324,6 +3397,9 @@ int arkCheckTemporalError(ARKodeMem ark_mem, int* nflagPtr, int* nefPtr,
---------------------------------------------------------------*/
sunbooleantype arkAllocVec(ARKodeMem ark_mem, N_Vector tmpl, N_Vector* v)
{
/* return failure if N_VClone or N_VDestroy is not implemented */
if ((!tmpl->ops->nvclone) || (!tmpl->ops->nvdestroy)) { return SUNFALSE; }

/* allocate the new vector if necessary */
if (*v == NULL)
{
Expand Down
27 changes: 0 additions & 27 deletions src/arkode/arkode_arkstep.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ void* ARKStepCreate(ARKRhsFn fe, ARKRhsFn fi, sunrealtype t0, N_Vector y0,
ARKodeMem ark_mem;
ARKodeARKStepMem step_mem;
SUNNonlinearSolver NLS;
sunbooleantype nvectorOK;
int retval;

/* Check that at least one of fe, fi is supplied and is to be used */
Expand All @@ -64,15 +63,6 @@ void* ARKStepCreate(ARKRhsFn fe, ARKRhsFn fi, sunrealtype t0, N_Vector y0,
return (NULL);
}

/* Test if all required vector operations are implemented */
nvectorOK = arkStep_CheckNVector(y0);
if (!nvectorOK)
{
arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
MSG_ARK_BAD_NVECTOR);
return (NULL);
}

/* Create ark_mem structure and set default values */
ark_mem = arkCreate(sunctx);
if (ark_mem == NULL)
Expand Down Expand Up @@ -2168,23 +2158,6 @@ int arkStep_AccessStepMem(ARKodeMem ark_mem, const char* fname,
return (ARK_SUCCESS);
}

/*---------------------------------------------------------------
arkStep_CheckNVector:
This routine checks if all required vector operations are
present. If any of them is missing it returns SUNFALSE.
---------------------------------------------------------------*/
sunbooleantype arkStep_CheckNVector(N_Vector tmpl)
{
if ((tmpl->ops->nvclone == NULL) || (tmpl->ops->nvdestroy == NULL) ||
(tmpl->ops->nvlinearsum == NULL) || (tmpl->ops->nvconst == NULL) ||
(tmpl->ops->nvscale == NULL) || (tmpl->ops->nvwrmsnorm == NULL))
{
return (SUNFALSE);
}
return (SUNTRUE);
}

/*---------------------------------------------------------------
arkStep_SetButcherTables
Expand Down
1 change: 0 additions & 1 deletion src/arkode/arkode_arkstep_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ int arkStep_AccessARKODEStepMem(void* arkode_mem, const char* fname,
ARKodeMem* ark_mem, ARKodeARKStepMem* step_mem);
int arkStep_AccessStepMem(ARKodeMem ark_mem, const char* fname,
ARKodeARKStepMem* step_mem);
sunbooleantype arkStep_CheckNVector(N_Vector tmpl);
int arkStep_SetButcherTables(ARKodeMem ark_mem);
int arkStep_CheckButcherTables(ARKodeMem ark_mem);
int arkStep_Predict(ARKodeMem ark_mem, int istage, N_Vector yguess);
Expand Down
3 changes: 2 additions & 1 deletion src/arkode/arkode_bbdpre.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ int ARKBBDPrecInit(void* arkode_mem, sunindextype Nlocal, sunindextype mudq,
if (retval != ARK_SUCCESS) { return (retval); }

/* Test compatibility of NVECTOR package with the BBD preconditioner */
if (ark_mem->tempv1->ops->nvgetarraypointer == NULL)
if ((ark_mem->tempv1->ops->nvgetarraypointer == NULL) ||
(ark_mem->tempv1->ops->nvsetarraypointer == NULL))
{
arkProcessError(ark_mem, ARKLS_ILL_INPUT, __LINE__, __func__, __FILE__,
MSG_BBD_BAD_NVECTOR);
Expand Down
27 changes: 0 additions & 27 deletions src/arkode/arkode_erkstep.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ void* ERKStepCreate(ARKRhsFn f, sunrealtype t0, N_Vector y0, SUNContext sunctx)
{
ARKodeMem ark_mem;
ARKodeERKStepMem step_mem;
sunbooleantype nvectorOK;
int retval;

/* Check that f is supplied */
Expand All @@ -60,15 +59,6 @@ void* ERKStepCreate(ARKRhsFn f, sunrealtype t0, N_Vector y0, SUNContext sunctx)
return (NULL);
}

/* Test if all required vector operations are implemented */
nvectorOK = erkStep_CheckNVector(y0);
if (!nvectorOK)
{
arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
MSG_ARK_BAD_NVECTOR);
return (NULL);
}

/* Create ark_mem structure and set default values */
ark_mem = arkCreate(sunctx);
if (ark_mem == NULL)
Expand Down Expand Up @@ -913,23 +903,6 @@ int erkStep_AccessStepMem(ARKodeMem ark_mem, const char* fname,
return (ARK_SUCCESS);
}

/*---------------------------------------------------------------
erkStep_CheckNVector:
This routine checks if all required vector operations are
present. If any of them is missing it returns SUNFALSE.
---------------------------------------------------------------*/
sunbooleantype erkStep_CheckNVector(N_Vector tmpl)
{
if ((tmpl->ops->nvclone == NULL) || (tmpl->ops->nvdestroy == NULL) ||
(tmpl->ops->nvlinearsum == NULL) || (tmpl->ops->nvconst == NULL) ||
(tmpl->ops->nvscale == NULL) || (tmpl->ops->nvwrmsnorm == NULL))
{
return (SUNFALSE);
}
return (SUNTRUE);
}

/*---------------------------------------------------------------
erkStep_SetButcherTable
Expand Down
1 change: 0 additions & 1 deletion src/arkode/arkode_erkstep_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ int erkStep_AccessARKODEStepMem(void* arkode_mem, const char* fname,
ARKodeMem* ark_mem, ARKodeERKStepMem* step_mem);
int erkStep_AccessStepMem(ARKodeMem ark_mem, const char* fname,
ARKodeERKStepMem* step_mem);
sunbooleantype erkStep_CheckNVector(N_Vector tmpl);
int erkStep_SetButcherTable(ARKodeMem ark_mem);
int erkStep_CheckButcherTable(ARKodeMem ark_mem);
int erkStep_ComputeSolutions(ARKodeMem ark_mem, sunrealtype* dsm);
Expand Down
17 changes: 0 additions & 17 deletions src/arkode/arkode_forcingstep.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,15 +362,6 @@ static void forcingStep_PrintMem(ARKodeMem ark_mem, FILE* outfile)
}
}

/*------------------------------------------------------------------------------
This routine checks if all required vector operations are present. If any of
them are missing it returns SUNFALSE.
----------------------------------------------------------------------------*/
static sunbooleantype forcingStep_CheckNVector(N_Vector y)
{
return y->ops->nvlinearsum != NULL;
}

/*------------------------------------------------------------------------------
This routine checks if all required SUNStepper operations are present. If any
of them are missing it return SUNFALSE.
Expand Down Expand Up @@ -423,14 +414,6 @@ static int forcingStep_CheckArgs(ARKodeMem ark_mem, SUNStepper stepper1,
return ARK_ILL_INPUT;
}

/* Test if all required vector operations are implemented */
if (!forcingStep_CheckNVector(y0))
{
arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__,
MSG_ARK_BAD_NVECTOR);
return ARK_ILL_INPUT;
}

return ARK_SUCCESS;
}

Expand Down
3 changes: 2 additions & 1 deletion src/arkode/arkode_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,8 @@ void arkFreeVecArray(int count, N_Vector** v, sunindextype lrw1, long int* lrw,
sunindextype liw1, long int* liw);
void arkFreeVectors(ARKodeMem ark_mem);
sunbooleantype arkCheckTimestepper(ARKodeMem ark_mem);
sunbooleantype arkCheckNvector(N_Vector tmpl);
sunbooleantype arkCheckNvectorRequired(N_Vector tmpl);
sunbooleantype arkCheckNvectorOptional(ARKodeMem ark_mem);

int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout);
int arkStopTests(ARKodeMem ark_mem, sunrealtype tout, N_Vector yout,
Expand Down
4 changes: 2 additions & 2 deletions src/arkode/arkode_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,7 @@ int ARKodeSetFixedStep(void* arkode_mem, sunrealtype hfixed)
based on the sign of stepdir. If 0, the direction will remain
unchanged. Note that if a fixed step size was previously set,
this function can change the sign of that.
This should only be called after ARKodeReset, or between
creating a stepper and ARKodeEvolve.
---------------------------------------------------------------*/
Expand Down Expand Up @@ -1499,7 +1499,7 @@ int ARKodeSetConstraints(void* arkode_mem, N_Vector constraints)

/* Test if required vector ops. are defined */
if (constraints->ops->nvdiv == NULL || constraints->ops->nvmaxnorm == NULL ||
constraints->ops->nvcompare == NULL ||
constraints->ops->nvcompare == NULL || constraints->ops->nvprod == NULL ||
constraints->ops->nvconstrmask == NULL ||
constraints->ops->nvminquotient == NULL)
{
Expand Down
16 changes: 16 additions & 0 deletions src/arkode/arkode_ls.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,14 @@ int ARKodeSetLSNormFactor(void* arkode_mem, sunrealtype nrmfac)
}
else if (nrmfac < ZERO)
{
/* Ensure that vector support N_VDotProd */
if (ark_mem->tempv1->ops->nvdotprod == NULL)
{
arkProcessError(ark_mem, ARKLS_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VDotProd unimplemented (required for ARKodeSetLSNormFactor)");
return (ARKLS_ILL_INPUT);
}

/* compute factor for WRMS norm with dot product */
N_VConst(ONE, ark_mem->tempv1);
arkls_mem->nrmfac = SUNRsqrt(N_VDotProd(ark_mem->tempv1, ark_mem->tempv1));
Expand Down Expand Up @@ -1676,6 +1684,14 @@ int ARKodeSetMassLSNormFactor(void* arkode_mem, sunrealtype nrmfac)
}
else if (nrmfac < ZERO)
{
/* Ensure that vector support N_VDotProd */
if (ark_mem->tempv1->ops->nvdotprod == NULL)
{
arkProcessError(ark_mem, ARKLS_ILL_INPUT, __LINE__, __func__,
__FILE__, "N_VDotProd unimplemented (required for ARKodeSetMassLSNormFactor)");
return (ARKLS_ILL_INPUT);
}

/* compute factor for WRMS norm with dot product */
N_VConst(ONE, ark_mem->tempv1);
arkls_mem->nrmfac = SUNRsqrt(N_VDotProd(ark_mem->tempv1, ark_mem->tempv1));
Expand Down
Loading

0 comments on commit 7c540be

Please sign in to comment.