Please contact MotionView Support to obtain information about an example.
The Model API consists mainly of a group of mrf functions that pass results data from the solver to the result API. Most of the functions require a pair of Open and Close functions.
Register functions should accompany the history data that can be animated, such as the position/orientation of rigid bodies or the modal participation factors of flexible bodies. If a type is registered as an animation object such as rigid body or flexible body, its component must be created using the function,
int mrfCreateElement(const char *element_name, const int element_id);
instead of its "ID-less" version:
int mrfCreateElement(const char *element_name, const int element_id)
This is because the result data and the model object are linked through IDs.
If a type is registered for rigid body animation, the first few components of that type must be specified in accordance with the order defined in the header file. The orientations of rigid bodies are defined by Euler parameters.
The following is the header file that contains a list of Result API functions. The names of the functions are self-explanatory.
int mrfOpenResult(const float start_time,const float end_time, int num_time_steps);
int mrfCloseResult(int flag=0);
int mrfOpenResultHeader(const char *mrf_fliename, const char *abf_filename, const char *tab_filename);
int mrfCloseResultHeader(void);
int mrfCreateDataType(const char *type_name);
int mrfOpenDataTypeByIndex(const int type_idx);
int mrfOpenDataTypeByName(const char* type_name);
int mrfRegisterForTabulatedOutput(void);
int mrfRegisterForRigidBodyAnimation(void);
/* x,y,z,e0,e1,e2,e3
*/
int mrfRegisterNoGroundBody(void);
/* by default, the api assumes that the first rigid body is the ground body
and its time history is discarded because they are time-invariant.
If in your model there is no ground body or you do not want to make the
ground body the first one in the rigid body element list, then you have
to call this function.
*/
int mrfRegisterForModalFlexBodyAnimation(const int num_modal_coords);
/* x,y,z,e0,e1,e2,e3
all followed by modal coordinates q1, q2, ....
*/
int mrfRegisterForAbsNodalFlexBodyAnimation(const int num_nodes);
/* x1,x2,...,xn,y1,y2,...,yn,z1,z2,...,zn where n=num_nodes */
int mrfCloseDataType(void);
int mrfCreateComponent(const char *component_name);
int mrfCreateElement(const char *element_name);
int mrfCreateElement(const char *element_name, const int element_id);
int mrfOpenTimeStep(const float time);
int mrfCloseTimeStep(void);
int mrfMoveToElementByIndex(const int element_idx);
int mrfMoveToElementByName(const char *element_name);
int mrfPutComponentData(const float *component_data);
The following is a working example and comments about the usage of the API functions in a simple solver.
Example solver code with the API Functions in place:
int main(int argc, char *argv[])
{
////////////// Read Model /////////////////////////////////////
model_data model;
ReadModel(argc, argv, &model);
////////////// Populate Header /////////////////////////////////////
mrfOpenResult(0.0f, (float)model.tend, model.num_steps);
mrfOpenResultHeader("balls.mrf", "balls.abf", "balls.tab");
mrfCreateDataType("Rigid Body");
mrfCreateDataType("System");
mrfOpenDataTypeByName("Rigid Body");
mrfRegisterForRigidBodyAnimation();
mrfRegisterNoGroundBody();
mrfRegisterForTabulatedOutput();
mrfCreateComponent("x");
mrfCreateComponent("y");
mrfCreateComponent("z");
mrfCreateComponent("e0");
mrfCreateComponent("e1");
mrfCreateComponent("e2");
mrfCreateComponent("e3");
mrfCreateComponent("xd");
mrfCreateComponent("yd");
mrfCreateComponent("zd");
mrfCreateComponent("xdd");
mrfCreateComponent("ydd");
mrfCreateComponent("zdd");
mrfCloseDataType();
mrfOpenDataTypeByName("System");
mrfRegisterForTabulatedOutput();
mrfCreateComponent("Potential");
mrfCreateComponent("Kinetic");
mrfCreateComponent("Total");
mrfCloseDataType();
int body_idx;
mrfOpenDataTypeByIndex(0);
for (body_idx=0;body_idx<model.num_balls;body_idx++)
char name[20];
sprintf(name,"Ball %i",body_idx+30102);
mrfCreateElement(name, body_idx+30102);
}
mrfCloseDataType();
mrfOpenDataTypeByIndex(1);
mrfCreateElement("Energy");
mrfCloseDataType();
mrfCloseResultHeader();
double *psi = new double [model.num_balls];
double *dis = new double [model.num_balls];
for (body_idx=0;body_idx<model.num_balls;body_idx++)
dis[body_idx] = sqrt(model.x[body_idx]*model.x[body_idx]+
model.y[body_idx]*model.y[body_idx]);
psi[body_idx] = asin(model.y[body_idx]/dis[body_idx]);
}
double step_size = model.tend/model.num_steps;
double time=0;
float q[13];
float energy[3];
for (int time_idx=0;time_idx<=model.num_steps;time_idx++,time+=step_size)
memset(energy,0,3*sizeof(float));
printf(" Time = %13.6E\n",time);
mrfOpenTimeStep((float)time);
mrfOpenDataTypeByIndex(0);
for (body_idx=0;body_idx<model.num_balls;body_idx++)
mrfMoveToElementByIndex(body_idx);
q[0] = (float)(dis[body_idx]*cos(2*pi*model.freq*time+psi[body_idx]));
q[1] = (float)(dis[body_idx]*sin(2*pi*model.freq*time+psi[body_idx]));
q[2] = (float)(model.z[body_idx]);
q[3] = 1;
q[4] = 0;
q[5] = 0;
q[6] = 0;
q[7] = (float)(-dis[body_idx]*sin(2*pi*model.freq*time+
psi[body_idx])*2*pi*model.freq);
q[8] = (float)( dis[body_idx]*cos(2*pi*model.freq*time+
psi[body_idx])*2*pi*model.freq);
q[9] = 0;
energy[0] += 0.5f*(q[3]*q[3] + q[4]*q[4] + q[5]*q[5]);
energy[1] += 9.8f*q[2];
q[10] = (float)(-dis[body_idx]*cos(2*pi*model.freq*time+
psi[body_idx])*2*pi*model.freq*2*pi*model.freq);
q[11] = (float)(-dis[body_idx]*sin(2*pi*model.freq*time+
psi[body_idx])*2*pi*model.freq*2*pi*model.freq);
q[12] = 0;
mrfPutComponentData(q);
}
mrfCloseDataType();
mrfOpenDataTypeByIndex(1);
mrfMoveToElementByIndex(0);
energy[2] = energy[0] + energy[1];
mrfPutComponentData(energy);
mrfCloseDataType();
mrfCloseTimeStep();
}
mrfCloseResult();
return 0;
}