PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
PeriDEMModel Class Reference

#include <periDEMModel.h>

Inheritance diagram for PeriDEMModel:
Collaboration diagram for PeriDEMModel:

Public Member Functions

 PeriDEMModel (std::shared_ptr< inp::Input > &deck, std::string modelName="PeriDEMModel")
 
void log (std::ostringstream &oss, int priority=0, bool check_condition=true, int override_priority=-1, bool screen_out=false)
 
void log (const std::string &str, int priority=0, bool check_condition=true, int override_priority=-1, bool screen_out=false)
 
void run (std::shared_ptr< inp::Input > &deck)
 
void restart (std::shared_ptr< inp::Input > &deck)
 
void init ()
 
void close ()
 
void integrate ()
 
void integrateStep ()
 
void computeForces ()
 
void computeExternalForces ()
 
void applyDisplacementBC ()
 
void applyInitialCondition ()
 
void output ()
 
std::string ppTwoParticleTest ()
 
std::string ppCompressiveTest ()
 
void checkStop ()
 
void setContact (std::unique_ptr< contact::Contact > c)
 
void setPostprocess (std::unique_ptr< postprocess::Postprocess > p)
 
- Public Member Functions inherited from data::ModelData
 ModelData (std::shared_ptr< inp::Input > &deck)
 Constructor.
 
const particle::BaseParticlegetParticleFromAllList (size_t i) const
 Get pointer to base particle.
 
particle::BaseParticle *& getParticleFromAllList (size_t i)
 Get pointer to base particle.
 
const particle::BaseParticlegetParticleFromParticleList (size_t i) const
 Get pointer to particle (excluding wall)
 
particle::BaseParticle *& getParticleFromParticleList (size_t i)
 
const particle::BaseParticlegetParticleFromWallList (size_t i) const
 Get pointer to wall.
 
particle::BaseParticle *& getParticleFromWallList (size_t i)
 
double getDensity (size_t i)
 Get density of particle.
 
double getHorizon (size_t i)
 Get horizon of particle.
 
size_t & getPtId (size_t i)
 Get particle id given the location in particle list.
 
const size_t & getPtId (size_t i) const
 Get particle id given the location in particle list.
 
void setPtId (size_t i, const size_t &id)
 Set particle id given the location in particle list.
 
double getKeyData (std::string key, bool issue_err=false)
 Get data for a key.
 
void appendKeyData (std::string key, double data, bool issue_err=false)
 Append value to data associated with key.
 
void setKeyData (std::string key, double data, bool issue_err=false)
 Set value to data associated with key.
 
int dimension () const
 
double timeStep () const
 
double currentDt () const
 
void setCurrentDt (double dt)
 
void advanceTime ()
 
size_t numPdForceNodes () const
 
size_t pdForceNode (size_t k) const
 
bool isDofFree (size_t i, unsigned int dof) const
 
double getVMag (size_t i) const
 
void setVMag (size_t i, double mag)
 
size_t currentStep () const
 
size_t numTimeSteps () const
 
const std::string & timeDiscretization () const
 
bool performOutput () const
 
bool shouldOutput () const
 
util::PointgetXRef (size_t i)
 Get reference coordinate of the node.
 
const util::PointgetXRef (size_t i) const
 Get reference coordinate of the node.
 
void setXRef (size_t i, const util::Point &x)
 Set reference coordinate of the node.
 
void addXRef (size_t i, const util::Point &x)
 Add reference coordinate of the node.
 
void setXRef (size_t i, int dof, double x)
 Set specific reference coordinate of the node.
 
void addXRef (size_t i, int dof, double x)
 Add specific reference coordinate of the node.
 
util::PointgetX (size_t i)
 Get current coordinate of the node.
 
const util::PointgetX (size_t i) const
 Get current coordinate of the node.
 
void setX (size_t i, const util::Point &x)
 Set current coordinate of the node.
 
void addX (size_t i, const util::Point &x)
 Add current coordinate of the node.
 
void setX (size_t i, int dof, double x)
 Set specific current coordinate of the node.
 
void addX (size_t i, int dof, double x)
 Add to specific current coordinate of the node.
 
util::PointgetU (size_t i)
 Get displacement of the node.
 
const util::PointgetU (size_t i) const
 Get displacement of the node.
 
void setU (size_t i, const util::Point &u)
 Set displacement of the node.
 
void addU (size_t i, const util::Point &u)
 Add to displacement of the node.
 
void setU (size_t i, int dof, double u)
 Set displacement of the node.
 
void addU (size_t i, int dof, double u)
 Add to displacement of the node.
 
util::PointgetV (size_t i)
 Get velocity of the node.
 
const util::PointgetV (size_t i) const
 Get velocity of the node.
 
void setV (size_t i, const util::Point &v)
 Set velocity of the node.
 
void addV (size_t i, const util::Point &v)
 Add to velocity of the node.
 
void setV (size_t i, int dof, double v)
 Set velocity of the node.
 
void addV (size_t i, int dof, double v)
 Add to velocity of the node.
 
util::PointgetF (size_t i)
 Get force of the node.
 
const util::PointgetF (size_t i) const
 Get force of the node.
 
void setF (size_t i, const util::Point &f)
 Set force of the node.
 
void addF (size_t i, const util::Point &f)
 Add to force of the node.
 
void setF (size_t i, int dof, double f)
 Set force of the node.
 
void addF (size_t i, int dof, double f)
 Add to force of the node.
 
double & getVol (size_t i)
 Get volume of the node.
 
const double & getVol (size_t i) const
 Get volume of the node.
 
void setVol (size_t i, const double &vol)
 Set volume of the node.
 
void addVol (size_t i, const double &vol)
 Add to volume of the node.
 
uint8_t & getFix (size_t i)
 Get fixity of the node.
 
const uint8_t & getFix (size_t i) const
 Get fixity of the node.
 
void setFix (size_t i, const unsigned int &dof, const bool &flag)
 Set fixity of the node.
 
double & getMx (size_t i)
 Get weighted-volume (mx) of the node.
 
