From 28b492bd54b163bb2904dbaf21d92a78b02d499e Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Fri, 24 Feb 2023 11:20:39 +0100
Subject: [PATCH] ENH: unroll loops for complexVector functions

STYLE: prefer STL naming real(), imag() instead of Re(), Im()
---
 applications/test/complex/Test-complex.C      |  20 ++
 .../test/matrices/Matrix/Test-Matrix.C        |  12 +-
 .../fields/Fields/complex/complexField.C      | 173 +++++++++-----
 .../fields/Fields/complex/complexField.H      |  77 +++++--
 .../fields/Fields/complex/complexFields.H     |   4 +-
 .../Fields/complex/complexVectorField.C       | 212 +++++++++++++-----
 .../Fields/complex/complexVectorField.H       |  89 ++++++--
 .../matrices/EigenMatrix/EigenMatrix.C        |  16 +-
 .../primitives/Vector/complex/complexVector.C |   3 -
 .../primitives/Vector/complex/complexVector.H |   4 +-
 .../Vector/complex/complexVectorI.H           |  15 ++
 src/OpenFOAM/primitives/complex/complex.H     |  36 +--
 src/OpenFOAM/primitives/complex/complexI.H    |   6 +
 .../energySpectrum/energySpectrum.C           |   2 +-
 src/randomProcesses/fft/calcEk.C              |   2 +-
 src/randomProcesses/fft/fft.C                 |  18 +-
 src/randomProcesses/turbulence/turbGen.C      |   7 +-
 17 files changed, 495 insertions(+), 201 deletions(-)

diff --git a/applications/test/complex/Test-complex.C b/applications/test/complex/Test-complex.C
index 7e76b09324f..e8940e07a78 100644
--- a/applications/test/complex/Test-complex.C
+++ b/applications/test/complex/Test-complex.C
@@ -145,6 +145,8 @@ int main(int argc, char *argv[])
 
         complexField cmplx(4);
 
+        zip(cmplx, reals, zero{});
+        zip(cmplx, 1, imags);
         zip(cmplx, reals, imags);
         Info<< nl
             << "zip " << reals << nl
@@ -360,6 +362,24 @@ int main(int argc, char *argv[])
     // MinMax fails since there is no less comparison operator
     // Info<< "min/max = " << MinMax<complex>(fld1) << nl;
 
+
+    // Cross-product
+    {
+        const vector vec(1, 2, 3);
+        const vector realValue(4, 5, 6);
+        const vector imagValue(7, 8, 9);
+
+        complexVector cmplxVec(zip(realValue, imagValue));
+
+        Info<< "complexVector: " << cmplxVec << nl;
+        Info<< "cross: " << (vec ^ cmplxVec) << nl;
+
+        Info<< "cross real: " << (vec ^ realValue) << nl
+            << "cross imag: " << (vec ^ imagValue) << nl
+            << "cross     : "
+            << zip((vec ^ realValue), (vec ^ imagValue)) << nl;
+    }
+
     Info<< "\nEnd\n" << endl;
 
     return 0;
diff --git a/applications/test/matrices/Matrix/Test-Matrix.C b/applications/test/matrices/Matrix/Test-Matrix.C
index 73d23b5fced..4c87f078970 100644
--- a/applications/test/matrices/Matrix/Test-Matrix.C
+++ b/applications/test/matrices/Matrix/Test-Matrix.C
@@ -468,13 +468,13 @@ int main(int argc, char *argv[])
 
                 for (auto& val : A)
                 {
-                    val.Re() = rndGen.GaussNormal<scalar>();
-                    val.Im() = rndGen.GaussNormal<scalar>();
+                    val.real(rndGen.GaussNormal<scalar>());
+                    val.imag(rndGen.GaussNormal<scalar>());
                 }
                 for (auto& val : B)
                 {
-                    val.Re() = rndGen.GaussNormal<scalar>();
-                    val.Im() = rndGen.GaussNormal<scalar>();
+                    val.real(rndGen.GaussNormal<scalar>());
+                    val.imag(rndGen.GaussNormal<scalar>());
                 }
 
                 Info<< nl << "# (A.T()).T() = A:" << nl;
@@ -893,8 +893,8 @@ int main(int argc, char *argv[])
 
             for (auto& val : A)
             {
-                val.Re() = rndGen.GaussNormal<scalar>();
-                val.Im() = rndGen.GaussNormal<scalar>();
+                val.real(rndGen.GaussNormal<scalar>());
+                val.imag(rndGen.GaussNormal<scalar>());
             }
 
             Info<< "# SquareMatrix<complex>.symmetric():" << nl
