Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atomistic file extension #16

Draft
wants to merge 26 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3432729
Refactor: Moved validation of segment header keywords
Aug 16, 2021
6fef06f
Moved parser_state into its own header
Aug 18, 2021
b582197
Added keywords header file
Aug 18, 2021
f4fcb5d
Use pegtl keywords rules to parse segment headers.
Aug 18, 2021
fcee71d
Implemented atomistic keywords
Aug 18, 2021
e8346d1
Improved exceptions in atomistic keywords
Aug 18, 2021
f3f0257
Implemented parsing of atomsitic keywords
Aug 18, 2021
b8b3d63
Adjusted ctypes structs to atomistic properties
Aug 18, 2021
b6005d6
Added unit test for atomistic ovf and made it work
Aug 18, 2021
0f19e98
Added check for missing and wrong keywords for meshtype 'lattice'
Aug 18, 2021
27ddbb2
Use segment.n_cells member instead of creating new anodes, bnodes and…
Aug 18, 2021
721a632
Minor changes in parser_state
Aug 18, 2021
b2fc5e3
Implemented compatibility format in write.
Aug 18, 2021
b6d3c21
Improved implementation of `basis_value` keyword
Aug 18, 2021
e117b62
Adjusted keyword `basis` for aovf_comp format
Aug 18, 2021
6c61daf
Completed parsing/writing of AOVF_COMP format files
Aug 18, 2021
7f94b2a
Testing: Moved atomistic tests to own file and extended them
Aug 19, 2021
97adfad
Small fix for atomistic keywords meshtype value
Aug 19, 2021
29f3b2c
Added extension_format defines in ovf.py
Aug 19, 2021
3d96f05
Added simple test for atomistic case to python API
Aug 19, 2021
b33696d
Unit test: Added a test that tries to read in weirdly formatted but v…
Aug 27, 2021
9a5a338
Parse_Rules: Changes to be more robust against whitespace/comments an…
Aug 31, 2021
8f5e068
Parse_Rules: More rigorous parsing
Aug 31, 2021
9b3ddcc
Moved pegtl parsing of Vector3 into a utility function
Sep 4, 2021
6c1308b
Renamed found_meshtype_atomistic to found_meshtype_lattice
Sep 5, 2021
32da6aa
Removed const_cast<char*>("literal").
Sep 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ if ( OVF_BUILD_TEST )
add_cxx_test( test_cpp_simple simple.cpp )
add_cxx_test( test_cpp_binary binary.cpp )
add_cxx_test( test_cpp_atomistic atomistic.cpp )
add_cxx_test( test_cpp_weird weird_formatting.cpp )
endif()


Expand Down
231 changes: 38 additions & 193 deletions include/detail/atomistic_keywords.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,202 +10,86 @@ namespace detail
namespace keywords
{

////// meshtype

// Only reimplement the new value
struct meshtype_value_lattice : TAO_PEGTL_ISTRING("lattice") // Only 'rectangular', 'irregular' or 'lattice' allowed
{ };
// set up some utilities for parsing vector3
namespace Vector3 = ovf::detail::parse::Vector3;

template<>
struct kw_action< meshtype_value_lattice >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.meshtype = strdup(in.string().c_str());
f._state->found_meshtype_atomistic = true;
f._state->found_meshtype = true;
}
};
using vec3_t = float[3];

////// bravaisa
// x
struct bravaisa_value_x : pegtl::pad<ovf::detail::parse::decimal_number, pegtl::blank>
{ };
template<typename Rule>
using vec3_action_t = Vector3::action<Rule, vec3_t>;

template<>
struct kw_action< bravaisa_value_x >
template<class Input>
inline void read_vector(const Input & in, vec3_t & vec3_data)
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisa[0] = std::stof(in.string());
}
};

// y
struct bravaisa_value_y : pegtl::pad<decimal_number, pegtl::blank>
{ };
Vector3::read_vec3<const Input &, vec3_t, vec3_action_t>(in, vec3_data);
}

