<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "ParallelUniqueId.h"
#include "MooseMesh.h"
#include "MooseTypes.h"
#include "MooseException.h"
#include "MooseVariableFieldBase.h"
#include "FVFluxKernel.h"
#include "FVFluxBC.h"
#include "FEProblem.h"
#include "SwapBackSentinel.h"
#include "MaterialBase.h"
#include "libmesh/libmesh_exceptions.h"
#include "libmesh/elem.h"

#include <set>

class MooseVariableFVBase;

/// This works like the Sentinel helper classes in MOOSE, except it is more
/// flexible and concise to use.  You just initialize it with a lambda and can
/// return it from within another function scope.  So a function that has other
/// cleanup functions associated with it can just wrap those cleanup funcs in
/// an OnScopeExit object and return it.  The caller of the function needing
/// cleanup simply catches its return value and voila - the cleanup function
/// are called at the end of the calling functions scope. Like this:
///
///   OnScopeExit doSomethingSpecial()
///   {
///     ...
///     return OnScopeExit([]{cleanupSomethingSpecial();});
///   }
///   void cleanupSomethingSpecial() {...}
///
///   void main()
///   {
///     auto cleaner_uper = doSomethingSpecial();
///   }
struct OnScopeExit
{
  std::function<void()> _f;
  OnScopeExit(std::function<void()> f) noexcept : _f(std::move(f)) {}
  OnScopeExit(OnScopeExit && other) : _f(std::move(other._f)) {}
  OnScopeExit & operator=(OnScopeExit && other)
  {
    _f = std::move(other._f);
    return *this;
  }
  ~OnScopeExit()
  {
    if (_f)
      _f();
  }
};

/**
 * This loops over a set of mesh faces (i.e. FaceInfo objects).  Callback
 * routines are provided for visiting each face, for visiting boundary faces,
 * for sudomain changes, and pre/post many of these events.
 */
template <typename RangeType>
class ThreadedFaceLoop
{
public:
  ThreadedFaceLoop(FEProblemBase & fe_problem, const std::set<TagID> & tags);

  ThreadedFaceLoop(ThreadedFaceLoop & x, Threads::split split);

  virtual ~ThreadedFaceLoop();

  virtual void operator()(const RangeType & range, bool bypass_threading = false);

  void join(const ThreadedFaceLoop & /*y*/){};

  virtual void onFace(const FaceInfo & fi) = 0;
  /// This is called once for each face after all face and boundary callbacks have been
  /// finished for that face.
  virtual void postFace(const FaceInfo & /*fi*/) {}
  /// This is called once after all face-looping is finished.
  virtual void post() {}

  /// This is called once for every face that is on a boundary *after* onFace
  /// is called for the face.
  virtual void onBoundary(const FaceInfo & fi, BoundaryID boundary) = 0;

  /// Called every time the current subdomain changes (i.e. the subdomain of *this* face's elem element
  /// is not the same as the subdomain of the last face's elem element).
  virtual void subdomainChanged(){};

  /// Called every time the neighbor subdomain changes (i.e. the subdomain of *this* face's neighbor element
  /// is not the same as the subdomain of the last face's neighbor element).
  virtual void neighborSubdomainChanged(){};

  /// Called if a MooseException is caught anywhere during the computation.
  virtual void caughtMooseException(MooseException &){};

protected:
  FEProblemBase & _fe_problem;
  MooseMesh & _mesh;
  const std::set<TagID> & _tags;
  THREAD_ID _tid;

  /// The subdomain for the current element
  SubdomainID _subdomain;

  /// The subdomain for the last element
  SubdomainID _old_subdomain;

  /// The subdomain for the current neighbor
  SubdomainID _neighbor_subdomain;

  /// The subdomain for the last neighbor<commit_msg>Ensure that we call appropriate subdomainSetup method when our elem or neighbor subdomain changes<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#pragma once

#include "ParallelUniqueId.h"
#include "MooseMesh.h"
#include "MooseTypes.h"
#include "MooseException.h"
#include "MooseVariableFieldBase.h"
#include "FVFluxKernel.h"
#include "FVFluxBC.h"
#include "FEProblem.h"
#include "SwapBackSentinel.h"
#include "MaterialBase.h"
#include "libmesh/libmesh_exceptions.h"
#include "libmesh/elem.h"

#include <set>

class MooseVariableFVBase;

/// This works like the Sentinel helper classes in MOOSE, except it is more
/// flexible and concise to use.  You just initialize it with a lambda and can
/// return it from within another function scope.  So a function that has other
/// cleanup functions associated with it can just wrap those cleanup funcs in
/// an OnScopeExit object and return it.  The caller of the function needing
/// cleanup simply catches its return value and voila - the cleanup function
/// are called at the end of the calling functions scope. Like this:
///
///   OnScopeExit doSomethingSpecial()
///   {
///     ...
///     return OnScopeExit([]{cleanupSomethingSpecial();});
///   }
///   void cleanupSomethingSpecial() {...}
///
///   void main()
///   {
///     auto cleaner_uper = doSomethingSpecial();
///   }
struct OnScopeExit
{
  std::function<void()> _f;
  OnScopeExit(std::function<void()> f) noexcept : _f(std::move(f)) {}
  OnScopeExit(OnScopeExit && other) : _f(std::move(other._f)) {}
  OnScopeExit & operator=(OnScopeExit && other)
  {
    _f = std::move(other._f);
    return *this;
  }
  ~OnScopeExit()
  {
    if (_f)
      _f();
  }
};

/**
 * This loops over a set of mesh faces (i.e. FaceInfo objects).  Callback
 * routines are provided for visiting each face, for visiting boundary faces,
 * for sudomain changes, and pre/post many of these events.
 */
template <typename RangeType>
class ThreadedFaceLoop
{
public:
  ThreadedFaceLoop(FEProblemBase & fe_problem, const std::set<TagID> & tags);

  ThreadedFaceLoop(ThreadedFaceLoop & x, Threads::split split);

  virtual ~ThreadedFaceLoop();

  virtual void operator()(const RangeType & range, bool bypass_threading = false);

  void join(const ThreadedFaceLoop & /*y*/){};

  virtual void onFace(const FaceInfo & fi) = 0;
  /// This is called once for each face after all face and boundary callbacks have been
  /// finished for that face.
  virtual void postFace(const FaceInfo & /*fi*/) {}
  /// This is called once after all face-looping is finished.
  virtual void post() {}

  /// This is called once for every face that is on a boundary *after* onFace
  /// is called for the face.
  virtual void onBoundary(const FaceInfo & fi, BoundaryID boundary) = 0;

  /// Called every time the current subdomain changes (i.e. the subdomain of *this* face's elem element
  /// is not the same as the subdomain of the last face's elem element).
  virtual void subdomainChanged() { _fe_problem.subdomainSetup(_subdomain, _tid); }

  /// Called every time the neighbor subdomain changes (i.e. the subdomain of *this* face's neighbor element
  /// is not the same as the subdomain of the last face's neighbor element).
  virtual void neighborSubdomainChanged()
  {
    _fe_problem.neighborSubdomainSetup(_neighbor_subdomain, _tid);
  }

  /// Called if a MooseException is caught anywhere during the computation.
  virtual void caughtMooseException(MooseException &){};

protected:
  FEProblemBase & _fe_problem;
  MooseMesh & _mesh;
  const std::set<TagID> & _tags;
  THREAD_ID _tid;

  /// The subdomain for the current element
  SubdomainID _subdomain;

  /// The subdomain for the last element
  SubdomainID _old_subdomain;

  /// The subdomain for the current neighbor
  SubdomainID _neighbor_subdomain;

  /// The subdomain for the last neighbor
{'fraction_non_alphanumeric': 0.11449906658369632, 'fraction_numerical': 0.0014934660858743, 'mean_word_length': 3.6397228637413397, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6977767', 'n_tokens_mistral': 2457, 'n_tokens_neox': 2373, 'n_words': 864}