/*! \fn updateInnerEquation * * This function updates inner equation with the current x. * * \param [ref] [data] * [in] [sysNumber] index of corresponding non-linear system */ int updateInnerEquation(void **dataIn, int sysNumber, int discrete) { DATA *data = (DATA*) ((void**)dataIn[0]); threadData_t *threadData = (threadData_t*) ((void**)dataIn[1]); NONLINEAR_SYSTEM_DATA* nonlinsys = &(data->simulationInfo->nonlinearSystemData[sysNumber]); int success = 0; /* solve non continuous at discrete points*/ if(discrete) { data->simulationInfo->solveContinuous = 0; } /* try */ #ifndef OMC_EMCC MMC_TRY_INTERNAL(simulationJumpBuffer) #endif /* call residual function */ nonlinsys->residualFunc((void*) dataIn, nonlinsys->nlsx, nonlinsys->resValues, (int*)&nonlinsys->size); /* replace extrapolated values by current x for discrete step */ memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); success = 1; /*catch */ #ifndef OMC_EMCC MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } if(discrete) { data->simulationInfo->solveContinuous = 1; } return success; }
/*! \fn getAnalyticalJacobian * * function calculates analytical jacobian * * \param [ref] [data] * \param [out] [jac] * * \author wbraun * */ int getAnalyticalJacobianNewton(DATA* data, threadData_t *threadData, double* jac, int sysNumber) { int i,j,k,l,ii,currentSys = sysNumber; NONLINEAR_SYSTEM_DATA* systemData = &(((DATA*)data)->simulationInfo.nonlinearSystemData[currentSys]); DATA_NEWTON* solverData = (DATA_NEWTON*)(systemData->solverData); const int index = systemData->jacobianIndex; memset(jac, 0, (solverData->n)*(solverData->n)*sizeof(double)); for(i=0; i < data->simulationInfo.analyticJacobians[index].sparsePattern.maxColors; i++) { /* activate seed variable for the corresponding color */ for(ii=0; ii < data->simulationInfo.analyticJacobians[index].sizeCols; ii++) if(data->simulationInfo.analyticJacobians[index].sparsePattern.colorCols[ii]-1 == i) data->simulationInfo.analyticJacobians[index].seedVars[ii] = 1; systemData->analyticalJacobianColumn(data, threadData); for(j = 0; j < data->simulationInfo.analyticJacobians[index].sizeCols; j++) { if(data->simulationInfo.analyticJacobians[index].seedVars[j] == 1) { if(j==0) ii = 0; else ii = data->simulationInfo.analyticJacobians[index].sparsePattern.leadindex[j-1]; while(ii < data->simulationInfo.analyticJacobians[index].sparsePattern.leadindex[j]) { l = data->simulationInfo.analyticJacobians[index].sparsePattern.index[ii]; k = j*data->simulationInfo.analyticJacobians[index].sizeRows + l; jac[k] = data->simulationInfo.analyticJacobians[index].resultVars[l]; ii++; }; } /* de-activate seed variable for the corresponding color */ if(data->simulationInfo.analyticJacobians[index].sparsePattern.colorCols[j]-1 == i) data->simulationInfo.analyticJacobians[index].seedVars[j] = 0; } } return 0; }
/*! \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; rt_ext_tp_tick(&nonlinsys->totalTimeClock); if(data->simulationInfo.discreteCall) { double *fvec = malloc(sizeof(double)*nonlinsys->size); int success = 0; #ifndef OMC_EMCC /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) #endif ((DATA*)data)->simulationInfo.solveContinuous = 0; nonlinsys->residualFunc((void*) dataAndThreadData, nonlinsys->nlsx, fvec, (int*)&nonlinsys->size); ((DATA*)data)->simulationInfo.solveContinuous = 1; success = 1; #ifndef OMC_EMCC /*catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } free(fvec); }
/*! \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); }
/*! \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; rt_ext_tp_tick(&nonlinsys->totalTimeClock); /* value extrapolation */ infoStreamPrint(LOG_NLS_EXTRAPOLATE, 1, "############ Start new iteration for system %d at time at %g ############", sysNumber, data->localData[0]->timeValue); printValuesListTimes((VALUES_LIST*)nonlinsys->oldValueList); /* if list is empty use current start values */ if (listLen(((VALUES_LIST*)nonlinsys->oldValueList)->valueList)==0) { //memcpy(nonlinsys->nlsxOld, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); //memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } else { /* get extrapolated values */ getValues((VALUES_LIST*)nonlinsys->oldValueList, data->localData[0]->timeValue, nonlinsys->nlsxExtrapolation, nonlinsys->nlsxOld); memcpy(nonlinsys->nlsx, nonlinsys->nlsxOld, nonlinsys->size*(sizeof(double))); } if(data->simulationInfo->discreteCall) { double *fvec = malloc(sizeof(double)*nonlinsys->size); int success = 0; #ifndef OMC_EMCC /* try */ MMC_TRY_INTERNAL(simulationJumpBuffer) #endif ((DATA*)data)->simulationInfo->solveContinuous = 0; nonlinsys->residualFunc((void*) dataAndThreadData, nonlinsys->nlsx, fvec, (int*)&nonlinsys->size); ((DATA*)data)->simulationInfo->solveContinuous = 1; success = 1; memcpy(nonlinsys->nlsxExtrapolation, nonlinsys->nlsx, nonlinsys->size*(sizeof(double))); #ifndef OMC_EMCC /*catch */ MMC_CATCH_INTERNAL(simulationJumpBuffer) #endif if (!success) { warningStreamPrint(LOG_STDOUT, 0, "Non-Linear Solver try to handle a problem with a called assert."); } free(fvec); }