Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions arcane/tools/GeometricGenerationScriban/GeomShapeInfos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace GeometricGenerationScriban
{
/// <summary>
/// Type of a geometric element (copy of Arcane::geometric::GeomType).
/// NOTE: the identifiers must correspond to those of the enumeration
/// GeomType of 'arcane/src/arcane/geometry/GeomType.h' and to the
/// descriptors of 'GeometricGenerationCpp/GeomShapeInfos.h'; this is
/// checked at startup by GeomShapeInfos.Check().
/// </summary>
public enum GeomType
{
Vertex,
Line2,
Triangle3,
Quad4,
Pentagon5,
Hexagon6,
Tetraedron4,
Pyramid5,
Pentaedron6,
Hexaedron8,
Heptaedron10,
Octaedron12
}

/// <summary>
/// Description of one geometric shape type.
/// </summary>
public sealed class GeomShapeInfo
{
public string Name { get; }
public GeomType Type { get; }
public int NbNode { get; }
public int NbEdge { get; }
public int NbFace { get; }
public int Dimension { get; }
public string BasicName { get; }
//! Name of the element holding a control sub-volume ("Quad4" or "Hexaedron8")
public string SvcName { get; }
//! Arguments "const Real3& a0, const Real3& a1, ..." (NbNode arguments)
public string CoordsArgs { get; }

internal GeomShapeInfo(GeomType type, int nb_node, int nb_edge, int nb_face,
int dimension, string basic_name)
{
Name = type.ToString();
Type = type;
NbNode = nb_node;
NbEdge = nb_edge;
NbFace = nb_face;
Dimension = dimension;
BasicName = basic_name;
SvcName = (dimension == 2) ? "Quad4" : "Hexaedron8";
var args = new StringBuilder();
for (int i = 0; i < nb_node; ++i) {
if (i != 0)
args.Append(", ");
args.Append("const Real3& a").Append(i);
}
CoordsArgs = args.ToString();
}
}

/// <summary>
/// Static description of the geometric shape types.
/// This is the data model of the generator.
/// </summary>
public static class GeomShapeInfos
{
static readonly GeomShapeInfo[] _items = new GeomShapeInfo[]{
new GeomShapeInfo(GeomType.Vertex, 1, 0, 0, 1, "Vertex"),
new GeomShapeInfo(GeomType.Line2, 2, 0, 0, 1, "Line"),
new GeomShapeInfo(GeomType.Triangle3, 3, 3, 3, 2, "Triangle"),
new GeomShapeInfo(GeomType.Quad4, 4, 4, 4, 2, "Quad"),
new GeomShapeInfo(GeomType.Pentagon5, 5, 5, 5, 2, "Pentagon"),
new GeomShapeInfo(GeomType.Hexagon6, 6, 6, 6, 2, "Hexagon"),
new GeomShapeInfo(GeomType.Tetraedron4, 4, 6, 4, 3, "Tetra"),
new GeomShapeInfo(GeomType.Pyramid5, 5, 12, 5, 3, "Pyramid"),
new GeomShapeInfo(GeomType.Pentaedron6, 6, 9, 5, 3, "Penta"),
new GeomShapeInfo(GeomType.Hexaedron8, 8, 12, 6, 3, "Hexa"),
new GeomShapeInfo(GeomType.Heptaedron10, 10, 15, 6, 3, "Wedge7"),
new GeomShapeInfo(GeomType.Octaedron12, 12, 18, 8, 3, "Wedge8")
};

public static IReadOnlyList<GeomShapeInfo> Items {
get { return _items; }
}

public static IReadOnlyList<GeomShapeInfo> Items2DAnd3D {
get {
var result = new List<GeomShapeInfo>();
foreach (var item in _items)
if (item.Dimension == 2 || item.Dimension == 3)
result.Add(item);
return result;
}
}

/// <summary>
/// Checks that each GeomType enumerator has exactly one descriptor
/// with the same identifier and the same value, and vice versa.
/// </summary>
public static void Check()
{
string[] names = Enum.GetNames(typeof(GeomType));
if (names.Length != _items.Length)
throw new InvalidOperationException("The number of GeomType enumerators does not match the number of descriptors");
foreach (var name in names) {
GeomShapeInfo found = null;
foreach (var item in _items) {
if (item.Name == name) {
if (found != null)
throw new InvalidOperationException("Duplicate descriptor for GeomType::" + name);
found = item;
}
}
if (found == null)
throw new InvalidOperationException("Missing descriptor for GeomType::" + name);
if (found.Type != (GeomType)Enum.Parse(typeof(GeomType), name))
throw new InvalidOperationException("Mismatched value for descriptor GeomType::" + name);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetExt>.dll</TargetExt>
<OutputType>Exe</OutputType>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="GeomShapeInfos.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Scriban" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
<None Include="Templates\*.scriban">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
84 changes: 84 additions & 0 deletions arcane/tools/GeometricGenerationScriban/Main.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Scriban;
using Scriban.Runtime;

namespace GeometricGenerationScriban
{
/// <summary>
/// Generation of the 'Generated*.h' files of arcane/src/arcane/geometry
/// from the Scriban templates of the 'Templates' directory.
/// This generator produces the same files as the C++26 reflection
/// generator 'GeometricGenerationCpp'. The generated headers are plain
/// C++ and can be used by any C++20 compiler.
/// </summary>
public static class MainClass
{
public static int Main(string[] args)
{
GeomShapeInfos.Check();

string base_path = (args.Length > 0) ? args[0] : "../../src/arcane/geometry";
string template_dir = Path.Combine(AppContext.BaseDirectory, "Templates");

_Generate(template_dir, "GeneratedConnectivity.h.scriban", base_path, "GeneratedConnectivity.h");
_Generate(template_dir, "GeneratedGeomShapeView.h.scriban", base_path, "GeneratedGeomShapeView.h");
_Generate(template_dir, "GeneratedGeomElement.h.scriban", base_path, "GeneratedGeomElement.h");
_Generate(template_dir, "GeneratedGeomElementView.h.scriban", base_path, "GeneratedGeomElementView.h");
_Generate(template_dir, "GeneratedGeomShapeViewDeclarations.h.scriban", base_path, "GeneratedGeomShapeViewDeclarations.h");
return 0;
}

static void _Generate(string template_dir, string template_name, string base_path, string output_name)
{
string template_path = Path.Combine(template_dir, template_name);
var template = Template.Parse(File.ReadAllText(template_path, Encoding.UTF8), template_path);
if (template.HasErrors) {
foreach (var error in template.Messages)
Console.Error.WriteLine("Template error: {0}", error);
throw new InvalidOperationException("Failed to parse template '" + template_path + "'");
}

var context = new TemplateContext();
context.PushGlobal(_BuildModel());
string text = template.Render(context);

string full_path = Path.Combine(base_path, output_name);
Console.WriteLine("Generating file '{0}'", full_path);
File.WriteAllText(full_path, text, new UTF8Encoding(true));
}

/// <summary>
/// Builds the model exposed to the templates: the objects are ScriptObject
/// with explicit keys (name, nb_node, ...) so that the rendering does not
/// depend on the .NET member renaming rules.
/// </summary>
static ScriptObject _BuildModel()
{
var root = new ScriptObject();
root["items"] = _ToList(GeomShapeInfos.Items);
root["items_2d_3d"] = _ToList(GeomShapeInfos.Items2DAnd3D);
return root;
}

static List<ScriptObject> _ToList(IReadOnlyList<GeomShapeInfo> descriptors)
{
var result = new List<ScriptObject>();
foreach (var info in descriptors) {
var obj = new ScriptObject();
obj["name"] = info.Name;
obj["nb_node"] = info.NbNode;
obj["nb_edge"] = info.NbEdge;
obj["nb_face"] = info.NbFace;
obj["dimension"] = info.Dimension;
obj["basic_name"] = info.BasicName;
obj["svc_name"] = info.SvcName;
obj["coords_args"] = info.CoordsArgs;
result.Add(obj);
}
return result;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// WARNING: This file is generated by a tool. DO NOT EDIT.
/*
* Generation of classes allowing retrieval of connectivity information
* for each type of geometric element.
*/
{{ for item in items }}/*!
* \ingroup ArcaneGeometric
* \brief Connectivity information for geometric elements of type GeomType::{{ item.name }}.
{{ if item.name == 'Pyramid5' }} *
* \note the pyramid has 8 edges but it is considered a degenerate hexahedron
* at the pyramid's apex. To account for this, we indicate
* that it has 12 edges.
{{ end }} */
class ARCANE_GEOMETRY_EXPORT {{ item.name }}Connectivity
: public CellConnectivity
{
public:

{{ item.name }}Connectivity()
: CellConnectivity({{ item.nb_node }},{{ item.nb_edge }},{{ item.nb_face }},GeomType::{{ item.name }})
{
_init();
}

public:

constexpr Int32 nbNode() const { return {{ item.nb_node }}; }
constexpr Int32 nbEdge() const { return {{ item.nb_edge }}; }
constexpr Int32 nbFace() const { return {{ item.nb_face }}; }

private:

void _init();
};
{{ end }}

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// WARNING: This file is generated by a tool. DO NOT EDIT.
/*
* Generation of classes managing geometric elements (GeomElement).
*/

{{ for item in items_2d_3d }}{{ if !for.first }}
{{ end }}/*!
* \ingroup ArcaneGeometric
* \brief Geometric elements of type GeomType::{{ item.name }}.
*/
class ARCANE_GEOMETRY_EXPORT {{ item.name }}Element
: public GeomElementBase< {{ item.nb_node }} >
{
public:

using ConstViewType = {{ item.name }}ElementConstView;
using ViewType = {{ item.name }}ElementView;

public:

using GeomElementBase< {{ item.nb_node }} >::init;

{{ item.name }}Element() = default;
{{ item.name }}Element(const VariableNodeReal3& coords,ItemWithNodes item) : GeomElementBase(coords,item){}
constexpr {{ item.name }}Element(ConstArrayView<Real3> coords) : GeomElementBase(coords){}
{{ item.name }}Element({{ item.coords_args }})
{
{{ for i in 0..(item.nb_node - 1) }} m_s[{{ i }}] = a{{ i }};
{{ end }} }

//! Initializes the instance with the coordinates passed as arguments
constexpr void init({{ item.coords_args }})
{
{{ for i in 0..(item.nb_node - 1) }} m_s[{{ i }}] = a{{ i }};
{{ end }} }
//! Conversion operator to a constant view
constexpr operator ConstViewType() const { return ConstViewType(m_s); }
//! Conversion operator to a mutable view
constexpr operator ViewType() { return ViewType(m_s); }
//! Constant view of the element
constexpr ConstViewType constView() const { return ConstViewType(m_s); }
//! Mutable view of the element
constexpr ViewType view() { return ViewType(m_s); }
};

//! Geometric element of type GeomType::{{ item.name }}
using {{ item.basic_name }}Element = {{ item.name }}Element;

{{ end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// WARNING: This file is generated by a tool. DO NOT EDIT.
/*
* Génération des classes des vues sur les éléments géométriques (GeomElement).
*/

{{ for item in items_2d_3d }}{{ if !for.first }}

{{ end }}/*!
* \ingroup ArcaneGeometric
* \brief Constant view on geometric elements of type GeomType::{{ item.name }}.
*
* It is possible to retrieve a view of this type via:
* - directly from an instance of Triangle3ShapeView.
* - directly from an instance of Triangle3Element
* - an instance of Triangle3ElementView via Triangle3ElementView::constView()
* - an instance of GeomShapeView via GeomShapeView::toTriangle3Element()
*
* For more information on usage, refer to \ref arcanedoc_cea_geometric_viewusage.
*/
class ARCANE_GEOMETRY_EXPORT {{ item.name }}ElementConstView
: public GeomElementConstViewBase
{
public:

constexpr {{ item.name }}ElementConstView(ARCANE_RESTRICT const Real3POD* ptr)
: GeomElementConstViewBase(ptr){}
};

/*!
* \ingroup ArcaneGeometric
* \brief Modifiable view on geometric elements of type GeomType::{{ item.name }}.
*
* It is possible to retrieve a view of this type via:
* - directly from an instance of Triangle3Element
* - an instance of Triangle3Element via Triangle3ElementView::view()
*
* For more information on usage, refer to \ref arcanedoc_cea_geometric_viewusage.
*/
class ARCANE_GEOMETRY_EXPORT {{ item.name }}ElementView
: public GeomElementViewBase
{
public:

using ConstViewType = {{ item.name }}ElementConstView;

public:

//! Construct a view from the coordinates passed as arguments
constexpr {{ item.name }}ElementView(ARCANE_RESTRICT Real3POD* ptr)
: GeomElementViewBase(ptr){}
//! Initializes the view with the coordinates passed as arguments
constexpr void init({{ item.coords_args }})
{
{{ for i in 0..(item.nb_node - 1) }} m_s[{{ i }}] = a{{ i }};
{{ end }} }
//! Conversion operator to a constant view
constexpr operator {{ item.name }}ElementConstView() const { return ConstViewType(m_s); }
//! Constant view on the element
constexpr {{ item.name }}ElementConstView constView() const { return ConstViewType(m_s); }
};

//! View on an element of type GeomType::{{ item.name }}
using {{ item.basic_name }}ElementView = {{ item.name }}ElementView ;
//! Constant view on an element of type GeomType::{{ item.name }}
using {{ item.basic_name }}ElementConstView = {{ item.name }}ElementConstView ;
{{ end }}
Loading
Loading