Refactor preprocessor
Refactor current functionality of preprocessor.
-
Modularize preprocessor for testability -
CLI -
high level architecture, leaving open detailed implementations
A rough draft:
#include "geometry/box.h"
#include "geometry/point.h"
#include "vtkwriter/vtkIO.h"
#include <array>
#include <memory>
#include <string>
#include <tuple>
#include <vector>
constexpr std::size_t Dimension = 3;
constexpr double remesh_tolerance = 1.0e1;
struct Material {
std::array<std::array<double, Dimension>, Dimension> basis_vectors;
Material(
const std::array<std::array<double, Dimension>, Dimension> &basis_vectors)
: basis_vectors{basis_vectors} {}
};
struct ExtendedFinnisSinclairCopper {
static std::array<std::array<double, Dimension>, Dimension>
make_basis_vectors(
const std::array<std::array<double, Dimension>, Dimension> &matrix) {
// TODO
return std::array<std::array<double, Dimension>, Dimension>{};
}
};
using Point = std::array<double, Dimension>;
using Simplex = std::array<Point, Dimension + 1>;
struct Mesh {
std::vector<Simplex> simplices;
std::vector<geometry::Point<Dimension>> points;
};
struct Lattice {
std::vector<int> material_ids;
geometry::Box<geometry::Point<Dimension>> domain_bounds;
std::vector<geometry::Point<Dimension>> points;
geometry::Box<geometry::Point<Dimension>> atomistic_domain;
};
using LatticeGenerator =
Lattice (*)(const std::array<std::array<double, Dimension>, Dimension> &);
// TODO: Adapt NanoIndentation.h to this interface
// Question: do we need different MeshGenerator?
using MeshGenerator = Mesh (*)(const Lattice &, const std::vector<Material> &);
// Question: should partitioning happen in preprocessing?
std::vector<Mesh> partition_mesh(const Mesh &global_mesh) {
// TODO, see mesh::uniformDistributionToLocalMesh
/*
Mesh local_mesh;
global_mesh.uniformDistributionToLocalMesh(local_mesh, lattice.material_ids);
local_mesh.initializeElementVectors();
local_mesh.updateElements();
local_mesh.initializeBravaisLattice(lattice.atomistic_domain, materials);
local_mesh.atomisticDomain_ = lattice.atomistic_domain;
local_mesh.initializeElementsAtomisticFlag();
*/
return std::vector<Mesh>{};
}
Mesh create_mesh(const LatticeGenerator &lattice_generator,
const MeshGenerator &mesh_generator,
const std::vector<Material> &materials) {
const auto lattice = lattice_generator(materials[0].basis_vectors);
auto mesh = mesh_generator(lattice, materials);
return mesh;
}
std::tuple<std::vector<geometry::Point<Dimension>>, std::vector<Simplex>>
triangulate(const std::vector<geometry::Point<Dimension>> &lattice_points) {
// TODO
return std::tuple<std::vector<geometry::Point<Dimension>>,
std::vector<Simplex>>{};
}
Mesh create_mesh_from_triangulation(
const std::vector<geometry::Point<Dimension>> &simplices,
const std::vector<Simplex> &points) {
// See: TriangulationToMesh::BuildMeshFromCgalTriangulation
// TODO
return Mesh{};
}
void trim_mesh(Mesh &mesh,
const geometry::Box<geometry::Point<Dimension>> &domain_bounds) {
//TODO
//See: mesh.trim(domain_bounds)
}
Mesh generate_mesh(const Lattice &lattice,
const std::vector<Material> &materials) {
const auto [simplices, points] = triangulate(lattice.points);
auto global_mesh = create_mesh_from_triangulation(simplices, points);
trim_mesh(global_mesh, lattice.domain_bounds);
return global_mesh;
}
struct CommandLineParameters {
bool display_element_markers;
std::string mesh_folder;
std::string partition_folder;
bool save_lattice_vectors;
};
CommandLineParameters parse_cmd_line(int argc, char *argv[]) {
// TODO
return CommandLineParameters{};
}
std::array<std::array<double, Dimension>, Dimension> identity() {
return std::array<std::array<double, Dimension>, Dimension>{
std::array<double, Dimension>{1., 0., 0.},
std::array<double, Dimension>{0., 1., 0.},
std::array<double, Dimension>{0., 0., 1.}};
}
void save_mesh(const Mesh &mesh, const std::string &output_folder,
bool save_lattice_vectors, bool display_element_markers) {
// save mesh .nc file and .pvtu file for visualization
vtkwriter::write_vtu_mesh_3d_minimal(mesh, remesh_tolerance, output_folder,
display_element_markers);
restart::WriteMeshParallel<Mesh, Dimension>(mesh, outputFileName,
save_lattice_vectors);
}
void save_initial_partition(const Mesh &mesh,
const std::string &output_folder) {
mesh.assignMaterials(materials);
bool reassign_lattice_vectors;
restart::ReadMeshFileParallel<QCMesh, DIM>(mesh, reassign_lattice_vectors,
outputMeshFile);
// there were no lattice vectors in the mesh file. Assigning all
// as initial vectors
if (reassign_lattice_vectors)
mesh.initializeBravaisLattice(materials);
mesh.initializeElementsAtomisticFlag();
vtkwriter::write_vtu_mesh_3d(mesh, remesh_tolerance, output_folder);
/**
* Needs:
* - nodes
* - simplices
* - quality
* - atomistic_flag
* - volume
* - rank
* - halo mesh (if display_halo_mesh)
* - nodes
* - simplices
* - ghost_nodes (if display_atom_markers)
* - boundary nodes (if display_boundary_nodes)
* - element markers (if display_element_markers)
*/
}
int main(int argc, char *argv[]) {
const auto cmd = parse_cmd_line(argc, argv);
std::vector<Material> materials{
ExtendedFinnisSinclairCopper::make_basis_vectors(identity())};
const auto global_mesh =
create_mesh(LatticeGenerator{}, MeshGenerator{}, materials);
const auto local_meshes = partition_mesh(global_mesh);
for (const auto local_mesh : local_meshes) {
// TODO: handle file names
save_mesh(local_mesh, cmd.mesh_folder, cmd.save_lattice_vectors,
cmd.display_element_markers);
save_initial_partition(local_mesh, cmd.partition_folder);
}
}
Edited by webmanue