Implementing getarg subroutine call - fortran

I've written a program in F90 which reads in a few input arrays from text files and then combines them through a function to a single output file. One of the input files is named for the day the data was collected using MMDDYY.tuvr and the output file is then named MMDDYY.fxi . I'd like to be able to input the MMDDYY of the data in the command line when running the program instead of having to manually change the code and compile each time, which is why I'm attempting to use getarg, but I cannot seem to make it work properly. The code im attempting to use is listed below (just shows the get arg and the open commands and not the entire program since this is where I'm having trouble):
CHARACTER(len=20) :: arg, tuvrname, fxiname
CALL getarg(1, arg)
IF(LEN_TRIM(arg) == 0) THEN
print*,'No date provided'
STOP
ELSE
tuvrname = TRIM(arg)'.tuvr'
fxiname = TRIM(arg).'fxi'
ENDIF
OPEN(1, file = tuvrname, status='old', action='read')
....
OPEN(4, file = fxiname, status='replace', action='write')
I also tried just using two separate getarg commands and entering MMDDDYY.tuvr MMDDYY.fxi in the command line and the program ran, but it could not seem to find my TUVR file as the output was empty.

I am not really experienced in using getarg. I use get_command_argument from Fortran 2003. I think you just forgot to use // to concatenate the strings.
CHARACTER(len=20) :: arg, tuvrname, fxiname
CALL getarg(1, arg)
IF(LEN_TRIM(arg) == 0) THEN
print*,'No date provided'
STOP
ELSE
tuvrname = TRIM(arg)//'.tuvr'
fxiname = TRIM(arg)//'.fxi'
ENDIF
print *, tuvrname, fxiname
end
or
CHARACTER(len=20) :: arg, tuvrname, fxiname
if (command_argument_count()<1) then
stop "Provide the file name."
end if
CALL get_command_argument(1, value=arg)
tuvrname = TRIM(arg)//'.tuvr'
fxiname = TRIM(arg)//'.fxi'
print *, tuvrname, fxiname
end

Related

Trying to write to end of file, but overwriting instead

Im using a microblaze soft processor on a Basys3 dev board. I am able to write a text file to an SD card but I am trying to write to the end of the file. Currently it overwrites anything that's in the file. Im using the DFATFS functions to do the writing. The Basys3 has a PMOD uSD reader attached.
I've tried using the fslseek function in DFATFS to move the file pointer to the end of file but it still writes to the beginning.
//the subroutine to print to the SD card
void SD(int32_t rando, int addr, int bit, int pc) {
DXSPISDVOL disk(XPAR_PMODSD_0_AXI_LITE_SPI_BASEADDR,
XPAR_PMODSD_0_AXI_LITE_SDCS_BASEADDR);
DFILE file;
int eof;
char printline[128];
sprintf(printline, "\nLFSR: %d ", rando);
// The drive to mount the SD volume to.
// Options are: "0:", "1:", "2:", "3:", "4:"
static const char szDriveNbr[] = "0:";
// Mount the disk
DFATFS::fsmount(disk, szDriveNbr, 1);
xil_printf("Disk mounted\r\n");
fr = file.fsopen("output.txt", FA_WRITE | FA_OPEN_ALWAYS);
if (fr == FR_OK) {
file.fslseek(0);
file.fswrite(printline, 12, &bytesWritten);
fr = file.fsclose();
} else {
xil_printf("Failed to open file to write to\r\n");
}
}
I expect the code to move the file pointer to the end of the file and print a new line after the previous one. When stepping through the program (multiple times through the print subroutine) but it always overwrites.

Issue with character variables when using call system in Fortran