const double & getMx (size_t i) const
 Get weighted-volume (mx) of the node.
 
void setMx (size_t i, const double &mx)
 Set weighted-volume (mx) of the node.
 
void addMx (size_t i, const double &mx)
 Add to weighted-volume (mx) of the node.
 
double & getThetax (size_t i)
 Get volumetric deformation (thetax) of the node.
 
const double & getThetax (size_t i) const
 Get volumetric deformation (thetax) of the node.
 
void setThetax (size_t i, const double &thetax)
 Set volumetric deformation (thetax) of the node.
 
void addThetax (size_t i, const double &thetax)
 Add to volumetric deformation (thetax) of the node.
 

Data Fields

std::unique_ptr< contact::Contactd_contact_p
 
std::unique_ptr< postprocess::Postprocessd_postprocess_p
 
- Data Fields inherited from data::ModelData
size_t d_n
 Current time step.
 
double d_time
 Current time.
 
double d_currentDt
 Current timestep.
 
size_t d_infoN
 Print log step interval.
 
std::string d_name
 Model name for log prefixes.
 
std::vector< std::pair< double, std::string > > d_pvdParticleEntries
 (simulation time, VTU filename) for output.pvd
 
std::vector< std::pair< double, std::string > > d_pvdStrainEntries
 (simulation time, VTU filename) for output_strain.pvd
 
std::map< std::string, double > d_dbgData
 Debug data.
 
std::ofstream d_ppFile
 File stream to output information.
 
std::shared_ptr< inp::Inputd_input_p
 Pointer to Input object.
 
std::shared_ptr< inp::ModelDeckd_modelDeck_p
 Pointer to deck holding problem related data.
 
std::shared_ptr< inp::OutputDeckd_outputDeck_p
 Pointer to deck holding output related data.
 
std::shared_ptr< inp::RestartDeckd_restartDeck_p
 Pointer to deck holding restart related data.
 
std::shared_ptr< inp::TestDeckd_testDeck_p
 Test deck.
 
std::shared_ptr< inp::BCDeckd_bcDeck_p
 Boundary condition deck.
 
std::shared_ptr< inp::ParticleDeckd_particleDeck_p
 Pointer to deck holding particle related data.
 
bool d_stop
 flag to stop the simulation midway
 
double d_hMax
 Minimum mesh over all particles and walls.
 
double d_hMin
 Maximum mesh over all particles and walls.
 
double d_maxContactR
 Maximum contact radius between over pairs of particles and walls.
 
size_t d_contNeighUpdateInterval
 Neighborlist update interval.
 
size_t d_contNeighTimestepCounter
 Contact neighborlist time step counter.
 
double d_contNeighSearchRadius
 Neighborlist contact search radius (multiple of d_maxContactR). This variable will be updated during simulation based on maximum velocity.
 
std::vector< char > d_mpiIncludeInContactCloud
 Per entry in d_particlesListTypeAll: include nodes in the MPI contact search cloud (owned grains, walls, and distance-limited ghosts). Empty / all-true when not using multi-rank particle parallel.
 
std::vector< std::vector< int > > d_mpiGhostNeedFrom
 Cached ghost grain ids requested from each MPI rank (skin rebuild).
 
std::vector< std::vector< int > > d_mpiGhostServeTo
 Cached grain ids this rank must send to each MPI rank.
 
bool d_mpiGhostPlanValid
 True once a ghost communication plan has been built.
 
size_t d_mpiGhostStepsSinceRebuild
 Force steps since last ghost-plan rebuild.
 
bool d_pdDofMpi
 Nodal DOF-MPI active.
 
bool d_pdGrainAligned
 DOF owners match whole-grain brick (same as particle-MPI). When true, every node of a grain lives on one rank — contact ghosts are the particle ghost plan, not a full nodal Allreduce. When false, Metis may split a grain across ranks — need syncAllOwned (or a PD halo large enough for contact) before contact reads remote u/v.
 
std::vector< size_t > d_pdNodePartition
 Owner rank for each node when d_pdDofMpi is true.
 
std::vector< std::vector< int > > d_pdGhostNeedFrom
 Ghost node ids requested from each rank (PD DOF halo).
 
std::vector< std::vector< int > > d_pdGhostServeTo
 Local node ids this rank must send to each rank.
 
std::vector< std::shared_ptr< particle::RefParticle > > d_referenceParticles
 Pointer to reference particle.
 
std::vector< particle::BaseParticle * > d_particlesListTypeAll
 List of particles + walls.
 
std::vector< particle::BaseParticle * > d_particlesListTypeParticle
 List of particles.
 
std::vector< particle::BaseParticle * > d_particlesListTypeWall
 List of walls.
 
std::vector< inp::MatDatad_particlesMatDataList
 List of particle material data. Only populated if needed for calculation of stress or other quantities.
 
std::vector< double > d_maxVelocityParticlesListTypeAll
 Maximum velocity among all nodes in the particle for each particle.
 
double d_maxVelocity
 Maximum velocity among all nodes.
 
std::vector< std::vector< size_t > > d_zInfo
 Zone information of particles. For zone 0, d_zInfo[0] = [n1, n2] where n1 is the index at which the particle in this zone starts in d_particlesListTypeAll and n2 is the index + 1, where index is at which the particle in this zone ends.
 
std::unique_ptr< loading::ParticleULoadingd_uLoading_p
 Pointer to displacement Loading object.
 
std::unique_ptr< loading::ParticleFLoadingd_fLoading_p
 Pointer to force Loading object.
 
std::unique_ptr< geometry::Fractured_fracture_p
 Fracture state of bonds.
 
std::unique_ptr< NSearchd_nsearch_p
 Pointer to nsearch.
 
std::vector< util::Pointd_xRef
 reference positions of the nodes
 
std::vector< util::Pointd_x
 Current positions of the nodes.
 
std::vector< util::Pointd_u
 Displacement of the nodes.
 
std::vector< util::Pointd_v
 Velocity of the nodes.
 
std::vector< double > d_vMag
 Magnitude of velocity of the nodes.
 
