<commit_before>/*##############################################################################

    Copyright (C) 2011 HPCC Systems.

    All rights reserved. This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
############################################################################## */

#ifndef CTFILE_HPP
#define CTFILE_HPP

#include "jiface.hpp"
#include "jhutil.hpp"
#include "hlzw.h"
#include "jcrc.hpp"
#include "jio.hpp"
#include "jfile.hpp"

#define NODESIZE 8192

#define HTREE_FPOS_OFFSET   0x01 // Obsolete, not supported
#define HTREE_TOPLEVEL_KEY  0x02
#define COL_PREFIX          0x04
#define COL_SUFFIX          0x08 // Obsolete, not supported
#define HTREE_VARSIZE       0x10
#define HTREE_FULLSORT_KEY  0x20
#define INDAR_TRAILING_SEG  0x80 // Obsolete, not supported
#define HTREE_COMPRESSED_KEY 0x40
#define HTREE_QUICK_COMPRESSED_KEY 0x48
#define KEYBUILD_VERSION 1 // unsigned short. NB: This should upped if a change would make existing keys incompatible with current build.

// structure to be read into - NO VIRTUALS.
// This header layout corresponds to FairCom cTree layout for compatibility with old systems ...

struct __declspec(novtable) jhtree_decl KeyHdr
{
    __int64 phyrec; /* last byte offset of file     00x */
    __int64 delstk; /* top of delete stack: fixed len data  08x */
    __int64 numrec; /* last byte offset written     10x */
    __int64 reshdr; /* resource header          18x */
    __int64 lstmbr; /* last super file member/position  20x */
    __int64 sernum; /* serial number            28x */
    __int64 nument; /* active entries           30x */
    __int64 root;   /* B-Tree root              38x */
    __int64 fileid; /* unique file id           40x */
    __int64 servid; /* unique server id         48x */
    short   verson; /* configuration options at create  50x */
    unsigned short  nodeSize;   /* node record size         52x */
    unsigned short  reclen; /* data record length           54x */
    unsigned short  extsiz; /* extend file (chunk) size     56x */
    unsigned short  flmode; /* file mode (virtual, etc)     58x */
    unsigned short  logtyp; /* permanent components of file mode    5ax */
    unsigned short  maxkbl; /* maximum key bytes leaf-var       5cx */
    unsigned short  maxkbn; /* maximum key bytes non leaf-var   5ex */
    char    updflg; /* update (corrupt) flag        60x */
    char    ktype;  /* file type flag           61x */
    char    autodup;/* duplicate flag           62x */
    char    deltyp; /* flag for type of idx delete      63x */
    unsigned char   keypad; /* padding byte             64x */
    unsigned char   flflvr; /* file flavor              65x */
    unsigned char   flalgn; /* file alignment           66x */
    unsigned char   flpntr; /* file pointer size            67x */
    unsigned short  clstyp; /* flag for file type           68x */
    short   length; /* key length               6ax */
    short   nmem;   /* number of members            6cx */
    short   kmem;   /* member number            6ex */
    __int64 lanchr; /* left most leaf anchor        70x */
    __int64 supid;  /* super file member #          78x */
    __int64 hdrpos; /* header position          80x */
    __int64 sihdr;  /* superfile header index hdr position  88x */
    __int64 timeid; /* time id#             90x */
    unsigned short  suptyp; /* super file type          98x */
    unsigned short  maxmrk; /* maximum exc mark entries per leaf    9ax */
    unsigned short  namlen; /* MAX_NAME at creation         9cx */
    unsigned short  xflmod; /* extended file mode info      9ex */
    __int64 defrel; /* file def release mask        a0x */
    __int64 hghtrn; /* tran# high water mark for idx    a8x */
    __int64 hdrseq; /* wrthdr sequence #            b0x */
    __int64 tstamp; /* update time stamp            b8x */
    __int64 rs3[3]; /* future use               c0x */
    __int64 fposOffset; /* amount by which file positions are biased        d8x */
    __int64 fileSize; /* fileSize - used in the bias calculation e0x */
    short nodeKeyLength; /* key length in intermediate level nodes e8x */
    unsigned short version; /* build version - to be updated if key format changes    eax*/
    short unused[2]; /* unused ecx */
    __int64 blobHead; /* fpos of first blob node f0x */
    __int64 metadataHead; /* fpos of first metadata node f8x */
};

//#pragma pack(1)
#pragma pack(push,1)
struct jhtree_decl NodeHdr
{
    __int64    rightSib;
    __int64    leftSib;
    unsigned short   numKeys;
    unsigned short   keyBytes;
    unsigned    crc32;
    char    unusedMemNumber;
    char    leafFlag;

    bool isValid(unsigned nodeSize)
    {
        return
            (rightSib % nodeSize == 0) &&
            (leftSib % nodeSize == 0) &&
            (unusedMemNumber==0) &&
            (keyBytes < nodeSize);
    }
};
//#pragma pack(4)
#pragma pack(pop)

class jhtree_decl CKeyHdr : public CInterface, implements IInterface
{
private:
    KeyHdr hdr;
public:
    IMPLEMENT_IINTERFACE;
    CKeyHdr();

    void load(KeyHdr &_hdr);
    void write(IWriteSeq *, CRC32 *crc = NULL);
    void write(IFileIOStream *, CRC32 *crc = NULL);

    unsigned int getMaxKeyLength();
    bool isVariable();
    inline unsigned int getNodeKeyLength()
    {
        return hdr.nodeKeyLength != -1 ? hdr.nodeKeyLength : getMaxKeyLength();
    }
    inline bool hasPayload()
    {
        return (hdr.nodeKeyLength != -1);
    }
    inline unsigned char getKeyPad() { return hdr.keypad; }
    inline char getKeyType() { return hdr.ktype; }
    inline offset_t getRootFPos() { return hdr.root; }
    inline unsigned short getMaxNodeBytes() { return hdr.maxkbl; }
    inline KeyHdr *getHdrStruct() { return &hdr; }
    inline static size32_t getSize() { return sizeof(KeyHdr); }
    inline unsigned getNodeSize() { return hdr.nodeSize; }
};

class jhtree_decl CNodeBase : public CInterface, implements IInterface
{
protected:
    NodeHdr hdr;
    byte keyType;
    size32_t keyLen;
    size32_t keyCompareLen;
    offset_t fpos;
    CKeyHdr *keyHdr;
    bool isVariable;

public:
    inline offset_t getFpos() const { return fpos; }
    inline size32_t getKeyLen() const { return keyLen; }
    inline size32_t getNumKeys() const { return hdr.numKeys; }
    inline bool isBlob() const { return hdr.leafFlag == 2; }
    inline bool isMetadata() const { return hdr.leafFlag == 3; }
    inline bool isLeaf() const { return hdr.leafFlag != 0; }

public:
    IMPLEMENT_IINTERFACE;

    CNodeBase();
    void load(CKeyHdr *keyHdr, offset_t fpos);
    ~CNodeBase();
};

class jhtree_decl CJHTreeNode : public CNodeBase
{
protected:
    size32_t keyRecLen;
    char *keyBuf;

    static SpinLock spin;
    static unsigned __int64 totalAllocatedCurrent;
    static unsigned __int64 totalAllocatedEver;
    static unsigned countAllocationsCurrent;
    static unsigned countAllocationsEver;

    void unpack(const void *node, bool needCopy);
    unsigned __int64 firstSequence;
    size32_t expandedSize;
    Owned<IRandRowExpander> rowexp;  // expander for rand rowdiff

    static char *expandKeys(void *src,unsigned keylength,size32_t &retsize, bool rowcompression);
    static IRandRowExpander *expandQuickKeys(void *src, bool needCopy);

    static void releaseMem(void *togo, size32_t size);
    static void *allocMem(size32_t size);

public:
    CJHTreeNode();
    virtual void load(CKeyHdr *keyHdr, const void *rawData, offset_t pos, bool needCopy);
    ~CJHTreeNode();
    size32_t getMemSize() { return expandedSize; }

// reading methods
    offset_t prevNodeFpos() const;
    offset_t nextNodeFpos() const ;
    virtual bool getValueAt(unsigned int num, char *key) const;
    virtual size32_t getSizeAt(unsigned int num) const;
    virtual offset_t getFPosAt(unsigned int num) const;
    virtual int compareValueAt(const char *src, unsigned int index) const;
    bool contains(const char *src) const;
    inline offset_t getRightSib() const { return hdr.rightSib; }
    inline offset_t getLeftSib() const { return hdr.leftSib; }
    unsigned __int64 getSequence(unsigned int num) const;

    virtual void dump();
};

class CJHVarTreeNode : public CJHTreeNode
{
    const char **recArray;

public:
    CJHVarTreeNode();
    ~CJHVarTreeNode();
    virtual void load(CKeyHdr *keyHdr, const void *rawData, offset_t pos, bool needCopy);
    virtual bool getValueAt(unsigned int num, char *key) const;
    virtual size32_t getSizeAt(unsigned int num) const;
    virtual offset_t getFPosAt(unsigned int num) const;
    virtual int compareValueAt(const char *src, unsigned int index) const;
    virtual void dump();
};

