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::BaseParticle * getParticleFromAllList (size_t i) const
 Get pointer to base particle.
 
particle::BaseParticle *& getParticleFromAllList (size_t i)
 Get pointer to base particle.
 
const particle::BaseParticle * getParticleFromParticleList (size_t i) const
 Get pointer to particle (excluding wall)
 
particle::BaseParticle *& getParticleFromParticleList (size_t i)
 
const particle::BaseParticle * getParticleFromWallList (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::Point & getXRef (size_t i)
 Get reference coordinate of the node.
 
const util::Point & getXRef (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::Point & getX (size_t i)
 Get current coordinate of the node.
 
const util::Point & getX (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::Point & getU (size_t i)
 Get displacement of the node.
 
const util::Point & getU (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::Point & getV (size_t i)
 Get velocity of the node.
 
const util::Point & getV (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::Point & getF (size_t i)
 Get force of the node.
 
const util::Point & getF (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::Contact > d_contact_p
 
std::unique_ptr< postprocess::Postprocess > d_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::Input > d_input_p
 Pointer to Input object.
 
std::shared_ptr< inp::ModelDeck > d_modelDeck_p
 Pointer to deck holding problem related data.
 
std::shared_ptr< inp::OutputDeck > d_outputDeck_p
 Pointer to deck holding output related data.
 
std::shared_ptr< inp::RestartDeck > d_restartDeck_p
 Pointer to deck holding restart related data.
 
std::shared_ptr< inp::TestDeck > d_testDeck_p
 Test deck.
 
std::shared_ptr< inp::BCDeck > d_bcDeck_p
 Boundary condition deck.
 
std::shared_ptr< inp::ParticleDeck > d_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::MatData > d_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::ParticleULoading > d_uLoading_p
 Pointer to displacement Loading object.
 
std::unique_ptr< loading::ParticleFLoading > d_fLoading_p
 Pointer to force Loading object.
 
std::unique_ptr< geometry::Fracture > d_fracture_p
 Fracture state of bonds.
 
std::unique_ptr< NSearch > d_nsearch_p
 Pointer to nsearch.
 
std::vector< util::Point > d_xRef
 reference positions of the nodes
 
std::vector< util::Point > d_x
 Current positions of the nodes.
 
std::vector< util::Point > d_u
 Displacement of the nodes.
 
std::vector< util::Point > d_v
 Velocity of the nodes.
 
std::vector< double > d_vMag
 Magnitude of velocity of the nodes.
 
std::vector< util::Point > d_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::Point > d_xQuadCur
 Current position of quadrature points.
 
std::vector< util::SymMatrix3 > d_strain
 Strain in elements (values at quadrature points)
 
std::vector< util::SymMatrix3 > d_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 512 of file periDEMModel.cpp.

512 {
513 log(" Computing external displacement bc \n", 3);
514 for (auto &p : d_particlesListTypeAll)
515 d_uLoading_p->apply(d_time, p); // applied in parallel
516}
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 518 of file periDEMModel.cpp.

518 {
519 log("Applying initial condition \n", 3);
520 for (auto &p : d_particlesListTypeAll)
521 loading::applyIC(p, d_bcDeck_p->d_icDeck); // applied in parallel
522}
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 537 of file periDEMModel.cpp.

537 {
538 if (d_testDeck_p->d_testName == "two_particle")
539 log(ppTwoParticleTest(), 2, d_n % d_infoN == 0, 3);
540 else if (d_testDeck_p->d_testName == "compressive_test")
541 log(ppCompressiveTest(), 2, d_n % d_infoN == 0, 3);
542 if (d_postprocess_p)
543 d_postprocess_p->checkStop(*this);
544}
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 476 of file periDEMModel.cpp.

476 {
477 log(" Computing external force \n", 3);
478
479 auto gravity = d_bcDeck_p->d_gravity;
480
481 if (gravity.length() > 1.0E-8) {
482 tf::Executor executor(util::parallel::getNThreads());
483 tf::Taskflow taskflow;
484
485 // Only owned force nodes (walls on rank 0 for particle-MPI; Metis owners
486 // for DOF-MPI). Applying gravity on every rank then Allreducing reaction
487 // would multiply wall weight by mpiSize.
488 const auto &nodes = d_fContCompNodes;
489 taskflow.for_each_index((std::size_t) 0, nodes.size(), (std::size_t)1,
490 [this, gravity, &nodes](std::size_t II) {
491 const size_t i = nodes[II];
492 this->d_f[i] += this->getDensity(i) * gravity;
493 });
494
495 executor.run(taskflow).get();
496 }
497
498 for (auto &p : d_particlesListTypeAll) {
499 if (p->isWall()) {
500 if (util::parallel::mpiRank() == 0)
501 d_fLoading_p->apply(d_time, p);
502 } else if (d_pdDofMpi) {
503 // Nodal ownership: apply on every rank; loading loops all nodes of p,
504 // but only owned force nodes are integrated.
505 d_fLoading_p->apply(d_time, p);
506 } else if (particle::isLocallyOwned(*p)) {
507 d_fLoading_p->apply(d_time, p);
508 }
509 }
510}
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 322 of file periDEMModel.cpp.

322 {
323
324 bool dbg_condition = d_n % d_infoN == 0;
325
326 log(" Compute forces \n", 2, dbg_condition, 3);
327
328 // Refresh ghost grain kinematics from owners before contact / damping.
329 {
330 const auto t_ex0 = steady_clock::now();
332 appendKeyData("mpi_exchange_wall_time",
333 util::methods::timeDiff(t_ex0, steady_clock::now()));
334 }
335
336 // Nodal DOF halo for PD neighbor reads (Single_Particle MPI).
338
339 // reset force
340 auto t1 = steady_clock::now();
341 float force_reset_time = 0;
342 {
343 tf::Executor executor(util::parallel::getNThreads());
344 tf::Taskflow taskflow;
345
346 taskflow.for_each_index(
347 (std::size_t) 0, d_x.size(), (std::size_t) 1,
348 [this](std::size_t i) { this->d_f[i] = util::Point(); }
349 ); // for_each
350
351 executor.run(taskflow).get();
352 force_reset_time = util::methods::timeDiff(t1, steady_clock::now());
353 }
354
355 // compute peridynamic forces
356 t1 = steady_clock::now();
357 pd::computeForces(*this);
358 auto pd_time = util::methods::timeDiff(t1, steady_clock::now());
359 appendKeyData("pd_compute_time", pd_time);
360 appendKeyData("avg_peridynamics_force_time", pd_time/d_infoN);
361
362 float current_contact_neigh_update_time = 0;
363 float contact_time = 0;
364 if (d_input_p->isMultiParticle() && d_contact_p) {
365 // update contact neighborlist
366 t1 = steady_clock::now();
367 d_contact_p->updateNeighborlist(*this);
368 current_contact_neigh_update_time = util::methods::timeDiff(t1,
369 steady_clock::now());
370 appendKeyData("contact_neigh_update_time",
371 current_contact_neigh_update_time);
372 appendKeyData("avg_contact_neigh_update_time",
373 current_contact_neigh_update_time / d_infoN);
374
375 // compute contact forces between particles
376 t1 = steady_clock::now();
377 d_contact_p->computeForces(*this);
378 contact_time = util::methods::timeDiff(t1, steady_clock::now());
379 appendKeyData("contact_compute_time", contact_time);
380 appendKeyData("avg_contact_force_time", contact_time / d_infoN);
381 }
382
383 // Compute external forces
384 t1 = steady_clock::now();
386 auto extf_time = util::methods::timeDiff(t1, steady_clock::now());
387 appendKeyData("extf_compute_time", extf_time);
388 appendKeyData("avg_extf_compute_time", extf_time/d_infoN);
389
390 // output avg time info
391 if (dbg_condition) {
392 if (d_input_p->isMultiParticle()) {
393 log(std::format(" Avg time (ms): \n"
394 " {:48s} = {:8d}\n"
395 " {:48s} = {:8d}\n"
396 " {:48s} = {:8d}\n"
397 " {:48s} = {:8d}\n"
398 " {:48s} = {:8d}\n"
399 " {:48s} = {:8d}\n",
400 "tree update", size_t(getKeyData("avg_tree_update_time")),
401 "contact neigh update",
402 size_t(getKeyData("avg_contact_neigh_update_time")),
403 "contact force",
404 size_t(getKeyData("avg_contact_force_time")),
405 "total contact", size_t(getKeyData("avg_tree_update_time")
406 + getKeyData(
407 "avg_contact_neigh_update_time")
408 + getKeyData(
409 "avg_contact_force_time")),
410 "peridynamics force",
411 size_t(getKeyData("avg_peridynamics_force_time")),
412 "external force",
413 size_t(getKeyData("avg_extf_compute_time") / d_infoN)),
414 2, dbg_condition, 3);
415
416 appendKeyData("avg_tree_update_time", 0.);
417 appendKeyData("avg_contact_neigh_update_time", 0.);
418 appendKeyData("avg_contact_force_time", 0.);
419 appendKeyData("avg_peridynamics_force_time", 0.);
420 appendKeyData("avg_extf_compute_time", 0.);
421 }
422 else {
423 log(std::format(" Avg time (ms): \n"
424 " {:48s} = {:8d}\n"
425 " {:48s} = {:8d}\n",
426 "peridynamics force", size_t(getKeyData("avg_peridynamics_force_time")),
427 "external force", size_t(getKeyData("avg_extf_compute_time")/d_infoN)),
428 2, dbg_condition, 3);
429
430 appendKeyData("avg_peridynamics_force_time", 0.);
431 appendKeyData("avg_extf_compute_time", 0.);
432 }
433 }
434
435 log(std::format(" {:50s} = {:8d} \n",
436 "Force reset time (ms)",
437 size_t(force_reset_time)
438 ),
439 2, dbg_condition, 3);
440
441 log(std::format(" {:50s} = {:8d} \n",
442 "External force time (ms)",
443 size_t(extf_time)
444 ),
445 2, dbg_condition, 3);
446
447 log(std::format(" {:50s} = {:8d} \n",
448 "Peridynamics force time (ms)",
449 size_t(pd_time)
450 ),
451 2, dbg_condition, 3);
452
453 if (d_input_p->isMultiParticle()) {
454
455 log(std::format(" {:50s} = {:8d} \n",
456 "Point cloud update time (ms)",
457 size_t(getKeyData("pt_cloud_update_time"))
458 ),
459 2, dbg_condition, 3);
460
461 log(std::format(" {:50s} = {:8d} \n",
462 "Contact neighborlist update time (ms)",
463 size_t(current_contact_neigh_update_time)
464 ),
465 2, dbg_condition, 3);
466
467 log(std::format(" {:50s} = {:8d} \n",
468 "Contact force time (ms)",
469 size_t(contact_time)
470 ),
471 2, dbg_condition, 3);
472 }
473
474}
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:309

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 // A particle with every degree of freedom fixed still has its force
241 // computed, because the reaction force on it is wanted.
242
243 // if this is a two-particle test, we set the force calculation off in
244 // first particle
245 if (d_testDeck_p->d_testName == "two_particle") {
246 d_particlesListTypeAll[0]->d_computeForce = false;
247 }
248
249 log(std::format("{}: Total particles = {}. \n",
251
252 for (const auto &p : d_particlesListTypeAll)
253 if (!p->d_computeForce)
254 log(std::format("{}: Force OFF in Particle i = {}. \n", d_name, p->getId()));
255
256 // Single-particle DOF-MPI: Metis node owners + PD ghost plan (T10).
258
259 log(d_name + ": Creating list of nodes on which force is to be computed.\n");
260 // Selection is per particle or wall: a node enters d_fCompNodes if force is
261 // computed on any node of its body. Selecting individual nodes is not
262 // implemented.
263 const int mpi_rank = util::parallel::mpiRank();
264 for (size_t i = 0; i < d_x.size(); i++) {
265 const auto &ptId = d_ptId[i];
266 const auto &pi = getParticleFromAllList(ptId);
267 bool node_owned = false;
268 if (d_pdDofMpi)
269 node_owned = (static_cast<int>(d_pdNodePartition[i]) == mpi_rank);
270 else if (pi->isWall())
271 // Walls are replicated; assemble wall contact/reaction on rank 0 only.
272 node_owned = (mpi_rank == 0);
273 else
274 node_owned = particle::isLocallyOwned(*pi);
275 if (pi->d_computeForce && node_owned) {
276 d_fContCompNodes.push_back(i);
277 // Walls keep contact (and reaction) but not peridynamic force. Treating a
278 // container as a PD body on a thin/boolean mesh makes Damage_Z explode
279 // and the neighbor search then allocates until the process is OOM-killed.
280 if (!pi->isWall())
281 d_fPdCompNodes.push_back(i);
282 }
283 }
284
285 // initialize remaining fields (if any)
286 d_Z = std::vector<float>(d_x.size(), 0.);
287 // Damage: volume-weighted phi (Silling/Trask) and broken-bond count
288 // fraction (Bhattacharya & Lipton).
289 d_phi = std::vector<float>(d_x.size(), 0.);
290 d_phiBond = std::vector<float>(d_x.size(), 0.);
291
292 t2 = steady_clock::now();
293 log(std::format("{}: Total setup time (ms) = {}. \n",
295
296 // compute complexity information
297 size_t free_dofs = 0;
298 for (const auto &f : d_fix) {
299 for (size_t dof = 0; dof < 3; dof++)
300 if (util::methods::isFree(f, dof))
301 free_dofs++;
302 }
303 log(std::format("{}: Computational complexity information \n"
304 " Total number of particles = {}, number of "
305 "particles = {}, number of walls = {}, \n"
306 " number of dofs = {}, number of free dofs = {}. \n",
310 3 * d_x.size(),
311 free_dofs));
312}
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:76
bool isFree(const int &i, const unsigned int &dof)
Returns true if degree of freedom is free.
Definition vecMethods.h:254

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 314 of file periDEMModel.cpp.

314 {
316}
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 318 of file periDEMModel.cpp.

318 {
319 time_int::Integrator().step(*this);
320}
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 524 of file periDEMModel.cpp.

524 {
525 if (currentStep() == 0)
526 log(std::format("{}: Output step = {}, time = {:.6f} \n", d_name, d_n, d_time),
527 2);
528 rw::writeOutput(*this);
529}
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 546 of file periDEMModel.cpp.

546 {
547 if (!d_postprocess_p)
548 return "";
549 return d_postprocess_p->compressive(*this);
550}

References d_postprocess_p.

Referenced by checkStop().

Here is the caller graph for this function:

◆ ppTwoParticleTest()

std::string PeriDEMModel::ppTwoParticleTest ( )

Definition at line 531 of file periDEMModel.cpp.

531 {
532 if (!d_postprocess_p)
533 return "";
534 return d_postprocess_p->twoParticle(*this);
535}

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: