Topic: Recreated: 'stand-alone' executable

I apoligize for accidentally removing the topic created by user umi.
There was something strange going on with the post approval, it showed duplicates, and approving them didn't take, so i thought I could remove them safely, but It seems that cleared the whole thread.

Luckily, I had the old thread in the browser cache, so i'll repost it here;

umi wrote:

Does anyone of you have a 'stand-alone' file for some simple sm problem (e.g. a cube discretized by a few elements with a distributed load and 1 NonLinearStatic load step)? I'm looking for something like src/main/main.C, but which does not read an input file and rather contains all .in-settings and definitions directly in the C++ code.

thanks for any help! smile

u.

Mikael wrote:

Short answer; No.
There is only a text-input implemented in OOFEM yet, so there is no good way to set up a problem without an input file.

May I ask what do you intend to do?

umi wrote:

I was planning to link oofem with some other library in order to set up a multi scale model. reading the mesh from an external file makes completely sense, but interfacing the two models via text files would be somewhat cumbersome and slow as compared to (parallel) copy of data in the computer memory.

So far I was thinking of replacing all input-"dependencies" in InstanciateProblem by hard coded values/instances/... Does anyone have attempted something like this with oofem? Does that make any sense?

Mikael wrote:

The input record don't explcitly depend on txt input, but it is the only one implemented.
I would recommend that you see how I imlemented multiscale / FE² in FE2FluidMaterial:
http://www.oofem.org/websvn/filedetails … material.C
I still use the txt input, since its the most reasonable way to send this information.

I suppose the issue you look at is that the subscale problems are randomly generated. Is this correct?
In situations like this, where you actually perform some of the post-processing live (which could happen with adaptivity, random subscales for statistical meassures, and possible other things), there are three options as i see it.

  1. Code up something yourself which basically creates a domain with everything set appropriately (which is what you were looking for)

  2. Write an input file and just call the initializing function to create a domain

  3. Imlement some in-code input records, without writing any files, and (again) call the initializing function to create the domain

If you opt to do alternative 1, you will probably end up missing initializing something, which could lead to all kinds of bugs.
I would say that alternative 2 isn't as bad as you might think. First, it does give you a complete subscale problem which you could check by itself so it behaves correctly. I dont think there is a huge overhead with writing files, but it does clutter things up with possible very many files, and other possible bothers that you encounter with file IO.

With alternative 3 one would first need to implement a new non-text based class for the DataReader and InputRecord class. (right now the only implementations are OOFEMTXTDataReader and OOFEMTXTInputRecord. Something like "DynamicDataReader" to which you can add entries manually (basically a linked list of DynamicInputRecords).
Since something like this has been requested before, I think I will implement such a DataReader (perhaps within a week or two).

Re: Recreated: 'stand-alone' executable

Thanks Mikael, I think option 3 would work great for me and also would be consistent with the oofem architecture smile
I'd be happy to do a little bit of testing with the new DataReader!

Re: Recreated: 'stand-alone' executable

I will see to creating those classes. Perhaps this weekend or the following.

Re: Recreated: 'stand-alone' executable

I've added DynamicDataReader + DynamicInputRecord for you to try out.
Note that the implementation is simplistic, so you'll need to add the records in the same order as in the text-input files (each line is basically an input record)
If you need to do any changes that i missed, upload a patch and i'll review it and possibly (probably) commit it.

Naturally, you'll need to use the SVN-version for these new classes.

Re: Recreated: 'stand-alone' executable

Thanks Mikael. I checked out the svn version and found your files. I don't know exactly where to start though... could you help me with a main file where you instanciated the DynamicsDataReader. I think that would clarify the required steps a lot to me ...

Re: Recreated: 'stand-alone' executable

It is not instanciated anywhere so far (i.e. completely unused).

I envision it being used as the following

#include "dynamicinputrecord.h"
#include "dynamicdatareader.h"

...

    DynamicDataReader myData;
    DynamicInputRecord *myInput;

    // First the outfile
    myInput = new DynamicInputRecord();
    myInput->setField("outputfile.out", IFT_EngngModel_outfile);
    myData.insertInputRecord(myInput);

    // Then the job description
    myInput = new DynamicInputRecord();
    myInput->setField("My custom problem", IFT_EngngModel_probdescription);
    myData.insertInputRecord(myInput);

    // Then the problem name and all those settings
    myInput = new DynamicInputRecord();
    myInput->setRecordKeywordField("LinearStatic");
    myInput->setField(0, IFT_LinearStatic_lstype);
    myInput->setField(0, IFT_LinearStatic_smtype);
    myInput->setField(50, IFT_EngngModel_nsteps);
    myData.insertInputRecord(myInput);

    // Then the domain record, followed by nodes, elements, materials, etc. exactly in the order done in the normal input files.
    ....

    EngngModel *em = InstanciateProblem(&myData, _processor, 0);
    myData.finish();

Re: Recreated: 'stand-alone' executable

Hello Umi,

there exists Python interface for Oofem, which could be interesting for your problem, see MuPIF page (http://www.oofem.org/wiki/doku.php?id=mupif:mupif0 for examples

Jan

Re: Recreated: 'stand-alone' executable

Is there any DynamicInputRecord() equivalent for output? Maybe a DynamicOutputRecord() so we could cache results data in memory and post process instead of opening and reading from file? Thanks.

Re: Recreated: 'stand-alone' executable

I'm not sure what such a record would store.
It seems like what you are asking for is essentially just the Domain object. You can query whatever you want from it (elements, nodes) so doing some in-code post-processing is certainly possible.

It is pretty much what I do for my FE^2 simulations, where a local FE-problem is solved in every gausspoint, with it's results homogenized for the macro-scale.

Re: Recreated: 'stand-alone' executable

That makes sense. Do you have a working example using DynamicDataReader()? The constants in the example above do not seem correct. Maybe that is an outdated example? Thanks.

Re: Recreated: 'stand-alone' executable

Unfortunately I don't have any complete example (this certainly should be done, but I just haven't had the time).

I did 2 changes which improved code overall, and that's related to the first 2 lines in the input files, which are a bit different from the rest (they aren't really input records, just strings).

