Nerve cells are separated from the extracellular region by a lipid bilayer membrane. When the cells aren’t conducting a signal, there is a potential difference of about -70 mV across the membrane. This difference is known as the cell’s resting potential. Mineral ions, such as sodium and potassium, and negatively charged protein ions, contained within the cell, maintain the resting potential. When the cell receives an external stimulus, its potential spikes toward a positive value, a process known as *depolarization*, before falling off again to the resting potential, called *repolarization*.

*Plot of a cell’s action potential.*

In one example, the concentration of the sodium ions at rest is much higher in the extracellular region than it is within the cell. The membrane contains gated channels that selectively allow the passage of ions though them. When the cell is stimulated, the sodium channels open up and there is a rush of sodium ions into the cell. This sodium “current” raises the potential of the cell, resulting in depolarization. However, since the channel gates are voltage driven, the sodium gates close after a while. The potassium channels then open up and an outbound potassium current flows, leading to the repolarization of the cell.

Hodgkin and Huxley explained this mechanism of generating action potential through mathematical equations (Ref. 2). While this was a great success in the mathematical modeling of biological phenomena, the full Hodgkin-Huxley model is quite complicated. On the other hand, the FitzHugh-Nagumo model is relatively simple, consisting of fewer parameters and only two equations. One is for the quantity *V*, which mimics the action potential, and the other is for the variable *W*, which modulates *V*.

Today, we’ll focus on the FN model, while the HH model will be a topic of discussion for a later time.

The two equations in the FN model are

\frac{dV}{dt} &=& V-V^3/3-W + I \label{FN1}

and

\frac{dW}{dt} &=& \epsilon(V+a-bW). \label{FN2}

The parameter corresponds to an excitation while *a* and *b* are the controlling parameters of the model. The evolution of *W* is slower than that of the evolution of *V* due to the parameter ε multiplying everything on the right-hand side of the second equation. The fixed points of the FN model equations are the solutions of the following equation system,

V-V^3/3-W + I &=& 0 \label{FN3}

and

V+a-bW &=& 0. \label{FN4}

The *V*-nullcline and *W*-nullcline are the curves and , respectively, in the VW-plane. Note that the *V*-nullcline is a cubic curve in the VW-plane and the *W*-nullcline is a straight line. The slope of the line is controlled in such a way that the nullclines intersect at a single point, making it the system’s only fixed point.

The parameter simply shifts *V*-nullcline up or down. Thus, changing modulates the position of the fixed point so that different values of cause the fixed point to be on the left, middle, or right part of the curve .

To simulate what happens when the fixed point is in each region, we can use the *Global DAE* interface included in the base package of COMSOL Multiphysics.

The *V*-nullcline is shown in the figure below in a green color. In the region above this nullcline , while in the region below it is positive. The *W*-nullcline is shown in red; in the region to the right of this straight line, , and to the left, .

Let’s first examine what happens if the fixed point is on the right side, Region 3, of the *V*-nullcline. We’ll say that when *t*, representing time, equals zero, both *V* and *W* are also at zero. In this case, both and are positive at and around the starting point and thus both change as time progresses. But since *V* evolves faster than *W*, *V* increases rapidly while *W* remains virtually unchanged. In the figure, we can see that this results in a near-horizontal part of the V-W curve.

As the curve approaches the *V*-nullcline, the rate of change of *V* slows down and *W* becomes more prominent. Since is still positive, *W* must increase, and the curve moves upwards. The fixed point then attracts this curve and the evolution ends at the fixed point.

*Plot of the VW-plane when the fixed point is on the right side of the* V*-nullcline.*

If the fixed point is in the middle, Region 2, then what we have discussed so far holds true. The difference is that once the curve goes beyond the right knee of the *V*-nullcline, becomes negative and *V* rapidly decays. While moving left, the curve crosses the red nullcline from right to left. From this point on, while both *V* and *W* diminish, the evolution of *V* dominates and the curve becomes horizontal once again.

This continues until the curve hits the left part of the *V*-nullcline. The curve begins to hug the *V*-nullcline and starts a slow downward journey. When it touches the left knee of the *V*-nullcline, it moves rapidly toward the right part of the *V*-nullcline. Note that this motion never hits the fixed point and therefore keeps repeating, which we can see in the plot below.

*Plot of the VW-plane when the fixed point is in the middle region of the* V*-nullcline.*

That leaves us with one last case to discuss — when the fixed point is on the left part, Region 1, of the *V*-nullcline. The results should look like the following plot. Note that the analyses we previously performed carry over.

*Plot of the VW-plane when the fixed point is on the left side of the* V*-nullcline. *

To explore the rich dynamics of the FN model described above, we need to repeatedly change various inputs without changing the underlying model. As such, a user interface that allows us to easily change the model parameters, perform the simulation, and analyze the new results without having to navigate the Model Builder tree structure to perform these various actions is desirable.

To accomplish this, we can turn to the Application Builder. This platform allows us to create an easy-to-use simulation app that exposes all of the essential aspects of the model, while keeping the rest behind the scenes. With this app, we can rapidly change the parameters via a user-friendly interface and study the results using both static figures and animations. The app also makes it easy for students to understand the FN model’s dynamics without having to worry about creating a model.

The important parameters of the FN model, i.e. *a, b,* ε, and *I*, are displayed in the app’s *Model Parameters* section. The graphical panels display various quantities of interest such as the waveform for *V* and *W*. We display the phase plane diagram in the top-right panel along with the *V*- and *W*-nullclines. The position of the fixed point is easily identifiable from that plot. Once the simulation is complete, we can animate the time trajectories by choosing the animation option from the ribbon toolbar. To get a summary of the simulation parameters and results, we can select the *Simulation Report* button.

*App showing the dynamics of the FitzHugh-Nagumo model when the fixed point is in Region 2. *

We can easily reproduce the cases described in the previous section with our app. The image above, for example, shows what happens when the fixed point is in Region 2. We can easily move the fixed point to either Region 1 or 3 by making the current 0.1 or 2.5, respectively. Note that any other parameters in the app can also be changed to see if other interesting trends emerge.

The app that we’ve presented here is just one example of what you can create with the Application Builder. The design of your app, from its layout to the parameters that are included, is all up to you. The flexibility of the Application Builder enables you to add as much complexity as needed, in part thanks to the Method Editor for Java® methods. In a follow-up blog post, we’ll create an app to illustrate the dynamics of the more complicated HH model. Stay tuned!

- FitzHugh R. Impulses and Physiological States in Theoretical Models of Nerve Membrane.
*Biophysical Journal*. 1961;1(6):445-466. - Hodgkin AL, Huxley AF. A quantitative description of membrane current and its application to conduction and excitation in nerve.
*The Journal of Physiology*. 1952;117(4):500-544.

- See how to combine equation-based modeling and apps in this blog post: Implementing the Weak Form with a COMSOL® App
- To find out how to build your own app, check out our Intro to Application Builder Videos series

*Oracle and Java are registered trademarks of Oracle and/or its affiliates.*

In COMSOL Multiphysics, we can evaluate spatial integrals by using either integration component coupling operators or the integration tools under *Derived Values* in the *Results* section. While these integrals are always evaluated over a fixed region, we will sometimes want to vary the limits of integration and obtain results with respect to the new limits.

In a 1D problem, for example, the integration operators will normally calculate something like

I = \int_a^b f(x)dx.

where *a* and *b* are fixed-end points of a domain.

What we want to do instead, though, is to compute

I(s) = \int_a^sf(x)dx, \qquad s\in [a,b],

and obtain the result with respect to the variable limit of integration *s*.

Since the integration operators work over a fixed domain, let’s think about how to use them to obtain integrals over varying limits. The trick is to change the integrand by multiplying it by a function that is equal to one within the limits of integration and zero outside of the limits. That is, we define a kernel function

k(s,x) =

\begin{cases}

1 \quad x \leq s\\

0 \quad \mathrm{otherwise},

\end{cases}

\begin{cases}

1 \quad x \leq s\\

0 \quad \mathrm{otherwise},

\end{cases}

and compute

I(s) = \int_a^Lk(s,x)f(x)dx = \int_a^sf(x)dx.

As indicated in our previous blog post about integration methods in time and space, we can build this kernel function by using a logical expression or a step function.

We also need to know how the auxiliary variable *s* is specified in COMSOL Multiphysics. This is where the *dest* operator comes into play. The *dest* operator forces its argument to be evaluated on the destination point rather than on the source points. In our case, if we define the left-hand side of the above equation as a variable in the COMSOL software, we type *dest(x)* instead of *s* on the right-hand side.

Let’s demonstrate this with an example. In this case, a model simulates a steady-state exothermic reaction in a parallel plate reactor. There is a heating cylinder near the center and an inlet on the left, at *x* = 0. One of the compounds has a concentration *cA*.

What we want to do is to calculate the total moles per unit thickness between the inlet and a cross section at a distance of *s* from the inlet. We then plot the result with respect to the distance from the inlet.

First, we define an integration coupling operator for the whole domain, keeping the default integration operator name as *intop1*. If we evaluate *intop1(cA)*, we get the integral for the entire domain. To vary the limit of integration horizontally, we build a kernel using a step function, which we’ll call *step1*. We then define a new variable, *intUpTox*.

*Combining the integration coupling operator,* dest *operator, and new variable to evaluate an integral with moving limits.*

Let’s see how the variable described in the image above works. As a variable, it is a distributed quantity and has a value equal to what the integration operator returns. During the integration, we evaluate *x* at every point in the domain of integration and *dest(x)* only at the point where *intUpTox* is computed. We find a horizontal line that spans from the inlet all the way to the outlet and plot *intUpTox*.

*Integrating concentration* cA *over a horizontally varying limit of integration.*

I(s) = \underbrace{\int_0^s\int_{y_{min}}^{y_{max}}c_A(x,y)dydx=\int_{\Omega} K(s,x)c_A(x,y)d\Omega}_{\text{Mathematical Expression}}=\underbrace{\mathrm{intop1(step1(x-s)*cA)=intop1(step1(x-dest(x))*cA)}}_{\text{COMSOL Implementation}}

If we instead plot *intUpTox/intop1(cA)*100*, we get a graph of the percentile mass to the left of a given point with respect to the *x*-coordinate.

