Skip to content
Snippets Groups Projects
grid_reader.c 15.53 KiB
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <ctype.h>
#include <math.h>
#include "grid_reader.h"
typedef struct
{
    size_t size;
    size_t nx, ny, nz;
    double* data;
    double*  origin;
    double** basis;
    
} grid;

void remove_new_line(char* str)
{
    while(*str != '\n')
        ++str;
    *str = '\0';
}

void remove_white_space(char* str)
{
    size_t len = strlen(str);
    char* ptr = str;
    //int count = 0;
    while(*ptr != '\0')
    {
        if(*ptr == ' ' || *ptr == '\t')
            ptr++;
        else
            break;
    }
    memmove(str, ptr, sizeof(char)*(len-(size_t)(ptr-str)+1));
    len = strlen(str); //new length
    ptr = str+len-1;
    while(*ptr == ' ')
        ptr--;
        //truncated the trailing white space
    *(ptr+1) = '\0';
}

void* gridformat_reader(const char* name)
{
    printf("Reading from file %s\n", name);
    char buffer[512];
    char delim[]=" \t";
    int set_count = 0;
    FILE* infile = fopen(name, "r");
    grid* grids = (grid*)malloc(sizeof(grid));

    grids->nx = 0;
    grids->ny = 0;
    grids->nz = 0;
    grids->size = 0;
    grids->origin = (double*)malloc(sizeof(double)*3);

    grids->basis  = (double**)malloc(sizeof(double*)*3);
    for(size_t i = 0; i < 3; ++i)
        grids->basis[i] = (double*)malloc(sizeof(double)*3);
    grids->data = NULL;

     
    if(infile == NULL)
    {
        perror("Error: ");
        printf("Failure opening file %s\n", name);
        return NULL;
    }
    size_t count = 0;
    size_t count_data = 0;

    while(fgets(buffer, 512, infile) != NULL)
    {
        char tmp[512];
        char str[512];
        strcpy(tmp, buffer);
        remove_new_line(tmp);
        remove_white_space(tmp); //strip the possible newline and puts '\0'
        //skip comment
        if(buffer[0] == '#')
            continue;
        strcpy(str, tmp);

        if(strlen(str) == 0)
            continue;
        char* rest = strtok(tmp, " ");

        if(rest == NULL)
            continue; 
        if(!strcmp(rest, "object") && set_count == 0)
        {
            strtok(str," ");
            strtok(NULL, " ");
            strtok(NULL, " ");
            strtok(NULL, " ");
            strtok(NULL, " ");

            rest = strtok(NULL, " ");
            grids->nx = (size_t)atoi(rest);

            rest = strtok(NULL, " ");
            grids->ny = (size_t)atoi(rest);

            rest = strtok(NULL, " ");
            grids->nz = (size_t)atoi(rest);

            grids->size = grids->nx*grids->ny*grids->nz;
            grids->data = (double*)malloc(sizeof(double)*(grids->size));
            //grids->data = (double***)malloc(sizeof(double**)*(grids->nx));
            if(grids->data == NULL)
            {
                perror("Error in malloc:");
                //printf("Error message %s\n", strerror(errno));
                return NULL;
            }
            /*
            for(size_t i = 0; i < grids->nx; ++i)
            {
                
                grids->data[i] = (double**)malloc(sizeof(double*)*(grids->ny));
                if(grids->data[i] == NULL)
                {
                    perror("Error in mallc:");

                    for(size_t j = 0; j < i; ++j)
                        free(grids->data[j]);

                    free(grids->data);
                    return NULL;
                }
            }
            for(size_t i = 0; i < grids->nx; ++i)
            {
                for(size_t j = 0; j < grids->ny; ++j)
                {
                    grids->data[i][j] = (double*)malloc(sizeof(double)*(grids->nz));

                    if(grids->data[i][j] == NULL)
                    {
                        perror("Error in malloc:");

                        for(size_t i1= 0; i1 < i; ++i1)
                            for(size_t j1 = 0; j1 < grids->ny; ++j1)
                                free(grids->data[i1][j1]);

                        for(size_t j1 = 0; j1 < j; ++j1)
                                free(grids->data[i][j1]);

                        for(size_t i1 = 0; i1 < grids->nx; ++i1)
                             free(grids->data[i1]);

                        free(grids->data);
                        return NULL;
                    }
                }
            }*/
            set_count = 1;
        }
        else if(!strcmp(rest, "origin"))
        {
            strtok(str," ");
            grids->origin[0] = (double)atof(strtok(NULL, " "));
            grids->origin[1] = (double)atof(strtok(NULL, " "));
            grids->origin[2] = (double)atof(strtok(NULL, " "));
        }
        else if(!strcmp(rest, "delta")) 
        {
            strtok(str," ");
            grids->basis[count][0] = (double)atof(strtok(NULL, " "));
            grids->basis[count][1] = (double)atof(strtok(NULL, " "));
            grids->basis[count][2] = (double)atof(strtok(NULL, " "));
            ++count;
        }
        else if(isdigit(str[0]) || isdigit(str[1]))
        {
            rest = strtok(str, delim);
            grids->data[count_data++] = (double)atof(rest);

            rest = strtok(NULL, delim);
            if(rest != NULL)
                grids->data[count_data++] = (double)atof(rest);
            else
                continue;

            rest = strtok(NULL, delim);
            if(rest != NULL)
                grids->data[count_data++] = (double)atof(rest);
            else
                continue;
        }
    }
    if(count_data != grids->size)
    {
        printf("Invalid file, data and count is not consistent.\n");
        grid_destroy(grids);
        //free(grids);
        return NULL;
    }
    printf("Sucessfully reading file %s\n", name);
    
    if(fclose(infile) != 0)
        perror("Error in closing file:");

    return grids;
}

