Skip to content

Commit c11dac5

Browse files
Merge pull request arcaneframework#260 from arcaneframework/dev/mab-acoustics-3d
acoustics in 3d
2 parents 180ae6e + 2c286e9 commit c11dac5

File tree

8 files changed

+248
-17
lines changed

8 files changed

+248
-17
lines changed

meshes/msh/sub_3d.geo

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//-----------------------------------------------------------------------------
2+
//
3+
// Name : sub.geo
4+
// Author : Mohd Afeef BADRI
5+
// Date : 04 / April / 2025
6+
//
7+
// ----------------------------------------------------------------------------
8+
// Comment : simple submarine problem mesh for ill posed acoustics
9+
//
10+
//
11+
// Usage : gmsh sub_3d.geo -2 -format msh41 -clmin 1 -clmax 1
12+
// gmsh sub_3d.geo -2 -format msh41 -setnumber MeshSize 1.0 -setnumber Rfactor 2.0
13+
//
14+
//-----------------------------------------------------------------------------
15+
16+
SetFactory("OpenCASCADE");
17+
18+
DefineConstant[ meshSize = {1.0, Min 1e-8, Max 100, Step 1, Name "MeshSize"} ];
19+
DefineConstant[ Rfactor = {1.0, Min 1, Max 100, Step 1, Name "Rfactor"} ];
20+
meshSize /= Rfactor;
21+
22+
//==============================================================================
23+
// Outer Sphere (Water Domain)
24+
//==============================================================================
25+
R_sphere = .1;
26+
Sphere(1) = {0, 0, 0, R_sphere};
27+
28+
//==============================================================================
29+
// Inner Torus (Cavity to be subtracted)
30+
//==============================================================================
31+
Sphere(2) = {0, 0, 0, R_sphere/10};
32+
33+
BooleanDifference{ Volume{1}; Delete; }{ Volume{2}; Delete; }
34+
35+
Physical Surface("outer", 10) = {3};
36+
Physical Surface("inner", 11) = {2};
37+
Physical Volume("water", 12) = {1};
38+
39+
Mesh.MshFileVersion = 4.1;

meshes/msh/sub_3d.msh

36.7 KB
Binary file not shown.

modules/acoustics/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ file(COPY "inputs" DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
2121
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/meshes)
2222
set(MESH_FILES
2323
sub.msh
24+
sub_3d.msh
2425
)
2526
foreach(MESH_FILE IN LISTS MESH_FILES)
2627
file(COPY ${MSH_DIR}/${MESH_FILE} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/meshes)
@@ -31,6 +32,8 @@ target_link_libraries(Acoustics PUBLIC FemUtils)
3132
enable_testing()
3233

3334
add_test(NAME [Acoustics]2D_submarine COMMAND Acoustics inputs/sub.arc)
35+
add_test(NAME [Acoustics]3D_sphere COMMAND Acoustics inputs/3d_sub.arc)
36+
3437

