Commit Graph

232 Commits

Author SHA1 Message Date
621740e90b polyBoundaryMesh::findPatchID,findPatchIDs: renamed findIndex,findIndices
Index is a better name to describe a label index than ID which may be an
integer, word or other means of identification.
2023-12-16 13:27:12 +00:00
b9fe7df344 polyTopoChange: New library containing the mesh topology change functionality
from the original dynamicMesh library, now separated into polyTopoChange and motionSolvers
2023-12-14 14:08:45 +00:00
abe43a9532 thermo: Standardise property names and remove molar functions
All property functions in the low-level templated thermo property
implementations and the high-level virtual interfaces have been made
consistent. All energies and enthalpies are lower case to denote that
they are specific quantities. Molar functions have been removed as these
are no longer used anywhere.
2023-12-01 17:11:59 +00:00
a5f0b5310a motionSmootherAlgoCheck: Moved to the new meshCheck library 2023-10-20 12:32:25 +01:00
a9a75605cb Test-Function1: Minor clean-up 2023-07-26 12:35:59 +01:00
835ef31a1d foamDictionary: Moved the dictionary tests/examples to applications/test/dictionary 2023-07-03 13:38:37 +01:00
0657826ab9 Replaced all remaining addTimeOptions.H includes with the more flexible timeSelector 2023-06-23 15:24:06 +01:00
f3df607dde Test-string: Remove dictionary substitution test
The dictionary/table-based expansions provided by stringOps::expand are
now too situation specific for this utility to concisely test with a
single complex string. These expansions are fundamental to the operation
of dictionary and dynamic code and receive good testing coverage in the
tutorial test loop anyway.
2023-06-23 15:15:51 +01:00
0927fd47fa stringOps: Rationalisation of expansions
Specific names have been given for expand functions. Unused functions
have been removed, and functions only used locally have been removed
from the namespace. Documentation has been corrected. Default and
alternative value handling has been removed from code template
expansion.
2023-06-22 11:46:23 +01:00
f49eb3011d applications/.*/decomposeParDict: Removed unused clutter 2023-06-21 15:11:19 +01:00
d0b2fe89e5 applications/test/dictionary: Corrected formatting of example dictionary files 2023-06-21 12:20:38 +01:00
c9bb53e109 ISstream: Corrected parsing of variables 2023-06-20 19:14:47 +01:00
5233335924 thermophysicalModels: Permit wildcard names of thermo dictionaries
This can be useful when reusing thermo configurations across multiple
setups. In one simulation, the fluid might be entirely air, and in
another there might be additional pollutant or fuel species. This could
be defined without changing the species' thermo enties as follows:

    "(mixture|air)"
    {
        specie
        {
            molWeight   28.9;
        }
        thermodynamics
        {
            Hf          0;
            Cv          724.8;
        }
        transport
        {
            mu          1.84e-05;
            Pr          0.7;
        }
    }

This was semi-supported before, but it lead to the wrong name (i.e., the
wildcard string) being stored in the base specie class. Now the name is
passed through the thermo constructors, so it is always correct.
2023-06-08 16:00:14 +01:00
08544446e8 Time, functionObjectList: Refactored to simplify construction and switching-off functionObjects 2023-06-06 08:17:52 +01:00
e00ff00dcd applications/test/vectorTools: Deleted, redundant tests 2023-05-31 11:18:10 +01:00
cae41959dd distributions: Generalised statistical distributions
This new class hierarchy replaces the distributions previously provided
by the Lagrangian library.

All distributions (except fixedValue) now require a "size exponent", Q,
to be specified along with their other coefficients. If a distribution's
CDF(x) (cumulative distribution function) represents what proportion of
the distribution takes a value below x, then Q determines what is meant
by "proportion":

- If Q=0, then "proportion" means the number of sampled values expected
  to be below x divided by the total number of sampled values.

- If Q=3, then "proportion" means the expected sum of sampled values
  cubed for values below x divided by the total sum of values cubed. If
  x is a length, then this can be interpreted as a proportion of the
  total volume of sampled objects.

- If Q=2, and x is a length, then the distribution might represent the
  proportion of surface area, and so on...

In addition to the user-specification of Q defining what size the given
distribution relates to, an implementation that uses a distribution can
also programmatically define a samplingQ to determine what sort of
sample is being constructed; whether the samples should have an equal
number (sampleQ=0), volume (sampleQ=3), area (sampleQ=2), etc...

