-
-
November 4, 2024 at 4:11 pmJason SumSubscriber
Re the post: Multi-Objective Shape Optimisation of Tesla Valve dated 11 Sept 2024
My project obejective is to optimise the shape of tesla valve and maxmise diodicity of the valve, in which diodicity comes from the two separate modelling cases (forward flow and reverse flow)
As the outlet and inlet for the two discrete simulation case are completely swapped, it seems not physically reasonable to set up two operation conditions (by just set 1st condition: 0Pa inlet 50Pa outlet and 2nd condition: 50Pa inlet and 0Pa outlet) in the gradient-based optimiser under adjoint solver, as the nature of inlet and outlet setup are different.
I tried another way: to simulate the flow solver for forward flow case first, and ran the adjoint solver for its sensitivity data, then imported such sensitivity of forward flow case into the reverse flow case, so that both sensitivity data may be able to be considered for the shape optimisation. However, the gradient-based optimiser not showing the observable of forward flow that just be imported. And supposingly gradient-based optimser is running iteratively for the ultimate optimal solution, and the adjoint solving will be kept running every iteration. While the iterative adjoint solving only involve the reverse flow case but not taking forward flow case into account, how can the optimisation really consider both targets (maxmising reverse flow and minimising forward flow).
This meant a lot to my project, please share your guide and insights. Much appreciated.
Thanks.
https://innovationspace.ansys.com/forum/forums/topic/multi-objective-shape-optimisation-of-tesla-valve/
-
November 4, 2024 at 4:33 pmRobForum Moderator
I suspect the problem is not the optimiser tools as such, but the fact that the two goals conflict significantly so you may need to rethink the objective function. Is the objective to minimize/maximise the flow in each direction or maximize the ratio forward-backwards? What then can be controlled to make the changes?
-
November 5, 2024 at 10:51 amJason SumSubscriber
Yes Rob, I am thinking to create a ratio (forward flowrate / reverse flowrate) - like diodicity, as the observable under the adjoint setup on Fluent.
But because of the two cases of discrete flow direction (forward & reverse) as shown similarly to the screenshot below, if I work on the adjoint setting in the Reverse's Fluent solver, it seems not to be able to obtain flow data and solutions from Foward's Fluent solver, making me unable to relate the observable defined with the "forward flowrate" simulated from Forward's Fluent solver.Also, as far as i know, in gradient-based optimiser, flow solving and adjoint solving are iteratively solved. If I just work on the adjoint setting in the Reverse's Fluent solver, flow and adjoint solving of foward flow case are not included in the iterations.
I tried to import the sensitivity data from Forward's Fluent solver to Reverse's Fluent solver, but it seems the sensitivity of foward flow did not contribute to the objective in the gradient-based optimiser.
Therefore I am still figuring out the way to take both flow cases into account for adjoint optimisation, and seeking for insights thanks!
-
-
November 5, 2024 at 11:17 amRobForum Moderator
I've flagged for the Optislang users as whilst I know roughly what it does, I have no idea what buttons there are to press.
Thinking from a fluidics point of view (you may want to read up on vortex diodes, J.R. Tippetts is a good person to start with) you may want to run all of the forward and backwards scenarios and then see how the results overlay. There may be a configuration for best forward/reverse ratio but a different design maximises forward flow: goal weighting may become as critical as goal setting.
-
November 10, 2024 at 8:47 amJason SumSubscriber
Thanks Rob for the direction and followup.
Btw, I am also encountering convergence issues when computing adjoint residuals, see if you or everyone could give me some insights please!
I checked my mesh quality - the orthogonality minimum > 0.3 and aspect ratio maximum ~ 25. But the skewness maximum reaches 0.77 in the sharp bifurcated point.
The flow (primal) residual converged smoothly at ~500th iteration.
I am wondering if the convergence issues of adjoint residual relates to mesh quality or adjoint solving setup.
Sometimes there are errors about AMG.
Console:
Computing the adjoint for observable flowrate_vent
Building matrix
adj-iter continuity x-velocity y-velocity flow-rate Time/Iter
1 7.2318e-01 2.2030e-02 2.2030e-02 1.0849e-01 00:00:00 1000
2 1.4271e+00 1.2319e+02 1.4418e+02 5.4420e-03 00:00:00 999
3 1.9062e+00 1.2993e+01 1.6403e+01 4.2350e-03 00:00:00 998
4 7.7279e-01 2.4223e+00 2.7424e+00 4.5459e-03 00:00:00 997
5 4.4907e-01 7.4641e-01 7.2582e-01 6.8885e-03 00:00:00 996
6 5.2455e-01 3.4912e-01 3.2358e-01 1.0935e-02 00:00:00 995
7 8.1358e-01 2.2345e-01 1.9349e-01 1.6073e-02 00:00:00 994
8 1.2856e+00 1.7354e-01 1.4127e-01 2.1458e-02 00:00:00 993
9 1.9739e+00 1.4778e-01 1.1828e-01 2.5596e-02 00:00:00 992
10 2.9258e+00 1.3446e-01 1.0747e-01 2.8035e-02 00:00:00 991
11 4.1593e+00 1.2670e-01 1.0160e-01 2.9023e-02 00:00:00 990
12 5.6364e+00 1.2173e-01 9.7927e-02 2.9159e-02 00:00:00 989
13 7.2619e+00 1.1829e-01 9.5377e-02 2.8913e-02 00:00:00 988
14 8.9073e+00 1.1580e-01 9.3494e-02 2.8543e-02 00:00:00 987
15 1.0448e+01 1.1394e-01 9.2067e-02 2.8168e-02 00:00:00 986
16 1.1798e+01 1.1255e-01 9.0979e-02 2.7834e-02 00:00:00 985
17 1.2915e+01 1.1151e-01 9.0150e-02 2.7556e-02 00:00:00 984
18 1.3800e+01 1.1072e-01 8.9523e-02 2.7331e-02 00:00:00 983
19 1.4478e+01 1.1013e-01 8.9052e-02 2.7154e-02 00:00:00 982
20 1.4984e+01 1.0969e-01 8.8700e-02 2.7017e-02 00:00:00 981
adj-iter continuity x-velocity y-velocity flow-rate Time/Iter
21 1.5356e+01 1.0936e-01 8.8438e-02 2.6911e-02 00:00:00 980
22 1.5625e+01 1.0912e-01 8.8245e-02 2.6832e-02 00:00:00 979
23 1.5818e+01 1.0894e-01 8.8102e-02 2.6771e-02 00:00:00 978
24 1.5955e+01 1.0880e-01 8.7997e-02 2.6726e-02 00:00:00 977
25 1.6053e+01 1.0871e-01 8.7921e-02 2.6693e-02 00:00:00 976
26 1.6123e+01 1.0864e-01 8.7865e-02 2.6668e-02 00:00:00 975
27 1.6172e+01 1.0859e-01 8.7824e-02 2.6650e-02 00:00:00 974
28 1.6207e+01 1.0855e-01 8.7794e-02 2.6637e-02 00:00:00 973
29 1.6232e+01 1.0852e-01 8.7772e-02 2.6627e-02 00:00:00 972
30 1.6250e+01 1.0850e-01 8.7756e-02 2.6620e-02 00:00:00 971
31 1.6263e+01 1.0849e-01 8.7745e-02 2.6615e-02 00:00:00 970
32 1.6272e+01 1.0848e-01 8.7736e-02 2.6611e-02 00:00:00 969
33 1.6278e+01 1.0847e-01 8.7730e-02 2.6608e-02 00:00:00 968
34 1.6283e+01 1.0846e-01 8.7726e-02 2.6606e-02 00:00:00 967
35 1.6286e+01 1.0846e-01 8.7723e-02 2.6605e-02 00:00:00 966
36 1.6288e+01 1.0846e-01 8.7720e-02 2.6604e-02 00:00:00 965
37 1.6290e+01 1.0845e-01 8.7719e-02 2.6603e-02 00:00:00 964
Detected: slow convergence!
Residual Minimization scheme is enabled.
38 1.6291e+01 1.0845e-01 8.7717e-02 2.6603e-02 00:00:00 963
Initial step of residual minization scheme (40,10).
Subiter 0 : residual 5.19566e+03
Subiter 1 : residual 3.49130e+03
Subiter 2 : residual 2.18049e+03
Subiter 3 : residual 1.59751e+03
Subiter 4 : residual 1.22762e+03
Subiter 5 : residual 8.73199e+02
Subiter 6 : residual 6.90256e+02
Subiter 7 : residual 5.49072e+02
Subiter 8 : residual 4.15565e+02
Subiter 9 : residual 2.96731e+02
Subiter 10 : residual 2.58569e+02
Subiter 11 : residual 2.33898e+02
Subiter 12 : residual 2.18858e+02
Subiter 13 : residual 2.05658e+02
Subiter 14 : residual 1.63541e+02
Subiter 15 : residual 1.14036e+02
Subiter 16 : residual 8.59763e+01
Subiter 17 : residual 6.80927e+01
Subiter 18 : residual 5.05588e+01
Subiter 19 : residual 3.92616e+01
Subiter 20 : residual 3.24915e+01
Subiter 21 : residual 2.74532e+01
Subiter 22 : residual 2.26129e+01
Subiter 23 : residual 1.92560e+01
Subiter 24 : residual 1.56194e+01
Subiter 25 : residual 1.17093e+01
Subiter 26 : residual 9.45615e+00
Subiter 27 : residual 7.70489e+00
Subiter 28 : residual 7.06570e+00
Subiter 29 : residual 6.46197e+00
Subiter 30 : residual 6.05601e+00
Subiter 31 : residual 5.84756e+00
Subiter 32 : residual 5.63515e+00
Subiter 33 : residual 5.03297e+00
Subiter 34 : residual 4.46038e+00
Subiter 35 : residual 3.93606e+00
Subiter 36 : residual 3.40827e+00
Subiter 37 : residual 3.05956e+00
Subiter 38 : residual 2.83304e+00
Subiter 39 : residual 2.70420e+00
Subiter 40 : residual 2.50963e+00
(Ref: Subiter 0 : residual 5.19566e+03)
39 1.1310e-01 2.0475e-02 2.1688e-02 1.8579e-04 00:03:12 962
Subiter 0 : residual 2.50963e+00
Subiter 1 : residual 2.47081e+00
Subiter 2 : residual 2.45322e+00
Subiter 3 : residual 2.33711e+00
Subiter 4 : residual 2.09191e+00
Subiter 5 : residual 1.79734e+00
Subiter 6 : residual 1.65007e+00
Subiter 7 : residual 1.53513e+00
Subiter 8 : residual 1.44179e+00
Subiter 9 : residual 1.41316e+00
Subiter 10 : residual 1.37896e+00
Subiter 11 : residual 1.20338e+00
Subiter 12 : residual 8.64229e-01
Subiter 13 : residual 5.58113e-01
Subiter 14 : residual 4.23508e-01
Subiter 15 : residual 3.25290e-01
Subiter 16 : residual 2.37135e-01
Subiter 17 : residual 1.68159e-01
Subiter 18 : residual 1.12768e-01
Subiter 19 : residual 8.10711e-02
Subiter 20 : residual 5.72218e-02
Subiter 21 : residual 4.44752e-02
Subiter 22 : residual 3.54293e-02
Subiter 23 : residual 2.44222e-02
Subiter 24 : residual 1.54195e-02
Subiter 25 : residual 1.01831e-02
Subiter 26 : residual 6.23093e-03
Subiter 27 : residual 3.67927e-03
Subiter 28 : residual 2.23154e-03
Subiter 29 : residual 1.47669e-03
Subiter 30 : residual 9.85336e-04
(Ref: Subiter 0 : residual 2.50963e+00)
40 1.4761e-02 2.5215e-03 2.7998e-03 1.8157e-05 00:02:33 961
Subiter 0 : residual 9.85336e-04
Subiter 1 : residual 7.90151e-04
Subiter 2 : residual 6.79519e-04
Subiter 3 : residual 5.39879e-04
Subiter 4 : residual 4.83322e-04
Subiter 5 : residual 3.78174e-04
Subiter 6 : residual 2.73488e-04
Subiter 7 : residual 2.10568e-04
Subiter 8 : residual 1.33842e-04
Subiter 9 : residual 7.92288e-05
Subiter 10 : residual 5.22424e-05
Subiter 11 : residual 3.74638e-05
Subiter 12 : residual 2.76896e-05
Subiter 13 : residual 2.07209e-05
Subiter 14 : residual 1.50188e-05
Subiter 15 : residual 9.85177e-06
Subiter 16 : residual 6.04442e-06
Subiter 17 : residual 3.97632e-06
Subiter 18 : residual 2.49694e-06
Subiter 19 : residual 1.65920e-06
Subiter 20 : residual 1.12416e-06
Subiter 21 : residual 8.02176e-07
Subiter 22 : residual 5.62510e-07
Subiter 23 : residual 3.42694e-07
Subiter 24 : residual 2.17740e-07
Subiter 25 : residual 1.51421e-07
Subiter 26 : residual 1.02756e-07
Subiter 27 : residual 6.98898e-08
Subiter 28 : residual 4.87897e-08
Subiter 29 : residual 3.53074e-08
Subiter 30 : residual 2.38567e-08
(Ref: Subiter 0 : residual 9.85336e-04)
adj-iter continuity x-velocity y-velocity flow-rate Time/Iter
41 3.7885e-07 5.7990e-08 5.7229e-08 8.1460e-10 00:02:02 960
! Adjoint solution is converged.
-
-
November 5, 2024 at 3:08 pmJason SumSubscriber
Thanks Rob. Following the previous post, grateful if Akram and Markus could offer some guides on this please.
-
November 12, 2024 at 2:05 pmRobForum Moderator
Akram's looking at what he can say whilst remaining within the Forum rules for staff.
Not sure about the adjoint bit, but I'd be surprised if you didn't have some boundary separation in the device, and that is generally unstable. Also remember that inflated meshes are just high aspect ratio cells if the flow isn't aligned (ie separation & reattachment points).
-
November 12, 2024 at 2:24 pmJason SumSubscriber
Thanks Rob for the updates and Akram for the followup.
Yes, I am concerning especially the tips (with inflation layers) of the tesla valve where flow diverges. Any measures or treatment you may propose in that particular regions as currently these regions are not in parallel with the flow and may cause numerical errors.(perhaps the reason leading to adjoint residual convergence issues?)
Best Regards,
Jason -
November 22, 2024 at 6:24 amJason SumSubscriber
Dear Akram,
Was your reply removed? I am still figuring out the ways based on your guide! Thanks.
-
December 2, 2024 at 12:19 pmAkram RadwanAnsys Employee
Hello Jason,
Let me try to reconstruct what was lost because of the database corruption. This time I have a local backup.
General recommendations
Do not use Ansys Workbench for shape optimization. You can prepare your calculations there. But the automation of WB can conflict with the various files the optimizer creates. I strongly recommend using the standalone version of Fluent for the optimization.
Do a sensitivity study before running the optimization. Note that Fluent can only post-process the sensitivity fields of the current calculation. To compare them, you need either separate sessions or export the results to EnSight to have both loaded at the same time. This analysis has multiple goals:
- Understand which regions of which operating condition are sensitive.
- Understand how different observable definitions might influence the result.
- Understand if or where observables support each other or are conflicting.
You can explore different optimization strategies:
- Explore different observables. Some might work better than others. For example, the velocity magnitude does not have a sign and can be maximized or minimized for the two directions. The mass flux has a sign and must be treated differently. For other boundary conditions you might need the pressure drop but measuring the total pressure drop between inlet and outlet or the pressure drop in one of the channels can lead to different results.
- You can apply a split optimization strategy. First, optimize the forward path on its own. Then optimize the reverse direction on its own. This simplifies the optimization process. Depending on the sensitivity distribution, you might want to restrict the deformability of certain regions.
- With the upcoming 2025 R1 (available in January), you can test if the optimizer can keep the mass flow rate in the forward direction above a user-defined minimum and minimize it in the other direction.
Also keep in mind that you have sharp corners in your geometry. The separation at these corners is often transient in nature, which influences the stability of the adjoint calculation more than it influences the stability of the flow calculation. The residual minimization scheme can often bring the adjoint residuals down. But you should be sure that the flow calculation is stable, i.e., stopping the flow calculation at different iterations does not show a different flow field. There are averaging methods available if this cannot be achieved but I do not recommend them before you have more experience with more stable flow calculations.
Boundary conditions
You have two possibilities for your BC types. You can use two pressure inlet BCs or a combination of mass flow/velocity and pressure outlet BCs.
The advantage of the pressure inlet BCs is the easy way to parameterize them. Don’t get confused by the name, when the flow goes out of the pressure inlet it behaves just like the pressure outlet BC type. You might need to initialize the flow calculation between the optimization steps, though. And two pressure BCs are not the most stable setup to begin with.
The advantage of mass flow inlet or velocity inlet and pressure outlet BCs is their stability. However, changing the BCs in an automated process is not available as a built-in method in Fluent. You need a few lines of script to do this.
But the choice of BC should be driven by what you want to model. The Tesla valve should choke the flow for the reverse direction. While it is doing this regardless of the boundary conditions, the outcome for the optimization can be very different. For pressure BCs the mass flow rate reduces, which can change the flow behavior (e.g., the existence or strength of recirculation and separation). For mass flow/velocity + pressure BCs the pressure drop changes but the general flow behavior is unlikely to change.
Consider the true operating conditions that apply to operating the device. There might be more than just the two general flow directions.I outlined the script to change the BC-type in the other thread if you need that. Because of the limitations of scripting support especially for Scheme, I cannot provide more details. When you have difficulties, test the script line by line before using it within the optimization loop.
To initialize the flow and/or adjoint solution, search the documentation for “;@”. You can find it in the Fluent 2024 R2 User’s Guide, III. Solution mode, chapter 48.2.6. Using the Gradient-Based Optimizer, step 10: https://ansyshelp.ansys.com/public/account/secured?returnurl=/Views/Secured/corp/v242/en/flu_ug/flu_adj_usage.html%23flu_adj_sec_adjoint_grad_opt
Add a new execute command using “Execute Repeatedly every 1 Design Iteration” with the following three lines:/solve/initialize/hyb-initialization yes
/adjoint/run/initialize
;@before-flowDepending on your strategy and operating conditions you might want to split this into two commands to initialize flow and adjoint separately at different steps of the optimization process.
Note: 2025 R1 will initialize automatically when you have more than one objective.
Adjoint convergence
From what you have shown, I’m not concerned about the adjoint convergence. The residual minimization scheme can reduce the adjoint residuals quite reliably. If it struggles, you can increase the number of modes.
Important: Never show the expert controls of the residual minimization stabilization scheme! Just having this box checked can change the behavior of the stabilization! Only use it when you know how it influences the calculation.Typically, I use Solution-Based Controls Initialization to reset the solver controls on initialization, 10 iterations for the first scheme without auto detection, and 20 on the second. That should be enough to converge the adjoint. If it’s not, increase the number of modes slowly. If you ever need values above 140 it’s time to think about alternative strategies and closer examination of the flow and adjoint solutions. For a better understanding, I recommend the training material for the gradient-based optimization that is available on the Ansys Learning Hub.
I also recommend taking a closer look at the flow behavior when you have convergence difficulties with adjoint. Do you have separation or recirculating flow somewhere? If yes, is this stable when you stop the calculation at different iterations or does it change slightly?
There are advanced diagnosis tools available in the text interface by keeping the cell residuals for the flow and the adjoint calculation, if you really want to dive deeper into understanding what is happening. I do not recommend this step. It requires a lot of experience to make sense out of the values that you see there. But it does exist if you want to analyze the stability on a cell level. Search the User’s Guide for “cell residuals” for the flow solver and check chapter 48.2.3.4. Printing and Postprocessing the Adjoint Equation Residuals for the adjoint solver. Again: I do not recommend this unless you have a lot of time to gain understanding of how to interpret the results with many different cases.Sensitivity analysis
Taking a closer look at the shape sensitivity is often ignored but it can give you valuable insights. The quantities you want to look at are the log10 shape sensitivity or the surface shape sensitivity. The first one is a logarithmic scale of the shape sensitivity, which makes it easier to see the distribution because it has a very large range. The second one is a smoothed version of the shape sensitivity.
I recommend to start with the surface shape sensitivity but before you do, change the postprocess options that you can access from the Design ribbon. Make sure the surface shape sensitivity is set to spring. The default radial basis function approach can be computationally expensive. Whichever method you use, this is just to get an impression of the sensitivity distribution, it is not used for anything by the mesh morphing. The Design Tool uses the raw shape sensitivity and applies the smoothing during the morphing process, which depends on the selected morphing method.
Unfortunately, it is not possible to export the surface shape sensitivity vector components to EnSight. If you want to use EnSight for a direct comparison, use the unsmoothed shape sensitivity components instead.Use vector plots for 2D cases. For 3D cases it is often more convenient to start with contour plots of the normal surface shape sensitivity. Check the regions of high absolute values for both flow directions.
- Are the regions similar?
- If yes, is the sign identical (general direction of the vector)?
- If yes, both observables support each other, it’s just a question of scaling them appropriately.
- If no, either the observables are in conflict with each other. Optimization without defining trade-offs is either very challenging or even impossible.
- If no, how different are they? Would it be possible to concentrate the shape change of one flow direction to certain regions and the reversed direction to different ones?
- If yes, is the sign identical (general direction of the vector)?
- How different are the absolute values of the shape sensitivities?
- Remember that the shape sensitivity has a unit that depends on the selected observable. If the observables are comparable (e.g., both use the average velocity magnitude at one boundary), differences indicate how to scale the objectives.
Based in the outcome of looking at the shape sensitivities you can derive an optimization strategy.
Remember: depending on maximizing or minimizing the observable, you might need to reverse the direction of the sensitivity vectors!
Optimization strategy
As indicated initially, there are different strategies possible. The flexibility of the optimizer is limited in favor of a fully automated workflow. Depending on the strategy that you want to use, you might need to do this manually.
Standard approach
Based on the sensitivity analysis, you can set you objectives and hope for the best. While this works well for a single objective, it rarely works for multiple objectives or conditions.Consecutive optimizations
This approach works best when the sensitivities have their extreme values in different regions of the domain. It is mostly useless when they are in conflict everywhere. Just run the optimizations with a single objective/condition. Once this cannot be continued, change the flow direction and run a new optimization.
You can also change the region easily with this approach, for example, to optimize the straight part of the pipe for the forward calculation and the bended part for the reversed direction.Customized approaches
Obviously, there are more approaches.Similar to the consecutive approach from above, you could do this in one step. There is no tool in Fluent to automate this apart from writing your own full optimization script. The idea is to set the first condition, calculate flow and adjoint, set the region and design conditions as needed, and morph the mesh. Then switch to the second condition and repeat. With this alternating approach you can run a combined optimization but with different settings for the mesh morphing.
You can also use different observables for the directions. I didn’t test this. But you could come up with an idea to maximize the flow rate through different parts of the domain, e.g., for the reverse direction maximize the flow rate through the bend, for the forward direction maximize the flow rate through the outlet. You can implement this in the optimizer by setting an objective to ‘none’ for the condition where it is not relevant. This will still calculate the adjoint for it, but it is not considered during mesh morphing.
As indicated above, 2025 R1 offers new methods for the optimization that can be useful for a case like this. You can implement a similar procedure yourself. Just run a single-objective optimization but stop it when the observable for the other operating condition is outside the bounds (e.g., the mass flow rate for the primary flow direction drops below a user-defined minimum). Only if this is the case, optimize for the other direction until it is well above the threshold. Then continue with the first set of settings.
There are more. I hope you get the idea that there is not just the workflow that is implemented in the gradient-based optimizer. That is the most common one, but not the only one. Understand the sensitivities. Then derive a workflow to change the shape in a promising way.
Conclusions
Optimizing a Tesla valve design is not the most trivial task.
- Start with the boundary conditions. Which ones are reasonable to describe the physics of the problem?
- Shed a thought or two about local stability of the flow calculation.
- Think of possible observables. There are often more than one possible objective functions and because of the nature of the adjoint method the resulting shape can be quite different.
- Analyze the sensitivities for the different operating conditions and observables. Understand where they support each other and where they are in conflict.
- Derive possible optimization strategies. Not all of them are available as built-in capabilities. Be creative, then simplify.
- Run the optimization. Analyze how it performs. Fine-tune the approach or use one of the other strategies.
I hope I didn’t miss a question and that I covered all of the lost information.
-
-
-
November 12, 2024 at 2:49 pmRobForum Moderator
Other than not using inflation, or rather getting the aspect ratio nearer 1.0 not really. If the separation or wake isn't stable convergence will be difficult. Most fluidic devices have local transient effects as they typically take advantage of "odd" fluid flow effects such as Coanda Effect.
-
November 22, 2024 at 11:18 amRobForum Moderator
Yes, Akram's post got lost and he's a way for a week or two. He's aware of the site issues so will check on his return: we may need reminding given the number of threads!
-
- You must be logged in to reply to this topic.
-
1156
-
488
-
481
-
225
-
201
© 2024 Copyright ANSYS, Inc. All rights reserved.