Code Monkey home page Code Monkey logo

Comments (133)

luzpaz avatar luzpaz commented on May 18, 2024 1

CC @howetuft (RenderWB dev) may be interested in this idea as well

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024 1

I think I will use ParaMiko for the SSH connection.

https://www.devdungeon.com/content/python-ssh-tutorial
https://www.geeksforgeeks.org/how-to-execute-shell-commands-in-a-remote-machine-using-python-paramiko/

Ignore the part about having to generate the ssh key. We'll have the user establish an ssh connection with the remote computer from the local computer before using ssh from CfdOF. In modern versions of Linux the first establishment of an ssh connection automatically generates the ssh key. Once the key is generated, the ssh connection can be opened with username and password only.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024 1

Thanks for doing due diligence. Onward

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024 1

Thanks for doing due diligence. Onward

Does that mean you agree that I'll need to use paramiko or fabric ?

from cfdof.

adrianinsaval avatar adrianinsaval commented on May 18, 2024 1

this would be a seriously good addition to the project!

@linuxguy123 What is the benefit of introducing paramiko as an extra 3rd party dependency ? (I'm asking because dependencies create more work for maintainers)

I think paramiko can be installed with pip so it shouldn't really be a problem, the addon manager can offer to install it when you install the workbench so there isn't any additional work for freecad packagers and cfdof itself doesn't need to package it either, just declare it as a dependency so that the addon manager can take care of it.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024 1

I'll keep the cluster and interacting with the remote processs 'at arm's length' ideas in mind moving forward. Personally, I like watching the residuals and outputs in FreeCAD. Makes it easy to kill the simulation if you see something obviously not working.

I agree, and I wasn't suggesting to lose this functionality, but (as you also mentioned) to monitor the log files rather than remaining attached to the process stdout. This is already how the 'probes' reporting function works - by watching the relevant files in postProcessing/... . I appreciate there is an elegance in keeping everything the same save for the process running through ssh. However every experience I have had of shared compute resources are machines with schedulers where you don't have the option of running heavyweight apps directly. Of course, you are free to take whatever approach works for you, but I do think there would be a lot of benefit in keeping that use case in mind.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024 1

What is the easiest way for me to run my version of CfdOF in my current FreeCAD installation ? And debug it using VS Code ?

Is there a "best practices" doc somewhere for FreeCAD workbench developers ?

You may find https://gitlab.com/opensimproject/cfdof/-/blob/master/CONTRIBUTING.md of some help.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024 1

Is there a way to reliably reload a workbench in FreeCAD without restarting FreeCAD?

When I make a change to my code, I'm currently having to restart FreeCAD to load the changed code and test it. Is there a way to reload the workbench such that I don't have to restart FreeCAD ?

@linuxguy123 check out FreeCAD/FreeCAD-addons#159

from cfdof.

howetuft avatar howetuft commented on May 18, 2024 1

Is there a way to reliably reload a workbench in FreeCAD without restarting FreeCAD?

When I make a change to my code, I'm currently having to restart FreeCAD to load the changed code and test it. Is there a way to reload the workbench such that I don't have to restart FreeCAD ?

If that can help:
For Render workbench, facing the same problem, I've chosen to write a function that reloads the workbench. The function is inside the workbench, the code is here: https://github.com/FreeCAD/FreeCAD-render/blob/master/Render/utils.py#L101
It is exposed in the workbench API, see here: https://github.com/FreeCAD/FreeCAD-render/blob/master/Render/__init__.py#L64

Therefore, now, to reload the workbench, I just enter Render.reload() in the console. Actually, with autocompletion, I just type 2 or 3 letters. You could even imagine to have it embedded in a button on the toolbar or anything that saves you some time.
To be complete, beforehand, I have to import the workbench once (import Render), I do it once and for all at the beginning of my session.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024 1

What command can I use to get an OpenFOAM version without triggering an error because I don't have any input files ? Something like $simpleFoam -version. If I run $simpleFoam I get a string I can parse the version out of, but it returns an error because there are no input files.

Update
The project is coming along really well, now that I am back working on it.

It turns out that RunFoamCommand works with ssh commands. Kudos to the developers for writing a function that I can use and extend without too much trouble.

Hardest part of the whole project was setting up the remote preferences, which is mostly complete, for a Linux remote computer anyway. I'll leave Windows and Docker stuff to other people, though it will be basically the same for a remote computer as for the local machine, so 95% of the existing code can be reused.

This will make sense when I share my code and you see what I've done.

These modifications should make it very practical to mesh and run OpenFOAM on remote computers. When I started the project I was worried the "linkage" would be finicky and not robust. But it's actually quite robust.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024 1

So does that mean you'll let me merge it into CfdOF ?

That's the intention, if you could please do a pull request once it's polished up to your satisfaction.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024 1

I'm adding the ability to have multiple remote hosts. Not just one. Because it is handy to have several hosts set up, ready to use.

CFD work involves a lot of A/B comparisons, comparing simulation 1 to simulation 2 after changing the geometry or flow speed, etc. With multiple remote hosts, I can have 2 different instances of FreeCAD open and send simulation 1 to remote host 1 and simulation 2 to remote host 2.

Likewise, a user can have an AWS host, a host at his university and a remote host in his office, all set up. If he can get off peak pricing on AWS, he can send the job there. If the university host is busy, he can run it on his office host. Multiple hosts offer lots of flexibility.

At some point I'll get and display the load percentages for the remote hosts on the pages that send jobs to the host. But for now I'll just allow different hosts to be used.

There has been talk of working with schedulers on the hosts. I'll leave that topic for another day. I'm aware of the need but for now, one step at a time.

Multiple Remote Hosts Preferences

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

BTW, I don't do Windows. I'll test remote processing on Linux workstations and remote computers but I won't do any testing on Windows devices. I don't even own a Windows machine. Someone else will have to test and troubleshoot on Windows and MacOS.

from cfdof.

howetuft avatar howetuft commented on May 18, 2024

Hello,
Yes, it could be inspiring for the rendering of some very complex scenes (although I think that, for Render WB, these will be borderline cases). Good luck, I will follow the code propositions with attention!

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I've cloned the current CfdOF Master onto my computer. I have not created a fork.

Unless someone tells me otherwise, I'll work on things locally before sharing them publicly.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Yes, it could be inspiring for the rendering of some very complex scenes (although I think that, for Render WB, these will be borderline cases). Good luck, I will follow the code propositions with attention!

How is rendering related to meshing and OpenFOAM ? You'd like to develop something similar (remote processing) for the Rendering WB ?

from cfdof.

howetuft avatar howetuft commented on May 18, 2024

Yes, remote processing could be a nice-to-have for rendering, as rendering can be quite CPU/GPU consuming, especially with recent emerging needs in terms of animation (see Movie workbench). Therefore if you explore solutions to export the load on remote workstations in FreeCAD context, that might be interesting.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Yes, remote processing could be a nice-to-have for rendering, as rendering can be quite CPU/GPU consuming, especially with recent emerging needs in terms of animation (see Movie workbench). Therefore if you explore solutions to export the load on remote workstations in FreeCAD context, that might be interesting.

Interesting.

What is really interesting to me is that "nobody" has done this already for the rendering crowd. I'm not a rendering guy. But I know that rendering is CPU intensive as evidenced by the plethora of Blender benchmarks. I just assumed that an application like Blender would have the ability off load some of the workload to another machine or a rendering cluster.

OpenFOAM is a great tool. But as a stand alone application, it requires a lot of patience to use. The worst part, for me, is setting up the mesh case.

CfdOF changes all that. It really streamlines the OpenFOAM workflow. Everything gets done in one place in one application with a good GUI. Object-> mesh->simulation->visualizing results. CfdOF even displays residuals as the simulation is running and has a couple reporting functions. Of course one will still use Paraview to get into the nitty gritty of the results, but CfdOF handles the processing aspect really well.

Unfortunately, serious CFD work is often computationally intensive. While a lot of work can be done on a workstation, there reaches a point where it is beneficial to use remote processing to get the job done. As of now, https://cfd.direct/cloud/remote-cfd-openfoam/ is the only remote processing UI that I am aware of.

IMHO the next step in streamlining the OpenFOAM experience is to enable remote processing in CfdOF.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I'll use rsync to move the files between the local and remote computer.
https://www.atlantic.net/vps-hosting/how-to-use-rsync-copy-sync-files-servers/

Nothing other than ssh needs to be set up on either machine for it to work.

Rsync may be problematic on Windows machines. https://www.ubackup.com/windows-10/rsync-windows-10-1021.html

In Windows, rsync will require the computer be using WSL. However OpenFOAM doesn't run on Windows natively either. It also requires WSL. So I don't see this being an issue for either the local computer or the remote computer as they'll both need WSL in order to run OpenFOAM.

FYI, OpenFOAM typically runs much slower under WSL than it does on natively on Linux. That might be another reason for CfdOF users to want to do their processing on a remote computer, running Linux instead of Windows.

As I said previously, I'm not a Windows guy.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

@linuxguy123 What is the benefit of introducing paramiko as an extra 3rd party dependency ? (I'm asking because dependencies create more work for maintainers)

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

@linuxguy123 What is the benefit of introducing paramiko as an extra 3rd party dependency ? (I'm asking because dependencies create more work for maintainers)

It essentially makes the ssh connection transparent by handling all the complexity. I could do the project without it.

I understand your concern. Let me test a homemade ssh session wrapper and I'll get back to you on that.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

I mean, if you want to use it as a proof of concept and then later use a homemade ssh wrapper...that would be cool. The less external dependencies the better.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#quoting-code

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#quoting-code

And when I use triple ticks it still inprets the # char and reformats the code. How do I avoid this ?

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

Test:

#32

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I mean, if you want to use it as a proof of concept and then later use a homemade ssh wrapper...that would be cool. The less external dependencies the better.

From what I understand, paramiko implements an ssh client for a python app to establish a permanent ssh session with the remote computer. One then sends commands to the ssh session to execute on the remote computer.

I do not think that functionality can be accomplished with os.system() or subprocess(). I was hoping that I could run an ssh command with subprocess() and it would remain persistent as long as the ssh command was running. I was hoping to interact with the ssh session via stdin, stdout and stderr into the sub processes.

However, it appears that the ssh process blocks subprocess from receiving or sending text to the remote computer.

Here is my test code.

#!/usr/bin/python
import subprocess
import os

# Say Hi.
print("\nStarting ssh-test.py")

#Test os.system locally
#print("Testing os.system locally")
#os.system('uname -a')

# Start an ssh session with the remote computer
# The remote computer is goliath
# The remote user is me

print('Starting ssh session with the remote computer')

# Approach 1
#subprocess.run(["/usr/bin/ssh","me@goliath"], input="password\n", text=True)
# result: Pseudo-terminal will not be allocated because stdin is not a terminal.

# Approach 1A
# subprocess.run(["/usr/bin/ssh","me@goliath"], input=b"password\n")
# result: same as above.

# Approach 2
#sshSession = subprocess.Popen(["/usr/bin/ssh me@goliath"],  # or ["/usr/bin/ssh", "me@goliath"] if shell=False
#                                stdin = subprocess.PIPE,
#                                stdout = subprocess.PIPE,
#                                stderr = subprocess.PIPE,
#                                shell=True) # also test with shell=False

#print ("stdout:", sshSession.stdout.readlines())
#print ("stderr:", sshSession.stderr.readlines())
#sshSession.stdin.writeline("uname -a\r")
#print (sshSession.stderr.readline())
#print (sshSession.stdout.readline())

#sshSession.stdin.writeline("password\r")
#sshSession.stdin.writeline("uname -a\r")
#print (sshSession.stderr.readline())
#print (sshSession.stdout.readline())
#result: ssh seems to block input from subprocess.stdin.write()

# Approach 3
#sshSession = subprocess.Popen(['/usr/bin/ssh', "me@goliath"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
#reply = sshSession.communicate('password\n')[0] # all variants of this ignore password as an input to the ssh login.
#reply = sshSession.communicate('')[0]
#print(reply)
# result: this accepts the password from the command line.  Can't pass it into the subprocess ?  subprocess also quits as soon as the
# login is successful

print("Exiting...")
print("Bye!\n")

Resources:
https://docs.python.org/3/library/subprocess.html
https://stackoverflow.com/questions/8980050/persistent-python-subprocess
https://stackoverflow.com/questions/48752152/how-do-i-pass-a-string-in-to-subprocess-run-using-stdin-in-python-3
https://stackoverflow.com/questions/8475290/how-do-i-write-to-a-python-subprocess-stdin

https://www.bogotobogo.com/python/python_ssh_remote_run.php <-Note that in all the examples the user has to input the password on the command line. ssh no longer allows the password to be passed in on the command line as an argument. And from What I can tell ssh blocks sending the password in using stdin. This is probably by design to prevent people from hacking into a computer programatically via ssh.

In the absence of getting some version of the above code working, ie creating a persistent ssh session, I will need to use paramiko or a library called fabric.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

What is the easiest way for me to run my version of CfdOF in my current FreeCAD installation ? And debug it using VS Code ?

Is there a "best practices" doc somewhere for FreeCAD workbench developers ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

To add a second tab to CfdOF preferences for the remote computing settings, does one call addReferencePage() with the second tab (page) ? Or how is another tab added to preferences ?

"Make sure the addPreferencePage() method is called only once, otherwise your pref page will be added several times" https://wiki.freecadweb.org/Workbench_creation

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I figured out a way to run commands on a remote computer via ssh using subprocess(). I'll update this thread with the details in the near future.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

It's going to be interesting doing this all in QProcess !

But there is this: https://github.com/sandsmark/QSsh

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

I like the idea. We have always had something like this in mind to support compute clusters on which most serious CFD ends up being done, in my experience. In that case you have the additional factor of schedulers to interact with, but that can be a future addition. However, in that vein I would prefer it if we interact with the program running on the remote machine 'at arms length', with the output data obtained by looking at its log files and output files rather than the controlling process directly owning the processes it creates via ssh - because on compute clusters you don't get to create/own the process directly.

  1. Add a Remote tab to the CfdOF Preferences GUI for the remote connection parameters and set up. The Remote tab would have a checkbox to allow the use of a remote computer and fields for the remote hostname and username on the remote computer as well as a way to test it the connection. Ie can one successfully invoke an ssh session with the remote computer ?

Sounds good.

The Remote tab will also allow setting up OpenFOAM, gmsh, cfmesh and Hisa on the remote machine, just as how it happens on the local computer right now.

Great, but perhaps more of a 'nice to have' since the remote machine may not be fully under your control. Presently in CfdOF we write the output so that it can run on any supported OpenFOAM version (i.e. it is not tailored to the version currently selected), with this sort of situation in mind (you might want to copy the case and run it on a cluster with a different version installed).

I also want to (eventually) handle the case of the workstation going to sleep, or being shut down or the user quitting FreeCAD while a remote task is running. I think I can do this by opening a new ssh connection when CfdOF is restarted and reattaching to the existing task. I'm not sure how I'll handle the data that will be missing while the connection is lost. I may have to buffer it on the remote side and redisplay it on the local side when the connection is resumed.

This would be good. For the report functions and residuals etc, the missed data can be harvested from the log and postprocessing files.

Thanks for your interest in taking this on!

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Interesting comments. I'm glad to see others feel it would be a worthwhile addition.

I'll keep the cluster and interacting with the remote processs 'at arm's length' ideas in mind moving forward. Personally, I like watching the residuals and outputs in FreeCAD. Makes it easy to kill the simulation if you see something obviously not working.

Thinking about this further, one could take the "at arms length" to the point that FreeCAD starts the process on the remote machine, launches a little stand alone monitoring app and detaches from the remote process completely. The stand alone app would essentially be the residuals and reporting functions which are matplotlib more than anything. Hmmmm.... It would also be nice to watch the core loads in such an app. Baby steps...

Having taken a closer look at the existing code, I'm going to try to do the ssh calls in QProcess like the existing code does. I'll run a test of this aspect of the project in the near future and report back with my findings.

Another change I'm thinking about making is to add the desired number of cores used as a field in both the local and remote meshing preferences and the CfdOF Mesh window.

When remote processing is used, the cores used will probably be quite different between the local machine and the remote machine. I see that the "Number of Processes" and"Number of Threads" properties are available in the Mesh properties, which was has worked fine until now. But these parameters will be constantly changing going forward so I feel they deserve both preferences and edit boxes on the Mesh window.

Keep the comments coming.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

FYI... there are two aspects of running a remote process in ssh that make things challenging. I'm posting this now so people who work on something similar can learn from my experience and understand my implementation decisions.

The first is the permissions aspect. At first I was going to get the user to input a password whenever an ssh session was needed. This doesn't work because ssh itself doesn't allow the password to be passed in on the command line. And if it did, it would appear in the logs on the remote machine.

The way around the ssh permission problem is to set up an ssh key, which is pretty easy.
On the local machine: ssh-keygen to generate a key. Then run ssh-copy-id user@remote to copy it to the remote machine. Unfortunately this will need to be done outside of FreeCAD. But if the user is knowledgeable enough to set up ssh on a remote computer, s/he can also do this step.

The other aspect is interacting with the remote process. I originally thought I'd be able to open an ssh session with subprocess() and utilize the session repeatedly by sending it commands and receiving the output via the stdin, stdout and stderr attached to the subprocess. However, it turns out that ssh blocks the process that is running within the ssh shell from interacting with subsProcess's stdin, stdout and stderr while the process is running. One gets all the output after the process (and ssh) has exited.

I have not found a way around this particular behaviour, even when using paramika.

However, there is a way to attain the desired functionality, ie having stdout and stderr available to the local machine, while the process runs in ssh. One can achieve this by piping the output of the remote process to files on the remote machine and then periodically reading said files from the local machine. It's not as nice as how things run locally, but will still work.

Having said all this, I have not tested running ssh within QProcess. I'm assuming that QProcess has no magical unblocking properties when using ssh and will have the same behavior.

The present code launches all external processes (meshing and OpenFOAM simulations) with QProcess. I will endeavor to do this as well because 1) I want to keep the code the same as much as possible and 2) it appears to work well. If QProcess acts as I think it will with ssh, I may write a wrapper class around QProcess (remoteQProcess?) that hides the complexity of the remote stdout and stderr files and makes it act just like the files are running locally.

Thoughts ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

The other way to achieve remote processing from FreeCAD would be to write a small server app that sat on the remote machine. This app would call the mesher and OpenFOAM from the remote machine and echo the results back to the local machine. In fact, this server could be installed on the local machine and used to run things there as well.

I suspect that writing that app would be non trivial due to the number of platforms (Linux, Windows, MacOC, etc) that people will have on their remote machines and installing it, setting up the firewall, etc. on the remote machine.

ssh is universally available on all platforms, or nearly so. And it's secure and easy to set up.

Having said all this, I'm open to discussion on the remote approach.

from cfdof.

mmcker avatar mmcker commented on May 18, 2024

Have you considered if mosh will help? (keep alive an ssh session)

https://github.com/mobile-shell/mosh

Also, I wouldn't immediately discard using wsl based on speed. I found wsl to be very fast - however, you must ensure you understand how to access the filesystems. https://learn.microsoft.com/en-us/windows/wsl/filesystems. My docker experiments (which uses wsl) seem to have the same speed for wsl as native performance.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Have you considered if mosh will help? (keep alive an ssh session)

https://github.com/mobile-shell/mosh

The problem isn't keeping the session alive. The issue is interacting with the session through stdout and stderr while a command is running in the session. For example, OpenFOAM may run for hours in an ssh session. We need/want the output of stdout and stderr for OpenFOAM while it is running. So far I've found that subProcess() will only give stdout and stderr after the process (OpenFOAM in this case) has completed.

Furthermore, I have not been able to send commands to an ssh session run in subProcess() using stdin. Others on the Internet have experienced the same as I have. If anyone knows how to do this, please chime in.

Also, I wouldn't immediately discard using wsl based on speed. I found wsl to be very fast - however, you must ensure you understand how to access the filesystems. https://learn.microsoft.com/en-us/windows/wsl/filesystems. My docker experiments (which uses wsl) seem to have the same speed for wsl as native performance.

I'll stick to plain Linux, thank you. I don't run Windows and have no need for WSL.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Update: I tested QProcess today running commands within ssh. It appears to work perfectly.

Running the mesh and OpenFOAM processes remotely might be as simple as copying the files over and then running the same commands prefixed with "ssh". With QProcess, Stdout and stderror of the command being run is available to the calling program the same whether the command is run locally or under ssh. This is very impressive. I was not able to achieve this with subProcess().

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I agree, and I wasn't suggesting to lose this functionality, but (as you also mentioned) to monitor the log files rather than remaining attached to the process stdout. This is already how the 'probes' reporting function works - by watching the relevant files in postProcessing/... .

I haven't looked closely at that code. That approach is interesting because as per my testing today, QProcess is very good about passing stdout and stderr to the calling program. Both when processes run locally and when they run remotely under ssh.

So why is the probe reporting done like that ? Why isn't stdout and stderror from QProcess used ?

I appreciate there is an elegance in keeping everything the same save for the process running through ssh. However every experience I have had of shared compute resources are machines with schedulers where you don't have the option of running heavyweight apps directly. Of course, you are free to take whatever approach works for you, but I do think there would be a lot of benefit in keeping that use case in mind.

Could you give me more information on this use case ? Not saying I will or will not handle it but the more I understand the better.

As far as I understand with cluster computing a single call starts the cluster processing the desired command and the results from the command are passed back via stdout and stderr as if the command was being run on a single machine. In fact, the residuals for each iteration in OF need to be passed back to the calling code so they can be examined before the next iteration is started.

If this is the case, the code I'm working on should work with a cluster setup as well.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Here is the code I tested with. Change mainwindow-cleaned.py to mainwindow.py before running.

QProcess Test.tar.gz

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

If you look in CfdConsoleProcess.py, the process is set up the same as how I've set up the process in my test, ie there are handlers for stdout and stderr.

def __init__(self, finished_hook=None, stdout_hook=None, stderr_hook=None):
        self.process = QProcess()
        self.finishedHook = finished_hook
        self.stdoutHook = stdout_hook
        self.stderrHook = stderr_hook
        self.process.finished.connect(self.finished)
        self.process.readyReadStandardOutput.connect(self.readStdout)
        self.process.readyReadStandardError.connect(self.readStderr)
        self.print_next_error_lines = 0
        self.print_next_error_file = False

There is no evidence of peeking into a locally cached stdout or stderr file on the computer.

Running a process remotely may be as easy as copying the files to the remote machine and prefixing the actual call with "ssh".

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024
def start(self, cmd, env_vars=None, working_dir=None):
        """ Start process and return immediately """
        self.print_next_error_lines = 0
        self.print_next_error_file = False
        env = QtCore.QProcessEnvironment.systemEnvironment()
        if env_vars:
            for key in env_vars:
                env.insert(key, env_vars[key])
        removeAppimageEnvironment(env)
        self.process.setProcessEnvironment(env)
        if working_dir:
            self.process.setWorkingDirectory(working_dir)
        if platform.system() == "Windows":
            # Run through a wrapper process to allow clean termination
            cmd = [os.path.join(FreeCAD.getHomePath(), "bin", "python.exe"),
                   '-u',  # Prevent python from buffering stdout
                   os.path.join(os.path.dirname(__file__), "WindowsRunWrapper.py")] + cmd
        FreeCAD.Console.PrintLog("CfdConsoleProcess running command: {}\n".format(cmd))
        self.process.start(cmd[0], cmd[1:])

For a remote run, change self.process.start(cmd[0], cmd[1:]) to:

remoteCmd = ["ssh", "me@server"]
remoteCmd.append(cmd) 
self.process.start(remoteCmd[0], remoteCmd[1:] )

Am I missing something ?

I will test this with OpenFOAM shortly.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

I agree, and I wasn't suggesting to lose this functionality, but (as you also mentioned) to monitor the log files rather than remaining attached to the process stdout. This is already how the 'probes' reporting function works - by watching the relevant files in postProcessing/... .

I haven't looked closely at that code. That approach is interesting because as per my testing today, QProcess is very good about passing stdout and stderr to the calling program. Both when processes run locally and when they run remotely under ssh.

So why is the probe reporting done like that ? Why isn't stdout and stderror from QProcess used ?

The code is in CfdRunnableFoam.py, in process_output()

It is done this way because that's where the output is written by OpenFOAM. It doesn't go into the log on stdout. There will likely be other monitoring functions in future that will be the same.

I appreciate there is an elegance in keeping everything the same save for the process running through ssh. However every experience I have had of shared compute resources are machines with schedulers where you don't have the option of running heavyweight apps directly. Of course, you are free to take whatever approach works for you, but I do think there would be a lot of benefit in keeping that use case in mind.

Could you give me more information on this use case ? Not saying I will or will not handle it but the more I understand the better.

A command is issued on the cluster to queue the program for future execution. When it reaches the top of the queue, it is run entirely detached, with stdout and stderr being redirected to files. Other commands can be issued to kill the job or query its running status. And example of such a scheduler is Slurm.

As far as I understand with cluster computing a single call starts the cluster processing the desired command and the results from the command are passed back via stdout and stderr as if the command was being run on a single machine. In fact, the residuals for each iteration in OF need to be passed back to the calling code so they can be examined before the next iteration is started.

Not sure if I'm misunderstanding ... but they don't need to be examined by calling code before the next iteration is started. The output on stdout is just for informational purposes and the computation continues regardless.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

For a remote run, change self.process.start(cmd[0], cmd[1:]) to self.process.start("ssh", cmd)

Am I missing something ?

I would just worry that the remote process would get taken out if the connection went down.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

The code is in CfdRunnableFoam.py, in process_output()

Thanks for the reply. I'll look at the code and comment later.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I want to set up a tabbed Preference page for the CfdOF workbench. I'm unsure how to do this. I'm working in Python with Qt-Creator.

My best guess is to set up the main preference page as an empty QTabWidget and install that page with FreeCADGui.addPreferencePage() in InitGui.py.

Then create separate pages for each of the tabs in the Preference section for my workbench. Then add the pages to the the QTabwidget in the init() call for the main Preference page.

Am I on the right track ?

Is there a workbench that has a tabbed Preference page that I could use as a reference ?

Approaches that don't work:

  1. Making the Preference page a QTabWidget. When I did this, I got the error message: CfdPreferencePage is not a preference page. No other error messages. From this I assume that the preference page must be a QWidget, ie form.

  2. Adding the preference pages by calling `FreeCADGui.addPreferencePage("/path/to/myUiFile.ui","CfdOF") twice with 2 different preference page UI files. When I did this, only the first page appears.

  3. Adding a Tab Widget to a QWidget Preference Page. When I did this, I got this:

Preference Page with tabs within tabs

While I could make that work, it isn't the desired intent.

So how does one set up a tabbed Preference page for a workbench ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I did a little digging and found this in src/Gui/DlgPreferencesImp.cpp:

/**
 * Create a new preference page called \a pageName on the group tab \a tabWidget.
 */
void DlgPreferencesImp::createPageInGroup(QTabWidget *tabWidget, const std::string &pageName)
{
    PreferencePage* page = WidgetFactory().createPreferencePage(pageName.c_str());
    if (page) {
        tabWidget->addTab(page, page->windowTitle());
        page->loadSettings();
        page->setProperty("GroupName", tabWidget->property("GroupName"));
        page->setProperty("PageName", QVariant(QString::fromStdString(pageName)));
    }
    else {
        Base::Console().Warning("%s is not a preference page\n", pageName.c_str());
    }
}

It appears that the only object that can be used as a preference page is a page, ie QWidget.

It also appears that this routine will add the page to tab but will not add a second page to another tab.

It would be really nice if a workbench could have multiple preference pages and if this routine would add each of them as tabs. Or if the routine could accept a QTabWidget in place of its own Tab Widget and let the user then connect his pages to the tabs on his Tab Widget.

In the mean time, the work around is to add a preference page that has tabs on it and implement them on that page. Such an implementation will appear as the window attached above.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

This the code that calls createPageInGroup:

/**
 * If the dialog is currently showing and the static variable _pages changed, this function 
 * will rescan that list of pages and add any that are new to the current dialog. It will not
 * remove any pages that are no longer in the list, and will not change the user's current
 * active page.
 */
void DlgPreferencesImp::reloadPages()
{
    // Make sure that pages are ready to create
    GetWidgetFactorySupplier();

    for (const auto &group : _pages) {
        QString groupName = QString::fromStdString(group.first);

        // First, does this group already exist?
        QTabWidget* tabWidget = nullptr;
        for (int tabNumber = 0; tabNumber < ui->tabWidgetStack->count(); ++tabNumber) {
            auto thisTabWidget = qobject_cast<QTabWidget*>(ui->tabWidgetStack->widget(tabNumber));
            if (thisTabWidget->property("GroupName").toString() == groupName) {
                tabWidget = thisTabWidget;
                break;
            }
        }

        // This is a new tab that wasn't there when we started this instance of the dialog: 
        if (!tabWidget) {
            tabWidget = createTabForGroup(group.first);
        }

        // Move on to the pages in the group to see if we need to add any
        for (const auto& page : group.second) {

            // Does this page already exist?
            QString pageName = QString::fromStdString(page);
            bool pageExists = false;
            for (int pageNumber = 0; pageNumber < tabWidget->count(); ++pageNumber) {
                PreferencePage* prefPage = qobject_cast<PreferencePage*>(tabWidget->widget(pageNumber));
                if (prefPage && prefPage->property("PageName").toString() == pageName) {
                    pageExists = true;
                    break;
                }
            }

            // This is a new page that wasn't there when we started this instance of the dialog:
            if (!pageExists) {
                createPageInGroup(tabWidget, page);
            }
        }
    }
}

It appears that this code should add another page to the group's (CfdOF) tabWidget:

// This is a new page that wasn't there when we started this instance of the dialog:
            if (!pageExists) {
                createPageInGroup(tabWidget, page);

But it checks if the page already exists based not on the filename of the page (ie preferencePage1.ui, preferencePage2.ui) but on the preferencePage.PageName property.

// Does this page already exist?
            QString pageName = QString::fromStdString(page);
            bool pageExists = false;
            for (int pageNumber = 0; pageNumber < tabWidget->count(); ++pageNumber) {
                PreferencePage* prefPage = qobject_cast<PreferencePage*>(tabWidget->widget(pageNumber));
                if (prefPage && prefPage->property("PageName").toString() == pageName) {
                    pageExists = true;
                    break;
                }
            }

If one uses the same page name for the pages being added, they will not be added.

I presume that pages are added by calling FreeCADGui.addPreferencePage("/path/to/myUiFile.ui","CfdOF") with each page.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I figured out how to add a second tab to a workbench's preference page. I'll update this post with how tomorrow.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Comments ?
Remote Processing Tab

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I'm just starting to write the code behind the Remote Preferences Page. My plan is to heavily reuse the code behind the local Preferences Page, but have 2 completely different code bases. Even though a lot of the functionality will be the same. I'm doing this for a few reasons:

  1. I don't want to pollute the code that already works.
  2. There will be enough differences with the remote code that a separate implementation may be justified.
  3. I'm learning as I go.

When I have everything working we can do a diff between the two code bases and see if it justifies merging them into one.

Speak now or forever hold your peace.

Large parts of CfdTools.py is going to get rewritten as well. For 2 reasons:

  1. it uses Python calls that can be used locally but will not be available on the remote host.
  2. it uses subProcess() to do things instead of QProcess(). As previously explained in this thread, subProcess doesn't work with ssh commands, whereas QProcess does.

So I'll probably have a separate source for the remote CfdTools.py as well, ie CfdRemoteTools.py.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I have 2 questions:

  1. Can I assume that all remote hosts (and all local hosts) would run POSIX compliant commands ? MinGW, Windows with WSL, Linux, MacOS ? I'm asking because I think I'll be rewriting a lot of the Python os. stuff that runs locally with POSIX commands so that they'll run on the remote hosts.

  2. What IDE and debugger are people using for Python and how does one set a breakpoint in the workbench code if one is running it from within a pre compiled FreeCAD release, ie 0.20-1.

Can one attach the debugger to the FreeCAD process and is it smart enough to know when it is at a breakpoint within the CfdOF code being worked on ? In which IDE can this be done and how ?

Thanks

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

The About Remote Processing button will display a document for the user to read and use. Understanding remote processing and setting up a remote computer will be a new thing for some CfdOF users. Without good user documentation and testing tools, remote processing will be a nightmare to support and troubleshoot.

This is the start of the document I intent to display. I am writing this document as I write the code for remote processing. Your input is welcome.

Background

Generating large meshes and simulating them in OpenFOAM can take considerable processing time on even the fastest desktop computer. In some cases hours or even days. Meanwhile the FreeCAD workstation machine is tied up and often not very responsive because the CPU core loads are high and the memory bandwidth is almost entirely consumed. The storage device will also be accessed frequently, further slowing down the local machine.

A better way to handle large meshing and simulation tasks is to off load them to a second (remote) computer, leaving the FreeCAD workstation almost unhindered while they run. Furthermore the remote computer can be optimized to run mesh and simulation loads much faster than a desktop machine might be.

The CfdOF is now capable of allow the user to use a remote computer to process meshes and run OpenFOAM simulations. It does this by using the Secure SHell (ssh) command to run the mesher and OpenFOAM on the remote computer. A few things are required to accomplish this:

  1. The remote computer must be accessible to the local computer via a network connection.
  2. ssh must be installed on the remote computer.
  3. The FreeCAD user must have access to a user account on the remote computer
  4. an ssh key must be generated and stored on the remote computer such that the FreeCAD user can connect to the remote computer using ssh without using a password.
  5. all the relevant meshing and simulation software must be installed on the remote computer.
  6. the remote computer must support POSIX file system commands such as ssh, rsync, etc.

The purpose of the Remote Computing tab in CfdOF preferences is to help the user set up and test each of the various components listed above.

Terminology

For the purpose of this discussion the FreeCAD workstation will be referred to as the local computer. The terms "workstation", "FreeCAD workstation" and local computer can be used interchangeably.

Also, the terms computer and host will also be used interchangeably. Strictly speaking a computer is any computing device whereas a host is a computer connected to a network that can be reached by its IP address or hostname. In this discussion we assume that all computers are connected to a network and have an IP address and a hostname.

About ssh

"The Secure Shell Protocol (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network." https://en.wikipedia.org/wiki/Secure_Shell As such it will allow a FreeCAD user to run meshing and OpenFOAM applications on the remote computer from accross the network, without actually being at the remote computer.

The remote computer can be any computer capable of running ssh and the meshing and OpenFOAM applications that supports POSIX filesystem commands. Generally this is any computer running Linux, MacOS or Windows with WSL or MinGW installed. Hardware wise the remote computer could be almost anything - a laptop, a desktop PC, a server or a cloud computer such as an AWS instance.

Remote Computer Setup

In order to allow CfdOF to use the remote computer for remote processing, it must be set up as follows:

Step 1) Log into the remote computer and verify that ssh is installed and running. On a linux computer one can do this with:

$ ps aux| grep sshd
root 1240 0.0 0.0 14024 8436 ? Ss 07:38 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

Step 2) Log into the remote computer via ssh from the local computer. On a linux computer one can do this from a console on the workstation with the following command:

$ssh @

Where username is the name of the user on the remote computer, not the FreeCAD workstation and IP address is the IP address of the remote computer. One can also use the hostname if the DNS server used on your network supports hostname resolution, ie dnsmasq is enabled. For example, if the remote computer's hostname is goliath and goliath's IP address is 192.168.2.159, one can do either of the following:

$ssh [email protected]
$ssh me@goliath

If an ssh key is not set up for the user on the remote computer, ssh will ask for the password for the user account on the remote machine. This password is not to be confused with the password used on the FreeCAD workstation.

In either case the host computer should respond with a ssh shell in which you can issue commands to run on the remote computer.

me@goliath$ ls -l
total 0
drwxr-xr-x. 1 me me 20 Feb 14 2022 Desktop
drwxr-xr-x. 1 me me 0 Feb 14 2022 Documents
drwxr-xr-x. 1 me me 42 Feb 14 2022 Downloads
drwxr-xr-x. 1 me me 0 Feb 14 2022 Music
drwxr-xr-x. 1 me me 28 Feb 14 2022 openfoam
drwxr-xr-x. 1 me me 0 Feb 14 2022 Pictures
drwxr-xr-x. 1 me me 0 Feb 14 2022 Public
drwxr-xr-x. 1 me me 0 Feb 14 2022 Templates
drwxr-xr-x. 1 me me 0 Feb 14 2022 Videos

To exit an ssh session, type exit:

$exit

Step 3) Set up ssh keys.

ssh keys are used to allow the use of ssh without promptng the user for a password. Remote computing in CfdOF requires that ssh be used with keys. Each workstation will need its own key for each remote computer that it uses, if it uses more than one remote computer.

To generate an ssh key for the local computer, use the following command on a local console shell on the workstation computer: (Do not run this from within an ssh session !)

$ssh-keygen

Do not use a passphrase. TODO: explain this.

To copy the key over to the remote server, run this command on a local console on the workstation computer:

ssh-copy-id @

It will prompt you for the password of your user account on the remote machine. It will then copy the ssh key you generated on the workstation over to the remote computer.

You should now be able to login to an ssh session on the remote computer without being prompted for a password.

ssh @

If you are prompted for a password when you log in your ssh key is not set up. You'll need to remedy this before proceeding further.

Note: ssh requires a unique key for every host/remote compute pair. ssh identifies computers by their hostname and IP address. If you generate your ssh key using an IP address and the IP address of either the local machine or the host changes, you will have to generate a new ssh key for the new address pair. To avoid this problem, use fixed IP addresses whenever possible or use hostnames instead of IP addresses.

Likewise if you change the remote computer you use you'll have to copy the generated ssh key to the new remote computer with:

$ssh-copy-id

Once you can reliably log into an ssh session on the remote computer from the local computer using an ssh key the remote computer is ready to be used by CfdOF for remote processing.

CfdOF Remote Processing Setup

Once ssh is set up on the remote computer, one can setup the rest of remote computing from the Cfdof Remote Computing preferences page. (FreeCAD->Edit->Preferences->CfdOF->Remote Computing)

Step 1) Click "Enable Remote Computing

Step 2) Input the host name or IP address of the remote computer to be used for remote processing.

Step 3) Run "Ping Remote Host" to verify that the hostname or IP address is correct and that the local computer can reach the remote computer over the network. You should see " pinged successfully in the Output field below.

Step 4) Input the username of the user account to be used on the remote computer.

Step 5) Run "Test SSH" to verify that ssh has been set up correctly on the remote computer. You should see "ssh verified with " in the Output field below.

Step 6) Run remote host dependency checker.

The output of this process will show the user what meshing and OpenFOAM applications have and haven't been installed on the remote computer and where they are if they have been installed.

To be continued...

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Is there a way to reliably reload a workbench in FreeCAD without restarting FreeCAD?

When I make a change to my code, I'm currently having to restart FreeCAD to load the changed code and test it. Is there a way to reload the workbench such that I don't have to restart FreeCAD ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Not sure if I'm misunderstanding ... but they don't need to be examined by calling code before the next iteration is started.

By "calling code", I mean the code that started the process on the computer that is running the process.

In the cluster situation the individual cluster host results are reassembled back to the "calling code", wherein the residual is examined before the next iteration.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I would just worry that the remote process would get taken out if the connection went down.

In Linux one can set up the remote process to continue running even if the ssh session shuts down. One can then reconnect to the remote process with a new ssh session. I'll update this post with details on how this is done later. I've done this with my own OpenFOAM remote processing.

We can use this technique to allow CfdOF to reconnect to the remote process if it loses connection or if the FreeCAD user exits FreeCAD. It will be a bit tricky to figure out where FreeCAD was at when it issued the process.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

@linuxguy123 check out FreeCAD/FreeCAD-addons#159

What is the library name to reload CfdOF ?

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

@oliveroxtoby do you mind weighing-in ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

@linuxguy123 check out FreeCAD/FreeCAD-addons#159

Is there a (re)load(workbench) that one could use to reload CfdOF without restarting FreeCAD ?

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

@linuxguy123 check out FreeCAD/FreeCAD-addons#159

What is the library name to reload CfdOF ?

You need to reload the specific python module or modules that you have changed. There are a few of the importlib commands scattered in CfdOF to do this which I put in as I needed them, but it's not comprehensive. @howetuft's solution is the best way to go, but would still need to be implemented in CfdOF.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

@howetuft's solution is the best way to go, but would still need to be implemented in CfdOF.

Should we open a new feature request for this ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Update
I'm still working on this project. Just busy this week. I'll be sharing an update in the near future.

from cfdof.

adrianinsaval avatar adrianinsaval commented on May 18, 2024

assuming this isn't dead, will it support using https://cfd.direct/cloud/?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

assuming this isn't dead, will it support using https://cfd.direct/cloud/?

Not sure yet. I'd have to have a closer look.

There is an issue with the CfdOF Preference pages not fitting well on 1920x1080 displays. See attached.

I'm not going to address this now.

Doesn't fit on 1920x1080

Doesn't fit on 1920x1080-2

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Remote Processing Preferences

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

meshing panel

The mesh case can be written and run locally or remotely.

All display/visualization is done locally, by copying the completed mesh back from the remote machine.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

meshing panel2

meshing processes and threads

Ignore the number of threads parameter. It isn't used anymore. It's a relic of past testing and I don't know how to get it out of the data. The number of threads per process is setable for local and remote individually, in case the users wants to do something different on each machine.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I've run into an issue - ./Allmesh runs fine locally, but the exact same mesh case fails on the remote machine. Why ?

The error on the remote run is:

--> FOAM FATAL IO ERROR: (openfoam-2206 patch=221104)
Unknown objectRefinement type insideSurface

Valid objectRefinement types :
[default: objectRefinement]5(box cone hollowCone line sphere)

file: system/meshDict.objectRefinements.MeshRefinement at line 26 to 28.

    From static Foam::autoPtr<Foam::Module::objectRefinement> Foam::Module::objectRefinement::New(const Foam::word&, const Foam::dictionary&)
    in file utilities/octrees/meshOctree/refinementControls/objectRefinement/newObjectRefinement.C at line 56.

FOAM exiting

My code builds the mesh case on the local machine and then copies it to the remote machine. The only difference in the build cases is the number of threads and processors is set differently for each.

Both machines are running OpenFOAM-2206, installed from the same source. Why would ./Allmesh run differently on one machine than the other ?

Is there anything besides the meshCase folder that needs to be copied to the remote machine to have ./Allmesh run properly ?

See attached session files below.

runMeshRemote.txt
runMeshLocal.txt

Update

I found the problem. The machines have different versions of cfMesh installed. I'll update cfMesh on the remote machine and report back.

The local machine has cfMesh-CfdOF (cfMesh 1.1.2) 1.19 and it works.

I didn't implement the code to install cfMesh on the remote machine. I guess it is time to do that. It also appears that I should use more stringent cfMesh version checking. This is what happens when you eat your own dogfood !

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

This project is coming along very well. Remote meshing and FOAMing should be operational with Linux local and remote computers shortly. From there "we" can add functionality for other local/remote OS combinations and the use of docker.

For me, remote processing is going to dramatically improve my CFD work flow. It will be a night and day difference. Moving files back and forth between my workstation and my CFD server was extremely tedious. It's fantastic to just press "Write mesh case on remote host" and it is over there, ready to run ! That is a game changer for me.

My CFD server is an AMD Epyc 7601 with 32 cores and 8 memory channels. It meshes about 6x faster than my present workstation (AMD 5900X) and runs FOAM about 3.5x faster. And my workstation doesn't get tied up while doing this work ! I might upgrade my CFD server to a dual EPYC 7002 configuration which would be even faster.

In the past I've only used the CFD server for large jobs because of the tedium of moving the files back and forth. I had scripts to do this, but it was still a hindrance. With remote processing built into CfdOF, I'll be using my CFD server all the time.

For me, the combination of FreeCAD, CfdOF and remote processing makes this a very high quality CFD tool. Up there with the likes of the commercial packages, not that I've used them very much.

I thought of another enhancement in CfdOF I would like to have - comparing result "sets". Whenever I'm doing CFD work, I'm trying to optimise geometries. I do this by tweaking the CAD object, running the CFD and checking the results, over and over. I'm thus doing lots of Save As... and then I usually have more than 1 project open at once so I can compare differences between geometries and results. It would be nice if this was streamlined somehow, to make it easier to do.

This isn't something I'm going to work on now or soon, but I'm interested in hearing people's thoughts on how it could be done better. Some sort of "diff" tool to compare the results of two or more simulations ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

This is how I installed cfMesh on the remote host.

#**********************************************************************************************
       def remoteDownloadInstallCfMesh(self):

        #TODO: this routine doesn't clean up after itself if it fails
        # Nor does it check for a full or partial build
        # If the user reruns the build after fully or partially building previously
        # this routine will fail.

        # Get the username and hostname for the remote host
        prefs = CfdTools.getPreferencesLocation()
        remote_user = FreeCAD.ParamGet(prefs).GetString("RemoteUsername", "")
        remote_hostname =FreeCAD.ParamGet(prefs).GetString("RemoteHostname", "")
        ssh_prefix = "ssh -tt " + remote_user + "@" + remote_hostname + " "
        working_dir = remote_hostname =FreeCAD.ParamGet(prefs).GetString("RemoteOutputPath", "")

        self.consoleMessage("Installing cfMesh on the remote host...")

        # create a dir to download the CfMesh source files to
        # cfMesh is installed in the user's home directory, not the output directory

        command = "EOT\n"
        #command += "cd " + working_dir + "\n"
        command += "mkdir cfMesh" + "\n"
        command += "exit \n"
        command += "EOT"

        try:
            command_result = CfdTools.runFoamCommand(ssh_prefix + "<< " + command)[0]
            working_dir += "/cfMesh"

            print("Created cfMesh install dir: " + working_dir)
            self.consoleMessage("Created cfMesh install directory " + working_dir)
        except:
             self.consoleMessage("Could not create an install directory on the remote host.")
             return

        # download the cfMesh source files
        command = "EOT\n"
        command += "cd " + working_dir + "\n"
        command += "wget "  + self.form.le_cfmesh_url.text() + "\n"
        command += "exit \n"
        command += "EOT"

        try:
             command_result = CfdTools.runFoamCommand(ssh_prefix + " << " + command)[0]
             self.consoleMessage("Downloaded cfMesh source files")
        except:
             self.consoleMessage("Could not download cfMesh source files.")
             return

        # unzip the downloaded file
        # TODO: this assumes the downloaded archive is called "download".  Which might not always be the case.
        # Get name of the downloaded file from the URL and use that filename in this command
        command = "EOT\n"
        command += "cd " + working_dir + "\n"
        command += "unzip download \n"
        command += "exit \n"
        command += "EOT"

        try:
             command_result = CfdTools.runFoamCommand(ssh_prefix + " << " + command)[0]
             self.consoleMessage("Unzipped cfMesh source files")
        except:
             self.consoleMessage("Could not unzip cfMesh source files.")
             return

        # run the wmake process
        # TODO: add the number of processes to use on the build with export WM_NCOMPPROCS=`nproc`;
        # TODO: add logging wiht ./Allwmake  ->  log.Allwmake
        # TODO: delete the previous log before starting the new build
        # Executing: { rm -f log.Allwmake; export WM_NCOMPPROCS=`nproc`; ./Allwmake 1> >(tee -a log.Allwmake) 2> >(tee -a log.Allwmake >&2); } in $WM_PROJECT_USER_DIR/cfmesh-cfdof

        command = "EOT\n"
        command += "cd " + working_dir + "/cfmesh-cfdof \n"
        command += "./Allwmake \n"
        command += "exit \n"
        command += "EOT"

        self.consoleMessage("Starting cfMesh build on remote host.")
        self.consoleMessage("This takes a bit of time.  Please wait.")
        try:
             command_result = CfdTools.runFoamCommand(ssh_prefix + " << " + command)[0]
             self.consoleMessage("Successfully built and installed cfMesh.")
        except:
             self.consoleMessage("Could not build cfMesh.")
             return

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I can't get CfdConsoleProcess.waitForStarted() to be true after starting my meshing process in a proxy. But my meshing process works with CfdRunFoamCommand outside of a proxy.

Is this a race condition ?

Here is the code that works using CFDRunFoamCommand() outside of a proxy.

 # Get the username and hostname for the remote host
        prefs = CfdTools.getPreferencesLocation()
        remote_user = FreeCAD.ParamGet(prefs).GetString('RemoteUsername', '')
        remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteHostname', '')

        # create the ssh connection command
        ssh_prefix = 'ssh -tt ' + remote_user + '@' + remote_hostname + ' '

        # Get the working directory for the mesh
        working_dir = remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteOutputPath', '')

        # create the command to do the actual work 
        command = 'EOT \n'
        command += 'cd ' + working_dir + '/meshCase \n'
        command += './Allmesh \n'
        command += 'exit \n'
        command += 'EOT'
        command = ssh_prefix + ' << '  + command

        self.consoleMessage("Starting remote meshing...")
        try:
            CfdTools.runFoamCommand(command)
            print("Remote meshing is complete.")
            self.consoleMessage("Remote meshing is complete.")
        except Exception as error:
             self.consoleMessage("Error meshing on remote host: " + str(error))

Here is the code that uses CfdConsoleProcess and proxy that doesn't work:

# run on remote host
            else:
                 # Get the username and hostname for the remote host
                 FreeCADGui.doCommand("prefs = CfdTools.getPreferencesLocation() \n" +
                                       "remote_user = FreeCAD.ParamGet(prefs).GetString('RemoteUsername', '')\n" +
                                       "remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteHostname', '')")

                 # create the ssh connection command
                 FreeCADGui.doCommand("ssh_prefix = 'ssh -tt ' + remote_user + '@' + remote_hostname + ' '")

                 # Get the working directory for the mesh
                 FreeCADGui.doCommand("working_dir = remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteOutputPath', '')")

                 # create the command to do the actual work
                 FreeCADGui.doCommand("command = 'EOT \\n' \n" +
                                      "command += 'cd ' + working_dir + '/meshCase \\n' \n" +
                                      "command += './Allmesh \\n' \n" +
                                      "command += 'exit \\n' \n" +
                                      "command += 'EOT' \n")
                 FreeCADGui.doCommand("command = ssh_prefix + ' << '  + command + '\\n'")

                 FreeCADGui.doCommand("print(command)")

                 FreeCADGui.doCommand("proxy.running_from_macro = True")
                 self.mesh_obj.Proxy.running_from_macro = False

                 FreeCADGui.doCommand("if proxy.running_from_macro:\n" +
                                      "  mesh_process = CfdConsoleProcess.CfdConsoleProcess()\n" +
                                      "  mesh_process.start(command)\n" +
                                      "  mesh_process.waitForFinished()\n" +
                                      "else:\n" +
                                      "  proxy.mesh_process.start(command)")


            if self.mesh_obj.Proxy.mesh_process.waitForStarted():
                # prevent user form running a second instance
                self.form.pb_run_mesh.setEnabled(False)
                self.form.pb_run_remote_mesh.setEnabled(False)

                # enable/disable the correct buttons
                if not remotely:
                    self.form.pb_stop_mesh.setEnabled(True)
                    self.form.pb_write_mesh.setEnabled(False)
                    self.form.pb_check_mesh.setEnabled(False)
                    self.form.pb_paraview.setEnabled(False)
                    self.form.pb_load_mesh.setEnabled(False)
                else:
                    self.form.pb_stop_remote_mesh.setEnabled(True)
                    self.form.pb_write_remote_mesh.setEnabled(False)
                    self.form.pb_check_mesh.setEnabled(False)
                    self.form.pb_paraview.setEnabled(False)
                    self.form.pb_load_mesh.setEnabled(False)
                self.consoleMessage("Mesher started ...")
            else:
                self.consoleMessage("Error starting meshing process", 'Error')

Here is the code that is executing in the Python console:

>>> from CfdOF.Mesh import CfdMeshTools
>>> from CfdOF import CfdTools
>>> from CfdOF import CfdConsoleProcess
>>> cart_mesh = CfdMeshTools.CfdMeshTools(FreeCAD.ActiveDocument.Cut_Mesh)
>>> proxy = FreeCAD.ActiveDocument.Cut_Mesh.Proxy
>>> proxy.cart_mesh = cart_mesh
>>> cart_mesh.error = False
>>> prefs = CfdTools.getPreferencesLocation() 
>>> remote_user = FreeCAD.ParamGet(prefs).GetString('RemoteUsername', '')
>>> remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteHostname', '')
>>> ssh_prefix = 'ssh -tt ' + remote_user + '@' + remote_hostname + ' '
>>> working_dir = remote_hostname =FreeCAD.ParamGet(prefs).GetString('RemoteOutputPath', '')
>>> command = 'EOT \n' 
>>> command += 'cd ' + working_dir + '/meshCase \n' 
>>> command += './Allmesh \n' 
>>> command += 'exit \n' 
>>> command += 'EOT' 
>>> 
>>> command = ssh_prefix + ' << '  + command + '\n'
>>> print(command)
>>> proxy.running_from_macro = True
>>> if proxy.running_from_macro:
>>>   mesh_process = CfdConsoleProcess.CfdConsoleProcess()
>>>   mesh_process.start(command)
>>>   mesh_process.waitForFinished()
>>> else:
>>>   proxy.mesh_process.start(command)

print(command) is returning this, which is correct. This same command is operating correctly with runFoamCommand outside of a proxy.

ssh -tt me@david  << EOT 
cd /tmp/meshCase 
./Allmesh 
exit 
EOT

The proxy code is failing on if self.mesh_obj.Proxy.mesh_process.waitForStarted():, which is returning false. When that happens it is executing: self.consoleMessage("Error starting meshing process", 'Error') and nothing else.

Why is waitForStarted() failing ?

How can I get a better error message as to what is going on ?

Update

I added time.sleep(2) before checking waitForStarted(). It made no difference.

            time.sleep(2)
            if self.mesh_obj.Proxy.mesh_process.waitForStarted():

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Where does proxy.mesh_process get set up and initialized ? I'm calling proxy.mesh_process.start(command) but haven't set up a mesh_process object ?

It gets set up in init:

self.mesh_obj.Proxy.mesh_process = CfdConsoleProcess(finished_hook=self.meshFinished,
                                                             stdout_hook=self.gotOutputLines,
                                                             stderr_hook=self.gotErrorLines)

The local code runs properly. It has 2 lines of code that the remote code doesn't have:

                 FreeCADGui.doCommand("cmd = CfdTools.makeRunCommand('./Allmesh', cart_mesh.meshCaseDir, source_env=False)")
                FreeCADGui.doCommand("env_vars = CfdTools.getRunEnvironment()")

I made my own command and I don't use env_vars. It runs with runFoamCommand without env_vars.

???? I'm stumped.

How do I read stdout and stderr from the CfdConsoleProcess ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

OF Solver

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

It's pretty quiet in here. I'm looking for comments and feedback as I go. If you see something you don't like, the sooner I hear about it the better.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

It's pretty quiet in here. I'm looking for comments and feedback as I go. If you see something you don't like, the sooner I hear about it the better.

Hi @linuxguy123, I'm the only other active developer at the moment as far as I know. This is a completely voluntary spare-time project for me and as such I don't have a lot of time to devote to it. I'll try to respond where I can but I'm afraid I can't do so with any degree of immediacy. Really appreciate your work though, it's looking good!!

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

It's pretty quiet in here. I'm looking for comments and feedback as I go. If you see something you don't like, the sooner I hear about it the better.

Hi @linuxguy123, I'm the only other active developer at the moment as far as I know. This is a completely voluntary spare-time project for me and as such I don't have a lot of time to devote to it. I'll try to respond where I can but I'm afraid I can't do so with any degree of immediacy. Really appreciate your work though, it's looking good!!

So does that mean you'll let me merge it into CfdOF ?

What happened to the other devs ? They did a lot of work !

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

local host meshing

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Improved the layout. I hate doing layouts !

Added threads and processes.

Added appending the filename to the output directory.

New Remote Host Preferences

from cfdof.

mmcker avatar mmcker commented on May 18, 2024

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Thanks. I'm still working on this, just got busy the last couple weeks.

The Preferences and Meshing page are all done for host profiles. There is still some cleanup to do and there are TODOs in the code, but they work pretty well. The Meshing page has an issue the mesh in a proxy, but works when run directly.

The OF process page works with a single host. I'll convert it to use host profiles shortly, maybe this weekend.

There isn't a lot of work left to do. I need this update for a work project so it will get done in the near future.

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

Maybe make a PR just in case so that it makes it in to the workbench ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

OpenFOAM Analysis Control

from cfdof.

luzpaz avatar luzpaz commented on May 18, 2024

@linuxguy123 any chance for a PR soon ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Let me finish up the analysis control page and then, yes.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Status Update

Remote preferences is working with N host profiles.

I have writing the mesh case and the OF cases to the remote hosts working.

I just got remote meshing and solving to work within a proxy. This stumped me for quite a while.

I need to do some clean up on enabling controls for remote and local operations so that they make sense. And a bit of code cleanup. Then I'll do a PR.

The code was a bit straggly in places before I started. For example, there are several different ways to run a process in the code. The var naming convention is different between the meshing app and the solver app. That sort of thing.

My code is straggly too. Because I wrote this update twice - once for a single remote host and then again for N remote hosts. My code is riddled with comments and TODO items. I prefer to leave them in for now. At some point I'll go back and clean things up.

Nevertheless, the code seems pretty solid - nothing seems to hang if there is an error, for example.

This enhancement only works with Linux remote hosts running these tools directly, not within Docker. It wouldn't take too much to allow the use of Docker on the remote hosts.

I don't even want to think about trying to run this stuff on a Windows remote host. It might not be too bad if the Windows host is running WSL. The big issue with a Windows host is it having ssh and, of course, the file path differences.

I wrote some documentation back in January but I need to update it.

I'll try and get all this work done before the weekend. (March 18th.)

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I cloned CfdOF Master to start this project. Any ideas on how I should do the merge ? Should I create a branch or merge into Master ? Or just send my code to someone to look at/run before I do the merge ?

I'll be working on this all day today.

from cfdof.

oliveroxtoby avatar oliveroxtoby commented on May 18, 2024

Could you create a github pull request (go to 'pull requests' at the top of the page)? It will update automatically as you push new commits to your fork.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

OK. I'll push what I have at the moment so people can start looking at it/ playing with it while I continue to clean it up.

There are little things that need attention yet. No biggies. Things like stopping the solver doesn't kill the process on the server.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I forked Master and added my changed files to it. We can remerge with jaheyns's Master once we are happy with my changes.

https://github.com/linuxguy123/CfdOF

I haven't tested if the new Master works. I'll leave that to you guys. Let me know here how you make out.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Botched the upload. I'm using QtCreator instead of VsCode and it has an issue with its git tool. Standby for another upload.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Uggg... QtCreator's git tool has a bug wherein it asks for a git password when it means to ask for the git username. Now when I do git push it is asking me for the password of an account that doesn't exit. And I can't figure out how to stop it from asking for that git account.

$git push mine
Password for 'https://[email protected]':

Any ideas how to fix this ?

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

User doc thus far. How do I export this post as a markdown file ?

Background

Generating large meshes and simulating them in OpenFOAM can take considerable processing time on even the fastest desktop computer. In some cases hours or even days. Meanwhile the FreeCAD workstation machine is tied up and often not very responsive because the CPU core loads are high and the memory bandwidth is almost entirely consumed. The workstation storage device will also be accessed frequently, further slowing down the local machine.

A better way to handle large meshing and simulation tasks is to off load them to a second (remote) computer, leaving the FreeCAD workstation almost unhindered while they run. Furthermore the remote computer can be optimized to run mesh and solver loads much faster than a desktop machine might be.

The CfdOF workbench is now capable of allowing the user to use a remote computer to process meshes and run OpenFOAM solvers. It does this by using the Secure SHell (ssh) command to run the mesher and OpenFOAM on the remote computer.

A few things are required to accomplish this:

  • The remote computer must be accessible to the local computer via a network connection.
  • ssh must be installed on the remote computer.
  • The FreeCAD user must have access to a user account on the remote computeran ssh key must be generated and stored on the remote computer such that the FreeCAD user can connect to the remote computer using ssh without using a password.
  • all the relevant meshing and OpenFOAM software must be installed on the remote computer.
  • the remote computer must support POSIX file system commands such as ssh, rsync, etc.

The purpose of the Remote Processing tab in CfdOF Preferences is to help the user set up and test each of the various components listed above.

Terminology

For the purpose of this discussion the FreeCAD workstation will be referred to as the local computer. The terms "workstation", "FreeCAD workstation" and local computer will be used interchangeably. Likewise the terms "server" and "remote host" refer to the non local computer that the remote processing will be done one.

Also, the terms computer and host will also be used interchangeably. Strictly speaking a computer is any computing device whereas a host is a computer connected to a network that can be reached by its IP address or hostname. In this discussion we assume that all computers are connected to a network and have an IP address and a hostname.

About ssh

"The Secure Shell Protocol (SSH) is a cryptographic [encrypted] network protocol for operating network services securely over an unsecured network." https://en.wikipedia.org/wiki/Secure_Shell

As such it will allow a FreeCAD user to run meshing and OpenFOAM applications on the remote computer from across the network, without actually being at the remote computer.The remote computer can be any computer capable of running ssh and the meshing and OpenFOAM applications that supports POSIX filesystem commands. Generally this is any computer running Linux, MacOS or Windows with WSL or MinGW installed. Hardware wise the remote computer could be almost anything - a laptop, a desktop PC, a server or a cloud computer such as an AWS instance.

However, at this time the CfdOF remote processing code has only been tested with Linux hosts.

Remote Computer Setup

In order to allow CfdOF to use the remote computer for remote processing, it must be set up as follows:

Step 1) Log into the remote computer and verify that ssh is installed and running.

On a linux computer one can do this with:

$ ps aux| grep sshd
root 1240 0.0 0.0 14024 8436 ? Ss 07:38 0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups

**Step 2) Log into the remote computer via ssh from the local computer. **

On a linux computer one can do this from a console on the workstation with the following command:

$ssh <username>@<remote computer hostname or IP address>

Where username is the name of the user on the remote computer, not the FreeCAD workstation and IP address is the IP address of the remote computer. One can also use the hostname if the DNS server used on your network supports hostname resolution, ie dnsmasq is enabled.

For example, if the remote computer's hostname is goliath and goliath's IP address is 192.168.2.159, one can do either of the following:

$ssh [email protected]
$ssh me@goliath

If an ssh key is not set up for the user on the remote computer, ssh will ask for the password for the user account on the remote machine. This password is not to be confused with the password used on the FreeCAD workstation.

In either case the host computer should respond with a ssh shell in which you can issue commands to run on the remote computer.

me@goliath$ ls -l
total 0
drwxr-xr-x. 1 me me 20 Feb 14 2022 Desktop
drwxr-xr-x. 1 me me 0 Feb 14 2022 Documents
drwxr-xr-x. 1 me me 42 Feb 14 2022 Downloads
drwxr-xr-x. 1 me me 0 Feb 14 2022 Music
drwxr-xr-x. 1 me me 28 Feb 14 2022 openfoam
drwxr-xr-x. 1 me me 0 Feb 14 2022 Pictures
drwxr-xr-x. 1 me me 0 Feb 14 2022 Public
drwxr-xr-x. 1 me me 0 Feb 14 2022 Templates
drwxr-xr-x. 1 me me 0 Feb 14 2022 Videos

Notice that the command prompt changed to me@goliath$

To exit an ssh session, type exit:

$exit

This will bring you back so the shell on your local computer.

Step 3) Set up ssh keys.ssh

keys are used to allow the use of ssh without prompting the user for a password. Remote computing in CfdOF requires that ssh be used with keys. Each workstation will need its own key for each remote computer that it uses, if it uses more than one remote computer.

To generate an ssh key for the local computer, use the following command on a local console shell on the workstation computer: (Do not run this from within an ssh session !)

$ssh-keygen

Do not use a passphrase. TODO: explain this.

To copy the key over to the remote server, run this command on a local console on the workstation computer:

ssh-copy-id <username>@<remotecomputer>

It will prompt you for the password of your user account on the remote machine. It will then copy the ssh key you generated on the workstation over to the remote computer.

You should now be able to login to an ssh session on the remote computer without being prompted for a password.

ssh <username>@<remotecomputer>

If you are prompted for a password when you log in your ssh key is not set up. You'll need to remedy this before proceeding further.

Note: ssh requires a unique key for every host/remote computer pair. ssh identifies computers by their hostname and IP address. If you generate your ssh key using an IP address and the IP address of either the local machine or the host changes, you will have to generate a new ssh key for the new address pair. To avoid this problem, use fixed IP addresses whenever possible or use hostnames instead of IP addresses.

Likewise if you change the remote computer you use you'll have to copy the generated ssh key to the new remote computer with:

$ssh-copy-id <username>@<remotecomputer>

using the new computer name or IP address.

Once you can reliably log into an ssh session on the remote computer from the local computer using an ssh key the remote computer is ready to be used by CfdOF for remote processing.

CfdOF Remote Processing Setup

Once ssh is set up on the remote computer, one can setup the rest of remote computing from the Cfdof Remote Computing preferences page. (FreeCAD->Edit->Preferences->CfdOF->Remote Computing)

Step 1) Click "Enable Remote Computing

Step 2) Add a new host profile

A host profile is where all the details about a host are kept. The host profile is not the name of the host, but it can be. The actual name of the host is stored in the hostname field.

Step 3) Input the host name or IP address of the remote computer to be used for remote processing.

Step 4) Run "Ping Remote Host" to verify that the hostname or IP address is correct and that the local computer can reach the remote computer over the network. You should see " pinged successfully in the Output field below.

Step 5) Input the username of the user account to be used on the remote computer.

Step 6) Run "Test ssh" to verify that ssh has been set up correctly on the remote computer. You should see "ssh verified with " in the Output field below.

Step 7) Run remote host dependency checker.The output of this process will show the user what meshing and OpenFOAM applications have and haven't been installed on the remote computer and where they are if they have been installed.

Notes

As of this writing, CfdOF Remote Processing assumes that OpenFOAM will run on the remote computer from the command line without any other instructions from the workstation via an ssh session.

For example, to find out what version of foam is installed on the remote computer, run foamVersion in an ssh session from the workstation:

[me@david]$ foamVersion 
OpenFOAM-2206

To test if foam itself will run, use simpleFoam:

[me@david]$ simpleFoam -help 
Usage: simpleFoam [OPTIONS] 
Options:  
-case <dir>       Specify case directory to use (instead of cwd)  
-decomposeParDict <file>                    Use specified file for decomposePar dictionary  
-dry-run          Check case set-up only using a single time step  
-dry-run-write    Check case set-up and write only using a single time step  
-parallel         Run in parallel  
-postProcess      Execute functionObjects only  
-doc              Display documentation in browser  
-help             Display short help and exit  
-help-full        Display full help and exitSteady-state solver for incompressible, turbulent flows. 

Using: OpenFOAM-2206 (2206) - visit www.openfoam.com 
Build: _8993af73-20221106 (patch=221104) Arch:  LSB;label=32;scalar=64

OpenFOAM is a vast application. It is beyond the scope of this document to teach CfdOF users how to install and configure it. There are many good online resources for this purpose.

www.reddit.com/r/openfoam
https://www.cfd-online.com/Forums/openfoam/
https://cfd.direct/openfoam/linux-guide/

One thing some users sometimes forget is that OpenFOAM must be initialized with a script prior to running it. This can be accomplished automatically by placing the following line (adjusted for the version of OpenFOAM being run) in the user's .bashrc file:

source /usr/lib/openfoam/openfoam2206/etc/bashrc

Note that this command will come into effect the next time a new bash session is started. Or you can run $source ~/.bashrc to reload it in the current session.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I've still got a git issue. I'll push my code to my fork as soon as I get it resolved.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I got the git permission issue worked out. But now I have merge issues:

$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   CfdOF/CfdPreferencePage.py
        new file:   CfdOF/CfdRemotePreferencePage.py
        modified:   CfdOF/CfdTools.py
        modified:   CfdOF/Mesh/CfdMesh.py
        modified:   CfdOF/Mesh/CfdMeshTools.py
        modified:   CfdOF/Mesh/TaskPanelCfdMesh.py
        modified:   CfdOF/Solve/CfdCaseWriterFoam.py
        modified:   CfdOF/Solve/TaskPanelCfdSolverControl.py
        modified:   Gui/CfdPreferencePage.ui
        new file:   Gui/CfdRemotePreferencePage.ui
        modified:   Gui/TaskPanelCfdMesh.ui
        modified:   Gui/TaskPanelCfdSolverControl.ui
        modified:   InitGui.py
$ git push mine
To https://github.com/linuxguy123/CfdOF
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/linuxguy123/CfdOF'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

I'm working on it.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

It was a mistake to fork before trying to merge. I should have created an empty repo and then pushed into it.

But it looks like the conflict is pretty small and all in one file.

$ git diff
diff --cc CfdOF/Mesh/TaskPanelCfdMesh.py
index 75afc58,4acfde2..0000000
--- a/CfdOF/Mesh/TaskPanelCfdMesh.py
+++ b/CfdOF/Mesh/TaskPanelCfdMesh.py
@@@ -470,22 -250,18 +470,30 @@@ class TaskPanelCfdMesh
              FreeCADGui.doCommand("cart_mesh.error = False")
              FreeCADGui.doCommand("cmd = CfdTools.makeRunCommand('checkMesh -meshQuality', cart_mesh.meshCaseDir)")
              FreeCADGui.doCommand("env_vars = CfdTools.getRunEnvironment()")
+             self.check_mesh_error = False
              FreeCADGui.doCommand("proxy.running_from_macro = True")
              self.mesh_obj.Proxy.running_from_macro = False
+             self.mesh_obj.Proxy.check_mesh_process = CfdConsoleProcess(
+                 stdout_hook=self.gotOutputLines, stderr_hook=self.gotErrorLines)
              FreeCADGui.doCommand("if proxy.running_from_macro:\n" +
-                                  "  mesh_process = CfdConsoleProcess.CfdConsoleProcess()\n" +
-                                  "  mesh_process.start(cmd, env_vars=env_vars)\n" +
-                                  "  mesh_process.waitForFinished()\n" +
+                                  "  proxy.check_mesh_process = CfdConsoleProcess()\n" +
+                                  "  proxy.check_mesh_process.start(cmd, env_vars=env_vars)\n" +
+                                  "  proxy.check_mesh_process.waitForFinished()\n" +
                                   "else:\n" +
++<<<<<<< HEAD
 +                                 "  proxy.mesh_process.start(cmd, env_vars=env_vars)")
 +            if self.mesh_obj.Proxy.mesh_process.waitForStarted():
 +                self.form.pb_check_mesh.setEnabled(False)   # Prevent user running a second instance
 +                self.form.pb_run_mesh.setEnabled(False)
 +                self.form.pb_write_mesh.setEnabled(False)
 +                #self.form.pb_write_remote_mesh.setEnabled(False)
 +                self.form.pb_stop_mesh.setEnabled(False)
 +                self.form.pb_paraview.setEnabled(False)
 +                self.form.pb_load_mesh.setEnabled(False)
++=======
+                                  "  proxy.check_mesh_process.start(cmd, env_vars=env_vars)")
+             if self.mesh_obj.Proxy.check_mesh_process.waitForStarted():
++>>>>>>> 2b67db0aab52d0005a8253944b109ddded72781b
                  self.consoleMessage("Mesh check started ...")
              else:
                  self.consoleMessage("Error starting mesh check process", 'Error')
@@@ -531,11 -310,8 +545,16 @@@
              FreeCADGui.doCommand("from CfdOF.Mesh import CfdMeshTools")
              FreeCADGui.doCommand("from CfdOF import CfdTools")
              FreeCADGui.doCommand("from CfdOF import CfdConsoleProcess")
++<<<<<<< HEAD
 +            FreeCADGui.doCommand("from FreeCAD import ParamGet")
 +            
 +            FreeCADGui.doCommand("cart_mesh = " +
 +                                 "CfdMeshTools.CfdMeshTools(FreeCAD.ActiveDocument." + self.mesh_obj.Name + ")")
 +            
++=======
+             FreeCADGui.doCommand("cart_mesh = "
+                                  "    CfdMeshTools.CfdMeshTools(FreeCAD.ActiveDocument." + self.mesh_obj.Name + ")")
++>>>>>>> 2b67db0aab52d0005a8253944b109ddded72781b
              FreeCADGui.doCommand("proxy = FreeCAD.ActiveDocument." + self.mesh_obj.Name + ".Proxy")
              FreeCADGui.doCommand("proxy.cart_mesh = cart_mesh")
              FreeCADGui.doCommand("cart_mesh.error = False")

I'll finish this tomorrow.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I fixed the conflict and the push worked. My repo now has all my changes and Oliver's too.
https://github.com/linuxguy123/CfdOF

I need to check that this was Oliver's intended change in TaskPanelCfdMesh.py:

FreeCADGui.doCommand("if proxy.running_from_macro:\n" +
                                 "  mesh_process = CfdConsoleProcess.CfdConsoleProcess()\n" +
                                 "  mesh_process.start(cmd, env_vars=env_vars)\n" +
                                 "  mesh_process.waitForFinished()\n" +
                                 "  proxy.check_mesh_process = CfdConsoleProcess()\n" +
                                 "  proxy.check_mesh_process.start(cmd, env_vars=env_vars)\n" +
                                 "  proxy.check_mesh_process.waitForFinished()\n" +
                                 "else:\n" +
                                 "  proxy.check_mesh_process.start(cmd, env_vars=env_vars)")

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Here is the file that I use for testing. I got it from a post in FreeCAD.org.

naca2412_BH.zip

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Right now the case files are moved over to the remote host and run in the remote output path. I have not implemented adding the filename to the output path and the results are not copied back to the workstation. I intend to change this in the near future.

I am contemplating giving the user the option to copy the results back and also the option of deleting the results on the server as shown in the GUI below.

If the results files are copied back to the workstation, the workstation will operate exactly as if the results were run locally. ie Checkmesh, Paraview, View mesh, etc. will work locally. Not everyone will want to do this. Some users will work with the results on the server.

Of those that do copy the results back, some will want to leave the results on the server for others to use in a shared work environment. Thus I've set up the Remote Output Path options the way I have.

Thoughts ?

This topic touches on another topic that will need addressing sooner or later. My strategy until now has been to touch as little of the existing code as possible and implement remote processing by adding the necessary code. To this end, I have not made any additions to the mesh object or the solver object. Everything needed to run a remote process has been passed into the routines that need it via global vars. Which is obviously messy and not good programming practice.

At some point I'll go back and add the variables that are needed for remote processing to the mesh and solver objects. It would make implementing things like copyBack and deleteOnServer a lot simpler. "At some point" = when I get some feedback on the addition I've done.

If you look at the TODOs in the code, there are lots of things that could be cleaned up. This isn't the only thing that could be addressed in the code base.

BTW, I'm doing this work because I need changes like this for a project I'm working on. It took a lot of effort to add remote processing to CfdOF. But that effort will be returned and a lot more going forward when I/we are using it.

Remote output path options

Remote Preferences-current

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

There is a thread on FreeCAD.org to discuss this release.
https://forum.freecad.org/viewtopic.php?p=668412#p668412

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

Just updated my repo with some code clean up and with copy_back working for meshing.

copy_back for meshing means we automatically have a local copy of the mesh case in which to ParaView, Check, Load Surface, etc.

I have not implemented add_filename_to_output yet.

I will now add copy_back to the solver.

The impetus for doing all this is that one can iterate a design with file1.FCstd, file2.FCStd, file3.FCstd and the output from each will go to /outputdir/file1, outputdir/file2, outputdir/file3 on the workstation automatically, without over writing the results of a previous design iteration. And if we open file1.FCstd in FreeCAD and click Paraview the results from file1 solve will open.

All this will happen automatically by copying the results back to the workstation and by adding the filename to the output dir. It should be a seamless experience whether things are processed on the workstation or on a remote host.

I'm doing this because I have several hundred CFDs to run, ASAP. I don't want to be wasting my time manually moving result files around and renaming directories. I want that to happen automatically so that I can focus on the design part of the work.

In a future update I'll set it up so that those results can be left on the server and opened there from the workstation. The impetus for this is that any user could access file1.FCstd located on a network server and have access to the mesh and solve results on a different server.

But baby steps first.

from cfdof.

linuxguy123 avatar linuxguy123 commented on May 18, 2024

I found a problem whereby process.finished is not firing even though the remote process is completing properly with zero errors. I'm looking into it.

Here is how a solve process ends on a remote host:

SIMPLE solution converged in 2107 iterations

18:34:05  forces ReportingFunction write:
    Sum of forces
        Total    : (0.82629446 29.246383 -3.2031941e-18)
        Pressure : (0.47268552 29.2442 -1.5489154e-18)
        Viscous  : (0.35360895 0.0021826911 -1.6542787e-18)
    Sum of moments
        Total    : (-2.924612 0.082628704 13.221892)
        Pressure : (-2.9243937 0.047268127 13.234571)
        Viscous  : (-0.00021826715 0.035360577 -0.012679146)
    writing force and moment files.

18:34:05  forceCoeffs ReportingFunction001 write:
    Coefficient	Total	Pressure	Viscous	Internal
    Cd:	0.01806582	0.010334635	0.0077311851	0
    Cd(f):	-0.036640459	-0.040502643	0.0038621839	0
    Cd(r):	0.054706279	0.050837278	0.0038690012	0
    Cl:	0.63943291	0.63938519	4.7721613e-05	0
    Cl(f):	0.1132315	0.11300963	0.00022186975	0
    Cl(r):	0.52620141	0.52637556	-0.00017414813	0
    CmPitch:	-0.20648495	-0.20668296	0.00019800894	0
    CmRoll:	-0.045673369	-0.045669961	-3.408656e-06	0
    CmYaw:	0.0012904041	0.00073818156	0.00055222255	0
    Cs:	7.0033542e-20	3.3864958e-20	3.6168584e-20	0
    Cs(f):	0.0012904041	0.00073818156	0.00055222255	0
    Cs(r):	-0.0012904041	-0.00073818156	-0.00055222255	0

    writing force and moment coefficient files.

End

18:34:05  Finalising parallel run
18:34:05  

The finished code in CfdConsoleProcess.py is not even getting called:

def finished(self, exit_code):
        print("Process has finished")
        if self.finishedHook:
            print("finished hook was called with exit code:" + str(exit_code))
            self.finishedHook(exit_code)
        else:
            print("Error: finished wasn't hooked to a handler")

from cfdof.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.