Skip to content

Commit

Permalink
Merge pull request #765 from MFraters/add_properties_wrapper_functions
Browse files Browse the repository at this point in the history
Add properties wrapper functions to c wrapper
  • Loading branch information
MFraters authored Oct 27, 2024
2 parents 062d91d + 8844806 commit e6eb1fc
Show file tree
Hide file tree
Showing 9 changed files with 492 additions and 36 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Added
- Added a velocities system where each feature can define a velocity field and the gwb can return the resulting velocity field. \[Menno Fraters; 2024-10-20; [#761](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/761)\]
- There is now a CMake variable to automatically update the reference files for failed tests (gdb-dat and gwb-grid tests) \[Menno Fraters; 2024-10-20; [#761](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/761)\]
- There is now a properties_output_size function, which returns the size of the output vector/array returned by the properties functions for a given properties input vector \[Menno Fraters; 2024-10-27; [#765](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/765)\]
- Added 2d and 3d versions of the properties function to the C wrapper \[Menno Fraters; 2024-10-27; [#765](https://github.com/GeodynamicWorldBuilder/WorldBuilder/pull/765)\]

## Changed

Expand Down
9 changes: 9 additions & 0 deletions include/world_builder/world.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ namespace WorldBuilder
*/
void parse_entries(Parameters &prm);

/**
* Return the size of the output vector returned by the properties function for a given properties vector.
*
* @param properties The properties parameter from the properties function. See the documentation of that
* function for more info.
* @return unsigned int Return the size of the output vector returned by the properties function for a given properties vector.
*/
unsigned int properties_output_size(const std::vector<std::array<unsigned int,3>> &properties) const;

/**
* Returns different values at a single point in one go stored in a vector of doubles.
*
Expand Down
105 changes: 105 additions & 0 deletions include/world_builder/wrapper_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,111 @@ extern "C" {
*/
void create_world(void **ptr_ptr_world, const char *world_builder_file, const bool *has_output_dir, const char *output_dir, const unsigned long random_number_seed);



/**
* Return the size of the output vector returned by the properties function for a given properties vector.
*
* @param properties The properties parameter from the properties function. See the documentation of that
* function for more info.
* @param n_properties number of properties
* @return unsigned int Return the size of the output vector returned by the properties function for a given properties vector.
*/
unsigned int properties_output_size(void *ptr_ptr_world,
const unsigned int properties[][3],
const unsigned int n_properties);

/**
* @brief This function returns 2D properties.
*
* The properties input decides what each entry means, and the output is generated in the
* same order as the properties input. The properties input consists of
* a 3D array, where the first entry identifies the property and the last two entries
* provide extra information about that property.
*
* Temperature is identified by 1 and no extra information is needed. So temperature
* input usually looks like {1,0,0}. A temperature query prodoces one entry in the output
* vector.
*
* Composition is identified by 2. This produces one
* value in the output. The second entry identifies the composition number and the third
* number is not used. So a composition query asking about composition 1 looks like this:
* {2,1,0}. A composition query prodoces one entry in the output vector.
*
* Grains are identified by 3. The second entry is the grain composition number and the third
* entry is the number of grains. A query about the grains, where it asks about composition 1
* (for example enstatite) and 500 grains, looks like this: {3,1,500}.
* A composition query prodoces n_grains*10 entries in the output vector. The first n_grains
* entries are the sizes of all the grains, and the other 9 entries are sets of rotation
* matrices. The rotation matrix entries are ordered [0][0],[0][1],[0][2],[1][0],[1][1],etc.
*
* The tag is identified by 4 and no extra information is needed. So the tag
* input usually looks like {4,0,0}. A tag query prodoces one entry in the output
* vector, representing the index of the tag of the last/dominant feature.
*
* @param ptr_ptr_world a pointer to the world
* @param x The x position of the point
* @param z The z position of the point
* @param depth The depth of the point
* @param properties an array of properties, which each property is an array of three integers.
* @param n_properties number of properties.
* @param values are the return values as a pointer to an array of doubles
*/
void properties_2d(void *ptr_ptr_world,
const double x,
const double z,
const double depth,
const unsigned int properties[][3],
const unsigned int n_properties,
double values[]);


/**
* @brief This function returns 3D properties.
*
* The properties input decides what each entry means, and the output is generated in the
* same order as the properties input. The properties input consists of
* a 3D array, where the first entry identifies the property and the last two entries
* provide extra information about that property.
*
* Temperature is identified by 1 and no extra information is needed. So temperature
* input usually looks like {1,0,0}. A temperature query prodoces one entry in the output
* vector.
*
* Composition is identified by 2. This produces one
* value in the output. The second entry identifies the composition number and the third
* number is not used. So a composition query asking about composition 1 looks like this:
* {2,1,0}. A composition query prodoces one entry in the output vector.
*
* Grains are identified by 3. The second entry is the grain composition number and the third
* entry is the number of grains. A query about the grains, where it asks about composition 1
* (for example enstatite) and 500 grains, looks like this: {3,1,500}.
* A composition query prodoces n_grains*10 entries in the output vector. The first n_grains
* entries are the sizes of all the grains, and the other 9 entries are sets of rotation
* matrices. The rotation matrix entries are ordered [0][0],[0][1],[0][2],[1][0],[1][1],etc.
*
* The tag is identified by 4 and no extra information is needed. So the tag
* input usually looks like {4,0,0}. A tag query prodoces one entry in the output
* vector, representing the index of the tag of the last/dominant feature.
*
* @param ptr_ptr_world a pointer to the world
* @param x The x position of the point
* @param x The y position of the point
* @param z The z position of the point
* @param depth The depth of the point
* @param properties an array of properties, which each property is an array of three integers.
* @param n_properties number of properties.
* @param values are the return values as a pointer to an array of doubles
*/
void properties_3d(void *ptr_ptr_world,
const double x,
const double y,
const double z,
const double depth,
const unsigned int properties[][3],
const unsigned int n_properties,
double values[]);

/**
* This function return the temperature at a specific location given x, z, depth and
* gravity.
Expand Down
41 changes: 41 additions & 0 deletions source/world_builder/world.cc
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,47 @@ namespace WorldBuilder



unsigned int
World::properties_output_size(const std::vector<std::array<unsigned int,3>> &properties) const
{
unsigned int n_output_entries = 0;
for (auto property : properties)
{
switch (property[0])
{
case 1: // Temperature
n_output_entries += 1;
break;
case 2: // composition
n_output_entries += 1;
break;
case 3: // grains (10 entries per grain)
{
n_output_entries += property[2]*10;
break;
}
case 4: // tag
{
n_output_entries += 1;
break;
}
case 5: // velocity (3 entries)
{
n_output_entries += 3;
break;
}
default:
WBAssertThrow(false,
"Internal error: Unimplemented property provided. " <<
"Only temperature (1), composition (2), grains (3), tag (4) or velocity (5) are allowed. "
"Provided property number was: " << property[0]);
}
}
return n_output_entries;
}



std::vector<double>
World::properties(const std::array<double, 2> &point,
const double depth,
Expand Down
138 changes: 105 additions & 33 deletions source/world_builder/wrapper_c.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@

#include "world_builder/wrapper_c.h"

#include "world_builder/assert.h"
#include "world_builder/world.h"
#include <vector>

extern "C" {
/**
* This function creates an object of the world builder and returns a pointer
* to it. This pointer can then be used to call the temperature and composition
* functions. When done call the release world function to destroy the object.
*/
void create_world(void **ptr_ptr_world, const char *world_builder_file, const bool *has_output_dir_, const char *output_dir_, const unsigned long random_number_seed)
void create_world(void **ptr_ptr_world, const char *world_builder_file,
const bool *has_output_dir_, const char *output_dir_,
const unsigned long random_number_seed)
{
bool has_output_dir = false;

Expand All @@ -42,67 +46,135 @@ extern "C" {
output_dir = *output_dir_;
}

WorldBuilder::World *a = new WorldBuilder::World(std::string(world_builder_file), has_output_dir, output_dir,random_number_seed);
WorldBuilder::World *a =
new WorldBuilder::World(std::string(world_builder_file), has_output_dir,
output_dir, random_number_seed);

*ptr_ptr_world = reinterpret_cast<void *>(a);
}


/**
* This function return the temperature at a specific location given x, z, depth and
* gravity.
*/
void temperature_2d(void *ptr_ptr_world, double x, double z, double depth, double *temperature)
unsigned int properties_output_size(void *ptr_ptr_world,const unsigned int properties_[][3],
const unsigned int n_properties)
{
WorldBuilder::World *a = reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double,2> position = {{x,z}};
*temperature = a->temperature(position,depth);
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
std::vector<std::array<unsigned int, 3>> properties(n_properties);
for (size_t i = 0; i < n_properties; ++i)
{
properties[i][0] = properties_[i][0];
properties[i][1] = properties_[i][1];
properties[i][2] = properties_[i][2];
}
return a->properties_output_size(properties);
}

void properties_2d(void *ptr_ptr_world, const double x, const double z,
const double depth, const unsigned int properties_[][3],
const unsigned int n_properties, double values[])
{
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double, 2> position = {{x, z}};
std::vector<std::array<unsigned int, 3>> properties(n_properties);
for (size_t i = 0; i < n_properties; ++i)
{
properties[i][0] = properties_[i][0];
properties[i][1] = properties_[i][1];
properties[i][2] = properties_[i][2];
}
std::vector<double> returned_values = a->properties(position, depth, properties);
for (unsigned i = 0; i < returned_values.size(); ++i)
{
values[i] = returned_values[i];
}
}

/**
* This function return the temperature at a specific location given x, y, z, depth and
* gravity.
*/
void temperature_3d(void *ptr_ptr_world, double x, double y, double z, double depth, double *temperature)
void properties_3d(void *ptr_ptr_world,
const double x,
const double y,
const double z,
const double depth,
const unsigned int properties_[][3],
const unsigned int n_properties,
double values[])
{
WorldBuilder::World *a = reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double,3> position = {{x,y,z}};
*temperature = a->temperature(position,depth);
std::vector<std::array<unsigned int,3>> properties(n_properties);
for (size_t i = 0; i < n_properties; ++i)
{
properties[i][0] = properties_[i][0];
properties[i][1] = properties_[i][1];
properties[i][2] = properties_[i][2];
}
std::vector<double> returned_values = a->properties(position, depth, properties);
for (unsigned i = 0; i < returned_values.size(); ++i)
{
values[i] = returned_values[i];
}
}


/**
* This function return the composition at a specific location given x, z, depth and
* composition number.
* This function return the temperature at a specific location given x, z, depth
* and gravity.
*/
void composition_2d(void *ptr_ptr_world, double x, double z, double depth, unsigned int composition_number, double *composition)
void temperature_2d(void *ptr_ptr_world, double x, double z, double depth,
double *temperature)
{
WorldBuilder::World *a = reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double,2> position = {{x,z}};
*composition = a->composition(position,depth,composition_number);
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double, 2> position = {{x, z}};
*temperature = a->temperature(position, depth);
}

/**
* This function return the temperature at a specific location given x, y, z,
* depth and gravity.
*/
void temperature_3d(void *ptr_ptr_world, double x, double y, double z,
double depth, double *temperature)
{
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double, 3> position = {{x, y, z}};
*temperature = a->temperature(position, depth);
}

/**
* This function return the composition at a specific location given x, y, z, depth and
* composition number.
* This function return the composition at a specific location given x, z, depth
* and composition number.
*/
void composition_3d(void *ptr_ptr_world, double x, double y, double z, double depth, unsigned int composition_number, double *composition)
void composition_2d(void *ptr_ptr_world, double x, double z, double depth,
unsigned int composition_number, double *composition)
{
WorldBuilder::World *a = reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double,3> position = {{x,y,z}};
*composition = a->composition(position,depth,composition_number);
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double, 2> position = {{x, z}};
*composition = a->composition(position, depth, composition_number);
}

/**
* This function return the composition at a specific location given x, y, z,
* depth and composition number.
*/
void composition_3d(void *ptr_ptr_world, double x, double y, double z,
double depth, unsigned int composition_number,
double *composition)
{
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
const std::array<double, 3> position = {{x, y, z}};
*composition = a->composition(position, depth, composition_number);
}

/**
* The destructor for the world builder class. Call this function when done with the
* world builder.
* The destructor for the world builder class. Call this function when done with
* the world builder.
*/
void release_world(void *ptr_ptr_world)
{
WorldBuilder::World *a = reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
WorldBuilder::World *a =
reinterpret_cast<WorldBuilder::World *>(ptr_ptr_world);
delete a;
}
}
Loading

0 comments on commit e6eb1fc

Please sign in to comment.