std::vector< util::Pointd_f
 Total force on the nodes.
 
std::vector< double > d_vol
 Nodal volumes.
 
std::vector< size_t > d_ptId
 Global node to particle id (walls are assigned id after last particle id)
 
std::vector< std::vector< size_t > > d_neighC
 Neighbor data for contact forces.
 
std::vector< std::vector< size_t > > d_neighPd
 Neighbor data for peridynamic forces.
 
std::vector< std::vector< float > > d_neighPdSqdDist
 Square distance neighbor data for peridynamic forces.
 
std::vector< std::vector< std::vector< size_t > > > d_neighWallNodes
 Neighbor data for contact between particle and walls.
 
std::vector< std::vector< std::vector< double > > > d_neighWallNodesDistance
 Neighbor data (distance) for contact between particle and walls.
 
std::vector< std::vector< size_t > > d_neighWallNodesCondensed
 Neighbor data for contact between particle and walls condensed into single vector for each particle.
 
std::vector< uint8_t > d_fix
 Vector of fixity mask of each node.
 
std::vector< uint8_t > d_forceFixity
 Vector of fixity mask of each node for force.
 
std::vector< double > d_thetaX
 Dilation.
 
std::vector< double > d_mX
 Weighted volume.
 
std::vector< size_t > d_fPdCompNodes
 List of global nodes on which force (peridynamic/internal) is to be computed.
 
std::vector< size_t > d_fContCompNodes
 List of global nodes on which force (contact) is to be computed.
 
std::vector< float > d_Z
 Damage at nodes.
 
std::vector< float > d_e
 Energy of the nodes.
 
std::vector< float > d_w
 Work done on each of the nodes.
 
std::vector< float > d_phi
 Damage function \( \phi \) at the nodes (volume-weighted, Silling 2000)
 
std::vector< float > d_phiBond
 Damage as broken-bond count fraction (Bhattacharya & Lipton 2023)
 
std::vector< float > d_eF
 Fracture energy of the nodes.
 
std::vector< float > d_eFB
 Bond-based fracture energy of the nodes.
 
std::vector< util::Pointd_xQuadCur
 Current position of quadrature points.
 
std::vector< util::SymMatrix3d_strain
 Strain in elements (values at quadrature points)
 
std::vector< util::SymMatrix3d_stress
 Stress in elements (values at quadrature points)
 
float d_te
 Total internal energy.
 
float d_tw
 Total work done.
 
float d_tk
 Total kinetic energy.
 
float d_teF
 Total fracture energy.
 
float d_teFB
 Total bond-based fracture energy.
 

Detailed Description

Default driver. Hands the run to time_int::Integrator at integrate(). Physics lives here: forces, BCs, output, particles.

Definition at line 32 of file periDEMModel.h.

Constructor & Destructor Documentation

◆ PeriDEMModel()

PeriDEMModel::PeriDEMModel ( std::shared_ptr< inp::Input > &  deck,
std::string  modelName = "PeriDEMModel" 
)
explicit

Definition at line 58 of file periDEMModel.cpp.

59 : data::ModelData(deck) {
60
61 d_name = std::move(modelName);
62
63 // Ensure output directory exists (Path from input; relative to cwd).
64 {
65 namespace fs = std::filesystem;
66 fs::path out(d_outputDeck_p->d_path);
67 if (!out.empty())
68 fs::create_directories(out);
69 }
70
71 // initialize logger
73 d_outputDeck_p->d_path + "log.txt");
74 if (!d_postprocess_p)
75 d_postprocess_p = std::make_unique<postprocess::Postprocess>();
76}
std::unique_ptr< postprocess::Postprocess > d_postprocess_p
A class to store model data.
Definition modelData.h:50
std::string d_name
Model name for log prefixes.
Definition modelData.h:604
std::shared_ptr< inp::OutputDeck > d_outputDeck_p
Pointer to deck holding output related data.
Definition modelData.h:625
void initLogger(int debug_level=logger_default_debug_lvl, std::string filename="")
Initializes the logger.
Definition io.cpp:18

References data::ModelData::d_name, data::ModelData::d_outputDeck_p, d_postprocess_p, and util::io::initLogger().

Here is the call graph for this function:

Member Function Documentation

◆ applyDisplacementBC()

void PeriDEMModel::applyDisplacementBC ( )

Definition at line 516 of file periDEMModel.cpp.

516 {
517 log(" Computing external displacement bc \n", 3);
518 for (auto &p : d_particlesListTypeAll)
519 d_uLoading_p->apply(d_time, p); // applied in parallel
520}
void log(std::ostringstream &oss, int priority=0, bool check_condition=true, int override_priority=-1, bool screen_out=false)
std::unique_ptr< loading::ParticleULoading > d_uLoading_p
Pointer to displacement Loading object.
Definition modelData.h:730
double d_time
Current time.
Definition modelData.h:595
std::vector< particle::BaseParticle * > d_particlesListTypeAll
List of particles + walls.
Definition modelData.h:704

References data::ModelData::d_particlesListTypeAll, data::ModelData::d_time, data::ModelData::d_uLoading_p, and log().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ applyInitialCondition()

void PeriDEMModel::applyInitialCondition ( )

Definition at line 522 of file periDEMModel.cpp.

522 {
523 log("Applying initial condition \n", 3);
524 for (auto &p : d_particlesListTypeAll)
525 loading::applyIC(p, d_bcDeck_p->d_icDeck); // applied in parallel
526}
std::shared_ptr< inp::BCDeck > d_bcDeck_p
Boundary condition deck.
Definition modelData.h:634
Collection of methods and database related to loading.
void applyIC(particle::BaseParticle *particle, const std::vector< inp::BCBaseDeck > &icVec)
Applies displacement initial condition.

References loading::applyIC(), data::ModelData::d_bcDeck_p, data::ModelData::d_particlesListTypeAll, and log().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ checkStop()

void PeriDEMModel::checkStop ( )

Definition at line 541 of file periDEMModel.cpp.

