Working with COMSOL Models in Python

If you’ve ever wished you could automate COMSOL model runs, sweep parameters faster, or export results without endless clicking—this video is for you.

In this quick walkthrough, I will show you how to connect COMSOL models to the Python programming environment using the MPh package. You’ll see how to load a model, explore its structure, adjust parameters, solve repeatedly across a voltage sweep, and capture results into a Pandas DataFrame for clean analysis and reporting.

Watch the full video below to follow along step-by-step. Download your Phython script file and MPh package here.


There’s no reason to learn software programs through trial and error, so in addition to our tips and tricks, our upcoming training classes will support you, the COMSOL® user, in utilizing best practices with many of the COMSOL® modules. Please visit our training calendar and find the course that is best for you.

 

[VIDEO TRANSCRIPTION]

Working with COMSOL Models in Python

Hi, I’m Mark Varady, I’m a senior engineer at AltaSim Technologies, and today I’d like to share with you how you can work with COMSOL models in the Python programming environment.

So just to get started, I’m going to provide some reference information. I’m not going to go through how to install Python or getting started and using Python, I’m going to assume you have it installed and you have some base knowledge of how to use Python already. However, I’m going to provide some links to help you get to that point if you need it. So, I’m providing links for the base Python installation at python.org. In addition to that, there are actually several Python distributions for different application areas. I like, personally, the Anaconda Scientific Python Distribution at anaconda.com. We’ll also be using Jupyter notebook, which allows you in a single document to mix not only Python code but word processing capability, formatted text, graphics, and so forth. So it’s a very useful tool to document your projects. If you need help getting up to speed and running Python, I like this tutorial video series on YouTube from Code Basics. And finally, we’re going to need the COMSOL busbar tutorial model, which is available on the COMSOL website here.

Okay, so once you have Python installed on your machine you’re going to want to install the specific package, the MPh package that allows you to work with COMSOL models in Python. And so, the way you would do that is to simply open up a command window, and we use the pip package installer, so you just type “pip install MPh” and so we see that our package is already installed. The requirements are already satisfied, and the pip installer not only installs the package we want but also all its dependencies, so we see “jpype” and so forth. Those are already installed, so we’re good to go. Next slide. So, what we see here are some useful documentation websites for this MPh package, on “read the docs,” we’re going to look at this a little bit in more detail, but also, we have the GitHub repository if you’re interested in looking through the source code for the MPh package.

Okay, so let’s take a look at this “read the docs” website, and I’m going to start from the home page. You can see there’s a tutorial page telling you how to get started with this, some demos for accomplishing specific tasks, and one other useful area on the documentation is you click on the API and specifically under “Model.”  This will give you all of the commands that are available to a model object within Python. Okay, and so we’ll make reference to this. So, let’s start here at this example: so this kind of tells you how you can get started. So, what I’m going to do is look at this, and I’m going to open up a Jupyter notebook, I’m going to put those side-by-side, and so the first thing we had to do of course is import the MPh package. So we do that, and then we have to start a client, which allows us to connect into a COMSOL model. So, we’re going to say “client=MPh.start.” Okay, and that’ll take a few seconds to start the client, and then once the client is started, we can then load the model. So, we create a variable to hold the model called “model,” the same “model=clients.load” and then the file path, which is the busbar model. And since the busbar model is in our current working directory, we just have to reference the name. So that’ll take a few seconds to load the busbar model. So, once the model is loaded, one of the first things that’s kind of useful to do is to look at the structure of the model. So, the MPh package comes equipped with this tree function, which allows you to look at the structure of the model so you can kind of see the parameters, the functions, the geometry, variables, couplings, physics, boundary conditions, and so forth. So, exactly what you would expect to see for a COMSOL model. Okay, and this example here on the “read the docs” website they’re showing how you can modify parameter values very simply.

So, let’s actually look at the available model parameters in our busbar model right now. So, we would just type in “model.parameters[ ]” and so this gives you a dictionary of name-value pairs, the parameter name and its value, along with its units. Okay, and so I’m going to key in on this Vito parameter; this is going to be the one we primarily manipulate in this tutorial video. And, so what I can do is say “model.parameter” (singular) and then just reference that parameter name Vtot. Okay, so now we have that returns the value in units of that model parameter. Now, say we want to change the value of that model parameter. We would use essentially the same command, but we would supply a second argument, which is the value and units that we want to change to. So, let’s say we want to change it to 40 millivolts. You’ve got to remember our quotes, and then if I do “model.parameters” again, we’ll see our Vtot parameter has changed to 40 millivolts as we intended, great. So, this simple example of how to change model parameters.