In the above integral, the limit of integration is given explicitly in terms of the *x*-coordinate. Sometimes, though, the limit may only be given in an implicit criteria, and it may not be straightforward to invert such criteria and obtain explicit limits. For example, say that we want to know the percentage of total moles within a certain radial distance from the center of the heating cylinder. Given a distance *s* from the center (*x _{pos}*,

k(s,x,y) = \mathrm{step1}\left[(x-x_{pos})^2+(y-y_{pos})^2-s^2\right].

But how do we specify *s*? We again use the *dest* operator: , and the kernel is

k(s,x,y) = \mathrm{step1}\left[(x-x_{pos})^2+(y-y_{pos})^2- (\mathrm{dest}(x)-x_{pos})^2-(\mathrm{dest}(y)-y_{pos})^2\right].

We implement this method by defining a Cut Line data set to obtain the horizontal line through the hole’s center and placing a graph of our integration expression over it. It is not necessary that the cut line is horizontal; it just needs to traverse the full domain that the integration operator defines. Furthermore, *s* should vary monotonically over the cut line.

*New data set made with a cut line passing through the center of the hole.*

In the image below, we added an insert by zooming in at the bottom left area of the graph. This section shows that there is no result on the plot for a distance of less than 2 mm from the center of the heating hole. This is because that region is not in our computational domain. Since the hole has a radius of 2 mm, the ordinate starts at 0 at an abscissa of 2 mm.

*Percentage of mass in a domain, which is within a radial distance from the fixed point. The radial distance is varied by using the* dest *operator in an implicit expression.*

In the previous sections, we evaluated integrals where the integrands were given. But what do we do if we have the integral and want to solve for the integrands? An example of such a problem is the Fredholm equation of the first kind

g(s) = \int_a^b K(s,x)u(x)dx,

where we want to solve for the function *u* when given the function *g* and Kernel *K*. These types of integral equations often arise in inverse problems.

In integro-differential equations, both the integrals and derivatives of the unknown function are involved. For example, say we have

\frac{du}{dx}+\int_a^bf(x,u(s))ds = g(x),

and want to solve for *u* given all of the other functions.

In our Application Gallery, we have the following integro-partial differential equation:

\rho C_p \frac{\partial T}{\partial t}+\frac{\partial }{\partial x}(-\kappa \frac{\partial T}{\partial x}) = \frac{4D_i}{D_o^2-D_i^2}\varepsilon \sigma T^4 – \frac{4}{D_o^2-D_i^2}\varepsilon \sigma\int_0^LK(x,s)T(s)^4ds,

where we solve for temperature *T(x)* and are given all of the other functions and parameters.

We can solve the above problem using the *Heat Transfer in Solids* interface. In this interface, we add the right-hand side of the above equation as a temperature-dependent heat source. The first source term is straightforward, but we need to add the integral in the second term using an integration coupling operator and the *dest* operator. For the integration operator named *intop1*, we can evaluate

\int_0^LK(x,s)T(s)^4ds

with *intop1(k(dest(x),x)*T^4)*.

For more details on the implementation and physical background of this problem, you can download the integro-partial differential program tutorial model here. Please note that some integral equations tend to be singular and we need to use regularization to obtain solutions.

In today’s blog post, we’ve learned how to integrate over varying spatial limits. This is necessary for evaluating integrals in postprocessing or formulating integral and integro-differential equations. For more information, you can browse related content on the COMSOL Blog:

- Overview of Integration Methods in Space and Time
- How to Integrate Functions Without Knowing the Limits of the Integral
- Analyze Your Simulation Results with Projection Operators

For a complete list of integration and other operators, please refer to the COMSOL Reference Manual.

If you have questions about the technique discussed here or with your COMSOL Multiphysics model, feel free to contact us.

]]>

Today’s example involves solving an axisymmetric heat conduction problem on a cylinder. This model was taken from the NAFEMS benchmark collection and solved in COMSOL Multiphysics using the *Heat Transfer in Solids* interface. We will take dimensions and material properties from that model and reproduce the result using the *General Form PDE* interface. Essentially we are now benchmarking our manual PDE interface approach to the problem by comparing it with the *Heat Transfer in Solids* interface, where the axial symmetry is automatically taken care of.

The equation for a stationary temperature distribution *T* on a rigid solid is

\rho C_p\mathbf{u}\cdot \nabla T + \nabla \cdot (-\kappa \nabla T)=Q,

If the translational velocity **u** is uniformly zero, the heat capacity *C _{p}* has no effect and the only material property we have to specify is the thermal conductivity

*An axisymmetric heat conduction problem solved with the *Heat Transfer in Solids* interface. This benchmark model is included in our Application Gallery.*

Let’s now solve the same problem on the same finite element mesh using the *General Form PDE* interface. This interface is one of the several mathematics interfaces in COMSOL Multiphysics that facilitate solving custom equations. When the equation you want to solve is not built into one of the physics interfaces, you can use the mathematics interfaces to solve algebraic equations, ordinary differential equations, and partial differential equations. The new equations you add can be linear or nonlinear, and they can be solved either on their own or coupled with the prebuilt physics interfaces. The equations for heat transfer are a good starting point since those are already available in the built-in interfaces and we can easily compare the results with those where we have used our own PDE.

The *General Form PDE* interface has the template

e_a\frac{\partial^2 u}{\partial t^2} + d_a\frac{\partial u}{\partial t} + \nabla \cdot \Gamma = f,

and we have to provide the mass coefficient *e _{a}*, the damping coefficient

If we compare this template with the equation from the *Heat Transfer in Solids* interface, with the dependent variable *u* standing for temperature, our flux specification should be that . To achieve this, we’ll specify the *r*- and *z*-components of the flux in the PDE interface as *-kappa*ur* and *-kappa*uz*, respectively. The mass and damping coefficients are not included in a stationary analysis.

As the image below indicates, the solution using the above settings differs from the solution we obtained using the *Heat Transfer in Solids* interface. What is the reason for this?

*An axisymmetric heat conduction problem solved with the *General Form PDE* interface. The effect of a curvilinear coordinate system is not accounted for here.*

The short explanation to such discrepancy is that the *Heat Transfer in Solids* interface understands as the divergence of the thermal flux, whereas the PDE interfaces understand as

\frac{\partial \Gamma_r}{\partial r} + \frac{\partial \Gamma_z}{\partial z}.

This expression is not the divergence of Γ in the cylindrical coordinate system. While we’ll demonstrate how to fix this in a later section, we’ll first provide a more detailed explanation of what causes the discrepancy.

The equations that the various physics interfaces in COMSOL Multiphysics solve are mathematical abstractions of the laws of physics. Often stated as conservation laws or accounting principles, these laws describe how a certain quantity changes on account of activities on a domain and across the domain’s boundary. While conservation laws hold for all materials, the extent of a given material’s response to domain forces and boundary fluxes differs from one material to another. The material responses are specified by so-called constitutive equations or equations of state. We have to make sure that constitutive equations do not violate the second law of thermodynamics. Together, conservation laws and valid constitutive equations provide enough information to derive a well-posed mathematical model.

For instance, thermal conduction in a rigid solid object is governed by the law of conservation of thermal energy. The rate of change of thermal energy equals the rate at which heat is supplied by sources in the domain plus heat flux through the boundary. From empirical observations, the heat flux in solids is proportional to the temperature gradient and is directed from hotter areas to colder areas. This is the constitutive equation. From here, we can use multivariable calculus to write the heat transfer equation for an isotropic material, for example, as

\rho C_p\frac{\partial T}{\partial t}+\rho C_p\mathbf{u}\cdot \nabla T + \nabla \cdot (-\kappa \nabla T)=Q,

where *T* is temperature, which is the primary variable whose evolution we want to track; *p*, *C _{p}*, and

After deriving mathematical models like the above equation, the next step is to solve them for the primary dependent variable and other quantities of interest. In heat conduction, for example, we want to obtain the temperature in time and space. To decide how we will identify a point in space, we select a coordinate system. Making a wise choice for a coordinate system can facilitate our analysis, whereas a bad choice can make our work unnecessarily complicated. No matter which coordinate system we choose, it is important to make sure that the physical meaning of the equation stays the same.

The heat conduction equation, for instance, contains the gradient of temperature. In the Cartesian coordinate system, we have

\nabla T = \frac{\partial T}{\partial x}\mathbf{e}_x + \frac{\partial T}{\partial y}\mathbf{e}_y+\frac{\partial T}{\partial z}\mathbf{e}_z,

whereas in the cylindrical coordinate system, we have

\nabla T = \frac{\partial T}{\partial r}\mathbf{e}_r + \frac{1}{r}\frac{\partial T}{\partial \phi}\mathbf{e}_{\phi}+\frac{\partial T}{\partial z}\mathbf{e}_z.

In the first case, partial derivatives of a scalar, with respect to independent variables, provide components of the gradient. This is not the case in a curvilinear coordinate system like the cylindrical coordinate system. As referenced earlier, the physical meaning of the gradient of temperature, as the vector that points in the direction of the greatest increase of temperature with a magnitude equal to the rate of increase, should stay the same. To ensure such invariance, we have to use covariant derivatives instead of regular partial derivatives. In the Cartesian coordinate system, covariant derivatives and partial derivatives overlap; in curvilinear systems, they do not.

The other differential operator we have is the divergence operator . In the heat transfer equation, this operator acts on the flux . When using the Cartesian coordinate system, taking the divergence of the flux involves differentiating only the components , , and of the flux. The basis vectors *e _{x}*,

\nabla \cdot (\kappa \nabla T) = \frac{\partial }{\partial x}(\kappa \frac{\partial T}{\partial x}) + \frac{\partial }{\partial y}(\kappa \frac{\partial T}{\partial y}) + \frac{\partial }{\partial z}(\kappa \frac{\partial T}{\partial z}) = \frac{1}{r}\frac{\partial }{\partial r}(r \kappa \frac{\partial T}{\partial r}) + \frac{1}{r}\frac{\partial }{\partial \phi}( \frac{\kappa}{r}\frac{\partial T}{\partial \phi})+\frac{\partial }{\partial z}(\kappa \frac{\partial T}{\partial z}).

Similarly, the dot product should always coincide with the product of the magnitudes of the two vectors and the cosine of the angle between them. In the Cartesian coordinate system, this is simply the sum of the products of the corresponding components of the two vectors. In curvilinear coordinate systems, the metric tensor of the coordinate system is added into the mix.

Because of the mathematical complexity that arises in curvilinear coordinate systems, you might wonder why we would want to use anything other than the Cartesian coordinate system. But, as we’ll highlight here, there are some applications where curvilinear coordinate systems are particularly useful.

Consider a three-dimensional problem where the geometry, material properties, boundary conditions, and heat sources are symmetric about an axis. The solution is rotationally symmetric about that axis. If we use a coordinate system with the *z* direction along the symmetry axis, all partial derivatives with respect to Φ vanish. What that leaves us with is a two-dimensional problem in the rz-plane. This results in an equation that is easier to solve than the one in the Cartesian coordinate system, where all three spatial partial derivatives remain in the equation. In the finite element modeling of such problems, using an axisymmetric formulation facilitates the use of 2D meshes rather than 3D meshes, which leads to significant savings for both memory and time.

Curvilinear coordinate systems are also useful when material properties, such as the thermal conductivity *κ*, are not isotropic. If the anisotropy occurs in certain directions, we can define coordinate systems that align with those preferential directions and simplify the material property input. Note that COMSOL Multiphysics features a *Curvilinear Coordinates* interface that can be used to generate nonstandard coordinate systems. You can learn more about how to use the *Curvilinear Coordinates* interface and how to solve anisotropic problems on curvilinear coordinate systems on the COMSOL Blog.

For our particular example, we’ll focus on using the standard cylindrical coordinate system.

In COMSOL Multiphysics, there are several physics-based interfaces that solve equations arising from one or more conservation laws. For instance, in the heat transfer in rigid solids example referenced above, we follow the conservation of thermal energy. In isothermal stress analysis problems, we follow the physical laws for conservation of mass, linear momentum, and angular momentum. When you use one of these physics interfaces, the software maintains the physical meanings of differential operators by using the corresponding expression for the Cartesian or curvilinear coordinates. That is, covariant derivatives are used instead of partial derivatives and, as a result, the coordinate system invariance is maintained.

But when you use the *Coefficient Form PDE* or *General Form PDE* interfaces, the software uses partial derivatives.

In other words, the physics interfaces understand , , and to be the gradient, divergence, and curl, respectively, of a physical scalar *u* or higher-order tensor Γ. On the other hand, in the PDE interfaces, these tensorial meanings no longer apply and the operators are replaced by partial derivatives with respect to the independent variables. For example, the independent variables may not represent physical coordinates.