diff --git a/src/OpenFOAM/fields/Fields/complex/complexField.C b/src/OpenFOAM/fields/Fields/complex/complexField.C
index f24fafbf658..e2c08e889d4 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexField.C
+++ b/src/OpenFOAM/fields/Fields/complex/complexField.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -46,27 +46,80 @@ namespace Foam
 void Foam::zip
 (
     complexField& result,
-    const UList<scalar>& re,
-    const UList<scalar>& im
+    const UList<scalar>& realValues,
+    const UList<scalar>& imagValues
 )
 {
     const label len = result.size();
 
     #ifdef FULLDEBUG
-    if (len != re.size() || len != im.size())
+    if (len != realValues.size() || len != imagValues.size())
     {
         FatalErrorInFunction
             << "Components sizes do not match: " << len << " ("
-            << re.size() << ' ' << im.size() << ')'
-            << nl
+            << realValues.size() << ' ' << imagValues.size() << ')' << nl
             << abort(FatalError);
     }
     #endif
 
     for (label i=0; i < len; ++i)
     {
-        result[i].Re() = re[i];
-        result[i].Im() = im[i];
+        result[i].real(realValues[i]);
+        result[i].imag(imagValues[i]);
+    }
+}
+
+
+void Foam::zip
+(
+    complexField& result,
+    const UList<scalar>& realValues,
+    const scalar imagValue
+)
+{
+    const label len = result.size();
+
+    #ifdef FULLDEBUG
+    if (len != realValues.size())
+    {
+        FatalErrorInFunction
+            << "Components sizes do not match: " << len
+            << " != " << realValues.size() << nl
+            << abort(FatalError);
+    }
+    #endif
+
+    for (label i=0; i < len; ++i)
+    {
+        result[i].real(realValues[i]);
+        result[i].imag(imagValue);
+    }
+}
+
+
+void Foam::zip
+(
+    complexField& result,
+    const scalar realValue,
+    const UList<scalar>& imagValues
+)
+{
+    const label len = result.size();
+
+    #ifdef FULLDEBUG
+    if (len != imagValues.size())
+    {
+        FatalErrorInFunction
+            << "Components sizes do not match: " << len
+            << " != " << imagValues.size() << nl
+            << abort(FatalError);
+    }
+    #endif
+
+    for (label i=0; i < len; ++i)
+    {
+        result[i].real(realValue);
+        result[i].imag(imagValues[i]);
     }
 }
 
@@ -74,27 +127,26 @@ void Foam::zip
 void Foam::unzip
 (
     const UList<complex>& input,
-    scalarField& re,
-    scalarField& im
+    scalarField& realValues,
+    scalarField& imagValues
 )
 {
     const label len = input.size();
 
     #ifdef FULLDEBUG
-    if (len != re.size() || len != im.size())
+    if (len != realValues.size() || len != imagValues.size())
     {
         FatalErrorInFunction
             << "Components sizes do not match: " << len << " ("
-            << re.size() << ' ' << im.size() << ')'
-            << nl
+            << realValues.size() << ' ' << imagValues.size() << ')' << nl
             << abort(FatalError);
     }
     #endif
 
     for (label i=0; i < len; ++i)
     {
-        re[i] = input[i].Re();
-        im[i] = input[i].Im();
+        realValues[i] = input[i].real();
+        imagValues[i] = input[i].imag();
     }
 }
 
@@ -103,82 +155,91 @@ void Foam::unzip
 
 Foam::complexField Foam::ComplexField
 (
-    const UList<scalar>& re,
-    const UList<scalar>& im
+    const UList<scalar>& realValues,
+    const UList<scalar>& imagValues
 )
 {
-    complexField result(re.size());
+    complexField result(realValues.size());
 
-    Foam::zip(result, re, im);
+    Foam::zip(result, realValues, imagValues);
 
     return result;
 }
 
 
-Foam::complexField Foam::ReComplexField(const UList<scalar>& re)
+Foam::complexField Foam::ComplexField
+(
+    const UList<scalar>& realValues,
+    const scalar imagValue
+)
 {
-    complexField cf(re.size());
+    complexField result(realValues.size());
 
-    forAll(cf, i)
-    {
-        cf[i].Re() = re[i];
-        cf[i].Im() = Zero;
-    }
+    Foam::zip(result, realValues, imagValue);
 
-    return cf;
+    return result;
 }
 
 