A number of fixes to the distributions have been made, including fixing
some fundamental bugs in the returned distribution of samples, incorrect
calculation of the distribution means, renaming misleadingly named
parameters, and correcting some inconsistencies in the way in which
tabulated PDF and CDF data was processed. Distributions no longer
require their parameters to be defined in a sub-dictionary, but a
sub-dictionary is still supported for backwards compatibility.

The distributions can now generate their PDF-s as well as samples, and a
test application has been added (replacing two previous applications),
which thoroughly checks consistency between the PDF and the samples for
a variety of combinations of values of Q and sampleQ.

Backwards incompatible changes are as follows:

- The standard deviation keyword for the normal (and multi-normal)
  distribution is now called 'sigma'. Previously this was 'variance',
  which was misleading, as the value is a standard deviation.

- The 'massRosinRammler' distribution has been removed. This
  functionality is now provided by the standard 'RosinRammler'
  distributon with a Q equal to 0, and a sampleQ of 3.

- The 'general' distribution has been split into separate distributions
  based on whether PDF or CDF data is provided. These distributions are
  called 'tabulatedDensity' and 'tabulatedCumulative', respectively.
2023-05-11 15:42:17 +01:00
bd7d1a438a scalar: Added optimised integer powers and roots 2023-05-11 10:05:30 +01:00
0080177d88 invIncGammaRatio_P: Additional divide by zero protection 2023-04-04 16:42:34 +01:00
2df8c2549a Test-incGamma: Added test application
This checks the consistency of incGamma and invIncGamma. It writes files
with columns containing values for different 'a' parameters. The
incGammaRatio_P.xy and invIncGammaRatio_P.xy files should generate the same
lines when the plot axis order is reversed. E.g., in gnuplot:

    plot "incGammaRatio_P.xy" us 1:5 w l, \
         "invIncGammaRatio_P.xy" us 5:1 w p
2023-04-04 15:19:01 +01:00
bcddcc89f6 applications/test: Replaced fvCFD.H with appropriate include files 2023-04-01 16:50:10 +01:00
f50ff139fc Test-rigidBodyDynamics: Corrected and improved visualisation of pendulumAndSpring 2023-03-03 15:53:30 +00:00
c802985a2d Test-patchToPatch: Added -region and -sourceRegion options 2023-02-16 15:15:30 +00:00
2c247c3e8f meshTools/algorithms/PatchEdgeFaceWave: Added point object with data 2023-02-16 11:12:36 +00:00
4dbc23c141 ListOps::identity -> identityMap
to avoid confusion with the tensor identity.
2023-02-03 17:12:31 +00:00
9e51bb48ce foamyHexMesh, foamyQuadMesh: Removed pending funding for further development and maintenance 2023-01-06 22:23:59 +00:00
2f4dd4fe27 Code simplification: GeometricField<Type, fvPatchField, volMesh> -> VolField<Type>
Using the VolField<Type> partial specialisation of
GeometricField<Type, fvPatchField, volMesh>
simplifies the code and improves readability.
2022-12-02 22:04:45 +00:00
ed7e703040 Time::timeName(): no longer needed, calls replaced by name()
The timeName() function simply returns the dimensionedScalar::name() which holds
the user-time name of the current time and now that timeName() is no longer
virtual the dimensionedScalar::name() can be called directly.  The timeName()
function implementation is maintained for backward-compatibility.
2022-11-30 15:53:51 +00:00
723f522c51 cutPoly: New polyhedral cutting routines and isoSurface algorithm
A set of routines for cutting polyhedra have been added. These can cut
polyhedral cells based on the adjacent point values and an iso-value
which defines the surface. The method operates directly on the
polyhedral cells; it does not decompose them into tetrahedra at any
point. The routines can compute the cut topology as well as integrals of
properties above and below the cut surface.

An iso-surface algorithm has been added based on these polyhedral
cutting routines. It is significantly more robust than the previous
algorithm, and produces compact surfaces equivalent to the previous
algorithm's maximum filtering level. It is also approximately 3 times
faster than the previous algorithm, and 10 times faster when run
repeatedly on the same set of cells (this is because some addressing is
cached and reused).

This algorithm is used by the 'isoSurface', 'distanceSurface' and
'cutPlane' sampled surfaces.

The 'cutPlane' sampled surface is a renaming of 'cuttingPlane' to make
it consistent with the corresponding packaged function. The name
'cuttingPlane' has been retained for backwards compatibility and can
still be used to select a 'cutPlane' surface. The legacy 'plane' surface
has been removed.

The 'average' keyword has been removed from specification of these
sampled surfaces as cell-centred values are no longer used in the
generation of or interpolation to an iso-surface. The 'filtering'
keyword has also been removed as it relates to options within the
previous algorithm. Zone support has been reinstated into the
'isoSurface' sampled surface. Interpolation to all these sampled
surfaces has been corrected to exactly match the user-selected
interpolation scheme, and the interpolation procedure no longer
unnecessarily re-generates data that is already available.
2022-11-23 16:56:23 +00:00
0203618a91 patchToPatch: Improve robustness of non-intersection methods
The nearest, matching and inverseDistance methods are now based on a
shared "nearby" method. This method creates, for each face, a local
stencil of opposing faces for which the bounding spheres overlap. This
has proven far more robust on cases with both conformal and
non-conformal interfaces.
2022-11-09 11:18:46 +00:00
94152725a8 fvMesh: added move constructor and disallowed construction
This support efficient return of fvMesh from functions which generate region
meshes without allowing risky copy construction.
2022-11-06 17:16:25 +00:00
704b65f8de triangle, tetrahedron: Consolidate circumCircle/Sphere functions 2022-10-27 08:52:14 +01:00
30eb5e28e6 fvMesh: Generalised the handing of old-time fields during mesh motion and topology change
Topology change occurs before the time-increment and hence the oldest time
field (old-time in the case of 1st order time schemes, old-old-time in the case
of 2nd-order time schemes) is not actually needed as it is replaced by the
current time-field after time-increment so there is no purpose to mapping this
field.  However, it is necessary to keep track of the existence of the
oldest-time field to ensure the correct number of old-time fields are cached for
the time-scheme.  This development allows fvMesh to delete the redundant
oldest-time fields in such a manner that GeometricField can reinstate them
correctly after time-increment which is more efficient and more reliable than
attempting to map them and done previously.

Additionally fvMesh movement, which occurs after time-increment, now ensure all
old-time fields are up-to-date before NCC stitcher mapping so that both fields
and their old-time values are mapped consistently.  This removes the need for
old-time field caching calls in MapGeometricFields, fvMeshAdder and
fvMeshStitcher, thus simplifying the code and improving maintainability.
2022-10-10 14:43:07 +01:00
f4ac5f8748 AMIInterpolation, cyclicAMI: Removed
AMIInterpolation and cyclicAMI have been superseded by patchToPatch and
nonConformalCoupled, respectively.

The motivation behind this change is explained in the following article:

    https://cfd.direct/openfoam/free-software/non-conformal-coupling/

Information about how to convert a case which uses cyclicAMI to
nonConformalCoupled can be found here:

    https://cfd.direct/openfoam/free-software/using-non-conformal-coupling/
2022-09-22 10:05:41 +01:00
0214138e6a Test-mappedPatch: Updated following changes to mappedPatchBase 2022-09-09 13:52:20 +01:00
278fa7f69c applications/test: updated to physicalProperties 2022-07-09 11:05:52 +01:00
867badc024 polyMesh, fvMesh: The moving and topoChanged flags are now maintained by fvMesh
avoiding problems with mesh generation, pre/post-processing applications
etc. triggering inappropriate changes to the moving and topoChanged states which
are only needed for updates in solvers corresponding to mesh changes.
2022-06-10 16:50:41 +01:00
d54f5ab9ad polyMesh: Changed topoChanging -> topoChanged
The topoChanged flag now indicates that the mesh topology has changed at the
start of the current time-step rather than it is changing during the run, for
subsequent time-steps without topology change it is set false until the next
topology change.
2022-06-10 12:01:28 +01:00
569fa31d09 Non-Conformal Coupled (NCC): Conservative coupling of non-conforming patches
This major development provides coupling of patches which are
non-conformal, i.e. where the faces of one patch do not match the faces
of the other. The coupling is fully conservative and second order
accurate in space, unlike the Arbitrary Mesh Interface (AMI) and
associated ACMI and Repeat AMI methods which NCC replaces.

Description:

A non-conformal couple is a connection between a pair of boundary
patches formed by projecting one patch onto the other in a way that
fills the space between them. The intersection between the projected
surface and patch forms new faces that are incorporated into the finite
volume mesh. These new faces are created identically on both sides of
the couple, and therefore become equivalent to internal faces within the
mesh. The affected cells remain closed, meaning that the area vectors
sum to zero for all the faces of each cell. Consequently, the main
benefits of the finite volume method, i.e. conservation and accuracy,
are not undermined by the coupling.

A couple connects parts of mesh that are otherwise disconnected and can
be used in the following ways:

+ to simulate rotating geometries, e.g. a propeller or stirrer, in which
  a part of the mesh rotates with the geometry and connects to a
  surrounding mesh which is not moving;
+ to connect meshes that are generated separately, which do not conform
  at their boundaries;
+ to connect patches which only partially overlap, in which the
  non-overlapped section forms another boundary, e.g. a wall;
+ to simulate a case with a geometry which is periodically repeating by
  creating multiple couples with different transformations between
  patches.

The capability for simulating partial overlaps replaces the ACMI
functionality, currently provided by the 'cyclicACMI' patch type, and
which is unreliable unless the couple is perfectly flat. The capability
for simulating periodically repeating geometry replaces the Repeat AMI
functionality currently provided by the 'cyclicRepeatAMI' patch type.

Usage:

The process of meshing for NCC is very similar to existing processes for
meshing for AMI. Typically, a mesh is generated with an identifiable set
of internal faces which coincide with the surface through which the mesh
will be coupled. These faces are then duplicated by running the
'createBaffles' utility to create two boundary patches. The points are
then split using 'splitBaffles' in order to permit independent motion of
the patches.

In AMI, these patches are assigned the 'cyclicAMI' patch type, which
couples them using AMI interpolation methods.

With NCC, the patches remain non-coupled, e.g. a 'wall' type. Coupling
is instead achieved by running the new 'createNonConformalCouples'
utility, which creates additional coupled patches of type
'nonConformalCyclic'. These appear in the 'constant/polyMesh/boundary'
file with zero faces; they are populated with faces in the finite volume
mesh during the connection process in NCC.

For a single couple, such as that which separates the rotating and
stationary sections of a mesh, the utility can be called using the
non-coupled patch names as arguments, e.g.

    createNonConformalCouples -overwrite rotatingZoneInner rotatingZoneOuter

where 'rotatingZoneInner' and 'rotatingZoneOuter' are the names of the
patches.

For multiple couples, and/or couples with transformations,
'createNonConformalCouples' should be run without arguments. Settings
will then be read from a configuration file named
'system/createNonConformalCouplesDict'. See
'$FOAM_ETC/caseDicts/annotated/createNonConformalCouplesDict' for
examples.

Boundary conditions must be specified for the non-coupled patches. For a
couple where the patches fully overlap, boundary conditions
corresponding to a slip wall are typically applied to fields, i.e
'movingWallSlipVelocity' (or 'slip' if the mesh is stationary) for
velocity U, 'zeroGradient' or 'fixedFluxPressure' for pressure p, and
'zeroGradient' for other fields.  For a couple with
partially-overlapping patches, boundary conditions are applied which
physically represent the non-overlapped region, e.g. a no-slip wall.

Boundary conditions also need to be specified for the
'nonConformalCyclic' patches created by 'createNonConformalCouples'. It
is generally recommended that this is done by including the
'$FOAM_ETC/caseDicts/setConstraintTypes' file in the 'boundaryField'
section of each of the field files, e.g.

    boundaryField
    {
        #includeEtc "caseDicts/setConstraintTypes"

        inlet
        {
             ...
        }

        ...
    }

For moving mesh cases, it may be necessary to correct the mesh fluxes
that are changed as a result of the connection procedure. If the
connected patches do not conform perfectly to the mesh motion, then
failure to correct the fluxes can result in noise in the pressure
solution.

Correction for the mesh fluxes is enabled by the 'correctMeshPhi' switch
in the 'PIMPLE' (or equivalent) section of 'system/fvSolution'. When it
is enabled, solver settings are required for 'MeshPhi'. The solution
just needs to distribute the error enough to dissipate the noise. A
smooth solver with a loose tolerance is typically sufficient, e.g. the
settings in 'system/fvSolution' shown below:

    solvers
    {
        MeshPhi
        {
            solver          smoothSolver;
            smoother        symGaussSeidel;
            tolerance       1e-2;
            relTol          0;
        }
        ...
    }

    PIMPLE
    {
         correctMeshPhi      yes;
         ...
    }

The solution of 'MeshPhi' is an inexpensive computation since it is
applied only to a small subset of the mesh adjacent to the
couple. Conservation is maintained whether or not the mesh flux
correction is enabled, and regardless of the solution tolerance for
'MeshPhi'.

Advantages of NCC:

+ NCC maintains conservation which is required for many numerical
  schemes and algorithms to operate effectively, in particular those
  designed to maintain boundedness of a solution.

+ Closed-volume systems no longer suffer from accumulation or loss of
  mass, poor convergence of the pressure equation, and/or concentration
  of error in the reference cell.

+ Partially overlapped simulations are now possible on surfaces that are
  not perfectly flat. The projection fills space so no overlaps or
  spaces are generated inside contiguously overlapping sections, even if
  those sections have sharp angles.

+ The finite volume faces created by NCC have geometrically accurate
  centres. This makes the method second order accurate in space.

+ The polyhedral mesh no longer requires duplicate boundary faces to be
  generated in order to run a partially overlapped simulation.

+ Lagrangian elements can now transfer across non-conformal couplings in
  parallel.

+ Once the intersection has been computed and applied to the finite
  volume mesh, it can use standard cyclic or processor cyclic finite
  volume boundary conditions, with no need for additional patch types or
  matrix interfaces.

+ Parallel communication is done using the standard
  processor-patch-field system. This is more efficient than alternative
  systems since it has been carefully optimised for use within the
  linear solvers.

+ Coupled patches are disconnected prior to mesh motion and topology
  change and reconnected afterwards. This simplifies the boundary
  condition specification for mesh motion fields.

Resolved Bug Reports:

+ https://bugs.openfoam.org/view.php?id=663
+ https://bugs.openfoam.org/view.php?id=883
+ https://bugs.openfoam.org/view.php?id=887
+ https://bugs.openfoam.org/view.php?id=1337
+ https://bugs.openfoam.org/view.php?id=1388
+ https://bugs.openfoam.org/view.php?id=1422
+ https://bugs.openfoam.org/view.php?id=1829
+ https://bugs.openfoam.org/view.php?id=1841
+ https://bugs.openfoam.org/view.php?id=2274
+ https://bugs.openfoam.org/view.php?id=2561
+ https://bugs.openfoam.org/view.php?id=3817

Deprecation:

NCC replaces the functionality provided by AMI, ACMI and Repeat AMI.
ACMI and Repeat AMI are insufficiently reliable to warrant further
maintenance so are removed in an accompanying commit to OpenFOAM-dev.
AMI is more widely used so will be retained alongside NCC for the next
version release of OpenFOAM and then subsequently removed from
OpenFOAM-dev.
2022-05-18 10:25:43 +01:00
6ebf845bc8 Function1s::squarePulse: Implemented integral 2022-05-12 12:00:20 +01:00
0289f383eb rigidBodyDynamics: Added rotating joint
This joint allows two bodies to rotate relative to each other at a
specified speed. The relative motion is completely specified, so this
joint has zero degrees of freedom.

It could be used, for example, to attach a rotating propeller to a
moving ship:

    bodies
    {
        hull
        {
            ...
        }
        propeller
        {
            type            rigidBody;

            // Dynamic properties
            mass            ...;
            centreOfMass    ...;
            inertia         ...;

            // The propeller is connected to the hull
            parent          hull;

            // The position relative to the hull
            transform       (1 0 0 0 1 0 0 0 1) (20 0 0);

            // Rotation settings
            joint
            {
                type            rotating;
                omega           (6 0 0);
            }
        }
    }
