Analysis Solution

Analysis Modeler

Creating Analysis Features - Part3

Implement physics behavior

Use Case

Abstract

This paper accompanies the CAAAniNewfeatureOverview technical article. This tutorial explains how to instantiate the Aero-dynamicSet Feature's StartUp inside an Analysis Document and implement all required interfaces in order to integrate it inside analysis Infrastructure. This tutorial will focus on the implementation of the interface that allow to access to the physics associated to the aero dynamic solver file and the way to display an image.


What You Will Learn With This Use Case

This use case is intended to help you create an Aero-Dynamic Set Feature that will be fully integrated inside Analysis Infrastructure. For this, we will see the implementation of  CATISamExplicitation and CATICharacCollector interfaces.

[Top]

About Analysis Collector

The analysis Spec/Result approach generate inside the field model concrete classes and the feature have to manage the life cycle of these objects.

The AeroDynamic Set is created by derivation of the feature type SolutionSet. Il will use an implementation of CATISamExplicitation Method where you can insert your applicative software. This method generate inside the field model an Explicit Set that can be retrieved by using on the CATISamExplicit Interface the GetExplicitObject Method, and used to connect the physical data access by managing the CATAnalysisCharacCollector's. These Object are controlled by implementing a specific interface CATICharacCollector.

This use case focuses on the interfaces to implement on the feature. For programming with CATAnalysisCharacCollector object, see in the reference [2] the Field Model Chapter.

[Top]

The CAAAniAeroDTransition Use Case

CAAAniAeroDTransition is a use case of the CAAAnalysisInterfaces.edu framework that illustrates the CATIA Analysis infrastructure frameworks capabilities.

What Does CAAAniAeroDTransition Do

The goal of this use case is to implement the access to the physics associated to the set. One this will be done, we can display the velocity vector by using an image. For this, copy the file called SPMUserImageDefinition in the "reffiles" directory:

This file is the definition of some images based on the velocity physical type. For example, some iso-surface of the velocity display on the finite elements:

[Top]

How to Launch CAAAniAeroDTransition

To launch CAAAniAeroDTransition, you will need to set up the build time environment, then compile CAAAniAeroDTransition along with its prerequisites, set up the run time environment, and then execute the use case [1].

[Top]

Where to Find the CAAAniAeroDTransition Code

The CAAAniAeroDTransition use case is made of classes located in the CAAAniAeroDTransition.m module of the CAAAnalysisInterfaces.edu framework:

Windows InstallRootDirectory\CAAAnalysisInterfaces.edu\CAAAniAeroDTransition.m\
Unix InstallRootDirectory/CAAAnalysisInterfaces.edu/CAAAniAeroDTransition.m/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed.

It is made of two files CAAAniAeroDCharacCollector.cpp and CAAAniExplicitAeroSet.cpp and their associated header files. The module generated is a shared library.

[Top]

Step-by-Step

Implement a characcollector needs to perform the following steps:

[Top]

Defining a CharacCollector Implementation

...
CATImplementClass( CAAAniADCharacCollector,DataExtension,CATECharacCollector,AeroDynamicSet);
  
// Tie the implementation to its interface
// ---------------------------------------
#include "TIE_CATICharacCollector.h"
TIE_CATICharacCollector( CAAAniADCharacCollector);

//-----------------------------------------------------------------------------
// Implements CATICharacCollector::GetAvailablePhysicalTypes
//-----------------------------------------------------------------------------
HRESULT CAAAniADCharacCollector::GetAvailablePhysicalTypes (int                       &oNumber,
                                                            const CATSamPhysicalType *&oPhysicalTypes,
                                                            const CATString          *&oUnits)
{
  ...
}
...

Associated to this setup of code must be defined inside the Object Modeler Dictionary. See CAAAnalysisInterfaces.edu.dico file defined in CAAAnalysisInterfaces.edu\CNEXT\code\dictionary. This definition line associates the AeroDynamicSet implementation of CATICharacCollector interface inside the shared library libCAAAniAeroDTransition. The same remark can be done for implementing the CATISamExplicitation method. For the features, this definition is based on the late type of the feature.

AeroDynamicSet   CATICharacCollector  libCAAAniAeroDTransition
AeroDynamicSet   CATISamExplicitation libCAAAniAeroDTransition