-Foam::complexField Foam::ImComplexField(const UList<scalar>& im)
+Foam::complexField Foam::ComplexField
+(
+    const scalar realValue,
+    const UList<scalar>& imagValues
+)
 {
-    complexField cf(im.size());
+    complexField result(imagValues.size());
 
-    forAll(cf, i)
-    {
-        cf[i].Re() = Zero;
-        cf[i].Im() = im[i];
-    }
+    Foam::zip(result, realValue, imagValues);
 
-    return cf;
+    return result;
 }
 
 
-Foam::scalarField Foam::ReImSum(const UList<complex>& cf)
+Foam::scalarField Foam::ReImSum(const UList<complex>& cmplx)
 {
-    scalarField sf(cf.size());
+    scalarField result(cmplx.size());
 
-    forAll(sf, i)
-    {
-        sf[i] = cf[i].Re() + cf[i].Im();
-    }
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complex& c) { return c.cmptSum(); }
+    );
 
-    return sf;
+    return result;
 }
 
 
-Foam::scalarField Foam::Re(const UList<complex>& cf)
+Foam::scalarField Foam::Re(const UList<complex>& cmplx)
 {
-    scalarField sf(cf.size());
+    scalarField result(cmplx.size());
 
-    forAll(sf, i)
-    {
-        sf[i] = cf[i].Re();
-    }
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complex& c) { return c.real(); }
+    );
 
-    return sf;
+    return result;
 }
 
 
-Foam::scalarField Foam::Im(const UList<complex>& cf)
+Foam::scalarField Foam::Im(const UList<complex>& cmplx)
 {
-    scalarField sf(cf.size());
+    scalarField result(cmplx.size());
 
-    forAll(sf, i)
-    {
-        sf[i] = cf[i].Im();
-    }
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complex& c) { return c.imag(); }
+    );
 
-    return sf;
+    return result;
 }
 
 
diff --git a/src/OpenFOAM/fields/Fields/complex/complexField.H b/src/OpenFOAM/fields/Fields/complex/complexField.H
index 70a2d44e905..8de655acae9 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexField.H
+++ b/src/OpenFOAM/fields/Fields/complex/complexField.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,8 +35,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef complexField_H
-#define complexField_H
+#ifndef Foam_complexField_H
+#define Foam_complexField_H
 
 #include "complex.H"
 #include "scalarField.H"
@@ -53,46 +53,87 @@ namespace Foam
 
 typedef Field<complex> complexField;
 
+
 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
-//- Zip together complex field from components
+//- Zip together complex field from real/imag components
+void zip
+(
+    complexField& result,
+    const UList<scalar>& realValues,
+    const UList<scalar>& imagValues
+);
+
+//- Zip together complex field from real components and constant imag component
+void zip
+(
+    complexField& result,
+    const UList<scalar>& realValues,
+    const scalar imagValue
+);
+
+//- Zip together complex field from constant real component and imag components
 void zip
 (
     complexField& result,
-    const UList<scalar>& re,
-    const UList<scalar>& im
+    const scalar realValue,
+    const UList<scalar>& imagValues
 );
 
 //- Unzip complex field into components
 void unzip
 (
     const UList<complex>& input,
-    scalarField& re,
-    scalarField& im
+    scalarField& realValues,
+    scalarField& imagValues
 );
 
 
-//- Zip up two lists of values into a list of complex
+//- Create complex field by zipping two lists of real/imag values
 complexField ComplexField
 (
-    const UList<scalar>& re,
-    const UList<scalar>& im
+    const UList<scalar>& realValues,
+    const UList<scalar>& imagValues
 );
 
-//- Create complex field from a list of real (using imag == 0)
-complexField ReComplexField(const UList<scalar>& re);
+//- Create complex field by zipping a list of real components
+//- and a constant imag component
+complexField ComplexField
+(
+    const UList<scalar>& realValues,
+    const scalar imagValue
+);
+
+//- Create complex field by zipping a constant real component
+//- and a list of imag components
+complexField ComplexField
+(
+    const scalar realValue,
+    const UList<scalar>& imagValues
+);
 
-//- Create complex field from a list of imag (using real == 0)
-complexField ImComplexField(const UList<scalar>& im);
 
 //- Extract real component
-scalarField Re(const UList<complex>& cf);
+scalarField Re(const UList<complex>& cmplx);
 
 //- Extract imag component
-scalarField Im(const UList<complex>& cf);
+scalarField Im(const UList<complex>& cmplx);
 
 //- Sum real and imag components