3538
if(FEMUTILS_HAS_SOLVER_BACKEND_PETSC)
3639
add_test(NAME [Acoustics]parse_and_exit COMMAND Acoustics
@@ -42,6 +45,11 @@ endif()
4245

4346
if(FEMUTILS_HAS_SOLVER_BACKEND_HYPRE)
4447
add_test(NAME [Acoustics]2D_submarine_hypre COMMAND Acoustics inputs/sub.hypre.arc)
48+
add_test(NAME [Acoustics]3D_sphere_hypre COMMAND Acoustics
49+
-A,//fem/linear-system/@name=AlephLinearSystem
50+
-A,//fem/linear-system/solver-backend=hypre
51+
-A,//fem/linear-system/solver-method=gmres
52+
inputs/3d_sub.arc)
4553
if(FEMUTILS_HAS_PARALLEL_SOLVER AND MPIEXEC_EXECUTABLE)
4654
add_test(NAME [Acoustics]2D_submarine_hypre_2p COMMAND ${MPIEXEC_EXECUTABLE} -n 2 ./Acoustics inputs/sub.hypre.arc)
4755
endif()

modules/acoustics/ElementMatrix.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,33 @@ _computeElementMatrixTria3(Cell cell)
3535
Real3 dxU = ArcaneFemFunctions::FeOperation2D::computeGradientXTria3(cell, m_node_coord);
3636
Real3 dyU = ArcaneFemFunctions::FeOperation2D::computeGradientYTria3(cell, m_node_coord);
3737

38-
return -area * (dxU ^ dxU) - area * (dyU ^ dyU) + m_kc2 * area * (1/ 12.) *massMatrix(U,U);
38+
return -area * (dxU ^ dxU) - area * (dyU ^ dyU) + m_kc2 * area * (1/ 12.) * massMatrix(U,U);
39+
}
40+
41+
/*---------------------------------------------------------------------------*/
42+
/*
43+
* @brief Computes the element matrix for a tetrahedral element (ℙ1 FE).
44+
*
45+
* This function calculates the integral of the expression:
46+
* a(𝑢,𝑣) = ∫∫∫ -(∂𝑢/∂𝑥 ∂𝑣/∂𝑥 + ∂𝑢/∂𝑦 ∂𝑣/∂𝑦 + ∂𝑢/∂𝑧 ∂𝑣/∂𝑧)dΩ + ∫∫∫ (𝑘²𝑢𝑣)dΩ
47+
*
48+
* Steps involved:
49+
* 1. Calculate the volume of the tetrahedron.
50+
* 2. Compute the gradients of the shape functions.
51+
* 3. Return a(𝑢,𝑣);
52+
*/
53+
/*---------------------------------------------------------------------------*/
54+
55+
RealMatrix<4, 4> FemModule::
56+
_computeElementMatrixTetra4(Cell cell)
57+
{
58+
Real volume = ArcaneFemFunctions::MeshOperation::computeVolumeTetra4(cell, m_node_coord);
59+
60+
RealVector<4> U = { 1, 1, 1, 1 };
61+
62+
Real4 dxU = ArcaneFemFunctions::FeOperation3D::computeGradientXTetra4(cell, m_node_coord);
63+
Real4 dyU = ArcaneFemFunctions::FeOperation3D::computeGradientYTetra4(cell, m_node_coord);
64+
Real4 dzU = ArcaneFemFunctions::FeOperation3D::computeGradientZTetra4(cell, m_node_coord);
65+
66+
return -volume * (dxU ^ dxU) - volume * (dyU ^ dyU) - volume * (dzU ^ dzU) + m_kc2 * volume * (1 / 20.) * massMatrix(U,U);
3967
}

modules/acoustics/FemModule.cc

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,23 @@ _assembleLinearOperator()
144144

145145
const auto node_dof(m_dofs_on_nodes.nodeDoFConnectivityView());
146146