Consider . In the physics interfaces, this means divergence. But in the PDE interfaces, this means in a 3D component and in a 2D axisymmetric component. The first results in , which overlaps with the divergence, and the latter results in , which is not the divergence of Γ.

In a cylindrical coordinate system, the divergence is given by

\nabla \cdot \Gamma = \frac{1}{r}\frac{\partial (r \Gamma)}{\partial r} + \frac{1}{r}\frac{\partial \Gamma_{\phi}}{\partial \phi}+\frac{\partial \Gamma_z}{\partial z}.

In an axisymmetric problem, the second item in this sum vanishes, leaving

(1)

\nabla \cdot \Gamma = \frac{1}{r}\frac{\partial (r \Gamma_r)}{\partial r} +\frac{\partial \Gamma_z}{\partial z} = \frac{\partial \Gamma_r}{\partial r} + \frac{\partial \Gamma_z}{\partial z}+\frac{\Gamma_r}{r}.

The expression in the PDE interfaces does not contain the last term, as the operator is interpreted simply as the sum of partial derivatives. For the divergence of a physical quantity in the cylindrical coordinate, we have to compensate for the last term in (1). We will use an example to highlight one approach for doing so using the source term.

Let’s now go back to our initial problem. What we want to solve is the stationary problem

\nabla \cdot \Gamma = f,

where is the divergence operator. For an axisymmetric problem, we have

\frac{\partial \Gamma_r}{\partial r} + \frac{\partial \Gamma_z}{\partial z}+\frac{\Gamma_r}{r}=f.

This is equivalent to

\frac{\partial \Gamma_r}{\partial r} + \frac{\partial \Gamma_z}{\partial z}=-\frac{\Gamma_r}{r}+f.

The left-hand side of this equation is what the *General Form PDE* interface in an axisymmetric component understands to be . The right-hand side of the equation is added as an extra source term, as shown in the screenshot below. The solution now matches the solution that we obtained using the *Heat Transfer in Solids* interface.

*An axisymmetric heat conduction problem solved with the *General Form PDE* interface. The effect of a curvilinear coordinate system is accounted for here.*

Of course the item added in the source term is not a physical heat source. It simply compensates for the missing term between the covariant differentiation that we need for divergence and the partial differentiation the PDE interface does. A good practice is to add this term in the PDE settings window and add physical heat sources to the Model Builder by right-clicking the PDE interface and selecting “Source”.

In this example, only the divergence operator was used. For other differential operators, such as the curl, you should make similar compensations when solving a physics-based problem.

These adjustments are for curvilinear coordinate systems embedded in a Euclidean space. If the underlying space you are working with is not Euclidean, there are no Cartesian coordinates at all. In such cases, you need to be vigilant, even when using 2D or 3D components without axisymmetry. COMSOL Multiphysics features built-in physics interfaces for these types of problems. They include the *Shell* and *Membrane* interfaces in structural mechanics, the *Thin-Film Flow* interfaces in fluid mechanics, the *Electric Currents, Shell* interface in electromagnetics, and more. For a more extensive list, take a look at our product specification chart.

Another approach to equation-based modeling is to use a physics interface as a PDE template for a problem with a similar mathematical structure. For example, to solve a physical problem that has a convection-diffusion-reaction nature, we can use either the *Heat Transfer* or the *Transport of Diluted Species* interfaces. These interfaces keep the tensorial meanings of differential operators in an axisymmetric component. All you need to do is to use the boundary and domain conditions that mathematically match the items you want to add.

The only downside to this strategy is that the units for the variables may not match the units you have. In such cases, you can use *nondimensionalization*. Once you obtain the dimensionless equations, you can make your COMSOL model dimensionless by going to the root of the Model Builder and setting *Unit System* to *None*.

*With nondimensionalization, you can use a physics interface to solve a different type of problem with a similar mathematical structure but different dimensions.*

With the *Coefficient Form PDE* and *General Form PDE* interfaces in COMSOL Multiphysics, you can implement partial differential equations to solve novel problems not yet built into the software. These partial differential equations may or may not be derived from a physical problem. Therefore, the differential operators in the PDE interfaces are by design kept simple and not converted to tensorial operators automatically. When solving a physical problem using curvilinear coordinate systems — say when you want to exploit axisymmetry — make sure that the items you enter in the software’s templates accurately represent your physical problem. In the physics-based interfaces, COMSOL Multiphysics takes care of this. But in the PDE interfaces, the software can not attach any meaning to your equations, leaving the responsibility to you.

One way to address this is to add extra source terms to balance the difference between partial derivatives and covariant derivatives. Another way is to use an existing physics interface that has the same mathematical structure as your equation. If you have any questions about these strategies or other questions pertaining to this topic, please do not hesitate to contact us.

For more details on differential operators in curvilinear coordinate systems and partial differential equations on surfaces, you can turn to various books on tensor calculus or differential geometry. Here are some of my personal favorites, in no particular order:

- Rutherford Aris,
*Vectors, Tensors, and the Basic Equations of Fluid Mechanics*, Dover Publications, Inc., 1989 - Pavel Grinfeld,
*Introduction to Tensor Analysis and the Calculus of Moving Surfaces*, Springer Science+Business Media, 2013 - Mikhail Itskov,
*Tensor Algebra and Tensor Analysis for Engineers: with Applications to Continuum Mechanics*, Springer-Verlag, 2013

The demands of a mesh generator can be quite extensive. The generated mesh, for instance, must conform to the geometry as well as create elements of the most optimal sizes and shapes. Elements where the edges and angles between them are close to being equal in size provide a greater chance of reaching solution convergence as well as more accurate results. Further, the generator may have to grade over short distances to create very small elements in tight spaces and very large elements in more open spaces without creating problems in the solution algorithms. Finally, it should be preferable that the generator acts automatically and works for all types of geometries.

Every meshing operation in COMSOL Multiphysics creates a mesh that conforms to the respective geometry. But the tetrahedral mesh generator, which operates under the *Free Tetrahedral* node in the Model Builder, is the only mesh generator in 3D that is fully automatic and can be applied to every geometry. And since it creates an *unstructured mesh* — that is, a mesh with irregular connectivity — it is well suited for complex-shaped geometries requiring a varying element size. Since tetrahedral meshes in COMSOL Multiphysics are used for a variety of physics, including multiphysics, the mesh generator needs to be very flexible. It should be possible to generate very fine meshes, very coarse meshes, meshes with fine resolution on curved boundaries, meshes with anisotropic elements in narrow regions, etc.

*A tetrahedral mesh of a gas turbine.*

Thanks to recent updates in COMSOL Multiphysics, you can now achieve improved quality in your tetrahedral meshing and thus advance the reliability of your simulation results. To demonstrate this, let’s walk through the steps of generating a tetrahedral mesh.

Most tetrahedral mesh generators fall into one of the following three classes:

- Advancing front-based generators, which pave the domain with tetrahedra, adding them one by one beginning from a boundary
- Octree-based generators, which first decompose the domain with an octree and then partition each octree cell into tetrahedra
- Delaunay-based generators, which maintain a geometric structure called the
*Delaunay tetrahedralization*of the domain and have remarkable mathematical properties

The tetrahedral mesh generator in COMSOL Multiphysics is a Delaunay-based mesh generator. As a Delaunay mesher, the process of generating a tetrahedral mesh can be divided into the five main steps described below. The third and fifth step of the meshing process have been significantly improved with upgrades to COMSOL Multiphysics version 5.2a. To illustrate the different steps, we’ll use a very coarse mesh of the piston geometry, which is available in the meshing tutorials of the Application Library within COMSOL Multiphysics.

*The geometry of the piston_mesh application.*

If you monitor the Progress window when building a tetrahedral mesh, you can see that the first 35% of the progress is devoted to the generation of the boundary mesh. But creating a boundary mesh that is well suited for the subsequent steps of the tetrahedral mesh generation process is not a straightforward task. There are several issues that must be addressed, such as:

- Adjusting the element size according to curved boundaries as well as distances between edges/faces across faces/domains
- Smoothly propagating the element size throughout the geometry
- Detecting self-intersecting edge and face mesh elements and resolving these problems
- Dealing with poorly parameterized CAD surfaces
- Dealing with virtual geometry definitions
- Creating high-quality triangles

*The boundary mesh for the piston_mesh application using the element size Extremely Coarse.*

The next step is to create the Delaunay tetrahedralization of the boundary mesh points, which form the convex hull of these points. These are also a set of points that have some nice mathematical properties, such as that no point of the point set will be placed inside the circumsphere of any tetrahedron. In 2D, the Delaunay triangulation of a set of points maximizes the minimum angle of all the angles of the triangles in the triangulation, although this property does not apply in 3D. Yet, there is no guarantee that the edge and triangle elements of the boundary mesh exist as edges and triangles in the Delaunay tetrahedralization of the boundary mesh points — not even for a convex boundary mesh. We will deal with this in the following step.

*The Delaunay tetrahedralization of the boundary mesh points forming the convex hull of the points.*

So far, we have generated the final boundary mesh and a Delaunay tetrahedralization of the boundary mesh points. Here, we will enforce the edges and triangles of the boundary mesh into the tetrahedralization. This is the most demanding part of the entire meshing process.

Last year, we released a completely new algorithm to account for this step, and the algorithm was significantly improved in COMSOL Multiphysics version 5.2a. In earlier versions, when meshing complex geometries, you may have received error messages like “failed to respect boundary element edge on geometry face” or “internal error in boundary respecting”. Such failures originated from this part of the meshing process. With the new improvements, it is possible to safely remove all tetrahedra on the outside of the boundary once all of the edges of the boundary mesh have been enforced into the tetrahedralization, and all of the tetrahedra intersecting the triangles of the boundary mesh have been addressed.

*The upper left part of the figure shows the boundary mesh in gray and the Delaunay tetrahedralization of the boundary mesh points in cyan. The zoomed view in the lower right part of the figure shows a few of the hundreds of tetrahedra that intersect edges and triangles of the boundary mesh. In this step, the tetrahedralization is modified such that no tetrahedron intersects the boundary mesh. Some additional points (so-called Steiner points) might be inserted to achieve a boundary conforming tetrahedralization.*

Now that we have a tetrahedralization across the entire geometry, with the boundary mesh from the first step serving as an outer boundary, we still have a tetrahedralization that does not contain any interior points (except the *Steiner points* that may have been added previously). Our next task is to refine the tetrahedralization by inserting points in the interior until the specified element size is achieved everywhere. The points can easily be inserted using a regular *Delaunay refinement* scheme. Some special treatment is needed though as at this stage, the tetrahedralization does not fulfill the Delaunay properties everywhere.

*The upper left part of the figure shows a cut through of the tetrahedralization after the third step, with only a few interior points inserted during that part of the meshing process. The lower right part of the figure shows the same cut through the tetrahedralization after the fourth step, where the tetrahedralization fulfills the element size specification also in the interior of the domain.*

At this point, we are almost done. But before we return the mesh to the user, we need to first improve the quality of the tetrahedra. Each tetrahedron can be assigned a quality value in the range of 0 to 1. A regular tetrahedron has a quality of 1 and a totally flat tetrahedron has a quality of 0. COMSOL Multiphysics version 5.2a delivers a new algorithm that further improves the quality of the meshes. The algorithm also features an option for reducing the risk of obtaining inverted curved elements as well as an option for avoiding the creation of elements that are too large.

