From f6e7af2be0fd791b9f7b29d7fca19cb02033583b Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Wed, 5 Oct 2022 17:35:24 -0600 Subject: [PATCH 1/4] add in support for 2GB+ archive files --- ansys/mapdl/reader/archive.py | 6 +- ansys/mapdl/reader/cython/_reader.pyx | 85 ++++++++++++--------------- ansys/mapdl/reader/cython/archive.c | 26 ++++---- ansys/mapdl/reader/cython/reader.c | 15 ++--- ansys/mapdl/reader/cython/reader.h | 9 ++- 5 files changed, 72 insertions(+), 69 deletions(-) diff --git a/ansys/mapdl/reader/archive.py b/ansys/mapdl/reader/archive.py index 921abcb1..6b95f618 100644 --- a/ansys/mapdl/reader/archive.py +++ b/ansys/mapdl/reader/archive.py @@ -123,13 +123,17 @@ def __init__( null_unallowed=False, verbose=False, name="", + read_eblock=False, ): """Initializes an instance of the archive class.""" self._read_parameters = read_parameters self._filename = pathlib.Path(filename) self._name = name self._raw = _reader.read( - self.filename, read_parameters=read_parameters, debug=verbose + self.filename, + read_parameters=read_parameters, + debug=verbose, + read_eblock=read_eblock, ) super().__init__( self._raw["nnum"], diff --git a/ansys/mapdl/reader/cython/_reader.pyx b/ansys/mapdl/reader/cython/_reader.pyx index 0a9fc242..4c7f3cb3 100644 --- a/ansys/mapdl/reader/cython/_reader.pyx +++ b/ansys/mapdl/reader/cython/_reader.pyx @@ -48,8 +48,8 @@ def safe_int(value): cdef extern from "reader.h": int read_nblock_from_nwrite(char*, int*, double*, int) - int read_nblock(char*, int*, double*, int, int*, int, int*) - int read_eblock(char*, int*, int*, int, int, int*) + int read_nblock(char*, int*, double*, int, int*, int, int64_t*) + int read_eblock(char*, int*, int*, int, int, int64_t*) int write_array_ascii(const char*, const double*, int); @@ -58,13 +58,13 @@ cdef extern from 'vtk_support.h': const int*, int64_t*, int64_t*, uint8_t*, const int) -cdef int myfgets(char *outstr, char *instr, int *n, int fsize): +cdef int myfgets(char *outstr, char *instr, int64_t *n, int64_t fsize): """Copies a single line from instr to outstr starting from position n """ cdef int k = n[0] # Search line at a maximum of 10000 characters - cdef int i, c + cdef int64_t i, c c = n[0] for i in range(1000): # check if end of file @@ -89,7 +89,7 @@ cdef int myfgets(char *outstr, char *instr, int *n, int fsize): return 1 -def py_read_eblock(char *raw, int n, char *line, int fsize): +def py_read_eblock(char *raw, int64_t n, char *line, int64_t fsize): """Read the eblock The format of the element "block" is as follows for the SOLID format: @@ -144,7 +144,7 @@ additional node numbers if there are more than eight. return elem_sz, elem, elem_off -def read(filename, read_parameters=False, debug=False): +def read(filename, read_parameters=False, debug=False, read_eblock=True): """Read blocked ansys archive file.""" badstr = 'Badly formatted cdb file' filename_byte_string = filename.encode("UTF-8") @@ -159,15 +159,15 @@ def read(filename, read_parameters=False, debug=False): # Load entire file to memory fseek(cfile, 0, SEEK_END) - cdef int fsize = ftell(cfile) + cdef int64_t fsize = ftell(cfile) fseek(cfile, 0, SEEK_SET) cdef char *raw = < char * >malloc(fsize*sizeof(char)) fread(raw, 1, fsize, cfile) fclose(cfile) - + # File counter cdef int tmpval, start_pos - cdef int n = 0 + cdef int64_t n = 0 # Define variables cdef size_t l = 0 @@ -205,13 +205,15 @@ def read(filename, read_parameters=False, debug=False): # keyopt keyopt = {} - # Read data up to and including start of NBLOCK while 1: if myfgets(line, raw, &n, fsize): break # Record element types if 'E' == line[0] or 'e' == line[0]: + if debug: + print('Hit "E"') + if b'ET,' == line[:3] or b'et,' == line[:3]: if debug: print('reading ET') @@ -226,7 +228,7 @@ def read(filename, read_parameters=False, debug=False): print('Invalid "ET" command %s' % line.decode()) continue - elif b'EBLOCK,' == line[:7] or b'eblock,' == line[:7]: + elif b'EBLOCK,' == line[:7] or b'eblock,' == line[:7] and read_eblock: if eblock_read: # Sometimes, DAT files contain two EBLOCKs. Read # only the first block. @@ -244,6 +246,9 @@ def read(filename, read_parameters=False, debug=False): print('finished') elif b'K' == line[0] or b'k' == line[0]: + if debug: + print('Hit "K"') + if b'KEYOP' in line or b'keyop' in line: if debug: print('reading KEYOP') @@ -262,6 +267,9 @@ def read(filename, read_parameters=False, debug=False): keyopt[key_num] = [entry[1:]] elif 'R' == line[0] or 'r' == line[0]: + if debug: + print('Hit "R"') + if b'RLBLOCK' in line or b'rlblock' in line: if debug: print('reading RLBLOCK') @@ -349,6 +357,9 @@ def read(filename, read_parameters=False, debug=False): rdat.append(rcon) elif 'N' == line[0] or 'n' == line[0]: + if debug: + print('Hit "N"') + # if line contains the start of the node block if line[:6] == b'NBLOCK' or line[:6] == b'nblock': if nodes_read: @@ -380,43 +391,13 @@ def read(filename, read_parameters=False, debug=False): nodes = nodes[:nnodes] nnum = nnum[:nnodes] - # # verify at the end of the block - # if nnodes_read != nnodes: - # nnodes = nnodes_read - # nodes = nodes[:nnodes] - # nnum = nnum[:nnodes] - # else: - # if myfgets(line, raw, &n, fsize): - # raise RuntimeError('Unable to read nblock format line or ' - # 'at end of file.') - - # bl_end = line.decode().replace(' ', '') - # if 'LOC' not in bl_end or b'-1' == bl_end[:2]: - # if debug: - # print('Unable to find the end of the NBLOCK') - # # need to reread the number of nodes - # n = start_pos - # if myfgets(line, raw, &n, fsize): raise Exception(badstr) - # nnodes = 0 - # while True: - # if myfgets(line, raw, &n, fsize): raise Exception(badstr) - # bl_end = line.decode().replace(' ', '') - # if 'LOC' not in bl_end or b'-1' == bl_end[:2]: - # break - # nnodes += 1 - - # # reread nodes - # n = start_pos - # if myfgets(line, raw, &n, fsize): raise Exception(badstr) - # d_size, f_size, nfld, nexp = node_block_format(line) - # nnum = np.empty(nnodes, dtype=ctypes.c_int) - # nodes = np.zeros((nnodes, 6)) - - # n = read_nblock(raw, &nnum[0], &nodes[0, 0], nnodes, - # &d_size[0], f_size, &n) - + if debug: + print('Read', nnodes_read, 'nodes') elif 'C' == line[0] or 'c' == line[0]: + if debug: + print('Hit "C"') + if line[:8] == b'CMBLOCK,' or line[:8] == b'cmblock,': # component block if debug: print('reading CMBLOCK') @@ -463,6 +444,9 @@ def read(filename, read_parameters=False, debug=False): elem_comps[comname] = component_interperter(component) elif '*' == line[0] and read_parameters: # maybe *DIM + if debug: + print('Hit "*"') + if b'DIM' in line: items = line.decode().split(',') if len(items) < 3: @@ -495,6 +479,10 @@ def read(filename, read_parameters=False, debug=False): # if the node block was not read for some reason if not nodes_read: + # Free cached archive file + if debug: + print('Did not read nodes block. Rereading from start.') + n = 0 while 1: if myfgets(line, raw, &n, fsize): @@ -516,6 +504,8 @@ def read(filename, read_parameters=False, debug=False): &d_size[0], f_size, &n) # Free cached archive file + if debug: + print('Freeing memory') free(raw) # assemble global element block @@ -524,6 +514,9 @@ def read(filename, read_parameters=False, debug=False): elem_off = np.empty(0, dtype=ctypes.c_int) elem_sz = 0 + if debug: + print('Returning arrays') + return {'rnum': np.asarray(rnum), 'rdat': rdat, 'ekey': np.asarray(elem_type, ctypes.c_int), diff --git a/ansys/mapdl/reader/cython/archive.c b/ansys/mapdl/reader/cython/archive.c index 70d1e1d0..5d52c67e 100644 --- a/ansys/mapdl/reader/cython/archive.c +++ b/ansys/mapdl/reader/cython/archive.c @@ -103,7 +103,7 @@ int write_eblock(FILE *file, // Write header fprintf(file, "EBLOCK,19,SOLID,%10d,%10d\n", elem_id[n_elem - 1], n_elem); - fprintf(file, "(19i8)\n"); + fprintf(file, "(19i10)\n"); int c; // position within offset array for (int i=0; i #include +// necessary for ubuntu build on azure +#ifdef __linux__ + #include +#endif //============================================================================= // Fast string to integer convert to ANSYS formatted integers @@ -216,11 +220,11 @@ static inline double ans_strtod2(char *raw, int fltsz){ // Number of nodes read. //============================================================================= int read_nblock(char *raw, int *nnum, double *nodes, int nnodes, int* intsz, - int fltsz, int *n){ + int fltsz, int64_t *n){ // set to start of the NBLOCK raw += n[0]; - int len_orig = strlen(raw); + int64_t len_orig = strlen(raw); int i, j, i_val, eol; for (i=0; i -int read_nblock(char*, int*, double*, int, int*, int, int*); -int read_eblock(char*, int*, int*, int, int, int*); +#ifdef __linux__ + #include +#endif + + +int read_nblock(char*, int*, double*, int, int*, int, int64_t*); +int read_eblock(char*, int*, int*, int, int, int64_t*); int read_nblock_from_nwrite(char*, int*, double*, int); int write_array_ascii(const char*, const double*, int nvalues); From 0521329ed8824ad46da236ab55b4c158fb3076aa Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Wed, 5 Oct 2022 17:44:19 -0600 Subject: [PATCH 2/4] revert back to 8 char --- ansys/mapdl/reader/archive.py | 5 ++++- ansys/mapdl/reader/cython/archive.c | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ansys/mapdl/reader/archive.py b/ansys/mapdl/reader/archive.py index a6d7cc97..e437a87c 100644 --- a/ansys/mapdl/reader/archive.py +++ b/ansys/mapdl/reader/archive.py @@ -78,6 +78,9 @@ class Archive(Mesh): name : str, optional Internally used parameter used to have a custom ``__repr__``. + read_eblock : bool, default: True + Read the element block. + Examples -------- >>> from ansys.mapdl import reader as pymapdl_reader @@ -125,7 +128,7 @@ def __init__( null_unallowed=False, verbose=False, name="", - read_eblock=False, + read_eblock=True, ): """Initializes an instance of the archive class.""" self._read_parameters = read_parameters diff --git a/ansys/mapdl/reader/cython/archive.c b/ansys/mapdl/reader/cython/archive.c index 4bb9c30e..24fa17cc 100644 --- a/ansys/mapdl/reader/cython/archive.c +++ b/ansys/mapdl/reader/cython/archive.c @@ -104,7 +104,7 @@ int write_eblock(FILE *file, // Write header fprintf(file, "EBLOCK,19,SOLID,%10d,%10d\n", elem_id[n_elem - 1], n_elem); - fprintf(file, "(19i10)\n"); + fprintf(file, "(19i8)\n"); int c; // position within offset array for (int i=0; i Date: Wed, 5 Oct 2022 17:51:25 -0600 Subject: [PATCH 3/4] fix syntax error --- ansys/mapdl/reader/cython/reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ansys/mapdl/reader/cython/reader.c b/ansys/mapdl/reader/cython/reader.c index 3449e0cd..b7a7cce5 100644 --- a/ansys/mapdl/reader/cython/reader.c +++ b/ansys/mapdl/reader/cython/reader.c @@ -220,7 +220,7 @@ static inline double ans_strtod2(char *raw, int fltsz){ // Number of nodes read. //============================================================================= int read_nblock(char *raw, int *nnum, double *nodes, int nnodes, int* intsz, - int fltsz, int64_t *n){ + int fltsz, int64_t* n){ // set to start of the NBLOCK raw += n[0]; From caf5e4d93288d031b75ef256285ac8faff4e819e Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Wed, 5 Oct 2022 17:56:11 -0600 Subject: [PATCH 4/4] add in stdint --- ansys/mapdl/reader/cython/reader.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ansys/mapdl/reader/cython/reader.c b/ansys/mapdl/reader/cython/reader.c index b7a7cce5..5d226ba7 100644 --- a/ansys/mapdl/reader/cython/reader.c +++ b/ansys/mapdl/reader/cython/reader.c @@ -1,13 +1,9 @@ +#include +#include +#include #include #include #include -#include -#include - -// necessary for ubuntu build on azure -#ifdef __linux__ - #include -#endif //============================================================================= // Fast string to integer convert to ANSYS formatted integers