The next thing we want to look at is how we would then define variables for this busbar model. And there’s two variables that I’d like to define here. First one is the total thermal energy increase of the busbar as a result of the resistive heating. And the second is the maximum temperature in the busbar. And so I don’t know off the top of my head what the relevance command is to do that, so we can go over to our documentation on the website here and we can look through the tutorial and the demos to see if there’s any examples of how to define a variable, or we could look at the commands that are available to the model object. And so if we scroll through this, we’re not going to find any commands that allow us to define a variable, so does that mean we can’t do it? The answer is no. There is a way that you can actually define the variables because essentially every command available in the Java API can be applied using the MPh code. Okay, so the way we do that – I’m going to go into the actual MPh file, the busbar model, so that’s open – and I’m going to go to the application builder. Okay, and I’m going to “Record Method,” I’m just going to take the default name “method 1” – so now we have a red outline around our window here indicating that any action that we take in the model builder is going to record the equivalent Java API code in that method that we just initiated. So, in order to define variables, I have to create a variables node, and since we’re looking at the total thermal energy, we need to define an integration operator over the entire domain of our objects, and also a maximum operator for the maximum temperature. So, let’s do that, let’s define an integration operator. So, I go to “Nonlocal Couplings” “Integration” and I want that to be defined over all domains. I’m going to do the same thing, I’m going to right-click on “Definitions” “Nonlocal Couplings” “Maximum” and do that over all domains. Okay, so I have my two coupling operators defined, now I can use those to define the variables I want. Okay, so the first one is the maximum temperature it’s just “Tmax” and that’s just simply the max operator define applied to the temperature. Okay, the total thermal energy increase is a little harder. Well, what is it? It’s just integrating over the entire object the density x the specific heat x the change in temperature from its initial temperature, which we’ll assume to be in this case, 293.15 Kelvin. So, let’s do that. This is going to be “intop1” and so what is the density? Well, we can make reference to the material, which in this case is “mat1.def.row” for density, and similarly for the specific heat that’s “mat1.def.CP” and then multiply that by the temperature difference from the reference. So, it’s “T-Tref,” I don’t have Tref defined, so I’ll just say it’s 293.15 Kelvin, okay, so I just need one more parenthesis, excellent. So, we see the units are correct, we have joules, so that’s good. Okay, so we have our variables defined. Now I want to go back to the application builder. We can see that our method has been populated with the code that we need for our Python script. Okay, so I have this extra line here that I don’t need, so I’m going to get rid of that, and I’m going to copy all these lines of code into my Jupyter notebook. Okay, and just unindent them. Okay, so the key thing is we can’t run these commands as-is. In order to run a Java API command on the model object within Python, we have to reference not the model object, but the “model.Java” object. And so that’s the key is we basically just have to instead of referencing the model, we’re referencing “model.Java.” So, I’m going to just apply that to all these lines of code. And then the other thing is I’ve got to change this true to a capital “T.” Okay so I’m gonna run this. And so now I have these variables created within my model, and if I want to look at this, I can use the “MPh.tree” command on the model so we should be able to see, well we don’t see, what’s under the variables node but we can see that we have our variables node there.