I am using a Fortran user subroutine (UMAT) in Abaqus. I use it to run other Abaqus sub-calculations within my main calculation.
The sub-calculation names are variables, so I am defining them this way:
character (len=256) :: strJOB,strOLDJOB
character (len=256) :: strGoToWorkPath,strCommand,strCmdLine
character (len=256) :: temp, strNOEL, strNPT, striCalcs, striCalcsPrev
write(temp, '(i6)') NOEL
read(temp, *) strNOEL
temp = ''
write(temp, '(i6)') NPT
read(temp, *) strNPT
temp = ''
write(temp, '(i6)') iCalcs
read(temp, *) striCalcs
temp = ''
write(temp, '(i6)') (iCalcs-1)
read(temp, *) striCalcsPrev
temp = ''
strJOB = "micro_" // trim(strNOEL) //"_"// trim(strNPT) // "_" // trim(striCalcs)
strOLDJOB = "micro_" // trim(strNOEL) //"_"// trim(strNPT) //"_"// trim(striCalcsPrev)
strGoToWorkPath = "cd C:\AbaqusCalc"
strCommand = "abaqus interactive job=" // trim(strJOB) // " oldjob=" // trim(strOLDJOB)
strCmdLine = trim(strGoToWorkPath) // ' && ' // trim(strCommand)
And then I just use call system(trim(strCmdLine)) to run my sub-calculation.
What is making me mad is that this works for some sub calculations (sometimes just 1, sometimes 100, it's kinda random), but then I get some error of this kind:
Abaqus Error: The following file(s) could not be located: micro_1_1_1#.odb
where # is always a "strange" character (you can see an example here https://www.dropbox.com/s/82b7u7enlxpc62e/1.jpg?dl=0 ). I can confirm (via debug or writing on a file the character variable strCmdLine) that I am executing correctly with the argument "oldjob=micro_1_1_1", like this:
cd C:\AbaqusCalc && abaqus interactive job=micro_1_1_2 oldjob=micro_1_1_1
In some cases Abaqus can find and process the oldjob (file micro_1_1_1.odb), but in another cases he just sticks that strange character between the end of the filename and the ".odb" extension.
My questions would be:
Is this related with the call system() function?
Can this be an error related with Abaqus and not with Fortran?
Is there any other way that I can use to call my Abaqus calculations, instead of call system?
Just something to try, this construct looks perfectly correct
strJOB = "micro_" // trim(strNOEL) //"_"// trim(strNPT) // "_" // trim(striCalcs)
however it can be done I think more neatly using a single internal write:
write(strJOB,'("micro_",i0,"_",i0,"_",i0)')NOEL,NPT,iCalcs
note the i0 nicely takes care of the blanks and strJOB is blank padded out to 256 characters in both cases.

How to run a mixed C++/Fortran project under Eclipse IDE?

I was trying to compile a mixed programming lanaguage (C++/Fortran) sample project provided by Intel Compiler 2013 under Eclipse IDE. I can run this project successfully under Visual Studio IDE (on Windows OS system), but I have not figured out how to run the same project under Eclipse on Linux. The configuration of linking the Fortran to the C++ project in Eclipse IDE is the main issue that troubles me.
Could anyone please tell me how to link these two projects? Thanks. The output should be simple "Testing...123."
Li
The source codes are as follows:
(1) the main program, fmain.f90
PROGRAM fmain
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
INTERFACE
SUBROUTINE c_routine (int_arg, str_in, str_out, str_out_len) BIND(C)
IMPORT ! Use declarations from host
INTEGER(C_INT), VALUE,INTENT(IN) :: int_arg
CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: str_in
CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(OUT) :: str_out
INTEGER(C_INT), VALUE, INTENT(IN) :: str_out_len
END SUBROUTINE c_routine
END INTERFACE
CHARACTER(80) OUTPUT_TEXT
INTEGER IN_ARG, OUTPUT_LEN
CHARACTER(80) INPUT_TEXT
INPUT_TEXT = "Testing..."//C_NULL_CHAR
IN_ARG = 123
CALL c_routine (IN_ARG, INPUT_TEXT, OUTPUT_TEXT, LEN(OUTPUT_TEXT))
OUTPUT_LEN = INDEX(OUTPUT_TEXT," ")
IF (OUTPUT_LEN == 0) OUTPUT_LEN = len(OUTPUT_TEXT)
WRITE (*,*) OUTPUT_TEXT(1:OUTPUT_LEN)
END
(2) csub.cpp
#include <stdio.h>
extern "C" void c_routine (
int int_arg, // integer to convert
char* input_text, // text to prepend to converted integer
char* output_text, // output buffer
int output_text_len // length of output buffer
)
{
sprintf_s(output_text,output_text_len,"%s%i ",input_text,int_arg);
}

formatting printf statement in cpp file

I have a cpp file within an xcode application, but am having trouble formatting the printf correctly.
My code is:
b2Vec2 axisA = b2MulT(xfA.R, m_axis);
printf("axis A = XXX", axisA);
I need to know what to put in XXX to print out the value of the 'axisA' variable.
Thanks
Printf accepts only plain data types, so you need to break it down:
printf("axis A = (%f,%f)", axisA.x, axisA.y);
or
printf("axis A = (%g,%g", axisA.x, axisA.y);

How to eliminate the '\n' at the end of a txt file

I'd like to eliminate the extra '\n' at the end of a txt file. Which function can be used to do this job in c / c++.
Thanks advanced
One approach would be to iterate of the file line-by-line using getline, saving off that data for later. After each line is read, write the previous line (with \n). When no more data is available write the final line without the \n anymore.
Alternately seek to the end to get the size, read the data in blocks of some chunk size, rewriting them until the second-to-last character. If the last character is a \n don't write it, otherwise do write it.
The posix way to do this is the truncate function.
If you get the length of the file using seek or another OS call you can use truncate to
trim the last char of the length of the file without rewriting the whole thing.
//This RESIZES the file without the need to REWRITE the whole thing:
struct stat fileStat;
stat("Filename", &fileStat);
status = truncate("Filename",fileStat.st_size-1);
The windows equivalent function is chsize however it requires opening a file first:
// Open a file
if( _sopen_s( &fh, "data", _O_RDWR | _O_CREAT, _SH_DENYNO,
_S_IREAD | _S_IWRITE ) == 0 )
{
if( ( result = _chsize( fh, _filelength( fh ) -1 ) ) == 0 )
printf( "Size successfully changed\n" );
else
printf( "Problem in changing the size\n" );
_close( fh );
}