class CJHTreeBlobNode : public CJHTreeNode
{
public:
    CJHTreeBlobNode ();
    ~CJHTreeBlobNode ();
    virtual bool getValueAt(unsigned int num, char *key) const {throwUnexpected();}
    virtual offset_t getFPosAt(unsigned int num) const {throwUnexpected();}
    virtual size32_t getSizeAt(unsigned int num) const {throwUnexpected();}
    virtual int compareValueAt(const char *src, unsigned int index) const {throwUnexpected();}
    virtual void dump() {throwUnexpected();}

    size32_t getTotalBlobSize(unsigned offset);
    size32_t getBlobData(unsigned offset, void *dst);
};

class CJHTreeMetadataNode : public CJHTreeNode
{
public:
    virtual bool getValueAt(unsigned int num, char *key) const {throwUnexpected();}
    virtual offset_t getFPosAt(unsigned int num) const {throwUnexpected();}
    virtual size32_t getSizeAt(unsigned int num) const {throwUnexpected();}
    virtual int compareValueAt(const char *src, unsigned int index) const {throwUnexpected();}
    virtual void dump() {throwUnexpected();}
    void get(StringBuffer & out);
};

class jhtree_decl CNodeHeader : public CNodeBase
{
public:
    CNodeHeader();

    void load(NodeHdr &hdr);

    inline offset_t getRightSib() const { return hdr.rightSib; }
    inline offset_t getLeftSib() const { return hdr.leftSib; }
};

class jhtree_decl CWriteNodeBase : public CNodeBase
{
protected:
    char *nodeBuf;
    char *keyPtr;
    int maxBytes;
    KeyCompressor lzwcomp;
    void writeHdr();

public:
    CWriteNodeBase(offset_t fpos, CKeyHdr *keyHdr);
    ~CWriteNodeBase();

    void write(IFileIOStream *, CRC32 *crc = NULL);
    void setLeftSib(offset_t leftSib) { hdr.leftSib = leftSib; }
    void setRightSib(offset_t rightSib) { hdr.rightSib = rightSib; }
};

class jhtree_decl CWriteNode : public CWriteNodeBase
{
private:
    char *lastKeyValue;
    unsigned __int64 lastSequence;

public:
    CWriteNode(offset_t fpos, CKeyHdr *keyHdr, bool isLeaf);
    ~CWriteNode();

    size32_t compressValue(const char *keyData, size32_t size, char *result);
    bool add(offset_t pos, const void *data, size32_t size, unsigned __int64 sequence);
    const void *getLastKeyValue() const { return lastKeyValue; }
    unsigned __int64 getLastSequence() const { return lastSequence; }
};

class jhtree_decl CBlobWriteNode : public CWriteNodeBase
{
    static unsigned __int64 makeBlobId(offset_t nodepos, unsigned offset);
public:
    CBlobWriteNode(offset_t _fpos, CKeyHdr *keyHdr);
    ~CBlobWriteNode();

    unsigned __int64 add(const char * &data, size32_t &size);
};

class jhtree_decl CMetadataWriteNode : public CWriteNodeBase
{
public:
    CMetadataWriteNode(offset_t _fpos, CKeyHdr *keyHdr);
    size32_t set(const char * &data, size32_t &size);
};

enum KeyExceptionCodes
{
    KeyExcpt_IncompatVersion = 1,
};
interface IKeyException : extends IException { };
IKeyException *MakeKeyException(int code, const char *format, ...) __attribute__((format(printf, 2, 3)));

#endif
<commit_msg>Change length in index header to unsigned<commit_after>/*##############################################################################

    Copyright (C) 2011 HPCC Systems.

    All rights reserved. This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
############################################################################## */

#ifndef CTFILE_HPP
#define CTFILE_HPP

#include "jiface.hpp"
#include "jhutil.hpp"
#include "hlzw.h"
#include "jcrc.hpp"
#include "jio.hpp"
#include "jfile.hpp"

#define NODESIZE 8192

#define HTREE_FPOS_OFFSET   0x01 // Obsolete, not supported
#define HTREE_TOPLEVEL_KEY  0x02
#define COL_PREFIX          0x04
#define COL_SUFFIX          0x08 // Obsolete, not supported
#define HTREE_VARSIZE       0x10
#define HTREE_FULLSORT_KEY  0x20
#define INDAR_TRAILING_SEG  0x80 // Obsolete, not supported
#define HTREE_COMPRESSED_KEY 0x40
#define HTREE_QUICK_COMPRESSED_KEY 0x48
#define KEYBUILD_VERSION 1 // unsigned short. NB: This should upped if a change would make existing keys incompatible with current build.

// structure to be read into - NO VIRTUALS.
// This header layout corresponds to FairCom cTree layout for compatibility with old systems ...

struct __declspec(novtable) jhtree_decl KeyHdr
{
    __int64 phyrec; /* last byte offset of file     00x */
    __int64 delstk; /* top of delete stack: fixed len data  08x */
    __int64 numrec; /* last byte offset written     10x */
    __int64 reshdr; /* resource header          18x */
    __int64 lstmbr; /* last super file member/position  20x */
    __int64 sernum; /* serial number            28x */
    __int64 nument; /* active entries           30x */
    __int64 root;   /* B-Tree root              38x */
    __int64 fileid; /* unique file id           40x */
    __int64 servid; /* unique server id         48x */
    short   verson; /* configuration options at create  50x */
    unsigned short  nodeSize;   /* node record size         52x */
    unsigned short  reclen; /* data record length           54x */
    unsigned short  extsiz; /* extend file (chunk) size     56x */
    unsigned short  flmode; /* file mode (virtual, etc)     58x */
    unsigned short  logtyp; /* permanent components of file mode    5ax */
    unsigned short  maxkbl; /* maximum key bytes leaf-var       5cx */
    unsigned short  maxkbn; /* maximum key bytes non leaf-var   5ex */
    char    updflg; /* update (corrupt) flag        60x */
    char    ktype;  /* file type flag           61x */
    char    autodup;/* duplicate flag           62x */
    char    deltyp; /* flag for type of idx delete      63x */
    unsigned char   keypad; /* padding byte             64x */
    unsigned char   flflvr; /* file flavor              65x */
    unsigned char   flalgn; /* file alignment           66x */
    unsigned char   flpntr; /* file pointer size            67x */
    unsigned short  clstyp; /* flag for file type           68x */
    unsigned short  length; /* key length               6ax */
    short   nmem;   /* number of members            6cx */
    short   kmem;   /* member number            6ex */
    __int64 lanchr; /* left most leaf anchor        70x */
    __int64 supid;  /* super file member #          78x */
    __int64 hdrpos; /* header position          80x */
    __int64 sihdr;  /* superfile header index hdr position  88x */
    __int64 timeid; /* time id#             90x */
    unsigned short  suptyp; /* super file type          98x */
    unsigned short  maxmrk; /* maximum exc mark entries per leaf    9ax */
    unsigned short  namlen; /* MAX_NAME at creation         9cx */
    unsigned short  xflmod; /* extended file mode info      9ex */
    __int64 defrel; /* file def release mask        a0x */
    __int64 hghtrn; /* tran# high water mark for idx    a8x */
    __int64 hdrseq; /* wrthdr sequence #            b0x */
    __int64 tstamp; /* update time stamp            b8x */
    __int64 rs3[3]; /* future use               c0x */
    __int64 fposOffset; /* amount by which file positions are biased        d8x */
    __int64 fileSize; /* fileSize - used in the bias calculation e0x */
    short nodeKeyLength; /* key length in intermediate level nodes e8x */
    unsigned short version; /* build version - to be updated if key format changes    eax*/
    short unused[2]; /* unused ecx */
    __int64 blobHead; /* fpos of first blob node f0x */
    __int64 metadataHead; /* fpos of first metadata node f8x */
};

//#pragma pack(1)
#pragma pack(push,1)
struct jhtree_decl NodeHdr
{
    __int64    rightSib;
    __int64    leftSib;
    unsigned short   numKeys;
    unsigned short   keyBytes;
    unsigned    crc32;
    char    unusedMemNumber;
    char    leafFlag;

    bool isValid(unsigned nodeSize)
    {
        return
            (rightSib % nodeSize == 0) &&
            (leftSib % nodeSize == 0) &&
            (unusedMemNumber==0) &&
            (keyBytes < nodeSize);
    }
};
//#pragma pack(4)
#pragma pack(pop)

class jhtree_decl CKeyHdr : public CInterface, implements IInterface
{
private:
    KeyHdr hdr;
public:
    IMPLEMENT_IINTERFACE;
    CKeyHdr();

    void load(KeyHdr &_hdr);
    void write(IWriteSeq *, CRC32 *crc = NULL);
    void write(IFileIOStream *, CRC32 *crc = NULL);

    unsigned int getMaxKeyLength();
    bool isVariable();
    inline unsigned int getNodeKeyLength()
    {
        return hdr.nodeKeyLength != -1 ? hdr.nodeKeyLength : getMaxKeyLength();
    }
    inline bool hasPayload()
    {
        return (hdr.nodeKeyLength != -1);
    }
    inline unsigned char getKeyPad() { return hdr.keypad; }
    inline char getKeyType() { return hdr.ktype; }
    inline offset_t getRootFPos() { return hdr.root; }
    inline unsigned short getMaxNodeBytes() { return hdr.maxkbl; }
    inline KeyHdr *getHdrStruct() { return &hdr; }
    inline static size32_t getSize() { return sizeof(KeyHdr); }
    inline unsigned getNodeSize() { return hdr.nodeSize; }
};

