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

Added separated class for the charge density equation solver + file f… #24

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 1 addition & 18 deletions include/ModelingMainDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
class ModelingMainDriver final
{
private:
std::string __expt_m_config_filename;
std::string m_config_filename; ///< Filename of the configuration to parse it.

static constexpr short const kdefault_max_numparticles_to_anim{5'000}; ///< Maximal count of particles to do animation.

Expand Down Expand Up @@ -151,23 +151,6 @@ class ModelingMainDriver final
template <typename Function, typename... Args>
void _processWithThreads(unsigned int num_threads, Function &&function, std::launch launch_plicy, Args &&...args);

/**
* @brief Solves the equation for the system using node charge density and boundary conditions.
*
* This function solves the system of equations based on the provided node charge density map
* and boundary conditions. It updates the solution vector accordingly.
*
* @param nodeChargeDensityMap A reference to a map containing the charge density at each node.
* @param gsmAssembler A shared pointer to the GSM assembler that constructs the system of equations.
* @param solutionVector A shared pointer to the vector manager that holds the solution.
* @param boundaryConditions A reference to a map containing boundary conditions for the system.
* @param time The current simulation time.
*/
void _solveEquation(std::map<GlobalOrdinal, double> &nodeChargeDensityMap,
std::shared_ptr<GSMAssembler> &gsmAssembler,
std::shared_ptr<VectorManager> &solutionVector,
std::map<GlobalOrdinal, double> &boundaryConditions, double time);

/**
* @brief Processes particle-in-cell (PIC) and surface collision tracking within a particle range.
*
Expand Down
44 changes: 44 additions & 0 deletions include/ParticleInCellEngine/ChargeDensityEquationSolver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef CHARGEDNSITYEQUATIONSOLVER_HPP
#define CHARGEDNSITYEQUATIONSOLVER_HPP

#include "FiniteElementMethod/BoundaryConditions/BoundaryConditionsManager.hpp"
#include "FiniteElementMethod/GSMAssembler.hpp"
#include "FiniteElementMethod/LinearAlgebraManagers/VectorManager.hpp"
#include "PICTypes.hpp"
#include "Utilities/ConfigParser.hpp"

/**
* @class ChargeDensityEquationSolver
* @brief A static class providing methods to solve charge density equations.
*
* This class offers static methods to process charge density maps, apply boundary conditions,
* and solve the resulting equations using a configurable matrix equation solver. The solution
* updates a vector manager, reflecting changes in node potentials and fields.
*/
class ChargeDensityEquationSolver {
public:
/**
* @brief Solves the charge density equation system at a given time moment.
*
* This method processes the provided node charge density map and boundary conditions,
* constructs the system of equations using the specified assembler, and solves the system.
* It also handles writing outputs such as electric potentials and fields to files.
*
* @param timeMoment The simulation time for which the system is solved.
* @param configFilename The configuration file specifying solver parameters and FEM settings.
* @param nodeChargeDensityMap A reference to a map containing charge density values per node.
* @param gsmAssembler A shared pointer to the GSM assembler that constructs the system matrix.
* @param solutionVector A shared pointer to the vector manager storing the computed solution.
* @param boundaryConditions A reference to a map defining boundary conditions for specific nodes.
*
* @throws std::runtime_error If a critical error occurs while parsing the configuration or solving equations.
* @throws std::exception For any generic error during processing.
*/
static void solve(double timeMoment, std::string_view configFilename,
NodeChargeDensitiesMap &nodeChargeDensityMap,
std::shared_ptr<GSMAssembler> &gsmAssembler,
std::shared_ptr<VectorManager> &solutionVector,
BoundaryConditionsMap &boundaryConditions);
};

#endif // !CHARGEDNSITYEQUATIONSOLVER_HPP
30 changes: 1 addition & 29 deletions include/ParticleInCellEngine/NodeChargeDensityProcessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,9 @@

#include "FiniteElementMethod/GSMAssembler.hpp"
#include "Geometry/CubicGrid.hpp"
#include "Particle/Particle.hpp"
#include "ParticleInCellEngine/PICTypes.hpp"
#include "Utilities/ConfigParser.hpp"

/**
* @brief Map of charge densities for nodes in a mesh.
* @details This type associates each node ID with its corresponding charge density.
* The structure is as follows:
* - Key: Node ID (GlobalOrdinal)
* - Value: Charge density at the node (double)
*/
using NodeChargeDensitiesMap = std::map<GlobalOrdinal, double>;

/**
* @brief Tracker for particles inside tetrahedrons over time.
* @details This type organizes particles by simulation time and tetrahedron ID.
* The structure is as follows:
* - Key: Simulation time (double)
* - Value: Map of tetrahedron ID to the particles inside it:
* - Key: Tetrahedron ID (size_t)
* - Value: Vector of particles inside the tetrahedron (ParticleVector)
*/
using ParticleTrackerMap = std::map<double, std::map<size_t, ParticleVector>>;

/**
* @brief Set of particle IDs that have settled on a 2D mesh.
* @details This type stores the IDs of particles that are considered settled
* after colliding or interacting with the 2D mesh.
* - Element: Particle ID (size_t)
*/
using ParticlesIDSet = std::set<size_t>;

static std::mutex g_nodeChargeDensityMap_mutex; ///< Mutex for synchronizing access to the charge densities in nodes.
static std::mutex g_particleTrackerMap_mutex; ///< Mutex for synchronizing access to the particles in tetrahedrons.
static std::shared_mutex g_settledParticles_mutex; ///< Mutex for synchronizing access to settled particle IDs.
Expand Down
47 changes: 47 additions & 0 deletions include/ParticleInCellEngine/PICTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef PICTYPES_HPP
#define PICTYPES_HPP

#include <map>
#include <set>

#include "FiniteElementMethod/FEMTypes.hpp"
#include "Particle/Particle.hpp"

/**
* @brief Map of charge densities for nodes in a mesh.
* @details This type associates each node ID with its corresponding charge density.
* The structure is as follows:
* - Key: Node ID (GlobalOrdinal)
* - Value: Charge density at the node (double)
*/
using NodeChargeDensitiesMap = std::map<GlobalOrdinal, double>;

/**
* @brief Tracker for particles inside tetrahedrons over time.
* @details This type organizes particles by simulation time and tetrahedron ID.
* The structure is as follows:
* - Key: Simulation time (double)
* - Value: Map of tetrahedron ID to the particles inside it:
* - Key: Tetrahedron ID (size_t)
* - Value: Vector of particles inside the tetrahedron (ParticleVector)
*/
using ParticleTrackerMap = std::map<double, std::map<size_t, ParticleVector>>;

/**
* @brief Set of particle IDs that have settled on a 2D mesh.
* @details This type stores the IDs of particles that are considered settled
* after colliding or interacting with the 2D mesh.
* - Element: Particle ID (size_t)
*/
using ParticlesIDSet = std::set<size_t>;

/**
* @brief Map of the boundary conditions.
* @details This type associates each node ID with its corresponding boundary condition value.
* The structure is as follows:
* - Key: Node ID (GlobalOrdinal)
* - Value: Value of the boundary conditions (double)
*/
using BoundaryConditionsMap = std::map<GlobalOrdinal, double>;

#endif // !PICTYPES_HPP
50 changes: 9 additions & 41 deletions src/ModelingMainDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ using json = nlohmann::json;
#include "ModelingMainDriver.hpp"
#include "Particle/CUDA/ParticleDeviceMemoryConverter.cuh"
#include "Particle/PhysicsCore/CollisionModel/CollisionModelFactory.hpp"
#include "ParticleInCellEngine/ChargeDensityEquationSolver.hpp"
#include "ParticleInCellEngine/NodeChargeDensityProcessor.hpp"

std::mutex ModelingMainDriver::m_PICTracker_mutex;
Expand Down Expand Up @@ -270,7 +271,7 @@ void ModelingMainDriver::_processWithThreads(unsigned int num_threads, Function
}

ModelingMainDriver::ModelingMainDriver(std::string_view config_filename)
: __expt_m_config_filename(config_filename),
: m_config_filename(config_filename),
m_config(config_filename)
{
// Checking mesh filename on validity and assign it to the class member.
Expand All @@ -289,44 +290,6 @@ ModelingMainDriver::ModelingMainDriver(std::string_view config_filename)

ModelingMainDriver::~ModelingMainDriver() { _gfinalize(); }

void ModelingMainDriver::_solveEquation(std::map<GlobalOrdinal, double> &nodeChargeDensityMap,
std::shared_ptr<GSMAssembler> &gsmAssembler,
std::shared_ptr<VectorManager> &solutionVector,
std::map<GlobalOrdinal, double> &boundaryConditions, double time)
{
try
{
auto nonChangebleNodes{m_config.getNonChangeableNodes()};
for (auto const &[nodeId, nodeChargeDensity] : nodeChargeDensityMap)
#if __cplusplus >= 202002L
if (std::ranges::find(nonChangebleNodes, nodeId) == nonChangebleNodes.cend())
#else
if (std::find(nonChangebleNodes.cbegin(), nonChangebleNodes.cend(), nodeId) == nonChangebleNodes.cend())
#endif
boundaryConditions[nodeId] = nodeChargeDensity;
BoundaryConditionsManager::set(solutionVector->get(), FEM_LIMITS_DEFAULT_POLYNOMIAL_ORDER, boundaryConditions);

MatrixEquationSolver solver(gsmAssembler, solutionVector);
auto solverParams{solver.createSolverParams(m_config.getSolverName(), m_config.getMaxIterations(), m_config.getConvergenceTolerance(),
m_config.getVerbosity(), m_config.getOutputFrequency(), m_config.getNumBlocks(), m_config.getBlockSize(),
m_config.getMaxRestarts(), m_config.getFlexibleGMRES(), m_config.getOrthogonalization(),
m_config.getAdaptiveBlockSize(), m_config.getConvergenceTestFrequency())};
solver.solve(m_config.getSolverName(), solverParams);
solver.calculateElectricField(); // Getting electric field for the each cell.

solver.writeElectricPotentialsToPosFile(time);
solver.writeElectricFieldVectorsToPosFile(time);
}
catch (std::exception const &ex)
{
ERRMSG(util::stringify("Can't solve the equation: ", ex.what()));
}
catch (...)
{
ERRMSG("Some error occured while solving the matrix equation Ax=b");
}
}

void ModelingMainDriver::_processPIC_and_SurfaceCollisionTracker(size_t start_index, size_t end_index, double t,
std::shared_ptr<CubicGrid> cubicGrid, std::shared_ptr<GSMAssembler> gsmAssembler)
{
Expand Down Expand Up @@ -598,7 +561,7 @@ void ModelingMainDriver::startModeling()
#endif

NodeChargeDensityProcessor::gather(t,
__expt_m_config_filename,
m_config_filename,
cubicGrid,
gsmAssembler,
m_particles,
Expand All @@ -607,7 +570,12 @@ void ModelingMainDriver::startModeling()
nodeChargeDensityMap);

// 2. Solve equation in the main thread.
_solveEquation(nodeChargeDensityMap, gsmAssembler, solutionVector, boundaryConditions, t);
ChargeDensityEquationSolver::solve(t,
m_config_filename,
nodeChargeDensityMap,
gsmAssembler,
solutionVector,
boundaryConditions);

// 3. Process surface collision tracking in parallel.
#ifdef USE_OMP
Expand Down
1 change: 1 addition & 0 deletions src/ParticleInCellEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# src/ParticleInCellEngine/CMakeLists.txt

set(PARTICLE_IN_CELL_ENGINE_SOURCES
ChargeDensityEquationSolver.cpp
NodeChargeDensityProcessor.cpp
)

Expand Down
49 changes: 49 additions & 0 deletions src/ParticleInCellEngine/ChargeDensityEquationSolver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "ParticleInCellEngine/ChargeDensityEquationSolver.hpp"
#include "FiniteElementMethod/FEMLimits.hpp"
#include "FiniteElementMethod/MatrixEquationSolver.hpp"

void ChargeDensityEquationSolver::solve(
double timeMoment, std::string_view configFilename,
NodeChargeDensitiesMap &nodeChargeDensityMap,
std::shared_ptr<GSMAssembler> &gsmAssembler,
std::shared_ptr<VectorManager> &solutionVector,
BoundaryConditionsMap &boundaryConditions) {
try {
ConfigParser configParser(configFilename);

auto nonChangebleNodes{configParser.getNonChangeableNodes()};
for (auto const &[nodeId, nodeChargeDensity] : nodeChargeDensityMap)
#if __cplusplus >= 202002L
if (std::ranges::find(nonChangebleNodes, nodeId) ==
nonChangebleNodes.cend())
#else
if (std::find(nonChangebleNodes.cbegin(), nonChangebleNodes.cend(),
nodeId) == nonChangebleNodes.cend())
#endif
boundaryConditions[nodeId] = nodeChargeDensity;
BoundaryConditionsManager::set(solutionVector->get(),
FEM_LIMITS_DEFAULT_POLYNOMIAL_ORDER,
boundaryConditions);

MatrixEquationSolver solver(gsmAssembler, solutionVector);
auto solverParams{solver.createSolverParams(
configParser.getSolverName(), configParser.getMaxIterations(),
configParser.getConvergenceTolerance(), configParser.getVerbosity(),
configParser.getOutputFrequency(), configParser.getNumBlocks(),
configParser.getBlockSize(), configParser.getMaxRestarts(),
configParser.getFlexibleGMRES(),
configParser.getOrthogonalization(),
configParser.getAdaptiveBlockSize(),
configParser.getConvergenceTestFrequency())};
solver.solve(configParser.getSolverName(), solverParams);
solver.calculateElectricField(); // Getting electric field for the
// each cell.

solver.writeElectricPotentialsToPosFile(timeMoment);
solver.writeElectricFieldVectorsToPosFile(timeMoment);
} catch (std::exception const &ex) {
ERRMSG(util::stringify("Can't solve the equation: ", ex.what()));
} catch (...) {
ERRMSG("Some error occured while solving the matrix equation Ax=b");
}
}
Loading