org-element-context are often used in org source code because they give quite reliable, precise, and comprehensive information about the local structure of an org document.
Counting the occurrence of both in
org.el gives the number 56 for
That precious information comes at a cost. The org-element parser is quite complicated and takes longer than a regexp-based search.
Therefore one needs to delimit the parsing for frequently run functions to a small local part of the document. The section headings are the most appropriate and most narrow boundaries for such parts.
The following slow variant
my-org-element-at-point does not have the limitations of
org-element-at-point but it is slower because it parses the whole Org buffer.
(defun my-org-element-neighborhood-p (element position &optional greater-element)
"Return non-nil if POSITION is within the bounds of ELEMENT.
If GREATER-ELEMENT is non-nil the result is only non-nil
if ELEMENT is contained in GREATER-ELEMENT.
If the result is non-nil it is actually ELEMENT."
(let ((b (org-element-property :begin element))
(e (org-element-property :end element)))
(<= b position)
(>= e position)
(or (null greater-element)
(and (>= b (org-element-property :begin greater-element))
(<= e (org-element-property :end greater-element))))
(defun my-org-element-at-point (&optional point)
"Slow but more complete version of `org-element-at-point`."
(unless point (setq point (point)))
(let ((tree (org-element-parse-buffer))
(org-element-map tree org-element-all-elements
(setq el-at (or (my-org-element-neighborhood-p el point el-at) el-at))))