Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
AlephTestSchemeFaces.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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#include "arcane/aleph/tests/AlephTest.h"
8#include "arcane/aleph/tests/AlephTestScheme.h"
9#include "arcane/aleph/tests/AlephTestSchemeFaces.h"
10
11#include "arcane/mesh/CellFamily.h"
12#include "arcane/mesh/FaceFamily.h"
13
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17namespace ArcaneTest
18{
19
20/*---------------------------------------------------------------------------*/
21/*---------------------------------------------------------------------------*/
22
23using namespace Arcane;
24
25ARCANE_REGISTER_SERVICE_ALEPHTESTSCHEMEFACES(Faces, AlephTestSchemeFaces);
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30AlephTestSchemeFaces::
31AlephTestSchemeFaces(const ServiceBuildInfo& sbi)
32: ArcaneAlephTestSchemeFacesObject(sbi)
33{
34 debug() << "\33[37m\t[AlephTestSchemeFaces::AlephTestSchemeFaces] New"
35 << "\33[0m";
36}
37
38AlephTestSchemeFaces::~AlephTestSchemeFaces(void)
39{
40 debug() << "\33[37m\t[AlephTestSchemeFaces::AlephTestSchemeFaces] Delete"
41 << "\33[0m";
42}
43
44/***************************************************************************
45 * Application of scheme-specific boundary conditions
46 ***************************************************************************/
47void AlephTestSchemeFaces::
48boundaries(ArcaneTest::CaseOptionsAlephTestModule* module_options)
49{
50 ItacFunction(AlephTestSchemeFaces);
51 // loop over the boundary conditions
52 for (int i = module_options->boundaryCondition.size() - 1; i >= 0; --i) {
53 Real temperature = module_options->boundaryCondition[i]->value();
54 FaceGroup face_group = module_options->boundaryCondition[i]->surface();
55 // loop over the faces of the surface
56 ENUMERATE_FACE (iFace, face_group) {
57 m_face_temperature[iFace] = temperature;
58 }
59 }
60}
61
62/***************************************************************************
63 * Count the number of non-zero elements per matrix row
64 ***************************************************************************/
65void AlephTestSchemeFaces::
66preFetchNumElementsForEachRow(IntegerArray& rows_nb_element,
67 const Integer rank_row_offset)
68{
69 ItacFunction(AlephTestSchemeFaces);
70 debug() << "\33[37m\t[AlephTestSchemeFaces::preFetchNumElementsForEachRow]"
71 << "\33[0m";
72 // Count the diagonal terms
73 rows_nb_element.fill(1);
74
75 // And add the face couplings
76 // Note: We must iterate over all cells and filter ghost faces
77 ENUMERATE_FACE (iFace, INNER_ACTIVE_FACE_GROUP(allCells())) {
78 if (iFace->backCell().isOwn())
79 rows_nb_element[m_cell_matrix_idx[iFace->backCell()] - rank_row_offset] += 1;
80 if (iFace->frontCell().isOwn())
81 rows_nb_element[m_cell_matrix_idx[iFace->frontCell()] - rank_row_offset] += 1;
82 }
83}
84
85/***************************************************************************
86 * AlephTestModule::_FaceComputeSetValues *
87 ***************************************************************************/
88void AlephTestSchemeFaces::
89setValues(const Real deltaT, AlephMatrix* aleph_mat)
90{
91 // Flush the coefficients
92 ENUMERATE_CELL (iCell, MESH_OWN_ACTIVE_CELLS(mesh()))
93 m_cell_coefs[iCell] = 0.;
94 // Faces 'inner'
95 debug() << "\33[37m[AlephTestSchemeFaces::setValues] inner-faces"
96 << "\33[0m";
97 ENUMERATE_FACE (iFace, INNER_ACTIVE_FACE_GROUP(allCells())) {
98 if (iFace->backCell().isOwn()) {
99 const Real surface = AlephTestModule::geoFaceSurface(*iFace, nodesCoordinates());
100 aleph_mat->setValue(m_cell_matrix_idx[iFace->backCell()],
101 m_cell_matrix_idx[iFace->frontCell()], -deltaT / surface);
102 m_cell_coefs[iFace->backCell()] += 1.0 / surface;
103 }
104 if (iFace->frontCell().isOwn()) {
105 const Real surface = AlephTestModule::geoFaceSurface(*iFace, nodesCoordinates());
106 aleph_mat->setValue(m_cell_matrix_idx[iFace->frontCell()],
107 m_cell_matrix_idx[iFace->backCell()], -deltaT / surface);
108 m_cell_coefs[iFace->frontCell()] += 1.0 / surface;
109 }
110 }
111 debug() << "\33[37m[AlephTestSchemeFaces::setValues] outer-faces"
112 << "\33[0m";
113 ENUMERATE_FACE (iFace, OUTER_ACTIVE_FACE_GROUP(allCells())) {
114 if (!iFace->cell(0).isOwn())
115 continue;
116 m_cell_coefs[iFace->cell(0)] += 1.0 / AlephTestModule::geoFaceSurface(*iFace, nodesCoordinates());
117 }
118 debug() << "\33[37m[AlephTestSchemeFaces::setValues] diagonale"
119 << "\33[0m";
120 ENUMERATE_CELL (iCell, MESH_OWN_ACTIVE_CELLS(mesh())) {
121 aleph_mat->setValue(m_cell_matrix_idx[iCell], m_cell_matrix_idx[iCell], 1.0 + deltaT * m_cell_coefs[iCell]);
122 }
123 debug() << "\33[37m[AlephTestSchemeFaces::setValues] done"
124 << "\33[0m";
125}
126
127/***************************************************************************
128 * AlephTestModule::_amrRefine *
129 ***************************************************************************/
130bool AlephTestSchemeFaces::
131amrRefine(RealArray& values, const Real trigRefine)
132{
133 ItacFunction(AlephTestSchemeFaces);
134 if (!options()->amr)
135 return false;
136 debug() << "\33[37m[AlephTestModule::_FaceAmrRefine]"
137 << "\33[0m";
138 Int32UniqueArray cells_lid;
139
140 /*ENUMERATE_CELL(iCell, allCells()){
141 debug()<<"\t\t[FaceAmrRefine] cell #"<<(iCell).localId();
142 ENUMERATE_FACE(iFace, (*iCell).faces()){
143 debug()<<"\t\t\t[FaceAmrRefine] face #"<<iFace->localId();
144 }
145 }*/
146
147 ENUMERATE_CELL (iCell, MESH_ALL_ACTIVE_CELLS(mesh())) {
148 if ((*iCell).level() == 1)
149 continue;
150 const Real T0 = m_cell_temperature[iCell];
151 const Real T1 = values[m_cell_matrix_idx[iCell]];
152 const Real ecart_relatif = ECART_RELATIF(T0, T1);
153 Cell iItem = (*iCell);
154
155 if (ecart_relatif > trigRefine) {
156 //debug()<< "[AlephTestModule::_amrRefine] HIT ecart_relatif="<<ecart_relatif<<", cell_"<<(*iCell).localId();
157 cells_lid.add((*iCell).localId());
159 }
160 }
161
162 if (cells_lid.size() == 0)
163 return false;
164
165 debug() << "\33[37m[AlephTestModule::_amrRefine] NOW refine"
166 << "\33[0m";
167 MESH_MODIFIER_REFINE_ITEMS(mesh());
168 mesh()->modifier()->endUpdate();
169
170 // Now callBack the values
171 CellInfoListView cells(mesh()->cellFamily());
172 //ItemInternalList faces = mesh()->faceFamily()->itemsInternal();
173 for (Integer i = 0, is = cells_lid.size(); i < is; ++i) {
174 Int32 lid = cells_lid[i];
175 Cell cell = cells[lid];
176
177 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j) {
178 //debug()<<"\t\t[amrRefineMesh] child cell #"<<cell.hChild(j).localId();
179 m_cell_temperature[cells[CELL_H_CHILD(cell, j).localId()]] = m_cell_temperature[cells[lid]];
180 auto faces = allCells().view()[CELL_H_CHILD(cell, j).localId()].toCell().faces();
181 Integer index = 0;
182 for (Face face : faces) {
183 if (face.isSubDomainBoundary()) {
184 //debug() << "\t\t\t[amrRefineMesh] outer face #"<< iFace->localId()<<", index="<<iFace.index()<<", T="<<m_face_temperature[cell.face(iFace.index())];
185 m_face_temperature[face] = m_face_temperature[cell.face(index)];
186 }
187 else {
188 //debug() << "\t\t\t[amrRefineMesh] inner face #"<< iFace->localId();//<<", T="<<m_face_temperature[face.toFace()];
189 m_face_temperature[face] = 0;
190 }
191 ++index;
192 }
193 }
194 }
195
196 debug() << "\33[37m[AlephTestModule::_amrRefine] done"
197 << "\33[0m";
198 return true;
199}
200
201/***********************************
202 * AlephTestModule::_FaceAmrRefine *
203 ***********************************/
204bool AlephTestSchemeFaces::
205amrCoarsen(RealArray& values, const Real trigCoarsen)
206{
207 ItacFunction(AlephTestSchemeFaces);
208 if (!options()->amr)
209 return false;
210 debug() << "\33[37m[AlephTestModule::_FaceAmrCoarsen]"
211 << "\33[0m";
212 Int32UniqueArray parents_to_coarsen_lid;
213 Int32UniqueArray children_to_coarsen_lid;
214 mesh::FaceReorienter faceReorienter(mesh());
215 mesh::DynamicMesh* dynMesh = dynamic_cast<mesh::DynamicMesh*>(mesh());
216 CellInfoListView cells(mesh()->cellFamily());
217 Int32UniqueArray faces_to_attach;
218 Int32UniqueArray lids_to_be_attached;
219
220 // Scan over all cells, active AND inactive
221 ENUMERATE_CELL (iCell, allCells()) {
222 Cell cell = *iCell;
223 //onst Real Tp=m_cell_temperature[iCell];
224 Real oldTs[4];
225 Real newTs[4];
226 Real sumTs = 0.0;
227 bool coarsit = true;
228
229 //debug()<<"true="<<true<<", false="<<false;
230 if (cell.level() == 1)
231 continue; // Avoid working on leaves
232
233 if (!CELL_HAS_H_CHILDREN(cell))
234 continue; // Avoid cells that do not have children
235
236 // Check if all children are active
237 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j)
238 coarsit &= CELL_H_CHILD(cell, j).isActive();
239 if (coarsit == false)
240 continue;
241
242 //debug()<<"\t\t[FaceAmrCoarsen] parent cell Tp="<<Tp<<", "<<cell.localId();
243 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j) {
244 oldTs[j] = m_cell_temperature[cells[CELL_H_CHILD(cell, j).localId()]];
245 newTs[j] = values[m_cell_matrix_idx[CELL_H_CHILD(cell, j)]];
246 sumTs += newTs[j];
247 coarsit &= (ECART_RELATIF(oldTs[j], newTs[j]) < trigCoarsen);
248 //debug()<<"\t\t\t[FaceAmrCoarsen] child cell #"<<cell.hChild(j).localId()<<", oldT="<<oldTs[j]<<", newT="<<newTs[j];
249 }
250 if (coarsit == false)
251 continue;
252
253 // Check the differences between children
254 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j)
255 coarsit &= (ECART_RELATIF(newTs[j], newTs[(j + 1) % 4]) < trigCoarsen);
256 if (coarsit == false)
257 continue;
258
259 debug() << "\n\t\t\t\t\t\t[FaceAmrCoarsen] parent cell to COARSE #" << cell.localId();
260
261 // Add the parent's lid to the pool of cells to coarsen
262 parents_to_coarsen_lid.add((*iCell).localId());
263
264 // And tag it as Active
265 (*iCell).mutableItemBase().removeFlags(ItemInternal::II_CoarsenInactive);
266 ARCANE_ASSERT(((*iCell).isActive()), ("Parent not active!"));
267
268 // Set the new value of the cell
269 m_cell_temperature[iCell] = sumTs / 4.0;
270
271 // Add the children's lids to remove them later
272 for (Integer j = 0, js = CELL_NB_H_CHILDREN(cell); j < js; ++j) {
273 children_to_coarsen_lid.add(CELL_H_CHILD(cell, j).localId());
274 CELL_H_CHILD(cell, j).mutableItemBase().setFlags(CELL_H_CHILD(cell, j).itemBase().flags() | ItemInternal::II_Inactive); //II_Coarsen
275 }
276
277 // Now stare at the children to set up new faces' values
278 Cell parent = cell;
279 //const Cell &parent = cellFamily()->itemsInternal()[parents_to_coarsen_lid[i]];
280 for (Face face : parent.faces()) {
281 if ((!face.backCell().null()) && (!face.frontCell().null())) {
282 debug() << "\t\t\t[FaceAmrCoarsen] FOCUS face #" << face.localId() << ", "
283 << face.backCell().localId() << "->"
284 << face.frontCell().localId();
285 // Now we are going to attach the neighbors to our parent
286 const Cell& neighbour = (face.backCell().localId() == parent.localId()) ? face.frontCell() : face.backCell();
287 debug() << "\t\t\t[FaceAmrCoarsen] neighbour #" << neighbour.localId() << ", level=" << neighbour.level();
288
289 // The parent's neighbor must be a parent
290 ARCANE_ASSERT((neighbour.level() == 0), ("Wrong neighbour level!"));
291
292 // If the neighbor is active, the current face is the one that must be used
293 if (neighbour.isActive()) {
294 debug() << "\t\t\t[FaceAmrCoarsen] neighbour is ACTIVE";
295 debug() << "\t\t\t[FaceAmrCoarsen] hit: face_" << face.localId() << ": " << neighbour.localId() << "->" << parent.localId();
296 //faces_to_attach.add(face.localId());
297 //lids_to_be_attached.add(parent.localId());
298 //dynMesh->trueFaceFamily().replaceBackCellToFace(face.internal(),neighbour.internal());//face.backCell().internal());
299 //dynMesh->trueFaceFamily().replaceFrontCellToFace(face.internal(),parent.internal());//face.frontCell().internal());
300 //faceReorienter.checkAndChangeOrientation(face.internal());
301 continue;
302 }
303
304 {
305 int iFound = 0;
306 bool found[2];
307 found[0] = found[1] = false;
308 // Otherwise, we reattach the faces of our neighbor's children to our parent
309 for (Integer j = 0, js = CELL_NB_H_CHILDREN(neighbour); j < js; ++j) {
310 //debug()<<"\t\t\t\t[FaceAmrCoarsen] neighbour child #"<<neighbour.hChild(j).localId();
311
312 auto faces = CELL_H_CHILD(neighbour, j).faces();
313 for (Face face : faces) {
314 if (face.backCell().null())
315 continue;
316 if (face.frontCell().null())
317 continue;
318
319 Cell other = (face.frontCell().localId() == CELL_H_CHILD(neighbour, j).localId()) ? face.backCell() : face.frontCell();
320 //debug()<<"\t\t\t\t[FaceAmrCoarsen] neighbour child face #"<<face.localId()<<", "<< face.backCell().localId()<<"->"<< face.frontCell().localId();
321
322 // If the other is a parent, that is not what we are looking for
323 if (other.level() == 0)
324 continue;
325
326 //debug()<<"\t\t\t\t[FaceAmrCoarsen] parent id="<<other.hParent().localId();
327 if (CELL_H_PARENT(other).localId() != parent.localId())
328 continue;
329
330 debug() << "\t\t\t\t[FaceAmrCoarsen] hit: face_" << face.localId() << ": " << CELL_H_CHILD(neighbour, j).localId() << "->" << parent.localId();
331 faces_to_attach.add(face.localId());
332 lids_to_be_attached.add(parent.localId());
333 found[iFound++] = true;
334 break;
335 }
336 if (iFound == 2)
337 break;
338 }
339 }
340 // ARCANE_ASSERT(((found[0]==true)&&(found[1]==true)),("Not found"));
341 }
342 else if (face.backCell().null()) {
343 debug() << "\t\t\t[FaceAmrCoarsen] skip face #" << face.localId() << ", ?->" << face.frontCell().localId() << " ";
344 }
345 else {
346 debug() << "\t\t\t[FaceAmrCoarsen] skip face #" << face.localId() << ", " << face.backCell().localId() << "->?"
347 << " ";
348 }
349 }
350 }
351
352 // If there is nothing to do, we exit
353 if (parents_to_coarsen_lid.size() == 0)
354 return false;
355
356 CellInfoListView cells_view(mesh()->cellFamily());
357 FaceInfoListView faces_view(mesh()->faceFamily());
358
359 // Remove the cells
360 for (Integer j = 0, js = children_to_coarsen_lid.size(); j < js; ++j) {
361 //const Cell &cell=cellFamily()->itemsInternal()[children_to_coarsen_lid[j]];
362 //debug()<<"\t\t[FaceAmrCoarsen] REMOVING CELL_"<<children_to_coarsen_lid[j];
363 dynMesh->trueCellFamily().removeCell(cells_view[children_to_coarsen_lid[j]]);
364 //dynMesh->trueCellFamily().detachCell(cellFamily()->itemsInternal()[children_to_coarsen_lid[j]]);
365 /* ENUMERATE_FACE(iFace, cell.faces()){
366 dynMesh->trueFaceFamily().populateBackFrontCellsFromParentFaces(cell.internal());
367
368 }*/
369 }
370 //mesh()->modifier()->endUpdate();
371
372 // Re-attach the faces
373 for (Integer j = 0, js = faces_to_attach.size(); j < js; ++j) {
374 Face face = faces_view[faces_to_attach[j]];
376 debug() << "\t\t[FaceAmrCoarsen] NOW patch face_" << faces_to_attach[j] << ": " << face.backCell().localId() << "->" << lids_to_be_attached[j];
377 //dynMesh->trueFaceFamily().replaceFrontCellToFace(face.internal(),cellFamily()->itemsInternal()[lids_to_be_attached[j]]);
378 dynMesh->trueFaceFamily().addFrontCellToFace(face, cells_view[lids_to_be_attached[j]]);
379 }
380 else {
381 debug() << "\t\t[FaceAmrCoarsen] NOW patch face_" << faces_to_attach[j] << ": " << face.frontCell().localId() << "->" << lids_to_be_attached[j];
382 //dynMesh->trueFaceFamily().replaceBackCellToFace(face.internal(),cellFamily()->itemsInternal()[lids_to_be_attached[j]]);
383 dynMesh->trueFaceFamily().addBackCellToFace(face, cells_view[lids_to_be_attached[j]]);
384 }
385 faceReorienter.checkAndChangeOrientation(face);
386 }
387 //faceFamily()->endUpdate();
388
389 // Update our changes
390 mesh()->modifier()->endUpdate();
391
392 debug() << "\t\t[FaceAmrCoarsen] nbCell=" << MESH_ALL_ACTIVE_CELLS(mesh()).size();
393
394 //dynMesh->trueCellFamily().allItems().internal()->clear();//m_all_active_cell_group=0;
395 /*ENUMERATE_CELL(iCell, allCells()){
396 debug()<<"\t\t[dump] cell #"<<(iCell).localId()<<" ("<<(*iCell).isActive()<<")";
397 ENUMERATE_FACE(iFace, (*iCell).faces()){
398 if ((!iFace->backCell().null())&&(!iFace->frontCell().null())){
399 debug()<<"\t\t\t[dump] face #"<<iFace->localId()<<", "\
400 <<iFace->backCell().localId()<<"->"\
401 <<iFace->frontCell().localId()\
402 <<" ("<<iFace->isActive()<<")";
403 }else if (iFace->backCell().null()){
404 debug()<<"\t\t\t[dump] face #"<<iFace->localId()<<", ?->" \
405 <<iFace->frontCell().localId()\
406 <<" ("<<iFace->isActive()<<")";
407 }else{
408 debug()<<"\t\t\t[dump] face #"<<iFace->localId()<<", " \
409 <<iFace->backCell().localId()<<"->?" \
410 <<" ("<<iFace->isActive()<<")";
411 }
412 }
413 }*/
414
415 // And inform the caller that there were changes
416 debug() << "[AlephTestModule::FaceAmrCoarsen] done";
417 return true;
418}
419
420/*---------------------------------------------------------------------------*/
421/*---------------------------------------------------------------------------*/
422
423} // namespace ArcaneTest
424
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
Integer size() const
Number of elements in the vector.
Matrix of a linear system.
Definition AlephMatrix.h:33
void setValue(const VariableRef &, const Item &, const VariableRef &, const Item &, const Real)
setValue from arguments in IVariables, Items, and Real
void fill(ConstReferenceType value)
Fills the array with the value value.
void add(ConstReferenceType val)
Adds element val to the end of the array.
View of cell information.
Cell of a mesh.
Definition Item.h:1300
FaceConnectedListViewType faces() const
List of faces of the cell.
Definition Item.h:1403
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
bool isActive() const
Definition Item.h:1451
Int32 level() const
Definition Item.h:1473
View of face information.
This function/class reorients faces.
Face of a cell.
Definition Item.h:1032
Cell frontCell() const
Cell in front of the face (null cell if none).
Definition Item.h:1780
Cell backCell() const
Cell behind the face (null cell if none).
Definition Item.h:1774
Int32 flags() const
Flags of the entity.
@ II_Inactive
The entity is inactive //COARSEN_INACTIVE,.
Definition ItemFlags.h:80
@ II_Refine
The entity is marked for refinement.
Definition ItemFlags.h:77
@ II_HasBackCell
The entity has a back cell.
Definition ItemFlags.h:53
@ II_CoarsenInactive
The entity is inactive and has children tagged for coarsening.
Definition ItemFlags.h:81
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
void addFlags(Int32 added_flags)
Adds the flags added_flags to those of the entity.
Structure containing the information to create a service.
void removeCell(Cell cell)
Implementation of a mesh.
Definition DynamicMesh.h:98
void addFrontCellToFace(Face face, Cell new_cell)
Adds a front cell to the face.
void addBackCellToFace(Face face, Cell new_cell)
Adds a back cell to the face.
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
Int32 Integer
Type representing an integer.
Array< Integer > IntegerArray
Dynamic one-dimensional array of integers.
Definition UtilsTypes.h:133
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
Array< Real > RealArray
Dynamic one-dimensional array of reals.
Definition UtilsTypes.h:135