So it should be something like this

#include "dynamicinputrecord.h"
#include "dynamicdatareader.h"

...

    DynamicDataReader myData;
    DynamicInputRecord *myInput;

    // First the outfile
    myData.setOutputFileName("outputfile.out");

    // Then the job description
    myData.setDescription("My custom problem");

    // Then the problem name and all those settings
    myInput = new DynamicInputRecord();
    myInput->setRecordKeywordField("LinearStatic");
    myInput->setField(0, IFT_LinearStatic_lstype);
    myInput->setField(0, IFT_LinearStatic_smtype);
    myInput->setField(50, IFT_EngngModel_nsteps);
    myData.insertInputRecord(myInput);

    // Then the domain record, followed by nodes, elements, materials, etc. exactly in the order done in the normal input files.
    ....

    EngngModel *em = InstanciateProblem(&myData, _processor, 0);
    myData.finish();

Re: Recreated: 'stand-alone' executable

It looks like "IFT_LinearStatic_lstype"above should be "_IFT_EngngModel_lstype"? Also, I'm not clear how to continue with the domain definition, would it be like this....?

myInput = new DynamicInputRecord();
myInput->setRecordKeywordField("domain", 1);   
myInput->setField("_2dTrussMode", _IFT_Domain_type);


Once I get the field types figured out this seems like a reasonable way to interface with the lib. Eventually it would be nice to have a document with all the constants like "_IFT_EngngModel_lstype" organized for easy look-up. Maybe I'll create one someday.

Re: Recreated: 'stand-alone' executable

Yes, your lstype fix should be correct, I had forgotten I had changed that. Another thing I missed is that it is preferable to use the _IFT macro even for the record keyword, like so

    myInput->setRecordKeywordField(_IFT_LinearStatic_Name);