We will see all the methods that need to be implemented. Note that the implementation is using a default Adapter CATECharacCollector that provides default implementation of methods to manage life cycle of the CATAnalysisCharacCollector. Some data members are added on this interface and one method Init that will initialize the output for this implementation.

HRESULT Init();
      
CATAnalysisExplicitModel *Model ;
CATAnalysisExplicitSet _Context ;
CATSamPhysicalType * _PhysicalTypes ;
CATString * _Units, *_Positions ;
CATSamCharacVersion *_Versions ;
int _NbPhysicalType;
...

[Top]

Initalizing the Data Members

As seen before, there is one physical data included in the file, a velocity. this physical data is associated by the physical type called "TRANSLATIONAL_VELOCITY". This data is a 3D vector of floats expressed at the nodes of the mesh. This will defined the version and the Position. The Field model set created by the feature is retrieved by using the CATISamExplicit. This set is considererd as a context for the creation of the CATAnalysisCharacCollector.

...
_NbPhysicalType = 0 ;
// Initialize the Context with the Explicit Object associated.
CATISamExplicit*  piExplicit=NULL;
hr = QueryInterface(IID_CATISamExplicit,(void**)&piExplicit);
if (piExplicit == NULL) return E_NOINTERFACE ;

hr= piExplicit->GetExplicitObject(_Context);
piExplicit-> Release(); 
piExplicit=NULL;
if (! SUCCEEDED(hr)) return E_FAIL ;
// Get a protection if the set is not yet in the field model.
if (_Context == NULL_exp) return hr;
// retrieve the Explcit Model
_Model = _Context.GetModel();
  ...
CATSamPhysicalType PhysType;
const CATAnalysisExplicitRulesData *pRulesData = NULL;
pRulesData = _Model->GetRulesData();
if (NULL == pRulesData) return E_FAIL ;

  hr = pRulesData-> GetPhysicalTypeNumber("TRANSLATIONAL_VELOCITY",PhysType);
  if (! SUCCEEDED(hr)) return E_FAIL ;

  _PhysicalTypes = new CATSamPhysicalType[1];
  _Units = new CATString[1];
  _Versions = new CATSamCharacVersion[1];
  _Positions = new CATString[1];

  _PhysicalTypes[0] = PhysType;
  _Units[0] = " ";
  CATSamMathType oMathematicalType;
  CATSamValue oValueType;
  int oMathematicalDimension,oRepeat ;
  
  //Retreive the version information inside the definition of the physical type.
  hr = aRulesData-> GetPhysicalTypeMathematicalInfo(PhysType,
                                                    oMathematicalType,
                                                    oValueType,
                                                    oMathematicalDimension,
                                                    oRepeat);
      
  _Versions[0].ValueType     = oValueType ;
  _Versions[0].MathType      = oMathematicalType ;
  _Versions[0].MathDimension = oMathematicalDimension ;
  _Versions[0].RefFrame      = CATSamRefFrameNone ;
  _Versions[0].Category      = CATSamValueNode ;

  _Positions[0] = "NODE" ;

  _NbPhysicalType = 1;
  ...

[Top]

Getting Available Physical Types

Now we will see how to implement the required method. The data accessibility will be controlled by calling the Init method and the following method just have to returned the data members.

...
HRESULT CAAAniADCharacCollector::GetAvailablePhysicalTypes (int & oNumber,
                                                            const CATSamPhysicalType* & oPhysicalTypes,
                                                            const CATString* & oUnits)
{
  oNumber = 0;
  if (!SUCCEEDED(Init())) return E_FAIL ;

  oNumber = _NbPhysicalType;
  if (_NbPhysicalType) oPhysicalTypes = _PhysicalTypes;
  if (_NbPhysicalType) oUnits = _Units;
  return S_OK;
}
...

[Top]

Getting the Available Version

Now we will see how to implement the required method. The data accessibility will be controlled by calling the Init method and the following method just have to returned the data members.

...
HRESULT CAAAniADCharacCollector::GetAvailableVersions (const CATSamPhysicalType iPhysicalType,
                                                       int & oNumber,
                                                       const CATSamCharacVersion* & oVersions)
{
  oNumber = 0;
  if (!SUCCEEDED(Init())) return E_FAIL ;
  oNumber = _NbPhysicalType ;
  if (_NbPhysicalType) oVersions = _Versions;
  return S_OK;
}
...

[Top]

Getting the Available Position

Now we will see how to implement the required method. The data accessibility will be controled by calling the Init method and the following method just have to returned the data members.