In this step, we will increase the quality of the worst elements such that the quality of the mesh, which is largely dictated by the quality of its worst elements, is sufficiently good for a typical simulation. The new algorithm has a broader palette of operations for improving the quality of the mesh including point relocation (often referred to as *smoothing*) and topological modification operations such as edge and face swapping, edge collapsing, and vertex insertions. By applying these operations repeatedly, an infinite number of unique tetrahedralizations can be reached for a domain defined by its boundary mesh, which means a mesh with better quality will always exist. However, for a given tetrahedralization where the minimum element quality cannot be improved by smoothing, it’s not obvious which topological operation to perform to improve the quality. Sometimes even a series of operations must be applied — vertex insertion followed by edge flipping and smoothing — before you can reach an optimized mesh.

There are three optimization levels included in the algorithm: *Basic, Medium,* and *High*. These levels determine the amount of effort put into the optimization process. Say, for instance, you build your mesh using the Basic option (the default) and encounter problems with convergence when computing the solution or perhaps reduced accuracy in your results due to a poor quality mesh. In this case, you can rebuild your mesh with a higher optimization level to get a better chance at convergence with better results.

*The quality improvement algorithm offers three levels of optimization (Basic, Medium, and High) that determine how much effort is put into the optimization process.*

*These mesh cut throughs show the elements with the lowest quality before optimization (upper left), with the optimization level set to Basic (middle), and with the optimization level set to High (lower right). The red tetrahedra have a quality value less than 0.1, while the yellow tetrahedra have a quality value between 0.1 and 0.25. The gray triangles define the mesh cut through’s boundary mesh.*

The algorithm also offers two options for reducing the risk of obtaining inverted curved elements as well as reducing the size of the largest tetrahedra. Note that these selections come at the cost of a longer meshing time and slightly lower element quality.

*If the geometry includes fillets or other curved regions with a relatively coarse mesh, and you solve with a geometry shape order higher than one, you can select the* Avoid inverted curved elements *check box. This will let the optimization algorithm try to reduce the number of mesh elements that become inverted when they are curved. If the computation is sensitive to mesh elements that are too large, you can select the* Avoid too large elements *check box in an effort to avoid generating tetrahedra that are larger than the specified element size.*

Mesh generation is a concept that is rather easy to understand: It is all about partitioning a geometry into pieces of linear shape. There are, however, some difficulties to address when it comes to generating a tetrahedral mesh for simulation purposes. There will always be challenging geometries for which the generator fails or gives a mesh with elements that are of a lower quality. But with recent improvements to the tetrahedral mesher in COMSOL Multiphysics, you can now better address such complex geometries and further advance your modeling processes for continued optimization.

- Browse other posts on the COMSOL Blog relating to the topic of meshing
- Head over to our Video Gallery to check out videos that show you how to utilize meshing features and functionality in COMSOL Multiphysics

When assigning materials to your model geometry, you may want to experiment with a few options and see how different materials affect your simulation results. In COMSOL Multiphysics, you can automate this process via the *Material Sweep* parametric study and *Material Switch* feature. As such, you do not need to add several materials one at a time and compute for the corresponding solution. In addition to saving you time during model set up, this facilitates the comparison of results during postprocessing.

*Screenshot from the material sweeps video, showcasing the ability to switch between different results based on the material.*

The Material Switch node houses the materials that you want to sweep over and provides functionality to automatically switch materials while your model is solving.

In the five-minute tutorial video below, we outline the procedure for performing a material sweep in your model and then walk you through the steps for doing so. This includes adding a Material Switch node; specifying parts of the geometry that the material sweep will be applied to; selecting the materials to switch between; adding the Material Sweep parametric study; and finally postprocessing the sweep’s results. We also briefly discuss how you can customize the materials being swept over as well as how to easily toggle between different sets of results obtained from your material sweep.

As mentioned earlier, COMSOL Multiphysics features a large collection of built-in materials that are available regardless of which modules you hold a license for. Upon adding any of these materials to your model, you will notice that the material properties are provided with certain default values.

In some cases, material properties are constant. In other cases, they may vary in space or be dependent on a physics variable such as temperature. If you want to make a constant material property variable, or if the built-in variation is not what you want to use, you can define your own function. In COMSOL Multiphysics, there are three types of functions that you can use to define a material property: *Interpolation*, *Analytic*, and *Piecewise* functions.

*Data table and plot for an Interpolation function.*

Interpolation functions are used to define a material property through reading in data from a table or file that contains values of the function at discrete points. You can enter this data manually or import it from an external file. This is useful when you have material properties that are obtained from experiments. COMSOL Multiphysics will automatically evaluate and then generate a function that fits the data you provide. Then, you can also choose how the function interpolates between the measured values or extrapolates outside of your specified range of data.

*Input fields and plot for an Analytic function.*

Analytic functions are used to define a function using built-in mathematical functions or other user-defined functions. You can enter an expression, specify the input arguments, and define the value range for each of the arguments in your equation.

*Settings for a Piecewise function.*

Piecewise functions are used to define a material property using different expressions over different intervals. The start and end point for each set of values, as well as the function applicable to that interval, can be entered manually or imported from an external file. The intervals that you define cannot overlap and there cannot be any holes between the intervals. That way, you have a continuous function uniquely defined in terms of the independent variable.

In the following seven-minute tutorial video, we discuss how to create and define Interpolation, Analytic, and Piecewise functions for any material property in your model, the advantages of using each type, and best practices to keep in mind when creating them. We also go over the settings for each function type, demonstrate how the selection of options such as *Extrapolation* will change your data plot, and show how you can call out your function in the *Material Contents* table.

While creating a model in COMSOL Multiphysics, you will at some point need to identify the materials that your objects are made of. Normally, this requires completing a series of steps in which you open the Add Material or Material Browser windows; choose the material; select and add it to your component; and then go into the material node’s settings to select the parts of the geometry to which the material applies. You would then need to repeat this procedure for each unique material that you want to include in your simulation. In COMSOL Multiphysics, you can expedite the above process using global materials and material links.

*Screenshot displaying use of the global materials and material links functionality.*

When a material is added under the *Global Materials* node, it is available to use anywhere throughout the model. Further, global materials can be used for any geometric entity level, whether you assign them to domains, boundaries, edges, or points.

Material links are used locally under a component’s material node to refer to a global material. This is advantageous when you have a COMSOL Multiphysics file that contains multiple components that are made up of similar materials, as you only need to specify the material once under the Global Materials node and can then link to it under each individual component. It is also beneficial for models in which the same material is assigned to different geometric entity levels such as domains and boundaries. In this case, you would again only need to add the material once and could also add a separate *Material Link* node for each geometric entity type.

In the six-minute tutorial video below, we show you how to use the global materials and material links functionality. We begin by demonstrating how to add global materials to your model and discuss the differences between adding materials globally and locally. Then, we walk through the steps of how to add material links to your model components and assign them to the geometry. After watching this video, we encourage you to try out this functionality yourself and see firsthand the ease with which you can assign materials in a model that contains multiple components or when you want to use the same materials on multiple parts.

You can significantly expedite the process of assigning materials to your model geometry using the features and functionality discussed here. To complement these tools, we’ve created instructional videos to help you learn how to utilize them in your own simulations. Whether you have a model file that involves multiple components, need to define a complicated material property, or have to test different materials in your simulation, COMSOL Multiphysics features built-in tools that make this process simpler and more efficient for you.

- To learn more about specifying and defining materials in your COMSOL Multiphysics models, watch this introductory video series: How to Use Materials in Your COMSOL Multiphysics Models
- Head over to our Video Gallery to check out other videos on the topic of material-based features and functionality

The STL format, as mentioned previously on the blog, is one of the standard file formats for 3D printing, but it is also often used as the format for 3D scans. STL files contain only the triangulated surface, which we can also call a surface mesh, of a 3D object. COMSOL Multiphysics supports multiple objects in a single STL file, according to a widely used nonstandard extension of the format.

In its standard form, a text STL file begins with a line starting with `solid`

and ends with a line starting with ` endsolid`

. Many programs support text STL files that can contain several of these sections in one file. Importing this type of file now results in multiple geometric objects, the number of which depends on how many such sections are found.

*An STL file of a vertebra imported into COMSOL Multiphysics. This sequence shows a number of the steps that can be taken to simplify the mesh and thus the simulation of this geometry: the imported surface mesh, the generated geometry, the geometry after partitioning and, finally, embedding this geometry into a surrounding volume and the final mesh that results from this. Image credit: Mark Yeoman, Continuum Blue Ltd., UK.*

The NASTRAN® file format is the most common format for exchanging 3D meshes among simulation tools. This format supports hundreds of NASTRAN® file entries describing various mesh elements, loads, and materials, making it possible to define a complete finite element model. The COMSOL Multiphysics software supports the import of the mesh, selections, and materials.

If we compare these two formats from the point of view of a COMSOL Multiphysics user, we will find some similarities. Both formats contain a mesh, although the NASTRAN® format can contain both volume and boundary mesh in addition to all of the other information mentioned above. When importing these files into COMSOL Multiphysics, the most important concern is how to prepare them for simulation. What we need to do depends on the type of simulation as well as on the contents of the files. The mesh in a NASTRAN® file may already be of a good enough quality to suit our simulation; in this case, we don’t really need to do anything else but import and start defining the physics.

This blog post concerns all other cases when we need to create a new mesh in COMSOL Multiphysics, or we need to modify the imported mesh in some way. Modifications can include, for example, that we need to create a solid object from the imported surface mesh, or that we need to add a surrounding domain, or sometimes just to partition and delete portions of what is imported. All of these operations, including the creation of a new mesh, require working with a geometry in COMSOL Multiphysics. To help address cases like these, let’s take a look at how to create a geometry using an imported STL or NASTRAN® file.

A couple of versions back, the steps to create a geometry from a mesh in COMSOL Multiphysics became more user friendly and intuitive. Now, when you import an STL file or a mesh in NASTRAN® file format as a geometry, the software automatically creates a *Mesh Part* that we can easily access by clicking the *Go To Source* button next to the *Mesh* drop-down list.

*The *Go to Source* button in the Geometry Settings window will take you to the created *Mesh Part*.*

In the *Mesh Part*, we can influence how the boundary of the mesh is partitioned by using the *Boundary partitioning* setting. Using a *Minimal* boundary partitioning creates as few faces as possible, sometimes only one. The *Minimal* setting is usually a good choice when the source is a 3D scan. Then there’s the default *Automatic* boundary partitioning, which is best suited for cases where the imported mesh has a natural face partitioning (i.e., when the mesh is from a CAD design). There’s also an option to manually set the parameters by choosing *Detect faces*.

*Left: The *Boundary partitioning* settings of the mesh import. Right: An STL file imported with the *Minimal* boundary partitioning setting. Geometry image credit: Mark Yeoman, Continuum Blue Ltd., UK.*

The Detect faces option is most useful when a mesh comes from a 3D scan and has one or more planar faces. In this case, we prefer to have as few faces as possible, but we want the planar faces to have their own boundaries. To accomplish this, we can set the *Maximum boundary neighbor angle* to 180 degrees as this produces the same behavior as the *Minimal* setting. To detect the planar faces, it is important to keep the *Detect planar boundaries* check box selected.

For times when changing the *Maximum boundary neighbor* angle is not satisfactory for our needs, we may also need to adjust the *Minimum relative area* and the *Maximum neighbor angle*. The *Minimum relative area* setting limits how small the detected planar faces can be relative to the total area of the surface mesh, while the *Maximum neighbor angle* setting sets the maximum tolerated angle between neighboring boundary elements in the same planar face.