class jhtree_decl CNodeBase : public CInterface, implements IInterface
{
protected:
    NodeHdr hdr;
    byte keyType;
    size32_t keyLen;
    size32_t keyCompareLen;
    offset_t fpos;
    CKeyHdr *keyHdr;
    bool isVariable;

public:
    inline offset_t getFpos() const { return fpos; }
    inline size32_t getKeyLen() const { return keyLen; }
    inline size32_t getNumKeys() const { return hdr.numKeys; }
    inline bool isBlob() const { return hdr.leafFlag == 2; }
    inline bool isMetadata() const { return hdr.leafFlag == 3; }
    inline bool isLeaf() const { return hdr.leafFlag != 0; }

public:
    IMPLEMENT_IINTERFACE;

    CNodeBase();
    void load(CKeyHdr *keyHdr, offset_t fpos);
    ~CNodeBase();
};

class jhtree_decl CJHTreeNode : public CNodeBase
{
protected:
    size32_t keyRecLen;
    char *keyBuf;

    static SpinLock spin;
    static unsigned __int64 totalAllocatedCurrent;
    static unsigned __int64 totalAllocatedEver;
    static unsigned countAllocationsCurrent;
    static unsigned countAllocationsEver;

    void unpack(const void *node, bool needCopy);
    unsigned __int64 firstSequence;
    size32_t expandedSize;
    Owned<IRandRowExpander> rowexp;  // expander for rand rowdiff

    static char *expandKeys(void *src,unsigned keylength,size32_t &retsize, bool rowcompression);
    static IRandRowExpander *expandQuickKeys(void *src, bool needCopy);

    static void releaseMem(void *togo, size32_t size);
    static void *allocMem(size32_t size);

public:
    CJHTreeNode();
    virtual void load(CKeyHdr *keyHdr, const void *rawData, offset_t pos, bool needCopy);
    ~CJHTreeNode();
    size32_t getMemSize() { return expandedSize; }

// reading methods
    offset_t prevNodeFpos() const;
    offset_t nextNodeFpos() const ;
    virtual bool getValueAt(unsigned int num, char *key) const;
    virtual size32_t getSizeAt(unsigned int num) const;
    virtual offset_t getFPosAt(unsigned int num) const;
    virtual int compareValueAt(const char *src, unsigned int index) const;
    bool contains(const char *src) const;
    inline offset_t getRightSib() const { return hdr.rightSib; }
    inline offset_t getLeftSib() const { return hdr.leftSib; }
    unsigned __int64 getSequence(unsigned int num) const;

    virtual void dump();
};

class CJHVarTreeNode : public CJHTreeNode
{
    const char **recArray;

public:
    CJHVarTreeNode();
    ~CJHVarTreeNode();
    virtual void load(CKeyHdr *keyHdr, const void *rawData, offset_t pos, bool needCopy);
    virtual bool getValueAt(unsigned int num, char *key) const;
    virtual size32_t getSizeAt(unsigned int num) const;
    virtual offset_t getFPosAt(unsigned int num) const;
    virtual int compareValueAt(const char *src, unsigned int index) const;
    virtual void dump();
};

class CJHTreeBlobNode : public CJHTreeNode
{
public:
    CJHTreeBlobNode ();
    ~CJHTreeBlobNode ();
    virtual bool getValueAt(unsigned int num, char *key) const {throwUnexpected();}
    virtual offset_t getFPosAt(unsigned int num) const {throwUnexpected();}
    virtual size32_t getSizeAt(unsigned int num) const {throwUnexpected();}
    virtual int compareValueAt(const char *src, unsigned int index) const {throwUnexpected();}
    virtual void dump() {throwUnexpected();}

    size32_t getTotalBlobSize(unsigned offset);
    size32_t getBlobData(unsigned offset, void *dst);
};

class CJHTreeMetadataNode : public CJHTreeNode
{
public:
    virtual bool getValueAt(unsigned int num, char *key) const {throwUnexpected();}
    virtual offset_t getFPosAt(unsigned int num) const {throwUnexpected();}
    virtual size32_t getSizeAt(unsigned int num) const {throwUnexpected();}
    virtual int compareValueAt(const char *src, unsigned int index) const {throwUnexpected();}
    virtual void dump() {throwUnexpected();}
    void get(StringBuffer & out);
};

class jhtree_decl CNodeHeader : public CNodeBase
{
public:
    CNodeHeader();

    void load(NodeHdr &hdr);

    inline offset_t getRightSib() const { return hdr.rightSib; }
    inline offset_t getLeftSib() const { return hdr.leftSib; }
};

class jhtree_decl CWriteNodeBase : public CNodeBase
{
protected:
    char *nodeBuf;
    char *keyPtr;
    int maxBytes;
    KeyCompressor lzwcomp;
    void writeHdr();

public:
    CWriteNodeBase(offset_t fpos, CKeyHdr *keyHdr);
    ~CWriteNodeBase();

    void write(IFileIOStream *, CRC32 *crc = NULL);
    void setLeftSib(offset_t leftSib) { hdr.leftSib = leftSib; }
    void setRightSib(offset_t rightSib) { hdr.rightSib = rightSib; }
};

class jhtree_decl CWriteNode : public CWriteNodeBase
{
private:
    char *lastKeyValue;
    unsigned __int64 lastSequence;

public:
    CWriteNode(offset_t fpos, CKeyHdr *keyHdr, bool isLeaf);
    ~CWriteNode();

    size32_t compressValue(const char *keyData, size32_t size, char *result);
    bool add(offset_t pos, const void *data, size32_t size, unsigned __int64 sequence);
    const void *getLastKeyValue() const { return lastKeyValue; }
    unsigned __int64 getLastSequence() const { return lastSequence; }
};

class jhtree_decl CBlobWriteNode : public CWriteNodeBase
{
    static unsigned __int64 makeBlobId(offset_t nodepos, unsigned offset);
public:
    CBlobWriteNode(offset_t _fpos, CKeyHdr *keyHdr);
    ~CBlobWriteNode();

    unsigned __int64 add(const char * &data, size32_t &size);
};

class jhtree_decl CMetadataWriteNode : public CWriteNodeBase
{
public:
    CMetadataWriteNode(offset_t _fpos, CKeyHdr *keyHdr);
    size32_t set(const char * &data, size32_t &size);
};

enum KeyExceptionCodes
{
    KeyExcpt_IncompatVersion = 1,
};
interface IKeyException : extends IException { };
IKeyException *MakeKeyException(int code, const char *format, ...) __attribute__((format(printf, 2, 3)));

#endif
<|endoftext|>


<commit_before>/* Solver.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_EXPT_SOLVE_SOLVER_HPP__
#define SUNFISH_EXPT_SOLVE_SOLVER_HPP__

#include "core/position/Position.hpp"
#include "core/move/Move.hpp"
#include "search/Searcher.hpp"
#include <string>
#include <cstdint>

namespace sunfish {

class Solver : LoggingSearchHandler {
public:

  struct Config {
    int muximumDepth;
    SearchConfig::TimeType muximumTimeSeconds;
    int numberOfThreads;
    bool noInterrupt;
  };

  struct Nodes {
    uint64_t nodes;
    uint64_t sample;
  };

  static CONSTEXPR_CONST int MaxDepthOfNodeCount = 10;

  struct Result {
    unsigned corrected;
    unsigned incorrected;
    unsigned mate;
    uint64_t nodes;
    double elapsed;
    Nodes nodesEachDepth[MaxDepthOfNodeCount];
  };

  Solver();

  bool solve(const char* path);

  bool solve(const std::string& path) {
    return solve(path.c_str());
  }

  const Config& getConfig() const {
    return config_;
  }

  void setConfig(const Config& config) {
    config_ = config;
  }

  void onIterateEnd(const Searcher& searcher, float elapsed, int depth) override;
  void onUpdatePV(const Searcher& searcher, const PV& pv, float elapsed, int depth, Score score, int multiPV) override;

private:

  bool solveCsaFile(const char* path);

  bool solve(const Position& position, Move correct);

private:

  Searcher searcher_;
  Config config_;
  Result result_;
  Move correct_;

};

} // namespace sunfish

#endif // SUNFISH_EXPT_SOLVE_SOLVER_HPP__
<commit_msg>Update solver<commit_after>/* Solver.hpp
 *
 * Kubo Ryosuke
 */

#ifndef SUNFISH_EXPT_SOLVE_SOLVER_HPP__
#define SUNFISH_EXPT_SOLVE_SOLVER_HPP__

#include "core/position/Position.hpp"
#include "core/move/Move.hpp"
#include "search/Searcher.hpp"
#include <string>
#include <cstdint>

namespace sunfish {

class Solver : LoggingSearchHandler {
public:

  struct Config {
    int muximumDepth;
    SearchConfig::TimeType muximumTimeSeconds;
    int numberOfThreads;
    bool noInterrupt;
  };

  struct Nodes {
    uint64_t nodes;
    uint64_t sample;
  };

  static CONSTEXPR_CONST int MaxDepthOfNodeCount = 20;

  struct Result {
    unsigned corrected;
    unsigned incorrected;
    unsigned mate;
    uint64_t nodes;
    double elapsed;
    Nodes nodesEachDepth[MaxDepthOfNodeCount];
  };

