1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "CALCULATOR.hxx"
24 #include "CALCULATOR_version.h"
27 #include <MEDCouplingFieldDoubleClient.hxx>
28 #include <MEDCouplingFieldDoubleServant.hxx>
29 #include <MEDCouplingMemArray.hxx>
30 #include <MEDCouplingMeshClient.hxx>
31 #include <MEDCouplingMeshServant.hxx>
37 \param orb Reference to CORBA ORB
38 \param poa Reference to Root POA
39 \param contId Parent SALOME container ID
40 \param instanceName Instance name of this engine
41 \param interfaceName Interface name of this engine
43 CALCULATOR::CALCULATOR( CORBA::ORB_ptr orb,
44 PortableServer::POA_ptr poa,
45 PortableServer::ObjectId* contId,
46 const char* instanceName,
47 const char* interfaceName )
48 : Engines_Component_i( orb, poa, contId, instanceName, interfaceName, true ),
49 _errorCode( CALCULATOR_ORB::RES_OK )
52 _id = _poa->activate_object( _thisObj );
58 CALCULATOR::~CALCULATOR()
63 \brief Get Euclidian norm of field
64 \param field Input field
65 \return Euclidian norm value
67 CORBA::Double CALCULATOR::norm2( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
69 beginService( "CALCULATOR::norm2" );
70 _errorCode = CALCULATOR_ORB::RES_OK;
72 if ( CORBA::is_nil( field ) )
74 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
78 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
79 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
81 CORBA::Double norme = 0.0;
89 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
92 endService( "CALCULATOR::norm2" );
97 \brief Get L2 norm of field
98 \param field Input field
101 CORBA::Double CALCULATOR::normL2( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
103 beginService( "CALCULATOR::normL2" );
104 _errorCode = CALCULATOR_ORB::RES_OK;
106 if ( CORBA::is_nil( field ) )
108 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
112 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
113 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
115 // Check that the source field is not on the nodes (a limitation of normL2)
116 if ( f1->getTypeOfField() == MEDCoupling::ON_NODES)
118 _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
122 CORBA::Double norme = 0.0;
126 norme = f1->normL2( 0 );
130 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
133 endService( "CALCULATOR::normL2" );
138 \brief Get max norm of field
139 \param field Input field
140 \return Max norm value
142 CORBA::Double CALCULATOR::normMax( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
144 beginService( "CALCULATOR::normMax" );
145 _errorCode = CALCULATOR_ORB::RES_OK;
147 if ( CORBA::is_nil( field ) )
149 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
153 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
154 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
156 CORBA::Double norme = 0.0;
160 norme = f1->normMax( 0 );
164 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
167 endService( "CALCULATOR::normMax" );
172 \brief Get L1 norm of field
173 \param field Input field
174 \return L1 norm value
176 CORBA::Double CALCULATOR::normL1( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
178 beginService( "CALCULATOR::normL1" );
179 _errorCode = CALCULATOR_ORB::RES_OK;
181 if ( CORBA::is_nil( field ) )
183 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
187 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
188 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
190 // Check that the source field is not on the nodes (a limitation of normL1)
191 if ( f1->getTypeOfField() == MEDCoupling::ON_NODES ) {
192 _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
196 CORBA::Double norme = 0.0;
199 norme = f1->normL1( 0 );
203 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
206 endService( "CALCULATOR::normL1" );
211 \brief Apply to each (scalar) field component the linear function x -> ax+b
212 \param field Input field
213 \param a First coefficient of linear function
214 \param b Second coefficient of linear function
215 \return Resulting field
217 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr CALCULATOR::applyLin( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field,
218 CORBA::Double a, CORBA::Double b )
220 beginService( "CALCULATOR::applyLin" );
221 _errorCode = CALCULATOR_ORB::RES_OK;
223 if ( CORBA::is_nil( field ) )
225 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
229 // Create a local field on the heap, because it has to remain after exiting the function
230 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
231 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
233 int nbOfCompo = f1->getArray()->getNumberOfComponents();
234 f1->getArray()->rearrange(1);
235 MEDCoupling::MEDCouplingFieldDoubleServant* NewField = NULL;
236 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR;
240 f1->applyLin( a, b, 0 );
241 f1->getArray()->rearrange( nbOfCompo );
242 // Create servant from f1, give it the property of c++ field (parameter true).
243 // This implies that when the client will release it's field, it will delete NewField,
245 NewField = new MEDCoupling::MEDCouplingFieldDoubleServant( f1 );
247 myFieldIOR = NewField->_this();
251 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
254 endService( "CALCULATOR::applyLin" );
259 \brief Sum two fields
260 \param field1 First input field
261 \param field2 Second input field
262 \return Resulting field
264 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr CALCULATOR::add( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field1,
265 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field2 )
267 beginService( "CALCULATOR::add" );
268 _errorCode = CALCULATOR_ORB::RES_OK;
270 if ( CORBA::is_nil( field1 ) || CORBA::is_nil( field2 ) )
272 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
276 // Create local fields from source corba fields
277 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f1 =
278 MEDCoupling::MEDCouplingFieldDoubleClient::New( field1 );
279 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f2 =
280 MEDCoupling::MEDCouplingFieldDoubleClient::New( field2 );
282 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fres;
286 f2->changeUnderlyingMesh( f1->getMesh(), 0, 1e-12 );
287 fres = (*f1) + (*f2);
289 catch ( INTERP_KERNEL::Exception )
291 _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
295 // Create CORBA field from c++ field fres; give property to servant (true).
296 MEDCoupling::MEDCouplingFieldDoubleServant* myFieldDoubleI = new MEDCoupling::MEDCouplingFieldDoubleServant( fres );
298 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr myFieldIOR = myFieldDoubleI->_this();
300 endService( "CALCULATOR::add" );
305 \brief Clone source field into four copies
306 \param field Input field
307 \param clone1 First resulting clone field
308 \param clone2 Second resulting clone field
309 \param clone3 Third resulting clone field
310 \param clone4 Fourth resulting clone field
312 void CALCULATOR::cloneField( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field,
313 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone1,
314 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone2,
315 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone3,
316 SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_out clone4 )
318 beginService( "CALCULATOR::cloneField" );
319 _errorCode = CALCULATOR_ORB::RES_OK;
321 if ( CORBA::is_nil( field ) )
323 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
327 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> f =
328 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
330 // Create four c++ fields on the heap by copying source field.
331 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc1 =
332 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
333 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc2 =
334 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
335 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc3 =
336 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
337 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fc4 =
338 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
340 // Initialize out references:
341 // Create CORBA clones from c++ fields - give property of c++ fields to servant (true)
342 MEDCoupling::MEDCouplingFieldDoubleServant* myClone1 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc1 );
343 MEDCoupling::MEDCouplingFieldDoubleServant* myClone2 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc2 );
344 MEDCoupling::MEDCouplingFieldDoubleServant* myClone3 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc3 );
345 MEDCoupling::MEDCouplingFieldDoubleServant* myClone4 = new MEDCoupling::MEDCouplingFieldDoubleServant( fc4 );
347 clone1 = myClone1->_this();
348 clone2 = myClone2->_this();
349 clone3 = myClone3->_this();
350 clone4 = myClone4->_this();
352 endService( "CALCULATOR::cloneField" );
356 \brief Print out the coordinates and field values to standard output
357 \param field Input field
359 void CALCULATOR::printField( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
361 beginService( "CALCULATOR::printField" );
362 _errorCode = CALCULATOR_ORB::RES_OK;
364 if ( CORBA::is_nil( field ) )
366 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
370 // Create a local field from source corba field.
371 // Use auto_ptr to perform automatic deletion after usage.
372 // The deletion of the client object will delete the remote corba object.
373 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> myField =
374 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
376 std::cout << myField->advancedRepr();
377 std::cout << std::endl;
378 std::cout << "Euclidian norm: " << myField->norm2() << std::endl;
379 std::cout << "Max norm: " << myField->normMax( 0 ) << std::endl;
380 std::cout << "------------------------------------------------------------------------" << std::endl << std::endl;
382 endService( "CALCULATOR::printField" );
386 \brief Calculate maximum relative difference of field with the previous one
387 \param field Input field
388 \return Convergence criterion value
390 CORBA::Double CALCULATOR::convergenceCriteria( SALOME_MED::MEDCouplingFieldDoubleCorbaInterface_ptr field )
392 beginService( "CALCULATOR::convergenceCriteria" );
393 _errorCode = CALCULATOR_ORB::RES_OK;
395 if ( CORBA::is_nil( field ) )
397 _errorCode = CALCULATOR_ORB::INVALID_FIELD;
402 static MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fold;
403 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fnew =
404 MEDCoupling::MEDCouplingFieldDoubleClient::New( field );
408 if ( (MEDCoupling::MEDCouplingFieldDouble*)fold == NULL )
410 // if old field is not set, set it and return 1
415 // if size of fields are not equal, return 1
416 // catch exception for non compatible fields
417 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingFieldDouble> fres;
420 fnew->changeUnderlyingMesh( fold->getMesh(), 0, 1e-12 );
421 fres = (*fnew) - (*fold);
422 criteria = fres->normMax( 0 );
424 catch ( INTERP_KERNEL::Exception )
426 _errorCode = CALCULATOR_ORB::NOT_COMPATIBLE;
432 _errorCode = CALCULATOR_ORB::EXCEPTION_RAISED;
435 endService( "CALCULATOR::convergenceCriteria" );
440 \brief Get last operation status
441 \return Last operation status: \c true if last operation succeded or \c false otherwise
443 CORBA::Boolean CALCULATOR::isDone()
445 return (_errorCode == CALCULATOR_ORB::RES_OK );
449 \brief Get last operation status
450 \return Last error code
452 CALCULATOR_ORB::ErrorCode CALCULATOR::getErrorCode()
458 \brief Get version information
459 \return Version of CALCULATOR engine
461 char* CALCULATOR::getVersion()
463 #if defined(CALCULATOR_DEVELOPMENT)
464 return CORBA::string_dup( CALCULATOR_VERSION_STR"dev" );
466 return CORBA::string_dup( CALCULATOR_VERSION_STR );
472 CALCULATORENGINE_EXPORT
473 PortableServer::ObjectId* CALCULATOREngine_factory( CORBA::ORB_ptr orb,
474 PortableServer::POA_ptr poa,
475 PortableServer::ObjectId* contId,
476 const char* instanceName,
477 const char* interfaceName )
479 CALCULATOR* myCALCULATOR = new CALCULATOR( orb, poa, contId, instanceName, interfaceName );
480 return myCALCULATOR->getId();