For example, to detect the two highlighted boundaries in the example below, we decreased the *Minimum relative area* to 0.001 and increased the *Maximum neighbor angle* to 1 degree.

*The *Detect faces* boundary partitioning feature (left) showing the exact settings used to create the geometry (right). Geometry image credit: Mark Yeoman, Continuum Blue Ltd., UK.*

If we need a boundary at a specific position, we can use the different partition features found under the *Mesh Part* menu. Using a *Ball*, *Box*, or *Cylinder* partitioning operation of a specified size can create boundaries that are not automatically detected or act as a complement to the *Minimal* boundary partitioning setting.

The next step in the import process involves creating a geometry with smooth edges and faces. The import settings involved influence how easy it is to build a working geometry out of the mesh.

*The geometry import settings highlighting the Simplify mesh settings.*

To make meshing the resulting geometry more robust, keep the *Simplify mesh* check box selected. If the triangles in the imported mesh are isotropic and define a relatively smooth surface, we can lower the *Relative simplification tolerance* and the *Defect removal factor* so that less simplification is performed.

By setting a tighter *Relative simplification tolerance*, we reduce the degree to which the mesh simplification algorithm can modify the mesh. This tolerance is relative to the entire geometry, while the *Defect removal factor* is relative to the local feature size. The two together limit how much the imported mesh can be modified at a certain location before it converts to a geometry. Based on personal experience, lowering one or both of these factors is more commonly required with meshes in NASTRAN® file format than with STL files.

*Left: Crankshaft mesh in NASTRAN® file format with fairly isotropic triangles and good representation of the shape. Middle: The created geometry with default settings. Right: The geometry with a lowered *Relative simplification factor* and* Defect removal factor*.*

On the other hand, raising the *Relative simplification tolerance* and *Defect removal factor* settings helps when the mesh triangles are anisotropic and the surface mesh doesn’t accurately represent the surfaces (i.e., when the mesh comes from scanned data). Increasing one or both of these parameters fixes more issues in the mesh, although it may result in a less accurate representation of the imported surface mesh.

*Left: Two anisotropic triangles among isotropic triangles. Middle: The geometry created with default import settings. Right: The geometry after increasing the *Defect removal factor*. Image credit: Mark Yeoman, Continuum Blue Ltd., UK.*

If a face appears strange, as pictured in the middle image above, it is usually due to problems that occur when generating the *rendering mesh*, or problems that occur when generating the on-screen visualization of the face. This could indicate that there is an underlying problem that will cause issues when, for example, partitioning the geometry, combining it with other objects, or even meshing. In this case, the geometry meshed without a problem and increasing the *Defect removal factor* produced a more “well-behaved” face.

The last import setting is the *Form solids from surface objects* check box, which creates solid objects from surface meshes with a ‘watertight’ region. This check box does not need to be selected when working with shells.

Another important note is that mesh files do not contain information about the *Length unit*, so this must be set manually in the settings window of the *Mesh Part* and the *Geometry* nodes.

*It is important to remember to set the correct *Length unit* for the *Mesh Part* and *Geometry*.*

After the mesh has been turned into a geometry, it is possible to add primitives, including blocks and spheres. It is also possible to introduce intersecting surfaces when performing Boolean operations where one geometry object is created from the mesh.

As the geometry’s surfaces are interpolated, they are not exact. Due to this, we can’t assume that the surfaces of an STL sphere, for example, are perfectly spherical. It is also difficult to combine these objects when they are expected to contain perfectly matching faces that are supposed to touch. In this case, it may help to apply the *Form an assembly* option and define *Identity pairs*, either automatically or manually, rather than using the default *Form Union* method to form the geometry for meshing.

For a design created in a CAD software, we recommend exporting it in an MCAD format and importing it with the CAD Import Module. In an earlier blog post, we discussed which module to choose for CAD import and concluded that the STL format is best when the data is originating from a 3D scan or when exporting deformed geometries or plots from COMSOL Multiphysics.

While changing the import parameters is not an exact science and involves some trial and error, we have demonstrated some best practices for creating a geometry from an imported mesh. We hope that you find these tips to be helpful as you utilize STL and NASTRAN® files within your own modeling processes. For more information about this topic and related areas of modeling, check out the resources below:

- To learn how to inspect the STL mesh and remove unwanted triangles, try out this tutorial: From Surface Mesh to Geometry: STL import of a Vertebra
- Read other posts related to meshing and geometry on the COMSOL Blog

If you have questions about this blog post or need help importing your meshes, please do not hesitate to contact us.

*NASTRAN is a registered trademark of NASA.*

COMSOL Multiphysics provides two ways for you to include only selected parts of a solution in your output. The first option is to define one or more selections, including the points, boundaries, or domains of interest, so you can restrict the output from the study to only include the fields in the parts of the geometry that those selections define. This method is straightforward and suitable if you are only interested in the simulation output within a certain part of the geometry, where you can perform postprocessing and access the fields and derived quantities as usual.

Note that if you store the solution for some boundaries or points, only the solution fields (the dependent variables) are available using this method. This means that derivatives and quantities that include derivatives, such as stresses and fluxes, are not available as they require that the solution is also available in the domain. If you are interested in storing some derived values such as stresses on just a few boundaries or points of interest, you will want to use our second option.

The second option is to add an *ODE and DAE* interface to define a new dependent variable, to which you can transfer the quantity of interest. The quantity of interest could be a global scalar quantity, such as the average or maximum of some field, or it could be the field value along some boundary. (In the latter case, using a selection provides an easier way of achieving the same result.) This method is useful in situations where the output of interest is a global scalar value that you transfer to a single degree of freedom as a variable within a simple algebraic equation. As mentioned above, it is also useful if the quantity of interest is a derived value based on derivatives, such as stresses and fluxes.

To only store the solution in a selected part of a geometry, create a named selection in the model component. To do so, right-click *Definitions* and choose a selection from the *Selections* submenu. An *Explicit* selection is simple to use if you want the selection to include some specific geometric entities — for example, domains, boundaries, or points. You can give the selection node a descriptive label like *Surrounding Air* or *Substrate Contact*. You can use several selection nodes to represent different parts of the geometry and combine them, either when determining what to store in the output or by creating another selection node that implements a Boolean operation, such as a *Union* or an *Intersection* selection node. Use one or more of these created selections in the study step settings to define the parts of the geometry for which the solution will be stored.

In a solid mechanics simulation, the value of the deflection (displacement) on one or more specific surfaces or points of interest can provide valuable information, which may be sufficient for you as the output from a simulation. The following plot, for instance, indicates the selected top surfaces on the model geometry for a feeder clamp within the Graphics window.

*Selected surfaces for a solid mechanics simulation.*

To store only the solution on those surfaces (boundaries), create an *Explicit* selection with the input entities set to the four top surfaces within the geometry where you want to store the solution. If a surface or point is not part of the created geometry, you can add extra *Curve* or *Point* nodes in the geometry sequence to divide a boundary or add a point (and a mesh node) at the desired location. The settings for the *Explicit* selection node appear as shown below.

Explicit *selection node settings.*

Here, the label has been changed to *Deflection Surfaces* to reflect what the selection contains.

You can now modify what to store in the output. In the Settings window of the *Study* step node, locate and expand the *Values of Dependent Variables* section. This section contains *Store fields in output* settings, where you can choose *For selections* from the drop-down menu. You can then click the *Add* button to open a list with available selections. In this case, choose the *Deflection Surface* selection and click *OK*.

*Settings for storing the deflection for the selected surfaces in the geometry.*

Now you can run your simulation. The only output will be the solution on the top surfaces, which you can visualize using a *Surface* plot.

*The displacement in the* y* direction on the selected surfaces in the geometry. For the rest of the geometry, there is no solution output.*

For the solution at points, you can postprocess the output using a *Point Evaluation* node under *Derived Values* and display the total displacement, for example. You can also use a *Point Graph* node in a *1D Plot Group* to plot the displacement versus time in a time-dependent simulation or a parameter value in a parametric sweep.

If you are interested in a scalar quantity, you only need a single degree of freedom (variable) that represents that quantity in the output. You can create such a variable as a simple algebraic equation using a global equation defined via the *Global ODEs and DAEs* interface. This interface and similar physics interfaces for defining ODEs and DAEs on domains or at points, for instance, are available under *Mathematics > ODE and DAE Interfaces* in the *Add Physics* window and in the Model Wizard. In the Settings window for the *Global Equations* node, define the name of the variable and the simple equation that sets it to the scalar quantity that you want to include in your simulation output.

Scalar coupling operators are important features in COMSOL Multiphysics to utilize for this purpose as well. With these powerful tools, you have the ability to create scalar quantities that are made globally available within the model.

Say that you are primarily interested in the average temperature within the model geometry. To extract its value, add an *Average Coupling Operator* (`aveop1`

, for example), defining it to be valid in the entire geometry (all domains) or in the domains of interest. You can then use this operator in a global algebraic equation to make it available in the simulation output as a scalar variable. If you want to store the maximum temperature instead, you can use a *Maximum Coupling Operator*.

The equation that the *Global ODEs and DAEs* interface solves for is

f(u,u_{t},u_{tt},t) = 0

In this case, however, the equation should only set the variable equal to the average temperature. As such, it is sufficient to enter `aveop1(T)-avtemp`

if you have called the variable in the algebraic equation `avtemp`

. Remember that the *Global ODEs and DAEs* interface sets the expression to zero to form the equation, thus solving the simple equation ` avtemp = aveop1(T)`

. Here, *T* represents the temperature field in the geometry, which is the dependent variable that you solve for but don’t want to include in the output. The following screenshot shows the Settings window for a *Global Equations* node in the *Global ODEs and DAEs* interface for this case.

Global Equations *node settings for creating a variable to store.*

Notice the *Units* section within the Settings window shown above. To avoid unit inconsistencies and to evaluate the created variable with the correct units, you should adjust the respective units for the dependent variable and for the source term.

Your final step is to set up the simulation so just the new scalar variable that you have defined is stored in the output. The following plot shows the average temperature in a geometry for a time-dependent simulation as a *Global* plot defined in a *1D Plot Group*.

*The mean (average) temperature versus time, computed as a single scalar output from a time-dependent simulation.*

In the study that you want to perform, first make sure that you have access to the solver configurations by right-clicking the main *Study* node and choosing *Show Default Solver*. Select *Solver Configurations > Solution > Dependent Variable* to access the settings for the dependent variables. In the cases above, there will be two nodes: a *Field* node (temperature) and a *State* node (average temperature). The first node represents the full temperature field in the geometry, while the second node represents the variable for the average temperature.

Click the *Temperature* node to display its Settings window. At the bottom of the *General* section, clear the *Store in output* check box so that the solver no longer stores the temperature field in the output.

*Clearing the* Store in output *check box within the* Temperature *node settings.*

When you have computed the solution, the scalar quantity will be available as a variable that you can display in a table using a *Global Evaluation* node. You can also plot a *Global* graph plot to show the deflection versus time or the mean temperature versus some parametric solutions. Since there are no field solutions, any plots that show such variables, or quantities using such variables, will appear with values of zero.

Let’s revisit our feeder clamp model to show how to use an algebraic equation to store the effective stress (von Mises stress) values on the top surfaces. To do so, add a *Boundary ODEs and DAEs* interface, available under *Mathematics > ODE and DAE Interfaces* in the *Add Physics* window and in the Model Wizard.