-scalarField ReImSum(const UList<complex>& cf);
+scalarField ReImSum(const UList<complex>& cmplx);
+
+
+//- Create complex field from a list of real (using imag == 0)
+inline complexField ReComplexField(const UList<scalar>& realValues)
+{
+    return ComplexField(realValues, scalar(0));
+}
+
+//- Create complex field from a list of imag (using real == 0)
+inline complexField ImComplexField(const UList<scalar>& imagValues)
+{
+    return ComplexField(scalar(0), imagValues);
+}
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/fields/Fields/complex/complexFields.H b/src/OpenFOAM/fields/Fields/complex/complexFields.H
index 4a9ac3f25d4..0eabcaf2bce 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexFields.H
+++ b/src/OpenFOAM/fields/Fields/complex/complexFields.H
@@ -31,8 +31,8 @@ Description
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef complexFields_H
-#define complexFields_H
+#ifndef Foam_complexFields_H
+#define Foam_complexFields_H
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
diff --git a/src/OpenFOAM/fields/Fields/complex/complexVectorField.C b/src/OpenFOAM/fields/Fields/complex/complexVectorField.C
index 99ce5ae5444..dfbc2a08746 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexVectorField.C
+++ b/src/OpenFOAM/fields/Fields/complex/complexVectorField.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -40,117 +40,209 @@ namespace Foam
 
 // * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
 
-Foam::complexVectorField Foam::ComplexField
+void Foam::zip
 (
-    const UList<vector>& re,
-    const UList<vector>& im
+    complexVectorField& result,
+    const UList<vector>& realValues,
+    const UList<vector>& imagValues
 )
 {
-    complexVectorField cvf(re.size());
+    const label len = result.size();
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
+    #ifdef FULLDEBUG
+    if (len != realValues.size() || len != imagValues.size())
     {
-        forAll(cvf, i)
-        {
-            cvf[i].component(cmpt).Re() = re[i].component(cmpt);
-            cvf[i].component(cmpt).Im() = im[i].component(cmpt);
-        }
+        FatalErrorInFunction
+            << "Components sizes do not match: " << len << " ("
+            << realValues.size() << ' ' << imagValues.size() << ')' << nl
+            << abort(FatalError);
     }
+    #endif
 
-    return cvf;
+    for (label i=0; i < len; ++i)
+    {
+        result[i] = Foam::zip(realValues[i], imagValues[i]);
+    }
 }
 
 
-Foam::complexVectorField Foam::ReComplexField(const UList<vector>& re)
+void Foam::zip
+(
+    complexVectorField& result,
+    const UList<vector>& realValues,
+    const vector& imagValue
+)
 {
-    complexVectorField cvf(re.size());
+    const label len = result.size();
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
+    #ifdef FULLDEBUG
+    if (len != realValues.size())
     {
-        forAll(cvf, i)
-        {
-            cvf[i].component(cmpt).Re() = re[i].component(cmpt);
-            cvf[i].component(cmpt).Im() = 0.0;
-        }
+        FatalErrorInFunction
+            << "Components sizes do not match: " << len << " != "
+            << realValues.size() << nl
+            << abort(FatalError);
     }
+    #endif
 
-    return cvf;
+    for (label i=0; i < len; ++i)
+    {
+        result[i] = Foam::zip(realValues[i], imagValue);
+    }
 }
 
 
-Foam::complexVectorField Foam::ImComplexField(const UList<vector>& im)
+void Foam::zip
+(
+    complexVectorField& result,
+    const vector& realValue,
+    const UList<vector>& imagValues
+)
 {
-    complexVectorField cvf(im.size());
+    const label len = result.size();
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
+    #ifdef FULLDEBUG
+    if (len != imagValues.size())
     {
-        forAll(cvf, i)
-        {
-            cvf[i].component(cmpt).Re() = 0.0;
-            cvf[i].component(cmpt).Im() = im[i].component(cmpt);
-        }
+        FatalErrorInFunction
+            << "Components sizes do not match: " << len << " != "
+            << imagValues.size() << nl
+            << abort(FatalError);
     }
+    #endif
 
-    return cvf;
+    for (label i=0; i < len; ++i)
+    {
+        result[i] = Foam::zip(realValue, imagValues[i]);
+    }
 }
 
 
