Skip to content

Commit 1929507

Browse files
Merge pull request #348 from arcaneframework/dev/alien-integration
Add Alien back-end
2 parents 462cbb8 + 0ef53d9 commit 1929507

File tree

22 files changed

+839
-17
lines changed

22 files changed

+839
-17
lines changed

femutils/AlienDoFLinearSystem.cc

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2+
//-----------------------------------------------------------------------------
3+
// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4+
// See the top-level COPYRIGHT file for details.
5+
// SPDX-License-Identifier: Apache-2.0
6+
//-----------------------------------------------------------------------------
7+
/*---------------------------------------------------------------------------*/
8+
/* PETScDoFLinearSystem.cc (C) 2022-2025 */
9+
/* */
10+
/* Linear system: Matrix A + Vector x + Vector b for Ax=b. */
11+
/*---------------------------------------------------------------------------*/
12+
/*---------------------------------------------------------------------------*/
13+
14+
#include "DoFLinearSystem.h"
15+
16+
#include <mpi.h>
17+
#include <arccore/trace/TraceAccessor.h>
18+
19+
#include <arcane/accelerator/RunCommandLoop.h>
20+
#include <arcane/utils/FatalErrorException.h>
21+
#include <arcane/utils/PlatformUtils.h>
22+
#include <arcane/utils/ArcaneGlobal.h>
23+
#include <arcane/utils/MemoryUtils.h>
24+
#include <arcane/utils/MemoryView.h>
25+
#include <arcane/utils/ITraceMng.h>
26+
#include <arcane/utils/NumArray.h>
27+
#include <arcane/utils/CommandLineArguments.h>
28+
29+
#include <arcane/core/ServiceFactory.h>
30+
#include <arcane/core/VariableTypes.h>
31+
#include <arcane/core/BasicService.h>
32+
#include <arcane/core/IParallelMng.h>
33+
#include <arcane/core/IItemFamily.h>
34+
#include <arcane/core/ItemPrinter.h>
35+
#include <arcane/core/Timer.h>
36+
37+
#include <arcane/accelerator/VariableViews.h>
38+
#include <arcane/accelerator/core/Runner.h>
39+
#include <arcane/accelerator/core/Memory.h>
40+
41+
#include "IDoFLinearSystemFactory.h"
42+
#include "internal/CsrDoFLinearSystemImpl.h"
43+
44+
#include <alien/arcane_tools/accessors/ItemVectorAccessor.h>
45+
#include <alien/core/block/VBlock.h>
46+
47+
#include <alien/arcane_tools/IIndexManager.h>
48+
#include <alien/arcane_tools/indexManager/BasicIndexManager.h>
49+
#include <alien/arcane_tools/indexManager/SimpleAbstractFamily.h>
50+
#include <alien/arcane_tools/distribution/DistributionFabric.h>
51+
#include <alien/arcane_tools/indexSet/IndexSetFabric.h>
52+
#include <alien/arcane_tools/data/Space.h>
53+
54+
#include <alien/kernels/simple_csr/algebra/SimpleCSRLinearAlgebra.h>
55+
#include <alien/kernels/simple_csr/algebra/SimpleCSRInternalLinearAlgebra.h>
56+
57+
#include <alien/ref/AlienRefSemantic.h>
58+
#include <alien/ref/AlienImportExport.h>
59+
60+
#include <alien/kernels/redistributor/Redistributor.h>
61+
#include <alien/ref/data/scalar/RedistributedVector.h>
62+
#include <alien/ref/data/scalar/RedistributedMatrix.h>
63+
#include <alien/ref/import_export/MatrixMarketSystemWriter.h>
64+
65+
#include <alien/expression/solver/SolverStater.h>
66+
#include <alien/AlienLegacyConfig.h>
67+
68+
#include <AlienDoFLinearSystemFactory_axl.h>
69+
70+
#ifdef ALIEN_USE_PETSC
71+
#include <alien/kernels/petsc/io/AsciiDumper.h>
72+
#include <alien/kernels/petsc/algebra/PETScLinearAlgebra.h>
73+
#endif
74+
75+
#ifdef ALIEN_USE_HYPRE
76+
#include <alien/kernels/hypre/HypreBackEnd.h>
77+
#include <alien/kernels/hypre/data_structure/HypreMatrix.h>
78+
#include <alien/kernels/hypre/data_structure/HypreVector.h>
79+
#include <alien/kernels/hypre/algebra/HypreLinearAlgebra.h>
80+
#endif
81+
82+
namespace Arcane::FemUtils
83+
{
84+
85+
using namespace Arcane;
86+
using namespace Alien;
87+
88+
class AlienDoFLinearSystemImpl
89+
: public CsrDoFLinearSystemImpl
90+
{
91+
public:
92+
93+
AlienDoFLinearSystemImpl(IItemFamily* dof_family, const String& solver_name)
94+
: CsrDoFLinearSystemImpl(dof_family, solver_name)
95+
, m_dof_matrix_numbering(VariableBuildInfo(dof_family, solver_name + "MatrixNumbering"))
96+
{
97+
info() << "[Alien-Info] Creating AlienDoFLinearSystemImpl()";
98+
}
99+
100+
~AlienDoFLinearSystemImpl() override
101+
{
102+
info() << "[Alien-Info] Calling AlienDoFLinearSystemImpl destructor";
103+
}
104+
105+
public:
106+
107+
void solve() override;
108+
109+
void setSolverCommandLineArguments(const CommandLineArguments& args) override
110+
{
111+
info() << "[Alien-Info] initialize command lines arguments";
112+
auto argv = *args.commandLineArgv();
113+
auto o = info() << "[Alien-Info] ./" << argv[0];
114+
115+
116+
for (int i = 1; i < *args.commandLineArgc(); i++)
117+
o << ' ' << argv[i];
118+
}
119+
120+
void setSolver(Alien::ILinearSolver* s) { m_solver_backend = s; }
121+
122+
CaseOptionsAlienDoFLinearSystemFactory* options;
123+
124+
private:
125+
126+
Alien::ILinearSolver* m_solver_backend;
127+
VariableDoFInt32 m_dof_matrix_numbering;
128+
129+
NumArray<Real, MDDim1> m_rhs_work_values;
130+
//! Work array to store values of solution vector in parallel
131+
NumArray<Real, MDDim1> m_result_work_values;
132+
};
133+
134+
void AlienDoFLinearSystemImpl::
135+
solve()
136+
{
137+
info() << "[Alien-Info] Calling Alien solver";
138+
139+
IItemFamily* dof_family = dofFamily();
140+
IParallelMng* pm = dof_family->parallelMng();
141+
Runner runner = this->runner();
142+
CSRFormatView csr_view = this->getCSRValues();
143+
144+
auto areaU = dof_family->allItems();
145+
146+
Alien::ArcaneTools::BasicIndexManager index_manager(pm);
147+
index_manager.setTraceMng(traceMng());
148+
149+
auto indexSetU = index_manager.buildScalarIndexSet("U", areaU);
150+
index_manager.prepare();
151+
UniqueArray<Arccore::Integer> allUIndex = index_manager.getIndexes(indexSetU);
152+
153+
Alien::ArcaneTools::Space space(&index_manager, "TestSpace");
154+
auto mdist = Alien::ArcaneTools::createMatrixDistribution(space);
155+
auto vdist = Alien::ArcaneTools::createVectorDistribution(space);
156+
157+
Alien::Vector vectorB(vdist);
158+
Alien::Vector vectorX(vdist);
159+
Alien::Matrix matrixA(mdist);
160+
// local matrix for exact measure without side effect
161+
// (however, you can reuse a matrix with several
162+
// builder)
163+
164+
Real a1 = platform::getRealTime();
165+
166+
pm->barrier();
167+
168+
{
169+
Alien::MatrixProfiler profiler(matrixA);
170+
///////////////////////////////////////////////////////////////////////////
171+
//
172+
// DEFINE PROFILE
173+
//
174+
ENUMERATE_DOF(idof, dof_family->allItems()) {
175+
if (!idof->isOwn()) {
176+
continue;
177+
}
178+
179+
int i = idof.index();
180+
// info() << "owned index: " << i << " local id: " << idof.localId();
181+
for (CsrRowColumnIndex csr_index : csr_view.rowRange(i)) {
182+
Int32 column_index = csr_view.column(csr_index);
183+
// info() << "column index: " << column_index << " allUIndex: " << allUIndex[idof.localId()] << " csr index: " << csr_index;
184+
profiler.addMatrixEntry(allUIndex[idof.localId()], allUIndex[column_index]);
185+
}
186+
}
187+
}
188+
{
189+
Alien::ProfiledMatrixBuilder builder(
190+
matrixA, Alien::ProfiledMatrixOptions::eResetValues);
191+
192+
ENUMERATE_DOF(idof, dof_family->allItems()) {
193+
if (!idof->isOwn()) {
194+
continue;
195+
}
196+
197+
int i = idof.index();
198+
for (CsrRowColumnIndex csr_index : csr_view.rowRange(i)) {
199+
Int32 column_index = csr_view.column(csr_index);
200+
// info() << "row: " << i << " col: " << column_index << " val: " << csr_view.value(csr_index);
201+
builder(allUIndex[idof.localId()], allUIndex[column_index]) += csr_view.value(csr_index);
202+
}
203+
}
204+
builder.finalize();
205+
}
206+
207+
Real a2 = platform::getRealTime();
208+
info() << "[Alien-Timer] Time to create matrix = " << (a2 - a1);
209+
210+
VariableDoFReal& rhs_variable = this->rhsVariable();
211+
VariableDoFReal& dof_variable = this->solutionVariable();
212+
auto rhs_data = rhs_variable.asArray();
213+
auto result_data = dof_variable.asArray();
214+
215+
{
216+
Alien::VectorWriter writer(vectorX);
217+
218+
ENUMERATE_DOF (idof, areaU.own()) {
219+
const Integer iIndex = allUIndex[idof->localId()];
220+
// info() << "local: " << idof->localId() << " global: " << idof.index();
221+
// info() << "local " << idof->localId()<< " iIndex " << iIndex << " res val: " << result_data[idof->localId()];
222+
writer[iIndex] = result_data[idof->localId()];
223+
}
224+
}
225+
226+
{
227+
Alien::VectorWriter writer(vectorB);
228+
229+
ENUMERATE_DOF (idof, areaU.own()) {
230+
const Integer iIndex = allUIndex[idof->localId()];
231+
// info() << "local " << idof->localId( )<< " iIndex " << iIndex << " rhs val: " << rhs_data[idof->localId()];
232+
writer[iIndex] = rhs_data[idof->localId()];
233+
}
234+
}
235+
236+
Real a3 = platform::getRealTime();
237+
info() << "[Alien-Timer] Time to create vectors = " << (a3 - a2);
238+
239+
m_solver_backend->solve(matrixA, vectorB, vectorX);
240+
241+
Real a4 = platform::getRealTime();
242+
info() << "[Alien-Timer] Time to solve = " << (a4 - a3);
243+
244+
Alien::SolverStatus status = m_solver_backend->getStatus();
245+
246+
if (status.succeeded) {
247+
info() << "[Alien-Info] " << "Converged in " << status.iteration_count + 1 << " iterations";
248+
249+
Alien::VectorReader reader(vectorX);
250+
// TODO understand this
251+
ENUMERATE_DOF(idof, areaU.own()) {
252+
const Integer iIndex = allUIndex[idof->localId()];
253+
// info() << "val:" << reader[iIndex];
254+
dof_variable[idof] = reader[iIndex];
255+
}
256+
}
257+
else
258+
info()<<"SOLVER FAILED";
259+
m_solver_backend->getSolverStat().print(Universe().traceMng(), status, "Linear Solver : ");
260+
}
261+
262+
class AlienDoFLinearSystemFactoryService
263+
: public ArcaneAlienDoFLinearSystemFactoryObject
264+
{
265+
public:
266+
267+
explicit AlienDoFLinearSystemFactoryService(const ServiceBuildInfo& sbi)
268+
: ArcaneAlienDoFLinearSystemFactoryObject(sbi)
269+
{
270+
info() << "[Alien-Info] Create AlienDoF";
271+
};
272+
IDoFLinearSystemImpl*
273+
createInstance(ISubDomain* sd, IItemFamily* dof_family, const String& solver_name) override
274+
{
275+
auto* x = new AlienDoFLinearSystemImpl(dof_family, solver_name);
276+
x->options = options();
277+
278+
Alien::ILinearSolver* solver_backend = options()->linearSolver.instance();
279+
x->setSolver(solver_backend);
280+
solver_backend->init();
281+
282+
return x;
283+
}
284+
};
285+
286+
ARCANE_REGISTER_SERVICE_ALIENDOFLINEARSYSTEMFACTORY(AlienLinearSystem,
287+
AlienDoFLinearSystemFactoryService);
288+
289+
} // namespace Arcane::FemUtils
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" ?><!-- -*- SGML -*- -->
2+
<service name="AlienDoFLinearSystemFactory" version="1.0" type="caseoption" namespace-name="Arcane::FemUtils">
3+
<interface name="Arcane::FemUtils::IDoFLinearSystemFactory" />
4+
<options>
5+
<service-instance name="linear-solver" type="Alien::ILinearSolver">
6+
<description>Service solveur</description>
7+
</service-instance>
8+
</options>
9+
</service>