template<>
struct kw_action< bravaisa_value_y >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisa[1] = std::stof(in.string());
}
};
////// meshtype

// z
struct bravaisa_value_z : pegtl::pad<decimal_number, pegtl::blank>
// ONLY TRIGGERS ON MESHTYPE LATTICE, the rest of the meshtype keyword is implemented in keywords.hpp
struct meshtype_value_lattice : TAO_PEGTL_ISTRING("lattice") // This keyword is triggered only, when meshtype lattice is found
{ };

template<>
struct kw_action< bravaisa_value_z >
struct kw_action< meshtype_value_lattice >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisa[2] = std::stof(in.string());
segment.meshtype = strdup(in.string().c_str());
f._state->found_meshtype = true;
f._state->found_meshtype_lattice = true;
}
};

struct bravaisa_value : pegtl::seq<bravaisa_value_x, bravaisa_value_y, bravaisa_value_z, end_kw_value>
////// bravaisa
struct bravaisa : TAO_PEGTL_ISTRING("bravaisa")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe "bravais_a" would be a more readable name than "bravaisa"?

{ };

struct bravaisa_value : pegtl::seq<Vector3::vec3, end_kw_value> {};
template<>
struct kw_action< bravaisa_value >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
f._state->found_bravaisa = true;
read_vector(in, segment.bravaisa);
}
};

struct bravaisa : TAO_PEGTL_ISTRING("bravaisa")
{ };

////// bravaisb
// x
struct bravaisb_value_x : pegtl::pad<ovf::detail::parse::decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisb_value_x >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisb[0] = std::stof(in.string());
}
};

// y
struct bravaisb_value_y : pegtl::pad<decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisb_value_y >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisb[1] = std::stof(in.string());
}
};

// z
struct bravaisb_value_z : pegtl::pad<decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisb_value_z >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisb[2] = std::stof(in.string());
}
};

struct bravaisb_value : pegtl::seq<bravaisb_value_x, bravaisb_value_y, bravaisb_value_z, end_kw_value>
struct bravaisb : TAO_PEGTL_ISTRING("bravaisb")
{ };

struct bravaisb_value : pegtl::seq<Vector3::vec3, end_kw_value> {};
template<>
struct kw_action< bravaisb_value >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
f._state->found_bravaisb = true;
read_vector(in, segment.bravaisb);
}
};

struct bravaisb : TAO_PEGTL_ISTRING("bravaisb")
{ };

////// bravaisc
// x
struct bravaisc_value_x : pegtl::pad<ovf::detail::parse::decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisc_value_x >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisc[0] = std::stof(in.string());
}
};

// y
struct bravaisc_value_y : pegtl::pad<decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisc_value_y >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisc[1] = std::stof(in.string());
}
};

// z
struct bravaisc_value_z : pegtl::pad<decimal_number, pegtl::blank>
{ };

template<>
struct kw_action< bravaisc_value_z >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
segment.bravaisc[2] = std::stof(in.string());
}
};

struct bravaisc_value : pegtl::seq<bravaisc_value_x, bravaisc_value_y, bravaisc_value_z, end_kw_value>
struct bravaisc : TAO_PEGTL_ISTRING("bravaisc")
{ };

struct bravaisc_value : pegtl::seq<Vector3::vec3, end_kw_value> {};
template<>
struct kw_action< bravaisc_value >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
f._state->found_bravaisc = true;
read_vector(in, segment.bravaisc);
}
};

struct bravaisc : TAO_PEGTL_ISTRING("bravaisc")
{ };


////// ncellpoints
struct ncellpoints : TAO_PEGTL_ISTRING("ncellpoints")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe "n_cell_points" would be more readable?

