-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use F90 interfaces and kinds to handle 4/8/d build issues, and only build one copy of the library #78
Comments
@jbathegit when do we think this issue will be addressed? |
@edwardhartnett I honestly have no idea. I haven't had any time to work on NCEPLIBS-bufr updates in the past couple of months, and I'm not sure how soon I'll be able to get back to it. I'd certainly welcome any help if someone else wants to work on this in the meantime. |
@edwardhartnett @aerorahul @rmclaren @kgerheiser @jack-woollen I've spent a bit of time looking into this. I've come up with a prototype that will work, but there are a couple of issues as noted below. For example, let's say I have an existing Fortran-77 library routine named writsa which has the following call signature:
and where all of the arguments are currently implicitly typed (so the first four are integers and the last two are reals), and the third argument (msgt) is an array of size lmsgt. The goal here is to develop a single interface that can automatically handle any of 3 cases that might be passed in by a user:
So I could pick, say, the second case as the new default (meaning that, going forward, the only compiled version of the library would be equivalent to the existing _8 build) and have something like the following:
I would then rename the existing subroutine writsa as writsa_f, and that way users can still call the same name writsa as before, but now it will automatically re-direct them through the proper interface procedure (either writsa_4, writsa_8, or writsa_d, depending on how they have the variables declared within their own application code), and where each of these would then act as a conduit into the existing subroutine (now renamed as writsa_f) and where the call signature there is now clearly defined with all of the arguments being 8-byte integers and 8-byte reals as the default build of the library. I've tested this out and it works; HOWEVER... the main issue I see here is one of efficiency; specifically, in the writsa_4 and writsa_d cases, I have to copy all of the 4-byte values input by the user into corresponding 8-byte local variables, then call the single writsa_f routine with those 8-byte variables, then copy the output back into the original 4-byte values. This is even more complicated by the fact that one of the variables (msgt) is an array, which means I need to dynamically allocate the correct amount of space at run time in order to do the transfers. This seems like a lot of extra overhead, especially if we have to dynamically allocate temporary memory every time the subroutine is called. Is there maybe a cleaner way to do this that I'm missing here? A secondary issue is that this, or whatever approach we end up using, will need to be replicated across hundreds of existing subroutines and functions in order to end up with a single build of the library that handles all of the existing _4, _8, and _d cases, plus all of the accompanying documentation, etc. Again, unless I'm missing something here that would make this process a lot more straightforward, this will be a lengthy task. I'd greatly appreciate any comments, thoughts, advice, suggestions, etc. - thanks! |
As you note there's no silver bullet when doing this in Fortran. Hopefully, a native method will be included in the next Fortran standard. But for now another way to overload the method would be to overload A method I've used before to reduce the code duplication is to use the pre-processor to
But then you split up the function body and interface definition and rely on the pre-processor. Or it could be automated with the build system. With bufr you would have to start at the lowest level functions and work your way up. |
As @kgerheiser notes, Fortran does not support templates. |
Ive never used it but fypp (https://fypp.readthedocs.io/en/stable/fypp.html) seems to be a popular way to address these kinds of issues. I noticed that some JCSDA code uses it. Its a little ugly in my opinion but anyways... |
I'm not in favor of bringing in any new tools like fypp. In fact, I strongly oppose the idea. There is always a strong urge to attempt to change Fortran in some way to overcome it's many shortcomings. (For example the UFS apparently has a home-rolled python to Fortran translator). In my experience, none of these band-aids on Fortran bring long-term benefit to the organization. For example, we would not be very delighted to have to be using one of the many pre-processors I remember from Fortran 77 days, which gave F77 programmers new and wonderful innovations, now long-since forgotten. Will programmers at EMC in 25 years want to deal with fypp, our home-rolled python translator, or any other hack we make to Fortran to try and make it more easy to program? Fortran is a long-term standard, but these other tools are local, temporary, and not really in it for the long haul. As the programmers that work on them retire or move on to new projects, these tools will be abandoned. But standard Fortran will march on, and NOAA will still want to run the millions of lines of existing Fortran code it has developed at great cost. Future NOAA programmers, cursing our shortsightedness, will simply be removing these band-aids and returning to standard Fortran (or C/C++). |
I would be in favor of moving the core of this library (in a gradual way) to C. I think C++ is not really needed, and is much harder for Fortran programmers to learn and consequently harder to staff. (It should not be assumed that any Fortran programmer can instantly learn either C or C++. There is a steep learning curve, especially when it comes to pointers and object oriented programming, which can be real stumbling blocks. Training and help is required. Also the programmer must be willing to put in the effort.) I also think this problem could be solved in pure Fortran by making the functions all accept double-precision, and then having single precision calls which cast/copy the data to double-precision. Since no calculations are done by the library (i.e. no hairy physics equations being solved) having single precision vs. double is not going to affect performance. @jbathegit do you know C or C++? The way to solve this in C would be first to write a function using parameters and void pointers, which could take any of the data sizes needed, then write simple C wrappers for each actual case needed (i.e. one for single precision one for double), then write Fortran APIs to call those C wrappers. This way the void pointer is hidden from the Fortran layer, and it just sees C functions with nice, well-defined types. All of this is 100% standard C and Fortran. |
Thanks everyone for your feedback and suggestions! First of all, and to answer the question from @edwardhartnett, yes I'm proficient in C, but not so much in C++. Secondly, a question for @rmclaren - in your example I was able to get around that by using the suggestion from @kgerheiser to incorporate an #include directive in a source file modi_writsa.F90:
But, as he noted, this separates the function body from the interface definition and relies on pre-processing, which in turn becomes a hairy mess for Doxygen to make sense of. Furthermore, while I was able to get a simple test code to compile and run via:
from the UNIX command line, I couldn't then get the same modi_writsa.F90 code to work within the existing CMake build procedure for NCEPLIBS-bufr; instead, it squawked with the following diagnostic:
So I'm still kind of stuck here. Please note that, whatever solution we come up, it has to work for any user and existing application code simply by calling the name |
@edwardhartnett @kgerheiser @rmclaren @aerorahul @jack-woollen Digging further, the undefined reference is due to the Am I missing something here? In other words, is there some straightforward way that I can make the |
There has to be a
And internally, each piece of code would use the individual modules that it needs. |
Thanks @kgerheiser, and yeah I did think of something like that, but I was hoping there might be some way for every user to not have to add any such new directive to their application code, or even worse within every individual source file of their code where any NCEPLIBS-bufr routine ever gets called. I guess I was hoping there might be some sort of generic Fortran structure that I was overlooking and that would automatically get compiled and be in scope within the library without users having to modify their own application code in order to have visibility to that interface(?) Anyway, thanks again for the confirmation, and if anyone else can think of a separate way around this, please let me know. I guess my other question is a more general one for @edwardhartnett, in terms of how important this is? I get that it would be nice to be able to have one version of the compiled library that all application codes can link to (vs. separate _4, _8 and _d builds), but this is quite a bit of restructuring just for one subprogram out of many, and we haven't even addressed the issue of how Doxygen is going to behave with all of these |
Another issue I see with a single public-facing Fortran module such as |
@jbathegit you can still interface with C by using |
I'm confused. Given the above example module In other words, |
How important is this? I would say quite important. Right now we are doing this 4/8/d thing, which is a NOAA special - I've never seen anyone else do this or even try it. So we are well outside the normal with this. Heading further down the road with 4/8/d is just putting off the problem. I have outlined a solution in C - can this work? |
Before this library is refactored/rewritten, what does the future use of BUFR look like in our systems and in general with the development around us? |
I have heard the desire to phase out GRIB1 (although this still has not been achieved). There has been no talk of getting rid of BUFR, has there? Our goal is to have world-class software so scientists can do world-class science. We will do whatever programming work we need to do, in order to achieve that. If that means extra programming... well, we are programmers. It's what we do all day, every day. |
BUFR is not going anywhere. I am talking about use of bufr, not about its existence. |
OK, so this is our bufr solution for NOAA for the next several decades. At the moment I am working hard on the GRIB libraries, and that will take some time. @jbathegit if you want to defer this entire conversation until I have free time to come help NCEPLIBS-bufr with this conversion away from 4/8/d, that's fine. We are doing this for other libraries, and will learn as we go. So let's table this issue for a while until we have more experience. Jeff, if you want to try out the C solution, I think that's where we will end up heading. |
I'm wondering how many codes use the 8 or the d version. And why.
…On Mon, Jan 24, 2022 at 9:02 AM Edward Hartnett ***@***.***> wrote:
I have heard the desire to phase out GRIB1 (although this still has not
been achieved). There has been no talk of getting rid of BUFR, has there?
Our goal is to have world-class software so scientists can do world-class
science. We will do whatever programming work we need to do, in order to
achieve that.
If that means extra programming... well, we are programmers. It's what we
do all day, every day.
[image: image]
<https://user-images.githubusercontent.com/38856240/150796455-ccab7308-6287-4d0c-b5cd-a167d785b853.png>
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6M757VQL6ZCSPLWOK3UXVLVVANCNFSM4TYNIUTQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@aerorahul raises a good question that I've raised myself in the past, which is what the future of BUFR looks like in our systems? He's correct that BUFR isn't going anywhere, and in fact we'll definitely continue receiving BUFR observational data from the outside world for many years/decades into the future. So we're always going to need to have software to be able to read and write BUFR when interacting with the rest of the world, because it is and will remain a WMO standard for a long time, and there's been no discussion whatsoever at the WMO level about changing that. But as I've mentioned previously, and just because we'll have a continued need to be able to read/decode and write/encode BUFR in our interactions with the rest of the world, that doesn't mean we necessarily need to forever continue to use BUFR as our internal NCEP storage and archive format. In other words, there's no reason many of our internal codes couldn't switch to something else (direct JEDI/IODA array vectors?) if that were deemed preferable, and in that case it would greatly reduce the number of NCEP codes that we have to support with our BUFR software. But of course that's an enterprise-level decision that would have far-reaching implications into a lot of existing software and other internal practices. So, again, just throwing that out there as food-for-thought. For my part, and to answer @jack-woollen's question, I have no idea how many existing codes or what percentage use the 8 or the d versions. I would imagine it's a fairly small number, because most BUFR values fit just fine into 32 bit fields. That said, there are a handful of newer BUFR descriptors whose range of values don't fit into 32 bits and therefore do require 8 bytes, and which is why I've suggested making that the new default and just tailoring all newly-developed interfaces to that build. |
The bufrlib inputs and outputs are all already 8 bytes. You don't need
different libraries for that.
…On Mon, Jan 24, 2022 at 1:11 PM Jeff Ator ***@***.***> wrote:
@aerorahul <https://github.com/aerorahul> raises a good question that
I've raised myself in the past, which is what the future of BUFR looks like
in our systems? He's correct that BUFR isn't going anywhere, and in fact
we'll definitely continue receiving BUFR observational data from the
outside world for many years/decades into the future. So we're always going
to need to have software to be able to read and write BUFR when interacting
with the rest of the world, because it is and will remain a WMO standard
for a long time, and there's been no discussion whatsoever at the WMO level
about changing that.
But as I've mentioned previously, and just because we'll have a continued
need to be able to read/decode and write/encode BUFR in our interactions
with the rest of the world, that doesn't mean we necessarily need to
forever continue to use BUFR as our internal NCEP storage and archive
format. In other words, there's no reason many of our internal codes
couldn't switch to something else (direct JEDI/IODA array vectors?) if that
were deemed preferable, and in that case it would greatly reduce the number
of NCEP codes that we have to support with our BUFR software. But of course
that's an enterprise-level decision that would have far-reaching
implications into a lot of existing software and other internal practices.
So, again, just throwing that out there as food-for-thought.
For my part, and to answer @jack-woollen <https://github.com/jack-woollen>'s
question, I have no idea how many existing codes or what percentage use the
8 or the d versions. I would imagine it's a fairly small number, because
most BUFR values fit just fine into 32 bit fields. That said, there are a
handful of newer BUFR descriptors whose range of values don't fit into 32
bits and therefore do require 8 bytes, and which is why I've suggested
making that the new default and just tailoring all newly-developed
interfaces to that build.
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6PG2T6ZSIUMDSOZLOTUXWI5TANCNFSM4TYNIUTQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@jack-woollen please clarify what you mean by this. Specifically, when a user application calls, e.g. Unless I'm missing something, the only things that are explicitly declared as 8 bytes within the library itself are the REAL values arrays that get passed into and out of subroutines such as |
@jeff Ator - NOAA Federal ***@***.***>
Okay, two different things.
1) When you say " there are a handful of newer BUFR descriptors whose range
of values don't fit into 32 bits and therefore do require 8 bytes, and
which is why I've suggested making that the new default and just tailoring
all newly-developed interfaces to that build", I'm just pointing out that
the bufr range of values which need 8 bytes to fit in are already taken
care of by the 8byte arrays which go into or out of the bufrlib calls in
each of the libraries now, unless I'm missing something. And by the way, if
you are suggesting only maintaining bufrlib_d or bufrlib_8, it seems to me
that makes more trouble than it saves. I think bufrlib_4 is the one to
focus on.
2) As for the unit numbers and dimensions, return codes, etc, they can be
explicitly defined as 4 bytes in "pure" 8 byte app codes. They will
probably never need 8 bytes themselves. The mbay array does have an
allocated dimension, which I assume could be used instead of '*'. Bottom
line, I think that reduction to just the 4 byte bufrlib would require a
smaller amount of changes, in a smaller number of codes, than other
alternatives which have been discussed.
…On Mon, Jan 24, 2022 at 2:39 PM Jeff Ator ***@***.***> wrote:
The bufrlib inputs and outputs are all already 8 bytes. You don't need
different libraries for that.
@jack-woollen <https://github.com/jack-woollen> please clarify what you
mean by this. Specifically, when a user application calls, e.g. SUBROUTINE
WRITSB(LUNIT), how does the subroutine know whether LUNIT was declared
(or compiled) as a 4-byte or 8-byte integer in the calling program? This
isn't mandated in the library itself, which just lets it be implicitly
declared as an integer. Similarly, when an application code calls FUNCTION
IUPBS01(MBAY,S01MNEM), the array MBAY is just implicitly declared
internally as DIMENSION MBAY(*), so how does the function know whether
each array member is 4 or 8 bytes long in the calling program? Since we
never defined these interfaces explicitly in the past, that's part of the
reason we now have this ambiguity.
Unless I'm missing something, the only things that are explicitly declared
as 8 bytes within the library itself are the REAL values arrays that get
passed into and out of subroutines such as UFBINT, UFBREP, etc.
Pretty-much every other integer or real call parameter to the library
doesn't have an explicit length specified.
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6KGXBGUWWYQUVC2LW3UXWTFJANCNFSM4TYNIUTQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Even if we still use BUFR files for archival/direct input to JEDI/IODA, that should still greatly simplify the codes that use BUFR libraries, no? We are already in the process of removing preprocessing (prepobs, etc.) code to put everything in JEDI UFO, so I think it's important to look at this with the lens of one unified software system (written in C++) will handle observation ingest once legacy systems are retired. The only other use that I could think of would be verification/MET+. Tagging @ADCollard @emilyhcliu for awareness/input. |
Also to comment on @edwardhartnett 's quote "OK, so this is our bufr solution for NOAA for the next several decades." I think that is a chilling thought. This current BUFR library has pieces old enough to run for senate. This warrants thought on what the BUFR library at NCEP will look like in 2040. |
On a related note, I don't think that any library subroutine or function which is never intended to be directly called from application codes should be on the list. Specifically, I noted
which I don't think should ever be called from outside of the library, and which I therefore don't think should need wrappers. |
Saving a transcript of recent email discussions into this GitHub issue, for the record... On Tue, Oct 18, 2022 at 3:49 PM Jeff Ator - NOAA Federal <jeff.ator@noaa.gov> wrote:
|
@jack-woollen I copied a transcript of our recent email discussion to this GitHub issue, so we have a record of it here. And based on the outcome of that discussion, I also just updated the Only detail I wanted to point out to you was in drfini.f. In that routine, we need to call X48 for both an array (MDRF) and for two scalars (LUNIT and NDRF), and the Gnu compiler squawks if you have different ranks for any argument between different calls to the same routine from within the same program block. So I just declared each of those two scalars as single-member arrays within drfini.f, and that resolved it. Take a look if you like and let me know if you have any questions. |
Jeff
My only question is does it work?
Jack
…On Mon, Oct 24, 2022 at 2:17 PM Jeff Ator ***@***.***> wrote:
@jack-woollen <https://github.com/jack-woollen> I copied a transcript of
our recent email discussion to this GitHub issue, so we have a record of it
here. And based on the outcome of that discussion, I also just updated the
r8wraps branch to use X48 and X84 in all of the routines for which we've
already developed I*8 wrappers. We've still got many more to go, but we're
making progress!
Only detail I wanted to point out to you was in drfini.f. In that routine,
we need to call X48 for both an array (MDRF) and for two scalars (LUNIT and
NDRF), and the Gnu compiler squawks if you have different ranks for any
argument between different calls to the same routine from within the same
program block. So I just declared each of those two scalars as
single-member arrays within drfini.f, and that resolved it. Take a look if
you like and let me know if you have any questions.
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6LSRZARAUKXY22FKYTWE3HERANCNFSM4TYNIUTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
It did when I ran the CI tests for both Intel and Gnu. The drfini routine is called from within two of the CI test programs (test_OUT_4.f and test_OUT_6.f) in the test subdirectory of the library bundle, and they both passed. |
👍👍
…On Mon, Oct 24, 2022 at 2:31 PM Jeff Ator ***@***.***> wrote:
Jeff My only question is does it work? Jack
It did when I ran the CI tests for both Intel and Gnu. The drfini routine
is called from within two of the CI test programs (test_OUT_4.f and
test_OUT_6.f) in the test subdirectory of the library bundle, and they both
passed.
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6IEB6V3CADPUEYFVDLWE3IZPANCNFSM4TYNIUTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Hey @jack-woollen, maybe I'm missing something obvious, but from a user perspective what's the difference between copysb and ufbcpy? I see the former calls the latter for compressed subsets, but for documentation purposes I'd like to better understand why a user would call one vs. the other in the first place? On a related note, I'd also like to better understand how ufbcup fits into the mix, and under what circumstances it would make sense for a user to call ufbcup instead of ufbcpy or copysb. (Thanks! ;-) |
@jeff Ator - NOAA Federal ***@***.***>
Wow, you're digging into the olden days with these questions!
Re ufbcpy and copysb, ufbcpy copies the inv and val arrays from one open
subset to another, whereas copysb does the equivalent of readsb and writsb.
Subroutine ufbcup was written to copy elements like ufbcpy does, except it
can copy elements into an output subset that could be a superset of the
input subset.
Welcome 😊
…On Mon, Oct 24, 2022 at 5:36 PM Jeff Ator ***@***.***> wrote:
Hey @jack-woollen <https://github.com/jack-woollen>, maybe I'm missing
something obvious, but from a user perspective what's the difference
between copysb and ufbcpy? I see the former calls the latter for compressed
subsets, but for documentation purposes I'd like to better understand why a
user would call one vs. the other in the first place?
On a related note, I'd also like to better understand how ufbcup fits into
the mix, and under what circumstances it would make sense for a user to
call ufbcup instead of ufbcpy or copysb.
(Thanks! ;-)
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6LQZ7EW35WT53DRS23WE36PFANCNFSM4TYNIUTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I hope all these historical details make it into the appropriate doxygen documentation, so they are captured for future users and maintainers, who will be working on this code long after we have all retired. ;-) |
@edwardhartnett I'm trying to update the Doxygen documentation as I go, which is the main reason I asked those questions ;-) @jack-woollen as I'm looking at ufbqcd and ufbqcp I'm seeing another potential issue. Each of those has a "real" as a calling argument (QCD is output from ufbqcd, whereas QCP is input to ufbqcp). But since it's not explicitly declared as "real*4" or "real*8" in either routine, then it seems we have a similar issue like we did before for integers, and where we ended up needing to use x48 and x84 to go back and forth between 4-byte and 8-byte values in order to be able to converge everything into a single library build. In this case, there probably aren't too many codes out there which call either routine, so do you happen to know if those are currently compiled with 4-byte reals or 8-byte reals? If so, then maybe we just explicitly declare them accordingly within both of those routines - thoughts? |
Or, another possible option... By my understanding, QCP and QCD really only ever hold integer values anyway, so is there any reason we couldn't just change them to integers (IQCP and IQCD?) in these routines and then use x48 and x84? These updates are all going to be part of a new 12.0.0 (major version) release anyway, so there's an implicit understanding that folks may need to make some tweaks to their application codes to work with the updated library anyway, and so we could just document these real->integer type changes in the documentation and in the user guide and release notes so that everyone's aware. Thoughts? |
@jeff Ator - NOAA Federal ***@***.***>
AFAIK, these codes, which were specifically written for prepobs codes, are
only used by them, and are all compiled with 4 byte reals. It might make
more sense to leave them be.
prepobs_cqcbufr.fd/cqcbufr.f:C BUFRLIB - CLOSBF OPENBF READMG
UFBQCD CLOSMG COPYMG
prepobs_cqcbufr.fd/cqcbufr.f: CALL UFBQCD(NFIN,'CQCHT',CQCPC)
prepobs_cqcbufr.fd/cqcbufr.f: CALL UFBQCD(NFIN,'VIRTMP',VTPPC)
prepobs_cqcbufr.fd/cqcbufr.f: CALL UFBQCD(NFIN,'RADCOR',RADPC)
prepobs_prepdata.fd/prepdata.f:C 'UFBQCD' TO ENCODE PGM CODE FOR
PREPDATA INTO PREPBUFR; CAN
prepobs_prepdata.fd/prepdata.f:C UFBINT WRITSB
UFBCNT UFBQCD DATELEN
prepobs_prepdata.fd/prepdata.f: CALL UFBQCD(IUNITP,'PREPRO',PCODE)
prepobs_prepacqc.fd/prepacqc.f:c - OPENBF CLOSBF
UFBQCD SETBMISS GETBMISS
prepobs_prepacqc.fd/prepacqc.f: call
ufbqcd(outlun,'NRLACQC',nrlacqc_pc)
prepobs_profcqc.fd/profcqc.f:C UFBQCD WRITSB UFBCNT
SETBMISS GETBMISS
prepobs_profcqc.fd/profcqc.f: CALL UFBQCD(NFIN,'CQCPROF',CQCPC)
syndat_syndata.fd/syndata.f:C READSB UFBQCD UFBCPY
UFBINT WRITSB
syndat_syndata.fd/syndata.f: CALL UFBQCD(IUNTPO,'SYNDATA',SYNPC)
gblevents.fd/gblevents.f:C> BUFRLIB - UFBINT UFBQCD
GETBMISS IBFMS
gblevents.fd/gblevents.f: CALL UFBQCD(IUNITP,'PREVENT',PVCD)
gblevents.fd/gblevents.f: CALL UFBQCD(IUNITP,'VIRTMP ',VTCD)
prepobs_prevents.fd/gblevents_cdas.f:C BUFRLIB - UFBINT UFBQCD
GETBMISS
prepobs_prevents.fd/gblevents_cdas.f: CALL
UFBQCD(IUNITP,'PREVENT',PVCD)
prepobs_prevents.fd/gblevents_cdas.f: CALL UFBQCD(IUNITP,'VIRTMP
',VTCD)
prepobs_cqcvad.fd/cqcvad.f:C BUFRLIB - DATELEN CLOSBF OPENBF
READMG UFBQCD
prepobs_cqcvad.fd/cqcvad.f: CALL UFBQCD(IUNIT,'CQCVAD ',CQCPC)
prepobs_glerladj.fd/glerlmain.f90:! readsb setbmiss
ufbcnt ufbcpy ufbevn ufbint ufbpos ufbqcd
prepobs_glerladj.fd/glerlmain.f90: call ufbqcd(13,'VIRTMP',vtcd)
prepobs_glerladj.fd/glerlmain.f90: call ufbqcd(13,'GLERL',pcode)
prepobs_oiqcbufr.fd/oiqcbufr.f:C OPENBF UFBQCD UFBINT
WRITSB UFBCNT
prepobs_oiqcbufr.fd/oiqcbufr.f: CALL UFBQCD(LUBIN,'OIQC',QCD)
…On Thu, Oct 27, 2022 at 1:33 PM Jeff Ator ***@***.***> wrote:
@edwardhartnett <https://github.com/edwardhartnett> I'm trying to update
the Doxygen documentation as I go, which is the main reason I asked those
questions ;-)
@jack-woollen <https://github.com/jack-woollen> as I'm looking at ufbqcd
and ufbqcp I'm seeing another potential issue. Each of those has a "real"
as a calling argument (QCD is output from ufbqcd, whereas QCP is input to
ufbqcp). But since it's not explicitly declared as "real*4" or "real*8"
in either routine, then it seems we have a similar issue like we did before
for integers, and where we ended up needing to use x48 and x84 to go back
and forth between 4-byte and 8-byte values in order to be able to converge
everything into a single library build.
In this case, there probably aren't too many codes out there which call
either routine, so do you happen to know if those are currently compiled
with 4-byte reals or 8-byte reals? If so, then maybe we just explicitly
declare them accordingly within both of those routines - thoughts?
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6IKLG75FZLVWARUT63WFK4FHANCNFSM4TYNIUTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Thanks Jack. I'm happy to leave them be if you're fairly confident that all of those codes are compiled using 4-byte reals. Alternatively, did you see my other suggestion about maybe just converting QCD and QCP from reals to integers (IQCD and IQCP?) within those two routines and then using x48 and x84 like we do for other integers? Not sure why those variables may have even been declared as reals in the first place, since unless I'm missing something they really should only ever contain integer values anyway. |
I agree they should really be integers. Don't remember why they were made
real in the first place. But since they are so specialized, I hesitate to
make the prepobs folks have to make changes in all those codes just for
that. Although, maybe it is a case of forcing some changes now so as not to
get bitten later on.
…On Thu, Oct 27, 2022 at 5:29 PM Jeff Ator ***@***.***> wrote:
Thanks Jack. I'm happy to leave them be if you're fairly confident that
all of those codes are compiled using 4-byte reals.
Alternatively, did you see my other suggestion about maybe just converting
QCD and QCP from reals to integers (IQCD and IQCP?) within those two
routines and then using x48 and x84 like we do for other integers? Not sure
why those variables may have even been declared as reals in the first
place, since unless I'm missing something they really should only ever
contain integer values anyway.
—
Reply to this email directly, view it on GitHub
<#78 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AO3XO6OT5DH2CDJIORZIFBTWFLX4DANCNFSM4TYNIUTQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Hey @jack-woollen, just an FYI that I pushed another commit up to the Specifically, we've only been worrying about adding _8 wrappers to user-callable library routines which have integer call arguments. So, for example, we hadn't added _8 wrappers to iupbs01 or iupbs3 because they didn't have any integer call arguments which required using x84 and/or x48. However, this leads to a problem when such routines internally call other user-callable library routines which do contain such wrappers. For example, iupbs01 internally calls gets1loc and i4dy, and iupbs3 internally calls getlens. And in those cases, if the application program previously called setim8b because it was compiled using 8-byte integers, then those internal calls to gets1loc, i4dy, and getlens end up getting made with im8b still set to .true., even though they're being internally called from within iupbs01 or iupbs3 which now themselves are only compiled as _4 as part of the library. And, in turn, this means that those internally-called routines are now themselves calling x84 and x48 when they shouldn't be. These errors quickly showed up when I began testing out some of the test code mods noted above. So to resolve this, we need to make sure that any user-callable subroutine or function in the library contains an internal _8 wrapper, even if the routine itself doesn't have any integer call arguments. That way, we know that im8b will have been switched to .false. before any internal calls are made to any other user-callable library routines. You can see where I made this change to iupbs01 and iupbs3 as part of this commit. |
Testing is a wonderful thing! Sounds like a good solution. Clearly defining the 4byte and 8byte pathways through common subroutines. Kind of head spinning. |
This will come after #77
Currently we build 3 flavors of the library, 4, 8, and D. Instead, use fortran interfaces and kinds to provide one library that handles all three cases.
Not sure when this should happen, we want to try this out on a simpler project first.
The text was updated successfully, but these errors were encountered: