@@ -108,7 +108,7 @@ def norm(dcoll: DiscretizationCollection, vec, p, dd=None) -> Scalar:
108108 actx .np .conjugate (vec )
109109 * _apply_mass_operator (dcoll , dd , dd , vec ))))
110110 elif p == np .inf :
111- return nodal_max (dcoll , dd , actx .np .abs (vec ))
111+ return nodal_max (dcoll , dd , actx .np .abs (vec ), init = 0. )
112112 else :
113113 raise ValueError ("unsupported norm order" )
114114
@@ -153,95 +153,121 @@ def nodal_sum_loc(dcoll: DiscretizationCollection, dd, vec) -> Scalar:
153153
154154 actx = vec .array_context
155155
156- return sum ([actx .np .sum (grp_ary ) for grp_ary in vec ])
156+ return sum ([
157+ actx .np .sum (grp_ary ) if grp_ary .size > 0 else actx .from_numpy (np .array (0. ))
158+ for grp_ary in vec ])
157159
158160
159- def nodal_min (dcoll : DiscretizationCollection , dd , vec ) -> Scalar :
161+ def nodal_min (dcoll : DiscretizationCollection , dd , vec , * , init = None ) -> Scalar :
160162 r"""Return the nodal minimum of a vector of degrees of freedom *vec*.
161163
162164 :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
163165 convertible to one.
164166 :arg vec: a :class:`~meshmode.dof_array.DOFArray` or an
165167 :class:`~arraycontext.container.ArrayContainer` of them.
168+ :arg init: an optional initial value. Defaults to `numpy.inf`.
166169 :returns: a device scalar denoting the nodal minimum.
167170 """
168171 comm = dcoll .mpi_communicator
169172 if comm is None :
170- return nodal_min_loc (dcoll , dd , vec )
173+ return nodal_min_loc (dcoll , dd , vec , init = init )
171174
172175 # NOTE: Do not move, we do not want to import mpi4py in single-rank computations
173176 from mpi4py import MPI
174177 actx = vec .array_context
175178
176179 return actx .from_numpy (
177- comm .allreduce (actx .to_numpy (nodal_min_loc (dcoll , dd , vec )), op = MPI .MIN ))
180+ comm .allreduce (
181+ actx .to_numpy (nodal_min_loc (dcoll , dd , vec , init = init )),
182+ op = MPI .MIN ))
178183
179184
180- def nodal_min_loc (dcoll : DiscretizationCollection , dd , vec ) -> Scalar :
185+ def nodal_min_loc (dcoll : DiscretizationCollection , dd , vec , * , init = None ) -> Scalar :
181186 r"""Return the rank-local nodal minimum of a vector of degrees
182187 of freedom *vec*.
183188
184189 :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
185190 convertible to one.
186191 :arg vec: a :class:`~meshmode.dof_array.DOFArray` or an
187192 :class:`~arraycontext.container.ArrayContainer` of them.
193+ :arg init: an optional initial value. Defaults to `numpy.inf`.
188194 :returns: a scalar denoting the rank-local nodal minimum.
189195 """
190196 if not isinstance (vec , DOFArray ):
191197 return min (
192- nodal_min_loc (dcoll , dd , comp )
198+ nodal_min_loc (dcoll , dd , comp , init = init )
193199 for _ , comp in serialize_container (vec )
194200 )
195201
196202 actx = vec .array_context
197203
204+ if init is None :
205+ init = np .inf
206+
207+ if np .isscalar (init ):
208+ init = actx .from_numpy (np .array (init ))
209+
198210 return reduce (
199- lambda acc , grp_ary : actx .np .minimum (acc , actx .np .min (grp_ary )),
200- vec , actx .from_numpy (np .array (np .inf )))
211+ lambda acc , grp_ary : actx .np .minimum (
212+ acc ,
213+ actx .np .min (grp_ary ) if grp_ary .size > 0 else init ),
214+ vec , init )
201215
202216
203- def nodal_max (dcoll : DiscretizationCollection , dd , vec ) -> Scalar :
217+ def nodal_max (dcoll : DiscretizationCollection , dd , vec , * , init = None ) -> Scalar :
204218 r"""Return the nodal maximum of a vector of degrees of freedom *vec*.
205219
206220 :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
207221 convertible to one.
208222 :arg vec: a :class:`~meshmode.dof_array.DOFArray` or an
209223 :class:`~arraycontext.container.ArrayContainer` of them.
224+ :arg init: an optional initial value. Defaults to `-numpy.inf`.
210225 :returns: a device scalar denoting the nodal maximum.
211226 """
212227 comm = dcoll .mpi_communicator
213228 if comm is None :
214- return nodal_max_loc (dcoll , dd , vec )
229+ return nodal_max_loc (dcoll , dd , vec , init = init )
215230
216231 # NOTE: Do not move, we do not want to import mpi4py in single-rank computations
217232 from mpi4py import MPI
218233 actx = vec .array_context
219234
220235 return actx .from_numpy (
221- comm .allreduce (actx .to_numpy (nodal_max_loc (dcoll , dd , vec )), op = MPI .MAX ))
236+ comm .allreduce (
237+ actx .to_numpy (nodal_max_loc (dcoll , dd , vec , init = init )),
238+ op = MPI .MAX ))
222239
223240
224- def nodal_max_loc (dcoll : DiscretizationCollection , dd , vec ) -> Scalar :
241+ def nodal_max_loc (dcoll : DiscretizationCollection , dd , vec , * , init = None ) -> Scalar :
225242 r"""Return the rank-local nodal maximum of a vector of degrees
226243 of freedom *vec*.
227244
228245 :arg dd: a :class:`~grudge.dof_desc.DOFDesc`, or a value
229246 convertible to one.
230247 :arg vec: a :class:`~meshmode.dof_array.DOFArray` or an
231248 :class:`~arraycontext.container.ArrayContainer`.
249+ :arg init: an optional initial value. Defaults to `-numpy.inf`.
232250 :returns: a scalar denoting the rank-local nodal maximum.
233251 """
234252 if not isinstance (vec , DOFArray ):
235253 return max (
236- nodal_max_loc (dcoll , dd , comp )
254+ nodal_max_loc (dcoll , dd , comp , init = init )
237255 for _ , comp in serialize_container (vec )
238256 )
239257
240258 actx = vec .array_context
241259
260+ if init is None :
261+ init = - np .inf
262+
263+ if np .isscalar (init ):
264+ init = actx .from_numpy (np .array (init ))
265+
242266 return reduce (
243- lambda acc , grp_ary : actx .np .maximum (acc , actx .np .max (grp_ary )),
244- vec , actx .from_numpy (np .array (- np .inf )))
267+ lambda acc , grp_ary : actx .np .maximum (
268+ acc ,
269+ actx .np .max (grp_ary ) if grp_ary .size > 0 else init ),
270+ vec , init )
245271
246272
247273def integral (dcoll : DiscretizationCollection , dd , vec ) -> Scalar :
0 commit comments