You are right to be unsure about the domain type. It's one line that isn't very well defined in the input file format as it is.
I think the code you wrote should work (even though my own comment in domain.h indicates that it might break). Please try it out and let me know if there seems to be problems.
I have plans to completely remove this line from the input format eventually (not yet, since it'll break backwards compatibility with older input files).


As for the _IFT_***_*** fields, these change all the time, and it is hard to keep a list up-to-date. Each component defines these variables at the top of the header files, forcing libraries that use these to directly include the header of the component they want to use. This way you can't miss if some function removes or renames some keywords. You are able to see all these keywords (hopefully with description) in the doxygen documentation for each component you wish to use.

However, we do want to also automatically produce an element/material input documentation based on these fields by having a script scan through all header files and collect the information. See this thread for more information:
http://www.oofem.org/forum/viewtopic.php?id=1384

Re: Recreated: 'stand-alone' executable

The example above crashes on 

myData.setOutputFileName("outputfile.out");

should this be working?

Note: I'm now using the oofem2.2 instead of the git repo, due to the static lib problem in my other post.
Thanks for your help.

Re: Recreated: 'stand-alone' executable

I can't see why it would crash on that function, its very innocent.
There has been modifications since version 2.2 though.  I think the 2.2 version wasn't sufficient. You could *write* the input files to text with it, but I dont think

EngngModel *em = InstanciateProblem(&myData, _processor, 0);
 

will work.

I think the best option is to try and get dynamic linking working on windows, which will take some work (see the other thread).

Re: Recreated: 'stand-alone' executable

This was my fault, while switching between versions of oofem I ended up using the wrong header files. But, in this process I did discover that oofem 2.2 is missing some functions related to DynamicDataReader. I think I will build my project as one big executable  for now while I experiment and eventually work on getting the dynamic linking to function on windows.

Re: Recreated: 'stand-alone' executable

Mikael, I think I'm close to getting a simple model to solve using DynamicDataReader. I'm trying to copy this model
http://www.oofem.org/resources/doc/oofe … ode49.html
Can you see any reason this is not working?
If fails at EngngModel *em = InstanciateProblem(&myData, _processor, 0);
I'm using the git branch
Thanks.


#include "linearstatic.h"
#include "simplecrosssection.h"
#include "isolinearelasticmaterial.h"
#include "truss2d.h"
#include "generalboundarycondition.h"

#include "dynamicinputrecord.h"
#include "dynamicdatareader.h"
#include "beam2d.h"
#include "constantsurfaceload.h"
#include "nodalload.h"
#include "structtemperatureload.h"
#include "peakfunction.h"

using namespace oofem;


DynamicInputRecord* CreateNode(int i, const FloatArray& coord, const IntArray& bcs, const IntArray& loads = IntArray(0))
{
     DynamicInputRecord* result = new DynamicInputRecord();
     result->setRecordKeywordField(_IFT_Node_Name, i);
     result->setField(coord, _IFT_Node_coords);
     result->setField(bcs, _IFT_DofManager_bc);
     result->setField(loads, _IFT_DofManager_load);
     return result;
}


DynamicInputRecord* CreateBeam(int i, const IntArray& nodes, int mat, int cs)
{
     DynamicInputRecord* result = new DynamicInputRecord();
     result->setRecordKeywordField(_IFT_Beam2d_Name, i);
     result->setField(nodes, _IFT_Element_nodes);
     result->setField(mat, _IFT_Element_mat);
     result->setField(cs, _IFT_Element_crosssect);
     return result;
}


int main(int argc, char *argv[])
{    
    DynamicDataReader myData;
    DynamicInputRecord *myInput;

    //Output File
    myData.setOutputFileName("outputfile.out");    

    //Description
    myData.setDescription("My custom problem");

    //Problem
    myInput = new DynamicInputRecord();
    myInput->setRecordKeywordField(_IFT_LinearStatic_Name, 1);
    myInput->setField(0, _IFT_EngngModel_lstype);
    myInput->setField(0, _IFT_EngngModel_smtype);
    myInput->setField(3, _IFT_EngngModel_nsteps);
    myData.insertInputRecord(DataReader::InputRecordType::IR_emodelRec, myInput);

    //Domain
    myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField("domain", 1);
     myInput->setField("2dBeam", _IFT_Domain_type);
     myData.insertInputRecord(DataReader::InputRecordType::IR_domainRec, myInput);

     //Output
     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_OutputManager_name, 1);
     myInput->setField(_IFT_OutputManager_tstepall);
     myInput->setField(_IFT_OutputManager_dofmanall);
     myInput->setField(_IFT_OutputManager_elementall);
     myData.insertInputRecord(DataReader::InputRecordType::IR_outManRec, myInput);

     //Components size record
     myInput = new DynamicInputRecord();
     myInput->setField(6, _IFT_Domain_ndofman);
     myInput->setField(5, _IFT_Domain_nelem);
     myInput->setField(1, _IFT_Domain_ncrosssect);
     myInput->setField(1, _IFT_Domain_nmat);
     myInput->setField(5, _IFT_Domain_nbc);
     myInput->setField(0, _IFT_Domain_nic);
     myInput->setField(3, _IFT_Domain_nloadtimefunct);
     myData.insertInputRecord(DataReader::InputRecordType::IR_domainCompRec, myInput);

     //Nodes
     FloatArray coord(3);
     IntArray bcs(3);
     IntArray loads(1);

     coord.setValues(0.0, 0.0, 0.0);    
     bcs.setValues(0, 1, 0);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(1, coord, bcs));

     coord.setValues(2.4, 0.0, 0.0);    
     bcs.setValues(0, 0, 0);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(2,coord, bcs));

     coord.setValues(3.8, 0.0, 0.0);    
     bcs.setValues(0, 0, 1);
     loads.setValues(4);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(3, coord, bcs));

     coord.setValues(5.8, 0.0, 1.5);    
     bcs.setValues(0, 0, 0);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(4, coord, bcs, loads));

     coord.setValues(7.8, 0.0, 3.0);    
     bcs.setValues(0, 1, 0);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(5, coord, bcs));

     coord.setValues(2.4, 0.0, 3.0);    
     bcs.setValues(1, 1, 2);
     myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(6, coord, bcs));

     //Elements
     IntArray nodes(2);    
     DynamicInputRecord* beam;

     nodes.setValues(2,1,2);
     beam = CreateBeam(1, nodes, 1, 1);    
     loads.setValues(2,3,1);
     beam->setField(loads, _IFT_Element_boundaryload);
     loads.setValues(2,1,5);
     beam->setField(loads, _IFT_Element_bodyload);
     myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);

     nodes.setValues(2,2,3);
     beam = CreateBeam(2, nodes, 1, 1);    
     beam->setField(6, _IFT_Beam2d_dofstocondense);    
     beam->setField(loads, _IFT_Element_bodyload);
     myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);

     nodes.setValues(2,3,4);
     beam = CreateBeam(3, nodes, 1, 1);    
     beam->setField(3, _IFT_Beam2d_dofstocondense);
     myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);
    
     nodes.setValues(2,4,5);
     beam = CreateBeam(4, nodes, 1, 1);   
     myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);

     nodes.setValues(2,6,2);
     beam = CreateBeam(5, nodes, 1, 1);    
     beam->setField(6, _IFT_Beam2d_dofstocondense);
     myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);

     //CrossSection
     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_SimpleCrossSection_Name, 1);
     myInput->setField(0.162, _IFT_SimpleCrossSection_area);
     myInput->setField(0.0039366, _IFT_SimpleCrossSection_iy);
     myInput->setField(1.e18, _IFT_SimpleCrossSection_shearcoeff);
     myInput->setField(0.54, _IFT_SimpleCrossSection_thick);
     myData.insertInputRecord(DataReader::InputRecordType::IR_crosssectRec, myInput);

     //Material
     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_IsotropicLinearElasticMaterial_Name, 1);
     myInput->setField(1.0, _IFT_Material_density);
     myInput->setField(_IFT_IsotropicLinearElasticMaterial_e);
     myInput->setField(0.2, _IFT_IsotropicLinearElasticMaterial_n);
     myInput->setField(1.2e-5, _IFT_IsotropicLinearElasticMaterial_talpha);
     myData.insertInputRecord(DataReader::InputRecordType::IR_matRec, myInput);

     //Boundary Conditions
     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_BoundaryCondition_Name, 1);
     myInput->setField(1, _IFT_GeneralBoundaryCondition_LoadTimeFunct);
     myInput->setField(0.0, _IFT_BoundaryCondition_PrescribedValue);
     myData.insertInputRecord(DataReader::InputRecordType::IR_bcRec, myInput);

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_BoundaryCondition_Name, 2);
     myInput->setField(2, _IFT_GeneralBoundaryCondition_LoadTimeFunct);
     myInput->setField(-0.006e-3, _IFT_BoundaryCondition_PrescribedValue);
     myData.insertInputRecord(DataReader::InputRecordType::IR_bcRec, myInput);

     //Loads
     FloatArray comps(3);    

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_ConstantSurfaceLoad_Name, 3);
     myInput->setField(1, _IFT_GeneralBoundaryCondition_LoadTimeFunct);
     comps.setValues(3, 0.0, 10.0, 0.0);
     myInput->setField(comps, _IFT_Load_components);
     myInput->setField(3, _IFT_BoundaryLoad_loadtype);
     myInput->setField(3, _IFT_BoundaryLoad_ndofs);
     myData.insertInputRecord(DataReader::InputRecordType::IR_bcRec, myInput);

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_NodalLoad_Name, 4);
     myInput->setField(1, _IFT_GeneralBoundaryCondition_LoadTimeFunct);
     comps.setValues(3, -18.0, 24.0, 0.0);
     myInput->setField(comps, _IFT_Load_components);
     myData.insertInputRecord(DataReader::InputRecordType::IR_bcRec, myInput);

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_StructuralTemperatureLoad_Name, 4);
     myInput->setField(1, _IFT_GeneralBoundaryCondition_LoadTimeFunct);
     comps.setValues(2, 30.0, -20.0);
     myInput->setField(comps, _IFT_Load_components);
     myData.insertInputRecord(DataReader::InputRecordType::IR_bcRec, myInput);
    
     //Functions
     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_PeakFunction_Name, 1);
     myInput->setField(1.0, _IFT_PeakFunction_t);
     myInput->setField(1.0, _IFT_PeakFunction_ft);
     myData.insertInputRecord(DataReader::InputRecordType::IR_ltfRec, myInput);

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_PeakFunction_Name, 2);
     myInput->setField(2.0, _IFT_PeakFunction_t);
     myInput->setField(1.0, _IFT_PeakFunction_ft);
     myData.insertInputRecord(DataReader::InputRecordType::IR_ltfRec, myInput);

     myInput = new DynamicInputRecord();
     myInput->setRecordKeywordField(_IFT_PeakFunction_Name, 3);
     myInput->setField(3.0, _IFT_PeakFunction_t);
     myInput->setField(1.0, _IFT_PeakFunction_ft);
     myData.insertInputRecord(DataReader::InputRecordType::IR_ltfRec, myInput);

    EngngModel *em = InstanciateProblem(&myData, _processor, 0);
    myData.finish();
}

