1 //                                               -*- C++ -*-
2 /**
3  *  @brief A class which implements the CompositeProcess process
4  *
5  *  Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6  *
7  *  This library is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "openturns/CompositeProcess.hxx"
23 #include "openturns/PersistentObjectFactory.hxx"
24 #include "openturns/Exception.hxx"
25 #include "openturns/WhiteNoise.hxx"
26 #include "openturns/SymbolicFunction.hxx"
27 #include "openturns/ValueFunction.hxx"
28 
29 BEGIN_NAMESPACE_OPENTURNS
30 
31 CLASSNAMEINIT(CompositeProcess)
32 
33 static const Factory<CompositeProcess> Factory_CompositeProcess;
34 
CompositeProcess()35 CompositeProcess::CompositeProcess()
36   : ProcessImplementation()
37   , function_(ValueFunction(SymbolicFunction("x", "x^2"), WhiteNoise().getMesh()))
38   , antecedent_(new WhiteNoise())
39 {
40   // Set the mesh
41   setMesh(function_.getOutputMesh());
42 }
43 
44 /* Standard constructor */
CompositeProcess(const FieldFunction & function,const Process & antecedent)45 CompositeProcess::CompositeProcess(const FieldFunction & function,
46                                    const Process & antecedent)
47   : ProcessImplementation()
48   , function_(function)
49   , antecedent_(antecedent)
50 {
51   if (function.getInputDimension() != antecedent_.getOutputDimension())
52     throw InvalidArgumentException(HERE) << "Error: trying to build a CompositeProcess from a Process and a FieldFunction with incompatible dimensions "
53                                          << "here Process dimension=" << antecedent_.getOutputDimension()
54                                          << " and FieldFunction input dimension=" << function.getInputDimension();
55   if (function.getInputMesh().getDimension() != antecedent_.getInputDimension())
56     throw InvalidArgumentException(HERE) << "Error: trying to build a CompositeProcess from a Process and a FieldFunction with incompatible mesh dimensions "
57                                          << "here Process mesh dimension=" << antecedent_.getInputDimension()
58                                          << " and FieldFunction mesh dimension=" << function.getInputMesh().getDimension();
59   setMesh(function.getOutputMesh());
60   setOutputDimension(function.getOutputDimension());
61   setDescription(function.getOutputDescription());
62 }
63 
64 /* Virtual constructor */
clone() const65 CompositeProcess * CompositeProcess::clone() const
66 {
67   return new CompositeProcess(*this);
68 }
69 
70 /* String converter */
__repr__() const71 String CompositeProcess::__repr__() const
72 {
73   OSS oss(true);
74   oss << "class=" << CompositeProcess::GetClassName()
75       << " function=" << function_.__repr__()
76       << " antecedent=" << antecedent_.getImplementation()->__repr__();
77   return oss;
78 }
79 
__str__(const String &) const80 String CompositeProcess::__str__(const String & ) const
81 {
82   OSS oss(false);
83   oss << getClassName() << "(" << function_.__str__()
84       << "(" << antecedent_.__str__() << ")";
85   return oss;
86 }
87 
88 /* Is the underlying a composite process ? */
isComposite() const89 Bool CompositeProcess::isComposite() const
90 {
91   return true;
92 }
93 
94 /* Antecedent accessor */
getAntecedent() const95 Process CompositeProcess::getAntecedent() const
96 {
97   return antecedent_;
98 }
99 
100 /* Function accessor */
getFunction() const101 FieldFunction CompositeProcess::getFunction() const
102 {
103   return function_;
104 }
105 
106 /* Realization accessor */
getRealization() const107 Field CompositeProcess::getRealization() const
108 {
109   Sample values(function_(antecedent_.getRealization().getValues()));
110   values.setDescription(getDescription());
111   Field result(function_.getOutputMesh(), values);
112   return result;
113 }
114 
115 /* Compute the next steps of a random walk */
getFuture(const UnsignedInteger stepNumber) const116 TimeSeries CompositeProcess::getFuture(const UnsignedInteger stepNumber) const
117 {
118   /* TimeGrid of the process */
119   RegularGrid timeGrid;
120   try
121   {
122     timeGrid = getTimeGrid();
123   }
124   catch (const InvalidArgumentException &)
125   {
126     throw InternalException(HERE) << "Error: can extend the realization of a process only if defined on a regular grid.";
127   }
128   if (stepNumber == 0) throw InvalidArgumentException(HERE) << "Error: the number of future steps must be positive.";
129   /* TimeGrid associated with the possible future */
130   const Scalar timeStep = timeGrid.getStep();
131   const RegularGrid futurTimeGrid(timeGrid.getEnd(), timeStep, stepNumber);
132   FieldFunction function(function_);
133   if (!function.isActingPointwise())
134     throw NotDefinedException(HERE) << "Error: can only ask future of a process with a point-wise function";
135   function.setInputMesh(futurTimeGrid);
136   return TimeSeries(futurTimeGrid, function(antecedent_.getFuture(stepNumber).getValues()));
137 }
138 
139 /* Get the marginal random vector corresponding to indices components */
getMarginal(const Indices & indices) const140 Process CompositeProcess::getMarginal(const Indices & indices) const
141 {
142   return new CompositeProcess(function_.getMarginal(indices), antecedent_.getMarginal(indices));
143 }
144 
145 /* Method save() stores the object through the StorageManager */
save(Advocate & adv) const146 void CompositeProcess::save(Advocate & adv) const
147 {
148   ProcessImplementation::save(adv);
149   adv.saveAttribute( "function_", function_ );
150   adv.saveAttribute( "antecedent_", antecedent_ );
151 }
152 
153 /* Method load() reloads the object from the StorageManager */
load(Advocate & adv)154 void CompositeProcess::load(Advocate & adv)
155 {
156   ProcessImplementation::load(adv);
157   adv.loadAttribute( "function_", function_ );
158   adv.loadAttribute( "antecedent_", antecedent_ );
159 }
160 
161 END_NAMESPACE_OPENTURNS
162