-Foam::vectorField Foam::ReImSum(const UList<complexVector>& cvf)
+Foam::complexVectorField Foam::ComplexField
+(
+    const UList<vector>& realValues,
+    const UList<vector>& imagValues
+)
 {
-    vectorField vf(cvf.size());
+    complexVectorField result(realValues.size());
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
-    {
-        forAll(cvf, i)
-        {
-            vf[i].component(cmpt) =
-                cvf[i].component(cmpt).Re() + cvf[i].component(cmpt).Im();
-        }
-    }
+    Foam::zip(result, realValues, imagValues);
 
-    return vf;
+    return result;
 }
 
 
-Foam::vectorField Foam::Re(const UList<complexVector>& cvf)
+Foam::complexVectorField Foam::ComplexField
+(
+    const UList<vector>& realValues,
+    const vector& imagValue
+)
 {
-    vectorField vf(cvf.size());
+    complexVectorField result(realValues.size());
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
-    {
-        forAll(cvf, i)
+    Foam::zip(result, realValues, imagValue);
+
+    return result;
+}
+
+
+Foam::complexVectorField Foam::ComplexField
+(
+    const vector& realValue,
+    const UList<vector>& imagValues
+)
+{
+    complexVectorField result(imagValues.size());
+
+    Foam::zip(result, realValue, imagValues);
+
+    return result;
+}
+
+
+Foam::vectorField Foam::ReImSum(const UList<complexVector>& cmplx)
+{
+    vectorField result(cmplx.size());
+
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complexVector& c)
         {
-            vf[i].component(cmpt) = cvf[i].component(cmpt).Re();
+            return vector(c.x().cmptSum(), c.y().cmptSum(), c.z().cmptSum());
         }
-    }
+    );
 
-    return vf;
+    return result;
 }
 
 
-Foam::vectorField Foam::Im(const UList<complexVector>& cvf)
+Foam::vectorField Foam::Re(const UList<complexVector>& cmplx)
 {
-    vectorField vf(cvf.size());
+    vectorField result(cmplx.size());
+
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complexVector& c)
+        {
+            return vector(c.x().real(), c.y().real(), c.z().real());
+        }
+    );
 
-    for (direction cmpt=0; cmpt<vector::nComponents; ++cmpt)
-    {
-        forAll(cvf, i)
+    return result;
+}
+
+
+Foam::vectorField Foam::Im(const UList<complexVector>& cmplx)
+{
+    vectorField result(cmplx.size());
+
+    std::transform
+    (
+        cmplx.cbegin(),
+        cmplx.cend(),
+        result.begin(),
+        [](const complexVector& c)
         {
-            vf[i].component(cmpt) = cvf[i].component(cmpt).Im();
+            return vector(c.x().imag(), c.y().imag(), c.z().imag());
         }
-    }
+    );
 
-    return vf;
+    return result;
 }
 
 
 Foam::complexVectorField Foam::operator^
 (
-    const UList<vector>& vf,
-    const UList<complexVector>& cvf
+    const UList<vector>& vec,
+    const UList<complexVector>& cmplx
 )
 {
-    return ComplexField(vf^Re(cvf), vf^Im(cvf));
+    const label len = cmplx.size();
+
+    #ifdef FULLDEBUG
+    if (len != vec.size())
+    {
+        FatalErrorInFunction
+            << "Parameter sizes do not match: " << vec.size()
+            << " != " << len << nl
+            << abort(FatalError);
+    }
+    #endif
+
+    complexVectorField result(len);
+
+    for (label i=0; i < len; ++i)
+    {
+        result[i] = (vec[i] ^ cmplx[i]);
+    }
+
+    return result;
 }
 
 
diff --git a/src/OpenFOAM/fields/Fields/complex/complexVectorField.H b/src/OpenFOAM/fields/Fields/complex/complexVectorField.H
index 15b8978581f..ab8e33215ef 100644
--- a/src/OpenFOAM/fields/Fields/complex/complexVectorField.H
+++ b/src/OpenFOAM/fields/Fields/complex/complexVectorField.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
-    Copyright (C) 2019 OpenCFD Ltd.
+    Copyright (C) 2019-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -35,8 +35,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef complexVectorField_H
-#define complexVectorField_H
+#ifndef Foam_complexVectorField_H
+#define Foam_complexVectorField_H
 
 #include "complex.H"
 #include "complexVector.H"
@@ -51,33 +51,92 @@ namespace Foam
 
 typedef Field<complexVector> complexVectorField;
 