Okay, the next thing I want to do is look at a specific use case. I want to sweep over a large number of parameters, solve the model for each value of the parameter, extract the variables that we just defined – the values of the variables we just defined – for each set of parameters, and store the results in a database, specifically a Pandas DataFrame. So, if you’re not familiar with Pandas, you can Google Python Pandas, and you’ll see it’s specific package for data science data analysis that’s actually quite useful. So, you want to make sure also you have Pandas installed – the Pandas package installed. So, the first thing we have to do is then import a couple of additional Python packages. I’m going to import NumPy and Pandas. So, let’s do that. Then the next thing is the parameter that we want to sweep over is the Vtot parameter that we were looking at up here, and I want to sweep over a range from 10 to 40 millivolts in increments of five, so I’m just going to define a list of values like so. So those are the values we’re going to sweep over. The next thing that we have to do is define a Pandas, or initialize a Pandas DataFrame. And so this DataFrame we want to have three columns, we want to have the value of the Vtot parameter in the first column, the maximum temperature in the second column, and the total thermal energy increase in the third column. And so those strings in here are the labels for each column. So, I’m initializing that Pandas DataFrame and then I want to set up a 4-loop to sweep over our model parameters. So, I’m going to copy some code, piece it in here, and I’m going to describe it line-for-line. So we’re doing a 4-loop over each value of Vtot in our list here and so for each value we’re going to update the value of the parameter using the parameter method. We’ll solve the model which is “model.solve”, we’ll evaluate the values of our maximum temperature and total thermal energy variables. You notice here I want to report not in the standard units – default units – of Kelvin, but degrees Celsius, and I want the total thermal energy in kilojoules not joules. Then I basically set up a list for this for the current row, and then I append that row to our DataFrame. And, furthermore, I save the MPh file for each value of the parameter, so when we’re done, we’re going to have seven additional MPh files, one for each value of the Vtot parameter that we’re sweeping over. We’re saving each of those files as we go. So, I’ll run this, and it’ll take a minute or so to run through all the cases. Oh, and so I just realized I just need to get rid of this base directory. So, it’s running, let’s actually open up our directory.  And you can see these MPh files being created as the code is running, so 10 if the next one will be 40, it’ll be the last one, and then this is done. Okay, so now we have new MPh files for each value of the parameter, and we should have a DataFrame containing the results of the model for each value of the parameter. So, if I type in “DF” which is the name of our DataFrame, and look at that we can see that we have for each value of the Vtot parameter, the maximum temperature, and the total thermal energy in kilojoules. Okay, so the results make sense as we increase the total voltage, the maximum temperature increases, and the total thermal energy increases. So, for this particular case, it’s only seven parameter values, but if you wanted to run the model over a large number of parameters, and sweep over not only one parameter but several parameters; this is a good way to do data analysis on something like that using the power of data analysis contained within the Pandas Python package.

Okay so let’s look at another use case. We now have several MPh files in our working directory, one for each value of the total voltage parameter. And so this highlights another important use case, one that I’ve used a few times now, where if you have several MPh files, and I want to do basically the same post-processing on each one and extract some results and present some results, what we can do is use Python to loop over all of these MPh files, do the post-processing on each one, and export the results. So, the first thing I want to do, I need to import another package, the glob package, which is going to allow us to list all the MPh files in our current directory. The other thing I want to do is for our plotting, I want all the plots to be on the same scale, and so what I have to do is extract the maximum temperature for all the cases that we ran. So I could just say it’s 169.13 or what I can do is actually just extract that maximum using this code. So, I’m just taking the “Tmax” column in our DataFrame, finding the max, and getting that specific item, okay. So I type in “overall_Max T”; that’s what you would expect 169.13, excellent. So, I’m just going to copy and paste some code in here, and I’ll explain what it means as we go. So again, I’m using the glob package to list all the files with an MPh extension. I’m going to loop over all those files – load each one. I’m going to set the units of this plot – so this plot that I’m doing is actually already defined within the MPh file – and it’s a plot of the temperate 3D plot of the temperature of our busbar. And so I’m going to set the units to degrees Celsius instead of Kelvin. I’m going to set the color range using the overall maximum temperature of this 169°C, I’m going to set up an export node to export our plot as an image, I’m going to define the name of the image file, and then run the export. So, if I run this – so it’s actually “client” not “client 1” – and I need to get rid of this base variable. Okay, so I go in here and we should see – we see plots popping up as it’s going through and doing the post-processing. Okay, so not only do I have the image files now created in the directory, but for each case a separate window popped up showing us the plot that we need. And you can see they’re all on the same color scale exactly as we intended.

Okay, so those are very simple use cases that I wanted to demonstrate for the MPh package today. I hope you find this helpful, and I hope this inspires you to consider other ways where you can use the power of the Python programming environment to help enhance your COMSOL analysis capabilities. Thanks, and I’ll see you next time.

Scroll to Top