541 {
542 if (d_testDeck_p->d_testName == "two_particle")
543 log(ppTwoParticleTest(), 2, d_n % d_infoN == 0, 3);
544 else if (d_testDeck_p->d_testName == "compressive_test")
545 log(ppCompressiveTest(), 2, d_n % d_infoN == 0, 3);
546 if (d_postprocess_p)
547 d_postprocess_p->checkStop(*this);
548}
std::string ppTwoParticleTest()
std::string ppCompressiveTest()
std::shared_ptr< inp::TestDeck > d_testDeck_p
Test deck.
Definition modelData.h:631
size_t d_infoN
Print log step interval.
Definition modelData.h:601
size_t d_n
Current time step.
Definition modelData.h:592

References data::ModelData::d_infoN, data::ModelData::d_n, d_postprocess_p, data::ModelData::d_testDeck_p, log(), ppCompressiveTest(), and ppTwoParticleTest().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ close()

void PeriDEMModel::close ( )

Definition at line 124 of file periDEMModel.cpp.

124 {
125 if (d_postprocess_p)
126 d_postprocess_p->close(*this);
127}

References d_postprocess_p.

Referenced by main(), run(), and anonymous_namespace{main.cpp}::runLaw().

Here is the caller graph for this function:

◆ computeExternalForces()

void PeriDEMModel::computeExternalForces ( )

Definition at line 480 of file periDEMModel.cpp.

480 {
481 log(" Computing external force \n", 3);
482
483 auto gravity = d_bcDeck_p->d_gravity;
484
485 if (gravity.length() > 1.0E-8) {
486 tf::Executor executor(util::parallel::getNThreads());
487 tf::Taskflow taskflow;
488
489 // Only owned force nodes (walls on rank 0 for particle-MPI; Metis owners
490 // for DOF-MPI). Applying gravity on every rank then Allreducing reaction
491 // would multiply wall weight by mpiSize.
492 const auto &nodes = d_fContCompNodes;
493 taskflow.for_each_index((std::size_t) 0, nodes.size(), (std::size_t)1,
494 [this, gravity, &nodes](std::size_t II) {
495 const size_t i = nodes[II];
496 this->d_f[i] += this->getDensity(i) * gravity;
497 });
498
499 executor.run(taskflow).get();
500 }
501
502 for (auto &p : d_particlesListTypeAll) {
503 if (p->isWall()) {
504 if (util::parallel::mpiRank() == 0)
505 d_fLoading_p->apply(d_time, p);
506 } else if (d_pdDofMpi) {
507 // Nodal ownership: apply on every rank; loading loops all nodes of p,
508 // but only owned force nodes are integrated.
509 d_fLoading_p->apply(d_time, p);
510 } else if (particle::isLocallyOwned(*p)) {
511 d_fLoading_p->apply(d_time, p);
512 }
513 }
514}
std::vector< size_t > d_fContCompNodes
List of global nodes on which force (contact) is to be computed.
Definition modelData.h:815
bool d_pdDofMpi
Nodal DOF-MPI active.
Definition modelData.h:680
std::unique_ptr< loading::ParticleFLoading > d_fLoading_p
Pointer to force Loading object.
Definition modelData.h:733
bool isLocallyOwned(const BaseParticle &p)
True if this rank updates / assembles forces for the particle. Walls are replicated on every rank....
unsigned int getNThreads()
Get number of threads to be used by taskflow.
int mpiRank()
get rank (id) of this processor

References data::ModelData::d_bcDeck_p, data::ModelData::d_fContCompNodes, data::ModelData::d_fLoading_p, data::ModelData::d_particlesListTypeAll, data::ModelData::d_pdDofMpi, data::ModelData::d_time, util::parallel::getNThreads(), particle::isLocallyOwned(), log(), and util::parallel::mpiRank().

Referenced by computeForces().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ computeForces()

void PeriDEMModel::computeForces ( )

Definition at line 326 of file periDEMModel.cpp.

