fprintf() C variables into FORTRAN input file format ???

G

google

first, a little background...

i have a C program which preprocesses some data, and then outputs the
results into a text file. that text file, in turn, is used as input
to a FORTRAN computational fluid dynamics (CFD) program. the FORTRAN
program goes to work on the provided data, and outputs a text file
which i read back in with another C program to postprocess the data
and analyze the results of the CFD run.

now on to the problem. the input file to the FORTRAN CFD program is
in the following format (which may look familiar to folks well versed
in FORTRAN, which i'm not):
(ronin)$ cat boundedmatrix.in
1.0D0 ! Ratio
1.5D0 ! AXMAX
1 ! NPNAX
1D-1 ! B
0.5D0 ! GAM
18 ! NKMAX
1.7D0 ! EPS
-1 ! NP
0.6283D0 ! LAM (wavelength)
1.50D0 ! MRR (real part of the refractive index)
0.02D0 ! MRI (imag part of the refractive index)
0.00001D0 ! DDELT
181 ! NPNA (number of angles)
2 ! NDGS

the format of the FORTRAN input parameters, as you can see, carries
the precision of the value with it. e.g., 1.0D0 is a double precision
value X 10^0. and, 1D-1 is a double precision value X 10^-1.

now then, i'm a complete novice when it comes to FORTRAN, and denoting
the value precision in the input file in this way seems, to this C
programmer, to be a little odd. but nevertheless that's the way it
is.

does anyone have any ideas on how i might get my fprintf()'s to output
these kinds of values without a lot of gymnastics? i've taken a
couple of simplistic runs at it but i haven't gotten anywhere except
really-frustrated-ville. it appears that it should be easy to do but
i haven't found a clever way yet. of course i know ahead of time
which of my C variables are double precision and so forth. for that
matter i know a priori which variables the FORTRAN program are
expected to be in double precision.

note that it is no way possible for me to modify the FORTRAN program,
it's a NSF-sourced CFD code and if i touch it i can look forward to
about 10 years of verification tests. each CFD run is taking about 6
hours on a 512 processor SGI Origin box as it is. so the solution can
not include "tweaking" the FORTRAN code in any way. i have to treat
the CFD program as an immutable black box.

ideas, thoughts, catalysts, FORTRAN-conversion.c source, hate mail,
etc are all welcome.

thanks
jim
 
M

Malcolm

google said:
1.0D0 is a double precision value X 10^0. and, 1D-1 is a double
precision value X 10^-1.

does anyone have any ideas on how i might get my fprintf()'s to
output these kinds of values without a lot of gymnastics?
All you need is a function

void dbltofortan(FILE *fpout, double x)
{
double lg = log10(x);
fprintf(fp, "%gD%d", x / pow(10, floor(lg)), floor(lg));
}

Hope this is right (untested).
 
A

Arthur J. O'Dwyer

now on to the problem. the input file to the FORTRAN CFD program is
in the following format (which may look familiar to folks well versed
in FORTRAN, which i'm not):
(ronin)$ cat boundedmatrix.in
1.0D0 ! Ratio
1.5D0 ! AXMAX
1 ! NPNAX
1D-1 ! B
0.5D0 ! GAM
the format of the FORTRAN input parameters, as you can see, carries
the precision of the value with it. e.g., 1.0D0 is a double precision
value X 10^0. and, 1D-1 is a double precision value X 10^-1.

The 'D', I suppose, represents significant figures somehow? That is,
is the value 0.1D0 different from the value 1D-1? If so, then I think
you'll have to cope with the fact that C's "float" and "double" values
don't have any concept of "significant figures," so you're going to
lose some information somewhere.
If 0.1D0 and 1D-1 are in fact the same value, then you should just
be able to write something like this, to append "D0" to the end of
each floating-point value you print:

#include <stdio.h>

int main(void)
{
double fieldval = 4.52;
const char *fieldname = "FOO";

char buffer[20];
sprintf(buffer, "%gD0", fieldval);
printf("%-20s! %s\n", buffer, fieldname);
return 0;
}

Does this solve your problem?

HTH,
-Arthur
 
B

Barry Schwarz

now on to the problem. the input file to the FORTRAN CFD program is
in the following format (which may look familiar to folks well versed
in FORTRAN, which i'm not):
(ronin)$ cat boundedmatrix.in
1.0D0 ! Ratio
1.5D0 ! AXMAX
1 ! NPNAX
1D-1 ! B
0.5D0 ! GAM
the format of the FORTRAN input parameters, as you can see, carries
the precision of the value with it. e.g., 1.0D0 is a double precision
value X 10^0. and, 1D-1 is a double precision value X 10^-1.

The 'D', I suppose, represents significant figures somehow? That is,
is the value 0.1D0 different from the value 1D-1? If so, then I think
you'll have to cope with the fact that C's "float" and "double" values
don't have any concept of "significant figures," so you're going to
lose some information somewhere.
If 0.1D0 and 1D-1 are in fact the same value, then you should just
be able to write something like this, to append "D0" to the end of
each floating-point value you print:

#include <stdio.h>

int main(void)
{
double fieldval = 4.52;
const char *fieldname = "FOO";

char buffer[20];
sprintf(buffer, "%gD0", fieldval);
printf("%-20s! %s\n", buffer, fieldname);
return 0;
}

Does this solve your problem?

HTH,
-Arthur
If your values will have a large range of exponents (rather than the
small range of -1 to 0 in the sample), use the %E format specification
with sprintf and then change the 'E' to 'D' in the string before
writing it to the file. The width and precision modifiers can provide
some additional control.


<<Remove the del for email>>
 
T

Tim Prince

google said:
first, a little background...

i have a C program which preprocesses some data, and then outputs the
results into a text file. that text file, in turn, is used as input
to a FORTRAN computational fluid dynamics (CFD) program. the FORTRAN
program goes to work on the provided data, and outputs a text file
which i read back in with another C program to postprocess the data
and analyze the results of the CFD run.

now on to the problem. the input file to the FORTRAN CFD program is
in the following format (which may look familiar to folks well versed
in FORTRAN, which i'm not):
(ronin)$ cat boundedmatrix.in
1.0D0 ! Ratio
1.5D0 ! AXMAX
1 ! NPNAX
1D-1 ! B
0.5D0 ! GAM
18 ! NKMAX
1.7D0 ! EPS
-1 ! NP
0.6283D0 ! LAM (wavelength)
1.50D0 ! MRR (real part of the refractive index)
0.02D0 ! MRI (imag part of the refractive index)
0.00001D0 ! DDELT
181 ! NPNA (number of angles)
2 ! NDGS

the format of the FORTRAN input parameters, as you can see, carries
the precision of the value with it. e.g., 1.0D0 is a double precision
value X 10^0. and, 1D-1 is a double precision value X 10^-1.

now then, i'm a complete novice when it comes to FORTRAN, and denoting
the value precision in the input file in this way seems, to this C
programmer, to be a little odd. but nevertheless that's the way it
is.

does anyone have any ideas on how i might get my fprintf()'s to output
these kinds of values without a lot of gymnastics? i've taken a
couple of simplistic runs at it but i haven't gotten anywhere except
really-frustrated-ville. it appears that it should be easy to do but
i haven't found a clever way yet. of course i know ahead of time
which of my C variables are double precision and so forth. for that
matter i know a priori which variables the FORTRAN program are
expected to be in double precision.

note that it is no way possible for me to modify the FORTRAN program,
it's a NSF-sourced CFD code and if i touch it i can look forward to
about 10 years of verification tests. each CFD run is taking about 6
hours on a 512 processor SGI Origin box as it is. so the solution can
not include "tweaking" the FORTRAN code in any way. i have to treat
the CFD program as an immutable black box.
You don't need to go to any trouble, any g or f format will work, as Fortran
reads accept [DEe] as equivalent. As in C, the format of the input doesn't
affect whether it is read as single (float) or double precision. The
comments are probably optional.
 
D

Dan Pop

In said:
now on to the problem. the input file to the FORTRAN CFD program is
in the following format (which may look familiar to folks well versed
in FORTRAN, which i'm not):
(ronin)$ cat boundedmatrix.in
1.0D0 ! Ratio
1.5D0 ! AXMAX
1 ! NPNAX
1D-1 ! B

the format of the FORTRAN input parameters, as you can see, carries
the precision of the value with it. e.g., 1.0D0 is a double precision
value X 10^0. and, 1D-1 is a double precision value X 10^-1.

As Tim Prince mentioned, this is true in Fortran source code, where
1.0D0 is a double precision constant, while 1.0E0 is a single precision
constant. In READ statements, the precision is already known from the
way the variable was declared, so both D and E are accepted.
now then, i'm a complete novice when it comes to FORTRAN, and denoting
the value precision in the input file in this way seems, to this C
programmer, to be a little odd. but nevertheless that's the way it
is.

does anyone have any ideas on how i might get my fprintf()'s to output
these kinds of values without a lot of gymnastics?

You only need a minimal amount of gymnastics, if you *really* want to
use 'D' instead of 'E': use sprintf with the %E format, then use strchr
to find the first 'E' character and replace it by 'D'. Output the
string to the file with fputs.

char line[LINESIZE], *p;
double ratio;
FILE *fp;
....
sprintf(line, "%-20E! Ratio\n", ratio);
if ((p = strchr(line, 'E')) != NULL) *p = 'D';
fputs(line, fp);

I used %-20E instead of a plain %E so that your comments get nicely
aligned, as in your example above. You may also want to use a precision
specification, if the values are computed in your program with more
precision than the default six digits implied by the absence of a
precision specification.

In the pathological case when the value is a NaN, my if statement may
replace an 'E' inside a comment by a 'D' ;-) If NaN's in the input
file are a real option, you can avoid this by adding an extra check:

if (ratio == ratio && (p = strchr(line, 'E')) != NULL) *p = 'D';

NaNs don't compare equal, so a NaN-aware compiler cannot assume that
ratio == ratio always evaluates to true. And this test is more portable
than the isnan macro (which need not be supported by C89 implementations).

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top