  Solver();

  bool solve(const char* path);

  bool solve(const std::string& path) {
    return solve(path.c_str());
  }

  const Config& getConfig() const {
    return config_;
  }

  void setConfig(const Config& config) {
    config_ = config;
  }

  void onIterateEnd(const Searcher& searcher, float elapsed, int depth) override;
  void onUpdatePV(const Searcher& searcher, const PV& pv, float elapsed, int depth, Score score, int multiPV) override;

private:

  bool solveCsaFile(const char* path);

  bool solve(const Position& position, Move correct);

private:

  Searcher searcher_;
  Config config_;
  Result result_;
  Move correct_;

};

} // namespace sunfish

#endif // SUNFISH_EXPT_SOLVE_SOLVER_HPP__
<|endoftext|>


<commit_before>/* Copyright 2007-2016 QReal Research Group, Dmitry Mordvinov, Yurii Litvinov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "utils/robotCommunication/tcpRobotCommunicator.h"

#include <QtCore/QFileInfo>

#include <qrkernel/logging.h>
#include <qrutils/inFile.h>

#include "src/robotCommunication/tcpRobotCommunicatorWorker.h"

using namespace utils::robotCommunication;

TcpRobotCommunicator::TcpRobotCommunicator(const QString &serverIpSettingsKey)
{
	mWorker.reset(new TcpRobotCommunicatorWorker(serverIpSettingsKey));

	mWorker->moveToThread(&mWorkerThread);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::connected
			, this, &TcpRobotCommunicator::onConnected, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::disconnected
			, this, &TcpRobotCommunicator::disconnected, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::newScalarSensorData
			, this, &TcpRobotCommunicator::newScalarSensorData, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::newVectorSensorData
			, this, &TcpRobotCommunicator::newVectorSensorData, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::printText
			, this, &TcpRobotCommunicator::printText, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::startedRunning
			, this, &TcpRobotCommunicator::startedRunning, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::messageFromRobot
			, this, &TcpRobotCommunicator::onMessageFromRobot, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::connectionError
			, this, &TcpRobotCommunicator::onConnectionError, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::trikRuntimeVersionError
			, this, &TcpRobotCommunicator::trikRuntimeVersionError, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::trikRuntimeVersionGettingError
			, this, &TcpRobotCommunicator::trikRuntimeVersionGettingError, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::uploadProgramDone
			, this, &TcpRobotCommunicator::uploadProgramDone, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::stopRobotDone
			, this, &TcpRobotCommunicator::stopRobotDone, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::runDirectCommandDone
			, this, &TcpRobotCommunicator::runDirectCommandDone, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::casingVersionReceived
			, this, &TcpRobotCommunicator::casingVersionReceived, Qt::QueuedConnection);

	mWorkerThread.start();

	QMetaObject::invokeMethod(mWorker.data(), "init");
}

TcpRobotCommunicator::~TcpRobotCommunicator()
{
	QMetaObject::invokeMethod(mWorker.data(), "deinit");

	if (mWorkerThread.isRunning()) {
		mWorkerThread.quit();
		mWorkerThread.wait();
	}
}

void TcpRobotCommunicator::uploadProgram(const QString &programName)
{
	if (programName.isEmpty()) {
		QLOG_ERROR() << "Empty program name";
		emit uploadProgramError(tr("Empty program name, can not upload"));
		return;
	}

	QString errorString;
	const QString fileContents = utils::InFile::readAll(programName, &errorString);
	if (!errorString.isEmpty()) {
		QLOG_ERROR() << "Reading file to transfer failed";
		emit uploadProgramError(tr("Can not read generated file, uploading aborted"));
		return;
	}

	const QString fileNameOnARobot = QFileInfo(programName).fileName();

	QMetaObject::invokeMethod(mWorker.data(), "uploadProgram"
			, Q_ARG(QString, fileNameOnARobot), Q_ARG(QString, fileContents));
}

void TcpRobotCommunicator::runProgram(const QString &programName)
{
	/// @todo: temporary hack. This must be done in TRIK Runtime
	if (programName.endsWith(".py")) {
		const QString directCommand =
				"script.system(\"mv /home/root/trik/scripts/%1 /home/root/; "
				"python '/home/root/%1'\")";
		runDirectCommand(directCommand.arg(programName));
	} else {
		QMetaObject::invokeMethod(mWorker.data(), "runProgram", Q_ARG(QString, programName));
	}
}

void TcpRobotCommunicator::runDirectCommand(const QString &directCommand, bool asScript)
{
	QMetaObject::invokeMethod(mWorker.data(), "runDirectCommand"
			, Q_ARG(QString, directCommand), Q_ARG(bool, asScript));
}

void TcpRobotCommunicator::requestCasingVersion()
{
	QMetaObject::invokeMethod(mWorker.data(), "requestCasingVersion");
}

void TcpRobotCommunicator::stopRobot()
{
	QMetaObject::invokeMethod(mWorker.data(), "stopRobot");
}

void TcpRobotCommunicator::requestData(const QString &sensor)
{
	QMetaObject::invokeMethod(mWorker.data(), "requestData", Q_ARG(QString, sensor));
}

void TcpRobotCommunicator::requestData()
{
	QMetaObject::invokeMethod(mWorker.data(), "requestData");
}

void TcpRobotCommunicator::connect()
{
	QMetaObject::invokeMethod(mWorker.data(), "connect");
}

void TcpRobotCommunicator::disconnect()
{
	QMetaObject::invokeMethod(mWorker.data(), "disconnect");
}

void TcpRobotCommunicator::onMessageFromRobot(const MessageKind &messageKind, const QString &message)
{

	switch (messageKind) {
	case MessageKind::error:
		emit errorFromRobot(message);
		break;
	case MessageKind::info:
		emit infoFromRobot(message);
		break;
	case MessageKind::text:
		emit printText(message);
		break;
	case MessageKind::fileContents:
		emit fileContentsFromRobot(message);
		break;
	case MessageKind::mail:
		emit mailFromRobot(message);
		break;
	}
}

void TcpRobotCommunicator::onConnectionError(const QString &error)
{
	emit connectionError(error);

	// Insane protocol for robot model connection require that "connection failed" event is emitted as "connected"
	// signal with "success" flag set to false and error string. Altering this protocol will lead to rewriting half
	// of the interpreter, so we will emit "connectionError" for new robot communication protocol classes and
	// "connected" for models.
	emit connected(false, error);
}

void TcpRobotCommunicator::onConnected()
{
	emit connected(true, "");
}
<commit_msg>removed python run hack<commit_after>/* Copyright 2007-2016 QReal Research Group, Dmitry Mordvinov, Yurii Litvinov
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. */

#include "utils/robotCommunication/tcpRobotCommunicator.h"

#include <QtCore/QFileInfo>

#include <qrkernel/logging.h>
#include <qrutils/inFile.h>

#include "src/robotCommunication/tcpRobotCommunicatorWorker.h"

using namespace utils::robotCommunication;

TcpRobotCommunicator::TcpRobotCommunicator(const QString &serverIpSettingsKey)
{
	mWorker.reset(new TcpRobotCommunicatorWorker(serverIpSettingsKey));

	mWorker->moveToThread(&mWorkerThread);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::connected
			, this, &TcpRobotCommunicator::onConnected, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::disconnected
			, this, &TcpRobotCommunicator::disconnected, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::newScalarSensorData
			, this, &TcpRobotCommunicator::newScalarSensorData, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::newVectorSensorData
			, this, &TcpRobotCommunicator::newVectorSensorData, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::printText
			, this, &TcpRobotCommunicator::printText, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::startedRunning
			, this, &TcpRobotCommunicator::startedRunning, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::messageFromRobot
			, this, &TcpRobotCommunicator::onMessageFromRobot, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::connectionError
			, this, &TcpRobotCommunicator::onConnectionError, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::trikRuntimeVersionError
			, this, &TcpRobotCommunicator::trikRuntimeVersionError, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::trikRuntimeVersionGettingError
			, this, &TcpRobotCommunicator::trikRuntimeVersionGettingError, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::uploadProgramDone
			, this, &TcpRobotCommunicator::uploadProgramDone, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::stopRobotDone
			, this, &TcpRobotCommunicator::stopRobotDone, Qt::QueuedConnection);
	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::runDirectCommandDone
			, this, &TcpRobotCommunicator::runDirectCommandDone, Qt::QueuedConnection);

	QObject::connect(mWorker.data(), &TcpRobotCommunicatorWorker::casingVersionReceived
			, this, &TcpRobotCommunicator::casingVersionReceived, Qt::QueuedConnection);

	mWorkerThread.start();

	QMetaObject::invokeMethod(mWorker.data(), "init");
}

TcpRobotCommunicator::~TcpRobotCommunicator()
{
	QMetaObject::invokeMethod(mWorker.data(), "deinit");

	if (mWorkerThread.isRunning()) {
		mWorkerThread.quit();
		mWorkerThread.wait();
	}
}

