Chi-Tech
CellVolumeIntegralPostProcessor.cc
Go to the documentation of this file.
2
4
10
11#include "ChiObjectFactory.h"
12
13namespace chi
14{
15
17
18// ##################################################################
20{
24
25 // clang-format off
27 "Computes the volumetric integral of a field-function as a scalar.");
28 // clang-format on
29 params.SetDocGroup("doc_PostProcessors");
30
32 "compute_volume_average",
33 false,
34 "Flag, when true will compute the volume average of the post-processor.");
35
36 return params;
37}
38
39// ##################################################################
41 const InputParameters& params)
42 : PostProcessor(params, PPType::SCALAR),
43 chi_physics::GridBasedFieldFunctionInterface(params),
44 chi_mesh::LogicalVolumeInterface(params),
45 compute_volume_average_(
46 params.GetParamValue<bool>("compute_volume_average"))
47{
48 value_ = ParameterBlock("", 0.0);
49}
50
51// ##################################################################
53{
54 const auto* grid_field_function = GetGridBasedFieldFunction();
55
56 ChiLogicalErrorIf(not grid_field_function,
57 "Attempted to access invalid field"
58 "function");
59
60 const auto& grid = grid_field_function->GetSpatialDiscretization().Grid();
61
62 const auto* logical_volume_ptr_ = GetLogicalVolume();
63 if (logical_volume_ptr_ == nullptr)
64 {
65 cell_local_ids_.reserve(grid.local_cells.size());
66 for (const auto& cell : grid.local_cells)
67 cell_local_ids_.push_back(cell.local_id_);
68 }
69 else
70 {
71 for (const auto& cell : grid.local_cells)
72 if (logical_volume_ptr_->Inside(cell.centroid_))
73 cell_local_ids_.push_back(cell.local_id_);
74 }
75
76 initialized_ = true;
77}
78
79// ##################################################################
81{
82 if (not initialized_) Initialize();
83
84 const auto* grid_field_function = GetGridBasedFieldFunction();
85
86 ChiLogicalErrorIf(not grid_field_function,
87 "Attempted to access invalid field"
88 "function");
89
90 const auto& ref_ff = *grid_field_function;
91 const auto& sdm = ref_ff.GetSpatialDiscretization();
92 const auto& grid = sdm.Grid();
93
94 const auto& uk_man = ref_ff.GetUnknownManager();
95 const auto uid = 0;
96 const auto cid = 0;
97
98 const auto field_data = ref_ff.GetGhostedFieldVector();
99
100 auto coord = sdm.GetSpatialWeightingFunction();
101
102 double local_integral = 0.0;
103 double local_volume = 0.0;
104 for (const uint64_t cell_local_id : cell_local_ids_)
105 {
106 const auto& cell = grid.local_cells[cell_local_id];
107 const auto& cell_mapping = sdm.GetCellMapping(cell);
108 const size_t num_nodes = cell_mapping.NumNodes();
109 const auto qp_data = cell_mapping.MakeVolumetricQuadraturePointData();
110
111 std::vector<double> node_dof_values(num_nodes, 0.0);
112 for (size_t i = 0; i < num_nodes; ++i)
113 {
114 const int64_t imap = sdm.MapDOFLocal(cell, i, uk_man, uid, cid);
115 node_dof_values[i] = field_data[imap];
116 } // for i
117
118 for (const size_t qp : qp_data.QuadraturePointIndices())
119 {
120 // phi_h = sum_j b_j phi_j
121 double ff_value = 0.0;
122 for (size_t j = 0; j < num_nodes; ++j)
123 ff_value += qp_data.ShapeValue(j, qp) *
124 node_dof_values[j];
125
126 local_integral += ff_value * coord(qp_data.QPointXYZ(qp)) * qp_data.JxW(qp);
127 local_volume += coord(qp_data.QPointXYZ(qp)) * qp_data.JxW(qp);
128 } // for qp
129 } // for cell-id
130
131 double globl_integral;
132 MPI_Allreduce(&local_integral, // sendbuf
133 &globl_integral, // recvbuf
134 1,
135 MPI_DOUBLE, // count + datatype
136 MPI_SUM, // operation
137 Chi::mpi.comm); // communicator
138 if (not compute_volume_average_) value_ = ParameterBlock("", globl_integral);
139 else
140 {
141 double globl_volume;
142 MPI_Allreduce(&local_volume, // sendbuf
143 &globl_volume, // recvbuf
144 1,
145 MPI_DOUBLE, // count + datatype
146 MPI_SUM, // operation
147 Chi::mpi.comm); // communicator
148
149 value_ = ParameterBlock("", globl_integral / globl_volume);
150 }
151
152 const int event_code = event_context.Code();
153 if (event_code == 32 /*SolverInitialized*/ or
154 event_code == 38 /*SolverAdvanced*/)
155 {
156 const auto& event_params = event_context.Parameters();
157
158 if (event_params.Has("timestep_index") and event_params.Has("time"))
159 {
160 const size_t index = event_params.GetParamValue<size_t>("timestep_index");
161 const double time = event_params.GetParamValue<double>("time");
162 TimeHistoryEntry entry{index, time, value_};
163 time_history_.push_back(std::move(entry));
164 }
165 }
166}
167
168} // namespace chi
#define ChiLogicalErrorIf(condition, message)
static chi::MPI_Info & mpi
Definition: chi_runtime.h:78
CellVolumeIntegralPostProcessor(const InputParameters &params)
bool initialized_
std::vector< uint64_t > cell_local_ids_
static InputParameters GetInputParameters()
void Initialize()
void Execute(const Event &event_context) override
const bool compute_volume_average_
int Code() const
Definition: Event.cc:19
const ParameterBlock & Parameters() const
Definition: Event.cc:20
void SetDocGroup(const std::string &doc_group)
void AddOptionalParameter(const std::string &name, T value, const std::string &doc_string)
void SetGeneralDescription(const std::string &description)
T GetParamValue(const std::string &param_name) const
Definition: PostProcessor.h:28
ParameterBlock value_
Definition: PostProcessor.h:88
std::vector< TimeHistoryEntry > time_history_
Definition: PostProcessor.h:90
static InputParameters GetInputParameters()
static chi::InputParameters GetInputParameters()
const LogicalVolume * GetLogicalVolume() const
RegisterChiObject(chi, KBAGraphPartitioner)
Definition: PostProcessor.h:31