-//- Zip up two lists of values into a list of complex
+
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+//- Zip together complex vector field from real/imag components
+void zip
+(
+    complexVectorField& result,
+    const UList<vector>& realValues,
+    const UList<vector>& imagValues
+);
+
+
+//- Zip together complex vector field from real components
+//- and constant imag component
+void zip
+(
+    complexVectorField& result,
+    const UList<vector>& realValues,
+    const vector& imagValue
+);
+
+
+//- Zip together complex vector field from constant real component
+//- and imag components
+void zip
+(
+    complexVectorField& result,
+    const vector& realValue,
+    const UList<vector>& imagValues
+);
+
+
+//- Create complexVector field by zipping two lists of real/imag values
 complexVectorField ComplexField
 (
-    const UList<vector>& re,
-    const UList<vector>& im
+    const UList<vector>& realValues,
+    const UList<vector>& imagValues
 );
 
+//- Create complexVector field by zipping a list of real components
+//- and a constant imag component
+complexVectorField ComplexField
+(
+    const UList<vector>& realValues,
+    const vector& imagValue
+);
 
-//- Create complex field from a list of real (using imag == 0)
-complexVectorField ReComplexField(const UList<vector>& re);
+//- Create complexVector field by zipping a constant real component
+//- and a list of imag components
+complexVectorField ComplexField
+(
+    const vector& realValue,
+    const UList<vector>& imagValues
+);
 
-//- Create complex field from a list of imag (using real == 0)
-complexVectorField ImComplexField(const UList<vector>& im);
 
 //- Extract real component
-vectorField Re(const UList<complexVector>& cvf);
+vectorField Re(const UList<complexVector>& cmplx);
 
 //- Extract imag component
-vectorField Im(const UList<complexVector>& cvf);
+vectorField Im(const UList<complexVector>& cmplx);
 
 //- Sum real and imag components
-vectorField ReImSum(const UList<complexVector>& cvf);
+vectorField ReImSum(const UList<complexVector>& cmplx);
+
+
+//- Create complexVector field from a list of real (using imag == 0)
+inline complexVectorField ReComplexField(const UList<vector>& realValues)
+{
+    return ComplexField(realValues, vector::zero);
+}
+
+//- Create complexVector field from a list of imag (using real == 0)
+inline complexVectorField ImComplexField(const UList<vector>& imagValues)
+{
+    return ComplexField(vector::zero, imagValues);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
+//- Cross-product
 complexVectorField operator^
 (
-    const UList<vector>& vf,
-    const UList<complexVector>& cvf
+    const UList<vector>& vec,
+    const UList<complexVector>& cmplx
 );
 
 
diff --git a/src/OpenFOAM/matrices/EigenMatrix/EigenMatrix.C b/src/OpenFOAM/matrices/EigenMatrix/EigenMatrix.C
index 30ddb10c36d..30f28d72106 100644
--- a/src/OpenFOAM/matrices/EigenMatrix/EigenMatrix.C
+++ b/src/OpenFOAM/matrices/EigenMatrix/EigenMatrix.C
@@ -873,8 +873,8 @@ void Foam::EigenMatrix<cmptType>::realSchur()
                 complex cDiv = complex(0.0, -H_[n - 1][n])
                         /complex(H_[n - 1][n-1]-p, q);
 
-                H_[n - 1][n - 1] = cDiv.Re();
-                H_[n - 1][n] = cDiv.Im();
+                H_[n - 1][n - 1] = cDiv.real();
+                H_[n - 1][n] = cDiv.imag();
             }
 
             H_[n][n - 1] = Zero;
@@ -907,8 +907,8 @@ void Foam::EigenMatrix<cmptType>::realSchur()
                     if (EValsIm_[i] == 0)
                     {
                         complex cDiv = complex(-ra, -sa)/complex(w, q);
-                        H_[i][n - 1] = cDiv.Re();
-                        H_[i][n] = cDiv.Im();
+                        H_[i][n - 1] = cDiv.real();
+                        H_[i][n] = cDiv.imag();
                     }
                     else
                     {
@@ -930,8 +930,8 @@ void Foam::EigenMatrix<cmptType>::realSchur()
                                 complex(x*r - z*ra + q*sa, x*s - z*sa - q*ra)
                                     /complex(vr, vi);
 
-                        H_[i][n - 1] = cDiv.Re();
-                        H_[i][n] = cDiv.Im();
+                        H_[i][n - 1] = cDiv.real();
+                        H_[i][n] = cDiv.imag();
 
                         if (mag(x) > (mag(z) + mag(q)))
                         {
@@ -946,8 +946,8 @@ void Foam::EigenMatrix<cmptType>::realSchur()
                             complex cDiv = complex(-r - y*H_[i][n - 1], -s
                                     - y*H_[i][n])/complex(z, q);
 
-                            H_[i + 1][n - 1] = cDiv.Re();
-                            H_[i + 1][n] = cDiv.Im();
+                            H_[i + 1][n - 1] = cDiv.real();
+                            H_[i + 1][n] = cDiv.imag();
                         }
                     }
 