void TcpRobotCommunicator::uploadProgram(const QString &programName)
{
	if (programName.isEmpty()) {
		QLOG_ERROR() << "Empty program name";
		emit uploadProgramError(tr("Empty program name, can not upload"));
		return;
	}

	QString errorString;
	const QString fileContents = utils::InFile::readAll(programName, &errorString);
	if (!errorString.isEmpty()) {
		QLOG_ERROR() << "Reading file to transfer failed";
		emit uploadProgramError(tr("Can not read generated file, uploading aborted"));
		return;
	}

	const QString fileNameOnARobot = QFileInfo(programName).fileName();

	QMetaObject::invokeMethod(mWorker.data(), "uploadProgram"
			, Q_ARG(QString, fileNameOnARobot), Q_ARG(QString, fileContents));
}

void TcpRobotCommunicator::runProgram(const QString &programName)
{
	QMetaObject::invokeMethod(mWorker.data(), "runProgram", Q_ARG(QString, programName));
}

void TcpRobotCommunicator::runDirectCommand(const QString &directCommand, bool asScript)
{
	QMetaObject::invokeMethod(mWorker.data(), "runDirectCommand"
			, Q_ARG(QString, directCommand), Q_ARG(bool, asScript));
}

void TcpRobotCommunicator::requestCasingVersion()
{
	QMetaObject::invokeMethod(mWorker.data(), "requestCasingVersion");
}

void TcpRobotCommunicator::stopRobot()
{
	QMetaObject::invokeMethod(mWorker.data(), "stopRobot");
}

void TcpRobotCommunicator::requestData(const QString &sensor)
{
	QMetaObject::invokeMethod(mWorker.data(), "requestData", Q_ARG(QString, sensor));
}

void TcpRobotCommunicator::requestData()
{
	QMetaObject::invokeMethod(mWorker.data(), "requestData");
}

void TcpRobotCommunicator::connect()
{
	QMetaObject::invokeMethod(mWorker.data(), "connect");
}

void TcpRobotCommunicator::disconnect()
{
	QMetaObject::invokeMethod(mWorker.data(), "disconnect");
}

void TcpRobotCommunicator::onMessageFromRobot(const MessageKind &messageKind, const QString &message)
{

	switch (messageKind) {
	case MessageKind::error:
		emit errorFromRobot(message);
		break;
	case MessageKind::info:
		emit infoFromRobot(message);
		break;
	case MessageKind::text:
		emit printText(message);
		break;
	case MessageKind::fileContents:
		emit fileContentsFromRobot(message);
		break;
	case MessageKind::mail:
		emit mailFromRobot(message);
		break;
	}
}

void TcpRobotCommunicator::onConnectionError(const QString &error)
{
	emit connectionError(error);

	// Insane protocol for robot model connection require that "connection failed" event is emitted as "connected"
	// signal with "success" flag set to false and error string. Altering this protocol will lead to rewriting half
	// of the interpreter, so we will emit "connectionError" for new robot communication protocol classes and
	// "connected" for models.
	emit connected(false, error);
}

void TcpRobotCommunicator::onConnected()
{
	emit connected(true, "");
}
<|endoftext|>


<commit_before>// $Id$
// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		const Point mapped_point =
		  // FE<Dim,T>::inverse_map(elem, elem->point(n));
		  FEInterface::inverse_map(Dim, fe_type, elem, elem->point(n));

		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, mapped_point);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	  libmesh_assert(o < 2);
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	  libmesh_assert(o < 2);
	case HEX20:
	  libmesh_assert(o < 2);
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

    unsigned int l2_hierarchic_n_dofs_per_elem(const ElemType t,
					       const Order o)
    {
      switch (o)
	{
	  // constant shape functions always have 1 DOF per element
	case CONSTANT:
	  return 1;

	  // Discontinuous linear shape functions
	  // expressed in the monomials.
	case FIRST:
	  {
	    switch (t)
	      {
	      case NODEELEM:
		return 1;

		// 1D linears have 2 DOFs per element
	      case EDGE2:
	      case EDGE3:
	      case EDGE4:
		return 2;

		// 2D linears have 3 DOFs per element
	      case TRI3:
	      case TRI6:
	      case QUAD4:
	      case QUAD8:
	      case QUAD9:
		return 3;

		// 3D linears have 4 DOFs per element
	      case TET4:
	      case TET10:
	      case HEX8:
	      case HEX20:
	      case HEX27:
	      case PRISM6:
	      case PRISM15:
	      case PRISM18:
	      case PYRAMID5:
		return 4;

	      default:
		{
#ifdef DEBUG
		  libMesh::err << "ERROR: Bad ElemType = " << t
			       << " for " << o << "th order approximation!"
			       << std::endl;
#endif
		  libmesh_error();
		}
	      }
	  }

	  // Discontinuous quadratic shape functions
	  // expressed in the monomials.
	case SECOND:
	  {
	    switch (t)
	      {
	      case NODEELEM:
		return 1;

		// 1D quadratics have 3 DOFs per element
	      case EDGE2:
	      case EDGE3:
	      case EDGE4:
		return 3;

		// 2D quadratics have 6 DOFs per element
	      case TRI3:
	      case TRI6:
	      case QUAD4:
	      case QUAD8:
	      case QUAD9:
		return 6;

		// 3D quadratics have 10 DOFs per element
	      case TET4:
	      case TET10:
	      case HEX8:
	      case HEX20:
	      case HEX27:
	      case PRISM6:
	      case PRISM15:
	      case PRISM18:
	      case PYRAMID5:
		return 10;

	      default:
		{
#ifdef DEBUG
		  libMesh::err << "ERROR: Bad ElemType = " << t
			       << " for " << o << "th order approximation!"
			       << std::endl;
#endif
		  libmesh_error();
		}
	      }
	  }

	  // Discontinuous cubic shape functions
	  // expressed in the monomials.
	case THIRD:
	  {
	    switch (t)
	      {
	      case NODEELEM:
		return 1;

	      case EDGE2:
	      case EDGE3:
	      case EDGE4:
		return 4;

	      case TRI3:
	      case TRI6:
	      case QUAD4:
	      case QUAD8:
	      case QUAD9:
		return 10;

	      case TET4:
	      case TET10:
	      case HEX8:
	      case HEX20:
	      case HEX27:
	      case PRISM6:
	      case PRISM15:
	      case PRISM18:
	      case PYRAMID5:
		return 20;

	      default:
		{
#ifdef DEBUG
		  libMesh::err << "ERROR: Bad ElemType = " << t
			       << " for " << o << "th order approximation!"
			       << std::endl;
#endif
		  libmesh_error();
		}
	      }
	  }

	  // Discontinuous quartic shape functions
	  // expressed in the monomials.
	case FOURTH:
	  {
	    switch (t)
	      {
	      case NODEELEM:
		return 1;

	      case EDGE2:
	      case EDGE3:
	      case EDGE4:
		return 5;

	      case TRI3:
	      case TRI6:
	      case QUAD4:
	      case QUAD8:
	      case QUAD9:
		return 15;

	      case TET4:
	      case TET10:
	      case HEX8:
	      case HEX20:
	      case HEX27:
	      case PRISM6:
	      case PRISM15:
	      case PRISM18:
	      case PYRAMID5:
		return 35;

	      default:
		{
#ifdef DEBUG
		  libMesh::err << "ERROR: Bad ElemType = " << t
			       << " for " << o << "th order approximation!"
			       << std::endl;
#endif
		  libmesh_error();
		}
	      }
	  }

	default:
	  {
	    const unsigned int order = static_cast<unsigned int>(o);
	    switch (t)
	      {
	      case NODEELEM:
		return 1;

	      case EDGE2:
	      case EDGE3:
		return (order+1);

	      case TRI3:
	      case TRI6:
	      case QUAD4:
	      case QUAD8:
	      case QUAD9:
		return (order+1)*(order+2)/2;

	      case TET4:
	      case TET10:
	      case HEX8:
	      case HEX20:
	      case HEX27:
	      case PRISM6:
	      case PRISM15:
	      case PRISM18:
	      case PYRAMID5:
		return (order+1)*(order+2)*(order+3)/6;

	      default:
		{
#ifdef DEBUG
		  libMesh::err << "ERROR: Bad ElemType = " << t
			       << " for " << o << "th order approximation!"
			       << std::endl;
#endif
		  libmesh_error();
		}
	      }
	  }

	  return 0;
	}
    } // l2_hierarchic_n_dofs_per_elem()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs_per_elem(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs_per_elem(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs_per_elem(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs_per_elem(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() specializations are only needed for 2 and 3D
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<commit_msg>Fix bug with L2_HIERARCHIC on non-simplices<commit_after>// $Id$
// The libMesh Finite Element Library.
// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// Local includes
#include "elem.h"
#include "fe.h"
#include "fe_interface.h"

namespace libMesh
{

  // ------------------------------------------------------------
  // Hierarchic-specific implementations

  // Anonymous namespace for local helper functions
  namespace {

