我在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
谁能说出我错过了什么?
答案 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
仅确定为输出采样数值解的位置,解算器内部可能会使用更多或有时甚至更少的步(插值输出值)。