R中的ODE函数如何进行计算

时间:2018-01-19 20:54:38

标签: r ode

我在R中使用ODE函数来解决这个等式:

library(deSolve)
FluidH <- function(t,state,parameters) {
with(as.list(c(state,parameters)),
dh <- Qin/A - ((5073.3*h^2+6430.1*h)/(60*A)) 
 list(c(dh))
  })
}

parameters <- c(Qin =10, A=6200)
state<- c(h=0.35)
time <- seq(0,2000,by=1)
out <- ode(y= state, func = FluidH, parms = parameters, times = time)

我可能会遗漏数学的东西,但当我尝试通过分配初始状态来自己计算h时,我不会得到与函数输出相同的数字! 例如,在时间1计算h:h = h0 + dh * dt - > h = 0.35 + 10/6200 - ((5073.3 * h ^ 2 + 6430.1 * h)/(60 * 6200))= 0.3438924348 并且ode的输出给出了0.343973044412394

谁能说出我错过了什么?

1 个答案:

答案 0 :(得分:0)

您使用步长......... typedef struct rIpmbResultDataStruc { uint8_t errorCode; uint8_t dataType; uint8_t data[ IPMB_MAX_DATACOUNT ]; }; ........ void eventHandleRequestReplyHandler() // #2 Finish request, implement received data { /* Serial.print( "Bytes: " ); Serial.println( __iIpmbDataByteCount ); Serial.print( "Command: " ); Serial.println( __rIpmbDataStruc.cmd ); Serial.print( "Version: " ); Serial.println( __rIpmbDataStruc.version, HEX ); Serial.print( "DataType: " ); Serial.println( __rIpmbDataStruc.dataType, HEX ); */ resetSendBuffer(); uint16_t i = 0; uint16_t iLength = 0; uint8_t iValue = 0; uint16_t iAddress = 0; // When reboot and sleep mode is previously requested, // don't allow other commands if( __bIpmbDoDeviceReset || __bIpmbDoDeviceSleep || isRebootSleepModeRequested() ) { Wire.write( IPMB_ECMD_BUSY ); Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); return; } if( isValidCommand( __rIpmbDataStruc.cmd ) // Valid command received? && isValidVersion( __rIpmbDataStruc.version ) // Version the same? && isValidDataType( __rIpmbDataStruc.dataType ) ) // Valid dataType specified? { if( __rIpmbDataStruc.cmd == IPMB_CMD_DIGITALWRITE ) { digitalWrite( getBuffDataUint16(0), getBuffDataUint16(1) ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_ANALOGWRITE ) { analogWrite( getBuffDataUint16(0), getBuffDataUint16(1) ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_DIGITALREAD ) { Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_UINT8 ); Wire.write( digitalRead( getBuffDataUint8(0) )); return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_ANALOGREAD ) { Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_UINT16 ); uint16_t iResult = analogRead( getBuffDataUint8(0) ); uint8_t* pResult = (uint8_t*)&iResult; Wire.write( *pResult++ ); Wire.write( *pResult ); return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_PINMODE ) { pinMode( getBuffDataUint8(0), getBuffDataUint8(1) ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_EEPROMREAD ) { Serial.println( "EEPROM READ"); //Serial.println( getBuffDataUint16(0) ); iAddress = IPMB_ADR_CUSTOM_DATA + getBuffDataUint16(0); iLength = getBuffDataUint16(1); if( iLength > IPMB_MAX_DATACOUNT ) { iLength = IPMB_MAX_DATACOUNT; } if( __rIpmbDataStruc.dataType == IPMB_DAT_TYPE_STREAM && iLength > 0 ) { //Wire.write( IPMB_DAT_TYPE_STREAM ); __rIpmbResultStruc.errorCode = IPMB_ECMD_OK; __rIpmbResultStruc.dataType = IPMB_DAT_TYPE_STREAM; while( i < iLength ) { __rIpmbResultStruc.data[i++] = readStorage( iAddress++ ); } //Serial.println( (char*)&__pIpmbResultByteBuff[0] ); Wire.write( (uint8_t*)&__pIpmbResultByteBuff[0], 2+i ); } else { Wire.write( IPMB_DAT_TYPE_UINT8 ); Wire.write( readStorage( iAddress, getBuffDataUint8(1) ) ); } return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_EEPROMWRITE ) { Serial.println( "EEPROM WRITE"); Serial.println( getBuffDataUint16(0) ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_UINT8 ); iAddress = IPMB_ADR_CUSTOM_DATA + getBuffDataUint16(0); if( __rIpmbDataStruc.dataType == IPMB_DAT_TYPE_STREAM ) { iLength = getBuffDataUint16(1); Serial.println( iLength ); delay(100); while( i < iLength ) { iValue = getBuffDataUint8(4+i); Serial.println( (char)iValue ); delay(100); if( writeStorage( iAddress++, iValue ) != iValue ) { Wire.write(0); return; } ++i; } Wire.write( IPMB_ECMD_OK ); Serial.println( "Done" ); delay(100); } else { Wire.write( writeStorage( iAddress, getBuffDataUint8(2), getBuffDataUint8(3), getBuffDataUint8(4) ) ); } return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_RESET ) { //Serial.println( "SoftReset!" ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); __bIpmbDoDeviceReset = true; return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_CONFIG ) { Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_UINT8 ); uint8_t iCfg = getBuffDataUint8(0); if( iCfg == IPMB_CFG_WIPE || iCfg == IPMB_CFG_WIPE_EEPROM ) { wipeStorage( iCfg == IPMB_CFG_WIPE_EEPROM ); Wire.write( IPMB_ECMD_OK ); // Always reset __bIpmbDoDeviceReset = true; } else if( iCfg == IPMB_CFG_MCUCLOCK ) { Wire.write( setMcuClock( getBuffDataUint8(1), __iIpmbConfigAutoSave ) ); } else if( iCfg == IPMB_CFG_PWMCLOCK ) { Wire.write( setPwmClock( getBuffDataUint8(1), getBuffDataUint8(2), __iIpmbConfigAutoSave ) ); } else { Wire.write(0); } // Set reboot flag if required if( __iIpmbRebootAtConfig && __iIpmbConfigAutoSave ) { __bIpmbDoDeviceReset = true; } return; } if( __rIpmbDataStruc.cmd == IPMB_CMD_SLEEP ) { //Serial.println( "Sleep" ); Wire.write( IPMB_ECMD_OK ); Wire.write( IPMB_DAT_TYPE_UINT8 ); if( getBuffDataUint8(0) ) { __bIpmbDoDeviceSleep = true; } Wire.write( (uint8_t)__bIpmbDoDeviceSleep ); return; } } if( isValidCommand( __rIpmbDataStruc.cmd ) && !isValidVersion( __rIpmbDataStruc.version )) { Wire.write( IPMB_ECMD_INVALID_VERSION ); } else { Wire.write( IPMB_ECMD_INVALID_REQUEST ); } Wire.write( IPMB_DAT_TYPE_NONE ); Wire.write(0); resetDataBuffer(); } 计算了Euler步。求解器使用更高阶的方法,通常具有更小的步长,该步长适合于满足相对和绝对误差的dt=1的默认误差容限。您给出的步长1e-6仅确定为输出采样数值解的位置,解算器内部可能会使用更多或有时甚至更少的步(插值输出值)。