In the Settings window for the main *Boundary ODEs and DAEs* interface, use the same *Deflection Boundaries* selection for the top surfaces. Make sure to specify the units so that they are compatible with a stress quantity. You can do so by choosing *Stress tensor* as the quantity for the new dependent variable and for the source, which is the von Mises stress from the main *Solid Mechanics* interface.

*The settings for the* Boundary ODEs and DAEs *interface, set up for a mechanical stress quantity.*

In the *Distributed ODE* subnode, you define the algebraic equation that sets the new dependent variable *bndstress* (defined on the top surfaces only) equal to the predefined variable for the von Mises stress, *solid.mises*, from the *Solid Mechanics* interface: `bndstress-nojac(solid.mises)`

.

The `nojac()`

operator is required, since we do not want this equation to contribute to the Jacobian (the system matrix) for the full model. You enter this expression in the source term and set all other coefficients to zero to solve the equation `0 = bndstress-nojac(solid.mises)`

(that is, ` bndstress = nojac(solid.mises)`

).

*The settings in the* Distributed ODE *node for defining an algebraic equation for the boundary stress.*

Before solving, you have to clear the *Store in output* check box in the *Displacement field* node under *Dependent Variables* in the solver sequence. You can then compute the solution and only store the stress values on the top surfaces, which you can plot using a *Surface* plot.

*A plot of the von Mises stress, stored only for the top surfaces.*

As we have shown here today, with just a few simple steps, you can set up a simulation where only part of the fields computed for, or even just one or a few scalar quantities of interest, can be stored in the output. These modeling techniques can significantly reduce your model file size and the time it takes to calculate and display these scalar quantities of interest. This is especially true if you plan to make simulations that include large parametric sweeps or long, detailed time-dependent studies.

To learn about other tools in COMSOL Multiphysics that are designed to optimize your simulation workflow, browse other posts within our Core Functionality category on the COMSOL Blog. If you have further questions relating to the modeling techniques presented here, please feel free to contact us.

]]>

Solid objects change their size, shape, and orientation in response to external loads. In classical linear elasticity, this deformation is ignored in the problem formulation. As such, the equilibrium equations are formulated on the undeformed configuration. In many engineering problems, the deformations are so small that the deformed configurations are not appreciably different from the undeformed configuration. Ignoring the changing geometry therefore makes practical sense as this yields a linear problem that is easier to solve.

On the other hand, for problems like metal forming, where the deformation is large, the equilibrium equations have to include the effect of changing geometry. Updating the equilibrium equations to include the effect of changing geometry introduces a nonlinearity known as geometric nonlinearity.

*Model geometry for a sheet metal forming process, where deformations can be rather large.*

When geometric nonlinearity is included in structural analysis, the COMSOL Multiphysics® software automatically makes a distinction between *Material* and *Spatial* frames. The material frame corresponds to the undeformed configuration, while the spatial frame corresponds to the deformed configuration. The software allows us to make a new geometry out of the deformed configuration; what we refer to as *remeshing a deformed configuration*. We can use this geometry as part of a new geometry sequence. Drill a hole in it, subtract it out of a bounding object, or simply add other geometric objects. Finally, solve a new physics problem on the composite domain. The new physics can be applied to the same COMSOL Multiphysics model in a different *component*, or in a different *model*. This is the first point that we will address.

If geometric nonlinearity is not included in structural analysis, the software does not distinguish between the material and spatial frames. Does that mean that if you do not want to include the effects of geometric nonlinearity in the equilibrium equations, you can not remesh a deformed configuration? The answer is no. You can split the two frames and force linear strains in the equilibrium equations. This is the second item that we will address.

For three-dimensional problems, there is an additional option. Surface plots can be exported as STL files. These files can be imported and used for solid modeling. In this process, we do not need to split the material and spatial frames. This is the third and last item we will discuss in today’s blog post.

Please note that

remeshing a deformed configurationmeans simply obtaining the deformed shape computed in structural analysis. When we use this deformed geometry for a later analysis, we are not considering residual stresses. If the second analysis is another structural analysis, keep in mind that the remeshed configuration is being used as a stress-free configuration for subsequent studies.

To consider effects of finite deformation in structural analysis, we have to select the *Include geometric nonlinearity* check box in the settings window of the study step. In some cases, COMSOL Multiphysics automatically enables geometric nonlinearity, such as when you include hyperelastic or other nonlinearly elastic materials, large-strain plastic/viscoelastic materials, or add any contact boundary conditions.

After we complete our structural analysis, we use the *Remesh Deformed Configuration* command to get the deformed shape. This is done in the meshing section of the Model Builder. Finally, the deformed mesh can be exported and imported back as a geometry object.

We demonstrate the above steps in the following sections.

Let’s consider the problem of squeezing a circular pipe between two flat stiff indenters. Because of the large deformation involved, geometric nonlinearity is included in the structural analysis, as shown in the screenshot below. Because of symmetries, we consider only a quarter of the geometry.

*The original geometry (outline) and the deformed geometry.*

The next step is to remesh the deformed configuration. This can be done by right-clicking on the data set (*Study 1/Solution 1* in this example) and choosing *Remesh Deformed Configuration*. Alternatively, we can use *Results > Remesh Deformed Configuration* from the menu while the data set is highlighted.

In either case, this adds a new mesh to the mesh sequence and opens the *Deformed Configuration* settings window. Next, we click on *Update*. Note that for parametric or time-dependent problems, we have to pick a parameter value or time step.

*Each parameter of a parametrized data set has its own deformed configuration.*

Finally, we go to the new mesh under *Meshes > Deformed Configuration* and build it.

*Remeshing a deformed configuration creates a new meshing sequence.*

One possibility is to reuse the deformed configuration in the same model file. To do so, we add another component and import the deformed mesh in the *Geometry* node of the new component, as highlighted in the screenshot below.

*A deformed mesh from one component can be imported in the geometry sequence of another component.*

We can now add more items to the geometry sequence. Let’s cut out from the bent pipe. We probably do not need the rigid indenter once we have used it to squeeze the pipe and will therefore get rid of it. The result is shown in the screenshot below. A new physics can be added to the second component.

*Deformed objects resulting from structural analysis can be used as part of a new geometry sequence.*

To use the deformed configuration in a different model file, export it to a separate file first.

If the *Include geometric nonlinearity* check box is unchecked, the spatial frame stays the same as the material frame. Therefore, we can not remesh the deformed configuration. If we do select the check box, COMSOL Multiphysics will include nonlinear terms in the strain tensor. What if we have a problem with infinitesimal strains and do not want to include expensive and unnecessary nonlinear strains in the equilibrium equations? The solution is to select the *Include geometric nonlinearity* check box in the study step, while ignoring the nonlinear strain terms by selecting the *Force linear strains* check box in the material model.

*Splitting material and spatial frames while keeping only linear strains in the equilibrium equation.*

The procedure for remeshing the deformed configuration remains the same as in the previous section.

The above method, including geometric nonlinearity and remeshing the deformed configuration, can be applied to both 2D and 3D problems. In 3D cases, we have an additional option via STL files. Any 3D surface plot can be exported as an STL file. This file can then be imported in the geometry sequence of another component or model file. By adding a *Deformation* node to a surface plot before exporting, we can get the deformed geometry. Do not include geometric nonlinearity, unless your problem is a large deformation problem.

*Add a deformation to a 3D surface plot and export the surface plot in the STL format.*

We can edit the *X*-, *Y*-, and *Z*-components of the displacements in the *Deformation* settings window of the above screenshot to introduce anisotropic or nonuniform scaling of the displacements. In fact, these quantities do not need to be structural displacements. By typing any valid mathematical expression for deformation components, we can subject the original geometry to arbitrary transformations.

To use the deformed geometry in a new file or component, the STL file generated in the above step can be imported in a geometry sequence, as shown below.

*Importing an STL file to a geometry sequence.*

COMSOL Multiphysics allows seamless coupling of different physics effects. If you want to couple structural analysis with another physics on the same domain, you will find built-in tools within our software that enable you to do so. The *Moving Mesh* and *Deformed Geometry* interfaces are often used together with physics interfaces to solve problems on evolving domains.

However, if you want to use the deformed configuration from a structural analysis as part of a new geometry sequence, where you add new objects to the deformed shape or include it in Boolean operations, you can apply the strategies demonstrated above.

As always, if you have any questions, please feel free to contact us.

]]>

To begin, let’s consider the needs of an app that uses external files:

- A user interface (UI) object for users to browse to file locations
- A UI object to let users choose between options read from the files
- Code to change relevant model object settings according to users’ selections

For the first and second items, the *File Import* object and a *Combo Box* in the Application Builder are good options. Meanwhile, there are a number of tools available that make the third task quite simple. One such tool is the *Record Code* feature, which generates equivalent Java® code for the tasks we perform using the user interface in the COMSOL Multiphysics® software.

When building apps, we often need more code than the methods that set the model inputs. Such auxiliary methods can convert data, manipulate arrays, or interact with the operating system, among other tasks. Again, the Application Builder includes built-in methods for such tasks, allowing you to add features to your apps with minimal coding.

Here, we will demonstrate these ideas by extending the functionality of a tuning fork app. First, we will add a combo box to select between tuning forks made of aluminum, brass, or steel. Then, we will add a File Import object to read materials from a data file.

Tuning forks are used to calibrate musical instruments to a standard pitch. Tuning fork-like structures, however, are also used in industrial applications such as MEMS gyroscopes.

In an earlier blog post, we presented a tuning fork app that calculates the natural frequency of a steel tuning fork given its length. The app does the reverse as well, determining the length to achieve a target frequency. In our original demonstration, we fixed the prong radius to one commercially available size. As such, users could only adjust the prong length.

*The original tuning fork application. The prong length can be changed, while other inputs are fixed.*

Say that you now want users to change the material or prong radius. One way to do so is to insert *Input Field* or *Slider* objects. These UI objects allow users to specify any values. On the other hand, the tuning fork market has only certain materials and prong radii. When you want an app to offer choices between discrete options, a Combo Box is one suitable object.

These options could be hardcoded if all of the available choices are known when the app is created. But what if new choices become available on the market after the app is distributed? Hardcoding the new options and redistributing the app is not ideal. A better plan is to design an app that allows users to point to a data file and make the app populate combo boxes and other UI objects. Whenever the available choices change, users can simply provide a new data file containing the updated options. This way you make the app enforce market or company standards, without presumptively setting the standards in stone.

A Combo Box helps users select from a predefined list and sets the value of a variable according to their choice. The available choices are specified in a *Choice List*, which features a *Value* and *Display name*. The *Display name* is a description that users see in the UI, while the *Value* is what the variable will contain. Such variables associated with input objects in the UI are called the input object’s *source*. An app programmer can, for example, use a variable in a conditional statement to execute a set of actions based on the selected entry.

The series of screenshots below show how to add a combo box for a material selection in the tuning fork app. *Aluminum, Brass,* and *Steel* are the predefined choices. Notice that we write full names for *Display name* but use shorter versions for *Value*. The source, the string **mat**, takes either **alm, brs,** or **stl** when the user clicks on *Aluminum, Brass,* or *Steel*.

*Associating a Choice List with a Combo Box.*

If we run the application now, clicking the combo box sets the string ** mat** to either

Let’s name this new method *change_material*. In the method, we need to include Java® code for updating the density, Young’s modulus, and Poisson’s ratio. To this end, we perform the following steps:

- Click
*Record Code* - Switch to the Model Builder and change the material properties to some numerical values
- Click
*Stop Recording*