    void l2_hierarchic_nodal_soln(const Elem* elem,
				  const Order order,
				  const std::vector<Number>& elem_soln,
				  std::vector<Number>&       nodal_soln,
				  unsigned Dim)
    {
      const unsigned int n_nodes = elem->n_nodes();

      const ElemType elem_type = elem->type();

      nodal_soln.resize(n_nodes);

      const Order totalorder = static_cast<Order>(order + elem->p_level());

      // FEType object to be passed to various FEInterface functions below.
      FEType fe_type(totalorder, L2_HIERARCHIC);

      switch (totalorder)
	{
	  // Constant shape functions
	case CONSTANT:
	  {
	    libmesh_assert (elem_soln.size() == 1);

	    const Number val = elem_soln[0];

	    for (unsigned int n=0; n<n_nodes; n++)
	      nodal_soln[n] = val;

	    return;
	  }

	  // For other orders do interpolation at the nodes
	  // explicitly.
	default:
	  {

	    const unsigned int n_sf =
	      // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
	      FEInterface::n_shape_functions(Dim, fe_type, elem_type);

	    for (unsigned int n=0; n<n_nodes; n++)
	      {
		const Point mapped_point =
		  // FE<Dim,T>::inverse_map(elem, elem->point(n));
		  FEInterface::inverse_map(Dim, fe_type, elem, elem->point(n));

		libmesh_assert (elem_soln.size() == n_sf);

		// Zero before summation
		nodal_soln[n] = 0;

		// u_i = Sum (alpha_i phi_i)
		for (unsigned int i=0; i<n_sf; i++)
		  nodal_soln[n] += elem_soln[i] *
		    // FE<Dim,T>::shape(elem, order, i, mapped_point);
		    FEInterface::shape(Dim, fe_type, elem, i, mapped_point);
	      }

	    return;
	  }
	}
    } // l2_hierarchic_nodal_soln()

    unsigned int l2_hierarchic_n_dofs(const ElemType t, const Order o)
    {
      libmesh_assert (o > 0);
      switch (t)
	{
	case NODEELEM:
	  return 1;
	case EDGE2:
	case EDGE3:
	  return (o+1);
	case QUAD4:
	case QUAD8:
	case QUAD9:
	  return ((o+1)*(o+1));
	case HEX8:
	case HEX20:
	case HEX27:
	  return ((o+1)*(o+1)*(o+1));
	case TRI6:
	  return ((o+1)*(o+2)/2);
	default:
	  libmesh_error();
	}

      libmesh_error();
      return 0;
    } // l2_hierarchic_n_dofs()

  } // anonymous namespace

  // Do full-specialization of nodal_soln() function for every
  // dimension, instead of explicit instantiation at the end of this
  // file.
  // This could be macro-ified so that it fits on one line...
  template <>
  void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }

  template <>
  void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }

  template <>
  void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }

  template <>
  void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem,
				       const Order order,
				       const std::vector<Number>& elem_soln,
				       std::vector<Number>& nodal_soln)
  { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }

  // Full specialization of n_dofs() function for every dimension
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // Full specialization of n_dofs_at_node() function for every dimension.
  // Discontinuous L2 elements only have interior nodes
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }

  // Full specialization of n_dofs_per_elem() function for every dimension.
  template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }
  template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); }

  // L2 Hierarchic FEMs are C^0 continuous
  template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }
  template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return C_ZERO; }

  // L2 Hierarchic FEMs are hierarchic (duh!)
  template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; }

#ifdef LIBMESH_ENABLE_AMR
  // compute_constraints() specializations are only needed for 2 and 3D
  template <>
  void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }

  template <>
  void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &constraints,
						 DofMap &dof_map,
						 const unsigned int variable_number,
						 const Elem* elem)
  { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
#endif // #ifdef LIBMESH_ENABLE_AMR

  // L2-Hierarchic FEM shapes need reinit
  template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }
  template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; }

} // namespace libMesh
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <vector>
#include <sstream>
#include <cmath>

#include <mpi.h> //activate mpi
#include <netcdf_par.h>

#include "dg/algorithm.h"
#include "dg/backend/timer.cuh"
#include "dg/backend/xspacelib.cuh"
#include "dg/backend/interpolation.cuh"
#include "file/read_input.h"
#include "file/nc_utilities.h"

#include "feltor.cuh"
#include "parameters.h"
#include "geometry.h"

/*
   - reads parameters from input.txt or any other given file,
   - integrates the Feltor - functor and
   - writes outputs to a given outputfile using netcdf
        density fields are the real densities in XSPACE ( not logarithmic values)
*/

