Skip to content
3 changes: 2 additions & 1 deletion include/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ class Mesh {

//! Return particles scalar data
//! \param[in] attribute Name of the scalar data attribute
std::vector<double> particles_statevars_data(const std::string& attribute);
std::vector<double> particles_statevars_data(
const std::string& attribute, unsigned phase = mpm::ParticlePhase::Solid);

//! Compute and assign rotation matrix to nodes
//! \param[in] euler_angles Map of node number and respective euler_angles
Expand Down
4 changes: 2 additions & 2 deletions include/mesh.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -1104,12 +1104,12 @@ std::vector<Eigen::Matrix<double, Tsize, 1>>
//! Return particle scalar data
template <unsigned Tdim>
std::vector<double> mpm::Mesh<Tdim>::particles_statevars_data(
const std::string& attribute) {
const std::string& attribute, unsigned phase) {
std::vector<double> scalar_data;
scalar_data.reserve(particles_.size());
// Iterate over particles and add scalar value to data
for (auto pitr = particles_.cbegin(); pitr != particles_.cend(); ++pitr)
scalar_data.emplace_back((*pitr)->state_variable(attribute));
scalar_data.emplace_back((*pitr)->state_variable(attribute, phase));
return scalar_data;
}

Expand Down
2 changes: 1 addition & 1 deletion include/solvers/mpm_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class MPMBase : public MPM {
//! Mathematical functions
std::map<unsigned, std::shared_ptr<mpm::FunctionBase>> math_functions_;
//! VTK state variables
std::vector<std::string> vtk_statevars_;
std::map<unsigned, std::vector<std::string>> vtk_statevars_;
//! Set node concentrated force
bool set_node_concentrated_force_{false};
//! Damping type
Expand Down
78 changes: 59 additions & 19 deletions include/solvers/mpm_base.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,44 @@ mpm::MPMBase<Tdim>::MPMBase(const std::shared_ptr<IO>& io) : mpm::MPM(io) {
try {
if (post_process_.at("vtk_statevars").is_array() &&
post_process_.at("vtk_statevars").size() > 0) {
for (unsigned i = 0; i < post_process_.at("vtk_statevars").size(); ++i) {
std::string attribute =
post_process_["vtk_statevars"][i].template get<std::string>();
vtk_statevars_.emplace_back(attribute);
// Iterate over state_vars
for (const auto& svars : post_process_["vtk_statevars"]) {
// Initial phase id and state vars
unsigned phase_id = 0;
std::vector<std::string> state_var;

// If state variables are arranged as string
if (svars.is_string()) {
std::string attribute = svars.template get<std::string>();
state_var.emplace_back(attribute);
}
// If state variables are arranged as json object
else if (svars.is_object()) {
// Phase id
if (svars.contains("phase_id"))
phase_id = svars.at("phase_id").template get<unsigned>();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a check for the valid input of phase_id?

Copy link
Contributor Author

@bodhinandach bodhinandach Aug 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I think this part is defined globally for simulating single-phase and two-phase, so checking phase_id might be a bit difficult as we need to go to particle level initially unless we specify it somewhere. Nevertheless, if you look at these lines:

double state_variable(
const std::string& var,
unsigned phase = mpm::ParticlePhase::Solid) const override {
return (state_variables_[phase].find(var) != state_variables_[phase].end())
? state_variables_[phase].at(var)
: std::numeric_limits<double>::quiet_NaN();
}

Maybe we can use state_variables_.at(phase) instead of state_variables_[phase] for all the above to assert if the given phase is not allocated. Just that it will be a slower call. What do you think @kks32?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any further thoughts on this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this guarantee that the variable is available: state_variables_[phase].find(var) != state_variables_[phase].end()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, if the state_variables_ have the appropriate phase. If the passed phase is equal or larger than state_variables_.size(), then it will cause a segmentation fault. For instance, if I am accessing index phase=1 in single-phase particle, it will be seg-fault

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kks32 Are we good with this? The current implementation has no phase_id check. So if input phase_id is not available, we will have seg fault.

// State variables
if (svars.at("statevars").is_array() &&
svars.at("statevars").size() > 0) {
for (unsigned i = 0; i < svars.at("statevars").size(); ++i) {
std::string attribute =
svars["statevars"][i].template get<std::string>();
state_var.emplace_back(attribute);
}
} else {
throw std::runtime_error(
"No VTK statevariable were specified, none will be generated");
}
}

// Check if vtk_statevars_ has the designated phase_id
if (vtk_statevars_.find(phase_id) != vtk_statevars_.end())
vtk_statevars_.at(phase_id).insert(vtk_statevars_.at(phase_id).end(),
state_var.begin(),
state_var.end());
else
vtk_statevars_.insert(std::make_pair(phase_id, state_var));
}
} else {
throw std::runtime_error(
Expand Down Expand Up @@ -554,23 +588,29 @@ void mpm::MPMBase<Tdim>::write_vtk(mpm::Index step, mpm::Index max_steps) {
}

// VTK state variables
for (const auto& attribute : vtk_statevars_) {
// Write state variables
auto file =
io_->output_file(attribute, extension, uuid_, step, max_steps).string();
vtk_writer->write_scalar_point_data(
file, mesh_->particles_statevars_data(attribute), attribute);
// Write a parallel MPI VTK container file
for (auto const& vtk_statevar : vtk_statevars_) {
unsigned phase_id = vtk_statevar.first;
for (const auto& attribute : vtk_statevar.second) {
std::string phase_attribute = "P" + std::to_string(phase_id) + attribute;
// Write state variables
auto file =
io_->output_file(phase_attribute, extension, uuid_, step, max_steps)
.string();
vtk_writer->write_scalar_point_data(
file, mesh_->particles_statevars_data(attribute, phase_id),
phase_attribute);
// Write a parallel MPI VTK container file
#ifdef USE_MPI
if (mpi_rank == 0 && mpi_size > 1) {
auto parallel_file = io_->output_file(attribute, ".pvtp", uuid_, step,
max_steps, write_mpi_rank)
.string();
unsigned ncomponents = 1;
vtk_writer->write_parallel_vtk(parallel_file, attribute, mpi_size, step,
max_steps, ncomponents);
}
if (mpi_rank == 0 && mpi_size > 1) {
auto parallel_file = io_->output_file(phase_attribute, ".pvtp", uuid_,
step, max_steps, write_mpi_rank)
.string();
unsigned ncomponents = 1;
vtk_writer->write_parallel_vtk(parallel_file, phase_attribute, mpi_size,
step, max_steps, ncomponents);
}
#endif
}
}
}
#endif
Expand Down