void grid_destroy(void* src)
{
    free(((grid*)src)->data);
    for(size_t i = 0; i < 3; ++i)
        free(((grid*)src)->basis[i]);
    free(((grid*)src)->origin);
    free(((grid*)src)->basis);
    free(src);
}

int gridformat_writer(char* name, void* src)
{
    ssize_t bytes_write;
    printf("Starting writing files %s\n", name);
    assert(src);
    grid* g = (grid*)src;
    int fildes = open(name, O_RDWR | O_CREAT | O_TRUNC, 0664);
    if(fildes == -1)
    {
        perror("Error in opeing file for writing");
        //exit(errno);
        //return -1;
        return errno;
    }
    bytes_write = write(fildes, "#OpenDx file generated from grids reader/writer program\n",56);
    if(bytes_write < -1)
    {
        return errno;
    }
    else if(bytes_write < 56)
    {
        return 9999;
    }

    char buff[1024];
    ssize_t len;
    sprintf(buff, "object 1 class gridpositions counts %lu %lu %lu\n", g->nx, g->ny, g->nz);
    len = strlen(buff);
    bytes_write = write(fildes, buff, len);

    if(bytes_write < -1)
    {
        return errno;
    }
    else if(bytes_write < len)
    {
        return 9999;
    }

    sprintf(buff, "origin %lf %lf %lf\n", g->origin[0], g->origin[1], g->origin[2]);
    len = strlen(buff);
    bytes_write = write(fildes, buff, len);

    if(bytes_write < -1)
    {
        return errno;
    }
    else if(bytes_write < len)
    {
        return 9999;
    }
    for(size_t i = 0; i < 3; i++)
    {
        sprintf(buff, "delta %lf %lf %lf\n", g->basis[i][0], g->basis[i][1], g->basis[i][2]);
        len = strlen(buff);
        bytes_write = write(fildes, buff, len);
        if(bytes_write < -1)
        {
            return errno;
        }
        else if(bytes_write < len)
        {
            return 9999;
        }

    }

    sprintf(buff, "object 2 class gridconnections counts %lu %lu %lu\n", g->nx, g->ny, g->nz); 
    len = strlen(buff);
    bytes_write = write(fildes, buff, len);
    if(bytes_write < -1)
    {
        return errno;
    }
    else if(bytes_write < len)
    {
        return 9999;
    }

    sprintf(buff, "object 3 class array type float rank 0 items %lu data follows\n", g->size);
    len = strlen(buff);
    bytes_write = write(fildes, buff, len);
    if(bytes_write < -1)
    {
        return errno;
    }
    else if(bytes_write < len)
    {
        return 9999;
    }

    size_t lines = g->size/3;
    for(size_t l = 0; l < lines; ++l)
    {
        sprintf(buff, "%.15lf %.15lf %.15lf\n", g->data[3*l], g->data[3*l+1], g->data[3*l+2]);
        len = strlen(buff);
        bytes_write = write(fildes, buff, len);
        if(bytes_write < -1)
        {
            return errno;
        }
        else if(bytes_write < len)
        {
            return 9999;
        }
    }
    if(g->size%3 == 1)
    {
        sprintf(buff, "%.15lf\n", g->data[g->size-1]);
        len = strlen(buff);
        bytes_write = write(fildes, buff, len);
        if(bytes_write < -1)
        {
            return errno;
        }
        else if(bytes_write < len)
        {
            return 9999;
        }
    }
    else if(g->size%3 == 2)
    {
        sprintf(buff, "%.15lf %.15lf\n", g->data[g->size-2], g->data[g->size-1]);
        len = strlen(buff);
        bytes_write = write(fildes, buff, len);
        if(bytes_write < -1)
        {
            return errno;
        }
        else if(bytes_write < len)
        {
            return 9999;
        }
    }
    if(close(fildes) == -1)
    {
        int err = errno;
        perror("Error in closing files");
        //exit(errno);
        return err;
    }
    return 0;
}

void set_grid_data(void* src, compute_type compute, void* kernel)
{
    grid* g = (grid*)src; 
    for(size_t i = 0; i < g->nx; ++i)
    {
        for(size_t j = 0; j < g->ny; ++j)
        {
            for(size_t k = 0; k < g->nz; ++k)
            {
                size_t idx = k + g->nz * j + g->nz * g->ny * i;
                g->data[idx] = (*compute)(i, j, k, g->origin, g->basis, kernel);
            }
        }
    } 
}

static void* create_new_grid(size_t nx, size_t ny, size_t nz, double* origin, double** basis)
{
    void* g = malloc(sizeof(grid));
    ((grid*)g)->nx = nx;
    ((grid*)g)->ny = ny;
    ((grid*)g)->nz = nz;
    ((grid*)g)->size = nx*ny*nz;
    ((grid*)g)->data = (double*)malloc(sizeof(double)*(((grid*)g)->size)); 

    ((grid*)g)->origin = (double*)malloc(sizeof(double)*3);
    for(size_t i = 0; i < 3; ++i)
        ((grid*)g)->origin[i] = origin[i];

    ((grid*)g)->basis  = (double**)malloc(sizeof(double*)*3);
    for(size_t i = 0; i < 3; ++i)
        ((grid*)g)->basis[i] = (double*)malloc(sizeof(double)*3);

    for(size_t i = 0; i < 3; ++i)
        for(size_t j = 0; j < 3; ++j)
            ((grid*)g)->basis[i][j] = basis[i][j];
    return g;

}

static size_t Index(size_t nx, size_t ny, size_t nz, int x, int y, int z)
{
    x = (x < 0) ? 0 : x;
    y = (y < 0) ? 0 : y;
    z = (z < 0) ? 0 : z;
    x = ((size_t)x >= nx) ? (int)nx-1 : x;
    y = ((size_t)y >= ny) ? (int)ny-1 : y;
    z = ((size_t)z >= nz) ? (int)nz-1 : z;
    return z + nz * (y + ny * x);
}
/*
static void inverse_3by3(double** m, double inv[3][3])
{
    double det = m[0][0]*(m[1][1]*m[2][2]-m[1][2]*m[2][1])-
                 m[0][1]*(m[1][0]*m[2][2]-m[1][2]*m[2][0])+ 
                 m[0][2]*(m[1][0]*m[2][1]-m[1][1]*m[2][0]);

    inv[0][0] = (m[1][1]*m[2][2]-m[1][2]*m[2][1])/det;
    inv[0][1] =-(m[0][1]*m[2][2]-m[0][2]*m[2][1])/det;
    inv[0][2] = (m[0][1]*m[1][2]-m[0][2]*m[1][1])/det;

    inv[1][0] =-(m[1][0]*m[2][2]-m[1][2]*m[2][0])/det;
    inv[1][1] = (m[0][0]*m[2][2]-m[0][2]*m[2][0])/det;
    inv[1][2] =-(m[0][0]*m[1][2]-m[0][2]*m[1][0])/det;

    inv[2][0] = (m[1][0]*m[2][1]-m[1][1]*m[2][0])/det;
    inv[2][1] =-(m[0][0]*m[2][1]-m[0][1]*m[2][0])/det;
    inv[2][2] = (m[0][0]*m[1][1]-m[0][1]*m[1][0])/det;

}*/
//resample the grid data such that each dimensition is even number by using linear interpolation
//I currently implement for diagonal basis set
void* resample_grid_data(void* src)
{
    grid* old_g = (grid*)src;
    grid* new_g;
    size_t nx, ny, nz;
    double** b = (double**)malloc(sizeof(double*)*3);
    for(size_t i = 0; i < 3; ++i)
    {
        b[i] = (double*)malloc(sizeof(double)*3);
        memset(b[i],0,sizeof(double)*3);
    }

    nx = (old_g->nx/2)*2;
    ny = (old_g->ny/2)*2;
    nz = (old_g->nz/2)*2;
    
    b[0][0] = old_g->basis[0][0]*(old_g->nx/(double)nx);
    b[1][1] = old_g->basis[1][1]*(old_g->ny/(double)ny);
    b[2][2] = old_g->basis[2][2]*(old_g->nz/(double)nz);

    new_g = create_new_grid(nx,ny,nz,old_g->origin, b);

    for(size_t i = 0; i < 3; ++i)
        free(b[i]);
    free(b);

    for(size_t i = 0; i < new_g->size; ++i)
    {
        size_t ix = i / new_g->nz / new_g->ny;
        size_t iy = i / new_g->nz % new_g->ny;
        size_t iz = i % new_g->nz;

        double posx = new_g->basis[0][0]*ix;
        double posy = new_g->basis[1][1]*iy;
        double posz = new_g->basis[2][2]*iz;

        int x0 = floor(posx/old_g->basis[0][0]);
        int y0 = floor(posy/old_g->basis[1][1]);
        int z0 = floor(posz/old_g->basis[2][2]);
 
        double posx0 = old_g->basis[0][0] * x0;
        double posy0 = old_g->basis[1][1] * y0;
        double posz0 = old_g->basis[2][2] * z0;

        int x1 = x0 + 1;
        int y1 = y0 + 1;
        int z1 = z0 + 1;

        double posx1 = old_g->basis[0][0] * x1;
        double posy1 = old_g->basis[1][1] * y1;
        double posz1 = old_g->basis[2][2] * z1;

        double xd = (posx-posx0)/(posx1-posx0);
        double yd = (posy-posy0)/(posy1-posy0);
        double zd = (posz-posz0)/(posz1-posz0);
        double c0 = ((1.-xd)* old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x0, y0, z0)] + 
                         xd * old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x1, y0, z0)])*(1.-yd) +
                    ((1.-xd)* old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x0, y1, z0)] + 
                         xd * old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x1, y1, z0)])*yd;
 
       double c1 = ((1.-xd)* old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x0, y0, z1)] +
                        xd * old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x1, y0, z1)])*(1.-yd) +
                   ((1.-xd)* old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x0, y1, z1)] + 
                        xd * old_g->data[Index(old_g->nx, old_g->ny, old_g->nz, x1, y1, z1)])*yd;
       new_g->data[i] = c0*(1.-zd) + c1*zd;
    }
    return new_g; 
}
double* get_grid_origin(void* src)
{
    return ((grid*)src)->origin;
}

double** get_grid_basis(void* src)
{
    return ((grid*)src)->basis;
}

double* get_grid_data(void* src)
{
    return ((grid*)src)->data;
}

size_t get_nx(void* src)
{
    return ((grid*)src)->nx;
}

size_t get_ny(void* src)
{
    return ((grid*)src)->ny;
}

size_t get_nz(void* src)
{
    return ((grid*)src)->nz;
}

size_t get_size(void* src)
{
    return ((grid*)src)->size;
}

void* copy_grid_format(void* ptr)
{
    grid* src  = (grid*)ptr;
    grid* dest = (grid*)malloc(sizeof(grid));
    dest->nx = src->nx;
    dest->ny = src->ny;
    dest->nz = src->nz;
    dest->size = src->size;
    dest->data = (double*)malloc(sizeof(double)*dest->size);
    dest->origin = (double*)malloc(sizeof(double)*3);

    dest->basis  = (double**)malloc(sizeof(double*)*3);
    for(size_t i = 0; i < 3; ++i)
        dest->basis[i] = (double*)malloc(sizeof(double)*3);

    for(size_t i = 0; i < 3; ++i)
    {
        for(size_t j = 0; j < 3; ++j)
        {
            dest->basis[i][j] = src->basis[i][j];
        }
        dest->origin[i] = src->origin[i];
    }
    return dest;   
}

void sum_grids(void* dest, int num, void** src)
{
    grid** in = (grid**)src;
    grid* out = (grid*)dest;
    for(size_t idx = 0; idx < out->size; idx++)
    {
        out->data[idx] = 0.;
        for(size_t i = 0; i < (size_t)num; ++i)
            out->data[idx] += in[i]->data[idx];
    }
}