326 {
327
328 bool dbg_condition = d_n % d_infoN == 0;
329
330 log(" Compute forces \n", 2, dbg_condition, 3);
331
332 // Refresh ghost grain kinematics from owners before contact / damping.
333 {
334 const auto t_ex0 = steady_clock::now();
336 appendKeyData("mpi_exchange_wall_time",
337 util::methods::timeDiff(t_ex0, steady_clock::now()));
338 }
339
340 // Nodal DOF halo for PD neighbor reads (Single_Particle MPI).
342
343 // reset force
344 auto t1 = steady_clock::now();
345 float force_reset_time = 0;
346 {
347 tf::Executor executor(util::parallel::getNThreads());
348 tf::Taskflow taskflow;
349
350 taskflow.for_each_index(
351 (std::size_t) 0, d_x.size(), (std::size_t) 1,
352 [this](std::size_t i) { this->d_f[i] = util::Point(); }
353 ); // for_each
354
355 executor.run(taskflow).get();
356 force_reset_time = util::methods::timeDiff(t1, steady_clock::now());
357 }
358
359 // compute peridynamic forces
360 t1 = steady_clock::now();
361 pd::computeForces(*this);
362 auto pd_time = util::methods::timeDiff(t1, steady_clock::now());
363 appendKeyData("pd_compute_time", pd_time);
364 appendKeyData("avg_peridynamics_force_time", pd_time/d_infoN);
365
366 float current_contact_neigh_update_time = 0;
367 float contact_time = 0;
368 if (d_input_p->isMultiParticle() && d_contact_p) {
369 // update contact neighborlist
370 t1 = steady_clock::now();
371 d_contact_p->updateNeighborlist(*this);
372 current_contact_neigh_update_time = util::methods::timeDiff(t1,
373 steady_clock::now());
374 appendKeyData("contact_neigh_update_time",
375 current_contact_neigh_update_time);
376 appendKeyData("avg_contact_neigh_update_time",
377 current_contact_neigh_update_time / d_infoN);
378
379 // compute contact forces between particles
380 t1 = steady_clock::now();
381 d_contact_p->computeForces(*this);
382 contact_time = util::methods::timeDiff(t1, steady_clock::now());
383 appendKeyData("contact_compute_time", contact_time);
384 appendKeyData("avg_contact_force_time", contact_time / d_infoN);
385 }
386
387 // Compute external forces
388 t1 = steady_clock::now();
390 auto extf_time = util::methods::timeDiff(t1, steady_clock::now());
391 appendKeyData("extf_compute_time", extf_time);
392 appendKeyData("avg_extf_compute_time", extf_time/d_infoN);
393
394 // output avg time info
395 if (dbg_condition) {
396 if (d_input_p->isMultiParticle()) {
397 log(std::format(" Avg time (ms): \n"
398 " {:48s} = {:8d}\n"
399 " {:48s} = {:8d}\n"
400 " {:48s} = {:8d}\n"
401 " {:48s} = {:8d}\n"
402 " {:48s} = {:8d}\n"
403 " {:48s} = {:8d}\n",
404 "tree update", size_t(getKeyData("avg_tree_update_time")),
405 "contact neigh update",
406 size_t(getKeyData("avg_contact_neigh_update_time")),
407 "contact force",
408 size_t(getKeyData("avg_contact_force_time")),
409 "total contact", size_t(getKeyData("avg_tree_update_time")
410 + getKeyData(
411 "avg_contact_neigh_update_time")
412 + getKeyData(
413 "avg_contact_force_time")),
414 "peridynamics force",
415 size_t(getKeyData("avg_peridynamics_force_time")),
416 "external force",
417 size_t(getKeyData("avg_extf_compute_time") / d_infoN)),
418 2, dbg_condition, 3);
419
420 appendKeyData("avg_tree_update_time", 0.);
421 appendKeyData("avg_contact_neigh_update_time", 0.);
422 appendKeyData("avg_contact_force_time", 0.);
423 appendKeyData("avg_peridynamics_force_time", 0.);
424 appendKeyData("avg_extf_compute_time", 0.);
425 }
426 else {
427 log(std::format(" Avg time (ms): \n"
428 " {:48s} = {:8d}\n"
429 " {:48s} = {:8d}\n",
430 "peridynamics force", size_t(getKeyData("avg_peridynamics_force_time")),
431 "external force", size_t(getKeyData("avg_extf_compute_time")/d_infoN)),
432 2, dbg_condition, 3);
433
434 appendKeyData("avg_peridynamics_force_time", 0.);
435 appendKeyData("avg_extf_compute_time", 0.);
436 }
437 }
438
439 log(std::format(" {:50s} = {:8d} \n",
440 "Force reset time (ms)",
441 size_t(force_reset_time)
442 ),
443 2, dbg_condition, 3);
444
445 log(std::format(" {:50s} = {:8d} \n",
446 "External force time (ms)",
447 size_t(extf_time)
448 ),
449 2, dbg_condition, 3);
450
451 log(std::format(" {:50s} = {:8d} \n",
452 "Peridynamics force time (ms)",
453 size_t(pd_time)
454 ),
455 2, dbg_condition, 3);
456
457 if (d_input_p->isMultiParticle()) {
458
459 log(std::format(" {:50s} = {:8d} \n",
460 "Point cloud update time (ms)",
461 size_t(getKeyData("pt_cloud_update_time"))
462 ),
463 2, dbg_condition, 3);
464
465 log(std::format(" {:50s} = {:8d} \n",
466 "Contact neighborlist update time (ms)",
467 size_t(current_contact_neigh_update_time)
468 ),
469 2, dbg_condition, 3);
470
471 log(std::format(" {:50s} = {:8d} \n",
472 "Contact force time (ms)",
473 size_t(contact_time)
474 ),
475 2, dbg_condition, 3);
476 }
477
478}
std::unique_ptr< contact::Contact > d_contact_p
void computeExternalForces()
std::vector< util::Point > d_x
Current positions of the nodes.
Definition modelData.h:745
void appendKeyData(std::string key, double data, bool issue_err=false)
Append value to data associated with key.
Definition modelData.h:215
double getKeyData(std::string key, bool issue_err=false)
Get data for a key.
Definition modelData.h:206
std::shared_ptr< inp::Input > d_input_p
Pointer to Input object.
Definition modelData.h:619
void exchangeGhostKinematics(data::ModelData &data)
Distance-limited ghosts + kinematics exchange. Rebuilds the ghost plan on a Verlet-skin cadence (tied...
void computeForces(data::ModelData &data)
Assemble nodal peridynamic force (constitutive response stays in material).
Definition pdForce.cpp:28
void exchangeGhostDisplacement(data::ModelData &data)
Halo-exchange nodal displacements (and current x) for PD ghosts.
Definition pdMpi.cpp:286
float timeDiff(std::chrono::steady_clock::time_point begin, std::chrono::steady_clock::time_point end, std::string unit="microseconds")
Returns difference between two times.
Definition vecMethods.h:304

References data::ModelData::appendKeyData(), computeExternalForces(), pd::computeForces(), d_contact_p, data::ModelData::d_infoN, data::ModelData::d_input_p, data::ModelData::d_n, data::ModelData::d_x, pd::exchangeGhostDisplacement(), particle::exchangeGhostKinematics(), data::ModelData::getKeyData(), util::parallel::getNThreads(), log(), and util::methods::timeDiff().

Referenced by main(), and anonymous_namespace{main.cpp}::runLaw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init()

void PeriDEMModel::init ( )

Definition at line 129 of file periDEMModel.cpp.

129 {
130
131 // init time step
132 d_n = 0;
133 d_time = 0.;
134 if (d_outputDeck_p->d_dtOut < 1)
135 throw std::runtime_error(
136 "Output_Interval must be >= 1 (use 1 to write every step).");
137 if (d_outputDeck_p->d_dtOutCriteria < 1)
138 d_outputDeck_p->d_dtOutCriteria = d_outputDeck_p->d_dtOut;
139 if (d_outputDeck_p->d_dtOutOld < 1)
140 d_outputDeck_p->d_dtOutOld = d_outputDeck_p->d_dtOut;
141 if (d_outputDeck_p->d_dtTestOut == 0)
142 d_outputDeck_p->d_dtTestOut = std::max<size_t>(1, d_outputDeck_p->d_dtOut / 10);
143 d_infoN = d_outputDeck_p->d_dtOut;
144
145 // debug/information variables
146 {
147 appendKeyData("debug_once", -1);
148 appendKeyData("update_contact_neigh_search_params_init_call_count", 0);
149 appendKeyData("tree_compute_time", 0);
150 appendKeyData("contact_compute_time", 0);
151 appendKeyData("contact_neigh_update_time", 0);
152 appendKeyData("peridynamics_neigh_update_time", 0);
153 appendKeyData("pd_compute_time", 0);
154 appendKeyData("extf_compute_time", 0);
155 appendKeyData("integrate_compute_time", 0);
156 appendKeyData("pt_cloud_update_time", 0);
157 appendKeyData("avg_tree_update_time", 0);
158 appendKeyData("avg_contact_neigh_update_time", 0);
159 appendKeyData("avg_contact_force_time", 0);
160 appendKeyData("avg_peridynamics_force_time", 0);
161 appendKeyData("avg_extf_compute_time", 0);
162 appendKeyData("pen_dist", 0);
163 appendKeyData("max_y", 0);
164 appendKeyData("contact_area_radius", 0);
165 }
166
167
168 auto t1 = steady_clock::now();
169 auto t2 = steady_clock::now();
170 log(d_name + ": Initializing objects.\n");
171
172 // create particles
173 log(d_name + ": Creating particles.\n");
176
177 log(d_name + ": Creating maximum velocity data for particles.\n");
179 = std::vector<double>(d_particlesListTypeAll.size(), 0.);
181
182 // setup contact
183 if (d_input_p->isMultiParticle()) {
184 if (!d_contact_p)
185 d_contact_p = std::make_unique<contact::Contact>();
186 log(d_name + ": Setting up contact.\n");
187 d_contact_p->setup(*this);
188 }
189
190 // setup element-node connectivity data if needed
191 log(d_name + ": Setting up element-node connectivity data for strain/stress.\n");
193
194 // create search object
195 log(d_name + ": Creating neighbor search tree.\n");
196
197 // create tree object
198 d_nsearch_p = std::make_unique<NSearch>(d_x, d_outputDeck_p->d_debug);
199
200 // setup tree
201 double set_tree_time = d_nsearch_p->setInputCloud();
202 log(std::format("{}: Tree setup time (ms) = {}. \n", d_name, set_tree_time));
203
204 // create neighborlists
205 log(d_name + ": Creating neighborlist for peridynamics.\n");
206 t1 = steady_clock::now();
208 t2 = steady_clock::now();
209 appendKeyData("peridynamics_neigh_update_time", util::methods::timeDiff(t1, t2));
210
211 if (d_input_p->isMultiParticle()) {
212 log(d_name + ": Creating neighborlist for contact.\n");
213 d_contNeighUpdateInterval = d_particleDeck_p->d_pNeighDeck.d_neighUpdateInterval;
214 d_contNeighSearchRadius = d_particleDeck_p->d_pNeighDeck.d_sFactor * d_maxContactR;
215 t1 = steady_clock::now();
216 d_contact_p->updateNeighborlist(*this);
217 t2 = steady_clock::now();
218 appendKeyData("contact_neigh_update_time", util::methods::timeDiff(t1, t2));
219 }
220
221 // create peridynamic bonds
222 log(d_name + ": Creating peridynamics bonds.\n");
223 d_fracture_p = std::make_unique<geometry::Fracture>(&d_x, &d_neighPd);
224
225 // compute quantities in state-based simulations
226 log(d_name + ": Compute state-based peridynamic quantities.\n");
227 material::computeStateMx(this, true);
228
229 // initialize loading class
230 log(d_name + ": Initializing displacement loading object.\n");
232 std::make_unique<loading::ParticleULoading>(d_bcDeck_p->d_dispDeck);
233 for (auto &p : d_particlesListTypeAll)
234 d_uLoading_p->setFixity(p);
235
236 log(d_name + ": Initializing force loading object.\n");
238 std::make_unique<loading::ParticleFLoading>(d_bcDeck_p->d_forceDeck);
239
240 // if all dofs of particle is fixed, then mark it so that we do not
241 // compute force
242 // MAYBE NOT as we may be interested in reaction forces
243 // for (auto &p : d_particlesListTypeAll)
244 // p->checkFixityForForce(); // TODO implement
245
246 // if this is a two-particle test, we set the force calculation off in
247 // first particle
248 if (d_testDeck_p->d_testName == "two_particle") {
249 d_particlesListTypeAll[0]->d_computeForce = false;
250 }
251
252 log(std::format("{}: Total particles = {}. \n",
254
255 for (const auto &p : d_particlesListTypeAll)
256 if (!p->d_computeForce)
257 log(std::format("{}: Force OFF in Particle i = {}. \n", d_name, p->getId()));
258
259 // Single-particle DOF-MPI: Metis node owners + PD ghost plan (T10).
261
262 log(d_name + ": Creating list of nodes on which force is to be computed.\n");
263 // TODO for now we simply look at particle/wall and check if we compute
264 // force on any of its node. Later, one can have control on individual
265 // nodes of particle/wall and remove from d_fCompNodes if no force is to
266 // be computed on them
267 const int mpi_rank = util::parallel::mpiRank();
268 for (size_t i = 0; i < d_x.size(); i++) {
269 const auto &ptId = d_ptId[i];
270 const auto &pi = getParticleFromAllList(ptId);
271 bool node_owned = false;
272 if (d_pdDofMpi)
273 node_owned = (static_cast<int>(d_pdNodePartition[i]) == mpi_rank);
274 else if (pi->isWall())
275 // Walls are replicated; assemble wall contact/reaction on rank 0 only.
276 node_owned = (mpi_rank == 0);
277 else
278 node_owned = particle::isLocallyOwned(*pi);
279 if (pi->d_computeForce && node_owned) {
280 d_fContCompNodes.push_back(i);
281 // Walls keep contact (and reaction) but not peridynamic force. Treating a
282 // container as a PD body on a thin/boolean mesh makes Damage_Z explode
283 // and the neighbor search then allocates until the process is OOM-killed.
284 if (!pi->isWall())
285 d_fPdCompNodes.push_back(i);
286 }
287 }
288
289 // initialize remaining fields (if any)
290 d_Z = std::vector<float>(d_x.size(), 0.);
291 // Damage: volume-weighted phi (Silling/Trask) and broken-bond count
292 // fraction (Bhattacharya & Lipton).
293 d_phi = std::vector<float>(d_x.size(), 0.);
294 d_phiBond = std::vector<float>(d_x.size(), 0.);
295
296 t2 = steady_clock::now();
297 log(std::format("{}: Total setup time (ms) = {}. \n",
299
300 // compute complexity information
301 size_t free_dofs = 0;
302 for (const auto &f : d_fix) {
303 for (size_t dof = 0; dof < 3; dof++)
304 if (util::methods::isFree(f, dof))
305 free_dofs++;
306 }
307 log(std::format("{}: Computational complexity information \n"
308 " Total number of particles = {}, number of "
309 "particles = {}, number of walls = {}, \n"
310 " number of dofs = {}, number of free dofs = {}. \n",
314 3 * d_x.size(),
315 free_dofs));
316}
std::vector< float > d_Z
Damage at nodes.
Definition modelData.h:818
std::vector< double > d_maxVelocityParticlesListTypeAll
Maximum velocity among all nodes in the particle for each particle.
Definition modelData.h:719
std::vector< uint8_t > d_fix
Vector of fixity mask of each node.
Definition modelData.h:792
std::vector< particle::BaseParticle * > d_particlesListTypeParticle
List of particles.
Definition modelData.h:707
std::vector< size_t > d_pdNodePartition
Owner rank for each node when d_pdDofMpi is true.
Definition modelData.h:692
std::unique_ptr< geometry::Fracture > d_fracture_p
Fracture state of bonds.
Definition modelData.h:736
std::vector< size_t > d_ptId
Global node to particle id (walls are assigned id after last particle id)
Definition modelData.h:764
std::vector< float > d_phi
Damage function at the nodes (volume-weighted, Silling 2000)
Definition modelData.h:834
std::shared_ptr< inp::ParticleDeck > d_particleDeck_p
Pointer to deck holding particle related data.
Definition modelData.h:637
std::vector< particle::BaseParticle * > d_particlesListTypeWall
List of walls.
Definition modelData.h:710
std::unique_ptr< NSearch > d_nsearch_p
Pointer to nsearch.
Definition modelData.h:739
std::vector< std::vector< size_t > > d_neighPd
Neighbor data for peridynamic forces.
Definition modelData.h:770
double d_maxContactR
Maximum contact radius between over pairs of particles and walls.
Definition modelData.h:649
double d_contNeighSearchRadius
Neighborlist contact search radius (multiple of d_maxContactR). This variable will be updated during ...
Definition modelData.h:658
std::vector< size_t > d_fPdCompNodes
List of global nodes on which force (peridynamic/internal) is to be computed.
Definition modelData.h:812
double d_maxVelocity
Maximum velocity among all nodes.
Definition modelData.h:722
size_t d_contNeighUpdateInterval
Neighborlist update interval.
Definition modelData.h:652
std::vector< float > d_phiBond
Damage as broken-bond count fraction (Bhattacharya & Lipton 2023)
Definition modelData.h:837
const particle::BaseParticle * getParticleFromAllList(size_t i) const
Get pointer to base particle.
Definition modelData.h:86
void setupQuadratureData(ModelData &data)
void computeStateMx(data::ModelData *model, bool compute_in_parallel=false)
Computes the moment term in state-based peridynamic formulation.
void updatePeridynamicNeighborlist(data::ModelData &data)
Horizon search restricted to the same particle.
void createParticles(data::ModelData &data)
Build refs then place particles according to the generation method.
void assignMpiOwners(data::ModelData &data)
Assign grain owners by spatial 2D brick decomposition of centers. Walls get owner -1 (all ranks)....
void setupDofPartition(data::ModelData &data)
Metis-partition nodes on the PD neighbor graph and build ghost plans. Call after d_neighPd is ready a...
Definition pdMpi.cpp:233
T max(const std::vector< T > &data)
Returns the maximum from list of data.
Definition vecMethods.h:74
bool isFree(const int &i, const unsigned int &dof)
Returns true if degree of freedom is free.
Definition vecMethods.h:249

References data::ModelData::appendKeyData(), particle::assignMpiOwners(), material::computeStateMx(), particle::createParticles(), data::ModelData::d_bcDeck_p, d_contact_p, data::ModelData::d_contNeighSearchRadius, data::ModelData::d_contNeighUpdateInterval, data::ModelData::d_fContCompNodes, data::ModelData::d_fix, data::ModelData::d_fLoading_p, data::ModelData::d_fPdCompNodes, data::ModelData::d_fracture_p, data::ModelData::d_infoN, data::ModelData::d_input_p, data::ModelData::d_maxContactR, data::ModelData::d_maxVelocity, data::ModelData::d_maxVelocityParticlesListTypeAll, data::ModelData::d_n, data::ModelData::d_name, data::ModelData::d_neighPd, data::ModelData::d_nsearch_p, data::ModelData::d_outputDeck_p, data::ModelData::d_particleDeck_p, data::ModelData::d_particlesListTypeAll, data::ModelData::d_particlesListTypeParticle, data::ModelData::d_particlesListTypeWall, data::ModelData::d_pdDofMpi, data::ModelData::d_pdNodePartition, data::ModelData::d_phi, data::ModelData::d_phiBond, data::ModelData::d_ptId, data::ModelData::d_testDeck_p, data::ModelData::d_time, data::ModelData::d_uLoading_p, data::ModelData::d_x, data::ModelData::d_Z, data::ModelData::getParticleFromAllList(), util::methods::isFree(), particle::isLocallyOwned(), log(), util::methods::max(), util::parallel::mpiRank(), pd::setupDofPartition(), data::setupQuadratureData(), util::methods::timeDiff(), and nsearch::updatePeridynamicNeighborlist().

Referenced by main(), run(), and anonymous_namespace{main.cpp}::runLaw().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ integrate()

void PeriDEMModel::integrate ( )

Definition at line 318 of file periDEMModel.cpp.

318 {
320}
void integrate(Model &model)
Definition integrator.h:37

References time_int::Integrator::integrate().

Referenced by main(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ integrateStep()

void PeriDEMModel::integrateStep ( )

Definition at line 322 of file periDEMModel.cpp.

322 {
323 time_int::Integrator().step(*this);
324}
void step(Model &model)
Definition integrator.h:90

References time_int::Integrator::step().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ log() [1/2]

void PeriDEMModel::log ( const std::string &  str,
int  priority = 0,
bool  check_condition = true,
int  override_priority = -1,
bool  screen_out = false 
)

Definition at line 83 of file periDEMModel.cpp.

84 {
85 util::io::log(priority, str, check_condition, override_priority, screen_out);
86}
void log(std::ostringstream &oss, bool screen_out=false, int printMpiRank=print_default_mpi_rank)
Global method to log the message.
Definition io.cpp:41

References util::io::log().

Here is the call graph for this function:

◆ log() [2/2]

void PeriDEMModel::log ( std::ostringstream &  oss,
int  priority = 0,
bool  check_condition = true,
int  override_priority = -1,
bool  screen_out = false 
)

Definition at line 78 of file periDEMModel.cpp.

79 {
80 util::io::log(priority, oss, check_condition, override_priority, screen_out);
81}

References util::io::log().

Referenced by applyDisplacementBC(), applyInitialCondition(), checkStop(), computeExternalForces(), computeForces(), init(), output(), and restart().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ output()

void PeriDEMModel::output ( )

Definition at line 528 of file periDEMModel.cpp.

528 {
529 if (currentStep() == 0)
530 log(std::format("{}: Output step = {}, time = {:.6f} \n", d_name, d_n, d_time),
531 2);
532 rw::writeOutput(*this);
533}
size_t currentStep() const
Definition modelData.h:164
void writeOutput(data::ModelData &data)
Write VTU/PVD (and optional strain VTU / particle-location CSV).

References data::ModelData::currentStep(), data::ModelData::d_n, data::ModelData::d_name, data::ModelData::d_time, log(), and rw::writeOutput().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ppCompressiveTest()

std::string PeriDEMModel::ppCompressiveTest ( )

Definition at line 550 of file periDEMModel.cpp.

550 {
551 if (!d_postprocess_p)
552 return "";
553 return d_postprocess_p->compressive(*this);
554}

References d_postprocess_p.

Referenced by checkStop().

Here is the caller graph for this function:

◆ ppTwoParticleTest()

std::string PeriDEMModel::ppTwoParticleTest ( )

Definition at line 535 of file periDEMModel.cpp.

535 {
536 if (!d_postprocess_p)
537 return "";
538 return d_postprocess_p->twoParticle(*this);
539}

References d_postprocess_p.

Referenced by checkStop().

Here is the caller graph for this function:

◆ restart()

void PeriDEMModel::restart ( std::shared_ptr< inp::Input > &  deck)

Definition at line 104 of file periDEMModel.cpp.

104 {
105
106 log(d_name + ": Restarting the simulation\n");
107
108 // set time step to step specified in restart deck
109 d_n = d_restartDeck_p->d_step;
110 d_time = double(d_n) * d_modelDeck_p->d_dt;
111 log(std::format(" Restart step = {}, time = {:.6f} \n", d_n, d_time));
112
113 // get backup of reference configuration
114 std::vector<util::Point> x_ref(d_x.size(), util::Point());
115 for (auto &x : d_x)
116 x_ref.push_back(x);
117
118 // read displacement and velocity from restart file
119 log(" Reading data from restart file = " + d_restartDeck_p->d_file + " \n");
120 auto reader = rw::reader::VtkParticleReader(d_restartDeck_p->d_file);
121 reader.readNodes(this);
122}
std::shared_ptr< inp::ModelDeck > d_modelDeck_p
Pointer to deck holding problem related data.
Definition modelData.h:622
std::shared_ptr< inp::RestartDeck > d_restartDeck_p
Pointer to deck holding restart related data.
Definition modelData.h:628
A vtk writer for simple point data and complex fem mesh data.
A structure to represent 3d vectors.
Definition point.h:30

References data::ModelData::d_modelDeck_p, data::ModelData::d_n, data::ModelData::d_name, data::ModelData::d_restartDeck_p, data::ModelData::d_time, data::ModelData::d_x, and log().

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

void PeriDEMModel::run ( std::shared_ptr< inp::Input > &  deck)

Definition at line 88 of file periDEMModel.cpp.

88 {
89
90 // initialize data
91 init();
92
93 // check for restart
94 if (d_modelDeck_p->d_isRestartActive)
95 restart(deck);
96
97 // integrate in time
98 integrate();
99
100 // close
101 close();
102}
void restart(std::shared_ptr< inp::Input > &deck)

References close(), data::ModelData::d_modelDeck_p, init(), integrate(), and restart().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setContact()

void PeriDEMModel::setContact ( std::unique_ptr< contact::Contact c)
inline

Definition at line 69 of file periDEMModel.h.

69{ d_contact_p = std::move(c); }

References d_contact_p.

◆ setPostprocess()

void PeriDEMModel::setPostprocess ( std::unique_ptr< postprocess::Postprocess p)
inline

Definition at line 71 of file periDEMModel.h.

71 {
72 d_postprocess_p = std::move(p);
73 }

References d_postprocess_p.

Referenced by main().

Here is the caller graph for this function:

Field Documentation

◆ d_contact_p

std::unique_ptr<contact::Contact> PeriDEMModel::d_contact_p

◆ d_postprocess_p

std::unique_ptr<postprocess::Postprocess> PeriDEMModel::d_postprocess_p

The documentation for this class was generated from the following files: