input: sa~njaya
output: स न्जय
That's because the Velthuis input code for ञ् is ~n, and the "~" is a special code in TeX, meaning "hard space".
Here's the workaround. I define a font-switching command \dev that will turn Velthuis into Devanāgarī. \dev is mostly made up of "\textsanskrit" which is set up using the standard XeLaTeX/polyglossia \newfontfamily commands. \textsanskrit does the work of invoking the mapping-conversion (from XeTeX's velthuis-sanskrit.tec file).
But just before \textsanskrit, we change tilde into a normal character. And after \textsanskrit, we turn tilde back into an "active" hard space. We use the \aftergroup command so that the "active" version of tilde is activated after the closing of the group that contains the Devanāgarī.
Here's the code:
\newfontfamily\textsanskrit [Script=Devanagari,Mapping=velthuis-sanskrit]{Nakula}
\def\maketildeletter{\catcode`\~=11 }
% Return tilde to being the default TeX "active" character for hard space
\def\maketildeactive{\catcode`\~=13 }
\def\dev{\maketildeletter\textsanskrit \aftergroup\maketildeactive}
Here's how you use it:
input: {\dev sa~njaya uvaaca}. What did Dr~Sañjaya say?
output: सञ्जय उवाच. What did Dr Sañjaya say?
where that space betwen "Dr" and "Sañjaya" is hard, and you can't break a line there.
Enjoy.
Update 2020:
Using David Carlisle's much better idea from the comments below, here's the new code:
\newfontfamily\textsanskrit [Script=Devanagari,Mapping=velthuis-sanskrit]{Nakula}
\def\dev{\edef~{\string~}\textsanskrit }
\def\dev{\edef~{\string~}\textsanskrit }
\begin{document}
{\dev sa~njaya uvaaca}. What did Dr~Sañjaya say?
\end{document}
{\dev sa~njaya uvaaca}. What did Dr~Sañjaya say?
\end{document}