Line data Source code
1 : /********************************************************************/
2 : /* SOFTWARE COPYRIGHT NOTIFICATION */
3 : /* Cardinal */
4 : /* */
5 : /* (c) 2021 UChicago Argonne, LLC */
6 : /* ALL RIGHTS RESERVED */
7 : /* */
8 : /* Prepared by UChicago Argonne, LLC */
9 : /* Under Contract No. DE-AC02-06CH11357 */
10 : /* With the U. S. Department of Energy */
11 : /* */
12 : /* Prepared by Battelle Energy Alliance, LLC */
13 : /* Under Contract No. DE-AC07-05ID14517 */
14 : /* With the U. S. Department of Energy */
15 : /* */
16 : /* See LICENSE for full restrictions */
17 : /********************************************************************/
18 :
19 : #ifdef ENABLE_NEK_COUPLING
20 :
21 : #include "NekBinnedPlaneIntegral.h"
22 : #include "NekInterface.h"
23 :
24 : registerMooseObject("CardinalApp", NekBinnedPlaneIntegral);
25 :
26 : InputParameters
27 18 : NekBinnedPlaneIntegral::validParams()
28 : {
29 18 : InputParameters params = NekPlaneSpatialBinUserObject::validParams();
30 18 : params.addClassDescription(
31 : "Compute the spatially-binned side integral of a field over the NekRS mesh");
32 18 : return params;
33 0 : }
34 :
35 50 : NekBinnedPlaneIntegral::NekBinnedPlaneIntegral(const InputParameters & parameters)
36 50 : : NekPlaneSpatialBinUserObject(parameters)
37 : {
38 49 : if (_fixed_mesh)
39 49 : computeBinVolumes();
40 48 : }
41 :
42 : void
43 49 : NekBinnedPlaneIntegral::getBinVolumes()
44 : {
45 49 : resetPartialStorage();
46 49 : mesh_t * mesh = nekrs::entireMesh();
47 49 : const auto & vgeo = nekrs::getVgeo();
48 :
49 66613 : for (int k = 0; k < mesh->Nelements; ++k)
50 : {
51 66564 : int offset = k * mesh->Np;
52 48757860 : for (int v = 0; v < mesh->Np; ++v)
53 : {
54 48691296 : Point p = nekPoint(k, v);
55 : unsigned int gap_bin;
56 : double distance;
57 48691296 : gapIndexAndDistance(p, gap_bin, distance);
58 :
59 48691296 : if (distance < _gap_thickness / 2.0)
60 : {
61 13949340 : unsigned int b = bin(p);
62 13949340 : _bin_partial_values[b] += vgeo[mesh->Nvgeo * offset + v + mesh->Np * JWID];
63 13949340 : _bin_partial_counts[b]++;
64 : }
65 : }
66 : }
67 :
68 : // sum across all processes
69 49 : MPI_Allreduce(
70 : _bin_partial_values, _bin_volumes, _n_bins, MPI_DOUBLE, MPI_SUM, platform->comm.mpiComm);
71 49 : MPI_Allreduce(
72 : _bin_partial_counts, _bin_counts, _n_bins, MPI_INT, MPI_SUM, platform->comm.mpiComm);
73 :
74 30089 : for (unsigned int i = 0; i < _n_bins; ++i)
75 : {
76 : // some bins require dividing by a different value, depending on the bin type
77 30040 : const auto local_bins = unrolledBin(i);
78 30040 : _bin_volumes[i] *= _side_bin->adjustBinValue(local_bins[_side_index]);
79 :
80 : // dimensionalize
81 30040 : nekrs::dimensionalizeVolume(_bin_volumes[i]);
82 : }
83 49 : }
84 :
85 : void
86 88 : NekBinnedPlaneIntegral::binnedPlaneIntegral(const field::NekFieldEnum & integrand,
87 : double * total_integral)
88 : {
89 88 : resetPartialStorage();
90 :
91 88 : mesh_t * mesh = nekrs::entireMesh();
92 88 : double (*f)(int, int) = nekrs::solutionPointer(integrand);
93 88 : const auto & vgeo = nekrs::getVgeo();
94 :
95 119032 : for (int k = 0; k < mesh->Nelements; ++k)
96 : {
97 118944 : int offset = k * mesh->Np;
98 72472032 : for (int v = 0; v < mesh->Np; ++v)
99 : {
100 72353088 : Point p = nekPoint(k, v);
101 :
102 : unsigned int gap_bin;
103 : double distance;
104 72353088 : gapIndexAndDistance(p, gap_bin, distance);
105 :
106 72353088 : if (distance < _gap_thickness / 2.0)
107 : {
108 17020704 : unsigned int b = bin(p);
109 17020704 : _bin_partial_values[b] +=
110 17020704 : f(offset + v, 0) * vgeo[mesh->Nvgeo * offset + v + mesh->Np * JWID];
111 : }
112 : }
113 : }
114 :
115 : // sum across all processes
116 88 : MPI_Allreduce(
117 : _bin_partial_values, total_integral, _n_bins, MPI_DOUBLE, MPI_SUM, platform->comm.mpiComm);
118 :
119 11168 : for (unsigned int i = 0; i < _n_bins; ++i)
120 : {
121 : // some bins require dividing by a different value, depending on the bin type
122 11080 : const auto local_bins = unrolledBin(i);
123 11080 : total_integral[i] *= _side_bin->adjustBinValue(local_bins[_side_index]);
124 :
125 11080 : nekrs::dimensionalizeVolumeIntegral(integrand, _bin_volumes[i], total_integral[i]);
126 : }
127 88 : }
128 :
129 : Real
130 83808 : NekBinnedPlaneIntegral::spatialValue(const Point & p, const unsigned int & component) const
131 : {
132 : // total bin index
133 83808 : const auto & i = bin(p);
134 :
135 : // get the index of the gap
136 83808 : auto local_indices = unrolledBin(i);
137 83808 : auto gap_index = local_indices[_side_index];
138 :
139 83808 : return _bin_values[i] * _velocity_bin_directions[gap_index](component);
140 : }
141 :
142 : void
143 48 : NekBinnedPlaneIntegral::computeIntegral()
144 : {
145 : // if the mesh is changing, re-compute the areas of the bins
146 48 : if (!_fixed_mesh)
147 0 : computeBinVolumes();
148 :
149 48 : if (_field == field::velocity_component)
150 : {
151 20 : binnedPlaneIntegral(field::velocity_x, _bin_values_x);
152 20 : binnedPlaneIntegral(field::velocity_y, _bin_values_y);
153 20 : binnedPlaneIntegral(field::velocity_z, _bin_values_z);
154 :
155 2540 : for (unsigned int i = 0; i < num_bins(); ++i)
156 : {
157 2520 : auto local_indices = unrolledBin(i);
158 2520 : auto gap_index = local_indices[_side_index];
159 :
160 2520 : Point velocity(_bin_values_x[i], _bin_values_y[i], _bin_values_z[i]);
161 2520 : _bin_values[i] = _velocity_bin_directions[gap_index] * velocity;
162 : }
163 : }
164 : else
165 28 : binnedPlaneIntegral(_field, _bin_values);
166 48 : }
167 :
168 : void
169 8 : NekBinnedPlaneIntegral::executeUserObject()
170 : {
171 8 : computeIntegral();
172 :
173 : // correct the values to areas
174 1088 : for (unsigned int i = 0; i < _n_bins; ++i)
175 1080 : _bin_values[i] /= _gap_thickness;
176 8 : }
177 :
178 : #endif
|