You may need a few more headers. I couldn't see how to post a file, so I just pasted.

Re: Recreated: 'stand-alone' executable

Hi. Im currently on a conference in Poland, so i cant try out the code now. Ill be back on sunday. At a glance, everything looks alrigth so without error messages i cant think of any reason

19

Re: Recreated: 'stand-alone' executable

Hi Mark,

please find included the corrected source. You can run the "diff" command to see changes I have made, Some mistakes are just simple, some may need explanation:

1) When creating nodal records:

coord.setValues(2.4, 0.0, 3.0);    
bcs.setValues(1, 1, 2);
myData.insertInputRecord(DataReader::InputRecordType::IR_dofmanRec, CreateNode(6, coord, bcs));

bcs.setValues(1, 1, 2): the first parameter is array size, so to get the array of (1,1,2) values you should use bcs.setValues(3, 1, 1, 2)

2) When creating elements:

  nodes.setValues(2,2,3);
  beam = CreateBeam(2, nodes, 1, 1);    
  beam->setField(6, _IFT_Beam2d_dofstocondense);    
  beam->setField(loads, _IFT_Element_bodyload);
  myData.insertInputRecord(DataReader::InputRecordType::IR_elemRec, beam);

the _IFT_Beam2d_dofstocondense field should contain an array, not integer.

