New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TLS for VectorPostprocessors #7819
Changes from all commits
59fd021
2705db3
2569c4d
119e35f
2948396
1de886a
7be7053
adcc4e9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,12 @@ class VectorPostprocessorData : public Restartable | |
*/ | ||
VectorPostprocessorData(FEProblem & fe_problem); | ||
|
||
struct VectorPostprocessorState | ||
{ | ||
VectorPostprocessorValue * current; | ||
VectorPostprocessorValue * old; | ||
}; | ||
|
||
/** | ||
* Initialization method, sets the current and old value to 0.0 for this | ||
* VectorPostprocessor | ||
|
@@ -64,26 +70,27 @@ class VectorPostprocessorData : public Restartable | |
/** | ||
* Get the map of names -> VectorPostprocessor values. Exposed for error checking. | ||
*/ | ||
const std::map<std::string, std::map<std::string, VectorPostprocessorValue*> > & values() const { return _values; } | ||
// const std::map<std::string, std::map<std::string, VectorPostprocessorValue*> > & values() const { return _values; } | ||
|
||
/** | ||
* Get the map of vectors for a particular VectorPostprocessor | ||
* @param vpp_name The name of the VectorPostprocessor | ||
*/ | ||
const std::map<std::string, VectorPostprocessorValue*> & vectors(const std::string & vpp_name) { return _values[vpp_name]; } | ||
const std::map<std::string, VectorPostprocessorState> & vectors(const std::string & vpp_name) const; | ||
|
||
/** | ||
* Copy the current post-processor values into old (i.e. shift it "back in time") | ||
*/ | ||
void copyValuesBack(); | ||
|
||
protected: | ||
private: | ||
VectorPostprocessorValue & getVectorPostprocessorHelper(const VectorPostprocessorName & vpp_name, const std::string & vector_name, bool get_current); | ||
|
||
/// Values of the post-processor at the current time | ||
std::map<std::string, std::map<std::string, VectorPostprocessorValue*> > _values; | ||
/// Values of the vector post-processor | ||
std::map<std::string, std::map<std::string, VectorPostprocessorState> > _values; | ||
|
||
/// Values of the post-processors at the time t-1 | ||
std::map<std::string, std::map<std::string, VectorPostprocessorValue*> > _values_old; | ||
std::set<std::string> _requested_items; | ||
std::set<std::string> _supplied_items; | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this for a planned dependency resolution? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes and no. Right now there's already dependency resolution on the objects themselves because they are UserObjects and sorted in the warehouse. The intention for this was to add in a new sanity check for the vectors themselves if you couple to vectors, there is no check on whether a vector that you couple to exists right now. I started on this but need to flesh it out quite a bit more and want to unify the way it works between VectorPostprocessors and Postprocessors. I can either continue to work on this or continue that work in another PR. I kind of want to handle it separately since this is already getting to be a substantial PR. |
||
|
||
#endif //VECTORPOSTPROCESSORDATA_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,18 +85,22 @@ TableOutput::outputVectorPostprocessors() | |
// Loop through the postprocessor names and extract the values from the VectorPostprocessorData storage | ||
for (const auto & vpp_name : out) | ||
{ | ||
const std::map<std::string, VectorPostprocessorValue*> & vectors = _problem_ptr->getVectorPostprocessorVectors(vpp_name); | ||
const auto & vectors = _problem_ptr->getVectorPostprocessorVectors(vpp_name); | ||
|
||
FormattedTable & table = _vector_postprocessor_tables[vpp_name]; | ||
auto table_it = _vector_postprocessor_tables.lower_bound(vpp_name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This set of 3 lines could use a bit of documentation. Took me a minute to figure out that you're just looking for or adding the table. I mean: is this really worth removing the "accidental" insertion side effect? The old code was so simple... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a fair criticism. I'm very, very tainted on RHS use of std::map::operator[]. I would say that I track down a bug about every 4-6 weeks that's related to careless use of that operator. I'd almost rather eradicate it's use anywhere in MOOSE but the syntax is very convenient which makes that hard to do. This particular case is actually one of the few cases where RHS brackets are OK because we want to always create tables so I'm torn. In general, this is the syntax I'd like to move to because for the normal access case, you either add a straight up error when the item isn't found or often just an assertion when you are "sure" the item is there (yeah right...) Here's another crazy idea... We use maps a lot in MOOSE. Maybe it's time to think about replacing our use of maps with a better container. We could start with just aliasing our container to std::map but quickly move to hiding implementation details such as the code you see there behind familiar operators like brackets. I've been using this |
||
if (table_it == _vector_postprocessor_tables.end() || table_it->first != vpp_name) | ||
table_it = _vector_postprocessor_tables.emplace_hint(table_it, vpp_name, FormattedTable()); | ||
|
||
FormattedTable & table = table_it->second; | ||
|
||
table.clear(); | ||
table.outputTimeColumn(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yikes! Was this doing a copy before?!? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep |
||
|
||
for (const auto & vec_it : vectors) | ||
{ | ||
VectorPostprocessorValue vector = *(vec_it.second); | ||
const auto & vector = *vec_it.second.current; | ||
|
||
for (unsigned int i=0; i<vector.size(); i++) | ||
for (auto i = beginIndex(vector); i < vector.size(); ++i) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do but I think we are in the minority. No other MOOSE devs are using this syntax, not even @dschwen. I wonder if we can do better still. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used it in 513c5df after you made a comment to that effect :-D. It might just take a bit to catch on. I suggest we start converting loops (if we decide to stick with it). Seeing it in action in existing code may improve adoption. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks to me should be a method in vector, vector.begin_index(). This beginIndex looks ugly although correct. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, sadly there is no method for creating an enumeration. There are other options and they are all uglier.
|
||
table.addData(vec_it.first, vector[i], i); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,8 +35,7 @@ PointSamplerBase::PointSamplerBase(const InputParameters & parameters) : | |
GeneralVectorPostprocessor(parameters), | ||
CoupleableMooseVariableDependencyIntermediateInterface(this, false), | ||
SamplerBase(parameters, this, _communicator), | ||
_mesh(_subproblem.mesh()), | ||
_point_vec(1) // Only going to evaluate one point at a time for now | ||
_mesh(_subproblem.mesh()) | ||
{ | ||
std::vector<std::string> var_names(_coupled_moose_vars.size()); | ||
|
||
|
@@ -52,42 +51,51 @@ PointSamplerBase::initialize() | |
{ | ||
SamplerBase::initialize(); | ||
|
||
// We do this here just in case it's been destroyed and recreated becaue of mesh adaptivity. | ||
// We do this here just in case it's been destroyed and recreated because of mesh adaptivity. | ||
_pl = _mesh.getPointLocator(); | ||
|
||
// Reset the _found_points array | ||
_found_points.resize(_points.size()); | ||
std::fill(_found_points.begin(), _found_points.end(), false); | ||
// Reset the point arrays | ||
_found_points.assign(_points.size(), false); | ||
|
||
_point_values.resize(_points.size()); | ||
std::for_each(_point_values.begin(), _point_values.end(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well done |
||
[](std::vector<Real> & vec) | ||
{ | ||
vec.clear(); | ||
}); | ||
} | ||
|
||
void | ||
PointSamplerBase::execute() | ||
{ | ||
MeshTools::BoundingBox bbox = _mesh.getInflatedProcessorBoundingBox(); | ||
|
||
for (unsigned int i=0; i<_points.size(); i++) | ||
/// So we don't have to create and destroy this | ||
std::vector<Point> point_vec(1); | ||
|
||
for (auto i = beginIndex(_points); i < _points.size(); ++i) | ||
{ | ||
Point & p = _points[i]; | ||
|
||
// Do a bounding box check so we're not doing unnecessary PointLocator lookups | ||
if (bbox.contains_point(p)) | ||
{ | ||
std::vector<Real> & values = _values[i]; | ||
auto & values = _point_values[i]; | ||
|
||
if (values.empty()) | ||
values.resize(_coupled_moose_vars.size()); | ||
|
||
// First find the element the hit lands in | ||
const Elem * elem = getLocalElemContainingPoint(p, i); | ||
const Elem * elem = getLocalElemContainingPoint(p); | ||
|
||
if (elem) | ||
{ | ||
// We have to pass a vector of points into reinitElemPhys | ||
_point_vec[0] = p; | ||
point_vec[0] = p; | ||
|
||
_subproblem.reinitElemPhys(elem, _point_vec, 0); // Zero is for tid | ||
_subproblem.reinitElemPhys(elem, point_vec, 0); // Zero is for tid | ||
|
||
for (unsigned int j=0; j<_coupled_moose_vars.size(); j++) | ||
for (auto j = beginIndex(_coupled_moose_vars); j < _coupled_moose_vars.size(); ++j) | ||
values[j] = _coupled_moose_vars[j]->sln()[0]; // The zero is for the "qp" | ||
|
||
_found_points[i] = true; | ||
|
@@ -100,7 +108,7 @@ void | |
PointSamplerBase::finalize() | ||
{ | ||
// Save off for speed | ||
unsigned int pid = processor_id(); | ||
const auto pid = processor_id(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Much better... we gotta get these |
||
|
||
/* | ||
* Figure out which processor is actually going "claim" each point. | ||
|
@@ -111,27 +119,27 @@ PointSamplerBase::finalize() | |
|
||
_communicator.maxloc(_found_points, max_id); | ||
|
||
for (unsigned int i=0; i<max_id.size(); i++) | ||
for (auto i = beginIndex(max_id); i < max_id.size(); ++i) | ||
{ | ||
// Only do this check on the proc zero because it's the same on every processor | ||
// _found_points should contain all 1's at this point (ie every point was found by a proc) | ||
if (pid == 0 && !_found_points[i]) | ||
mooseError("In " << name() << ", sample point not found: " << _points[i]); | ||
|
||
if (max_id[i] == pid) | ||
SamplerBase::addSample(_points[i], _ids[i], _values[i]); | ||
SamplerBase::addSample(_points[i], _ids[i], _point_values[i]); | ||
} | ||
|
||
SamplerBase::finalize(); | ||
} | ||
|
||
const Elem * | ||
PointSamplerBase::getLocalElemContainingPoint(const Point & p, unsigned int /*id*/) | ||
PointSamplerBase::getLocalElemContainingPoint(const Point & p) | ||
{ | ||
const Elem * elem = (*_pl)(p); | ||
|
||
if (elem && elem->processor_id() == processor_id()) | ||
return elem; | ||
|
||
return NULL; | ||
return nullptr; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to reviewer: I think we should avoid creating VectoPostprocessor instances in our objects. We may eventually want to make the constructor private like we have for Material and Variable containers to help prevent users from missing the reference in normal declarations. This particular vector is not a declared vector so I switched it to C++ vector.