<commit_before>/*
 * Copyright 2009-2016 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <stdio.h>
#include <stdexcept>
#include "xmltopologyreader.h"

namespace votca { namespace csg {

bool XMLTopologyReader::ReadTopology(string filename, Topology &top)  {
    _top = ⊤

    Property options;
    load_property_from_xml(options, filename);
    ParseRoot(options.get("topology"));

    _top->RebuildExclusions();
    return true;
}

void XMLTopologyReader::ReadTopolFile(string file) {
    TopologyReader *reader;
    reader = TopReaderFactory().Create(file);
    if(!reader)
        throw runtime_error(file + ": unknown topology format");

    reader->ReadTopology(file, *_top);

    delete reader;
    // Clean XML molecules and beads.
}

void XMLTopologyReader::ParseRoot(Property &property)  {
    _has_base_topology = false;
    if (property.hasAttribute("base")) {
        ReadTopolFile(property.getAttribute<string>("base"));
        _has_base_topology = true;
    }

    // Iterate over keys at first level.
    for (Property::iterator it = property.begin(); it != property.end(); ++it) {
        if (it->name() == "h5md_particle_group") {
            _top->setParticleGroup(it->getAttribute<string>("name"));
        } else if (it->name() == "molecules") {
            _mol_index = 1;
            _bead_index = 0;
            ParseMolecules(*it);
        } else if (it->name() == "bonded") {
            ParseBonded(*it);
        } else if (it->name() == "box") {
            ParseBox(*it);
        } else if (it->name() == "beadtypes") {
            ParseBeadTypes(*it);
        } else {
            throw runtime_error("unknown tag: topology."+ it->name());
        }
    }
}

void XMLTopologyReader::ParseBox(Property &p) {
    matrix m(0.0);
    m[0][0] = p.getAttribute<double>("xx");
    m[1][1] = p.getAttribute<double>("yy");
    m[2][2] = p.getAttribute<double>("zz");
    _top->setBox(m);
}

void XMLTopologyReader::ParseMolecules(Property &p) {
    for (Property::iterator it = p.begin(); it != p.end(); ++it) {
        if (it->name() == "clear") {
            _top->ClearMoleculeList();
        } else if (it->name() == "rename") {
            string molname = it->getAttribute<string>("name");
            string range = it->getAttribute<string>("range");
            _top->RenameMolecules(range, molname);
        } else if (it->name() == "define" || it->name() == "molecule") {
            string molname = it->getAttribute<string>("name");
            int first = 0;
            if (it->name() == "define")
                first = it->getAttribute<int>("first");
            int nbeads = it->getAttribute<int>("nbeads");
            int nmols = it->getAttribute<int>("nmols");
            if (it->name() == "define" && first < 1)
                throw std::runtime_error("Attribute first is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("first")));
            if (nbeads < 1)
                throw std::runtime_error("Attribute nbeads is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("nbeads")));
            if (nmols < 1)
                throw std::runtime_error("Attribute nmols is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("nmols")));
            if (it->name() == "define") {
                _top->CreateMoleculesByRange(molname, first, nbeads, nmols);
            } else {
                if (_has_base_topology)
                    throw std::runtime_error("The defined list of beads only works for pure xml topology, without 'base' attribute.");
                ParseMolecule(*it, molname, nbeads, nmols);
            }
        }
    }
}

void XMLTopologyReader::ParseMolecule(Property &p, string molname, int nbeads, int nmols) {
    vector<XMLBead*> xmlBeads;
    for (Property::iterator it=p.begin(); it != p.end(); ++it) {
        if (it->name() == "bead") {
            string atname = it->getAttribute<string>("name");
            string attype = it->getAttribute<string>("type");
            double atmass, atq;
            try {
                atmass = it->getAttribute<double>("mass");
            } catch (runtime_error) {
                atmass = 1.0;
            }
            try {
                atq = it->getAttribute<double>("q");
            } catch (runtime_error) {
                atq = 0.0;
            }
            XMLBead *xmlBead = new XMLBead(atname, attype, atmass, atq);
            xmlBeads.push_back(xmlBead);
        } else {
            throw std::runtime_error(
                "Wrong element under topology.molecules.molecule: " + it->name());
        }
    }
    // Create molecule in topology. Replicate data.
    int resnr = _top->ResidueCount();
    for (int mn = 0; mn < nmols; mn++) {
        Molecule *mi = _top->CreateMolecule(molname);
        XMLMolecule *xmlMolecule = new XMLMolecule(molname, nmols);
        xmlMolecule->pid = mi->getId();
        xmlMolecule->mi = mi;
        _molecules.insert(make_pair(molname, xmlMolecule));
        for (vector<XMLBead*>::iterator itb = xmlBeads.begin(); itb != xmlBeads.end(); ++itb) {
            stringstream bname;
            XMLBead &b = **itb;
            _top->CreateResidue(molname, resnr);
            BeadType *type = _top->GetOrCreateBeadType(b.type);
            Bead *bead = _top->CreateBead(1, b.name, type, resnr, b.mass, b.q);
            bname << _mol_index << ":" << molname << ":" << b.name;
            mi->AddBead(bead, bname.str());

            // Data for bonded terms.
            XMLBead *b_rep = new XMLBead(b);
            b_rep->pid = _bead_index;
            if (xmlMolecule->name2beads.count(b.name) != 0)
                throw std::runtime_error(
                    "Atom " + b.name + " in molecule " + molname + " already exists.");
            xmlMolecule->name2beads.insert(make_pair(b.name, b_rep));
            _bead_index++;
        }
        resnr++;
    }
    _mol_index++;

    // clean up
    for (std::vector<XMLBead*>::iterator itb = xmlBeads.begin(); itb != xmlBeads.end(); ++itb) {
        delete (*itb);
    }
}

void XMLTopologyReader::ParseBeadTypes(Property &el) {
    for (Property::iterator it = el.begin(); it != el.end(); ++it) {
        if (it->name() == "rename") {
            string name = it->getAttribute<string>("name");
            string newname = it->getAttribute<string>("newname");
            if (name == "" || newname == "")
                throw runtime_error("invalid rename tag, name or newname are empty.");
            _top->RenameBeadType(name, newname);
        } else if (it->name() == "mass") {
            string name = it->getAttribute<string>("name");
            double value = it->getAttribute<double>("value");
            _top->SetBeadTypeMass(name, value);
        } else {
            throw std::runtime_error("Wrong element under beadtypes: " + it->name());
        }
    }
}

void XMLTopologyReader::ParseBonded(Property &el) {
    for (Property::iterator it = el.begin(); it != el.end(); ++it) {
        if (it->name() == "bond") {
            ParseBond(*it);
        } else if (it->name() == "angle") {
            ParseAngle(*it);
        } else if (it->name() == "dihedral") {
            ParseDihedral(*it);
        } else {
            throw std::runtime_error("Wrong element under bonded: " + it->name());
        }
    }
}

void XMLTopologyReader::ParseBond(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 2 == 1)
        throw runtime_error("Wrong number of beads in bond: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        if (b1.molname == b2.molname) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                ic = new IBond(xmlBead1.pid, xmlBead2.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}

void XMLTopologyReader::ParseAngle(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 3 == 1)
        throw runtime_error("Wrong number of beads in angle: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        BondBead b3(*(it++));
        if ((b1.molname == b2.molname) && (b2.molname == b3.molname)) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
                ic = new IAngle(xmlBead1.pid, xmlBead2.pid, xmlBead3.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}
void XMLTopologyReader::ParseDihedral(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 4 == 1)
        throw runtime_error("Wrong number of beads in dihedral: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        BondBead b3(*(it++));
        BondBead b4(*(it++));
        if ((b1.molname == b2.molname) && (b3.molname == b4.molname) &&
                (b1.molname == b4.molname)) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
                XMLBead &xmlBead4 = *xmlMolecule.name2beads[b4.atname];
                ic = new IDihedral(xmlBead1.pid, xmlBead2.pid,
                                   xmlBead3.pid, xmlBead4.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}

XMLTopologyReader::~XMLTopologyReader() {
    // Clean _molecules map
    for (MoleculesMap::iterator it = _molecules.begin(); it != _molecules.end(); ++it) {
        XMLMolecule *xmlMolecule = it->second;
        for (vector<XMLBead*>::iterator itb = xmlMolecule->beads.begin();
            itb != xmlMolecule->beads.end(); ++itb) {
            delete (*itb);
        }
        xmlMolecule->beads.clear();
        delete xmlMolecule;
    }
}

}}

<commit_msg>xmltopologyreader: add resid tag<commit_after>/*
 * Copyright 2009-2016 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include <stdio.h>
#include <stdexcept>
#include "xmltopologyreader.h"

namespace votca { namespace csg {

bool XMLTopologyReader::ReadTopology(string filename, Topology &top)  {
    _top = ⊤

    Property options;
    load_property_from_xml(options, filename);
    ParseRoot(options.get("topology"));

    _top->RebuildExclusions();
    return true;
}

void XMLTopologyReader::ReadTopolFile(string file) {
    TopologyReader *reader;
    reader = TopReaderFactory().Create(file);
    if(!reader)
        throw runtime_error(file + ": unknown topology format");

    reader->ReadTopology(file, *_top);

    delete reader;
    // Clean XML molecules and beads.
}

void XMLTopologyReader::ParseRoot(Property &property)  {
    _has_base_topology = false;
    if (property.hasAttribute("base")) {
        ReadTopolFile(property.getAttribute<string>("base"));
        _has_base_topology = true;
    }

    // Iterate over keys at first level.
    for (Property::iterator it = property.begin(); it != property.end(); ++it) {
        if (it->name() == "h5md_particle_group") {
            _top->setParticleGroup(it->getAttribute<string>("name"));
        } else if (it->name() == "molecules") {
            _mol_index = 1;
            _bead_index = 0;
            ParseMolecules(*it);
        } else if (it->name() == "bonded") {
            ParseBonded(*it);
        } else if (it->name() == "box") {
            ParseBox(*it);
        } else if (it->name() == "beadtypes") {
            ParseBeadTypes(*it);
        } else {
            throw runtime_error("unknown tag: topology."+ it->name());
        }
    }
}

void XMLTopologyReader::ParseBox(Property &p) {
    matrix m(0.0);
    m[0][0] = p.getAttribute<double>("xx");
    m[1][1] = p.getAttribute<double>("yy");
    m[2][2] = p.getAttribute<double>("zz");
    _top->setBox(m);
}

void XMLTopologyReader::ParseMolecules(Property &p) {
    for (Property::iterator it = p.begin(); it != p.end(); ++it) {
        if (it->name() == "clear") {
            _top->ClearMoleculeList();
        } else if (it->name() == "rename") {
            string molname = it->getAttribute<string>("name");
            string range = it->getAttribute<string>("range");
            _top->RenameMolecules(range, molname);
        } else if (it->name() == "define" || it->name() == "molecule") {
            string molname = it->getAttribute<string>("name");
            int first = 0;
            if (it->name() == "define")
                first = it->getAttribute<int>("first");
            int nbeads = it->getAttribute<int>("nbeads");
            int nmols = it->getAttribute<int>("nmols");
            if (it->name() == "define" && first < 1)
                throw std::runtime_error("Attribute first is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("first")));
            if (nbeads < 1)
                throw std::runtime_error("Attribute nbeads is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("nbeads")));
            if (nmols < 1)
                throw std::runtime_error("Attribute nmols is suppose to be > 0, but found " +
                    boost::lexical_cast<string>(it->getAttribute<string>("nmols")));
            if (it->name() == "define") {
                _top->CreateMoleculesByRange(molname, first, nbeads, nmols);
            } else {
                if (_has_base_topology)
                    throw std::runtime_error("The defined list of beads only works for pure xml topology, without 'base' attribute.");
                ParseMolecule(*it, molname, nbeads, nmols);
            }
        }
    }
}

void XMLTopologyReader::ParseMolecule(Property &p, string molname, int nbeads, int nmols) {
    vector<XMLBead*> xmlBeads;
    vector<int> xmlResidues;
    for (Property::iterator it=p.begin(); it != p.end(); ++it) {
        if (it->name() == "bead") {
            string atname = it->getAttribute<string>("name");
            string attype = it->getAttribute<string>("type");
            double atmass, atq;
            int resid;
            try {
                atmass = it->getAttribute<double>("mass");
            } catch (runtime_error) {
                atmass = 1.0;
            }
            try {
                atq = it->getAttribute<double>("q");
            } catch (runtime_error) {
                atq = 0.0;
            }
            try {
                resid = it->getAttribute<int>("resid");
                if (resid<=0)
                    throw std::runtime_error(
                        "Residue count for beads in topology.molecules.molecule has to be greater than zero");
            } catch (runtime_error) {
                resid = -1;
            }
            if (!xmlResidues.empty()){
                if (!(xmlResidues.back()==resid || xmlResidues.back()==(resid-1)))
                    throw std::runtime_error(
                        "Residue count for beads in topology.molecules.molecule does not increase monotonically in steps of 1");
                if (xmlResidues.back()!=-1 && resid==-1)
                    throw std::runtime_error(
                        "Residue count for beads in topology.molecules.molecule has to be declared for all beads or for none");
            }
            xmlResidues.push_back(resid);
            XMLBead *xmlBead = new XMLBead(atname, attype, atmass, atq);
            xmlBeads.push_back(xmlBead);
        } else {
            throw std::runtime_error(
                "Wrong element under topology.molecules.molecule: " + it->name());
        }
    }
    if (xmlResidues.size() != xmlBeads.size())
        throw std::runtime_error(
            "Number of elements in bead-vector and residue-vector are not identical");
    // Create molecule in topology. Replicate data.
    int resnr = _top->ResidueCount();
    if (!xmlResidues.empty()){
        if (!(xmlResidues.front() == resnr+1 || xmlResidues.front() == -1))
        throw std::runtime_error(
            "Residue count for beads in topology.molecules.molecule has to be greater than the number of residues already in the topology");
    }
    for (int mn = 0; mn < nmols; mn++) {
        Molecule *mi = _top->CreateMolecule(molname);
        XMLMolecule *xmlMolecule = new XMLMolecule(molname, nmols);
        xmlMolecule->pid = mi->getId();
        xmlMolecule->mi = mi;
        _molecules.insert(make_pair(molname, xmlMolecule));
        vector<int>::iterator resit = xmlResidues.begin();
        for (vector<XMLBead*>::iterator itb = xmlBeads.begin(); itb != xmlBeads.end(); ++itb, ++resit) {
            stringstream bname;
            XMLBead &b = **itb;
            if (*resit != -1){
                if (_top->ResidueCount() < *resit){
                    _top->CreateResidue(molname, resnr);
                resnr = *resit - 1;
                }
            }else{
                _top->CreateResidue(molname, resnr);
            }
            BeadType *type = _top->GetOrCreateBeadType(b.type);
            Bead *bead = _top->CreateBead(1, b.name, type, resnr, b.mass, b.q);
            bname << _mol_index << ":" << molname << ":" << b.name;
            mi->AddBead(bead, bname.str());

            // Data for bonded terms.
            XMLBead *b_rep = new XMLBead(b);
            b_rep->pid = _bead_index;
            if (xmlMolecule->name2beads.count(b.name) != 0)
                throw std::runtime_error(
                    "Atom " + b.name + " in molecule " + molname + " already exists.");
            xmlMolecule->name2beads.insert(make_pair(b.name, b_rep));
            _bead_index++;
        }
        resnr++;
    }
    _mol_index++;

    // clean up
    for (std::vector<XMLBead*>::iterator itb = xmlBeads.begin(); itb != xmlBeads.end(); ++itb) {
        delete (*itb);
    }
}

void XMLTopologyReader::ParseBeadTypes(Property &el) {
    for (Property::iterator it = el.begin(); it != el.end(); ++it) {
        if (it->name() == "rename") {
            string name = it->getAttribute<string>("name");
            string newname = it->getAttribute<string>("newname");
            if (name == "" || newname == "")
                throw runtime_error("invalid rename tag, name or newname are empty.");
            _top->RenameBeadType(name, newname);
        } else if (it->name() == "mass") {
            string name = it->getAttribute<string>("name");
            double value = it->getAttribute<double>("value");
            _top->SetBeadTypeMass(name, value);
        } else {
            throw std::runtime_error("Wrong element under beadtypes: " + it->name());
        }
    }
}

void XMLTopologyReader::ParseBonded(Property &el) {
    for (Property::iterator it = el.begin(); it != el.end(); ++it) {
        if (it->name() == "bond") {
            ParseBond(*it);
        } else if (it->name() == "angle") {
            ParseAngle(*it);
        } else if (it->name() == "dihedral") {
            ParseDihedral(*it);
        } else {
            throw std::runtime_error("Wrong element under bonded: " + it->name());
        }
    }
}

void XMLTopologyReader::ParseBond(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 2 == 1)
        throw runtime_error("Wrong number of beads in bond: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        if (b1.molname == b2.molname) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                ic = new IBond(xmlBead1.pid, xmlBead2.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}

void XMLTopologyReader::ParseAngle(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 3 == 1)
        throw runtime_error("Wrong number of beads in angle: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        BondBead b3(*(it++));
        if ((b1.molname == b2.molname) && (b2.molname == b3.molname)) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
                ic = new IAngle(xmlBead1.pid, xmlBead2.pid, xmlBead3.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}
void XMLTopologyReader::ParseDihedral(Property &p) {
    string name = p.get("name").as<string>();
    string beads = p.get("beads").as<string>();
    Tokenizer tok(beads, " \n\t");
    vector<string> bead_list;
    tok.ToVector(bead_list);
    if (bead_list.size() % 4 == 1)
        throw runtime_error("Wrong number of beads in dihedral: " + name);
    Interaction *ic = NULL;
    typedef pair<MoleculesMap::iterator, MoleculesMap::iterator> MRange;
    int b_index = 0;
    for (vector<string>::iterator it = bead_list.begin(); it != bead_list.end(); ) {
        BondBead b1(*(it++));
        BondBead b2(*(it++));
        BondBead b3(*(it++));
        BondBead b4(*(it++));
        if ((b1.molname == b2.molname) && (b3.molname == b4.molname) &&
                (b1.molname == b4.molname)) {
            // Iterates over molecules and gets atom pids.
            MRange mRange = _molecules.equal_range(b1.molname);
            for (MoleculesMap::iterator itm = mRange.first;
                 itm != mRange.second; ++itm) {
                XMLMolecule &xmlMolecule = *itm->second;
                XMLBead &xmlBead1 = *xmlMolecule.name2beads[b1.atname];
                XMLBead &xmlBead2 = *xmlMolecule.name2beads[b2.atname];
                XMLBead &xmlBead3 = *xmlMolecule.name2beads[b3.atname];
                XMLBead &xmlBead4 = *xmlMolecule.name2beads[b4.atname];
                ic = new IDihedral(xmlBead1.pid, xmlBead2.pid,
                                   xmlBead3.pid, xmlBead4.pid);
                ic->setGroup(name);
                ic->setIndex(b_index);
                ic->setMolecule(xmlMolecule.pid);
                xmlMolecule.mi->AddInteraction(ic);
                _top->AddBondedInteraction(ic);
                b_index++;
            }
        } else {
            throw std::runtime_error(
                "Beads from different molecules, not supported!");
        }
    }
}

XMLTopologyReader::~XMLTopologyReader() {
    // Clean _molecules map
    for (MoleculesMap::iterator it = _molecules.begin(); it != _molecules.end(); ++it) {
        XMLMolecule *xmlMolecule = it->second;
        for (vector<XMLBead*>::iterator itb = xmlMolecule->beads.begin();
            itb != xmlMolecule->beads.end(); ++itb) {
            delete (*itb);
        }
        xmlMolecule->beads.clear();
        delete xmlMolecule;
    }
}

}}

<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Ripcord Software Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
**/

#include <gtest/gtest.h>

#include <thread>

#include "../libjsapi.h"

static rs::jsapi::Runtime rt_;

class MultiRuntimeTests : public ::testing::Test {
protected:
    virtual void SetUp() {

    }

    virtual void TearDown() {

    }

public:
    static bool SanityCheckWhatMessage(const char* msg);
};

bool MultiRuntimeTests::SanityCheckWhatMessage(const char* msg) {
    while (*msg != '\0') {
        if (*msg < 0x0d || *msg > 0x7e) {
            return false;
        }
        msg++;
    }
    return true;
}

TEST_F(MultiRuntimeTests, test1) {
    ASSERT_THROW({
        rs::jsapi::Runtime rt;
    }, rs::jsapi::RuntimeThreadInstanceException);
}

TEST_F(MultiRuntimeTests, test2) {
    std::thread t([](){
        rs::jsapi::Runtime rt;
        rs::jsapi::Script script(rt, "(function(){return 42;})();");
        script.Compile();

        rs::jsapi::Value result(rt);
        script.Execute(result);

        ASSERT_TRUE(result.isNumber());
        ASSERT_EQ(42, result.toNumber());
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test3) {
    std::thread t([](){
        rs::jsapi::Runtime rt1;

        ASSERT_THROW({
            rs::jsapi::Runtime rt2;
        }, rs::jsapi::RuntimeThreadInstanceException);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test4) {
    std::thread t([](){
        rs::jsapi::Runtime rt1;

        ASSERT_THROW({
            rs::jsapi::Runtime rt2;
        }, rs::jsapi::RuntimeThreadInstanceException);

        ASSERT_THROW({
            rs::jsapi::Runtime rt3;
        }, rs::jsapi::RuntimeThreadInstanceException);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test4b) {
    std::thread t([](){
        bool thrown = false;
        rs::jsapi::Runtime rt1;

        try {
            rs::jsapi::Runtime rt2;
        } catch (const rs::jsapi::RuntimeThreadInstanceException& ex) {
            auto what = ex.what();
            ASSERT_TRUE(MultiRuntimeTests::SanityCheckWhatMessage(what));
            thrown = true;
        }

        ASSERT_TRUE(thrown);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test5) {
    std::thread t([](){
        do {
            rs::jsapi::Runtime rt;
            rs::jsapi::Script script(rt, "(function(){return 42;})();");
            script.Compile();

            rs::jsapi::Value result(rt);
            script.Execute(result);

            ASSERT_TRUE(result.isNumber());
            ASSERT_EQ(42, result.toNumber());
        } while (false);

        do {
            rs::jsapi::Runtime rt;
            rs::jsapi::Script script(rt, "(function(){return 42;})();");
            script.Compile();

            rs::jsapi::Value result(rt);
            script.Execute(result);

            ASSERT_TRUE(result.isNumber());
            ASSERT_EQ(42, result.toNumber());
        } while (false);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test6) {
    std::thread t([](){
        rs::jsapi::Runtime rt;

        rs::jsapi::Script bootstrapScript1(rt, "var count = 42;");
        bootstrapScript1.Compile();
        bootstrapScript1.Execute();

        auto context2 = rt.NewContext();
        rs::jsapi::Script bootstrapScript2(*context2, "var count = 42;");
        bootstrapScript2.Compile();
        bootstrapScript2.Execute();

        rs::jsapi::Script script1(rt, "(function(){return count++;})();");
        script1.Compile();

        rs::jsapi::Script script2(*context2, "(function(){return count++;})();");
        script2.Compile();

        rs::jsapi::Value result1a(rt);
        script1.Execute(result1a);

        ASSERT_TRUE(result1a.isNumber());
        ASSERT_EQ(42, result1a.toNumber());

        rs::jsapi::Value result1b(rt);
        script1.Execute(result1b);

        ASSERT_TRUE(result1b.isNumber());
        ASSERT_EQ(43, result1b.toNumber());

        rs::jsapi::Value result2a(*context2);
        script2.Execute(result2a);

        ASSERT_TRUE(result2a.isNumber());
        ASSERT_EQ(42, result2a.toNumber());
    });

    t.join();
}<commit_msg>Correct thread detection on OSX for multi-runtime tests * OSX uses the same thread when initializing statics and executing main, this fails the multi-runtime units<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Ripcord Software Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
**/

#include <gtest/gtest.h>

#include <thread>

#include "../libjsapi.h"

static rs::jsapi::Runtime rt_;

class MultiRuntimeTests : public ::testing::Test {
protected:
    virtual void SetUp() {

    }

    virtual void TearDown() {

    }

public:
    static bool SanityCheckWhatMessage(const char* msg);
};

bool MultiRuntimeTests::SanityCheckWhatMessage(const char* msg) {
    while (*msg != '\0') {
        if (*msg < 0x0d || *msg > 0x7e) {
            return false;
        }
        msg++;
    }
    return true;
}

TEST_F(MultiRuntimeTests, test1) {
#ifndef __APPLE__
    ASSERT_THROW({
        rs::jsapi::Runtime rt;
    }, rs::jsapi::RuntimeThreadInstanceException);
#endif
}

TEST_F(MultiRuntimeTests, test2) {
    std::thread t([](){
        rs::jsapi::Runtime rt;
        rs::jsapi::Script script(rt, "(function(){return 42;})();");
        script.Compile();

        rs::jsapi::Value result(rt);
        script.Execute(result);

        ASSERT_TRUE(result.isNumber());
        ASSERT_EQ(42, result.toNumber());
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test3) {
    std::thread t([](){
        rs::jsapi::Runtime rt1;

        ASSERT_THROW({
            rs::jsapi::Runtime rt2;
        }, rs::jsapi::RuntimeThreadInstanceException);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test4) {
    std::thread t([](){
        rs::jsapi::Runtime rt1;

        ASSERT_THROW({
            rs::jsapi::Runtime rt2;
        }, rs::jsapi::RuntimeThreadInstanceException);

        ASSERT_THROW({
            rs::jsapi::Runtime rt3;
        }, rs::jsapi::RuntimeThreadInstanceException);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test4b) {
    std::thread t([](){
        bool thrown = false;
        rs::jsapi::Runtime rt1;

        try {
            rs::jsapi::Runtime rt2;
        } catch (const rs::jsapi::RuntimeThreadInstanceException& ex) {
            auto what = ex.what();
            ASSERT_TRUE(MultiRuntimeTests::SanityCheckWhatMessage(what));
            thrown = true;
        }

        ASSERT_TRUE(thrown);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test5) {
    std::thread t([](){
        do {
            rs::jsapi::Runtime rt;
            rs::jsapi::Script script(rt, "(function(){return 42;})();");
            script.Compile();

            rs::jsapi::Value result(rt);
            script.Execute(result);

            ASSERT_TRUE(result.isNumber());
            ASSERT_EQ(42, result.toNumber());
        } while (false);

        do {
            rs::jsapi::Runtime rt;
            rs::jsapi::Script script(rt, "(function(){return 42;})();");
            script.Compile();

            rs::jsapi::Value result(rt);
            script.Execute(result);

            ASSERT_TRUE(result.isNumber());
            ASSERT_EQ(42, result.toNumber());
        } while (false);
    });

    t.join();
}

TEST_F(MultiRuntimeTests, test6) {
    std::thread t([](){
        rs::jsapi::Runtime rt;

        rs::jsapi::Script bootstrapScript1(rt, "var count = 42;");
        bootstrapScript1.Compile();
        bootstrapScript1.Execute();

        auto context2 = rt.NewContext();
        rs::jsapi::Script bootstrapScript2(*context2, "var count = 42;");
        bootstrapScript2.Compile();
        bootstrapScript2.Execute();

        rs::jsapi::Script script1(rt, "(function(){return count++;})();");
        script1.Compile();

        rs::jsapi::Script script2(*context2, "(function(){return count++;})();");
        script2.Compile();

        rs::jsapi::Value result1a(rt);
        script1.Execute(result1a);

        ASSERT_TRUE(result1a.isNumber());
        ASSERT_EQ(42, result1a.toNumber());

        rs::jsapi::Value result1b(rt);
        script1.Execute(result1b);

        ASSERT_TRUE(result1b.isNumber());
        ASSERT_EQ(43, result1b.toNumber());

        rs::jsapi::Value result2a(*context2);
        script2.Execute(result2a);

        ASSERT_TRUE(result2a.isNumber());
        ASSERT_EQ(42, result2a.toNumber());
    });

    t.join();
}<|endoftext|>


<commit_before>//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// debug.cpp: Debugging utilities.

#include "common/debug.h"

#include <stdio.h>
#include <stdarg.h>

namespace gl
{
void trace(const char *format, ...)
{
    if (true)
    {
        if (format)
        {
            FILE *file = fopen("debug.txt", "a");

            if (file)
            {
                va_list vararg;
                va_start(vararg, format);
                vfprintf(file, format, vararg);
                va_end(vararg);

                fclose(file);
            }
        }
    }
}
}
<commit_msg>Make it easier to disable tracing<commit_after>//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// debug.cpp: Debugging utilities.

#include "common/debug.h"

#include <stdio.h>
#include <stdarg.h>

static bool trace_on = true;

namespace gl
{
void trace(const char *format, ...)
{
    if (trace_on)
    {
        if (format)
        {
            FILE *file = fopen("debug.txt", "a");

            if (file)
            {
                va_list vararg;
                va_start(vararg, format);
                vfprintf(file, format, vararg);
                va_end(vararg);

                fclose(file);
            }
        }
    }
}
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include <cassert>
#include <algorithm>

#include "OpenEXR/ImathLimits.h"

#include <GL/gl.h>

#include "maya/MGlobal.h"
#include "maya/MImage.h"
#include "maya/MImageFileInfo.h"

#include "IECore/ImageReader.h"
#include "IECore/ImagePrimitive.h"
#include "IECore/VectorTypedData.h"

#include "IECoreMaya/ImageFile.h"

using namespace IECore;
using namespace IECoreMaya;

ImageFile::ImageFile() : m_rData( 0 ), m_gData( 0 ), m_bData( 0 ), m_aData( 0 )
{
}

ImageFile::~ImageFile()
{
}

void *ImageFile::creator()
{
	return new ImageFile;
}

template<typename T>
static float getFloatData( ConstDataPtr d, int idx )
{
	assert( idx >= 0 );

	if ( idx >= (int)(runTimeCast< const T >(d)->readable().size()) )
	{
		return 0.0f;
	}

	return runTimeCast< const T >(d)->readable()[ idx ];
}

template<typename T>
static float getNormalizedFloatData( ConstDataPtr d, int idx )
{
	return getFloatData<T>( d, idx ) / Imath::limits<typename T::ValueType::value_type>::max();
}

static float getFloatDataDespatch( ConstDataPtr d, int idx )
{
	switch ( d->typeId() )
	{
		case FloatVectorDataTypeId:
			return getFloatData<FloatVectorData>( d, idx );
		case DoubleVectorDataTypeId:
			return getFloatData<DoubleVectorData>( d, idx );
		case HalfVectorDataTypeId:
			return getFloatData<HalfVectorData>( d, idx );
		case IntVectorDataTypeId:
			return getNormalizedFloatData<IntVectorData>( d, idx );
		case UIntVectorDataTypeId:
			return getNormalizedFloatData<UIntVectorData>( d, idx );
		case CharVectorDataTypeId:
			return getNormalizedFloatData<CharVectorData>( d, idx );
		case UCharVectorDataTypeId:
			return getNormalizedFloatData<UCharVectorData>( d, idx );
		case LongVectorDataTypeId:
			return getNormalizedFloatData<LongVectorData>( d, idx );
		default:
			throw Exception("Invalid channel data type");
	}
}

MStatus ImageFile::open( MString pathName, MImageFileInfo* info )
{
	ImagePrimitivePtr image;
	ImageReaderPtr reader;

	try
	{
		reader = runTimeCast<ImageReader>( Reader::create( pathName.asChar() ) );
		if (!reader)
		{
			return MS::kFailure;
		}

		image = runTimeCast< ImagePrimitive >( reader->read() );
		if (!image)
		{
			return MS::kFailure;
		}

		if (!reader->isComplete())
		{
			return MS::kFailure;
		}
	}
	catch ( std::exception &e )
	{
		return MS::kFailure;
	}

	m_width = image->width();
	m_height = image->height();

	std::vector<std::string> channelNames;
	image->channelNames( channelNames );

	if ( std::find( channelNames.begin(), channelNames.end(), "R" ) == channelNames.end()
		|| std::find( channelNames.begin(), channelNames.end(), "G" ) == channelNames.end()
		|| std::find( channelNames.begin(), channelNames.end(), "B" ) == channelNames.end() )
	{
		return MS::kFailure;
	}

	m_numChannels = 3;
	if ( std::find( channelNames.begin(), channelNames.end(), "A" ) != channelNames.end() )
	{
		m_numChannels = 4;
	}

	assert( m_numChannels == 3 || m_numChannels == 4 );

	m_rData = image->variables["R"].data;
	if (! m_rData )
	{
		return MS::kFailure;
	}

	m_gData = image->variables["G"].data;
	if (! m_gData )
	{
		return MS::kFailure;
	}

	m_bData = image->variables["B"].data;
	if (! m_bData )
	{
		return MS::kFailure;
	}

	if ( m_numChannels == 4 )
	{
		m_aData = image->variables["A"].data;
		if (! m_aData )
		{
			return MS::kFailure;
		}
	}

	if (info)
	{
		info->width( m_width );
		info->height( m_height );

		info->channels( m_numChannels );
		info->numberOfImages( 1 );

		info->imageType( MImageFileInfo::kImageTypeColor );
		info->pixelType( MImage::kFloat  );
		info->hardwareType( MImageFileInfo::kHwTexture2D  );
	}

	return MS::kSuccess;
}

void ImageFile::populateImage( float* pixels ) const
{
	assert( pixels );

	for (unsigned y = 0; y < m_height; y++)
	{
		for (unsigned x = 0; x < m_width; x++)
		{
			unsigned pixelIndex = ((m_height - y - 1) * m_width) + x;

			assert( pixelIndex < m_width * m_height );

			*pixels++ = getFloatDataDespatch( m_rData, pixelIndex );
			*pixels++ = getFloatDataDespatch( m_gData, pixelIndex );
			*pixels++ = getFloatDataDespatch( m_bData, pixelIndex );

			if ( m_aData )
			{
				*pixels++ = getFloatDataDespatch( m_aData, pixelIndex );
			}
		}
	}
}

MStatus ImageFile::load( MImage& image, unsigned int idx )
{
	MStatus s;

	assert( idx == 0 );
	assert( m_rData	);
	assert( m_gData	);
	assert( m_bData	);

	s = image.create( m_width, m_height, m_numChannels, MImage::kFloat );
	assert(s);

	image.setRGBA( true );

	populateImage( image.floatPixels() );

	return MS::kSuccess;
}

MStatus ImageFile::glLoad( const MImageFileInfo& info, unsigned int idx )
{
	assert( idx == 0 );
	assert( m_rData	);
	assert( m_gData	);
	assert( m_bData	);

	float *pixels = new float[ m_width * m_height * m_numChannels ];

	populateImage( pixels );

	switch (m_numChannels)
	{
		case 3:
			glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_FLOAT, pixels );
		case 4:
			glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_FLOAT, pixels );
		default:
			assert(false);
	}

	delete [] pixels;

	return MS::kSuccess;
}

<commit_msg>Added asserts<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include <cassert>
#include <algorithm>

#include "OpenEXR/ImathLimits.h"

#include <GL/gl.h>

#include "maya/MGlobal.h"
#include "maya/MImage.h"
#include "maya/MImageFileInfo.h"

#include "IECore/ImageReader.h"
#include "IECore/ImagePrimitive.h"
#include "IECore/VectorTypedData.h"

#include "IECoreMaya/ImageFile.h"

using namespace IECore;
using namespace IECoreMaya;

ImageFile::ImageFile() : m_rData( 0 ), m_gData( 0 ), m_bData( 0 ), m_aData( 0 )
{
}

ImageFile::~ImageFile()
{
}

void *ImageFile::creator()
{
	return new ImageFile;
}

template<typename T>
static float getFloatData( ConstDataPtr d, int idx )
{
	assert( d );
	assert( idx >= 0 );

	if ( idx >= (int)(runTimeCast< const T >(d)->readable().size()) )
	{
		return 0.0f;
	}

	return runTimeCast< const T >(d)->readable()[ idx ];
}

template<typename T>
static float getNormalizedFloatData( ConstDataPtr d, int idx )
{
	assert( d );

	return getFloatData<T>( d, idx ) / Imath::limits<typename T::ValueType::value_type>::max();
}

static float getFloatDataDespatch( ConstDataPtr d, int idx )
{
	assert( d );

	switch ( d->typeId() )
	{
		case FloatVectorDataTypeId:
			return getFloatData<FloatVectorData>( d, idx );
		case DoubleVectorDataTypeId:
			return getFloatData<DoubleVectorData>( d, idx );
		case HalfVectorDataTypeId:
			return getFloatData<HalfVectorData>( d, idx );
		case IntVectorDataTypeId:
			return getNormalizedFloatData<IntVectorData>( d, idx );
		case UIntVectorDataTypeId:
			return getNormalizedFloatData<UIntVectorData>( d, idx );
		case CharVectorDataTypeId:
			return getNormalizedFloatData<CharVectorData>( d, idx );
		case UCharVectorDataTypeId:
			return getNormalizedFloatData<UCharVectorData>( d, idx );
		case LongVectorDataTypeId:
			return getNormalizedFloatData<LongVectorData>( d, idx );
		default:
			throw Exception("Invalid channel data type");
	}
}

MStatus ImageFile::open( MString pathName, MImageFileInfo* info )
{
	ImagePrimitivePtr image;
	ImageReaderPtr reader;

	try
	{
		reader = runTimeCast<ImageReader>( Reader::create( pathName.asChar() ) );
		if (!reader)
		{
			return MS::kFailure;
		}

		image = runTimeCast< ImagePrimitive >( reader->read() );
		if (!image)
		{
			return MS::kFailure;
		}

		if (!reader->isComplete())
		{
			return MS::kFailure;
		}
	}
	catch ( std::exception &e )
	{
		return MS::kFailure;
	}

	m_width = image->width();
	m_height = image->height();

	std::vector<std::string> channelNames;
	image->channelNames( channelNames );

	if ( std::find( channelNames.begin(), channelNames.end(), "R" ) == channelNames.end()
		|| std::find( channelNames.begin(), channelNames.end(), "G" ) == channelNames.end()
		|| std::find( channelNames.begin(), channelNames.end(), "B" ) == channelNames.end() )
	{
		return MS::kFailure;
	}

	m_numChannels = 3;
	if ( std::find( channelNames.begin(), channelNames.end(), "A" ) != channelNames.end() )
	{
		m_numChannels = 4;
	}

	assert( m_numChannels == 3 || m_numChannels == 4 );

	m_rData = image->variables["R"].data;
	if (! m_rData )
	{
		return MS::kFailure;
	}

	m_gData = image->variables["G"].data;
	if (! m_gData )
	{
		return MS::kFailure;
	}

	m_bData = image->variables["B"].data;
	if (! m_bData )
	{
		return MS::kFailure;
	}

	if ( m_numChannels == 4 )
	{
		m_aData = image->variables["A"].data;
		if (! m_aData )
		{
			return MS::kFailure;
		}
	}

	if (info)
	{
		info->width( m_width );
		info->height( m_height );

		info->channels( m_numChannels );
		info->numberOfImages( 1 );

		info->imageType( MImageFileInfo::kImageTypeColor );
		info->pixelType( MImage::kFloat  );
		info->hardwareType( MImageFileInfo::kHwTexture2D  );
	}

	return MS::kSuccess;
}

void ImageFile::populateImage( float* pixels ) const
{
	assert( pixels );

	for (unsigned y = 0; y < m_height; y++)
	{
		for (unsigned x = 0; x < m_width; x++)
		{
			unsigned pixelIndex = ((m_height - y - 1) * m_width) + x;

			assert( pixelIndex < m_width * m_height );

			*pixels++ = getFloatDataDespatch( m_rData, pixelIndex );
			*pixels++ = getFloatDataDespatch( m_gData, pixelIndex );
			*pixels++ = getFloatDataDespatch( m_bData, pixelIndex );

			if ( m_aData )
			{
				*pixels++ = getFloatDataDespatch( m_aData, pixelIndex );
			}
		}
	}
}

MStatus ImageFile::load( MImage& image, unsigned int idx )
{
	MStatus s;

	assert( idx == 0 );
	assert( m_rData	);
	assert( m_gData	);
	assert( m_bData	);

	s = image.create( m_width, m_height, m_numChannels, MImage::kFloat );
	assert(s);

	image.setRGBA( true );

	populateImage( image.floatPixels() );

	return MS::kSuccess;
}

MStatus ImageFile::glLoad( const MImageFileInfo& info, unsigned int idx )
{
	assert( idx == 0 );
	assert( m_rData	);
	assert( m_gData	);
	assert( m_bData	);

	float *pixels = new float[ m_width * m_height * m_numChannels ];

	populateImage( pixels );

	switch (m_numChannels)
	{
		case 3:
			glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_FLOAT, pixels );
		case 4:
			glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_FLOAT, pixels );
		default:
			assert(false);
	}

	delete [] pixels;

	return MS::kSuccess;
}

<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_global.h>

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_partition.h>
#include <fclaw2d_exchange.h>
#include <fclaw2d_physical_bc.h>
#include <fclaw2d_regrid.h>
#include <fclaw2d_clawpatch.h>

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

/* -----------------------------------------------------------------
   Initial grid
   ----------------------------------------------------------------- */
static
void cb_initialize (fclaw2d_domain_t *domain,
                    fclaw2d_patch_t *this_patch,
                    int this_block_idx,
                    int this_patch_idx,
                    void *user)
{
    fclaw2d_vtable_t vt;
    fclaw2d_build_mode_t build_mode = FCLAW2D_BUILD_FOR_UPDATE;

    fclaw2d_patch_data_new(domain,this_patch);
    fclaw2d_clawpatch_build_cb(domain,this_patch,
                               this_block_idx,
                               this_patch_idx,
                               (void*) &build_mode);

    vt = fclaw2d_get_vtable(domain);
    vt.patch_initialize(domain,this_patch,this_block_idx,this_patch_idx);
}

/* -----------------------------------------------------------------
   Public interface
   ----------------------------------------------------------------- */

void fclaw2d_initialize (fclaw2d_domain_t **domain)
{
    int i;
    double t;

    char basename[BUFSIZ];
    const fclaw2d_vtable_t vt = fclaw2d_get_vtable(*domain);
    const amr_options_t *gparms = get_domain_parms(*domain);

    fclaw2d_domain_data_t* ddata = fclaw2d_domain_get_data(*domain);

    /* This mapping context is needed by fortran mapping functions */
    fclaw2d_map_context_t *cont = fclaw2d_domain_get_map_context(*domain);
    SET_CONTEXT(&cont);

    int minlevel = gparms->minlevel;
    int maxlevel = gparms->maxlevel;

    // This is where the timing starts.
    ddata->is_latest_domain = 1;
    for (i = 0; i < FCLAW2D_TIMER_COUNT; ++i) {
        fclaw2d_timer_init (&ddata->timers[i]);
    }

    /* set specific refinement strategy */
    fclaw2d_domain_set_refinement
      (*domain, gparms->smooth_refine, gparms->coarsen_delay);

    /* start timing */
    fclaw2d_domain_barrier (*domain);
    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_WALLTIME]);

    if (vt.problem_setup != NULL)
    {
        vt.problem_setup(*domain);
    }

    /* Get an initial domain */
    fclaw2d_domain_setup(NULL,*domain);

    fclaw2d_domain_iterate_level(*domain, minlevel, cb_initialize,
                                 (void *) NULL);

    fclaw_bool time_interp = fclaw_false;
    t = fclaw2d_domain_get_time(*domain);
    fclaw2d_set_physical_bc(*domain,minlevel,t,time_interp);

    // VTK output during amrinit
    if (gparms->vtkout & 1) {
        // into timer
        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

        // output
        snprintf (basename, BUFSIZ, "%s_init_level_%02d",
                  gparms->prefix, minlevel);
        fclaw2d_output_write_vtk (*domain, basename);

        // out of timer
        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
    }

    // Refine as needed, one level at a time.
    if (minlevel < maxlevel)
    {
        int level =  minlevel;
        int domain_init = 1;
        fclaw_bool have_new_refinement = 1;
        while (level < maxlevel && have_new_refinement)
        {
            fclaw2d_domain_iterate_level(*domain, level,
                                         fclaw2d_regrid_tag4refinement,
                                         (void *) &domain_init);

            // Construct new domain based on tagged patches.
            fclaw2d_domain_t *new_domain = fclaw2d_domain_adapt(*domain);
            have_new_refinement = new_domain != NULL;

            // Domain data may go out of scope now.
            ddata = NULL;

            if (have_new_refinement)
            {
                fclaw2d_domain_setup(*domain,new_domain);
                ddata = fclaw2d_domain_get_data(new_domain);

                // Re-initialize new grids
                fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);
                fclaw2d_domain_iterate_adapted(*domain, new_domain,
                                               fclaw2d_regrid_repopulate,
                                               (void *) &domain_init);
                fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);

                // Set boundary need ghost cell values so they are available
                // for using at tagging criteria, if necessary.
                int new_level = level+1;
                time_interp = fclaw_false;
                t = fclaw2d_domain_get_time(new_domain);
                fclaw2d_set_physical_bc(new_domain,new_level,t,time_interp);

                // free all memory associated with old domain
                fclaw2d_domain_reset(domain);
                *domain = new_domain;
                new_domain = NULL;

                // VTK output during amrinit
                if (gparms->vtkout & 1) {
                    // into timer
                    ddata = fclaw2d_domain_get_data (*domain);
                    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
                    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

                    // output
                    snprintf (basename, BUFSIZ, "%s_init_level_%02d_adapt",
                              gparms->prefix, level);
                    fclaw2d_output_write_vtk (*domain, basename);

                    /* out of timer */
                    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
                    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
                    ddata = NULL;
                }

                /* Repartition domain to new processors. Do I need this here?*/
                fclaw2d_partition_domain(domain, level);

                /* Set up ghost patches */
                fclaw2d_exchange_setup(*domain);

                level++;
            }
        }
    }
    else
    {
        /* minlevel == maxlevel;  no refining necessary.  We have an initial
           partition, so we don't need to partition a new domaoin. */

        fclaw2d_exchange_setup(*domain);
    }

    /* Print global minimum and maximum levels */
    fclaw_global_infof("Global minlevel %d maxlevel %d\n",
                (*domain)->global_minlevel, (*domain)->global_maxlevel);

    /* Stop timer */
    ddata = fclaw2d_domain_get_data(*domain);
    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<commit_msg>Restructure initial refinement loop<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <fclaw2d_global.h>

#include <fclaw2d_forestclaw.h>
#include <fclaw2d_partition.h>
#include <fclaw2d_exchange.h>
#include <fclaw2d_physical_bc.h>
#include <fclaw2d_regrid.h>
#include <fclaw2d_clawpatch.h>

#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif

/* -----------------------------------------------------------------
   Initial grid
   ----------------------------------------------------------------- */
static
void cb_initialize (fclaw2d_domain_t *domain,
                    fclaw2d_patch_t *this_patch,
                    int this_block_idx,
                    int this_patch_idx,
                    void *user)
{
    fclaw2d_vtable_t vt;
    fclaw2d_build_mode_t build_mode = FCLAW2D_BUILD_FOR_UPDATE;

    fclaw2d_patch_data_new(domain,this_patch);
    fclaw2d_clawpatch_build_cb(domain,this_patch,
                               this_block_idx,
                               this_patch_idx,
                               (void*) &build_mode);

    vt = fclaw2d_get_vtable(domain);
    vt.patch_initialize(domain,this_patch,this_block_idx,this_patch_idx);
}

/* -----------------------------------------------------------------
   Public interface
   ----------------------------------------------------------------- */

void fclaw2d_initialize (fclaw2d_domain_t **domain)
{
    int i;
    double t;

    char basename[BUFSIZ];
    const fclaw2d_vtable_t vt = fclaw2d_get_vtable(*domain);
    const amr_options_t *gparms = get_domain_parms(*domain);

    fclaw2d_domain_data_t* ddata = fclaw2d_domain_get_data(*domain);

    /* This mapping context is needed by fortran mapping functions */
    fclaw2d_map_context_t *cont = fclaw2d_domain_get_map_context(*domain);
    SET_CONTEXT(&cont);

    int minlevel = gparms->minlevel;
    int maxlevel = gparms->maxlevel;

    // This is where the timing starts.
    ddata->is_latest_domain = 1;
    for (i = 0; i < FCLAW2D_TIMER_COUNT; ++i) {
        fclaw2d_timer_init (&ddata->timers[i]);
    }

    /* set specific refinement strategy */
    fclaw2d_domain_set_refinement
      (*domain, gparms->smooth_refine, gparms->coarsen_delay);

    /* start timing */
    fclaw2d_domain_barrier (*domain);
    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_WALLTIME]);

    if (vt.problem_setup != NULL)
    {
        vt.problem_setup(*domain);
    }

    /* Get an initial domain */
    fclaw2d_domain_setup(NULL,*domain);

    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);
    fclaw2d_domain_iterate_level(*domain, minlevel, cb_initialize,
                                 (void *) NULL);
    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);

    fclaw_bool time_interp = fclaw_false;
    t = fclaw2d_domain_get_time(*domain);
    fclaw2d_set_physical_bc(*domain,minlevel,t,time_interp);

    // VTK output during amrinit
    if (gparms->vtkout & 1) {
        // into timer
        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

        // output
        snprintf (basename, BUFSIZ, "%s_init_level_%02d",
                  gparms->prefix, minlevel);
        fclaw2d_output_write_vtk (*domain, basename);

        // out of timer
        fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
        fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
    }

    // Refine as needed, one level at a time.
    if (minlevel < maxlevel)
    {
        int level =  minlevel;
        int domain_init = 1;
        fclaw_bool have_new_refinement = 1;
        while (level < maxlevel && have_new_refinement)
        {
            fclaw2d_domain_iterate_level(*domain, level,
                                         fclaw2d_regrid_tag4refinement,
                                         (void *) &domain_init);

            // Construct new domain based on tagged patches.
            fclaw2d_domain_t *new_domain = fclaw2d_domain_adapt(*domain);
            have_new_refinement = new_domain != NULL;

            // Domain data may go out of scope now.
            ddata = NULL;

            if (have_new_refinement)
            {
                fclaw2d_domain_setup(*domain,new_domain);
                ddata = fclaw2d_domain_get_data(new_domain);

                // Re-initialize new grids
                fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);
                fclaw2d_domain_iterate_adapted(*domain, new_domain,
                                               fclaw2d_regrid_repopulate,
                                               (void *) &domain_init);
                fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_BUILDREGRID]);

                // Set boundary need ghost cell values so they are available
                // for using at tagging criteria, if necessary.
                int new_level = level+1;
                time_interp = fclaw_false;
                t = fclaw2d_domain_get_time(new_domain);
                fclaw2d_set_physical_bc(new_domain,new_level,t,time_interp);

                // free all memory associated with old domain
                fclaw2d_domain_reset(domain);
                *domain = new_domain;
                new_domain = NULL;

                // VTK output during amrinit
                if (gparms->vtkout & 1) {
                    // into timer
                    ddata = fclaw2d_domain_get_data (*domain);
                    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
                    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);

                    // output
                    snprintf (basename, BUFSIZ, "%s_init_level_%02d_adapt",
                              gparms->prefix, level);
                    fclaw2d_output_write_vtk (*domain, basename);

                    /* out of timer */
                    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_OUTPUT]);
                    fclaw2d_timer_start (&ddata->timers[FCLAW2D_TIMER_INIT]);
                    ddata = NULL;
                }

                /* Repartition domain to new processors. Do I need this here?*/
                fclaw2d_partition_domain(domain, level);

                /* Set up ghost patches */
                fclaw2d_exchange_setup(*domain);

                level++;
            }
        }
    }
    else
    {
        /* minlevel == maxlevel;  no refining necessary.  We have an initial
           partition, so we don't need to partition a new domaoin. */

        fclaw2d_exchange_setup(*domain);
    }

    /* Print global minimum and maximum levels */
    fclaw_global_infof("Global minlevel %d maxlevel %d\n",
                (*domain)->global_minlevel, (*domain)->global_maxlevel);

    /* Stop timer */
    ddata = fclaw2d_domain_get_data(*domain);
    fclaw2d_timer_stop (&ddata->timers[FCLAW2D_TIMER_INIT]);
}

#ifdef __cplusplus
#if 0
{
#endif
}
#endif
<|endoftext|>