147-
BC::IArcaneFemBC* bc = options()->boundaryConditions();
148-
if(bc){
149-
for (BC::INeumannBoundaryCondition* bs : bc->neumannBoundaryConditions()){
150-
ArcaneFemFunctions::BoundaryConditions2D::applyNeumannToRhs(bs, node_dof, m_node_coord, rhs_values);
147+
auto applyBoundaryConditions = [&](auto BCFunctions) {
148+
BC::IArcaneFemBC* bc = options()->boundaryConditions();
149+
if (bc) {
150+
for (BC::INeumannBoundaryCondition* bs : bc->neumannBoundaryConditions()) {
151+
BCFunctions.applyNeumannToRhs(bs, node_dof, m_node_coord, rhs_values);
152+
}
151153
}
154+
};
155+
156+
// Apply the correct boundary conditions based on mesh dimension
157+
if (mesh()->dimension() == 3) {
158+
using BCFunctions = ArcaneFemFunctions::BoundaryConditions3D;
159+
applyBoundaryConditions(BCFunctions());
160+
}
161+
else {
162+
using BCFunctions = ArcaneFemFunctions::BoundaryConditions2D;
163+
applyBoundaryConditions(BCFunctions());
152164
}
153165

154166
elapsedTime = platform::getRealTime() - elapsedTime;
@@ -157,11 +169,7 @@ _assembleLinearOperator()
157169

158170
/*---------------------------------------------------------------------------*/
159171
/**
160-
* @brief Assembles the bilinear operator matrix for triangular elements.
161-
*
162-
* This method computes and assembles the global matrix A for the FEM linear
163-
* system. For each cell (triangle), it calculates the local element matrix &
164-
* adds the contributions to the global matrix based on the nodes of the cell.
172+
* @brief Calls the right function for LHS assembly
165173
*/
166174
/*---------------------------------------------------------------------------*/
167175

@@ -171,28 +179,51 @@ _assembleBilinearOperator()
171179
info() << "[ArcaneFem-Info] Started module _assembleBilinearOperator()";
172180
Real elapsedTime = platform::getRealTime();
173181

182+
if (mesh()->dimension() == 3)
183+
_assembleBilinear<4>([this](const Cell& cell) {
184+
return _computeElementMatrixTetra4(cell);
185+
});
186+
if (mesh()->dimension() == 2)
187+
_assembleBilinear<3>([this](const Cell& cell) {
188+
return _computeElementMatrixTria3(cell);
189+
});
190+
191+
elapsedTime = platform::getRealTime() - elapsedTime;
192+
ArcaneFemFunctions::GeneralFunctions::printArcaneFemTime(traceMng(), "lhs-matrix-assembly", elapsedTime);
193+
}
194+
195+
/*---------------------------------------------------------------------------*/
196+
/**
197+
* @brief Assembles the bilinear operator matrix for the FEM linear system.
198+
*
199+
* The method performs the following steps:
200+
* 1. Computes element matrix using provided `compute_element_matrix` function.
201+
* 2. Assembles global matrix by adding contributions from each cell's element
202+
* matrix to the corresponding entries in the global matrix.
203+
*/
204+
/*---------------------------------------------------------------------------*/
205+
template <int N>
206+
void FemModule::
207+
_assembleBilinear(const std::function<RealMatrix<N, N>(const Cell&)>& compute_element_matrix)
208+
{
174209
auto node_dof(m_dofs_on_nodes.nodeDoFConnectivityView());
175210

176211
ENUMERATE_ (Cell, icell, allCells()) {
177212
Cell cell = *icell;
178213

179-
auto K_e = _computeElementMatrixTria3(cell); // element matrix
214+
auto K_e = compute_element_matrix(cell); // element matrix based on the provided function
180215
Int32 n1_index = 0;
181216
for (Node node1 : cell.nodes()) {
182217
Int32 n2_index = 0;
183218
for (Node node2 : cell.nodes()) {
184219
Real v = K_e(n1_index, n2_index);
185-
if (node1.isOwn()) {
220+
if (node1.isOwn())
186221
m_linear_system.matrixAddValue(node_dof.dofId(node1, 0), node_dof.dofId(node2, 0), v);
187-
}
188222
++n2_index;
189223
}
190224
++n1_index;
191225
}
192226
}
193-
194-
elapsedTime = platform::getRealTime() - elapsedTime;
195-
ArcaneFemFunctions::GeneralFunctions::printArcaneFemTime(traceMng(), "lhs-matrix-assembly", elapsedTime);
196227
}
197228

198229
/*---------------------------------------------------------------------------*/
@@ -272,7 +303,7 @@ _validateResults()
272303
if (allNodes().size() < 200)
273304
ENUMERATE_ (Node, inode, allNodes()) {
274305
Node node = *inode;
275-
info() << "u[" << node.localId() << "][" << node.uniqueId() << "] = " << m_u[node];
306+
info() << "u[" << node.uniqueId() << "] = " << m_u[node];
276307
}
277308

278309
String filename = options()->resultFile();

modules/acoustics/FemModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ class FemModule
9292
void _validateResults();
9393

9494
RealMatrix<3, 3> _computeElementMatrixTria3(Cell cell);
95+
RealMatrix<4, 4> _computeElementMatrixTetra4(Cell cell);
96+
97+
template <int N>
98+
void _assembleBilinear(const std::function<RealMatrix<N, N>(const Cell&)>& compute_element_matrix);
9599
};
96100

