Passing arrays to lua as function argument from Fortran - arrays

I am looking for Fortran examples (also interface function) to pass arrays as arguments to lua functions. I was able to use fortlua project to start. But the example provided passes one element at a time. Appreciate any help.
--Lua code
local q1
local q2
function getoutput( qout1, qout2)
-- qout1 and qout2 are arrays with some dimension
q1 = qout1
q2 = qout2
end
-- in fortran I used
config_function('getoutput', args, 2, cstatus)
But setting the args is where I am looking for some help. The following code does the job for scalar argument variable not an array I guess.
!> Evaluate a function in the config file and get its result.
FUNCTION config_function(name,args,nargs,status)
REAL :: config_function
CHARACTER(LEN=*) :: name
REAL, DIMENSION(nargs) :: args
REAL(KIND=c_double) :: anarg
INTEGER :: nargs
INTEGER :: status
INTEGER :: iargs
INTEGER(c_int) :: stackstart
stackstart = lua_gettop(mluastate)
config_function = 0
status = 0
CALL lua_getglobal(mluastate,TRIM(name)//C_NULL_CHAR)
IF ( lua_type(mluastate,-1) .eq. LUA_TFUNCTION ) THEN
DO iargs = 1,nargs
anarg = args(iargs)
CALL lua_pushnumber(mluastate,anarg)
ENDDO
IF (lua_pcall(mluastate,nargs,1,0) .eq. 0) THEN
if (lua_isnumber(mluastate,-1) .ne. 0) THEN
config_function = lua_tonumber(mluastate,-1)
CALL lua_settop(mluastate,-2)
ELSE
! Nothing to pop here
status=-3
ENDIF
ELSE
CALL lua_settop(mluastate,-2)
status=-2
ENDIF
ELSE
CALL lua_settop(mluastate,-2)
status=-1
ENDIF
IF (stackstart .ne. lua_gettop(mluastate)) THEN
WRITE(*,*) 'The stack is a different size coming out of config_function'
ENDIF
END FUNCTION config_function

To expand a little bit on my comment, here is a small program implementing an array argument with the help of Aotus:
program aot_vecarg_test
use flu_binding, only: flu_State, flu_settop
use aotus_module, only: open_config_file, close_config
use aot_fun_module, only: aot_fun_type, aot_fun_do, &
& aot_fun_put, aot_fun_open, &
& aot_fun_close
use aot_references_module, only: aot_reference_for, aot_reference_to_top
use aot_table_module, only: aot_table_open, aot_table_close, &
& aot_table_from_1Darray
implicit none
type(flu_State) :: conf
type(aot_fun_type) :: luafun
integer :: iError
character(len=80) :: ErrString
real :: args(2)
integer :: argref
integer :: arghandle
args(1) = 1.0
args(2) = 2.0
call create_script('aot_vecarg_test_config.lua')
write(*,*)
write(*,*) 'Running aot_vecarg_test...'
write(*,*) ' * open_config_file (aot_vecarg_test_config.lua)'
call open_config_file(L = conf, filename = 'aot_vecarg_test_config.lua', &
& ErrCode = iError, ErrString = ErrString)
if (iError /= 0) then
write(*,*) ' : unexpected FATAL Error occured !!!'
write(*,*) ' : Could not open the config file aot_ref_test_config.lua:'
write(*,*) trim(ErrString)
STOP
end if
write(*,*) ' : success.'
! Create a table with data
call aot_table_from_1Darray( L = conf, &
& thandle = arghandle, &
& val = args )
! Create a reference to this table
call flu_setTop(L = conf, n = arghandle)
argref = aot_reference_for(L = conf)
! Start the processing of the function
call aot_fun_open(L = conf, fun = luafun, key = 'print_array')
! Put the previously defined table onto the stack by using the reference
call aot_reference_to_top(L = conf, ref = argref)
! Put the top of the stack to the argument list of the Lua function
call aot_fun_put(L = conf, fun = luafun)
! Execute the Lua function
call aot_fun_do(L = conf, fun = luafun, nresults = 0)
call aot_fun_close(L = conf, fun = luafun)
write(*,*) ' * close_conf'
call close_config(conf)
write(*,*) ' : success.'
write(*,*) '... Done with aot_vecarg_test.'
write(*,*) 'PASSED'
contains
subroutine create_script(filename)
character(len=*) :: filename
open(file=trim(filename), unit=22, action='write', status='replace')
write(22,*) '-- test script for vectorial argument'
write(22,*) 'function print_array(x)'
write(22,*) ' for i, num in ipairs(x) do'
write(22,*) ' print("Lua:"..num)'
write(22,*) ' end'
write(22,*) 'end'
close(22)
end subroutine create_script
end program aot_vecarg_test
This makes use of a little helping routine aot_table_from_1Darray that creates a Lua table for an array of real numbers. Have a look at its code to see how data can be put into a table.
We then create a reference to this table to easily look it up later on and pass it as an argument to the Lua function.
The example creates the corresponding Lua script itself, which defines a simple function that expects a single table as input and prints each of the tables entries. Running this yields the following output:
Running aot_vecarg_test...
* open_config_file (aot_vecarg_test_config.lua)
: success.
Lua:1.0
Lua:2.0
* close_conf
: success.
... Done with aot_vecarg_test.
PASSED
Where the two lines starting with Lua are written by the Lua function print_array.
There are other possible solutions, but I hope this gives at least some idea on how this could be done. We could also think about extending the aot_fun_put interface to take care of arrays itself.

Related

How to solve "list-directed I/O syntax error" during .CSV file reading in Fortran90?

I premise I've read many questions about this problem but I cannot solve it.
During the reading of my .csv file I get the following error:
forrtl: severe (59): list-directed I/O syntax error, unit 10, file D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv. It seems to be produced by a specific line of my .csv file attached beloew (the last one).
Here is my .CSV file:
"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162
Here is my Fortran program (it contains a main file and some modules):
program Main_NEOs_orbits_TEST
use DataType
use Constants
use DataHandling
implicit none
! Declarations
character*100 :: input_path,output_path_ast_EM_loc, input_filename_ast,input_filename_cmt, output_path, output_filename_ast
character*118 :: str_line
character*2 :: str_name
character*30, dimension (3) :: str_output
integer :: i,j,iflag, no_data_lines1,n_lines2, iReturn, num_orb_elem
type(NEO), dimension (:), allocatable :: Ast_data
! Definition of constants, paths names and file names
input_path = 'D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\'
input_filename_ast = 'test_Ast.csv'
! Reading of asteroids data
call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)
stop
end program Main_NEOs_orbits_TEST
**********************************************************************************************************************************************
module Constants
use DataType
implicit none
real(pr), parameter :: ZERO = 0.0_pr, ONE = 1.0_pr, TWO = 2.0_pr, THREE = 3.0_pr, FOUR = 4.0_pr, SEVEN = 7.0_pr
real(pr), parameter :: HALF = 0.5_pr, QUART = 0.25_pr
real(pr), parameter :: DAY = 86400.0_pr, YEAR = 365.25_pr*DAY, CENTURY = 36525.0_pr
real(pr), parameter :: KILO = 1000.0_pr
real(pr), parameter :: AU2Km = 149597870.700_pr ! (from Astronomicals Unit to kilometers)
real(pr), parameter :: tol = 1.e-9_pr
real(pr), parameter :: xmu = 1.32712440018e11_pr ! (km^3 * s^-2) xmu = G * M_Sun https://ssd.jpl.nasa.gov/astro_par.html
! Unit number for files
integer :: iu_in1 = 10 !input file
integer :: iu_in2 = 11 !input file
integer :: iu_out1 = 12 !output file
integer :: iu_out2 = 13 !output file
end module Constants
**********************************************************************************************************************************************
module DataHandling
use DataType
implicit none
contains
!***********************************************************************
subroutine read_NEOs_data(UnitNum, FilePath, FileName, DataLinesNum, NEOs_data)
!***********************************************************************
! Subroutine for reading of asteroids database
!***********************************************************************
! INPUT:
!
! OUTPUT:
!***********************************************************************
implicit none
! Arguments
integer, intent (in) :: UnitNum
character (len=*), intent (in) :: FilePath
character (len=*), intent (in) :: FileName
integer, intent (out) :: DataLinesNum
type(NEO), dimension (:), allocatable, intent(out) :: NEOs_data
!Local variables
integer :: i, iflag
open(unit = UnitNum, file = trim(FilePath) // trim(FileName), status='old', &
access = 'sequential',form = 'formatted', action='read')
! Count lines
DataLinesNum = 0
read(UnitNum,*) ! Header line
do
read(UnitNum,*,iostat = iflag)
if (iflag/=0) exit
DataLinesNum = DataLinesNum + 1
enddo
rewind(UnitNum)
! Variables allocation
allocate(NEOs_data(DataLinesNum))
! Data reading
read(UnitNum,*) ! skip header line (variables names will be assigned again)
do i = 1, DataLinesNum
read(UnitNum,*) NEOs_data(i)
enddo
close(unit = UnitNum, status='keep')
return
end subroutine read_NEOs_data
!***********************************************************************
end module DataHandling
**********************************************************************************************************************************************
module DataType
implicit none
integer, parameter :: pr = selected_real_kind (p = 15) ! original value (p = 14)
!"NEO" data type declaration
type NEO ! NEOs data :
character*20 :: pdes ! pdes Object primary designation
character*20 :: name ! IAU name Object IAU name
real(pr) :: epoch ! Epoch Epoch Julian Date (TDB)
real(pr) :: a ! a Semi-major axis (au)
real(pr) :: e ! e Eccentricity
real(pr) :: i ! i Inclination w.r.t. xy-plane (deg)
real(pr) :: om ! om Longitude of Ascending Node (deg)
real(pr) :: w ! w Argument of Perihelion wrt to ecliptic/equinox (deg)
real(pr) :: ma ! ma Mean anomaly (deg)
real(pr) :: q ! q Perihelion distance (au)
real(pr) :: ad ! ad Aphelion distance (au)
end type NEO
end module DataType
I need to mantain the format of the .csv file, so I cannot modify it.
Can you explain me why the line:
594913,'Aylo'i ,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162 produces the above said error?
Error output:
forrtl: severe (59): list-directed I/O syntax error, unit 10, file D:\OneDrive\MSc_Thesis\Projects\NEOs_orbits - TEST\InputFiles\test_Ast.csv
Image PC Routine Line Source
libifcoremdd.dll 00007FFE5DBBAA5D Unknown Unknown Unknown
libifcoremdd.dll 00007FFE5DC1B6FC Unknown Unknown Unknown
NEOs_orbits_TEST. 00007FF75BB41B9B DATAHANDLING_mp_R 53 DataHandling.f90
NEOs_orbits_TEST. 00007FF75BB43072 MAIN__ 57 Main_NEOs_orbits_TEST.f90
NEOs_orbits_TEST. 00007FF75BB4332E Unknown Unknown Unknown
NEOs_orbits_TEST. 00007FF75BB45F69 Unknown Unknown Unknown
NEOs_orbits_TEST. 00007FF75BB45E8E Unknown Unknown Unknown
NEOs_orbits_TEST. 00007FF75BB45D4E Unknown Unknown Unknown
NEOs_orbits_TEST. 00007FF75BB45FDE Unknown Unknown Unknown
KERNEL32.DLL 00007FFF269C7034 Unknown Unknown Unknown
ntdll.dll 00007FFF288A2651 Unknown Unknown Unknown
line 53: read(UnitNum,*) NEOs_data(i)
line 57: call read_NEOs_data(iu_in1, input_path, input_filename_ast, no_data_lines1, Ast_data)
Problematic line: 594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162
Vladimir explains why you can not use list directed input for this, due to the unfortunate use of inverted commas. Here is a simple version of how I might go about addressing this problem, were I doing it properly I would package things up in modules a bit more carefully:
ijb#LAPTOP-GUG8KQ9I:~/work/stack$ cat csv.f90
Module split_string_module
Type, Public :: split_string_token
Character( Len = : ), Allocatable, Public :: token
End type split_string_token
Public :: split_string
Private
Contains
Pure Subroutine split_string( separators, string, tokens )
! Split a string given the separators into an array of tokens
Implicit None
Character( Len = * ) , Intent( In ) :: separators
Character( Len = * ) , Intent( In ) :: string
Type( split_string_token ), Dimension( : ), Allocatable, Intent( Out ) :: tokens
Type( split_string_token ) :: new_token
Character( Len = : ), Allocatable :: current
Integer :: split_point
Allocate( tokens( 1:0 ) )
current = string
! While we have some characters
Do While( Len( current ) > 0 )
! Find the first separator
split_point = Scan( current, separators )
If( split_point /= 0 ) Then
! We have a separator - split the string at that point
new_token%token = current( 1:split_point - 1 )
! Catch the case of the last character in the string being a separator
If( split_point + 1 <= Len( current ) ) Then
current = current( split_point + 1: )
Else
current = ''
End If
Else
! No separator found, so the remainder of the string is a token
new_token%token = current
current = ''
End If
! Add the token to the list
tokens = [ tokens, new_token ]
End Do
End Subroutine split_string
End Module split_string_module
Module read_csv_module
Public :: read_csv_line
Private
Contains
Subroutine read_csv_line( unit, tokens, error )
! Read a line and split it into an array of comma separated tokens
Use split_string_module, Only : split_string_token, split_string
Implicit None
Integer , Intent( In ) :: unit
Type( split_string_token ), Dimension( : ), Allocatable, Intent( Out ) :: tokens
Integer , Intent( Out ) :: error
Integer, Parameter :: max_line_length = 4096
Character( Len = max_line_length ) :: line
Read( unit, '( a )', iostat = error ) line
If( error == 0 ) Then
Call split_string( ',', Trim( line ), tokens )
End If
End Subroutine read_csv_line
End Module read_csv_module
Program testit
Use read_csv_module , Only : read_csv_line
Use split_string_module, Only : split_string_token
Type( split_string_token ), Dimension( : ), Allocatable :: tokens
Integer :: unit
Integer :: error
Integer :: i
Open( newunit = unit, file = 'input.dat' )
error = 0
Do While( error == 0 )
Call read_csv_line( unit, tokens, error )
If( error == 0 ) Then
Do i = 1, Size( tokens )
Write( *, '( a, 3x )', Advance = 'No' ) Trim( tokens( i )%token )
End Do
Write( *, * )
End If
End Do
Close( unit )
End Program testit
ijb#LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 --version
GNU Fortran (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ijb#LAPTOP-GUG8KQ9I:~/work/stack$ gfortran-10 -Wall -Wextra -Wuse-without-only -Werror -fcheck=all -std=f2008 -g -O csv.f90
ijb#LAPTOP-GUG8KQ9I:~/work/stack$ cat input.dat
"pdes","name","epoch","a","e","i","om","w","ma","q","ad"
1580,Betulia,2459600.5,2.197288160959855,.4871550690589618,52.07925829047207,62.2921305585828,159.5134530240992,16.62891169416756,1.126868095165017,3.267708226754692
1620,Geographos,2459600.5,1.245689288381319,.3353623816094239,13.33753650294321,337.1849253204765,276.9463790166408,300.4925456829043,.8279319618844114,1.663446614878227
1627,Ivar,2459600.5,1.86327342970777,.3967369932313492,8.451956512766827,133.120308337423,167.8035837640704,129.0289785125129,1.124043931637646,2.602502927777894
1685,Toro,2459600.5,1.367465568905196,.435966790549019,9.382739662870495,274.2362441040706,127.2114688956593,300.0617970060148,.7712959936433091,1.963635144167082
1862,Apollo,2459600.5,1.470502475713431,.5600430467767759,6.353083928279622,35.56898244993719,286.0386669340027,60.20237527657879,.6469577889220891,2.294047162504772
1863,Antinous,2459600.5,2.25922922966352,.6059920366929147,18.39886422664638,346.4237098245764,268.0896471241496,244.0101430178307,.8901543074235589,3.628304151903481
1864,Daedalus,2459600.5,1.460979692497998,.6144866009907846,22.21536437289675,6.613194571694206,325.6563726287792,196.1166696228387,.5632272471383416,2.358732137857654
1865,Cerberus,2459600.5,1.079986459127503,.4669721847798676,16.09858904525619,212.8963846822369,325.2653260753237,170.2073771841984,.57566282277606,1.584310095478947
1866,Sisyphus,2459600.5,1.893353802479725,.5383695942642949,41.20637430558688,63.47259682927852,293.0824330786623,331.1476239661798,.8740296840399557,2.912677920919495
1915,Quetzalcoatl,2459600.5,2.543790754476287,.5706410666538692,20.40472660837776,162.9348721741076,347.8091351438147,41.39145147165023,1.092199284997688,3.995382223954886
1916,Boreas,2459600.5,2.272324177667199,.4498393843780145,12.88297395642586,340.5981620510102,335.9167764123868,352.2401366045371,1.250143268478108,3.294505086856289
1917,Cuyo,2459600.5,2.14981121226236,.5054666607865446,23.95922692157032,188.2869783127825,194.5115030151171,82.2843922810623,1.063153317478631,3.236469107046088
1943,Anteros,2459600.5,1.430366783173011,.2560374828122278,8.706034969532251,246.3110706020363,338.3801329232052,173.8814283992249,1.064139272511169,1.796594293834852
1980,Tezcatlipoca,2459600.5,1.709370985747121,.3648359123967504,26.8689695764886,246.560199388918,115.4661353995156,314.1597421163634,1.085731062537538,2.333010908956705
1981,Midas,2459600.5,1.776435963774881,.6501354173857774,39.82986428861084,356.8569898560586,267.8286153975083,202.5329806814936,.621512027006993,2.931359900542769
2059,Baboquivari,2459600.5,2.64324121274608,.531432311471031,11.02055447003622,200.6851159860844,192.4190577597405,181.8930083473287,1.23853742528094,4.04794500021122
2061,Anza,2459600.5,2.264279343476608,.5360981217114927,3.800349706160866,207.3741353983842,157.0286649770264,354.1526556258232,1.050403440408666,3.478155246544549
2062,,2459600.5,.9669087478156669,.1827720931291991,18.9345273941421,108.5428491298942,148.0586126391113,21.46549438015371,.7901848121124645,1.143632683518869
"1979 XB",,2444221.5,2.228085656329666,.7084495059291489,24.73412122397795,86.0555030947377,75.57989828051527,346.3183743701075,.6495994739350907,3.806571838724241
594913,'Aylo'chaxnim,2459600.5,.5554326489245599,.1770230892406738,15.86839958719851,6.704982245275168,187.3289626591178,211.0111749229703,.4571082455468037,.6537570523023162
ijb#LAPTOP-GUG8KQ9I:~/work/stack$ ./a.out
"pdes" "name" "epoch" "a" "e" "i" "om" "w" "ma" "q" "ad"
1580 Betulia 2459600.5 2.197288160959855 .4871550690589618 52.07925829047207 62.2921305585828 159.5134530240992 16.62891169416756 1.126868095165017 3.267708226754692
1620 Geographos 2459600.5 1.245689288381319 .3353623816094239 13.33753650294321 337.1849253204765 276.9463790166408 300.4925456829043 .8279319618844114 1.663446614878227
1627 Ivar 2459600.5 1.86327342970777 .3967369932313492 8.451956512766827 133.120308337423 167.8035837640704 129.0289785125129 1.124043931637646 2.602502927777894
1685 Toro 2459600.5 1.367465568905196 .435966790549019 9.382739662870495 274.2362441040706 127.2114688956593 300.0617970060148 .7712959936433091 1.963635144167082
1862 Apollo 2459600.5 1.470502475713431 .5600430467767759 6.353083928279622 35.56898244993719 286.0386669340027 60.20237527657879 .6469577889220891 2.294047162504772
1863 Antinous 2459600.5 2.25922922966352 .6059920366929147 18.39886422664638 346.4237098245764 268.0896471241496 244.0101430178307 .8901543074235589 3.628304151903481
1864 Daedalus 2459600.5 1.460979692497998 .6144866009907846 22.21536437289675 6.613194571694206 325.6563726287792 196.1166696228387 .5632272471383416 2.358732137857654
1865 Cerberus 2459600.5 1.079986459127503 .4669721847798676 16.09858904525619 212.8963846822369 325.2653260753237 170.2073771841984 .57566282277606 1.584310095478947
1866 Sisyphus 2459600.5 1.893353802479725 .5383695942642949 41.20637430558688 63.47259682927852 293.0824330786623 331.1476239661798 .8740296840399557 2.912677920919495
1915 Quetzalcoatl 2459600.5 2.543790754476287 .5706410666538692 20.40472660837776 162.9348721741076 347.8091351438147 41.39145147165023 1.092199284997688 3.995382223954886
1916 Boreas 2459600.5 2.272324177667199 .4498393843780145 12.88297395642586 340.5981620510102 335.9167764123868 352.2401366045371 1.250143268478108 3.294505086856289
1917 Cuyo 2459600.5 2.14981121226236 .5054666607865446 23.95922692157032 188.2869783127825 194.5115030151171 82.2843922810623 1.063153317478631 3.236469107046088
1943 Anteros 2459600.5 1.430366783173011 .2560374828122278 8.706034969532251 246.3110706020363 338.3801329232052 173.8814283992249 1.064139272511169 1.796594293834852
1980 Tezcatlipoca 2459600.5 1.709370985747121 .3648359123967504 26.8689695764886 246.560199388918 115.4661353995156 314.1597421163634 1.085731062537538 2.333010908956705
1981 Midas 2459600.5 1.776435963774881 .6501354173857774 39.82986428861084 356.8569898560586 267.8286153975083 202.5329806814936 .621512027006993 2.931359900542769
2059 Baboquivari 2459600.5 2.64324121274608 .531432311471031 11.02055447003622 200.6851159860844 192.4190577597405 181.8930083473287 1.23853742528094 4.04794500021122
2061 Anza 2459600.5 2.264279343476608 .5360981217114927 3.800349706160866 207.3741353983842 157.0286649770264 354.1526556258232 1.050403440408666 3.478155246544549
2062 2459600.5 .9669087478156669 .1827720931291991 18.9345273941421 108.5428491298942 148.0586126391113 21.46549438015371 .7901848121124645 1.143632683518869
"1979 XB" 2444221.5 2.228085656329666 .7084495059291489 24.73412122397795 86.0555030947377 75.57989828051527 346.3183743701075 .6495994739350907 3.806571838724241
594913 'Aylo'chaxnim 2459600.5 .5554326489245599 .1770230892406738 15.86839958719851 6.704982245275168 187.3289626591178 211.0111749229703 .4571082455468037 .6537570523023162
ijb#LAPTOP-GUG8KQ9I:~/work/stack$
The list directed format is quite convenient, but at the same time quite complicated.
In this case you are reading something that starts with an apostrophe, contains another apostrophe and hence looks like an apostrophe-delimited sequence. In apostrophe-delimited character sequences the apostrophes are delimiters and are not considered to be a part of the string. However, this 'Aylo'chaxnim is then invalid because it has another stray characters after the delimiting apostrophe. If you need to parse this, you will need some custom parser and not the generic list-directed format.
Another option is consider this 'Aylo'chaxnim to be invalid (probably entered by the data provider by mistake) and remove it before giving it to your program. either manually, if it happens only as an exception, or by some pre-processing script.
Note that if there are additional characters before the starting apostrophe, it is fine. In that case the internal apostrophes are not interpreted as delimiters, but as normal characters in the character string.
As Ian Bush shown, the name is a legitimate asteroid name. So if you need to read the correct name 'Aylo'chaxnim you will need to parse the line yourself. You can tokenize it by localizing the commas and then parse the individual tokens.
There are also CSV reader libraries available but you have to check that they are actually able to cope with this.

List of valid operations in Tensorflow

I am using (learning) Tensorflow through the eager C API, or to be even more precise through a FreePascal wrapper around it.
When I want to do e.g. a matrix multiplication, I call
TFE_Execute(Op, #OutTensH, #NumOutVals, Status);
where Op.Op_Name is 'MatMul'. I have a couple of other instructions figured out, e.g. 'Transpose', 'Softmax', 'Inv', etc., but I do not have a complete list. In particular I want to get the determinant of a matrix, but cannot find it (assume it exists). I tried to find it on the web, as well as in the source on GitHub, but no success.
In Python there is tf.linalg.det, but already in C++ API I do not find it.
Could someone direct me to a place where I can find a complete list of supported operations?
Can someone tell me how to calculate the determinant with Tensorflow?
Edit: On Gaurav's request I attach a small program. As said above, it is in Pascal, and calls the C API through a wrapper. I therefore copied also the relevant part of the wrapper here (full version: https://macpgmr.github.io/). The set-up works, the "only" question is that I do not find a list of supported operations.
// A minimal program to transpose a matrix
program test;
uses
SysUtils,
TF;
var
Tensor:TTensor;
begin
Tensor:=TTensor.CreateSingle([2,1],[1.0,2.0]);
writeln('Before transpose ',Tensor.Dim[0],' x ',Tensor.Dim[1]); // 2 x 1
Tensor:=Tensor.Temp.ExecOp('Transpose',TTensor.CreateInt32([1,0]).Temp);
writeln('After transpose ',Tensor.Dim[0],' x ',Tensor.Dim[1]); // 1 x 2
FreeAndNil(Tensor);
end.
// extract from TF.pas ( (C) Phil Hess ). It basically re-packages the operation
// and calls the relevant C TFE_Execute, with the same operation name passed on:
// in our case 'Transpose'.
// I am looking for a complete list of supported operations.
function TTensor.ExecOp(const OpName : string;
Tensor2 : TTensor = nil;
Tensor3 : TTensor = nil;
Tensor4 : TTensor = nil) : TTensor;
var
Status : TF_StatusPtr;
Op : TFE_OpPtr;
NumOutVals : cint;
OutTensH : TFE_TensorHandlePtr;
begin
Result := nil;
Status := TF_NewStatus();
Op := TFE_NewOp(Context, PAnsiChar(OpName), Status);
try
if not CheckStatus(Status) then
Exit;
{Add operation input tensors}
TFE_OpAddInput(Op, TensorH, Status);
if not CheckStatus(Status) then
Exit;
if Assigned(Tensor2) then {Operation has 2nd tensor input?}
begin
TFE_OpAddInput(Op, Tensor2.TensorH, Status);
if not CheckStatus(Status) then
Exit;
end;
if Assigned(Tensor3) then {Operation has 3rd tensor input?}
begin
TFE_OpAddInput(Op, Tensor3.TensorH, Status);
if not CheckStatus(Status) then
Exit;
end;
if Assigned(Tensor4) then {Operation has 4th tensor input?}
begin
TFE_OpAddInput(Op, Tensor4.TensorH, Status);
if not CheckStatus(Status) then
Exit;
end;
{Set operation attributes}
TFE_OpSetAttrType(Op, 'T', DataType); //typically result type same as input's
if OpName = 'MatMul' then
begin
TFE_OpSetAttrBool(Op, 'transpose_a', #0); //default (False)
TFE_OpSetAttrBool(Op, 'transpose_b', #0); //default (False)
end
else if OpName = 'Transpose' then
TFE_OpSetAttrType(Op, 'Tperm', Tensor2.DataType) //permutations type
else if OpName = 'Sum' then
begin
TFE_OpSetAttrType(Op, 'Tidx', Tensor2.DataType); //reduction_indices type
TFE_OpSetAttrBool(Op, 'keep_dims', #0); //default (False)
end
else if (OpName = 'RandomUniform') or (OpName = 'RandomStandardNormal') then
begin
TFE_OpSetAttrInt(Op, 'seed', 0); //default
TFE_OpSetAttrInt(Op, 'seed2', 0); //default
TFE_OpSetAttrType(Op, 'dtype', TF_FLOAT); //for now, use this as result type
end
else if OpName = 'OneHot' then
begin
TFE_OpSetAttrType(Op, 'T', Tensor3.DataType); //result type must be same as on/off
TFE_OpSetAttrInt(Op, 'axis', -1); //default
TFE_OpSetAttrType(Op, 'TI', DataType); //indices type
end;
NumOutVals := 1;
try
// **** THIS IS THE ACTUAL CALL TO THE C API, WHERE Op HAS THE OPNAME
TFE_Execute(Op, #OutTensH, #NumOutVals, Status);
// ***********************************************************************
except on e:Exception do
raise Exception.Create('TensorFlow unable to execute ' + OpName +
' operation: ' + e.Message);
end;
if not CheckStatus(Status) then
Exit;
Result := TTensor.CreateWithHandle(OutTensH);
finally
if Assigned(Op) then
TFE_DeleteOp(Op);
TF_DeleteStatus(Status);
{Even if exception occurred, don't want to leave any temps dangling}
if Assigned(Tensor2) and Tensor2.IsTemp then
Tensor2.Free;
if Assigned(Tensor3) and Tensor3.IsTemp then
Tensor3.Free;
if Assigned(Tensor4) and Tensor4.IsTemp then
Tensor4.Free;
if IsTemp then
Free;
end;
end;
In the meantime, I found the description file of TensorFlow at: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/ops/ops.pbtxt. This includes all the operations and their detailed specification.
If someone is interested in a pascal interface to TF, I created one at https://github.com/zsoltszakaly/tensorflowforpascal.
Here is how you can obtain the list of valid operation names from Python:
from tensorflow.python.framework.ops import op_def_registry
registered_ops = op_def_registry.get_registered_ops()
valid_op_names = sorted(registered_ops.keys())
print(len(valid_op_names)) # Number of operation names in TensorFlow 2.0
1223
print(*valid_op_names, sep='\n')
# Abort
# Abs
# AccumulateNV2
# AccumulatorApplyGradient
# AccumulatorNumAccumulated
# AccumulatorSetGlobalStep
# AccumulatorTakeGradient
# Acos
# Acosh
# Add
# ...

Scala: Parsing Array of String to a case class

I have created a case class like this:
def case_class(): Unit = {
case class StockPrice(quarter : Byte,
stock : String,
date : String,
open : Double,
high : Double,
low : Double,
close : Double,
volume : Double,
percent_change_price : Double,
percent_change_volume_over_last_wk : Double,
previous_weeks_volume : Double,
next_weeks_open : Double,
next_weeks_close : Double,
percent_change_next_weeks_price : Double,
days_to_next_dividend : Double,
percent_return_next_dividend : Double
)
And I have thousands of line as Array of String like this:
1,AA,1/7/2011,$15.82,$16.72,$15.78,$16.42,239655616,3.79267,,,$16.71,$15.97,-4.42849,26,0.182704
1,AA,1/14/2011,$16.71,$16.71,$15.64,$15.97,242963398,-4.42849,1.380223028,239655616,$16.19,$15.79,-2.47066,19,0.187852
1,AA,1/21/2011,$16.19,$16.38,$15.60,$15.79,138428495,-2.47066,-43.02495926,242963398,$15.87,$16.13,1.63831,12,0.189994
1,AA,1/28/2011,$15.87,$16.63,$15.82,$16.13,151379173,1.63831,9.355500109,138428495,$16.18,$17.14,5.93325,5,0.185989
How Can I parse data from Array into that case class?
Thank you for your help!
You can proceed as below (I've taken simplified example)
Given your case class and data (lines)
// Your case-class
case class MyCaseClass(
fieldByte: Byte,
fieldString: String,
fieldDouble: Double
)
// input data
val lines: List[String] = List(
"1,AA,$1.1",
"2,BB,$2.2",
"3,CC,$3.3"
)
Note: you can read lines from a text file as
val lines = Source.fromFile("my_file.txt").getLines.toList
You can have some utility methods for mapping (cleaning & parsing)
// remove '$' symbols from string
def removeDollars(line: String): String = line.replaceAll("\\$", "")
// split string into tokens and
// convert into MyCaseClass object
def parseLine(line: String): MyCaseClass = {
val tokens: Seq[String] = line.split(",")
MyCaseClass(
fieldByte = tokens(0).toByte,
fieldString = tokens(1),
fieldDouble = tokens(2).toDouble
)
}
And then use them to convert strings into case-class objects
// conversion
val myCaseClassObjects: Seq[MyCaseClass] = lines.map(removeDollars).map(parseLine)
As a more advanced (and generalized) approach, you can generate the mapping (parsing) function for converting tokens into fields of your case-class using something like reflection, as told here
Here's one way of doing it. I'd recommend splitting everything you do up into lots of small, easy-to-manage functions, otherwise you will get lost trying to figure out where something is going wrong if it all starts throwing exceptions. Data setup:
val array = Array("1,AA,1/7/2011,$15.82,$16.72,$15.78,$16.42,239655616,3.79267,,,$16.71,$15.97,-4.42849,26,0.182704",
"1,AA,1/14/2011,$16.71,$16.71,$15.64,$15.97,242963398,-4.42849,1.380223028,239655616,$16.19,$15.79,-2.47066,19,0.187852",
"1,AA,1/21/2011,$16.19,$16.38,$15.60,$15.79,138428495,-2.47066,-43.02495926,242963398,$15.87,$16.13,1.63831,12,0.189994",
"1,AA,1/28/2011,$15.87,$16.63,$15.82,$16.13,151379173,1.63831,9.355500109,138428495,$16.18,$17.14,5.93325,5,0.185989")
case class StockPrice(quarter: Byte, stock: String, date: String, open: Double,
high: Double, low: Double, close: Double, volume: Double, percent_change_price: Double,
percent_change_volume_over_last_wk: Double, previous_weeks_volume: Double,
next_weeks_open: Double, next_weeks_close: Double, percent_change_next_weeks_price: Double,
days_to_next_dividend: Double, percent_return_next_dividend: Double
)
Function to turn Array[String] into Array[List[String]] and handle any empty fields (I've made an assumption here that you want empty fields to be 0. Change this as necessary):
def splitArray(arr: Array[String]): Array[List[String]] = {
arr.map(
_.replaceAll("\\$", "") // Remove $
.split(",") // Split by ,
.map {
case x if x.isEmpty => "0" // If empty
case y => y // If not empty
}
.toList
)
}
Function to turn a List[String] into a StockPrice. Note that this will fall over if the List isn't exactly 16 items long. I'll leave you to handle any of that. Also, the names are pretty non-descriptive so you can change that too. It will also fall over if your data doesn't map to the relevant .toDouble or toByte or whatever - you can handle this yourself too:
def toStockPrice: List[String] => StockPrice = {
case a :: b :: c :: d :: e :: f :: g :: h :: i :: j :: k :: l :: m :: n :: o :: p :: Nil =>
StockPrice(a.toByte, b, c, d.toDouble, e.toDouble, f.toDouble, g.toDouble, h.toDouble, i.toDouble, j.toDouble,
k.toDouble, l.toDouble, m.toDouble, n.toDouble, o.toDouble, p.toDouble)
}
A nice function to bring this all together:
def makeCaseClass(arr: Array[String]): Seq[StockPrice] = {
val splitArr: Array[List[String]] = splitArray(arr)
splitArr.map(toStockPrice)
}
Output:
println(makeCaseClass(array))
//ArraySeq(
// StockPrice(1,AA,1/7/2011,15.82,16.72,15.78,16.42,2.39655616E8,3.79267,0.0,0.0,16.71,15.97,-4.42849,26.0,0.182704),
// StockPrice(1,AA,1/14/2011,16.71,16.71,15.64,15.97,2.42963398E8,-4.42849,1.380223028,2.39655616E8,16.19,15.79,-2.47066,19.0,0.187852),
// StockPrice(1,AA,1/21/2011,16.19,16.38,15.6,15.79,1.38428495E8,-2.47066,-43.02495926,2.42963398E8,15.87,16.13,1.63831,12.0,0.189994),
// StockPrice(1,AA,1/28/2011,15.87,16.63,15.82,16.13,1.51379173E8,1.63831,9.355500109,1.38428495E8,16.18,17.14,5.93325,5.0,0.185989)
//)
Edit:
To explain the a :: b :: c ..... bit - this is a way of assigning names to items in a List or Seq, given you know the List's size.
val ls = List(1, 2, 3)
val a :: b :: c :: Nil = List(1, 2, 3)
println(a == ls.head) // true
println(b == ls(1)) // true
println(c == ls(2)) // true
Note that the Nil is important because it signifies the last element of the List being Nil. Without it, c would be equal to List(3) as the rest of any List is assigned to the last value in your definition.
You can use this in pattern matching as I have in order to do something with the results:
val ls = List(1, "b", true)
ls match {
case a :: b :: c if c == true => println("this will not be printed")
case a :: b :: c :: Nil if c == true => println(s"this will get printed because c == $c")
} // not exhaustive but you get the point
You can also use it if you know what you want each element in the List to be, like this:
val personCharacteristics = List("James", 26, "blue", 6, 85.4, "brown")
val name :: age :: eyeColour :: otherCharacteristics = personCharacteristics
println(s"Name: $name; Age: $age; Eye colour: $eyeColour")
// Name: James; Age: 26; Eye colour: blue
Obviously these examples are pretty trivial and not exactly what you'd see as a professional Scala developer (at least I don't), but it's a handy thing to be aware of as I do still use this :: syntax at work sometimes.

Abaqus 6.14-2 vumat vexternaldb error code 1073741819 with allocatable arrays

as stated above i am trying to get a vumat running, using allocatable arrays. I need to store and reuse the history of some values, therefore I tried allocatable arrays:
C
subroutine vumat(
C Read only -
1 nblock, ndir, nshr, nstatev, nfieldv, nprops, lanneal,
2 stepTime, totalTime, dt, cmname, coordMp, charLength,
3 props, density, strainInc, relSpinInc,
4 tempOld, stretchOld, defgradOld, fieldOld,
5 stressOld, stateOld, enerInternOld, enerInelasOld,
6 tempNew, stretchNew, defgradNew, fieldNew,
C Write only -
7 stressNew, stateNew, enerInternNew, enerInelasNew )
C
include 'vaba_param.inc'
#include <SMAAspUserSubroutines.hdr>
dimension props(nprops), density(nblock), coordMp(nblock,*),
1 charLength(nblock), strainInc(nblock,ndir+nshr),
2 relSpinInc(nblock,nshr), tempOld(nblock),
3 stretchOld(nblock,ndir+nshr),
4 defgradOld(nblock,ndir+nshr+nshr),
5 fieldOld(nblock,nfieldv), stressOld(nblock,ndir+nshr),
6 stateOld(nblock,nstatev), enerInternOld(nblock),
7 enerInelasOld(nblock), tempNew(nblock),
8 stretchNew(nblock,ndir+nshr),
8 defgradNew(nblock,ndir+nshr+nshr),
9 fieldNew(nblock,nfieldv),
1 stressNew(nblock,ndir+nshr), stateNew(nblock,nstatev),
2 enerInternNew(nblock), enerInelasNew(nblock)
c ID & Contents of lStatusArray
parameter ( j_iID_lStatusArray = 1)
parameter ( i_lStatusArray_Status = 1)
parameter ( n_lStatusArray_size = 1)
integer lStatusArray(n_lStatusArray_size)
pointer(ptrlStatusArray,lStatusArray)
print *,"huhu"
c************* this line causes the only error! *****************
ptrlStatusArray = SMALocalIntArrayAccess(j_iID_lStatusArray)
return
end
C
C
C ************************************************
C user routine to dynamically exchange data
Subroutine vexternaldb(lOp, i_Array, niArray, r_Array, nrArray)
*
include 'vaba_param.inc'
#include <SMAAspUserSubroutines.hdr>
dimension i_Array(niArray),
* r_Array(nrArray)
C possible values for argument lOp
parameter (j_int_startAnalysis = 0,
* j_int_startStep = 1,
* j_int_setupIncrement = 2,
* j_int_startIncrement = 3,
* j_int_endIncrement = 4,
* j_int_endStep = 5,
* j_int_endAnalysis = 6)
C contents of i_Array
parameter (
* i_int_nTotalNodes = 1,
* i_int_nTotalElements = 2,
* i_int_kStep = 3,
* i_int_kInc = 4,
* i_int_iStatus = 5,
* i_int_lWriteRestart = 6)
C possible values for i_Array(i_int_iStatus)
parameter (j_int_continue = 0,
* j_int_terminateStep = 1,
* j_int_terminateAnalysis = 2)
C contents of r_Array
parameter (
* i_flt_totalTime = 1,
* i_flt_stepTime = 2,
* i_flt_dTime = 3 )
c ID & Contents of lStatusArray
parameter ( j_iID_lStatusArray = 1)
parameter ( i_lStatusArray_Status = 1)
parameter ( n_lStatusArray_size = 1)
integer lStatusArray(n_lStatusArray_size)
pointer(ptrlStatusArray,lStatusArray)
*
if( lOp .eq. j_int_StartAnalysis) then
ptrlStatusArray = SMALocalIntArrayCreate(
* j_iID_lStatusArray, n_lStatusArray_size)
lStatusArray(i_lStatusArray_Status) = j_int_continue
end if
if( i_Array(i_int_iStatus) .eq. j_int_TerminateAnalysis .or.
* lOp .eq. j_int_endAnalysis) then
call SMALocalIntArrayDelete(j_iID_lStatusArray)
end if
*
* Skip writing restart frames to save on disk!
i_Array(i_int_lWriteRestart) = 0
*
return
end
C ************************************************
C
When I want to run the code, it works well without the marked line. Otherwise, if I want to get access to the array utilizing SMALocalIntArrayAccess, Abaqus crashes:
Abaqus JOB test
Abaqus 6.14-2
Begin Compiling Single Precision Abaqus/Explicit User Subroutines
12/8/2016 4:29:41 PM
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0 Build 20160721
Copyright (C) 1985-2016 Intel Corporation. All rights reserved.
End Compiling Single Precision Abaqus/Explicit User Subroutines
Begin Linking Single Precision Abaqus/Explicit User Subroutines
Bibliothek "explicitU.lib" und Objekt "explicitU.exp" werden erstellt.
End Linking Single Precision Abaqus/Explicit User Subroutines
12/8/2016 4:29:41 PM
Begin Analysis Input File Processor
12/8/2016 4:29:41 PM
Run pre.exe
12/8/2016 4:29:42 PM
End Analysis Input File Processor
Begin Abaqus/Explicit Packager
12/8/2016 4:29:42 PM
Run package.exe
huhu
12/8/2016 4:29:42 PM
Abaqus Error: The executable package.exe
aborted with system error code 1073741819.
Please check the .dat, .msg, and .sta files for error messages if the files
exist. If there are no error messages and you cannot resolve the problem,
please run the command "abaqus job=support information=support" to report and
save your system information. Use the same command to run Abaqus that you
used when the problem occurred. Please contact your local Abaqus support
office and send them the input file, the file support.log which you just
created, the executable name, and the error code.
Abaqus/Analysis exited with errors
I have totally no idea what I can do now. I tried several machines aswell.

Convert.ChangeType() Returns incorrect value

I've got a class that parses a CNC file, but I'm having difficulties with trailing "words" on each line of the file.
My code parses all leading "words" until it reaches the final word. It's most noticeable when parsing "Z" values or other Double type values. I've debugged it enough to notice that it successfully parses the numerical value just as it does with "X" and "Y" values, but it doesn't seem to successfully convert it to double. Is there an issue with a character I'm missing or something?
Here's my code:
If IO.File.Exists("Some GCode File.eia") Then
Dim sr As New IO.StreamReader("Some GCode File.eia")
Dim i As Integer = 0
'Read text file
Do While Not sr.EndOfStream
'Get the words in the line
Dim words() As String = sr.ReadLine.Split(" ")
'iterate through each word
For i = 0 To words.Length - 1 Step 1
'iterate through each "registered" keyword. Handled earlier in program
For Each cmd As String In _registeredCmds.Keys
'if current word resembles keyword then process
If words(i) Like cmd & "*" Then
_commands.Add(i, _registeredCmds(cmd))
'Double check availability of a Type to convert to
If Not IsNothing(_commands(i).DataType) Then
'Verify enum ScopeType exists
If Not IsNothing(_commands(i).Scope) Then
'If ScopeType is modal then just set it to True. I'll fix later
If _commands(i).Scope = ScopeType.Modal Then
_commands(i).DataValue = True
Else
'Catch errors in conversion
Try
'Get the value of the gcode command by removing the "registered" keyword from the string
Dim strTemp As String = words(i).Remove(0, words(i).IndexOf(_commands(i).Key) + _commands(i).Key.Length)
'Save the parsed value into an Object type in another class
_commands(i).DataValue = Convert.ChangeType(strTemp, _commands(i).DataType)
Catch ex As Exception
'Log(vbTab & "Error:" & ex.Message)
End Try
End If
Else
'Log(vbTab & "Command scope is null")
End If
Else
'Log(vbTab & "Command datatype is null")
End If
Continue For
End If
Next
Next
i += 1
Loop
Else
Throw New ApplicationException("FilePath provided does not exist! FilePath Provided:'Some GCode File.eia'")
End If
Here's an example of the GCode:
N2930 X-.2187 Y-1.2378 Z-.0135
N2940 X-.2195 Y-1.2434 Z-.0121
N2950 X-.2187 Y-1.249 Z-.0108
N2960 X-.2164 Y-1.2542 Z-.0096
N2970 X-.2125 Y-1.2585 Z-.0086
N2980 X-.207 Y-1.2613 Z-.0079
N2990 X-.2 Y-1.2624 Z-.0076
N3000 X0.
N3010 X12.
N3020 X24.
N3030 X24.2
N3040 X24.2072 Y-1.2635 Z-.0075
N3050 X24.2127 Y-1.2665 Z-.0071
N3060 X24.2167 Y-1.2709 Z-.0064
N3070 X24.2191 Y-1.2763 Z-.0057
N3080 X24.2199 Y-1.2821 Z-.0048
N3090 X24.2191 Y-1.2879 Z-.004
N3100 X24.2167 Y-1.2933 Z-.0032
N3110 X24.2127 Y-1.2977 Z-.0026
N3120 X24.2072 Y-1.3007 Z-.0021
N3130 X24.2 Y-1.3018 Z-.002
N3140 X24.
N3150 X12.
N3160 X0.
N3170 X-.2
N3180 X-.2074 Y-1.3029 Z-.0019
N3190 X-.2131 Y-1.306 Z-.0018
N3200 X-.2172 Y-1.3106 Z-.0016
N3210 X-.2196 Y-1.3161 Z-.0013
N3220 X-.2204 Y-1.3222 Z-.001
N3230 X-.2196 Y-1.3282 Z-.0007
N3240 X-.2172 Y-1.3338 Z-.0004
N3250 X-.2131 Y-1.3384 Z-.0002
N3260 X-.2074 Y-1.3415 Z-.0001
N3270 X-.2 Y-1.3426 Z0.
N3280 X0.
N3290 X12.
N3300 X24.
N3310 X24.2
N3320 G0 Z.1
N3330 Z1.0
N3340 G91 G28 Z0.0
N3350 G90
With regard to the sample CNC code above, you'll notice that X and Y commands with a trailing Z command parse correctly.
EDIT
Per comment, here is a breakdown of _commands()
_commands = SortedList(Of Integer, Command)
Command is a class with the following properties:
Scope as Enum ScopeType
Name as String
Key as String
DataType as Type
DataValue as Object
EDIT: Solution!
Figured out what was wrong. The arrays that make up the construction of the classes were essentially being passed a reference to the "registered" array of objects from the Command class. Therefore every time I parsed the value out of the "word" each line, I was overwriting the DataValue in the Command object.
The solution was to declare a new 'Command' object with every parse and append it to the proper array.
Here's my short hand:
...
For I = 0 To words.Length - 1 Step 1
'iterate through each "registered" keyword. Handled earlier in program
For Each cmd as String in _registeredCmds.Keys
'if current word resembles keyword then process
If words(I) Like cmd & "*" Then
'NEW!!! Declare unassigned Command object
Dim com As Command
' ****** New elongated logic double checking existence of values.....
If _registeredCmds.Keys.Scope = ScopeType.Modal Then
'assign Command object to previously declared variable com
com = New Command()'There's technically passing arguments now to ensure items are transferred
Else
'Parse and pass DataValue from this word
com = New Command()'There's technically passing arguments now to ensure items are transferred
End If
'New sub to add Command object to local array
Add(com)
Continue For
End If
Next
Next
...

Resources