diff --git a/src/OpenFOAM/primitives/Vector/complex/complexVector.C b/src/OpenFOAM/primitives/Vector/complex/complexVector.C
index b1838bd1b5c..819b54b40c6 100644
--- a/src/OpenFOAM/primitives/Vector/complex/complexVector.C
+++ b/src/OpenFOAM/primitives/Vector/complex/complexVector.C
@@ -24,9 +24,6 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-Description
-    Vector of complex numbers.
-
 \*---------------------------------------------------------------------------*/
 
 #include "complexVector.H"
diff --git a/src/OpenFOAM/primitives/Vector/complex/complexVector.H b/src/OpenFOAM/primitives/Vector/complex/complexVector.H
index fbba707ef45..7016b19109d 100644
--- a/src/OpenFOAM/primitives/Vector/complex/complexVector.H
+++ b/src/OpenFOAM/primitives/Vector/complex/complexVector.H
@@ -36,8 +36,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef complexVector_H
-#define complexVector_H
+#ifndef Foam_complexVector_H
+#define Foam_complexVector_H
 
 #include "complex.H"
 #include "vector.H"
diff --git a/src/OpenFOAM/primitives/Vector/complex/complexVectorI.H b/src/OpenFOAM/primitives/Vector/complex/complexVectorI.H
index fbd0a769262..bf01a86b674 100644
--- a/src/OpenFOAM/primitives/Vector/complex/complexVectorI.H
+++ b/src/OpenFOAM/primitives/Vector/complex/complexVectorI.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011 OpenFOAM Foundation
+    Copyright (C) 2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -30,6 +31,20 @@ License
 namespace Foam
 {
 
+// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
+
+//- Zip together complexVector from real/imag vectors
+inline complexVector zip(const vector& realValue, const vector& imagValue)
+{
+    return complexVector
+    (
+        complex(realValue.x(), imagValue.x()),
+        complex(realValue.y(), imagValue.y()),
+        complex(realValue.z(), imagValue.z())
+    );
+}
+
+
 // * * * * * * * * * * * * * * * Global Operators  * * * * * * * * * * * * * //
 
 inline complexVector operator*(const complex& v1, const complexVector& v2)
diff --git a/src/OpenFOAM/primitives/complex/complex.H b/src/OpenFOAM/primitives/complex/complex.H
index 6fa4bc5bf04..cc54994d23e 100644
--- a/src/OpenFOAM/primitives/complex/complex.H
+++ b/src/OpenFOAM/primitives/complex/complex.H
@@ -138,24 +138,6 @@ public:
         void imag(scalar val) noexcept { im = val; }
 
 
-    // Access
-
-        //- Real part of complex number
-        scalar Re() const noexcept { return re; }
-
-        //- Imaginary part of complex number
-        scalar Im() const noexcept { return im; }
-
-
-    // Edit
-
-        //- Real part of complex number
-        scalar& Re() noexcept { return re; }
-
-        //- Imaginary part of complex number
-        scalar& Im() noexcept { return im; }
-
-
     // Methods
 
         //- Complex conjugate
@@ -168,6 +150,9 @@ public:
         //- The L2-norm squared of complex
         inline scalar magSqr() const;
 
+        //- The sum of real/imag components
+        inline scalar cmptSum() const noexcept;
+
 
     // Member Operators
 
@@ -219,6 +204,21 @@ public:
         friend complex operator/(const complex& c1, const complex& c2);
         friend complex operator/(const complex& c, const scalar s);
         friend complex operator/(const scalar s, const complex& c);
+
+
+    // Housekeeping
+
+        //- Get real part of complex number. Same as real()
+        scalar Re() const noexcept { return re; }
+
+        //- Get imaginary part of complex number. Same as imag()
+        scalar Im() const noexcept { return im; }
+
+        //- Non-const access to real part. Prefer real() setter method
+        scalar& Re() noexcept { return re; }
+
+        //- Non-const access to imaginary part. Prefer imag() setter method
+        scalar& Im() noexcept { return im; }
 };
 
 
