The executable generates two files.
#if BITPIT_ENABLE_MPI==1
#include <mpi.h>
#endif
#include "bitpit_surfunstructured.hpp"
#include "bitpit_voloctree.hpp"
#include "bitpit_levelset.hpp"
#include "bitpit_LA.hpp"
#include "bitpit_operators.hpp"
#include "bitpit_IO.hpp"
#include "bitpit_RBF.hpp"
#include "bitpit_common.hpp"
#include <array>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
#include <iomanip>
using namespace std;
using namespace bitpit;
void
parse_parameters(std::map<std::string, std::vector<double>> &map,
std::string file,
const std::string delimiter)
{
std::ifstream myfile(file);
if (myfile.is_open())
{
std::string line;
std::vector<std::string> column_names;
std::vector<double> line_of_data;
unsigned int line_count = 0;
while (std::getline(myfile, line))
{
std::vector<std::string> list_of_words_base;
std::string s = line;
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
list_of_words_base.push_back(token);
s.erase(0, pos + delimiter.length());
}
std::vector<std::string> list_of_words_clean;
for (std::size_t i = 0; i < list_of_words_base.size(); ++i)
{
if (list_of_words_base[i] != "")
{
list_of_words_clean.push_back(list_of_words_base[i]);
}
}
if (line_count != 0)
{
line_of_data.resize(list_of_words_clean.size());
for (std::size_t i = 0; i < line_of_data.size(); i++)
{
line_of_data[i] = std::stod(list_of_words_clean[i]);
}
for (std::size_t i = 0; i < line_of_data.size(); ++i)
{
map[column_names[i]].push_back(line_of_data[i]);
}
}
else
{
column_names = list_of_words_clean;
for (std::size_t i = 0; i < list_of_words_clean.size(); ++i)
{
std::vector<double> base_vector;
map[column_names[i]] = base_vector;
}
}
++line_count;
}
myfile.close();
}
else
std::cout << "Unable to open file";
std::vector<std::string> names = {"nb_subdivision",
"nb_adaptions",
"radius_ratio",
"base_function",
"mesh_range",
"tolerance",
"scaling"};
std::vector<double> values = {16,
0,
1,
2,
0.2,
1e-8,
1.0};
for (std::size_t i = 0; i < names.size(); i++)
{
if (map.find("f") == map.end())
map[names[i]].push_back(values[i]);
}
}
void run(std::string filename,
std::string data_path,
std::string parameter_file) {
constexpr int dimensions(3);
std::map<std::string, std::vector<double>> parameters;
parse_parameters(parameters, parameter_file," ");
int nb_subdivision = static_cast<int>(parameters["nb_subdivision"][0]);
int nb_adaptions = static_cast<int>(parameters["nb_adaptions"][0]);
double radius_ratio = parameters["radius_ratio"][0];
int base_function = static_cast<int>(parameters["base_function"][0]);
double mesh_range = parameters["mesh_range"][0];
double TOL = parameters["tolerance"][0];
double scaling = parameters["scaling"][0];
std::vector<std::string> timers_name;
std::vector<double> timers_values;
timers_name.push_back("load_geometry");
double time_start = MPI_Wtime();
#if BITPIT_ENABLE_MPI
#else
#endif
try {
STL0->importSTL(data_path + filename + ".stl", true);
}
catch (const std::bad_alloc &) {
STL0->importSTL(data_path + filename + ".stl", false);
}
STL0->deleteCoincidentVertices();
STL0->initializeAdjacencies();
STL0->getVTK().setName("levelset");
std::array<double, dimensions> center{};
STL0->scale(scaling,scaling,scaling,center);
std::array<double, dimensions> stlMin, stlMax, meshMin, meshMax, delta;
double h(0.), dh;
STL0->getBoundingBox(stlMin, stlMax);
delta = stlMax - stlMin;
meshMin = stlMin - mesh_range * delta;
meshMax = stlMax + mesh_range * delta;
for (int i = 0; i < dimensions; ++i) {
h = std::max(h, meshMax[i] - meshMin[i]);
}
dh = h / nb_subdivision;
#if BITPIT_ENABLE_MPI
#else
#endif
mesh.initializeAdjacencies();
mesh.initializeInterfaces();
mesh.update();
mesh.getVTK().setName("RBF_" + filename);
#if BITPIT_ENABLE_MPI
mesh.setVTKWriteTarget(PatchKernel::WriteTarget::WRITE_TARGET_CELLS_INTERNAL);
#endif
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("compute_levelset");
time_start = MPI_Wtime();
int id0 = levelset.
addObject(std::move(STL0), 0);
mesh.write();
std::vector<bitpit::adaption::Info> adaptionData_levelset;
for (int r = 0; r < nb_adaptions; ++r) {
for (auto &cell: mesh.getCells()) {
long cellId = cell.getId();
if (object0.
evalCellValue(cellId,
false) < mesh.evalCellSize(cellId))
mesh.markCellForRefinement(cellId);
}
adaptionData_levelset = mesh.update(true);
levelset.
update(adaptionData_levelset);
mesh.write();
}
unsigned long nP_total = mesh.getCellCount();
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("add_nodes_to_RBF");
time_start = MPI_Wtime();
switch (base_function) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
case 8:
break;
case 9:
break;
case 10:
break;
case 11:
break;
case 12:
break;
case 13:
break;
case 14:
break;
default:
break;
}
std::vector<double> values;
std::vector<double> weights;
std::vector<double> radii;
std::vector<std::array<double, dimensions>> nodes;
values.resize(nP_total);
weights.resize(nP_total);
nodes.resize(nP_total);
radii.resize(nP_total);
for (size_t it_RBF = 0; it_RBF < nP_total; it_RBF++) {
nodes[it_RBF] = mesh.evalCellCentroid(it_RBF);
radii[it_RBF] = mesh.evalCellSize(it_RBF) * radius_ratio;
}
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("fill_matrix");
time_start = MPI_Wtime();
int nNZ = nP_total*(1+(2*(int)ceil(radius_ratio)^dimensions));
#if BITPIT_ENABLE_MPI==1
SparseMatrix A(MPI_COMM_WORLD,
true, nP_total, nP_total, nNZ);
#else
#endif
std::vector<long> rowPattern;
std::vector<double> rowValues;
for (unsigned long i = 0; i < nP_total; i++) {
for (unsigned long j = 0; j < nP_total; j++) {
rowPattern.push_back(j);
rowValues.push_back(v_ij);
}
}
A.addRow(rowPattern, rowValues);
rowPattern.clear();
rowValues.clear();
}
A.assembly();
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("fill_RHS");
time_start = MPI_Wtime();
for (unsigned long i = 0; i < nP_total; ++i) {
b[i] = values[i];
}
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("solve_system");
time_start = MPI_Wtime();
for (unsigned long i = 0; i < nP_total; ++i) {
initialSolution[i] = values[i];
}
timers_values.push_back(MPI_Wtime() - time_start);
timers_name.push_back("add_weights_to_RBFObject");
time_start = MPI_Wtime();
for (unsigned long i = 0; i < nP_total; i++) {
weights[i] = x[i];
}
std::size_t nMaxCellVertices = mesh.getCell(0).getVertexIds().size();
timers_values.push_back(MPI_Wtime()-time_start);
timers_name.push_back("output_RBF_and_analytical");
time_start = MPI_Wtime();
std::vector<double> display_values;
display_values.resize(nP_total);
ReferenceElementInfo::MAX_ELEM_VERTICES)
const PatchKernel::CellConstRange &cellWriteRange = mesh.getVTKCellWriteRange();
for (
const Cell &cell:cellWriteRange){
const unsigned long global_id = cell.getId();
mesh.getCellVertexCoordinates(global_id, vertexCoordinates);
std::array<double, dimensions> point = cell.evalCentroid(vertexCoordinates);
std::vector<double> temp_disp = RBFObject.
evalRBF(point);
display_values[global_id] = temp_disp[0];
}
mesh.getVTK().addData<double>("RBF", VTKFieldType::SCALAR, VTKLocation::CELL, display_values);
mesh.write();
timers_values.push_back(MPI_Wtime()-time_start);
timers_name.push_back("output_RBF_to_file");
time_start = MPI_Wtime();
ofstream fw("RBF_" + filename + ".output", std::ofstream::ate);
if (fw.is_open()) {
fw << "support_radius basis_function node_x node_y ";
if (dimensions == 3)
{
fw << "node_z ";
}
fw << "weight \n";
for (unsigned long line = 0; line < nP_total; line++) {
int PRECISION = 20;
std::ostringstream streamObj_support_radius;
std::ostringstream streamObj_x;
std::ostringstream streamObj_y;
std::ostringstream streamObj_z;
std::ostringstream streamObj_weight;
streamObj_support_radius << std::fixed;
streamObj_x << std::fixed;
streamObj_y << std::fixed;
streamObj_z << std::fixed;
streamObj_weight << std::fixed;
streamObj_support_radius << std::setprecision(PRECISION);
streamObj_x << std::setprecision(PRECISION);
streamObj_y << std::setprecision(PRECISION);
streamObj_z << std::setprecision(PRECISION);
streamObj_weight << std::setprecision(PRECISION);
streamObj_support_radius << radii[line];
streamObj_x << nodes[line][0];
streamObj_y << nodes[line][1];
streamObj_z << nodes[line][2];
streamObj_weight << weights[line];
std::string strObj_support_radius = streamObj_support_radius.str();
std::string strObj_x = streamObj_x.str();
std::string strObj_y = streamObj_y.str();
std::string strObj_z = streamObj_z.str();
std::string strObj_weight = streamObj_weight.str();
fw << strObj_support_radius << " " << base_function << " "<<
strObj_x << " " << strObj_y << " ";
if (dimensions == 3)
{
fw << strObj_z << " ";
}
fw << strObj_weight << " ";
if (line < nP_total -1)
fw << "\n";
}
fw.close();
timers_values.push_back(MPI_Wtime()-time_start);
int nb_timers = timers_name.size();
for (int t = 0; t < nb_timers; t++)
{
}
}
int main(int argc, char *argv[])
{
int nProcs = 1;
int rank = 0;
#if BITPIT_ENABLE_MPI==1
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (nProcs>1)
{
exit(1);
}
#endif
std::vector<std::string> argList;
for(int i=0;i<argc;i++)
argList.emplace_back(argv[i]);
std::string data_path = "../test/integration_tests/levelset/data/";
std::string filename = "cube";
std::string parameter_file = "RBF_example_00001.param";
if (argc > 3)
{
data_path = argList[1];
filename = argList[2];
parameter_file = argList[3];
}
log::manager().initialize(log::MODE_COMBINE,
true, nProcs, rank);
try {
run(filename,
data_path,
parameter_file);
}
catch (const std::exception &exception) {
exit(1);
}
#if BITPIT_ENABLE_MPI==1
MPI_Finalize();
#endif
return 0;
}
The Cell class defines the cells.
Interface class for all objects with respect to whom the levelset function may be computed.
void setCellBulkEvaluationMode(LevelSetBulkEvaluationMode evaluationMode)
virtual double evalCellValue(long id, bool signedLevelSet) const
void enableVTKOutput(const LevelSetFieldset &fieldset, bool enable=true)
LevelSetObject & getObject(int) const
void setNarrowBandSize(double size=0)
void setMesh(VolumeKernel *mesh)
void update(const std::vector< adaption::Info > &adaptionData)
int addObject(LevelSetBooleanOperation, int, int, int id=levelSetDefaults::OBJECT)
void setMode(RBFMode mode)
void setSupportRadius(double)
void setFunction(RBFBasisFunction)
std::vector< double > evalRBF(const std::array< double, 3 > &)
double evalBasisPair(int i, int j)
Class to handle Radial Basis Function with a large set of 3D points as nodes.
int addNode(const std::array< double, 3 > &)
The SurfUnstructured class defines an unstructured surface triangulation.
The SystemSolver class provides methods for building and solving large linear systems.
double * getSolutionRawPtr()
void restoreSolutionRawPtr(double *raw_solution)
const double * getSolutionRawReadPtr() const
void restoreRHSRawPtr(double *raw_rhs)
void assembly(const SparseMatrix &matrix)
The VolOctree defines a Octree patch.
std::array< T, d > abs(const std::array< T, d > &x)
RBFBasisFunction
Enum class defining types of RBF kernel functions that could be used in bitpit::RBF class.
#define BITPIT_CREATE_WORKSPACE(workspace, item_type, size, stack_size)
@ SIGN_PROPAGATION
Sign is propagated from the narrow band, no other data will be evaluated.
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
LoggerManipulator< log::Level > fileVerbosity(const log::Level &threshold)
Logger & disableConsole(Logger &logger, const log::Level &level)
LoggerManager & manager()