2022-04-05 11:36:39 +01:00
7592a81c6e polyMeshMap: New mesh to mesh map for the new mapping update function mapMesh(const polyMeshMap&)
This new mapping structure is designed to support run-time mesh-to-mesh mapping
to allow arbitrary changes to the mesh structure, for example during extreme
motion requiring significant topology change including region disconnection etc.
2022-04-04 11:15:41 +01:00
6047f27aac polyDistributionMap: renamed from polyMeshDistributionMap for consistency with polyTopoChangeMap 2022-03-31 23:44:47 +01:00
3ace8f434b polyTopoChangeMap: Renamed from mapPolyMesh to clarify purpose and scope
The polyTopoChangeMap is the map specifically relating to polyMesh topological
changes generated by polyTopoChange and used to update and map mesh related
types and fields following the topo-change.
2022-03-31 22:05:37 +01:00
2e6eb5f2ce polyMeshDistributionMap: renamed mapDistributePolyMesh -> polyMeshDistributionMap
This is a map data structure rather than a class or function which performs the
mapping operation so polyMeshDistributionMap is more logical and comprehensible
than mapDistributePolyMesh.
2022-03-31 18:01:44 +01:00
a7030ee97e CompactListList: Removed unnecessary templating and create unallocated base 2022-02-04 15:17:27 +00:00
25a6d068f0 sampledSets, streamlines: Various improvements
Sampled sets and streamlines now write all their fields to the same
file. This prevents excessive duplication of the geometry and makes
post-processing tasks more convenient.

"axis" entries are now optional in sampled sets and streamlines. When
omitted, a default entry will be used, which is chosen appropriately for
the coordinate set and the write format. Some combinations are not
supported. For example, a scalar ("x", "y", "z" or "distance") axis
cannot be used to write in the vtk format, as vtk requires 3D locations
with which to associate data. Similarly, a point ("xyz") axis cannot be
used with the gnuplot format, as gnuplot needs a single scalar to
associate with the x-axis.

Streamlines can now write out fields of any type, not just scalars and
vectors, and there is no longer a strict requirement for velocity to be
one of the fields.

Streamlines now output to postProcessing/<functionName>/time/<file> in
the same way as other functions. The additional "sets" subdirectory has
been removed.

The raw set writer now aligns columns correctly.

The handling of segments in coordSet and sampledSet has been
fixed/completed. Segments mean that a coordinate set can represent a
number of contiguous lines, disconnected points, or some combination
thereof. This works in parallel; segments remain contiguous across
processor boundaries. Set writers now only need one write method, as the
previous "writeTracks" functionality is now handled by streamlines
providing the writer with the appropriate segment structure.

Coordinate sets and set writers now have a convenient programmatic
interface. To write a graph of A and B against some coordinate X, in
gnuplot format, we can call the following:

    setWriter::New("gnuplot")->write
    (
        directoryName,
        graphName,
        coordSet(true, "X", X), // <-- "true" indicates a contiguous
        "A",                    //     line, "false" would mean
        A,                      //     disconnected points
        "B",
        B
    );

This write function is variadic. It supports any number of
field-name-field pairs, and they can be of any primitive type.

Support for Jplot and Xmgrace formats has been removed. Raw, CSV,
Gnuplot, VTK and Ensight formats are all still available.

The old "graph" functionality has been removed from the code, with the
exception of the randomProcesses library and associated applications
(noise, DNSFoam and boxTurb). The intention is that these should also
eventually be converted to use the setWriters. For now, so that it is
clear that the "graph" functionality is not to be used elsewhere, it has
been moved into a subdirectory of the randomProcesses library.
2021-12-07 11:18:27 +00:00
a13826f1d6 Test-liquid: Separate data blocks for gnuplot 2021-10-29 13:09:29 +01:00
81f6cf91d0 liquidProperties: Added properties for NH3 (ammonia) 2021-10-29 12:51:46 +01:00
3ef3e96c3f Time: Added run-time selectable userTime option
replacing the virtual functions overridden in engineTime.

Now the userTime conversion function in Time is specified in system/controlDict
such that the solver as well as all pre- and post-processing tools also operate
correctly with the chosen user-time.

For example the user-time and rpm in the tutorials/combustion/XiEngineFoam/kivaTest case are
now specified in system/controlDict:

userTime
{
    type     engine;
    rpm      1500;
}

The default specification is real-time:

userTime
{
    type     real;
}

but this entry can be omitted as the real-time class is instantiated
automatically if the userTime entry is not present in system/controlDict.
2021-10-19 09:09:01 +01:00
3554f2140e Test-IOField: Updated and improved to use typeIOobject 2021-09-02 07:55:49 +01:00