...
HRESULT CAAAniADCharacCollector::GetAvailablePositions (const CATSamPhysicalType iPhysicalType,
                                                        const CATSamCharacVersion & iVersion,
                                                        int & oNumber,
                                                        const CATString* & oPositions)
{
  oNumber = 0;
  if (!SUCCEEDED(Init())) return E_FAIL ;
  oNumber = _NbPhysicalType ;
  if (_NbPhysicalType) oPositions = _Positions;
  return S_OK;
}
      ...

[Top]

Getting/Setting Current Occurrences

This kind of solution may not support occurrences (Variable data according to a parameter). For this the GetNumberOfOccurrences Method will returned ZERO, and the Get and Set Current occurrences method will have no particular interest. But they have to be implemented.

The convention about the Number Of Occurrences and the index of the Current Occurrence is :

  GetNumberOfOccurrences GetCurrentOccurrence
Single Occurrence 0 -1
Multi Occurrence N (N > 0) [0,n-1]

-1 if the Characteristics are not linked to any particular Occurrences or to all of them.

 

...
//=============================================================================
HRESULT CAAAniADCharacCollector::GetNumberOfOccurrences (int & oNumberOfOccurrences)
{
  oNumberOfOccurrences = 0;
  return S_OK;
}
//=============================================================================
HRESULT CAAAniADCharacCollector::GetCurrentOccurrence (int & oOccurrenceNumber)
{
  oOccurrenceNumber = -1;
  return S_OK;
}
//=============================================================================
HRESULT CAAAniADCharacCollector::SetCurrentOccurrence (const int iOccurrenceNumber)
{	
  if (iOccurrenceNumber == -1) 
    return S_OK;
  else   
    return E_FAIL;
}
...

[Top]

Accessing the File for Results

The path name of the file is stored on the analysis set in an attribute as defined in the CATfct file. The attribute is called ExternalFile. To get access to the file use the standard PPR modeler tools:

...
  CATUnicodeString Path;

  CATISpecAttrAccess *piAccess = NULL;
  QueryInterface(IID_CATISpecAttrAccess,(void **)&piAccess);
  if (NULL != Access)
  {
    CATILinkableObject *piLink = piAccess ->
    GetExternalObject("ExternalFile");
    if (Link)
    {
      CATDocument * pDoc = piLink -> GetDocument ();
      if (NULL != pDoc) CATSamDocumentTools::GetFileStorage(pDoc,Path);
      piLink -> Release();
    }
    piAccess -> Release(); piAccess = NULL;
  }
  ...

Once the Path value is set; you can manipulate the file as usually, for example Open it:

...
  FILE * stream = fopen (Path.ConvertToChar(),"r");
  ...

[Top]

GetCharacCollector

This is the most important method. Its goal it to returned the CATAnalysisCharacCollector Object that will manage the results access. The first step is to control if this object exists. For this use the FindCharacCollector method on the Field model context. If the Collector exists, Increase its Life Counter with an AddRef and return it.

  ...
  _Context.FindCharacCollector(iPhysicalType, iVersion, iPosition, _CurrentOccurence, CharacCollector) ;
 if (CharacCollector)
 {
    CharacCollector -> AddRef();
    oCharacCollector = CharacCollector;
    return S_OK;
  }
  ...

If It does not exists, allocate a new one and fill its data. For this a sequence of method to call well defined.

  ...
  CharacCollector = new CATAnalysisCharacCollector;
  CharacCollector -> SetContext(_Context,TRUE);

  _Model->GetPhysicalTypeUnit(iPhysicalType, CharUnit) ;
  CharacCollector->SetDefinition(iPhysicalType, CharUnit, iVersion, iPosition, _CurrentOccurence);

  _Model -> GetNbNodes(_Context,NbEntities);
  CharacCollector->SetNbEntities(NbEntities) ;

  if (iEntityFlags == NULL)
  {
    EntityFlags = new char[NbEntities] ; // array of EntityFlags
    memset(EntityFlags, 1, NbEntities) ; // set them all == 1
    CharacCollector->SetEntities(EntityFlags) ;
    // A pointer to the table of flag of the entities.
  }
  else
  CharacCollector->SetEntities(iEntityFlags);

  int nbRepeat[1]={1};
  Dimensions = new CATSamDimension (1, 1, 1, nbRepeat, CATSamValueReal, CATSamMathTypeVector, 3) ;
  CharacCollector -> SetDimensions(1, Dimensions, DimensionPointers) ;
  delete Dimensions ;

  float *Fvalues;
  Fvalues = new float [3*NbEntities];
  Values = _Fvalues;
  for( i=0;i<3*NbEntities;i++)
  {
    _Fvalues[i]=(float)(i);
  }

  CharacCollector -> SetValues(3*NbEntities,3*sizeof(float)*NbEntities,Values, ValuePointers) ;
  delete [] _Fvalues;

  CharacCollector -> AddRef();
  oCharacCollector = CharacCollector;

  ...