The software will give us the Java® code corresponding to the set of actions we performed in the Model Builder. This is more efficient and less prone to error than looking for object names and methods in the *COMSOL Programming Reference Manual*.

*Adding a new method and using record code to obtain the code for changing density, Young’s modulus, and Poisson’s ratio.*

The Java® code above, obtained using the Record Code feature, fixes the material properties to one set of values. Next, we add a conditional block to choose material properties based on the string mat. Don’t want to have to remember the Java® code syntax for an if-else statement? Use the *Language Elements* feature! Finally, we associate the method with the *On data change* event of the combo box, as shown below.

*The Language Elements feature can be used to get Java® code syntax, if needed.*

Note that even when you are only interested in scripting, with no plan to make an app, you can utilize the Record Code feature to quickly and easily generate code. To learn more, read our blog post “Apps: How to Use the Editor Tools and Record Code Features“.

To incorporate external files, the app has to enable users to browse to such files. The Application Builder has a File Import object for this purpose. As when adding any input object, we take the following two steps:

- Associate the File Import object with an item in the model or a declaration
- Code a method that runs when the data in the input object changes

The first task is mandatory. In the current example, we will associate the File Import object with a File declaration. A File Import object stores a file path and generates an alias to the path.

The second task, which has a method run right after an input object’s data change, is optional. For instance, the value might only be used later when computing the solution. But the app we are creating has to execute the following actions when the file name in the File Import object changes:

- Read the file and store its content in a string matrix
- Store the labels for all of the rows in a string array
- Update the values and display names of the combo box based on the contents of the data file just read

To this end, we will create a new method, *read_materials_file*, and link it with the File Import object’s *On data change* event, as illustrated in the following screenshot.

*Adding a File Import object and associating it with a File declaration and* On data change *event.*

Let’s now write the code for this method. In the Application Builder, methods are written using the Java® programming language. We could write such codes from scratch but the Application Builder’s Method Library contains several built-in methods for file input/output and other actions, making the process more efficient.

For reading comma-separated values (CSV file), we can use the *readCSVFile* method. The argument to this method is a string for the file path and the output is a string matrix.

`String[][] readCSVFile(String name)`

For the purpose of this demonstration, we assume that the first column of the data file contains material labels, such as *Aluminum* and *Steel from supplier 1*. We want to extract this column and display it in the combo box. To extract a column from an array, we can use the built-in *getColumn* method. The arguments are a string matrix and the column number. The column index starts from zero, as is the case with Java® code array indices.

`String[] getColumn(String[][] matrix, int column)`

To change values in a Choice List, we can use the built-in *setList* method. This method changes the values and display names of a Choice List to the strings in the argument.

`setList(String[] value, String[] displayNames)`

Using the above built-in methods, we obtain the following short code for reading a CSV file, storing the contents, and updating the combo box’s Choice List.

*The built-in Method Library in the Application Builder contains several methods for manipulating data or UI objects, file reading/writing, and interacting with the operating system.*

Let’s clarify the string **upload:///file_matCSV** and the integer array **matindex** in the above method. The string **upload:///file_matCSV** represents the file path. Go to the *Access using* section in the File declaration settings window to find this alias. The integer array **matindex** makes up values for the combo box’s Choice List.

In the method, we assume the first column in the CSV file to be material labels. These labels, extracted using the built-in method *getColumn*, are displayed in the combo box. The values, on the other hand, are internal tags for programming. As such, we should not expect an app user to supply them. Since we can not foresee the number of rows in the data file, we can not hardcode the *value* string either.

What we can do instead is get the number of rows in the file and store as many integers in an integer array. This entails changing the source data of the combo box from a string to an integer (see the integer *imat* in the screenshot below). Finally, make the built-in *toString* method convert the integer array to a string array for the *setList* method. That way, when a user clicks on the combo box, the integer changes to the index number of the selected row. The app can then use this number to go to the relevant row in the string matrix holding the file’s content.

The above modifications result in the following method.

*Combo boxes can use strings or integers as sources.*

Notice the old code for hardcoded material options is still around. Our goal is to let users incorporate their own material data file, if they have one. Otherwise, they need alternate options. To that end, we make a new method out of the commented section and have it called when users prefer the built-in choices to external data files. This preference can be expressed, for example, by checking on/off within a check box. The resulting implementation is highlighted below.

*A Boolean variable associated with a check box can be used to switch between a material data file and alternate hardcoded options.*

A method local to the check box object is used to enable the file browser or disable the browser and populate the combo box with default options, based on the value of the check box. The Record Code feature is again used to get the Java® code for enabling and disabling the file browser.

*A user interface object can have a local method that runs when a user interacts with that particular object. Local methods can not be called from elsewhere in the app.*

Now let’s utilize our app with the following sample CSV file.

*Apps can be linked to a user-specified data file.*

Here’s a look at the final version of the app in action.

The main purpose of today’s blog post is to demonstrate how to link apps to external data files. Note that some auxiliary refinements have been left out.

We assumed that the data file contains labels, densities, Young’s moduli, and Poisson ratios in columns in that order. It is possible that the data file is not in that order or contains some columns that are unnecessary for the app’s purpose. Rather than asking users to restructure their file to conform to our assumptions, we can add input fields or dialog boxes in the app to ask the user which column contains what information.

Consider the case where a user has more than one data file, say from different suppliers and possibly with different formats. Instead of reading just one file at a time, we may want to make the app append the Choice List every time a new file is read. The Application Builder has built-in methods for appending arrays, finding unique values when there are duplicates, writing the appended data to an output file for future use, and more.

In this app, the mechanical properties and length of the tuning fork can be edited while the radius is fixed. If the radius needs to be read from a data file as well, we just need to use the Record Code feature to get the Java® code for changing the radius and add it to the methods above. This is true for any model input.

We have taken for granted that the data will be in the right units. If this is not certain, we can use the Application Builder’s built-in methods for string manipulation and data validation to take care of that.

We have shown you how to use an external data file with an app. This feature helps you design apps that cater to evolving company or market standards, without the need for modifying the code when such changes happen. The same techniques for file reading and manipulation may come in handy if your app needs a lengthy list of inputs. App users can easily store their frequently used sets of values in a data file.

To effectively and efficiently create apps, we encourage you to utilize the Application Builder’s Method Library. It contains several methods that can enhance the functionality and usability of apps. For more details, you can refer to the *Introduction to Application Builder* manual, particularly the *Built-in Method Library* appendix.

For further information on the basics of building COMSOL apps, be sure to check out our Intro to Application Builder Videos series as well as this blog post on automating model preprocessing with the Application Builder.

If you have any questions about this blog post or building simulation apps, please do not hesitate to contact us.

*Oracle and Java are registered trademarks of Oracle and/or its affiliates.*

The mesh that you choose for your COMSOL Multiphysics simulation strongly affects your modeling requirements. In fact, meshing is one of the most memory-intensive steps when it comes to setting up and solving a finite element problem.

Identifying the mesh best-suited for your particular model often involves choosing the correct element types and sizes. In COMSOL Multiphysics, meshing utilizes four different element types: tetrahedra (tets), hexahedra (bricks), triangular prisms (prisms), and pyramids. There are also nine preset element size settings, which range from *Extremely fine* to *Extremely coarse*.

*Images of different element types. From left to right: a tetrahedron, hexahedron, triangular prism, and pyramid.*

Meshing, like many of the tools available in COMSOL Multiphysics, is customizable and interactive. In just a few steps, you can easily mesh individual faces or domains. Further, the default physics-controlled meshing sequences create meshes that consist of different element types and size features, which you can use as a starting point to add, move, disable, and delete meshing operations. Each meshing operation is built in the order it appears in the meshing sequence to produce the final mesh. Customizing the meshing sequence can help reduce memory requirements by controlling the number, type, and quality of elements, thereby creating an efficient and accurate simulation.

Let’s say that you want to model an electronic component that is mounted on a circuit board by solder joints. Such a device may generate high temperatures when turned on for extended periods of time. As noted in a previous blog post, overheating can damage the device itself and may even present a fire hazard.

In the case of our tutorial model, exposure to extended periods of heat can cause creep in the solder joints holding the electronic component in place. This may eventually result in permanent deformation and failure of the joints. Here, we’ll examine how different meshes can be used to study such a device.

*An electronic component that is mounted on a circuit board by solder ball joints.*

To begin, we’ll use the default *Physics-controlled mesh*, which is a simple, unstructured tetrahedral mesh. This mesh is automatically created and adapted for the model’s physics settings, with the element size defaulting to *Normal*, and the meshing sequence, consisting of a *Size* and a *Free Tetrahedral* node, is hidden.

*A default mesh on the electronic component geometry.*

The resulting mesh, shown above, consists of about 45,000 elements. While this number of elements does resolve the geometry quite well, it does so in all regions of the geometry even where much fewer elements would be adequate to use for meshing, thus reducing memory requirements. Let’s see how modifying the meshing sequence can reduce the number of mesh elements…

In order to reduce mesh elements, we can customize the mesh to be more detailed at the spherical domains, which represent the joints, and coarser throughout the rest of the geometry. To do this, we can now turn our attention to the local and global size attributes in the meshing sequence. In the default meshing sequence, the settings of the first *global attribute* feature are applied to the following *Free Tetrahedral 1* node. The name global attribute feature is given to the first *Size* feature node used in a sequence because it influences all of the operations that follow it.

To achieve our goal, we add a *local Size attribute*, which applies to the individual solder joint domains, to the *Free Tetradhedral 1* operation. Doing so enables us to focus on the key elements of our design. The initial mesh utilizing this method consists of approximately 28,000 elements, almost half the number of elements as the default mesh.

*A customized mesh, which contains more mesh elements around the spherical domains.*

To further reduce the element number, we can apply a swept mesh, which notably reduces the size of a model and its computational complexity. In our example, we modify the *Free Tetrahedral 1* operation to apply only to the domains of the solder joints. Now we want to use the upper part of the circuit board and the electronic component as the sources for our swept mesh. It is important to note, however, that a few of these model faces are already meshed as they border the solder joints.

Next, we add a *Free Triangular* feature node to our meshing sequence. Since COMSOL Multiphysics adds new nodes into the meshing sequence after the current feature node, the *Free Triangular 1* node becomes the current feature instead of the existing *Free Tetrahedral 1* node. If desired, you can easily change this by moving the order of the nodes in the meshing sequence. Keep in mind that doing so may cause build errors if an operation depends on earlier operations in the sequence.

*Mesh with an added *Free Triangular 1* feature node.*

We can now once again turn our attention to the local and global size attributes in the meshing sequence. When we created the *Free Triangular 1* node, the mesher applied the settings of the first global *Size* feature. We are able to add a coarser triangular mesh to the *Free Triangular 1* operation using a local size attribute. The new mesh, however, has an almost identical appearance to the previous iteration. This is due to the fact that the mesher had to utilize the solder joints’ preexisting mesh on the edges and the global size settings (which are set as *Normal*) on the outer edges. Therefore, the local coarser mesh was only applied to the interior of the meshed faces.

To avoid this issue, we simply need to ensure that the first global *Size* node is set as the coarsest mesh in your entire geometry. Then, you can create local size feature nodes for meshing operations that require finer meshes. After applying this technique, we utilize a *Coarser* predefined mesh size for the swept mesher and continue sweeping the source mesh throughout our remaining domains. The result is a mesh that contains around 17,000 elements.

*Revised mesh with even fewer elements.*