3) there are some modifications in domain and outputmanager records required, they have to be initialized in this "nonstandard" way.

Borek

Post's attachments

corrected_example.C 8.72 kb, 6 downloads since 2013-08-29 

You don't have the permssions to download the attachments of this post.

Re: Recreated: 'stand-alone' executable

Here us a good reason to be able to use initializer lists from C++11. Syntax would be much cleaner than the setValues function.


I think we should add a separate build target like this to oofem to showcase the functionality. E.g. oofem/src/main/beamsimulation.C

Re: Recreated: 'stand-alone' executable

Thanks a lot for the help

Re: Recreated: 'stand-alone' executable

I still get an error "EngngModel::InstanciateProblem - Failed to construct engineering model if type" after making the changes above. Is there more I have to do to get a Problem created and solved?

Re: Recreated: 'stand-alone' executable

My only guess is that this still has to do with linking. Before main() is executed, it should perform the static initialization, where this funciton is executed

bool ClassFactory :: registerEngngModel(const char *name, EngngModel * ( *creator )(int, EngngModel *))
{
    engngList[name] = creator;
    return true;
}

for each engineering model.
You could try to add printf to just verify that it actually runs.

bool ClassFactory :: registerEngngModel(const char *name, EngngModel * ( *creator )(int, EngngModel *))
{
    printf("Registering engng with name: %s\n", name);
    engngList[name] = creator;
    return true;
}

and a bunch of engng should show up. It should work when simply link all the objects files, or a dynamic library.