int main( int argc, char* argv[])
{
    ////////////////////////////////setup MPI///////////////////////////////
    MPI_Init( &argc, &argv);
    int periods[3] = {false, false, true}; //non-, non-, periodic
    int rank, size;
    MPI_Comm_rank( MPI_COMM_WORLD, &rank);
    MPI_Comm_size( MPI_COMM_WORLD, &size);
    int np[3];
    if(rank==0)
    {
        std::cin>> np[0] >> np[1] >>np[2];
        std::cout << "Computing with "<<np[0]<<" "<<np[1]<<" "<<np[2]<<std::endl;
        std::cout << "Size is "<<size<<std::endl;
        assert( size == np[0]*np[1]*np[2]);
    }
    MPI_Bcast( np, 3, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Comm comm;
    MPI_Cart_create( MPI_COMM_WORLD, 3, np, periods, true, &comm);
    ////////////////////////Parameter initialisation//////////////////////////
    std::vector<double> v,v3;
    std::string input, geom;
    if( argc != 4)
    {
        if(rank==0)std::cerr << "ERROR: Wrong number of arguments!\nUsage: "<< argv[0]<<" [inputfile] [geomfile] [outputfile]\n";
        return -1;
    }
    else
    {
        v = file::read_input( argv[1]);
        input = file::read_file( argv[1]);
    }
    const eule::Parameters p( v);
    if(rank==0) p.display( std::cout);

    ////////////////////////////////set up computations///////////////////////////
    try{ v3 = file::read_input( argv[2]); }
    catch (toefl::Message& m) {
        if(rank==0) m.display();
        geom = file::read_file( argv[2]);
        if(rank==0) std::cout << geom << std::endl;
        return -1;
    }
    geom = file::read_file( argv[2]);
    const solovev::GeomParameters gp(v3);
    if(rank==0) gp.display( std::cout);
    double Rmin=gp.R_0-(gp.boxscale)*gp.a;
    double Zmin=-(gp.boxscale)*gp.a*gp.elongation;
    double Rmax=gp.R_0+(gp.boxscale)*gp.a;
    double Zmax=(gp.boxscale)*gp.a*gp.elongation;

    //Make grids: both the dimensions of grid and grid_out must be dividable by the mpi process numbers in that direction
     dg::MPI_Grid3d grid( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n, p.Nx, p.Ny, p.Nz, dg::DIR, dg::DIR, dg::PER, dg::cylindrical, comm);
     dg::Grid3d<double> grid_out = dg::create::ghostless_grid( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n_out, p.Nx_out, p.Ny_out, p.Nz_out, comm);

    //create RHS
    eule::Feltor< dg::MMatrix, dg::MVec, dg::MPrecon > feltor( grid, p,gp);
    eule::Rolkar< dg::MMatrix, dg::MVec, dg::MPrecon > rolkar( grid, p,gp);

    /////////////////////The initial field////////////////////////////////////////////
    //dg::Gaussian3d init0(gp.R_0+p.posX*gp.a, p.posY*gp.a, M_PI/p.Nz, p.sigma, p.sigma, p.sigma, p.amp);
    //dg::BathRZ init0(16,16,p.Nz,Rmin,Zmin, 30.,5.,p.amp);
    //solovev::ZonalFlow init0(gp,p.amp);
    solovev::Nprofile grad(gp); //initial background profile

    std::vector<dg::MVec> y0(4, dg::evaluate( grad, grid)), y1(y0);

    //field aligned blob
    dg::Gaussian gaussian( gp.R_0+p.posX*gp.a, p.posY*gp.a, p.sigma, p.sigma, p.amp);
    dg::GaussianZ gaussianZ( M_PI, p.m_par, 1);
    y1[1] = feltor.dz().evaluate( gaussian, (unsigned)p.Nz/2);
    y1[2] = dg::evaluate( gaussianZ, grid);
    dg::blas1::pointwiseDot( y1[1], y1[2], y1[1]);

    //y1[1] = dg::evaluate( init0, grid);
    //damp the bath on psi boundaries
    //dg::blas1::pointwiseDot(rolkar.damping(), y1[1], y1[1]);
    dg::blas1::axpby( 1., y1[1], 1., y0[1]); //initialize ni
    dg::blas1::transform(y0[1], y0[1], dg::PLUS<>(-1));
    feltor.initializene(y0[1],y0[0]);

    dg::blas1::axpby( 0., y0[2], 0., y0[2]); //set Ue = 0
    dg::blas1::axpby( 0., y0[3], 0., y0[3]); //set Ui = 0

    dg::Karniadakis< std::vector<dg::MVec> > karniadakis( y0, y0[0].size(), p.eps_time);
    karniadakis.init( feltor, rolkar, y0, p.dt);
    double time = 0;

    /////////////////////////////set up netcdf/////////////////////////////////
    file::NC_Error_Handle err;
    int ncid;
    MPI_Info info = MPI_INFO_NULL;
    err = nc_create_par( argv[3], NC_NETCDF4|NC_MPIIO|NC_CLOBBER, comm, info, &ncid);
    err = nc_put_att_text( ncid, NC_GLOBAL, "inputfile", input.size(), input.data());
    err = nc_put_att_text( ncid, NC_GLOBAL, "geomfile",  geom.size(), geom.data());
    int dimids[4], tvarID;
    {
        dg::Grid3d<double> global_grid_out( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n_out, p.Nx_out, p.Ny_out, p.Nz_out);
        err = file::define_dimensions( ncid, dimids, &tvarID, global_grid_out);

        solovev::FieldR fieldR(gp);
        solovev::FieldZ fieldZ(gp);
        solovev::FieldP fieldP(gp);
        dg::HVec vecR = dg::evaluate( fieldR, global_grid_out);
        dg::HVec vecZ = dg::evaluate( fieldZ, global_grid_out);
        dg::HVec vecP = dg::evaluate( fieldP, global_grid_out);
        int vecID[3];
        err = nc_def_var( ncid, "BR", NC_DOUBLE, 3, &dimids[1], &vecID[0]);
        err = nc_def_var( ncid, "BZ", NC_DOUBLE, 3, &dimids[1], &vecID[1]);
        err = nc_def_var( ncid, "BP", NC_DOUBLE, 3, &dimids[1], &vecID[2]);
        err = nc_enddef( ncid);
        err = nc_put_var_double( ncid, vecID[0], vecR.data());
        err = nc_put_var_double( ncid, vecID[1], vecZ.data());
        err = nc_put_var_double( ncid, vecID[2], vecP.data());
        err = nc_redef(ncid);
    }

    std::string names[5] = {"electrons", "ions", "Ue", "Ui", "potential"};
    int dataIDs[5], energyID; //VARIABLE IDS
    //use global dimensionality
    for( unsigned i=0; i<5; i++)
    {
        err = nc_def_var( ncid, names[i].data(), NC_DOUBLE, 4, dimids, &dataIDs[i]);
        err = nc_var_par_access( ncid, dataIDs[i], NC_COLLECTIVE);
    }
    nc_def_var( ncid, "energy", NC_DOUBLE, 1, dimids, &energyID);
    err = nc_var_par_access( ncid, tvarID, NC_COLLECTIVE);
    err = nc_var_par_access( ncid, energyID, NC_COLLECTIVE);
    err = nc_enddef(ncid);
    ///////////////////////////////////first output/////////////////////////
    int dims[3],  coords[3];
    MPI_Cart_get( comm, 3, dims, periods, coords);
    size_t count[4] = {1., grid_out.Nz(), grid_out.n()*(grid_out.Ny()), grid_out.n()*(grid_out.Nx())};
    size_t start[4] = {0, coords[2]*count[1], coords[1]*count[2], coords[0]*count[3]};
    dg::MVec transferD( dg::evaluate(dg::zero, grid));
    dg::HVec transferH( dg::evaluate(dg::zero, grid_out));
    //create local interpolation matrix
    cusp::csr_matrix<int, double, cusp::host_memory> interpolate = dg::create::interpolation( grid_out, grid.local());
    if(rank==0)std::cout << "First write ...\n";
    for( unsigned i=0; i<4; i++)
    {
        dg::blas2::symv( interpolate, y0[i].data(), transferH);
        err = nc_put_vara_double( ncid, dataIDs[i], start, count, transferH.data() );
    }
    transferD = feltor.potential()[0];
    dg::blas2::symv( interpolate, transferD.data(), transferH);
    err = nc_put_vara_double( ncid, dataIDs[4], start, count, transferH.data());
    err = nc_put_vara_double( ncid, tvarID, start, count, &time);
    double E0 = feltor.energy(), energy0 = E0, E1 = 1, diff = 0;
    err = nc_put_vara_double( ncid, energyID, start, count, &E1);
    if(rank==0)std::cout << "First write successful!\n";
    ///////////////////////////////////////Timeloop/////////////////////////////////
    dg::Timer t;
    t.tic();
#ifdef DG_BENCHMARK
    unsigned step = 0;
#endif //DG_BENCHMARK
    for( unsigned i=0; i<p.maxout; i++)
    {

#ifdef DG_BENCHMARK
        dg::Timer ti;
        ti.tic();
#endif//DG_BENCHMARK
        for( unsigned j=0; j<p.itstp; j++)
        {
            try{ karniadakis( feltor, rolkar, y0);}
            catch( dg::Fail& fail) {
                std::cerr << "CG failed to converge to "<<fail.epsilon()<<"\n";
                std::cerr << "Does Simulation respect CFL condition?\n";
                return -1;
            }
        }
        time += p.itstp*p.dt;
#ifdef DG_BENCHMARK
        ti.toc();
        step+=p.itstp;
        if(rank==0)std::cout << "\n\t Step "<<step <<" of "<<p.itstp*p.maxout <<" at time "<<time;
        if(rank==0)std::cout << "\n\t Average time for one step: "<<ti.diff()/(double)p.itstp<<"s";
        ti.tic();
#endif//DG_BENCHMARK
        //err = nc_open_par( argv[3], NC_WRITE|NC_MPIIO, comm, info, &ncid);
        start[0] = i;
        for( unsigned j=0; j<4; j++)
        {
            dg::blas2::symv( interpolate, y0[j].data(), transferH);
            err = nc_put_vara_double( ncid, dataIDs[j], start, count, transferH.data());
        }
        transferD = feltor.potential()[0];
        dg::blas2::symv( interpolate, transferD.data(), transferH);
        err = nc_put_vara_double( ncid, dataIDs[4], start, count, transferH.data() );
        err = nc_put_vara_double( ncid, tvarID, start, count, &time);
        E1 = feltor.energy()/energy0;
        err = nc_put_vara_double( ncid, energyID, start, count, &E1);

        //err = nc_close(ncid); DONT DO IT DOESNT WORK
#ifdef DG_BENCHMARK
        ti.toc();
        if(rank==0)std::cout << "\n\t Time for output: "<<ti.diff()<<"s\n\n"<<std::flush;
        ti.tic();
#endif//DG_BENCHMARK
    }
    t.toc();
    unsigned hour = (unsigned)floor(t.diff()/3600);
    unsigned minute = (unsigned)floor( (t.diff() - hour*3600)/60);
    double second = t.diff() - hour*3600 - minute*60;
    if(rank==0)std::cout << std::fixed << std::setprecision(2) <<std::setfill('0');
    if(rank==0)std::cout <<"Computation Time \t"<<hour<<":"<<std::setw(2)<<minute<<":"<<second<<"\n";
    if(rank==0)std::cout <<"which is         \t"<<t.diff()/p.itstp/p.maxout<<"s/step\n";
    err = nc_close(ncid);
    MPI_Finalize();

    return 0;

}

<commit_msg>feltor_hpc<commit_after>#include <iostream>
#include <iomanip>
#include <vector>
#include <sstream>
#include <cmath>

#include <mpi.h> //activate mpi
#include <netcdf_par.h>

#include "dg/algorithm.h"
#include "dg/backend/timer.cuh"
#include "dg/backend/xspacelib.cuh"
#include "dg/backend/interpolation.cuh"
#include "file/read_input.h"
#include "file/nc_utilities.h"

#include "feltor.cuh"
#include "parameters.h"
#include "geometry.h"

/*
   - reads parameters from input.txt or any other given file,
   - integrates the Feltor - functor and
   - writes outputs to a given outputfile using netcdf
        density fields are the real densities in XSPACE ( not logarithmic values)
*/

int main( int argc, char* argv[])
{
    ////////////////////////////////setup MPI///////////////////////////////
    MPI_Init( &argc, &argv);
    int periods[3] = {false, false, true}; //non-, non-, periodic
    int rank, size;
    MPI_Comm_rank( MPI_COMM_WORLD, &rank);
    MPI_Comm_size( MPI_COMM_WORLD, &size);
    int np[3];
    if(rank==0)
    {
        std::cin>> np[0] >> np[1] >>np[2];
        std::cout << "Computing with "<<np[0]<<" "<<np[1]<<" "<<np[2]<<std::endl;
        std::cout << "Size is "<<size<<std::endl;
        assert( size == np[0]*np[1]*np[2]);
    }
    MPI_Bcast( np, 3, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Comm comm;
    MPI_Cart_create( MPI_COMM_WORLD, 3, np, periods, true, &comm);
    ////////////////////////Parameter initialisation//////////////////////////
    std::vector<double> v,v3;
    std::string input, geom;
    if( argc != 4)
    {
        if(rank==0)std::cerr << "ERROR: Wrong number of arguments!\nUsage: "<< argv[0]<<" [inputfile] [geomfile] [outputfile]\n";
        return -1;
    }
    else
    {
        v = file::read_input( argv[1]);
        input = file::read_file( argv[1]);
    }
    const eule::Parameters p( v);
    if(rank==0) p.display( std::cout);

    ////////////////////////////////set up computations///////////////////////////
    try{ v3 = file::read_input( argv[2]); }
    catch (toefl::Message& m) {
        if(rank==0) m.display();
        geom = file::read_file( argv[2]);
        if(rank==0) std::cout << geom << std::endl;
        return -1;
    }
    geom = file::read_file( argv[2]);
    const solovev::GeomParameters gp(v3);
    if(rank==0) gp.display( std::cout);
    double Rmin=gp.R_0-(gp.boxscale)*gp.a;
    double Zmin=-(gp.boxscale)*gp.a*gp.elongation;
    double Rmax=gp.R_0+(gp.boxscale)*gp.a;
    double Zmax=(gp.boxscale)*gp.a*gp.elongation;

    //Make grids: both the dimensions of grid and grid_out must be dividable by the mpi process numbers in that direction
     dg::MPI_Grid3d grid( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n, p.Nx, p.Ny, p.Nz, dg::DIR, dg::DIR, dg::PER, dg::cylindrical, comm);
     dg::Grid3d<double> grid_out = dg::create::ghostless_grid( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n_out, p.Nx_out, p.Ny_out, p.Nz_out, comm);

    //create RHS
    eule::Feltor< dg::MMatrix, dg::MVec, dg::MPrecon > feltor( grid, p,gp);
    eule::Rolkar< dg::MMatrix, dg::MVec, dg::MPrecon > rolkar( grid, p,gp);

    /////////////////////The initial field////////////////////////////////////////////
    //dg::Gaussian3d init0(gp.R_0+p.posX*gp.a, p.posY*gp.a, M_PI/p.Nz, p.sigma, p.sigma, p.sigma, p.amp);
    //dg::BathRZ init0(16,16,p.Nz,Rmin,Zmin, 30.,5.,p.amp);
    //solovev::ZonalFlow init0(gp,p.amp);
    solovev::Nprofile grad(gp); //initial background profile

    std::vector<dg::MVec> y0(4, dg::evaluate( grad, grid)), y1(y0);

    //field aligned blob
    dg::Gaussian gaussian( gp.R_0+p.posX*gp.a, p.posY*gp.a, p.sigma, p.sigma, p.amp);
    dg::GaussianZ gaussianZ( M_PI, p.m_par, 1);
    y1[1] = feltor.dz().evaluate( gaussian, (unsigned)p.Nz/2);
    y1[2] = dg::evaluate( gaussianZ, grid);
    dg::blas1::pointwiseDot( y1[1], y1[2], y1[1]);

    //y1[1] = dg::evaluate( init0, grid);
    //damp the bath on psi boundaries
    //dg::blas1::pointwiseDot(rolkar.damping(), y1[1], y1[1]);
    dg::blas1::axpby( 1., y1[1], 1., y0[1]); //initialize ni
    dg::blas1::transform(y0[1], y0[1], dg::PLUS<>(-1));
    feltor.initializene(y0[1],y0[0]);

    dg::blas1::axpby( 0., y0[2], 0., y0[2]); //set Ue = 0
    dg::blas1::axpby( 0., y0[3], 0., y0[3]); //set Ui = 0

    dg::Karniadakis< std::vector<dg::MVec> > karniadakis( y0, y0[0].size(), p.eps_time);
    karniadakis.init( feltor, rolkar, y0, p.dt);
    double time = 0;

    /////////////////////////////set up netcdf/////////////////////////////////
    file::NC_Error_Handle err;
    int ncid;
    MPI_Info info = MPI_INFO_NULL;
    err = nc_create_par( argv[3], NC_NETCDF4|NC_MPIIO|NC_CLOBBER, comm, info, &ncid);
    err = nc_put_att_text( ncid, NC_GLOBAL, "inputfile", input.size(), input.data());
    err = nc_put_att_text( ncid, NC_GLOBAL, "geomfile",  geom.size(), geom.data());
    int dimids[4], tvarID;
    {
        dg::Grid3d<double> global_grid_out( Rmin,Rmax, Zmin,Zmax, 0, 2.*M_PI, p.n_out, p.Nx_out, p.Ny_out, p.Nz_out);
        err = file::define_dimensions( ncid, dimids, &tvarID, global_grid_out);

        solovev::FieldR fieldR(gp);
        solovev::FieldZ fieldZ(gp);
        solovev::FieldP fieldP(gp);
        dg::HVec vecR = dg::evaluate( fieldR, global_grid_out);
        dg::HVec vecZ = dg::evaluate( fieldZ, global_grid_out);
        dg::HVec vecP = dg::evaluate( fieldP, global_grid_out);
        int vecID[3];
        err = nc_def_var( ncid, "BR", NC_DOUBLE, 3, &dimids[1], &vecID[0]);
        err = nc_def_var( ncid, "BZ", NC_DOUBLE, 3, &dimids[1], &vecID[1]);
        err = nc_def_var( ncid, "BP", NC_DOUBLE, 3, &dimids[1], &vecID[2]);
        err = nc_enddef( ncid);
        err = nc_put_var_double( ncid, vecID[0], vecR.data());
        err = nc_put_var_double( ncid, vecID[1], vecZ.data());
        err = nc_put_var_double( ncid, vecID[2], vecP.data());
        err = nc_redef(ncid);
    }

    std::string names[5] = {"electrons", "ions", "Ue", "Ui", "potential"};
    int dataIDs[5], energyID; //VARIABLE IDS
    //use global dimensionality
    for( unsigned i=0; i<5; i++)
    {
        err = nc_def_var( ncid, names[i].data(), NC_DOUBLE, 4, dimids, &dataIDs[i]);
        err = nc_var_par_access( ncid, dataIDs[i], NC_COLLECTIVE);
    }
    nc_def_var( ncid, "energy", NC_DOUBLE, 1, dimids, &energyID);
    err = nc_var_par_access( ncid, tvarID, NC_COLLECTIVE);
    err = nc_var_par_access( ncid, energyID, NC_COLLECTIVE);
    err = nc_enddef(ncid);
    ///////////////////////////////////first output/////////////////////////
    int dims[3],  coords[3];
    MPI_Cart_get( comm, 3, dims, periods, coords);
    size_t count[4] = {1., grid_out.Nz(), grid_out.n()*(grid_out.Ny()), grid_out.n()*(grid_out.Nx())};
    size_t start[4] = {0, coords[2]*count[1], coords[1]*count[2], coords[0]*count[3]};
    dg::MVec transferD( dg::evaluate(dg::zero, grid));
    dg::HVec transferH( dg::evaluate(dg::zero, grid_out));
    //create local interpolation matrix
    cusp::csr_matrix<int, double, cusp::host_memory> interpolate = dg::create::interpolation( grid_out, grid.local());
    if(rank==0)std::cout << "First write ...\n";
    for( unsigned i=0; i<4; i++)
    {
        dg::blas2::symv( interpolate, y0[i].data(), transferH);
        err = nc_put_vara_double( ncid, dataIDs[i], start, count, transferH.data() );
    }
    transferD = feltor.potential()[0];
    dg::blas2::symv( interpolate, transferD.data(), transferH);
    err = nc_put_vara_double( ncid, dataIDs[4], start, count, transferH.data());
    err = nc_put_vara_double( ncid, tvarID, start, count, &time);
    double E0 = feltor.energy(), energy0 = E0, E1 = 1, diff = 0;
    err = nc_put_vara_double( ncid, energyID, start, count, &E1);
    if(rank==0)std::cout << "First write successful!\n";
    ///////////////////////////////////////Timeloop/////////////////////////////////
    dg::Timer t;
    t.tic();
#ifdef DG_BENCHMARK
    unsigned step = 0;
#endif //DG_BENCHMARK
    for( unsigned i=0; i<p.maxout; i++)
    {

#ifdef DG_BENCHMARK
        dg::Timer ti;
        ti.tic();
#endif//DG_BENCHMARK
        for( unsigned j=0; j<p.itstp; j++)
        {
            try{ karniadakis( feltor, rolkar, y0);}
            catch( dg::Fail& fail) {
                std::cerr << "CG failed to converge to "<<fail.epsilon()<<"\n";
                std::cerr << "Does Simulation respect CFL condition?\n";
                return -1;
            }
        }
        time += p.itstp*p.dt;
#ifdef DG_BENCHMARK
        ti.toc();
        step+=p.itstp;
        if(rank==0)std::cout << "\n\t Step "<<step <<" of "<<p.itstp*p.maxout <<" at time "<<time;
        if(rank==0)std::cout << "\n\t Average time for one step: "<<ti.diff()/(double)p.itstp<<"s";
        ti.tic();
#endif//DG_BENCHMARK
        //err = nc_open_par( argv[3], NC_WRITE|NC_MPIIO, comm, info, &ncid);
        start[0] = i;
        for( unsigned j=0; j<4; j++)
        {
            dg::blas2::symv( interpolate, y0[j].data(), transferH);
            err = nc_put_vara_double( ncid, dataIDs[j], start, count, transferH.data());
        }
        transferD = feltor.potential()[0];
        dg::blas2::symv( interpolate, transferD.data(), transferH);
        err = nc_put_vara_double( ncid, dataIDs[4], start, count, transferH.data() );
        err = nc_put_vara_double( ncid, tvarID, start, count, &time);
        E1 = feltor.energy()/energy0;
        err = nc_put_vara_double( ncid, energyID, start, count, &E1);

        //err = nc_close(ncid); DONT DO IT!
#ifdef DG_BENCHMARK
        ti.toc();
        if(rank==0)std::cout << "\n\t Time for output: "<<ti.diff()<<"s\n\n"<<std::flush;
#endif//DG_BENCHMARK
    }
    t.toc();
    unsigned hour = (unsigned)floor(t.diff()/3600);
    unsigned minute = (unsigned)floor( (t.diff() - hour*3600)/60);
    double second = t.diff() - hour*3600 - minute*60;
    if(rank==0)std::cout << std::fixed << std::setprecision(2) <<std::setfill('0');
    if(rank==0)std::cout <<"Computation Time \t"<<hour<<":"<<std::setw(2)<<minute<<":"<<second<<"\n";
    if(rank==0)std::cout <<"which is         \t"<<t.diff()/p.itstp/p.maxout<<"s/step\n";
    err = nc_close(ncid);
    MPI_Finalize();

    return 0;

}

<|endoftext|>