97101
#endif
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
100 0.000287725021892968
2+
101 0.000239487109431728
3+
102 6.51015195239284e-05
4+
103 0.000418360390566261
5+
104 0.000695100947909542
6+
105 0.00011841053666585
7+
106 0.000745230270268164
8+
107 0.00155214956876286
9+
108 -0.00218100907895198
10+
109 0.000502915198987293
11+
110 0.00206940546040083
12+
111 -0.000100127323893553
13+
112 -0.0012251385696835
14+
113 -0.00263987079126473
15+
114 -0.00236862276135281
16+
115 -0.000155901277895176
17+
116 -0.000239852535688998
18+
117 -0.00305089164066475
19+
118 0.000190996771418783
20+
119 -0.00545688210886177
21+
120 0.000579180510396156
22+
121 -0.000219216523123141
23+
122 -0.00141865600256941
24+
123 -0.00865160369166539
25+
124 -8.99509445725068e-05
26+
125 -0.00375564689083683
27+
126 -0.000125389596609557
28+
127 -0.00760882841914332
29+
128 0.000254953852276821
30+
129 -0.00649672558348422
31+
130 -0.000466848324349205
32+
131 -0.00011253003924276
33+
132 0.000371406994764287
34+
133 0.000105571321312606
35+
134 -0.000222638935562521
36+
135 -0.0240200497028155
37+
136 0.000436231362124546
38+
137 0.000413657809187159
39+
138 0.00014359469311985
40+
139 -0.013834859215644
41+
140 -0.00414893245513014
42+
141 -5.30925790943364e-05
43+
142 -0.00588048336219698
44+
143 0.000344793471343447
45+
144 -0.017452978722355
46+
145 -0.0109365904183506
47+
146 0.00178745648624318
48+
147 4.19894278062304e-05
49+
148 -0.000150093689767147
50+
149 4.19582047111049e-05
51+
150 -0.000131206554784793
52+
151 5.60241137246923e-05
53+
152 -3.55502845594731e-05
54+
153 0.000596956497932044
55+
154 3.0625429695194e-05
56+
155 -0.0140370936494099
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
Case configuration for an acoustics simulation.
4+
The following sections define:
5+
- General simulation settings
6+
- Mesh configurations details
7+
- Finite Element Method (FEM) configurations
8+
- Post-processing options
9+
-->
10+
<case codename="Acoustics" xml:lang="en" codeversion="1.0">
11+
12+
<!--
13+
Arcane-specific settings:
14+
- title: The name or description of the case.
15+
- timeloop: Defines the time-stepping loop for the simulation.
16+
-->
17+
<arcane>
18+
<title>Sphere in sphere Toy Case</title>
19+
<timeloop>AcousticsLoop</timeloop>
20+
</arcane>
21+
22+
23+
<!--
24+
Mesh configurations:
25+
- filename: Path to the mesh file used in the simulation.
26+
-->
27+
<meshes>
28+
<mesh>
29+
<filename>meshes/sub_3d.msh</filename>
30+
</mesh>
31+
</meshes>
32+
33+
34+
<!--
35+
FEM (Finite Element Method) settings:
36+
- kc2: Coefficient used in the FEM calculations.
37+
- boundary-conditions: Defines neumann boundary conditions for the simulation.
38+
- linear-system: Specifies the linear system solver to use.
39+
- result-file: File for validation (optional)
40+
-->
41+
<fem>
42+
<kc2>18e5</kc2>
43+
<boundary-conditions>
44+
<neumann>
45+
<surface>inner</surface>
46+
<value>11e2</value>
47+
</neumann>
48+
</boundary-conditions>
49+
<linear-system name="SequentialBasicLinearSystem" />
50+
<result-file>check/sphere_3d.txt</result-file>
51+
</fem>
52+
53+
<!--
54+
Post-processing settings:
55+
- output-period: Defines how often output should be generated.
56+
- output: Specifies which variables are to be outputted.
57+
-->
58+
<arcane-post-processing>
59+
<output-period>1</output-period>
60+
<output>
61+
<variable>U</variable>
62+
</output>
63+
</arcane-post-processing>
64+
65+
</case>

0 commit comments

Comments
 (0)