femutils/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ if (TARGET Arcane::arcane_aleph_petsc)
1414
list(APPEND ACCELERATOR_SOURCES PETScDoFLinearSystem.cc)
1515
endif()
1616

17+
find_package(Alien)
18+
if (Alien_FOUND)
19+
list(APPEND ACCELERATOR_SOURCES AlienDoFLinearSystem.cc)
20+
endif()
21+
1722
add_library(FemUtils
1823
FemUtils.h
1924
FemUtils.cc
@@ -44,6 +49,7 @@ add_library(FemUtils
4449
SequentialBasicDoFLinearSystemFactory_axl.h
4550
HypreDoFLinearSystemFactory_axl.h
4651
PETScDoFLinearSystemFactory_axl.h
52+
AlienDoFLinearSystemFactory_axl.h
4753
FemBoundaryConditions_axl.h
4854
MeshTensorVariable.h
4955
MeshTensorVariable.H
@@ -61,6 +67,7 @@ arcane_generate_axl(AlephDoFLinearSystemFactory)
6167
arcane_generate_axl(SequentialBasicDoFLinearSystemFactory)
6268
arcane_generate_axl(HypreDoFLinearSystemFactory)
6369
arcane_generate_axl(PETScDoFLinearSystemFactory)
70+
arcane_generate_axl(AlienDoFLinearSystemFactory)
6471
arcane_generate_axl(FemBoundaryConditions)
6572

6673
target_compile_definitions(FemUtils PRIVATE $<$<BOOL:${ENABLE_DEBUG_MATRIX}>:ENABLE_DEBUG_MATRIX>)
@@ -76,6 +83,20 @@ set(FEMUTILS_HAS_PARALLEL_SOLVER FALSE)
7683
set(FEMUTILS_HAS_PARALLEL_SOLVER_TRILINOS FALSE)
7784
set(FEMUTILS_HAS_PARALLEL_SOLVER_HYPRE FALSE)
7885
set(FEMUTILS_HAS_PARALLEL_SOLVER_PETSC FALSE)
86+
set(FEMUTILS_HAS_PARALLEL_SOLVER_ALIEN FALSE)
87+
88+
if (Alien_FOUND)
89+
find_package(Boost REQUIRED)
90+
find_package(AlienPlugins REQUIRED)
91+
target_link_libraries(FemUtils PRIVATE
92+
Alien::alien_core
93+
Alien::alien_semantic_ref
94+
alien_arcane_tools
95+
arcane_full
96+
)
97+
message(STATUS "Alien backend is available")
98+
set(FEMUTILS_HAS_SOLVER_BACKEND_ALIEN TRUE)
99+
endif()
79100

80101
if (TARGET Arcane::arcane_aleph_trilinos)
81102
set(FEMUTILS_HAS_PARALLEL_SOLVER TRUE)
@@ -130,3 +151,4 @@ set(FEMUTILS_HAS_PARALLEL_SOLVER ${FEMUTILS_HAS_PARALLEL_SOLVER} CACHE BOOL "Is
130151
set(FEMUTILS_HAS_SOLVER_BACKEND_TRILINOS ${FEMUTILS_HAS_SOLVER_BACKEND_TRILINOS} CACHE BOOL "Is Trilinos solver available" FORCE)
131152
set(FEMUTILS_HAS_SOLVER_BACKEND_PETSC ${FEMUTILS_HAS_SOLVER_BACKEND_PETSC} CACHE BOOL "Is PETSc solver available" FORCE)
132153
set(FEMUTILS_HAS_SOLVER_BACKEND_HYPRE ${FEMUTILS_HAS_SOLVER_BACKEND_HYPRE} CACHE BOOL "Is Hypre solver available" FORCE)
154+
set(FEMUTILS_HAS_SOLVER_BACKEND_ALIEN ${FEMUTILS_HAS_SOLVER_BACKEND_ALIEN} CACHE BOOL "Is Alien solver available" FORCE)

femutils/FemDoFsOnNodes.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ initialize(IMesh* mesh, Int32 nb_dof_per_node)
7979
Int64UniqueArray uids(mesh->allNodes().size() * nb_dof_per_node);
8080
{
8181
Integer dof_index = 0;
82-
UniqueArray<Int64> hash_maker({0,0});
82+
// Use a mask to make sure the uniqueId() of the dof
83+
// can not be negative if we multiply the uniqueId().
84+
const UInt64 uid_mask = (1<<28) - 1;
8385
ENUMERATE_NODE (inode, mesh->allNodes()) {
8486
Node node = *inode;
8587
Int64 node_unique_id = node.uniqueId().asInt64();
86-
hash_maker[0] = node_unique_id;
8788
for (Integer i = 0; i < nb_dof_per_node; ++i) {
88-
hash_maker[1] = i;
89-
uids[dof_index] = MeshUtils::generateHashUniqueId(hash_maker.constView());
89+
uids[dof_index] = (node_unique_id & uid_mask) * nb_dof_per_node + i;
9090
++dof_index;
9191
}
9292
}

modules/aerodynamics/FemModule.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ startInit()
4242
if (m_matrix_format == "BSR" || m_matrix_format == "AF-BSR") {
4343
bool use_csr_in_linear_system =
4444
options()->linearSystem.serviceName() == "HypreLinearSystem" ||
45+
options()->linearSystem.serviceName() == "AlienLinearSystem" ||
4546
options()->linearSystem.serviceName() == "PETScLinearSystem";
4647
if (m_matrix_format == "BSR")
4748
m_bsr_format.initialize(mesh(), 1, use_csr_in_linear_system, 0);

modules/elasticity/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ enable_testing()
4242

4343
if(FEMUTILS_HAS_SOLVER_BACKEND_PETSC)
4444
set(SOLVER_PETSC_GMRES
45-
-A,//fem/petsc-flags=-ksp_monitor\ -ksp_type\ gmres\ -pc_type\ bjacobi\ -ksp_rtol\ 1e-15)
45+
-A,//fem/petsc-flags=-ksp_monitor\ -ksp_type\ gmres\ -pc_type\ bjacobi\ -ksp_rtol\ 1e-15\ -ksp_atol\ 1e-15)
4646

4747
add_test(NAME [elasticity]Dirichlet COMMAND Elasticity
4848
-A,//fem/solution-comparison-file=check/bar.2D.Dirichlet.bodyForce.txt

0 commit comments

Comments
 (0)