Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to return radial (inflow/outflow) from CalculateRadialWindProfile #81

Open
zarzycki opened this issue Jul 31, 2024 · 1 comment

Comments

@zarzycki
Copy link
Contributor

When using --radial_wind_profile...

In CalculateRadialWindProfile, the azimuthal wind is calculated:

                // Calculate radial velocity
                //double dUr = dUx * dRx + dUy * dRy + dUz * dRz;

                // Calculate azimuthal velocity
                double dUa = dUx * dAx + dUy * dAy + dUz * dAz;

We should also allow the user to request radial velocity (inflow/outflow to the node).

I am not sure the cleanest way to do this. Perhaps something like

radial_wind_profile(, , , , )

where if opt is 0, it returns azimuthal wind and opt is 1 is returns radial wind.

I believe you then could take the radially averaged azimuthal and radial and combine them to get the true wind magnitude (which is what you'd get with radial_profile(_VEGMAG(U,V),X,Y).

Where this would be useful is for calculating inflow angle/cross-isobaric diagnostics such as those in Nardi et al., 2022.

@zarzycki
Copy link
Contributor Author

zarzycki commented Feb 6, 2025

FYI, here is what I did to get this working. I essentially added an optional arg to radial_wind_profile() that is either 0 (azimuthal) or 1 (radial). I think if the user omits this the code performs as is currently does.

The only drawback to this framework is that it essentially loops over all the nodes twice (one to get az wind, one to get rad wind). I assume there's a smarter way to just push both az and rad wind onto the stack (or whatever C++ people call it) but then it make it hard for me to come up with a good way to handle output, so this was most logical for me.

diff --git a/src/nodes/NodeFileEditor.cpp b/src/nodes/NodeFileEditor.cpp
index 0b1d808..c8a30b0 100644
--- a/src/nodes/NodeFileEditor.cpp
+++ b/src/nodes/NodeFileEditor.cpp
@@ -381,8 +381,10 @@ void CalculateRadialWindProfile(
 	VariableIndex varixU,
 	VariableIndex varixV,
 	std::string strBins,
-	std::string strBinWidth
+	std::string strBinWidth,
+	bool do_azimuth = true  // ChatGPT tells me if we define it this way, we can preserve current behavior
 ) {
+
 	// Get number of bins
 	int nBins = pathnode.GetColumnDataAsInteger(cdh, strBins);
 
@@ -522,16 +524,20 @@ void CalculateRadialWindProfile(
 			_EXCEPTIONT("Logic error");
 		}
 */
-		// Calculate radial velocity
-		//double dUr = dUx * dRx + dUy * dRy + dUz * dRz;
 
-		// Calculate azimuthal velocity
-		double dUa = dUx * dAx + dUy * dAy + dUz * dAz;
-		
-		// Azimuthal convention positive if cyclonic, flip in SH
-		if (dLat0 < 0.0) {
-			dUa = -dUa;
-		}
+    double dUa;  // define in proper scope
+    if (do_azimuth) {
+        // Calculate azimuthal velocity
+        dUa = dUx * dAx + dUy * dAy + dUz * dAz;
+        // Azimuthal convention positive if cyclonic, flip in SH
+        if (dLat0 < 0.0) {
+            dUa = -dUa;
+        }
+    } else {
+        // Calculate radial velocity and cheat-store as dUa
+        double dUr = dUx * dRx + dUy * dRy + dUz * dRz;
+        dUa = dUr;
+    }
 
 		//printf("%1.5e %1.5e :: %1.5e %1.5e\n", dUlon, dUlat, dUr, dUa);
 
@@ -2149,7 +2155,7 @@ try {
 			}
 
 			// Only assignment and function evaluations available
                        // CMZ increase from 5->6
-			if ((pargtree->size() <= 2) || (pargtree->size() >= 5)) {
+			if ((pargtree->size() <= 2) || (pargtree->size() >= 6)) {
 				_EXCEPTIONT("Syntax error: Unable to interpret calculation");
 			}
 			if ((*pargtree)[1] != "=") {
@@ -2442,12 +2448,28 @@ try {
 
 			// radial_wind_profile
 			if (((*pargtree)[2] == "radial_wind_profile") || ((*pargtree)[2] == "quadrant_wind_profile")) {
-				if (nArguments != 4) {
-					_EXCEPTION2("Syntax error: Function \"%s\" "
-						"requires four arguments:\n"
-						"%s(<u variable>, <v variable>, <# bins>, <bin width>)",
-						(*pargtree)[2].c_str(), (*pargtree)[2].c_str());
-				}
+        if (nArguments != 4 && nArguments != 5) {
+            _EXCEPTION2("Syntax error: Function \"%s\" "
+                "requires four or five arguments:\n"
+                "%s(<u variable>, <v variable>, <# bins>, <bin width>[, optional arg])",
+                (*pargtree)[2].c_str(), (*pargtree)[2].c_str());
+        }
+
+        bool do_azimuth;
+        if (nArguments == 4) {
+            // existing behavior
+            do_azimuth = true;
+        } else {
+            // If 5th argument is 0, do_azimuth is true; if 1, do_azimuth is false (return radial)
+            int azimuth_flag = std::stoi((*pargfunc)[4].c_str());
+
+            if (azimuth_flag != 0 && azimuth_flag != 1) {
+                _EXCEPTION2("Syntax error: Function \"%s\" "
+                    "fifth argument must be 0 or 1:\n"
+                    "%s(<u variable>, <v variable>, <# bins>, <bin width>, <0|1>)",
+                    (*pargtree)[2].c_str(), (*pargtree)[2].c_str());
+            }
+            do_azimuth = (azimuth_flag == 0);
+        }
 
 				bool fRadialWindProfile = ((*pargtree)[2] == "radial_wind_profile");
 
@@ -2492,7 +2514,8 @@ try {
 								varixU,
 								varixV,
 								(*pargfunc)[2],
-								(*pargfunc)[3]);
+								(*pargfunc)[3],
+								do_azimuth);
 
 						} else {
 							CalculateQuadrantWindProfile(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant