/* * function calculates a jacobian matrix */ static int nlsDenseJac(long int N, N_Vector vecX, N_Vector vecFX, DlsMat Jac, void *userData, N_Vector tmp1, N_Vector tmp2) { NLS_KINSOL_USERDATA *kinsolUserData = (NLS_KINSOL_USERDATA*) userData; DATA* data = kinsolUserData->data; threadData_t *threadData = kinsolUserData->threadData; int sysNumber = kinsolUserData->sysNumber; NONLINEAR_SYSTEM_DATA *nlsData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); NLS_KINSOL_DATA* kinsolData = (NLS_KINSOL_DATA*) nlsData->solverData; /* prepare variables */ double *x = N_VGetArrayPointer(vecX); double *fx = N_VGetArrayPointer(vecFX); double *xScaling = NV_DATA_S(kinsolData->xScale); double *fRes = NV_DATA_S(kinsolData->fRes); double xsave, xscale, sign; double delta_hh; const double delta_h = sqrt(DBL_EPSILON*2e1); long int i,j; /* performance measurement */ rt_ext_tp_tick(&nlsData->jacobianTimeClock); for(i = 0; i < N; i++) { xsave = x[i]; delta_hh = delta_h * (fabs(xsave) + 1.0); if ((xsave + delta_hh >= nlsData->max[i])) delta_hh *= -1; x[i] += delta_hh; /* Calculate difference quotient */ nlsKinsolResiduals(vecX, kinsolData->fRes, userData); /* Calculate scaled difference quotient */ delta_hh = 1. / delta_hh; for(j = 0; j < N; j++) { DENSE_ELEM(Jac, j, i) = (fRes[j] - fx[j]) * delta_hh; } x[i] = xsave; } /* debug */ if (ACTIVE_STREAM(LOG_NLS_JAC)){ infoStreamPrint(LOG_NLS_JAC, 0, "##KINSOL## omc dense matrix."); PrintMat(Jac); } /* performance measurement and statistics */ nlsData->jacobianTime += rt_ext_tp_tock(&(nlsData->jacobianTimeClock)); nlsData->numberOfJEval++; return 0; }
/*! \fn wrapper_fvec_newton for the residual Function * tensolve calls for the subroutine fcn(n, x, fvec, iflag, data) * * fj decides whether the function values or the jacobian matrix shall be calculated * fj = 1 ==> calculate function values * fj = 0 ==> calculate jacobian matrix */ int wrapper_fvec_newton(int* n, double* x, double* fvec, void* userdata, int fj) { DATA_USER* uData = (DATA_USER*) userdata; DATA* data = (DATA*)(uData->data); void *dataAndThreadData[2] = {data, uData->threadData}; int currentSys = ((DATA_USER*)userdata)->sysNumber; NONLINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->nonlinearSystemData[currentSys]); DATA_NEWTON* solverData = (DATA_NEWTON*)(systemData->solverData); int flag = 1; int *iflag=&flag; if (fj) { (data->simulationInfo->nonlinearSystemData[currentSys].residualFunc)(dataAndThreadData, x, fvec, iflag); } else { /* performance measurement */ rt_ext_tp_tick(&systemData->jacobianTimeClock); if(systemData->jacobianIndex != -1) { getAnalyticalJacobianNewton(data, uData->threadData, solverData->fjac, currentSys); } else { double delta_h = sqrt(solverData->epsfcn); double delta_hh; double xsave; int i,j,l, linear=0; for(i = 0; i < *n; i++) { delta_hh = fmax(delta_h * fmax(fabs(x[i]), fabs(fvec[i])), delta_h); delta_hh = ((fvec[i] >= 0) ? delta_hh : -delta_hh); delta_hh = x[i] + delta_hh - x[i]; xsave = x[i]; x[i] += delta_hh; delta_hh = 1. / delta_hh; wrapper_fvec_newton(n, x, solverData->rwork, userdata, 1); solverData->nfev++; for(j = 0; j < *n; j++) { l = i * *n + j; solverData->fjac[l] = (solverData->rwork[j] - fvec[j]) * delta_hh; } x[i] = xsave; } } /* performance measurement and statistics */ systemData->jacobianTime += rt_ext_tp_tock(&(systemData->jacobianTimeClock)); systemData->numberOfJEval++; } return *iflag; }
/* * function calculates a jacobian matrix by * numerical method finite differences with coloring * into a sparse SlsMat matrix */ static int nlsSparseJac(N_Vector vecX, N_Vector vecFX, SlsMat Jac, void *userData, N_Vector tmp1, N_Vector tmp2) { NLS_KINSOL_USERDATA *kinsolUserData = (NLS_KINSOL_USERDATA*) userData; DATA* data = kinsolUserData->data; threadData_t *threadData = kinsolUserData->threadData; int sysNumber = kinsolUserData->sysNumber; NONLINEAR_SYSTEM_DATA *nlsData = &(data->simulationInfo->nonlinearSystemData[sysNumber]); NLS_KINSOL_DATA* kinsolData = (NLS_KINSOL_DATA*) nlsData->solverData; /* prepare variables */ double *x = N_VGetArrayPointer(vecX); double *fx = N_VGetArrayPointer(vecFX); double *xsave = N_VGetArrayPointer(tmp1); double *delta_hh = N_VGetArrayPointer(tmp2); double *xScaling = NV_DATA_S(kinsolData->xScale); double *fRes = NV_DATA_S(kinsolData->fRes); SPARSE_PATTERN* sparsePattern = &(nlsData->sparsePattern); const double delta_h = sqrt(DBL_EPSILON*2e1); long int i,j,ii; int nth = 0; /* performance measurement */ rt_ext_tp_tick(&nlsData->jacobianTimeClock); /* reset matrix */ SlsSetToZero(Jac); for(i = 0; i < sparsePattern->maxColors; i++) { for(ii=0; ii < kinsolData->size; ii++) { if(sparsePattern->colorCols[ii]-1 == i) { xsave[ii] = x[ii]; delta_hh[ii] = delta_h * (fabs(xsave[ii]) + 1.0); if ((xsave[ii] + delta_hh[ii] >= nlsData->max[ii])) delta_hh[ii] *= -1; x[ii] += delta_hh[ii]; /* Calculate scaled difference quotient */ delta_hh[ii] = 1. / delta_hh[ii]; } } nlsKinsolResiduals(vecX, kinsolData->fRes, userData); for(ii = 0; ii < kinsolData->size; ii++) { if(sparsePattern->colorCols[ii]-1 == i) { nth = sparsePattern->leadindex[ii]; while(nth < sparsePattern->leadindex[ii+1]) { j = sparsePattern->index[nth]; setJacElementKluSparse(j, ii, (fRes[j] - fx[j]) * delta_hh[ii], nth, Jac); nth++; }; x[ii] = xsave[ii]; } } } /* finish sparse matrix */ finishSparseColPtr(Jac); /* debug */ if (ACTIVE_STREAM(LOG_NLS_JAC)){ infoStreamPrint(LOG_NLS_JAC, 1, "##KINSOL## Sparse Matrix."); PrintSparseMat(Jac); nlsKinsolJacSumSparse(Jac); messageClose(LOG_NLS_JAC); } /* performance measurement and statistics */ nlsData->jacobianTime += rt_ext_tp_tock(&(nlsData->jacobianTimeClock)); nlsData->numberOfJEval++; return 0; }
/*! \fn solve linear system with lapack method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * \author wbraun */ int solveLapack(DATA *data, int sysNumber) { int i, j, iflag = 1; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo.linearSystemData[sysNumber]); DATA_LAPACK* solverData = (DATA_LAPACK*)systemData->solverData; int success = 1; /* We are given the number of the linear system. * We want to look it up among all equations. */ int eqSystemNumber = systemData->equationIndex; int indexes[2] = {1,eqSystemNumber}; _omc_scalar residualNorm = 0; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Lapack Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); /* set data */ _omc_setVectorData(solverData->x, systemData->x); _omc_setVectorData(solverData->b, systemData->b); _omc_setMatrixData(solverData->A, systemData->A); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* reset matrix A */ memset(systemData->A, 0, (systemData->size)*(systemData->size)*sizeof(double)); /* update matrix A */ systemData->setA(data, systemData); /* update vector b (rhs) */ systemData->setb(data, systemData); } else { /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobianLapack(data, solverData->A->data, sysNumber); } else { assertStreamPrint(data->threadData, 1, "jacobian function pointer is invalid" ); } /* calculate vector b (rhs) */ _omc_copyVector(solverData->work, solverData->x); wrapper_fvec_lapack(solverData->work, solverData->b, &iflag, data, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); /* Log A*x=b */ if(ACTIVE_STREAM(LOG_LS_V)){ _omc_printVector(solverData->x, "Vector old x", LOG_LS_V); _omc_printMatrix(solverData->A, "Matrix A", LOG_LS_V); _omc_printVector(solverData->b, "Vector b", LOG_LS_V); } rt_ext_tp_tick(&(solverData->timeClock)); /* Solve system */ dgesv_((int*) &systemData->size, (int*) &solverData->nrhs, solverData->A->data, (int*) &systemData->size, solverData->ipiv, solverData->b->data, (int*) &systemData->size, &solverData->info); infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if(solverData->info < 0) { warningStreamPrint(LOG_LS, 0, "Error solving linear system of equations (no. %d) at time %f. Argument %d illegal.", (int)systemData->equationIndex, data->localData[0]->timeValue, (int)solverData->info); success = 0; } else if(solverData->info > 0) { warningStreamPrint(LOG_LS, 0, "Failed to solve linear system of equations (no. %d) at time %f, system is singular for U[%d, %d].", (int)systemData->equationIndex, data->localData[0]->timeValue, (int)solverData->info+1, (int)solverData->info+1); success = 0; /* debug output */ if (ACTIVE_STREAM(LOG_LS)){ _omc_printMatrix(solverData->A, "Matrix U", LOG_LS); _omc_printVector(solverData->b, "Output vector x", LOG_LS); } } if (1 == success){ if (1 == systemData->method){ /* take the solution */ solverData->x = _omc_addVectorVector(solverData->x, solverData->work, solverData->b); /* update inner equations */ wrapper_fvec_lapack(solverData->x, solverData->work, &iflag, data, sysNumber); residualNorm = _omc_euclideanVectorNorm(solverData->work); } else { /* take the solution */ _omc_copyVector(solverData->x, solverData->b); } if (ACTIVE_STREAM(LOG_LS_V)){ infoStreamPrint(LOG_LS_V, 1, "Residual Norm %f of solution x:", residualNorm); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) { infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); } messageClose(LOG_LS_V); } } return success; }
/*! \fn solve linear system with UmfPack method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * * author: kbalzereit, wbraun */ int solveUmfPack(DATA *data, int sysNumber) { LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo.linearSystemData[sysNumber]); DATA_UMFPACK* solverData = (DATA_UMFPACK*)systemData->solverData; int i, j, status = UMFPACK_OK, success = 0, ni=0, n = systemData->size, eqSystemNumber = systemData->equationIndex, indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with UMFPACK Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* set A matrix */ solverData->Ap[0] = 0; systemData->setA(data, systemData); solverData->Ap[solverData->n_row] = solverData->nnz; if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Matrix A"); printMatrixCSR(solverData->Ap, solverData->Ai, solverData->Ax, n); messageClose(LOG_LS_V); } /* set b vector */ systemData->setb(data, systemData); } else { solverData->Ap[0] = 0; /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1) { getAnalyticalJacobianUmfPack(data, sysNumber); } else { assertStreamPrint(data->threadData, 1, "jacobian function pointer is invalid" ); } solverData->Ap[solverData->n_row] = solverData->nnz; /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); wrapper_fvec_umfpack(solverData->work, systemData->b, data, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); if (ACTIVE_STREAM(LOG_LS_V)) { if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Old solution x:"); for(i = 0; i < solverData->n_row; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } infoStreamPrint(LOG_LS_V, 1, "Matrix A n_rows = %d", solverData->n_row); for (i=0; i<solverData->n_row; i++) { infoStreamPrint(LOG_LS_V, 0, "%d. Ap => %d -> %d", i, solverData->Ap[i], solverData->Ap[i+1]); for (j=solverData->Ap[i]; j<solverData->Ap[i+1]; j++) { infoStreamPrint(LOG_LS_V, 0, "A[%d,%d] = %f", i, solverData->Ai[j], solverData->Ax[j]); } } messageClose(LOG_LS_V); for (i=0; i<solverData->n_row; i++) infoStreamPrint(LOG_LS_V, 0, "b[%d] = %e", i, systemData->b[i]); } rt_ext_tp_tick(&(solverData->timeClock)); /* symbolic pre-ordering of A to reduce fill-in of L and U */ if (0 == solverData->numberSolving) { status = umfpack_di_symbolic(solverData->n_col, solverData->n_row, solverData->Ap, solverData->Ai, solverData->Ax, &(solverData->symbolic), solverData->control, solverData->info); } /* compute the LU factorization of A */ if (0 == status) { status = umfpack_di_numeric(solverData->Ap, solverData->Ai, solverData->Ax, solverData->symbolic, &(solverData->numeric), solverData->control, solverData->info); } if (0 == status) { if (1 == systemData->method) { status = umfpack_di_solve(UMFPACK_A, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } else { status = umfpack_di_solve(UMFPACK_Aat, solverData->Ap, solverData->Ai, solverData->Ax, systemData->x, systemData->b, solverData->numeric, solverData->control, solverData->info); } } if (status == UMFPACK_OK) { success = 1; } else if (status == UMFPACK_WARNING_singular_matrix) { if (!solveSingularSystem(systemData)) { success = 1; } } infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); /* print solution */ if (1 == success) { if (1 == systemData->method) { /* take the solution */ for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += solverData->work[i]; /* update inner equations */ wrapper_fvec_umfpack(systemData->x, solverData->work, data, sysNumber); } else { /* the solution is automatically in x */ } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData.modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, status); } solverData->numberSolving += 1; return success; }
/*! \fn solve linear system with totalpivot method * * \param [in] [data] * [sysNumber] index of the corresponing non-linear system * * \author bbachmann */ int solveTotalPivot(DATA *data, threadData_t *threadData, int sysNumber, double* aux_x) { void *dataAndThreadData[2] = {data, threadData}; int i, j; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_TOTALPIVOT* solverData = (DATA_TOTALPIVOT*) systemData->solverData[1]; int n = systemData->size, status; double fdeps = 1e-8; double xTol = 1e-8; int eqSystemNumber = systemData->equationIndex; int indexes[2] = {1,eqSystemNumber}; int rank; /* We are given the number of the linear system. * We want to look it up among all equations. */ /* int eqSystemNumber = systemData->equationIndex; */ int success = 1; double tmpJacEvalTime; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Total Pivot Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); debugVectorDoubleLS(LOG_LS_V,"SCALING",systemData->nominal,n); debugVectorDoubleLS(LOG_LS_V,"Old VALUES",aux_x,n); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method){ /* reset matrix A */ vecConstLS(n*n, 0.0, systemData->A); /* update matrix A -> first n columns of matrix Ab*/ systemData->setA(data, threadData, systemData); vecCopyLS(n*n, systemData->A, solverData->Ab); /* update vector b (rhs) -> -b is last column of matrix Ab*/ rt_ext_tp_tick(&(solverData->timeClock)); systemData->setb(data, threadData, systemData); vecScalarMultLS(n, systemData->b, -1.0, solverData->Ab + n*n); } else { /* calculate jacobian -> first n columns of matrix Ab*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobianTotalPivot(data, threadData, solverData->Ab, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } /* calculate vector b (rhs) -> -b is last column of matrix Ab */ wrapper_fvec_totalpivot(aux_x, solverData->Ab + n*n, dataAndThreadData, sysNumber); } tmpJacEvalTime = rt_ext_tp_tock(&(solverData->timeClock)); systemData->jacobianTime += tmpJacEvalTime; infoStreamPrint(LOG_LS_V, 0, "### %f time to set Matrix A and vector b.", tmpJacEvalTime); debugMatrixDoubleLS(LOG_LS_V,"LGS: matrix Ab",solverData->Ab, n, n+1); rt_ext_tp_tick(&(solverData->timeClock)); status = solveSystemWithTotalPivotSearchLS(n, solverData->x, solverData->Ab, solverData->indRow, solverData->indCol, &rank); infoStreamPrint(LOG_LS_V, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if (status != 0) { warningStreamPrint(LOG_STDOUT, 0, "Error solving linear system of equations (no. %d) at time %f.", (int)systemData->equationIndex, data->localData[0]->timeValue); success = 0; } else { debugVectorDoubleLS(LOG_LS_V, "SOLUTION:", solverData->x, n+1); if (1 == systemData->method){ /* add the solution to old solution vector*/ vecAddLS(n, aux_x, solverData->x, aux_x); wrapper_fvec_totalpivot(aux_x, solverData->b, dataAndThreadData, sysNumber); } else { /* take the solution */ vecCopyLS(n, solverData->x, aux_x); } if (ACTIVE_STREAM(LOG_LS_V)){ infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i=0; i<systemData->size; ++i) { infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], aux_x[i]); } messageClose(LOG_LS_V); } } return success; }
/*! \fn solve linear system with Klu method * * \param [in] [data] * [sysNumber] index of the corresponding linear system * * * author: wbraun */ int solveKlu(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_KLU* solverData = (DATA_KLU*)systemData->solverData; int i, j, status = 0, success = 0, n = systemData->size, eqSystemNumber = systemData->equationIndex, indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Klu Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { /* set A matrix */ solverData->Ap[0] = 0; systemData->setA(data, threadData, systemData); solverData->Ap[solverData->n_row] = solverData->nnz; if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Matrix A"); printMatrixCSR(solverData->Ap, solverData->Ai, solverData->Ax, n); messageClose(LOG_LS_V); } /* set b vector */ systemData->setb(data, threadData, systemData); } else { solverData->Ap[0] = 0; /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1){ getAnalyticalJacobian(data, threadData, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } solverData->Ap[solverData->n_row] = solverData->nnz; /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); residual_wrapper(solverData->work, systemData->b, dataAndThreadData, sysNumber); } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); if (ACTIVE_STREAM(LOG_LS_V)) { if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Old solution x:"); for(i = 0; i < solverData->n_row; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } infoStreamPrint(LOG_LS_V, 1, "Matrix A n_rows = %d", solverData->n_row); for (i=0; i<solverData->n_row; i++){ infoStreamPrint(LOG_LS_V, 0, "%d. Ap => %d -> %d", i, solverData->Ap[i], solverData->Ap[i+1]); for (j=solverData->Ap[i]; j<solverData->Ap[i+1]; j++){ infoStreamPrint(LOG_LS_V, 0, "A[%d,%d] = %f", i, solverData->Ai[j], solverData->Ax[j]); } } messageClose(LOG_LS_V); for (i=0; i<solverData->n_row; i++) infoStreamPrint(LOG_LS_V, 0, "b[%d] = %e", i, systemData->b[i]); } rt_ext_tp_tick(&(solverData->timeClock)); /* symbolic pre-ordering of A to reduce fill-in of L and U */ if (0 == solverData->numberSolving) { infoStreamPrint(LOG_LS_V, 0, "Perform analyze settings:\n - ordering used: %d\n - current status: %d", solverData->common.ordering, solverData->common.status); solverData->symbolic = klu_analyze(solverData->n_col, solverData->Ap, solverData->Ai, &solverData->common); } /* compute the LU factorization of A */ if (0 == solverData->common.status){ solverData->numeric = klu_factor(solverData->Ap, solverData->Ai, solverData->Ax, solverData->symbolic, &solverData->common); } if (0 == solverData->common.status){ if (1 == systemData->method){ if (klu_solve(solverData->symbolic, solverData->numeric, solverData->n_col, 1, systemData->b, &solverData->common)){ success = 1; } } else { if (klu_tsolve(solverData->symbolic, solverData->numeric, solverData->n_col, 1, systemData->b, &solverData->common)){ success = 1; } } } infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); /* print solution */ if (1 == success){ if (1 == systemData->method){ /* take the solution */ for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += systemData->b[i]; /* update inner equations */ residual_wrapper(systemData->x, solverData->work, dataAndThreadData, sysNumber); } else { /* the solution is automatically in x */ memcpy(systemData->x, systemData->b, sizeof(double)*systemData->size); } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, status); } solverData->numberSolving += 1; return success; }
void TimeManager::updateTick() { _realTime = rt_ext_tp_tock(&_visualTimer)*1e9; }
int solveLis(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; LINEAR_SYSTEM_DATA* systemData = &(data->simulationInfo->linearSystemData[sysNumber]); DATA_LIS* solverData = (DATA_LIS*)systemData->solverData; int i, ret, success = 1, ni, iflag = 1, n = systemData->size, eqSystemNumber = systemData->equationIndex; char *lis_returncode[] = {"LIS_SUCCESS", "LIS_ILL_OPTION", "LIS_BREAKDOWN", "LIS_OUT_OF_MEMORY", "LIS_MAXITER", "LIS_NOT_IMPLEMENTED", "LIS_ERR_FILE_IO"}; LIS_INT err; int indexes[2] = {1,eqSystemNumber}; infoStreamPrintWithEquationIndexes(LOG_LS, 0, indexes, "Start solving Linear System %d (size %d) at time %g with Lis Solver", eqSystemNumber, (int) systemData->size, data->localData[0]->timeValue); /* set old values as start value for the iteration */ for(i=0; i<n; i++) { err = lis_vector_set_value(LIS_INS_VALUE, i, systemData->x[i], solverData->x); } rt_ext_tp_tick(&(solverData->timeClock)); if (0 == systemData->method) { lis_matrix_set_size(solverData->A, solverData->n_row, 0); /* set A matrix */ systemData->setA(data, threadData, systemData); lis_matrix_assemble(solverData->A); /* set b vector */ systemData->setb(data, threadData, systemData); } else { lis_matrix_set_size(solverData->A, solverData->n_row, 0); /* calculate jacobian -> matrix A*/ if(systemData->jacobianIndex != -1) { getAnalyticalJacobianLis(data, threadData, sysNumber); } else { assertStreamPrint(threadData, 1, "jacobian function pointer is invalid" ); } lis_matrix_assemble(solverData->A); /* calculate vector b (rhs) */ memcpy(solverData->work, systemData->x, sizeof(double)*solverData->n_row); wrapper_fvec_lis(solverData->work, systemData->b, dataAndThreadData, sysNumber); /* set b vector */ for(i=0; i<n; i++) { err = lis_vector_set_value(LIS_INS_VALUE, i, systemData->b[i], solverData->b); } } infoStreamPrint(LOG_LS, 0, "### %f time to set Matrix A and vector b.", rt_ext_tp_tock(&(solverData->timeClock))); rt_ext_tp_tick(&(solverData->timeClock)); err = lis_solve(solverData->A,solverData->b,solverData->x,solverData->solver); infoStreamPrint(LOG_LS, 0, "Solve System: %f", rt_ext_tp_tock(&(solverData->timeClock))); if (err) { warningStreamPrint(LOG_LS_V, 0, "lis_solve : %s(code=%d)\n\n ", lis_returncode[err], err); printLisMatrixCSR(solverData->A, solverData->n_row); success = 0; } /* Log A*x=b */ if(ACTIVE_STREAM(LOG_LS_V)) { char *buffer = (char*)malloc(sizeof(char)*n*25); printLisMatrixCSR(solverData->A, n); /* b vector */ infoStreamPrint(LOG_LS_V, 1, "b vector [%d]", n); for(i=0; i<n; i++) { buffer[0] = 0; sprintf(buffer, "%s%20.12g ", buffer, solverData->b->value[i]); infoStreamPrint(LOG_LS_V, 0, "%s", buffer); } messageClose(LOG_LS_V); free(buffer); } /* print solution */ if (1 == success) { if (1 == systemData->method) { /* take the solution */ lis_vector_get_values(solverData->x, 0, solverData->n_row, systemData->x); for(i = 0; i < solverData->n_row; ++i) systemData->x[i] += solverData->work[i]; /* update inner equations */ wrapper_fvec_lis(systemData->x, solverData->work, dataAndThreadData, sysNumber); } else { /* write solution */ lis_vector_get_values(solverData->x, 0, solverData->n_row, systemData->x); } if (ACTIVE_STREAM(LOG_LS_V)) { infoStreamPrint(LOG_LS_V, 1, "Solution x:"); infoStreamPrint(LOG_LS_V, 0, "System %d numVars %d.", eqSystemNumber, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).numVar); for(i = 0; i < systemData->size; ++i) infoStreamPrint(LOG_LS_V, 0, "[%d] %s = %g", i+1, modelInfoGetEquation(&data->modelData->modelDataXml,eqSystemNumber).vars[i], systemData->x[i]); messageClose(LOG_LS_V); } } else { warningStreamPrint(LOG_STDOUT, 0, "Failed to solve linear system of equations (no. %d) at time %f, system status %d.", (int)systemData->equationIndex, data->localData[0]->timeValue, err); } return success; }
/*! \fn solve non-linear systems * * \param [in] [data] * \param [in] [sysNumber] index of corresponding non-linear system * * \author wbraun */ int solve_nonlinear_system(DATA *data, threadData_t *threadData, int sysNumber) { void *dataAndThreadData[2] = {data, threadData}; int success = 0, saveJumpState; NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo->nonlinearSystemData[sysNumber]); struct dataNewtonAndHybrid *mixedSolverData; data->simulationInfo->currentNonlinearSystemIndex = sysNumber; /* enable to avoid division by zero */ data->simulationInfo->noThrowDivZero = 1; ((DATA*)data)->simulationInfo->solveContinuous = 1; /* performance measurement */ rt_ext_tp_tick(&nonlinsys->totalTimeClock); /* grab the initial guess */ infoStreamPrint(LOG_NLS_EXTRAPOLATE, 1, "############ Start new iteration for system %ld at time at %g ############", nonlinsys->equationIndex, data->localData[0]->timeValue); /* if last solving is too long ago use just old values */ if (fabs(data->localData[0]->timeValue - nonlinsys->lastTimeSolved) < 5*data->simulationInfo->stepSize) { getInitialGuess(nonlinsys, data->localData[0]->timeValue); } else { nonlinsys->getIterationVars(data, nonlinsys->nlsx); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } /* update non continuous */ if (data->simulationInfo->discreteCall) { updateInnerEquation(dataAndThreadData, sysNumber, 1); } /* try */ #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif /* handle asserts */ saveJumpState = threadData->currentErrorStage; threadData->currentErrorStage = ERROR_NONLINEARSOLVER; /* use the selected solver for solving nonlinear system */ switch(data->simulationInfo->nlsMethod) { #if !defined(OMC_MINIMAL_RUNTIME) case NLS_HYBRID: success = solveHybrd(data, threadData, sysNumber); break; case NLS_KINSOL: success = nlsKinsolSolve(data, threadData, sysNumber); break; case NLS_NEWTON: success = solveNewton(data, threadData, sysNumber); /* check if solution process was successful, if not use alternative tearing set if available (dynamic tearing)*/ if (!success && nonlinsys->strictTearingFunctionCall != NULL){ debugString(LOG_DT, "Solving the casual tearing set failed! Now the strict tearing set is used."); success = nonlinsys->strictTearingFunctionCall(data, threadData); if (success) success=2; } break; #endif case NLS_HOMOTOPY: success = solveHomotopy(data, threadData, sysNumber); break; #if !defined(OMC_MINIMAL_RUNTIME) case NLS_MIXED: mixedSolverData = nonlinsys->solverData; nonlinsys->solverData = mixedSolverData->newtonData; success = solveHomotopy(data, threadData, sysNumber); /* check if solution process was successful, if not use alternative tearing set if available (dynamic tearing)*/ if (!success && nonlinsys->strictTearingFunctionCall != NULL){ debugString(LOG_DT, "Solving the casual tearing set failed! Now the strict tearing set is used."); success = nonlinsys->strictTearingFunctionCall(data, threadData); if (success){ success=2; /* update iteration variables of the causal set*/ nonlinsys->getIterationVars(data, nonlinsys->nlsx); } } if (!success) { nonlinsys->solverData = mixedSolverData->hybridData; success = solveHybrd(data, threadData, sysNumber); } nonlinsys->solverData = mixedSolverData; break; #endif default: throwStreamPrint(threadData, "unrecognized nonlinear solver"); } /* set result */ nonlinsys->solved = success; /* handle asserts */ threadData->currentErrorStage = saveJumpState; /*catch */ #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif /* update value list database */ updateInitialGuessDB(nonlinsys, data->localData[0]->timeValue, data->simulationInfo->currentContext); if (nonlinsys->solved == 1) { nonlinsys->lastTimeSolved = data->localData[0]->timeValue; } /* enable to avoid division by zero */ data->simulationInfo->noThrowDivZero = 0; ((DATA*)data)->simulationInfo->solveContinuous = 0; /* performance measurement and statistics */ nonlinsys->totalTime += rt_ext_tp_tock(&(nonlinsys->totalTimeClock)); nonlinsys->numberOfCall++; /* write csv file for debugging */ #if !defined(OMC_MINIMAL_RUNTIME) if (data->simulationInfo->nlsCsvInfomation) { print_csvLineCallStats(((struct csvStats*) nonlinsys->csvData)->callStats, nonlinsys->numberOfCall, data->localData[0]->timeValue, nonlinsys->numberOfIterations, nonlinsys->numberOfFEval, nonlinsys->totalTime, nonlinsys->solved ); } #endif return check_nonlinear_solution(data, 1, sysNumber); }