View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0003850||OpenFOAM||Bug||public||2022-06-22 05:48||2022-06-24 11:34|
|Platform||Linux||OS||Ubuntu||OS Version||20.04 LTS|
|Fixed in Version||dev|
|Summary||0003850: Lagrangian injection uses realtime, but TimeFunction1 integral expects userTimes and can't follow flowRate as written|
|Description||I am currently working on updating our lagrangian models using userTime with engine models to work in OF-dev and was having trouble matching the flowRate profile. The massTotal is correct, but the flow profile does not.|
In searching through the InjectionModel.C and the various implementations, the problem seems to occur in the volumeToInject function. According to the code, SOI, duration and the time arguments used to integrate are all in seconds; for example in ConeNozzle:
Conversion of duration: https://cpp.openfoam.org/dev/ConeInjection_8C_source.html#l00189
However, volumeToInject uses the integral function for TimeFunction1, which expects userTime and converts to time:
There appears to be inconsistency in where the conversion of values should occur
I have been using mass basis parcels so that the total target mass is always injected. With the integration inconsistency, the flowRate is essentially truncated at whatever the duration scaled to real time is
|Steps To Reproduce||I am working on a test case to upload without proprietary information, but the basic steps are:|
1) Create a case with a cloud that has a userTime (engine cases with any kind of injector should suffice)
2) Specify the duration,flowRate and SOI in the appropriate userTime (Crank angle degrees in an engine case)
3) Make the parcelBasis mass so that the total mass at the end of injection is respected no matter what
3) Run the simulation and plot the liquid mass injected
|Additional Information||Converting the flowRate to time does nothing as the initial scaling and truncation happen when volumeTotal is calculated.|
|Tags||No tags attached.|
Test case with logfiles of liquid injected mass, columns are:
Time numbeParcelsAdded massIntroduced liquidPenetration
aachenEngineInjTest.tar.gz (178,315 bytes)
Updated case to have separate files for time and userTime injection flowRate profiles
aachenEngineInjTest.tar-2.gz (178,305 bytes)
> According to the code, SOI, duration and the time arguments used to integrate are all in seconds
Would you rather the injection specification were in CA or seconds? We discussed this when updating the implementation and concluded that seconds would probably be better for injectors.
The injection models convert the start of injection and duration from userTime to time:
SOI_ = owner.db().time().userTimeToTime(SOI_);
duration_ = owner.db().time().userTimeToTime(duration_);
Would you rather all injection specification were in real time or some in real time and some in user time?
If the profiles are specified in user-time I think TimeFunction1 should be changed thus:
Type Foam::TimeFunction1<Type>::value(const scalar x) const
const scalar x1,
const scalar x2
I am not sure how to run your case or analyse or interpret the results, could you test this change and let me know if it resolves the issue.
Thank you for looking into this. Prior to the change in how time is handled, if a simulation was an engine simulation then everything was specified in userTime. I think having all inputs to be in userTime would require the least modifications to the codebase. I will test the proposed code change and get back to you.
I also realize I didn't leave enough instructions, it was super late when I finished that case. The case uses reactingFoam. There is an include statement at the top of the system/controlDict in workDir, as well as in constant/liquidSprayProperties. To run the case as an engine case, change these includes to
To run as a regular case, change the include to
And temporarily remove the dynamicMeshDict
> I think having all inputs to be in userTime would require the least modifications to the codebase.
Changing these inputs from user-time to time is easy and if it makes more sense to the users I am happy to make the change. I am not sure what the most common specification for injection in engines is so I will need input from the users of this functionality.
This is a tricky design choice indeed. Injection, and in particular, injection duration, is a specific event which may not be intuitively correlated with the engine CAD time because then change in RPM would implicitly change the injection event, which in my opinion, results in easy mistakes and would require subsequent injection setup changes. On the other hand, different RPM requires typically different injection profile anyway...
Typically, fuel injection mass/volume flow rate profiles are estimated based on specific numerical tools or by experiments. Such profiles are typically expressed in SI units and when considering duration, it is estimated/given based on knowledge on injector control signals, expressed in seconds. However, start of injection (SOI) in user input dictionary is easiest to keep in CAD grasp on when the injection takes place.
Hence, for me the most logical input types would be:
- SOI: engineTime [CAD]
- profiles: SI units [m3/s or kg/s]
- duration: [seconds]
Of course, the above has a drawback of mixing units which is not a good habit either.
In the end, I believe that users create injection setups / profiles with some sort of script outside openfoam so I think clarity should be weighted most here.
Any ideas / comments mturcios777 ?
@henry, the proposed fix does solve the problem and the flowRateProfile when specified in userTime is respected. We did have a concern that other libraries and objects that use TimeFunction1 may not function properly though if they assume that input is in userTime.
An alternative solution so that the flowProfile is in time which we have tested is to change any calls to value and integrate in ALL the injection models to use converted userTime. Searching through the code the injection models are the only place TimeFunction1 is used.
A third alternative is to use Function1 insteam of timeFunction1 and assume the user always has their profile correct. We have not tested this.
@peksa, in previous versions of OpenFOAM with the specific engineTime class, all the user inputs had to be CAD. This made sense to us as we have pre-processing scripts where RPM is an input parameter and the flowProfile is created in crank angle. I think most users would have a similar means of converting profiles.
Here is input from a colleague who helped find the issue and propose the second possible workaround, for additional information:
Just to insist, the current implementation of the InjectorModels is inconsistent/bugged with the current design choice to convert all time-related variables in realTime (not userTime) and give the flowRateProfile in realTime (not userTime).
Indeed, the value() and integral() functions of the TimeFunction1 class (used to evaluate and integrate the flowRateProfile in InjectionModels), in their current implementation, take inputs in userTime (not realTime) and convert them to realTime using the function userTimeToTime(), as the flowRateProfile is given in realTime by design.
However, the variables fed to the functions value() and integral() in the InjectionModels are in realTime (design choice), whereas to use these functions the variables should be in fact in userTime. This results in an erroneous behavior of the InjectorModel in all instances where userTime is not realTime.
A proposed fix for the current design choice of converting all time variables to realTime and to keep the flowRateProfile in realTime is to convert to userTime the inputs of the functions value() and integral() using owner.db().time().timeToUserTime(x) in all calls to flowRateProfile.value() and flowRateProfile.integral() in the InjectorModels (not in TimeFunction1).
An alternative solution would be the proposed above fix, where all time variables are converted to realTime but the flowRateProfile is given in userTime, and where the evalute() and integral() functions of TimeFunction1 read in realTime variables and convert them to userTime (as the flowRateProfile is in userTime by design in this scenario).
Another solution is to keep all time variables in userTime as well as the flowRateProfile in the InjectionModels and to use the time variables as is in the functions value() and integrate() of TimeFunction1.
I am capable if implementing any of the options, I just need to know which of the user inputs should be in CA and which is seconds.
I will consult internally and get back to you by the end of the week.
On a design/architechture side, is there a reason we have the addition of TimeFunction1 and Function1. Is it to reduce the amount of conversions required for userTimes?
In any case, some documentation in the injectors and TimeFunction1 laying out which times are expected as arguments would be helpful, so we know when to supply them. Knowing that TimeFunction1 expects realTimes and integrates based on the equivalent userTime would have saved a lot of trouble in figuring out this bug.
||TimeFunction1 is more convenient to use if the input table or function is specified in user time, that is the point. If the input were to be specified in real time then Function1 would be used and TimeFunction1 could be deleted.|
||If we run our engine cases with injection, we normally specify the x-values, i.e. time, in CAD, i.e. userTime, and the y-values in SI units (kg/s)|
||Is that your preference or what you do because that is what is currently supported in OpenFOAM?|
||This would be our preference. However, we currently do not have an injection setup in OpenFOAM (yet).|
|Our preference would also be that the flowRate be specified in userTime.|
Resolved by commit 9d50ffdfbb99a87bcf08bae7cfd5922ef07ad604
|2022-06-22 05:48||mturcios777||New Issue|
|2022-06-22 06:54||mturcios777||File Added: aachenEngineInjTest.tar.gz|
|2022-06-22 06:54||mturcios777||Note Added: 0012630|
|2022-06-22 07:36||mturcios777||File Added: aachenEngineInjTest.tar-2.gz|
|2022-06-22 07:36||mturcios777||Note Added: 0012631|
|2022-06-22 09:05||henry||Note Added: 0012632|
|2022-06-22 11:25||henry||Note Added: 0012633|
|2022-06-22 13:33||henry||Note Added: 0012634|
|2022-06-22 14:59||mturcios777||Note Added: 0012635|
|2022-06-22 15:04||henry||Note Added: 0012636|
|2022-06-22 17:22||peksa||Note Added: 0012637|
|2022-06-22 17:43||mturcios777||Note Added: 0012638|
|2022-06-22 18:16||mturcios777||Note Added: 0012639|
|2022-06-22 18:46||henry||Note Added: 0012640|
|2022-06-22 18:59||henry||Note Edited: 0012640|
|2022-06-22 22:13||mturcios777||Note Added: 0012641|
|2022-06-22 22:36||henry||Note Added: 0012642|
|2022-06-23 12:59||cgoessni||Note Added: 0012643|
|2022-06-23 13:06||henry||Note Added: 0012644|
|2022-06-23 14:13||cgoessni||Note Added: 0012645|
|2022-06-23 22:18||mturcios777||Note Added: 0012646|
|2022-06-24 11:34||henry||Assigned To||=> henry|
|2022-06-24 11:34||henry||Status||new => resolved|
|2022-06-24 11:34||henry||Resolution||open => fixed|
|2022-06-24 11:34||henry||Fixed in Version||=> dev|
|2022-06-24 11:34||henry||Note Added: 0012650|