If you would like to more precisely control the number of mesh elements, you can choose to specify the distribution for the swept mesher yourself. When applying this approach to our tutorial example, the mesh includes about 21,000 elements, with a higher resolution confined to the domains important to our analysis, the solder joints.

*Mesh focusing on important design elements, while remaining less dense in other areas.*

As we have demonstrated here, modifying meshing sequences is a powerful tool for greatly reducing mesh elements and thus minimizing computational time — all while still delivering accurate results for the key areas of a geometry. Interested in learning more about meshing? Take a look at the resources highlighted below.

- Download the tutorial model: Using Meshing Sequences
- Browse the COMSOL Blog for further posts related to the topic of meshing
- Check out these videos to learn more about utilizing the meshing capabilities of COMSOL Multiphysics:

In a previous blog post on modeling the harmonic excitations of linear systems, we identified two conditions under which it is possible to model the transient response of a system in the frequency domain. These two conditions are:

- All time-varying loads and constraints on the system must vary sinusoidally at the same fixed frequency.
- All loads, constraints, and material properties must be independent of the solution.

Today, we will look at relaxing both of these assumptions a bit. Let’s begin our discussion with a very common case of a system where the loads do not vary purely sinusoidally in time: the vibration of a tensioned guitar string. As we all know, when you increase the tension on a guitar string, the pitch (the fundamental frequency of vibration) increases.

*The strings of a guitar vibrate at different frequencies based on the string tension.*

Let’s consider such a case in terms of the generic partial differential equation from our earlier blog post:

(1)

\begin{align}

M u_{tt} + C u_t + \nabla \cdot (-K \nabla u) = F_0+\tilde F sin(\omega t) &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla u) + Au = f _0 + \tilde f sin(\omega t ) &\text{ on } \Gamma_1 \\

u = g_0 + \tilde g sin ( \omega t) &\text{ on } \Gamma_2

\end{align}

M u_{tt} + C u_t + \nabla \cdot (-K \nabla u) = F_0+\tilde F sin(\omega t) &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla u) + Au = f _0 + \tilde f sin(\omega t ) &\text{ on } \Gamma_1 \\

u = g_0 + \tilde g sin ( \omega t) &\text{ on } \Gamma_2

\end{align}

where the body loads, , boundary loads, , and constraints, , are decomposed into a constant component and a sinusoidally time-varying component. As a structural engineer, you might refer to this as a decomposition into static and dynamic components. As an electrical engineer, you would describe these elements as the DC and AC components, respectively.

We can further assume that the dynamic components are much smaller in magnitude than the static components, that is: , , and . If the dynamic loads are relatively small, then it is reasonable to assume that the dynamic loads will lead to small oscillations for the statically loaded case. That is, we are assuming that the solution will take the form: . This is also known as a *harmonic perturbation*, or a *frequency-domain perturbation*. In COMSOL Multiphysics, we refer to this as a *Prestressed Analysis* study for the structural mechanics physics interfaces; a *Small-Signal Analysis* study for the electromagnetics physics interfaces; and an *AC Impedance* study for the electrochemistry physics interfaces.

These study types all have the same underlying solution approach. They start out by ignoring the sinusoidally time-varying component and first solve the stationary problem:

(2)

\begin{align}

\nabla \cdot (-K \nabla u_0) = F_0 &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla u_0) + Au_0 = f _0 &\text{ on } \Gamma_1 \\

u_0 = g_0 &\text{ on } \Gamma_2

\end{align}

\nabla \cdot (-K \nabla u_0) = F_0 &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla u_0) + Au_0 = f _0 &\text{ on } \Gamma_1 \\

u_0 = g_0 &\text{ on } \Gamma_2

\end{align}

where, in fact, both the material properties and loads can be directly dependent on the solution. That is, , , , and . This means that the stationary problem can actually be nonlinear, which doesn’t really complicate the analysis as long as the combination of the material nonlinearities, static loads, and constraints represent a well-posed problem. For a better understanding of how to address such nonlinear stationary problems, take a look at our Solver series.

After solving for the stationary response of the system, we can use the static solution, , to evaluate the nonlinear material properties used by the frequency-domain perturbation form of the governing equation:

(3)

\begin{align}

-\omega^2 M(u_0) \tilde u + j \omega C(u_0) \tilde u + \nabla \cdot (-K(u_0) \nabla \tilde u) = \tilde F &\text { on } \Omega \\

\mathbf{n} \cdot (K(u_0) \nabla \tilde u) + A(u_0) \tilde u = \tilde f &\text{ on } \Gamma_1 \\

\tilde u = \tilde g &\text{ on } \Gamma_2

\end{align}

-\omega^2 M(u_0) \tilde u + j \omega C(u_0) \tilde u + \nabla \cdot (-K(u_0) \nabla \tilde u) = \tilde F &\text { on } \Omega \\

\mathbf{n} \cdot (K(u_0) \nabla \tilde u) + A(u_0) \tilde u = \tilde f &\text{ on } \Gamma_1 \\

\tilde u = \tilde g &\text{ on } \Gamma_2

\end{align}

For structural problems, the static solution will also represent the deformed state of the system. The frequency-domain perturbation equations are formed on this deformed state, introducing a so-called geometric nonlinearity, in addition to the material nonlinearity.

The above governing equation can also be posed as an eigenfrequency problem by homogenizing all loads and constraints, that is, setting each of them to zero magnitude.

Our Application Gallery features a number of tutorials that demonstrate this solution approach. Here are some examples:

- Vibrating String
- Vibrating Membrane
- Piezoelectric Tonpilz Transducer with a Prestressed Bolt
- Pull-In Voltage for a Biased Resonator — 3D
- Small-Signal Analysis of an Inductor
- Small-Signal Analysis of a MOSFET
- Electrochemical Impedance Spectroscopy

Up to this point, the examples presented have all assumed that the response of the system due to the frequency-domain loading is linear. That is, we previously assumed that if any of the frequency-domain loads or constraints () are increased in magnitude by a scalar value, then the frequency-domain solution will increase in magnitude by the same scalar value. Of course, for such an assumption to hold, the loads, constraints, and material properties must all be independent of, , the frequency-domain solution. There are, however, many cases where this is not true. Let’s find out how to address some of these situations.

We can start with a case where material properties are dependent on the cycle-averaged solution. Since the field, , is complex valued, the cycle-averaged magnitude is given by: . This allows us to solve governing equations of the form:

(4)

\begin{align}

-\omega^2 M(|\tilde u|) \tilde u + j \omega C(|\tilde u|) \tilde u + \nabla \cdot (-K(|\tilde u|) \nabla \tilde u) = \tilde F(|\tilde u|) &\text { on } \Omega \\

\mathbf{n} \cdot (K(|\tilde u|) \nabla \tilde u) + A(|\tilde u|) \tilde u = \tilde f(|\tilde u|) &\text{ on } \Gamma_1 \\

\tilde u = \tilde g(|\tilde u|) &\text{ on } \Gamma_2

\end{align}

-\omega^2 M(|\tilde u|) \tilde u + j \omega C(|\tilde u|) \tilde u + \nabla \cdot (-K(|\tilde u|) \nabla \tilde u) = \tilde F(|\tilde u|) &\text { on } \Omega \\

\mathbf{n} \cdot (K(|\tilde u|) \nabla \tilde u) + A(|\tilde u|) \tilde u = \tilde f(|\tilde u|) &\text{ on } \Gamma_1 \\

\tilde u = \tilde g(|\tilde u|) &\text{ on } \Gamma_2

\end{align}

This nonlinear partial differential equation can actually be solved with exactly the same algorithms described in our Solver series. So, in fact, there is almost nothing “extra” that we need to learn in order to address such problems, other than to enter the appropriate expression for the material nonlinearity. For an example of such a problem, see our tutorial model of self focusing in a BK-7 optical glass, where the refractive index, , is directly dependent on , the electromagnetic field intensity.

The material property does not need to be such a simple function of the cycle-averaged magnitude. The AC/DC Module, for instance, includes an effective HB curve modeling approach that uses the nonlinear material relationships described in this previous blog post on modeling magnetic materials in the frequency domain.

So far, we have only considered a material response that is nonlinear with respect to the cycle-averaged field magnitude. It is, however, also possible for the sinusoidal excitation on the system to couple into a higher harmonic excitation of the system. To understand why this is so, keep in mind that our excitations vary in time as and that we have assumed that our solution will also vary sinusoidally in time and at the same frequency: . But, if there is any material response that depends directly on the instantaneous (not cycle-averaged) field magnitude, then we can use the trigonometric identity to deduce that the response is actually of the form: .

This type of response, referred to as *frequency-doubling* or *higher harmonic generation*, is fairly common in electromagnetics, especially optical systems. Although there may, in fact, be many higher harmonics, in practice, only one or two higher harmonics are likely of engineering interest. In such cases, we can write a new set of general governing equations:

(5)

\begin{align}

-\omega^2 M \tilde u_1 -j \omega C \tilde u_1 + \nabla \cdot (-K \nabla \tilde u_1) = \tilde F_1 -Q &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla \tilde u_1) + A \tilde u_1 = \tilde f_1 &\text{ on } \Gamma_1 \\

\tilde u = \tilde g_1 &\text{ on } \Gamma_2 \\

-4 \omega^2 M \tilde u_2 -j 2 \omega C \tilde u_2 + \nabla \cdot (-K \nabla \tilde u_2) = + Q &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla \tilde u_2) + A \tilde u_2 = 0 &\text{ on } \Gamma_1 \\

\tilde u_2 = 0 &\text{ on } \Gamma_2

\end{align}

-\omega^2 M \tilde u_1 -j \omega C \tilde u_1 + \nabla \cdot (-K \nabla \tilde u_1) = \tilde F_1 -Q &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla \tilde u_1) + A \tilde u_1 = \tilde f_1 &\text{ on } \Gamma_1 \\

\tilde u = \tilde g_1 &\text{ on } \Gamma_2 \\

-4 \omega^2 M \tilde u_2 -j 2 \omega C \tilde u_2 + \nabla \cdot (-K \nabla \tilde u_2) = + Q &\text { on } \Omega \\

\mathbf{n} \cdot (K \nabla \tilde u_2) + A \tilde u_2 = 0 &\text{ on } \Gamma_1 \\

\tilde u_2 = 0 &\text{ on } \Gamma_2

\end{align}

where there is a general domain coupling term, , between the two sets of equations. For simplicity, the static components are omitted. Also keep in mind that all material properties can be dependent on the frequency and thus vary for the different harmonics. Now, what we have here is a set of governing partial differential equations with a nonlinear coupling term. Solving these equations simply requires looking to the same solution approaches that we introduced here.

Download this tutorial model to see an example that demonstrates the modeling of second-harmonic generation in the frequency domain.

There does come a point past which you can no longer exploit the assumptions that we’ve discussed here to simplify the problem, even if you have sinusoidal excitations. In such situations, you will want to shift focus to time-domain modeling. Although modeling in the time domain will take longer than it would in the frequency domain, you can capture the full temporal evolution of the solution and incorporate any kind of nonlinearity, even one that leads to a nonsinusoidal response.

Within the Application Gallery, you can find several general examples of time-domain modeling. They include:

- Nonlinear Acoustics — Modeling of the 1D Westervelt Equation
- Vibrating Beam in Fluid Flow
- Second Harmonic Generation of a Gaussian Beam

If you have any questions about the modeling approaches discussed here and think they would be useful for your multiphysics modeling needs, please don’t hesitate to contact us.

]]>