Repository: OpenMDAO/OpenMDAO

Issue:
openmdao command running scripts results in incorrect Problem name and name for reports directory
### Description

A Problem created in a script and run with the python command has the correct name, which is the name of the script minus the extension. 

But when the script is run using the openmdao command, the Problem name is `openmdao`. This results in the reports directory being name `openmdao_out`, which is not the desired behavior. It should also be the script name. 

### Example

Here is a script that can be used to show the problem. Assume the name of the script is `model_script.py`

```
import openmdao.api as om
prob = om.Problem()
prob.setup()
prob.final_setup()
print(f'{prob._name=}')

```

Then run the script using python and openmdao to see the difference

```
$ python model_script.py
prob._name='model_script'
$ openmdao model_script.py
prob._name='openmdao'
```

### OpenMDAO Version

3.37.1-dev

### Relevant environment information

_No response_

Discussion:

Solution patch:
diff --git a/openmdao/core/problem.py b/openmdao/core/problem.py
index ccc5b6815..424f1299d 100644
--- a/openmdao/core/problem.py
+++ b/openmdao/core/problem.py
@@ -98,7 +98,11 @@ def _get_top_script():
         The absolute path, or None if it can't be resolved.
     """
     try:
-        return pathlib.Path(__main__.__file__).resolve()
+        script_name = os.environ.get('OPENMDAO_SCRIPT_NAME')
+        if script_name is not None:
+            return pathlib.Path(script_name).resolve()
+        else:
+            return pathlib.Path(__main__.__file__).resolve()
     except Exception:
         # this will error out in some cases, e.g. inside of a jupyter notebook, so just
         # return None in that case.
diff --git a/openmdao/utils/file_utils.py b/openmdao/utils/file_utils.py
index 23dbe10c1..23e6d0885 100644
--- a/openmdao/utils/file_utils.py
+++ b/openmdao/utils/file_utils.py
@@ -13,7 +13,7 @@ import shutil
 import tempfile
 
 from openmdao.utils.om_warnings import issue_warning
-from openmdao.utils.general_utils import env_truthy
+from openmdao.utils.testing_utils import set_env_vars_context, env_truthy
 
 
 def get_module_path(fpath):
@@ -199,7 +199,8 @@ def _load_and_exec(script_name, user_args):
         '__cached__': None,
     }
 
-    exec(code, globals_dict)  # nosec: private, internal use only
+    with set_env_vars_context(OPENMDAO_SCRIPT_NAME=script_name):
+        exec(code, globals_dict)  # nosec: private, internal use only
 
 
 def fname2mod_name(fname):


Test patch:
diff --git a/openmdao/utils/tests/test_cmdline.py b/openmdao/utils/tests/test_cmdline.py
index 0809e465d..9df0ccba4 100644
--- a/openmdao/utils/tests/test_cmdline.py
+++ b/openmdao/utils/tests/test_cmdline.py
@@ -161,6 +161,23 @@ class CmdlineTestCase(unittest.TestCase):
                 self.assertNotIn(p1_outdir, subdirs)
                 self.assertNotIn(p2_outdir, subdirs)
 
+    def test_outdir(self):
+        env_vars = os.environ.copy()
+        env_vars["OPENMDAO_REPORTS"] = "1"
+        env_vars["TESTFLO_RUNNING"] = "0"
+
+        cmd = f"openmdao {os.path.join(scriptdir, 'circle_opt.py')}"
+        proc = subprocess.Popen(cmd.split(),  # nosec: trusted input
+                                env=env_vars,
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        try:
+            outs, errs = proc.communicate(timeout=10)
+        except subprocess.TimeoutExpired:
+            proc.kill()
+            outs, errs = proc.communicate()
+
+        self.assertTrue(os.path.exists('circle_opt_out'))
+
     def test_n2_err(self):
         # command should raise exception but still produce an n2 html file
         cmd = f'openmdao n2 --no_browser {scriptdir}/bad_connection.py'
@@ -188,6 +205,7 @@ class CmdlineTestCase(unittest.TestCase):
         else:
             self.fail("Didn't find expected err msg in output.")
 
+
 class CmdlineTestCaseCheck(unittest.TestCase):
     def test_auto_ivc_warnings_check(self):
         cmd = 'openmdao check -c auto_ivc_warnings {}'.format(os.path.join(scriptdir, 'auto_ivc_warnings.py'))