diff options
-rw-r--r-- | agent.cpp | 18 | ||||
-rw-r--r-- | agent.hpp | 3 | ||||
-rw-r--r-- | header.hpp | 19 | ||||
-rw-r--r-- | input/options.input | 16 | ||||
-rw-r--r-- | main.cpp | 112 | ||||
-rw-r--r-- | makefile | 4 | ||||
-rw-r--r-- | mesh.cpp | 34 | ||||
-rw-r--r-- | mesh.hpp | 14 | ||||
-rw-r--r-- | parser.cpp | 114 | ||||
-rw-r--r-- | parser.hpp | 55 | ||||
-rwxr-xr-x | tools/merge-results.sh (renamed from merge-results.sh) | 0 |
11 files changed, 314 insertions, 75 deletions
@@ -29,12 +29,12 @@ void Agent::advance(Mesh* mesh, size_t step) // GETTERS AND SETTERS // ------------------------------------------------------------------------ -Agent::Agent() +void Agent::init(int n_iteration) { - time.resize(N_ITERATION); - domain.resize(N_ITERATION); - path.resize(N_ITERATION); - for (size_t i = 0; i < N_ITERATION; i ++) + time.resize(n_iteration); + domain.resize(n_iteration); + path.resize(n_iteration); + for (int i = 0; i < n_iteration; i ++) path[i].resize(DIM); } @@ -150,7 +150,7 @@ void Agent::advance_surface(Mesh* mesh, size_t step) // check if out of the domain: if the agent travelled thrice the // maximum length of the cell and still can't find a neighboring // cell, it must be advected out of the domain - if (distance_norm > 10.0 * location->get_maximum_length()) + if (distance_norm > 15.0 * location->get_maximum_length()) domain[step] = OUTSIDE_FLAG; } else { @@ -224,9 +224,9 @@ void Agent::advance_subsurface(Mesh* mesh, size_t step) // check if out of the domain: if the agent travelled thrice the // maximum length of the cell and still can't find a neighboring // cell, it must be advected out of the domain - if (distance_norm > 10.0 * location->get_maximum_length()) { - domain[step] = OUTSIDE_FLAG; - } + // if (distance_norm > 15.0 * location->get_maximum_length()) { + // domain[step] = OUTSIDE_FLAG; + // } // check if exfiltrates int neighbor_index = mesh->get_cell(cell_index, SUBSURFACE_FLAG)->get_coupled_neighbor(); @@ -12,8 +12,9 @@ class Agent public: - Agent(); + // Agent(); + void init(int n_iteration); void set_cell_index(int value); void set_domain(int value, size_t step); void set_path(double x, double y, double z, size_t step); @@ -6,22 +6,21 @@ #include <iostream> #include <vector> #include <string> // string class -//#include <omp.h> #include <algorithm> // min #include <float.h> // DBL_MAX #include <math.h> // fabs, sqrt #include <mpi.h> +#include <fstream> // ifstream +#include <sstream> // stringstream +#include <string.h> // strcmp #include <H5Cpp.h> #include <H5File.h> #define MAXPRINT 5 -#define MAXTIMESTEP 1.0e5 +#define MAXTIMESTEP 1.0e8 #define EPS 1.0e-10 -#define N_AGENT 100 -#define N_ITERATION 2000 -#define SEED 108 #define CFL 0.5 #define DIM 3 @@ -35,19 +34,13 @@ #define INFILTRATE_TRUE 1 #define INFILTRATE_FALSE 2 -#define SURFACE_MESH_FILE "../test/visdump_surface_mesh.h5" -#define SURFACE_DATA_FILE "../test/visdump_surface_data.h5" -#define SUBSURFACE_MESH_FILE "../test/visdump_mesh.h5" -#define SUBSURFACE_DATA_FILE "../test/visdump_data.h5" -#define SURFACE_DATA_GROUP_NAME_H5 "11841" -#define SUBSURFACE_DATA_GROUP_NAME_H5 "11841" +// #define SURFACE_DATA_GROUP_NAME_H5 "11841" +// #define SUBSURFACE_DATA_GROUP_NAME_H5 "11841" #define MESH_MIXED_ELEMENTS "/0/Mesh/MixedElements" #define MESH_NODES "/0/Mesh/Nodes" #define AREADIV 0.01 -#define FUZZ 0.1 -#define RADIUS 200.0 #define SUBSURFACE_FLAG 1 #define SURFACE_FLAG 2 diff --git a/input/options.input b/input/options.input new file mode 100644 index 0000000..345e606 --- /dev/null +++ b/input/options.input @@ -0,0 +1,16 @@ +// input file for agent provocateur + +n_agent : 100 // Number of agents +fuzz : 0.1 // Fuzzy equivalence constant, used for geometry +seed : 108 // Random seed +n_iteration : 2000 // Number of iteration steps + +surfacemesh : ./test/visdump_surface_mesh.h5 // Surface mesh file +surfacedata : ./test/visdump_surface_data.h5 // Surface data file +surfacetime : 0.0 236.7 473.5 709.3 941.8 // Time levels +surfacegroup : 0 3746 6484 9372 11841 // Group names for surface + +subsurfacemesh : ./test/visdump_mesh.h5 // Subsurface mesh file +subsurfacedata : ./test/visdump_data.h5 // Subsurface data file +subsurfacetime : 0.0 236.7 473.5 709.3 941.8 // Time levels +subsurfacegroup : 0 3746 6484 9372 11841 // Group names for subsurface @@ -2,6 +2,7 @@ #include "mesh.hpp" #include "agent.hpp" +#include "parser.hpp" int main(int argc, char* argv[]) { @@ -13,25 +14,74 @@ int main(int argc, char* argv[]) MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); - Mesh mesh = Mesh(); - - H5::H5File fp_subsurface = H5::H5File(SUBSURFACE_MESH_FILE, H5F_ACC_RDONLY); - H5::H5File dp_subsurface = H5::H5File(SUBSURFACE_DATA_FILE, H5F_ACC_RDONLY); - H5::H5File fp_surface = H5::H5File(SURFACE_MESH_FILE, H5F_ACC_RDONLY); - H5::H5File dp_surface = H5::H5File(SURFACE_DATA_FILE, H5F_ACC_RDONLY); + if (rank == 0) { + + std::cout << std::endl; + std::cout << " / /^ agent provocateur" << std::endl; + std::cout << " o--o =================" << std::endl; + std::cout << std::endl; + + std::cout << "[~>] Read in input data" << std::endl; + + } - if (rank == 0) + Parser parser; + parser.read_options("input/options.input"); + + if (rank == 0) { + + std::cout << "[~~>] Number of agents: " << parser.n_agent << std::endl; + std::cout << "[~~>] Number of iterations: " << parser.n_iteration << std::endl; + std::cout << "[~~>] Random seed: " << parser.seed << std::endl; + std::cout << "[~~>] Geometric fuzz: " << parser.fuzz << std::endl; + + std::cout << "[~~>] Surface mesh file: " << parser.surface_mesh_file << std::endl; + std::cout << "[~~>] Surface data file: " << parser.surface_data_file << std::endl; + std::cout << "[~~>] Surface time: "; + for (uint i = 0; i < parser.surface_time.size(); i ++) + std::cout << parser.surface_time[i] << " "; + std::cout <<std::endl; + std::cout << "[~~>] Surface group: "; + for (uint i = 0; i < parser.surface_data_group.size(); i ++) + std::cout << parser.surface_data_group[i] << " "; + std::cout <<std::endl; + + std::cout << "[~~>] Subsurface mesh file: " << parser.subsurface_mesh_file << std::endl; + std::cout << "[~~>] Subsurface data file: " << parser.subsurface_data_file << std::endl; + std::cout << "[~~>] Subsurface time: "; + for (uint i = 0; i < parser.subsurface_time.size(); i ++) + std::cout << parser.subsurface_time[i] << " "; + std::cout <<std::endl; + std::cout << "[~~>] Subsurface group: "; + for (uint i = 0; i < parser.subsurface_data_group.size(); i ++) + std::cout << parser.subsurface_data_group[i] << " "; + std::cout << std::endl; + std::cout << std::endl; + std::cout << "[~>] Building the subsurface mesh" << std::endl; + + } + Mesh mesh = Mesh(); + + mesh.set_fuzz(parser.fuzz); + + H5::H5File fp_subsurface = H5::H5File(parser.subsurface_mesh_file.c_str(), H5F_ACC_RDONLY); + H5::H5File dp_subsurface = H5::H5File(parser.subsurface_data_file.c_str(), H5F_ACC_RDONLY); + H5::H5File fp_surface = H5::H5File(parser.surface_mesh_file.c_str(), H5F_ACC_RDONLY); + H5::H5File dp_surface = H5::H5File(parser.surface_data_file.c_str(), H5F_ACC_RDONLY); + mesh.build_subsurface_mesh(fp_subsurface); fp_subsurface.close(); if (rank == 0) { std::cout << "[~~>] Number of cells: " << mesh.get_n_cells(SUBSURFACE_FLAG) << std::endl; + std::cout << std::endl; + std::cout << "[~>] Building the surface mesh (includes coupling with subsurface and may take a while)" << std::endl; } - mesh.build_surface_mesh(fp_surface, dp_surface); + mesh.build_surface_mesh(fp_surface, dp_surface, parser.surface_data_group[0]); fp_surface.close(); if (rank == 0) { @@ -39,18 +89,18 @@ int main(int argc, char* argv[]) int len_surf = mesh.get_n_cells(SURFACE_FLAG); std::cout << "[~~>] Number of cells: " << len_surf << std::endl; + std::cout << std::endl; FILE *mesh_fp = fopen("mesh.csv", "w"); fprintf(mesh_fp, "x (m), y (m), z (m), index\n"); Cell *c; - for (int n = 0; n < len_surf; n ++) { - c = mesh.get_cell(n, SURFACE_FLAG); - fprintf(mesh_fp, "%f, %f, %f, %d\n", - c->get_coordinate(0), - c->get_coordinate(1), - c->get_coordinate(2), n); + c = mesh.get_cell(n, SURFACE_FLAG); + fprintf(mesh_fp, "%f, %f, %f, %d\n", + c->get_coordinate(0), + c->get_coordinate(1), + c->get_coordinate(2), n); } fclose(mesh_fp); @@ -59,30 +109,36 @@ int main(int argc, char* argv[]) } - mesh.build_environment(dp_subsurface, SUBSURFACE_FLAG); + mesh.build_environment(dp_subsurface, parser.subsurface_data_group[0], SUBSURFACE_FLAG); dp_subsurface.close(); - mesh.build_environment(dp_surface, SURFACE_FLAG); - dp_subsurface.close(); + if (rank == 0) { + std::cout << "[~>] Reading the surface environment" << std::endl; + std::cout << std::endl; + } + + mesh.build_environment(dp_surface, parser.surface_data_group[0], SURFACE_FLAG); + dp_surface.close(); // Place agents in the domain and advance N_ITERATION steps // Bootstrap - srand(SEED + rank); + srand(parser.seed + rank); int len = mesh.get_n_cells(SUBSURFACE_FLAG); int index; - std::cout << "[~>] Releasing " << N_AGENT << " agents" << std::endl; + std::cout << "[~>] Releasing " << parser.n_agent << " agents" << std::endl; - size_t partition = N_AGENT / size; + size_t partition = parser.n_agent / size; size_t low_bound = rank * partition; size_t high_bound = (rank + 1) * partition; if (rank == size - 1) // top processor picks up extras - high_bound = N_AGENT; + high_bound = parser.n_agent; for (size_t i = low_bound; i < high_bound; i ++) { Agent agent; + agent.init(parser.n_iteration); index = rand()%len; agent.set_cell_index(index); @@ -97,16 +153,20 @@ int main(int argc, char* argv[]) mesh.get_cell(index, SUBSURFACE_FLAG)->get_coordinate(1), mesh.get_cell(index, SUBSURFACE_FLAG)->get_coordinate(2), 1); - size_t step; + int step; char output_fname[1024]; // move agent - for (step = 1; step < N_ITERATION; step ++) { - if (step % (N_ITERATION / 5) == 0 && i % (N_AGENT / 5) == 0) { - std::cout << "[~~~>] agent[" << i << "] step = " << step << " dt = " << agent.get_timestepsize() << " s" << std::endl; + for (step = 1; step < parser.n_iteration; step ++) { + if (step % (parser.n_iteration / 5) == 0 && i % (parser.n_agent / 5) == 0) { + std::cout << "[~~>] agent[" << i << "] step = " << step << " dt = " << agent.get_timestepsize() << " s" << std::endl; } + agent.advance(&mesh, step); + + // update environment if necessary + } // write out results @@ -114,7 +174,7 @@ int main(int argc, char* argv[]) FILE *result_fp = fopen(output_fname, "w"); fprintf(result_fp, "time (s), x (m), y (m), z (m), domain\n"); - for (step = 0; step < N_ITERATION; step ++) { + for (step = 0; step < parser.n_iteration; step ++) { fprintf(result_fp, "%f, %f, %f, %f, %d\n", agent.get_time(step), agent.get_path(step, 0), @@ -2,9 +2,9 @@ PRG=agent-provocateur #CC=g++-11 CC=mpic++ -CXXFLAGS=-Wall -Wextra -pedantic -O0 -fopenmp +CXXFLAGS=-Wall -Wextra -pedantic -O0 LFLAGS=-I/opt/hdf5/include -L/opt/hdf5/lib -SRC=cell.cpp mesh.cpp main.cpp agent.cpp +SRC=parser.cpp cell.cpp mesh.cpp main.cpp agent.cpp LIB=-lm -lhdf5 -lhdf5_cpp OBJ=$(SRC:.cpp=.o) @@ -7,14 +7,14 @@ // -- PUBLIC METHODS // ------------------------------------------------------------------------ -void Mesh::build_surface_mesh(H5::H5File fp, H5::H5File ep) +void Mesh::build_surface_mesh(H5::H5File fp, H5::H5File ep, std::string datasetname) { get_mesh_metadata(fp, SURFACE_NCOL); handle_surface_node_data(fp); - build_surface_cells(ep); + build_surface_cells(ep, datasetname); } @@ -29,20 +29,17 @@ void Mesh::build_subsurface_mesh(H5::H5File fp) } -void Mesh::build_environment(H5::H5File ep, int flag) +void Mesh::build_environment(H5::H5File ep, std::string datasetname, int flag) { std::string groupname; - std::string datasetname; // Read in velocities in x direction if (flag == SUBSURFACE_FLAG) { groupname = "darcy_velocity.cell.0"; - datasetname = SUBSURFACE_DATA_GROUP_NAME_H5; } else if (flag == SURFACE_FLAG) { groupname = "surface-velocity.cell.0"; - datasetname = SURFACE_DATA_GROUP_NAME_H5; } read_velocity(ep, groupname, datasetname, flag, 0); @@ -51,10 +48,8 @@ void Mesh::build_environment(H5::H5File ep, int flag) if (flag == SUBSURFACE_FLAG) { groupname = "darcy_velocity.cell.1"; - datasetname = SUBSURFACE_DATA_GROUP_NAME_H5; } else if (flag == SURFACE_FLAG) { groupname = "surface-velocity.cell.1"; - datasetname = SURFACE_DATA_GROUP_NAME_H5; } read_velocity(ep, groupname, datasetname, flag, 1); @@ -63,10 +58,8 @@ void Mesh::build_environment(H5::H5File ep, int flag) if (flag == SUBSURFACE_FLAG) { groupname = "darcy_velocity.cell.2"; - datasetname = SUBSURFACE_DATA_GROUP_NAME_H5; } else if (flag == SURFACE_FLAG) { groupname = "surface-surface_subsurface_flux.cell.0"; - datasetname = SURFACE_DATA_GROUP_NAME_H5; } read_velocity(ep, groupname, datasetname, flag, 2); @@ -90,7 +83,7 @@ void Mesh::build_environment(H5::H5File ep, int flag) } // Read in water depth - read_water_depth(ep); + read_water_depth(ep, datasetname); } #if VERBOSE @@ -164,6 +157,11 @@ double Mesh::get_low_coordinate(int index) return low_coordinates[index]; } +void Mesh::set_fuzz(double value) +{ + fuzz = value; +} + // ------------------------------------------------------------------------ // -- PRIVATE METHODS // ------------------------------------------------------------------------ @@ -198,7 +196,7 @@ void Mesh::handle_surface_node_data(H5::H5File fp) } -void Mesh::build_surface_cells(H5::H5File ep) +void Mesh::build_surface_cells(H5::H5File ep, std::string datasetname) { std::vector<double> coords1(DIM-1); @@ -206,7 +204,7 @@ void Mesh::build_surface_cells(H5::H5File ep) std::vector<double> coords3(DIM-1); std::vector<double> coords_avg(DIM-1); - read_elevation(ep); + read_elevation(ep, datasetname); for (int i = 0; i < n_cells_surface; i ++) { @@ -270,7 +268,7 @@ void Mesh::build_surface_cells(H5::H5File ep) double xy_distance = sqrt(distance[0]*distance[0] + distance[1]*distance[1]); - if (xy_distance <= FUZZ) { + if (xy_distance <= fuzz) { dz = std::min(dz, fabs(distance[2])); coupled_neighbor = k; if (dz <= 2.0 * subsurface_cells[k].get_characteristic_length()) @@ -479,11 +477,11 @@ void Mesh::read_velocity(H5::H5File fp, std::string groupname, std::string datas } -void Mesh::read_water_depth(H5::H5File fp) +void Mesh::read_water_depth(H5::H5File fp, std::string datasetname) { H5::Group group = fp.openGroup("surface-ponded_depth.cell.0"); - H5::DataSet dataset = group.openDataSet(SURFACE_DATA_GROUP_NAME_H5); + H5::DataSet dataset = group.openDataSet(datasetname.c_str()); H5::DataType datatype = dataset.getDataType(); H5::DataSpace dataspace = dataset.getSpace(); @@ -512,11 +510,11 @@ void Mesh::read_water_depth(H5::H5File fp) } -void Mesh::read_elevation(H5::H5File fp) +void Mesh::read_elevation(H5::H5File fp, std::string datasetname) { H5::Group group = fp.openGroup("surface-elevation.cell.0"); - H5::DataSet dataset = group.openDataSet(SURFACE_DATA_GROUP_NAME_H5); + H5::DataSet dataset = group.openDataSet(datasetname.c_str()); H5::DataType datatype = dataset.getDataType(); H5::DataSpace dataspace = dataset.getSpace(); @@ -13,10 +13,10 @@ public: Mesh(); - void build_surface_mesh(H5::H5File fp, H5::H5File ep); + void build_surface_mesh(H5::H5File fp, H5::H5File ep, std::string datasetname); void build_subsurface_mesh(H5::H5File fp); - void build_environment(H5::H5File ep, int flag); + void build_environment(H5::H5File ep, std::string datasetname, int flag); void build_subsurface_environment(H5::H5File ep); Cell* get_cell(int index, int flag); @@ -25,6 +25,7 @@ public: double get_high_coordinate(int index); void set_low_coordinate(int index, double value); double get_low_coordinate(int index); + void set_fuzz(double value); int get_n_cells(int flag); @@ -32,6 +33,8 @@ private: int n_cells_subsurface; int n_cells_surface; + + double fuzz; std::vector<Cell> subsurface_cells; std::vector<Cell> surface_cells; @@ -41,18 +44,17 @@ private: std::vector<std::vector<double>> nodes; std::vector<std::vector<int>> element_node_indices; - //std::vector<std::vector<std::vector<hsize_t>>> edge_ids; void handle_subsurface_node_data(H5::H5File fp); void build_subsurface_cells(); void handle_surface_node_data(H5::H5File fp); - void build_surface_cells(H5::H5File fp); + void build_surface_cells(H5::H5File fp, std::string datasetname); void get_mesh_metadata(H5::H5File fp, int ncol); void read_velocity(H5::H5File fp, std::string groupname, std::string datasetname, int flag, int index); - void read_water_depth(H5::H5File fp); - void read_elevation(H5::H5File fp); + void read_water_depth(H5::H5File fp, std::string datasetname); + void read_elevation(H5::H5File fp, std::string datasetname); }; diff --git a/parser.cpp b/parser.cpp new file mode 100644 index 0000000..39527ed --- /dev/null +++ b/parser.cpp @@ -0,0 +1,114 @@ +#include "header.hpp" +#include "parser.hpp" + +void ParserLine::parse() +{ + + key.clear(); + value.clear(); + + if (!line.empty() && line.find("//", 0) != 0) { + + uint splitloc = line.find(":", 0); // find the colon + key = line.substr(0, splitloc); // store the key and value strings + key.erase(std::remove(key.begin(), key.end(), ' '), key.end()); // remove spaces and tabs + key.erase(std::remove(key.begin(), key.end(), '\t'), key.end()); + std::string val = line.substr(splitloc+1, line.length()-splitloc); + + size_t splitter = val.find("//", 0); + std::string strloc; + if (splitter != std::string::npos) { + strloc = val.substr(0, splitter); + } else { + strloc = val; + } + + value.clear(); + value.str(strloc); + + } + +} + + +void Parser::read_options(std::string fname) +{ + + std::ifstream fInStream(fname); + std::string line; + ParserLine pline; + + // initialize all read-in values to -999 + fuzz = -999; + n_agent = -999; + n_iteration = -999; + + if (fInStream.is_open()) { + + while (std::getline(fInStream, line)) { + + pline.line = line; + pline.parse(); + + if (!pline.key.empty()) { + + // Match the key and store the value + if (!strcmp("surfacemesh", pline.key.c_str())) { + pline.value >> surface_mesh_file; + } + else if (!strcmp("surfacedata", pline.key.c_str())) { + pline.value >> surface_data_file; + } + else if (!strcmp("surfacetime", pline.key.c_str())) { + double time; + while (pline.value >> time) { + surface_time.push_back(time); + } + } + else if (!strcmp("surfacegroup", pline.key.c_str())) { + std::string group; + while (pline.value >> group) { + surface_data_group.push_back(group); + } + } + else if (!strcmp("subsurfacemesh", pline.key.c_str())) { + pline.value >> subsurface_mesh_file; + } + else if (!strcmp("subsurfacedata", pline.key.c_str())) { + pline.value >> subsurface_data_file; + } + else if (!strcmp("subsurfacetime", pline.key.c_str())) { + double time; + while (pline.value >> time) { + subsurface_time.push_back(time); + } + } + else if (!strcmp("subsurfacegroup", pline.key.c_str())) { + std::string group; + while (pline.value >> group) { + subsurface_data_group.push_back(group); + } + } + else if (!strcmp("n_agent", pline.key.c_str())) { + pline.value >> n_agent; + } + else if (!strcmp("fuzz", pline.key.c_str())) { + pline.value >> fuzz; + } + else if (!strcmp("seed", pline.key.c_str())) { + pline.value >> seed; + } + else if (!strcmp("n_iteration", pline.key.c_str())) { + pline.value >> n_iteration; + } + else { + std::cerr << "[!!] Unrecognised option key" << std::endl; + } + + } + + } + + } + +} diff --git a/parser.hpp b/parser.hpp new file mode 100644 index 0000000..7ffda0d --- /dev/null +++ b/parser.hpp @@ -0,0 +1,55 @@ +// -*- mode: c++ -*- + +// +// Purpose: Read-in functionality to define parameters at runtime +// Based on the implementation of Morales-Hernandez /et al./'s SERGHEI +// + +#ifndef PARSER_HPP +#define PARSER_HPP + +#include "header.hpp" + +class ParserLine +{ + +public: + + std::string line; + std::string key; + std::stringstream value; + + void parse(); + +}; + +class Parser +{ + +public: + + std::string surface_mesh_file; + std::string surface_data_file; + std::string subsurface_mesh_file; + std::string subsurface_data_file; + + std::vector<std::string> surface_data_group; + std::vector<double> surface_time; + + std::vector<std::string> subsurface_data_group; + std::vector<double> subsurface_time; + + int n_agent; + int n_iteration; + int seed; + + int surface_np; + int subsurface_np; + + double fuzz; + + void read_options(std::string fname); + +}; + +#endif diff --git a/merge-results.sh b/tools/merge-results.sh index 5459897..5459897 100755 --- a/merge-results.sh +++ b/tools/merge-results.sh |