[Top]

Implementing CATISamExplicitation

This is done in the CAAAniExplicitAeroSet.cpp file. This is the minimum implementation that is required to manage the Life Cycle of the explicit model object associated to this set.The intent is to create a new version of the field model object, and to ask to the system to remove the previous one (and all associated characCollectors). The system will also manage the undo/redo.

...
CATBeginImplementClass(CAAAniExplicitAeroSet,CacheExtension,CATISamExplicitation,STRUCTURAL_AeroDynamicSet);
CATEndImplementClass(CAAAniExplicitAeroSet);

CATImplementBOA (CATISamExplicitation, CAAAniExplicitAeroSet);

//-----------------------------------------------------------------------------
// Implements CATISamExplicitation::TranslateToFieldModel
//-----------------------------------------------------------------------------
HRESULT CAAAniExplicitAeroSet::TranslateToFieldModel(CATISpecObject* iFeatToTranslate, 
        CATISamAnalysisModel* iFEMModel, CATAnalysisExplicitListUsr& iOldExplObjects, CATAnalysisExplicitListUsr& oNewExplObjects)
{

HRESULT HR = S_OK ;
CATISamExplicit *piExplicit = NULL ;
CATAnalysisExplicitChild Child;
CATAnalysisExplicitSet OldSet, NewSet ;
CATAnalysisExplicitList Children ;
CATAnalysisExplicitListUsr ContainingData ;
CATAnalysisExplicitModel *ExplicitModel = NULL ;
CATSamPhysicalType PhysicalType;
CATISamAnalysisSet_var spSet(iFeatToTranslate);

if(!iFeatToTranslate) goto error;

// Retrieve CATISamExplicit interface for GetContainingData and UpdateExplicitList methods
//-----------------------------------------------------------------------------
iFeatToTranslate -> QueryInterface (IID_CATISamExplicit,(void**)& piExplicit);
if (piExplicit == NULL) goto error;

// Retrieve physcal type of the previous version 
OldSet = *(iOldExplObjects.First()) ;
if (OldSet == NULL_exp) goto error;
ExplicitModel = OldSet.GetModel();
if (ExplicitModel == NULL) goto error;

OldSet.GetPhysicalType(PhysicalType);

if (!SUCCEEDED(ContainingData.CreateList(ExplicitModel))) goto error;
if (!SUCCEEDED(piExplicit -> GetContainingData(iOldExplObjects, ContainingData))) goto error;

if (!SUCCEEDED(NewSet.CreateSet(ExplicitModel,PhysicalType))) goto error;

oNewExplObjects += NewSet;

OldSet.GetChildrenList(Children);
Child = *(Children.First());
while ( Child != NULL_exp )
{
CATSamDataType DataType = Child.GetType();
if (DataType == CATSamDataTypeSet || DataType == CATSamDataTypeEntity) NewSet.AddChild(Child);
Child = *(Children.Next()) ;
}

if (!SUCCEEDED(piExplicit -> UpdateExplicitList(iOldExplObjects, ContainingData, oNewExplObjects))) goto error;

piExplicit -> Release(); piExplicit = NULL;
if (ContainingData != NULL_exp) ContainingData.Delete() ;

cout << "Insert here the applicative software you need for updating the feature "<< endl;

return S_OK;

error:
if (piExplicit) piExplicit -> Release(); piExplicit = NULL;
if (ContainingData != NULL_exp) ContainingData.Delete() ;
return E_FAIL;
}
... 

[Top]

In Short

This tutorial has demonstrated how to integrate the Aero-Dynamic Set Feature's Set into the feature modeler standards and retrieve some physics' for visualization.

[Top]


References

[1] Feature Modeler documentation
[2] Analysis Modeler Overview
[3] Integrate new Feature inside Analysis.
[Top]

History

Version: 1 [Sep 2005] Document Reviewed
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.