diff --git a/src/OpenFOAM/primitives/complex/complexI.H b/src/OpenFOAM/primitives/complex/complexI.H
index cfb57ae2ffc..ceda93cb89e 100644
--- a/src/OpenFOAM/primitives/complex/complexI.H
+++ b/src/OpenFOAM/primitives/complex/complexI.H
@@ -90,6 +90,12 @@ inline Foam::scalar Foam::complex::magSqr() const
 }
 
 
+inline Foam::scalar Foam::complex::cmptSum() const noexcept
+{
+    return (re + im);
+}
+
+
 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
 
 inline void Foam::complex::operator=(const Foam::zero)
diff --git a/src/functionObjects/randomProcesses/energySpectrum/energySpectrum.C b/src/functionObjects/randomProcesses/energySpectrum/energySpectrum.C
index 8e1d24af700..0a8a159b287 100644
--- a/src/functionObjects/randomProcesses/energySpectrum/energySpectrum.C
+++ b/src/functionObjects/randomProcesses/energySpectrum/energySpectrum.C
@@ -73,7 +73,7 @@ void Foam::functionObjects::energySpectrum::calcAndWriteSpectrum
     (
         fft::forwardTransform
         (
-            ReComplexField(U),
+            ComplexField(U, vector::zero),
             List<int>({N.x(), N.y(), N.z()})
         )
        /scalar(cmptProduct(N))
diff --git a/src/randomProcesses/fft/calcEk.C b/src/randomProcesses/fft/calcEk.C
index ebc234cfb26..5baf01cb475 100644
--- a/src/randomProcesses/fft/calcEk.C
+++ b/src/randomProcesses/fft/calcEk.C
@@ -41,7 +41,7 @@ graph calcEk
     (
         fft::forwardTransform
         (
-            ReComplexField(U.primitiveField()),
+            ComplexField(U.primitiveField(), vector::zero),
             K.nn()
         )*recRootN,
         K
diff --git a/src/randomProcesses/fft/fft.C b/src/randomProcesses/fft/fft.C
index 8d483b60310..27c4dc5299b 100644
--- a/src/randomProcesses/fft/fft.C
+++ b/src/randomProcesses/fft/fft.C
@@ -47,7 +47,7 @@ void Foam::fft::fftRenumberRecurse
         // We've worked out the renumbering scheme. Now copy
         // the components across
 
-        data[l1] = complex(renumData[l2].Re(), renumData[l2].Im());
+        data[l1] = renumData[l2];
     }
     else
     {
@@ -150,12 +150,12 @@ Foam::fft::realTransform1D(const scalarField& field)
     auto tresult = tmp<complexField>::New(nBy2 + 1);
     auto& result = tresult.ref();
 
-    result[0].Re() = out[0];
-    result[nBy2].Re() = out[nBy2];
+    result[0].real(out[0]);
+    result[nBy2].real(out[nBy2]);
     for (label i = 1; i < nBy2; ++i)
     {
-        result[i].Re() = out[i];
-        result[i].Im() = out[n - i];
+        result[i].real(out[i]);
+        result[i].imag(out[n - i]);
     }
 
     fftw_destroy_plan(plan);
@@ -198,8 +198,8 @@ void Foam::fft::transform
 
     forAll(field, i)
     {
-        inPtr[i][0] = field[i].Re();
-        inPtr[i][1] = field[i].Im();
+        inPtr[i][0] = field[i].real();
+        inPtr[i][1] = field[i].imag();
     }
 
     // Create the plan
@@ -220,8 +220,8 @@ void Foam::fft::transform
 
     forAll(field, i)
     {
-        field[i].Re() = outPtr[i][0];
-        field[i].Im() = outPtr[i][1];
+        field[i].real(outPtr[i][0]);
+        field[i].imag(outPtr[i][1]);
     }
 
     fftw_destroy_plan(plan);
diff --git a/src/randomProcesses/turbulence/turbGen.C b/src/randomProcesses/turbulence/turbGen.C
index 23b119f87a1..dd50dea39a7 100644
--- a/src/randomProcesses/turbulence/turbGen.C
+++ b/src/randomProcesses/turbulence/turbGen.C
@@ -74,8 +74,11 @@ Foam::vectorField Foam::turbGen::U()
     (
         fft::reverseTransform
         (
-            ComplexField(cos(constant::mathematical::twoPi*rndPhases)*s,
-            sin(constant::mathematical::twoPi*rndPhases)*s),
+            ComplexField
+            (
+                cos(constant::mathematical::twoPi*rndPhases)*s,
+                sin(constant::mathematical::twoPi*rndPhases)*s
+            ),
             K.nn()
         )*recRootN
     );
-- 
GitLab