diff --git a/arcane/src/arcane/core/CaseFunction2.h b/arcane/src/arcane/core/CaseFunction2.h
new file mode 100644
index 000000000..2213ac62b
--- /dev/null
+++ b/arcane/src/arcane/core/CaseFunction2.h
@@ -0,0 +1,116 @@
+// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
+//-----------------------------------------------------------------------------
+// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
+// See the top-level COPYRIGHT file for details.
+// SPDX-License-Identifier: Apache-2.0
+//-----------------------------------------------------------------------------
+/*---------------------------------------------------------------------------*/
+/* CaseFunction2.h (C) 2000-2023 */
+/* */
+/* Fonction du jeu de données avec type de valeur explicite. */
+/*---------------------------------------------------------------------------*/
+#ifndef ARCANE_CORE_CASEFUNCTION2_H
+#define ARCANE_CORE_CASEFUNCTION2_H
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+#include "arcane/utils/Real3.h"
+#include "arcane/core/CaseFunction.h"
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+namespace Arcane
+{
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/*!
+ * \internal
+ * \brief Implémentation de CaseFunction permettant de retourner directement
+ * la valeur associée à un paramètre sans passer par une référence.
+ *
+ * Cela est principalement utilisé pour simplifier les extensions C# en évitant
+ * les différentes surcharges de value().
+ *
+ * Pour utiliser cette classe, il faut implémenter les méthodes 'valueAs*'
+ * pour les deux types d'argument \a Integer et \a Real et pour les
+ * différents types de retour possibles.
+ */
+class ARCANE_CORE_EXPORT CaseFunction2
+: public CaseFunction
+{
+ public:
+
+ //! Construit une fonction du jeu de données.
+ explicit CaseFunction2(const CaseFunctionBuildInfo& cfbi)
+ : CaseFunction(cfbi)
+ {}
+
+ protected:
+
+ void value(Real param, Real& v) const override
+ {
+ v = valueAsReal(param);
+ }
+ void value(Real param, Integer& v) const override
+ {
+ v = valueAsInteger(param);
+ }
+ void value(Real param, bool& v) const override
+ {
+ v = valueAsBool(param);
+ }
+ void value(Real param, String& v) const override
+ {
+ v = valueAsString(param);
+ }
+ void value(Real param, Real3& v) const override
+ {
+ v = valueAsReal3(param);
+ }
+ void value(Integer param, Real& v) const override
+ {
+ v = valueAsReal(param);
+ }
+ void value(Integer param, Integer& v) const override
+ {
+ v = valueAsInteger(param);
+ }
+ void value(Integer param, bool& v) const override
+ {
+ v = valueAsBool(param);
+ }
+ void value(Integer param, String& v) const override
+ {
+ v = valueAsString(param);
+ }
+ void value(Integer param, Real3& v) const override
+ {
+ v = valueAsReal3(param);
+ }
+
+ public:
+
+ virtual Real valueAsReal(Real param) const = 0;
+ virtual Integer valueAsInteger(Real param) const = 0;
+ virtual bool valueAsBool(Real param) const = 0;
+ virtual String valueAsString(Real param) const = 0;
+ virtual Real3 valueAsReal3(Real param) const = 0;
+
+ virtual Real valueAsReal(Integer param) const = 0;
+ virtual Integer valueAsInteger(Integer param) const = 0;
+ virtual bool valueAsBool(Integer param) const = 0;
+ virtual String valueAsString(Integer param) const = 0;
+ virtual Real3 valueAsReal3(Integer param) const = 0;
+};
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+} // namespace Arcane
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+#endif
diff --git a/arcane/src/arcane/core/InterfaceImpl.cc b/arcane/src/arcane/core/InterfaceImpl.cc
index a30e86985..f915f9de2 100644
--- a/arcane/src/arcane/core/InterfaceImpl.cc
+++ b/arcane/src/arcane/core/InterfaceImpl.cc
@@ -93,6 +93,7 @@
#include "arcane/core/IPhysicalUnitConverter.h"
#include "arcane/core/IPhysicalUnit.h"
#include "arcane/core/IStandardFunction.h"
+#include "arcane/core/CaseFunction2.h"
#include "arcane/core/IServiceAndModuleFactoryMng.h"
#include "arcane/core/IGhostLayerMng.h"
#include "arcane/core/IMeshUniqueIdMng.h"
diff --git a/arcane/src/arcane/core/srcs.cmake b/arcane/src/arcane/core/srcs.cmake
index b149cdb43..7c2240c29 100644
--- a/arcane/src/arcane/core/srcs.cmake
+++ b/arcane/src/arcane/core/srcs.cmake
@@ -393,6 +393,7 @@ set(ARCANE_ORIGINAL_SOURCES
CaseDatasetSource.h
CaseFunction.cc
CaseFunction.h
+ CaseFunction2.h
CaseOptions.h
CaseOptionServiceImpl.h
CaseOptionTypes.h
diff --git a/arcane/src/arcane/tests/CMakeLists.txt b/arcane/src/arcane/tests/CMakeLists.txt
index d9b1a21ba..5c386f54d 100644
--- a/arcane/src/arcane/tests/CMakeLists.txt
+++ b/arcane/src/arcane/tests/CMakeLists.txt
@@ -695,6 +695,7 @@ if (ARCANE_HAS_DOTNET_TESTS)
if (ARCANE_HAS_TASKS)
arcane_add_csharp_test_sequential(hydro_cs_task testSimpleHydroCS-1.arc -m 15 -K 4)
endif()
+ arcane_add_csharp_test_sequential(casefunction_cs testCaseFunctionModule-1.arc)
endif()
arcane_add_test_parallel(loadbalance_test1 testLoadBalanceHydro-MeshPartitionerTester.arc 4 -m 30)
diff --git a/arcane/src/arcane/tests/CaseFunctionTester.axl b/arcane/src/arcane/tests/CaseFunctionTester.axl
new file mode 100644
index 000000000..fc9d471fb
--- /dev/null
+++ b/arcane/src/arcane/tests/CaseFunctionTester.axl
@@ -0,0 +1,19 @@
+
+
+
+
+ Module de test des 'ICaseFunction'.
+
+
+
+
+ Fonction f(x) -> x * 2.0
+
+
+ Fonction f(x) -> x * 3.0
+
+
+ Fonction f(x,position) -> x * normL2(position)
+
+
+
diff --git a/arcane/src/arcane/tests/CaseFunctionTesterModule.cc b/arcane/src/arcane/tests/CaseFunctionTesterModule.cc
new file mode 100644
index 000000000..6d89e7eeb
--- /dev/null
+++ b/arcane/src/arcane/tests/CaseFunctionTesterModule.cc
@@ -0,0 +1,196 @@
+// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
+//-----------------------------------------------------------------------------
+// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
+// See the top-level COPYRIGHT file for details.
+// SPDX-License-Identifier: Apache-2.0
+//-----------------------------------------------------------------------------
+/*---------------------------------------------------------------------------*/
+/* CaseFunctionTesterModule.cc (C) 2000-2023 */
+/* */
+/* Module de test des 'CaseFunction'. */
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+#include "arcane/core/StandardCaseFunction.h"
+#include "arcane/core/ITimeLoopMng.h"
+#include "arcane/core/TimeLoopEntryPointInfo.h"
+#include "arcane/core/TimeLoop.h"
+#include "arcane/core/IMesh.h"
+
+#include "arcane/tests/CaseFunctionTester_axl.h"
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+namespace ArcaneTest
+{
+using namespace Arcane;
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+/*!
+ * \brief Module de test des 'ICaseFunction'.
+ */
+class CaseFunctionTesterModule
+: public ArcaneCaseFunctionTesterObject
+{
+ public:
+
+ explicit CaseFunctionTesterModule(const ModuleBuildInfo& mbi);
+
+ public:
+
+ static void staticInitialize(ISubDomain* sd);
+
+ public:
+
+ VersionInfo versionInfo() const override { return Arcane::VersionInfo(0, 1, 0); }
+
+ public:
+
+ void init();
+ void loop();
+
+ private:
+};
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+ARCANE_DEFINE_STANDARD_MODULE(CaseFunctionTesterModule, CaseFunctionTester);
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+namespace
+{
+ class StandardFuncTest
+ : public StandardCaseFunction
+ , public IBinaryMathFunctor
+ {
+ public:
+
+ StandardFuncTest(const CaseFunctionBuildInfo& bi)
+ : StandardCaseFunction(bi)
+ {}
+
+ public:
+
+ virtual IBinaryMathFunctor* getFunctorRealReal3ToReal()
+ {
+ return this;
+ }
+ virtual Real apply(Real r, Real3 r3)
+ {
+ return r + r3.normL2();
+ }
+ };
+
+} // namespace
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+CaseFunctionTesterModule::
+CaseFunctionTesterModule(const ModuleBuildInfo& mbi)
+: ArcaneCaseFunctionTesterObject(mbi)
+{
+ addEntryPoint(this, "Init",
+ &CaseFunctionTesterModule::init, IEntryPoint::WInit);
+ addEntryPoint(this, "Loop",
+ &CaseFunctionTesterModule::loop);
+}
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+void CaseFunctionTesterModule::
+staticInitialize(ISubDomain* sd)
+{
+ ITimeLoopMng* tlm = sd->timeLoopMng();
+ ITimeLoop* time_loop = tlm->createTimeLoop("CaseFunctionTester");
+
+ {
+ List clist;
+ clist.add(TimeLoopEntryPointInfo("CaseFunctionTester.Init"));
+ time_loop->setEntryPoints(ITimeLoop::WInit, clist);
+ }
+
+ {
+ List clist;
+ clist.add(TimeLoopEntryPointInfo("CaseFunctionTester.Loop"));
+ time_loop->setEntryPoints(ITimeLoop::WComputeLoop, clist);
+ }
+
+ {
+ StringList clist;
+ clist.add("CaseFunctionTester");
+ time_loop->setRequiredModulesName(clist);
+ }
+
+ tlm->registerTimeLoop(time_loop);
+}
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+void CaseFunctionTesterModule::
+loop()
+{
+ if (m_global_iteration() > 10)
+ subDomain()->timeLoopMng()->stopComputeLoop(true);
+
+ // Temps de début d'itération auquel sont calculées les valeurs des fonctions
+ Real global_time = m_global_old_time();
+ Int32 global_iter = m_global_iteration();
+
+ {
+ Real v1 = options()->realTimeMultiply2.value();
+ Real expected_v1 = global_time * 2.0;
+ info() << "Function: real-time-multiply-2: " << v1;
+ if (!math::isNearlyEqual(v1, expected_v1))
+ ARCANE_FATAL("Bad (1) value v={0} expected={1}", v1, expected_v1);
+ }
+ {
+ int v1 = options()->intIterMultiply3.value();
+ int expected_v1 = global_iter * 3;
+ info() << "Function: int-iter-multiply-3: " << v1;
+ if (v1 != expected_v1)
+ ARCANE_FATAL("Bad (2) value v={0} expected={1}", v1, expected_v1);
+ }
+ {
+ ICaseFunction* opt_function = options()->realNormL2.function();
+ IStandardFunction* scf = options()->realNormL2.standardFunction();
+ if (!scf)
+ ARCANE_FATAL("No standard case function for option 'real-norml2'");
+ auto* functor = scf->getFunctorRealReal3ToReal();
+ if (!functor)
+ ARCANE_FATAL("Standard function '{0}' is not convertible to f(Real,Real3) -> Real", opt_function->name());
+
+ VariableNodeReal3& node_coord = defaultMesh()->nodesCoordinates();
+ ENUMERATE_ (Node, inode, allNodes()) {
+ Real3 coord = node_coord[inode];
+ Real v1 = functor->apply(global_time, coord);
+ Real expected_v1 = global_time * coord.normL2();
+ info() << "Function: real-norml2: " << v1;
+ if (!math::isNearlyEqual(v1, expected_v1))
+ ARCANE_FATAL("Bad (3) value v={0} expected={1}", v1, expected_v1);
+ }
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+void CaseFunctionTesterModule::
+init()
+{
+ m_global_deltat.assign(1.5);
+}
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+} // End namespace ArcaneTest
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
diff --git a/arcane/src/arcane/tests/DotNetCaseFunctionProvider.cs b/arcane/src/arcane/tests/DotNetCaseFunctionProvider.cs
index 2d9902e0f..e71d9404b 100644
--- a/arcane/src/arcane/tests/DotNetCaseFunctionProvider.cs
+++ b/arcane/src/arcane/tests/DotNetCaseFunctionProvider.cs
@@ -12,15 +12,38 @@
using IntegerArrayView = Arcane.Int32ArrayView;
#endif
-[Arcane.Service("DotNetCaseFunctionProvider",typeof(Arcane.ICaseFunctionProvider))]
-public class DotNetCaseFunctionProvider : Arcane.ICaseFunctionProvider_WrapperService
+namespace ArcaneTest
{
- public DotNetCaseFunctionProvider(ServiceBuildInfo bi) : base(bi)
+ [Arcane.Service("DotNetCaseFunctionProvider",typeof(Arcane.ICaseFunctionProvider))]
+ public class DotNetCaseFunctionProvider : Arcane.ICaseFunctionProvider_WrapperService
{
+ public DotNetCaseFunctionProvider(ServiceBuildInfo bi) : base(bi)
+ {
+ }
+
+ public override void RegisterCaseFunctions(ICaseMng cm)
+ {
+ Console.WriteLine("REGISTER C# CASE_FUNCTION_PROVIDER");
+ Arcane.CaseFunctionLoader.LoadCaseFunction(cm,typeof(MyTestCaseFunction));
+ }
}
- public override void RegisterCaseFunctions(ICaseMng cm)
+ public class MyTestCaseFunction
{
- Console.WriteLine("REGISTER C# CASE_FUNCTION_PROVIDER");
+ public Real FuncTimeMultiply2(Real x)
+ {
+ Console.WriteLine("FuncTimeMultiply2 x={0}",x);
+ return x * 2.0;
+ }
+ public int FuncIterMultiply3(int x)
+ {
+ Console.WriteLine("FuncIterMultiply3 x={0}",x);
+ return x * 3;
+ }
+ public Real FuncStandardRealReal3NormL2(Real x,Real3 position)
+ {
+ Console.WriteLine("FuncStandardNormL2 x={0} position={1}",x,position);
+ return x * System.Math.Sqrt(position.x*position.x + position.y*position.y + position.z*position.z);
+ }
}
}
diff --git a/arcane/src/arcane/tests/srcs.cmake b/arcane/src/arcane/tests/srcs.cmake
index 1c7d0463b..8ed72cb96 100644
--- a/arcane/src/arcane/tests/srcs.cmake
+++ b/arcane/src/arcane/tests/srcs.cmake
@@ -6,6 +6,7 @@ set(ARCANE_SOURCES
ParticleUnitTest.cc
TestUnitTest.cc
CaseFunctionUnitTest.cc
+ CaseFunctionTesterModule.cc
CaseOptionsTesterModule.cc
ParallelTesterModule.cc
SubMeshTestModule.cc
@@ -83,6 +84,7 @@ set(AXL_FILES
CheckpointTester
SimpleHydro
ScriptTester
+ CaseFunctionTester
CaseOptionsTester
ParallelTester
SubMeshTest
diff --git a/arcane/tests/testCaseFunctionModule-1.arc b/arcane/tests/testCaseFunctionModule-1.arc
new file mode 100644
index 000000000..910cda31e
--- /dev/null
+++ b/arcane/tests/testCaseFunctionModule-1.arc
@@ -0,0 +1,19 @@
+
+
+
+ Test Arcane 1
+ Test Arcane 1
+ CaseFunctionTester
+
+
+
+ 422
+
+
+
+ 1.5
+ 1
+ 1
+
+
+
diff --git a/arcane/tools/wrapper/core/ArcaneSwigCore.i b/arcane/tools/wrapper/core/ArcaneSwigCore.i
index e8326adb3..2804eb020 100644
--- a/arcane/tools/wrapper/core/ArcaneSwigCore.i
+++ b/arcane/tools/wrapper/core/ArcaneSwigCore.i
@@ -35,7 +35,7 @@ using namespace Arcane::Accelerator;
#define SWIG_DISPOSE csdispose
#define SWIG_DISPOSE_DERIVED csdispose_derived
-namespace Arcane
+namespace Arccore
{
class IFunctor;
namespace Internal
@@ -43,6 +43,14 @@ namespace Arcane
class ExternalRef;
}
}
+namespace Arcane
+{
+ using Arccore::IFunctor;
+ namespace Internal
+ {
+ using Arccore::Internal::ExternalRef;
+ }
+}
#define ARCCORE_DECLARE_REFERENCE_COUNTED_CLASS(a)
diff --git a/arcane/tools/wrapper/core/ArcaneSwigCoreInclude.h b/arcane/tools/wrapper/core/ArcaneSwigCoreInclude.h
index 9b992854c..fedce17a0 100644
--- a/arcane/tools/wrapper/core/ArcaneSwigCoreInclude.h
+++ b/arcane/tools/wrapper/core/ArcaneSwigCoreInclude.h
@@ -1,11 +1,11 @@
// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
//-----------------------------------------------------------------------------
-// Copyright 2000-2022 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
+// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: Apache-2.0
//-----------------------------------------------------------------------------
/*---------------------------------------------------------------------------*/
-/* ArcaneSwigCoreInclude.h (C) 2000-2022 */
+/* ArcaneSwigCoreInclude.h (C) 2000-2023 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
@@ -61,6 +61,7 @@
#include "arcane/CaseOptionsMulti.h"
#include "arcane/CaseOptionService.h"
#include "arcane/StandardCaseFunction.h"
+#include "arcane/CaseFunction2.h"
#include "arcane/ICaseOptions.h"
#include "arcane/ICaseMng.h"
#include "arcane/ICaseFunctionProvider.h"
diff --git a/arcane/tools/wrapper/core/ArrayView.i b/arcane/tools/wrapper/core/ArrayView.i
index cc1fa0028..40b5135e7 100644
--- a/arcane/tools/wrapper/core/ArrayView.i
+++ b/arcane/tools/wrapper/core/ArrayView.i
@@ -11,6 +11,11 @@
/*---------------------------------------------------------------------------*/
// On ne peut pas inclure 'arcane/utils/UtilsTypes.h' car SWIG (3.0.12) ne
// semble pas bien gérer 'using' des classes de Arccore.
+namespace Arccore
+{
+ template class IFunctorWithArgumentT;
+}
+
namespace Arcane
{
template class ArrayView;
@@ -35,8 +40,6 @@ namespace Arcane
template class Collection;
template class List;
- template class IFunctorWithArgumentT;
-
template class EventObservable;
template class EventObserver;
diff --git a/arcane/tools/wrapper/core/CMakeLists.txt b/arcane/tools/wrapper/core/CMakeLists.txt
index f09ac77f3..d3d664dd9 100644
--- a/arcane/tools/wrapper/core/CMakeLists.txt
+++ b/arcane/tools/wrapper/core/CMakeLists.txt
@@ -31,6 +31,7 @@ set(ARCANE_SWIG_CORE_CSHARP_FILES
ArcaneSimpleExecutor
AssemblyLoaderHelper
CaseOptionMultiEnumT
+ CaseFunction
Debug
ExternalRef
EntryPoint
diff --git a/arcane/tools/wrapper/core/CaseOption.i b/arcane/tools/wrapper/core/CaseOption.i
index 3cdcd0879..6d27554e2 100644
--- a/arcane/tools/wrapper/core/CaseOption.i
+++ b/arcane/tools/wrapper/core/CaseOption.i
@@ -23,6 +23,7 @@ namespace Arcane
%feature("director") Arcane::ICaseOptionServiceContainer;
%feature("director") Arcane::StandardCaseFunction;
%feature("director") Arcane::CaseFunction;
+%feature("director") Arcane::CaseFunction2;
%feature("director") Arcane::CaseOptionComplexValue;
%ignore Arcane::ICaseFunction::value;
@@ -62,6 +63,7 @@ namespace Arcane
%include arcane/core/ICaseFunction.h
%include arcane/core/CaseFunction.h
%include arcane/core/StandardCaseFunction.h
+%include arcane/core/CaseFunction2.h
%include arcane/core/ICaseFunctionProvider.h
/*---------------------------------------------------------------------------*/
diff --git a/arcane/tools/wrapper/core/DotNetObject.i b/arcane/tools/wrapper/core/DotNetObject.i
index 1867c78fb..da6089eed 100644
--- a/arcane/tools/wrapper/core/DotNetObject.i
+++ b/arcane/tools/wrapper/core/DotNetObject.i
@@ -1,5 +1,5 @@
// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
-%typemap(cscode) Arcane::Internal::ExternalRef
+%typemap(cscode) Arccore::Internal::ExternalRef
%{
internal delegate void DestroyDelegate(IntPtr handle);
@@ -20,9 +20,9 @@
}
%}
-%typemap(csclassmodifiers) Arcane::Internal::ExternalRef "public partial class"
+%typemap(csclassmodifiers) Arccore::Internal::ExternalRef "public partial class"
// La classe 'ExternaRef' est dans 'arccore/base'
-namespace Arcane::Internal
+namespace Arccore::Internal
{
class ExternalRef
{
diff --git a/arcane/tools/wrapper/core/ItemPairGroup.i b/arcane/tools/wrapper/core/ItemPairGroup.i
index 4ee60e43d..55b54ff2c 100644
--- a/arcane/tools/wrapper/core/ItemPairGroup.i
+++ b/arcane/tools/wrapper/core/ItemPairGroup.i
@@ -79,4 +79,4 @@ namespace Arcane
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
-%template(ItemPairGroupCustomFunctor) Arcane::IFunctorWithArgumentT;
+%template(ItemPairGroupCustomFunctor) Arccore::IFunctorWithArgumentT;
diff --git a/arcane/tools/wrapper/core/Service.i b/arcane/tools/wrapper/core/Service.i
index 06edbf1af..3ec1218c6 100644
--- a/arcane/tools/wrapper/core/Service.i
+++ b/arcane/tools/wrapper/core/Service.i
@@ -16,7 +16,7 @@
%rename BasicModule BasicModule_INTERNAL;
-%typemap(cscode) Arcane::IFunctor %{
+%typemap(cscode) Arccore::IFunctor %{
public delegate void FunctorDelegate();
private FunctorDelegate m_functor;
public FunctorDelegate Functor { get { return m_functor; } }
@@ -138,7 +138,7 @@
%include arcane/core/BasicModule.h
%include arcane/core/IEntryPoint.h
-namespace Arcane
+namespace Arccore
{
class IFunctor
{
diff --git a/arcane/tools/wrapper/core/csharp/CaseFunction.cs b/arcane/tools/wrapper/core/csharp/CaseFunction.cs
new file mode 100644
index 000000000..9516455ba
--- /dev/null
+++ b/arcane/tools/wrapper/core/csharp/CaseFunction.cs
@@ -0,0 +1,450 @@
+//-----------------------------------------------------------------------------
+// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
+// See the top-level COPYRIGHT file for details.
+// SPDX-License-Identifier: Apache-2.0
+//-----------------------------------------------------------------------------
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+
+#if ARCANE_64BIT
+using Integer = System.Int64;
+#else
+using Integer = System.Int32;
+#endif
+using Real = System.Double;
+
+namespace Arcane
+{
+ public class CaseFunctionLoader
+ {
+ static List m_case_functions;
+
+ /*!
+ * \brief Charge les 'CaseFunction' issues de la classe \a class_type.
+ *
+ * Toutes les méthodes publiques de \a class_type dont le prototype correspond
+ * à une \a CaseFunction sont considérées comme des fonctions du jeu de données.
+ *
+ * Par exemple:
+ * \code
+ * double func1(int);
+ * int func2(double);
+ * \endcode
+ *
+ * Les méthodes trouvées sont ajoutées à \a case_mng
+ */
+ public static void LoadCaseFunction(ICaseMng case_mng,Type class_type)
+ {
+ if (class_type==null)
+ return;
+
+ ConstructorInfo ci = class_type.GetConstructor(new Type[0]);
+ object o = ci.Invoke(null);
+
+ TraceAccessor Trace = new TraceAccessor(case_mng.TraceMng());
+
+ // TODO: utile actuellement pour conserver une référence mais il faudrait ensuite
+ // supprimer
+ if (m_case_functions==null)
+ m_case_functions = new List();
+
+ List current_functions = new List();
+
+ //ICaseMng cm = sd.CaseMng();
+ BindingFlags flags = BindingFlags.Public|BindingFlags.InvokeMethod|BindingFlags.Instance|BindingFlags.DeclaredOnly;
+ MethodInfo[] methods = class_type.GetMethods(flags);
+
+ foreach(MethodInfo method in methods){
+ string func_name = method.Name;
+ Trace.Info(String.Format("FOUND METHOD name={0}",func_name));
+ var cfbi = new CaseFunctionBuildInfo(case_mng.TraceMng(),func_name);
+ ICaseFunction ucf = UserCaseFunction.Create(Trace,o,method,cfbi);
+ if (ucf==null)
+ ucf = UserStandardCaseFunction.Create(Trace,o,method,cfbi);
+ if (ucf!=null)
+ current_functions.Add(ucf);
+ else{
+ string msg = $"User function '{func_name}' is invalid."+
+ " Valid prototypes are f(Real,Real|Real3) -> Real|Real3 or f(Real|Integer) -> Real|Integer|bool";
+ throw new ApplicationException(msg);
+ }
+ }
+ foreach(ICaseFunction cf in current_functions){
+ case_mng.AddFunction(cf);
+ m_case_functions.Add(cf);
+ }
+ }
+ }
+
+ //! Function f(Real,Real) -> Real
+ class RealRealToRealFunctor : IRealRealToRealMathFunctor
+ {
+ delegate Real MyDelegate(Real a,Real b);
+ MyDelegate m_delegate;
+
+ public RealRealToRealFunctor(object o,MethodInfo method)
+ {
+ m_delegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate),o,method);
+ }
+ public override Real Apply(Real a,Real b)
+ {
+ return m_delegate(a,b);
+ }
+ public override void Apply(RealConstArrayView a,RealConstArrayView b,RealArrayView out_v)
+ {
+ for (int i=0; i Real
+ class RealReal3ToRealFunctor : IRealReal3ToRealMathFunctor
+ {
+ delegate Real MyDelegate(Real a,Real3 b);
+ MyDelegate m_delegate;
+
+ public RealReal3ToRealFunctor(object o,MethodInfo method)
+ {
+ m_delegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate),o,method);
+ }
+ public override Real Apply(Real a,Real3 b)
+ {
+ return m_delegate(a,b);
+ }
+ public override void Apply(RealConstArrayView a,Real3ConstArrayView b,RealArrayView out_v)
+ {
+ for (int i=0; i Real3
+ class RealRealToReal3Functor : IRealRealToReal3MathFunctor
+ {
+ delegate Real3 MyDelegate(Real a,Real b);
+ MyDelegate m_delegate;
+
+ public RealRealToReal3Functor(object o,MethodInfo method)
+ {
+ m_delegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate),o,method);
+ }
+ public override Real3 Apply(Real a,Real b)
+ {
+ return m_delegate(a,b);
+ }
+ public override void Apply(RealConstArrayView a,RealConstArrayView b,Real3ArrayView out_v)
+ {
+ for (int i=0; i Real3
+ class RealReal3ToReal3Functor : IRealReal3ToReal3MathFunctor
+ {
+ delegate Real3 MyDelegate(Real a,Real3 b);
+ MyDelegate m_delegate;
+
+ public RealReal3ToReal3Functor(object o,MethodInfo method)
+ {
+ m_delegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate),o,method);
+ }
+ public override Real3 Apply(Real a,Real3 b)
+ {
+ return m_delegate(a,b);
+ }
+ public override void Apply(RealConstArrayView a,Real3ConstArrayView b,Real3ArrayView out_v)
+ {
+ for (int i=0; i {3}",method_name,param1_type,param2_type,return_type));
+
+ // Créé l'instance correspondante au type de la fonction retournée.
+ if (return_type==real_type && param1_type==real_type && param2_type==real_type){
+ trace.Info("Found f(Real,Real) -> Real");
+ var v = new RealRealToRealFunctor(o,method);
+ return new UserStandardCaseFunction(v,cfbi);
+ }
+
+ if (return_type==real_type && param1_type==real_type && param2_type==real3_type){
+ trace.Info("Found f(Real,Real3) -> Real");
+ var v = new RealReal3ToRealFunctor(o,method);
+ return new UserStandardCaseFunction(v,cfbi);
+ }
+
+ if (return_type==real3_type && param1_type==real_type && param2_type==real_type){
+ trace.Info("Found f(Real,Real) -> Real3");
+ var v = new RealRealToReal3Functor(o,method);
+ return new UserStandardCaseFunction(v,cfbi);
+ }
+
+ if (return_type==real3_type && param1_type==real_type && param2_type==real3_type){
+ trace.Info("Found f(Real,Real3) -> Real3");
+ var v = new RealReal3ToReal3Functor(o,method);
+ return new UserStandardCaseFunction(v,cfbi);
+ }
+ return null;
+ }
+
+ public override IRealRealToRealMathFunctor GetFunctorRealRealToReal()
+ {
+ return m_rr_to_r;
+ }
+
+ public override IRealRealToReal3MathFunctor GetFunctorRealRealToReal3()
+ {
+ return m_rr_to_r3;
+ }
+
+ public override IRealReal3ToRealMathFunctor GetFunctorRealReal3ToReal()
+ {
+ return m_rr3_to_r;
+ }
+
+ public override IRealReal3ToReal3MathFunctor GetFunctorRealReal3ToReal3()
+ {
+ return m_rr3_to_r3;
+ }
+ }
+
+ /*!
+ * \brief Représente une fonction du type table de marche
+ *
+ * Pour l'instant on a uniquement le support des fonctions
+ * avec le prototype suivant: f(Real|Integer) -> Real|Integer|Bool.
+ */
+ class UserCaseFunction : Arcane.CaseFunction2
+ {
+ delegate double RealToRealDelegate(double v);
+ delegate double IntegerToRealDelegate(int v);
+ delegate int RealToIntegerDelegate(double v);
+ delegate int IntegerToIntegerDelegate(int v);
+ delegate bool RealToBoolDelegate(double v);
+ delegate bool IntegerToBoolDelegate(int v);
+
+ RealToRealDelegate m_real_to_real_delegate;
+ IntegerToRealDelegate m_integer_to_real_delegate;
+
+ RealToIntegerDelegate m_real_to_integer_delegate;
+ IntegerToIntegerDelegate m_integer_to_integer_delegate;
+
+ RealToBoolDelegate m_real_to_bool_delegate;
+ IntegerToBoolDelegate m_integer_to_bool_delegate;
+
+ public UserCaseFunction(Arcane.CaseFunctionBuildInfo cfbi) : base(cfbi)
+ {
+ }
+
+ public override double ValueAsReal(double v)
+ {
+ if (m_real_to_real_delegate!=null)
+ return m_real_to_real_delegate(v);
+ if (m_real_to_integer_delegate!=null)
+ return (double)m_real_to_integer_delegate(v);
+ if (m_integer_to_integer_delegate!=null)
+ return (double)m_integer_to_integer_delegate((int)v);
+ if (m_integer_to_real_delegate!=null)
+ return m_integer_to_integer_delegate((int)v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(Real) -> Real");
+ }
+
+ public override int ValueAsInteger(double v)
+ {
+ if (m_real_to_integer_delegate!=null)
+ return m_real_to_integer_delegate(v);
+ if (m_integer_to_integer_delegate!=null)
+ return m_integer_to_integer_delegate((int)v);
+ if (m_real_to_real_delegate!=null)
+ return (int)m_real_to_real_delegate(v);
+ if (m_integer_to_real_delegate!=null)
+ return (int)m_integer_to_integer_delegate((int)v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(Real) -> int");
+ }
+
+ public override bool ValueAsBool(double v)
+ {
+ if (m_real_to_bool_delegate!=null)
+ return m_real_to_bool_delegate(v);
+ if (m_integer_to_bool_delegate!=null)
+ return m_integer_to_bool_delegate((int)v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(Real) -> bool");
+ }
+
+ public override double ValueAsReal(int v)
+ {
+ if (m_integer_to_real_delegate!=null)
+ return m_integer_to_integer_delegate(v);
+ if (m_real_to_real_delegate!=null)
+ return m_real_to_real_delegate((double)v);
+ if (m_integer_to_integer_delegate!=null)
+ return (double)m_integer_to_integer_delegate(v);
+ if (m_real_to_integer_delegate!=null)
+ return (double)m_real_to_integer_delegate(v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(int) -> Real");
+ }
+
+ public override int ValueAsInteger(int v)
+ {
+ if (m_integer_to_integer_delegate!=null)
+ return m_integer_to_integer_delegate(v);
+ if (m_real_to_integer_delegate!=null)
+ return m_real_to_integer_delegate((double)v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(int) -> int");
+ }
+
+ public override bool ValueAsBool(int v)
+ {
+ if (m_integer_to_bool_delegate!=null)
+ return m_integer_to_bool_delegate(v);
+ if (m_real_to_bool_delegate!=null)
+ return m_real_to_bool_delegate((double)v);
+ throw new ApplicationException("Bad type for user function. Should be convertible to f(int) -> bool");
+ }
+
+ public override Real3 ValueAsReal3(int v)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string ValueAsString(int v)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override Real3 ValueAsReal3(Real v)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override string ValueAsString(Real v)
+ {
+ throw new NotSupportedException();
+ }
+
+ public static UserCaseFunction Create(TraceAccessor trace, object o,MethodInfo method,CaseFunctionBuildInfo cfbi)
+ {
+ string method_name = method.Name;
+ ParameterInfo[] method_params = method.GetParameters();
+ int nb_param = method_params.Length;
+
+ if (nb_param!=1)
+ return null;
+
+ Type real_type = typeof(double);
+ Type integer_type = typeof(int);
+ Type bool_type = typeof(bool);
+ Type return_type = method.ReturnType;
+ Type param1_type = method_params[0].ParameterType;
+
+ trace.Info(String.Format("METHOD_INFO={0} f({1}) -> {2}",method_name,param1_type,return_type));
+
+ // Créé l'instance correspondante au type de la fonction retournée
+
+ if (return_type==real_type && param1_type==real_type){
+ trace.Info("Found f(Real) -> Real");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamReal;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueReal;
+ var v = new UserCaseFunction(cfbi);
+ v.m_real_to_real_delegate = (RealToRealDelegate)Delegate.CreateDelegate(typeof(RealToRealDelegate),o,method);
+ return v;
+ }
+
+ if (return_type==real_type && param1_type==integer_type){
+ trace.Info("Found f(int) -> Real");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamInteger;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueReal;
+ var v = new UserCaseFunction(cfbi);
+ v.m_integer_to_real_delegate = (IntegerToRealDelegate)Delegate.CreateDelegate(typeof(IntegerToRealDelegate),o,method);
+ return v;
+ }
+
+ if (return_type==integer_type && param1_type==real_type){
+ trace.Info("Found f(Real) -> int");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamReal;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueInteger;
+ var v = new UserCaseFunction(cfbi);
+ v.m_real_to_integer_delegate = (RealToIntegerDelegate)Delegate.CreateDelegate(typeof(RealToIntegerDelegate),o,method);
+ return v;
+ }
+
+ if (return_type==integer_type && param1_type==integer_type){
+ trace.Info("Found f(int) -> int");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamInteger;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueInteger;
+ var v = new UserCaseFunction(cfbi);
+ v.m_integer_to_integer_delegate = (IntegerToIntegerDelegate)Delegate.CreateDelegate(typeof(IntegerToIntegerDelegate),o,method);
+ return v;
+ }
+
+ if (return_type==bool_type && param1_type==real_type){
+ trace.Info("Found f(Real) -> bool");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamReal;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueBool;
+ var v = new UserCaseFunction(cfbi);
+ v.m_real_to_bool_delegate = (RealToBoolDelegate)Delegate.CreateDelegate(typeof(RealToBoolDelegate),o,method);
+ return v;
+ }
+
+ if (return_type==bool_type && param1_type==integer_type){
+ trace.Info("Found f(int) -> bool");
+ cfbi.m_param_type = ICaseFunction.eParamType.ParamInteger;
+ cfbi.m_value_type = ICaseFunction.eValueType.ValueBool;
+ var v = new UserCaseFunction(cfbi);
+ v.m_integer_to_bool_delegate = (IntegerToBoolDelegate)Delegate.CreateDelegate(typeof(IntegerToBoolDelegate),o,method);
+ return v;
+ }
+
+ return null;
+
+ }
+ }
+}
+