{ };
Expand All @@ -221,7 +105,7 @@ namespace keywords
{
segment.ncellpoints = std::stoi(in.string());
f._state->found_ncellpoints = true;
segment.basis = new float[3 * segment.ncellpoints];
f._state->_basis.reserve(segment.ncellpoints); // If we find ncellpoints, we reserve the space
}
};

Expand Down Expand Up @@ -292,62 +176,21 @@ namespace keywords
struct cur_basis_line_value_z : pegtl::pad<decimal_number, pegtl::blank>
{ };

struct basis_value_line : pegtl::seq< pegtl::string<'#'>, pegtl::opt<TAO_PEGTL_ISTRING("#%")>, cur_basis_line_value_x, cur_basis_line_value_y, cur_basis_line_value_z>
struct basis_value_line : Vector3::vec3
{ };

struct basis_value : pegtl::seq< pegtl::eol, pegtl::list<basis_value_line, pegtl::eol > >
struct basis_value : pegtl::seq< pegtl::eol, pegtl::list<pegtl::seq< pegtl::string<'#'>, pegtl::opt<TAO_PEGTL_ISTRING("#%")>, basis_value_line>, pegtl::eol > >
{ };

template<>
struct kw_action< cur_basis_line_value_x >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
if( !f._state->found_ncellpoints ) // Need to make sure that the basis array is already allocated
{
throw tao::pegtl::parse_error(fmt::format("ncellpoints must be specified before the basis!"), in);
}
segment.basis[3 * f._state->_cur_basis_line + 0] = std::stof(in.string());
}
};

template<>
struct kw_action< cur_basis_line_value_y >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
if( !f._state->found_ncellpoints ) // Need to make sure that the basis array is already allocated
{
throw tao::pegtl::parse_error(fmt::format("ncellpoints must be specified before the basis!"), in);
}
segment.basis[3*f._state->_cur_basis_line + 1] = std::stof(in.string());
}
};

template<>
struct kw_action< cur_basis_line_value_z >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
if( !f._state->found_ncellpoints ) // Need to make sure that the basis array is already allocated
{
throw tao::pegtl::parse_error(fmt::format("ncellpoints must be specified before the basis!"), in);
}
segment.basis[3* f._state->_cur_basis_line + 2] = std::stof(in.string());
}
};

template<>
struct kw_action< basis_value_line >
{
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
// fmt::print("basis line value: {}\n", in.string());
f._state->_cur_basis_line++;
float temp[3];
read_vector( in, temp );
f._state->_basis.push_back( {temp[0], temp[1], temp[2]} );
Comment on lines +191 to +193
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::vector<std::array<float, 3>> _basis = std::vector<std::array<float, 3>>(0);

I therefore believe it would be more canonical to write

auto atom = f._state->_basis.emplace_back();
read_vector( in, (*atom).data() );

or

std::array<float,3> atom;
read_vector( in, atom.data() );
f._state->_basis.push_back(atom);

}
};

Expand All @@ -357,12 +200,14 @@ namespace keywords
template< typename Input >
static void apply( const Input& in, ovf_file & f, ovf_segment & segment)
{
// fmt::print("basis value: {}\n", in.string());

f._state->found_basis = true;
if( segment.ncellpoints != f._state->_cur_basis_line ) // Need to make sure that the basis array is already allocated
// Allocate and data in segment struct and copy
segment.basis = new float[3 * f._state->_basis.size()];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid memory leaks, lines like this should probably be preceded by

if( segment.basis )
    delete segment.basis;

for( int i=0; i<f._state->_basis.size(); i++)
{
throw tao::pegtl::parse_error( fmt::format("ncellpoints ({}) and number of specified basis atoms ({}) does not match!", segment.ncellpoints, f._state->_cur_basis_line ), in);
segment.basis[3*i] = f._state->_basis[i][0];
segment.basis[3*i + 1] = f._state->_basis[i][1];
segment.basis[3*i + 2] = f._state->_basis[i][2];
}
}
};
Expand Down
Loading